First support for symbols - mostly untested.
git-svn-id: svn://svn.cc65.org/cc65/trunk@4805 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -90,6 +90,7 @@ struct DbgInfo {
|
|||||||
Collection FileInfoByName; /* File infos sorted by name */
|
Collection FileInfoByName; /* File infos sorted by name */
|
||||||
Collection FileInfoById; /* File infos sorted by id */
|
Collection FileInfoById; /* File infos sorted by id */
|
||||||
Collection LineInfoByAddr; /* Line information sorted by address */
|
Collection LineInfoByAddr; /* Line information sorted by address */
|
||||||
|
Collection SymInfoByName; /* Symbol information sorted by name */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Input tokens */
|
/* Input tokens */
|
||||||
@@ -196,6 +197,14 @@ struct LineInfo {
|
|||||||
} Seg;
|
} Seg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Internally used symbol info struct */
|
||||||
|
typedef struct SymInfo SymInfo;
|
||||||
|
struct SymInfo {
|
||||||
|
cc65_symbol_type Type; /* Type of symbol */
|
||||||
|
long Value; /* Value of symbol */
|
||||||
|
char SymName[1]; /* Name of symbol */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -837,6 +846,47 @@ static int CompareFileInfoById (const void* L, const void* R)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Symbol info */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static SymInfo* NewSymInfo (const StrBuf* Name, long Val, cc65_symbol_type Type)
|
||||||
|
/* Create a new SymInfo struct, intialize and return it */
|
||||||
|
{
|
||||||
|
/* Allocate memory */
|
||||||
|
SymInfo* S = xmalloc (sizeof (SymInfo) + SB_GetLen (Name));
|
||||||
|
|
||||||
|
/* Initialize it */
|
||||||
|
S->Value = Val;
|
||||||
|
S->Type = Type;
|
||||||
|
memcpy (S->SymName, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
|
||||||
|
|
||||||
|
/* Return it */
|
||||||
|
return S;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void FreeSymInfo (SymInfo* S)
|
||||||
|
/* Free a SymInfo struct */
|
||||||
|
{
|
||||||
|
xfree (S);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int CompareSymInfoByName (const void* L, const void* R)
|
||||||
|
/* Helper function to sort symbol infos in a collection by name */
|
||||||
|
{
|
||||||
|
/* Sort by file name */
|
||||||
|
return strcmp (((const SymInfo*) L)->SymName,
|
||||||
|
((const SymInfo*) R)->SymName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Debug info */
|
/* Debug info */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -855,6 +905,7 @@ static DbgInfo* NewDbgInfo (void)
|
|||||||
InitCollection (&Info->FileInfoByName);
|
InitCollection (&Info->FileInfoByName);
|
||||||
InitCollection (&Info->FileInfoById);
|
InitCollection (&Info->FileInfoById);
|
||||||
InitCollection (&Info->LineInfoByAddr);
|
InitCollection (&Info->LineInfoByAddr);
|
||||||
|
InitCollection (&Info->SymInfoByName);
|
||||||
|
|
||||||
/* Return it */
|
/* Return it */
|
||||||
return Info;
|
return Info;
|
||||||
@@ -884,6 +935,12 @@ static void FreeDbgInfo (DbgInfo* Info)
|
|||||||
/* Free line info */
|
/* Free line info */
|
||||||
DoneCollection (&Info->LineInfoByAddr);
|
DoneCollection (&Info->LineInfoByAddr);
|
||||||
|
|
||||||
|
/* Free symbol info */
|
||||||
|
for (I = 0; I < CollCount (&Info->SymInfoByName); ++I) {
|
||||||
|
FreeSymInfo (CollAt (&Info->SymInfoByName, I));
|
||||||
|
}
|
||||||
|
DoneCollection (&Info->SymInfoByName);
|
||||||
|
|
||||||
/* Free the structure itself */
|
/* Free the structure itself */
|
||||||
xfree (Info);
|
xfree (Info);
|
||||||
}
|
}
|
||||||
@@ -1704,6 +1761,7 @@ static void ParseSym (InputData* D)
|
|||||||
cc65_symbol_type Type;
|
cc65_symbol_type Type;
|
||||||
long Value;
|
long Value;
|
||||||
StrBuf SymName = STRBUF_INITIALIZER;
|
StrBuf SymName = STRBUF_INITIALIZER;
|
||||||
|
SymInfo* S;
|
||||||
enum {
|
enum {
|
||||||
ibNone = 0x00,
|
ibNone = 0x00,
|
||||||
ibSymName = 0x01,
|
ibSymName = 0x01,
|
||||||
@@ -1814,10 +1872,8 @@ static void ParseSym (InputData* D)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create the symbol info and remember it */
|
/* Create the symbol info and remember it */
|
||||||
#if 0
|
S = NewSymInfo (&SymName, Value, Type);
|
||||||
S = NewSegInfo (&SegName, Id, Start, Size, &OutputName, OutputOffs);
|
CollAppend (&D->Info->SymInfoByName, S);
|
||||||
CollAppend (&D->Info->SegInfoByName, S);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ErrorExit:
|
ErrorExit:
|
||||||
/* Entry point in case of errors */
|
/* Entry point in case of errors */
|
||||||
@@ -2287,6 +2343,61 @@ static LineInfo* FindLineInfoByLine (FileInfo* F, cc65_line Line)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void ProcessSymInfo (InputData* D)
|
||||||
|
/* Postprocess symbol infos */
|
||||||
|
{
|
||||||
|
/* Get pointers to the symbol info collections */
|
||||||
|
Collection* SymInfoByName = &D->Info->SymInfoByName;
|
||||||
|
|
||||||
|
/* Sort the symbol infos by name */
|
||||||
|
CollSort (SymInfoByName, CompareSymInfoByName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int FindSymInfoByName (Collection* SymInfos, const char* SymName, int* Index)
|
||||||
|
/* Find the SymInfo for a given file name. The function returns true if the
|
||||||
|
* name was found. In this case, Index contains the index of the first item
|
||||||
|
* that matches. If the item wasn't found, the function returns false and
|
||||||
|
* Index contains the insert position for SymName.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Do a binary search */
|
||||||
|
int Lo = 0;
|
||||||
|
int Hi = (int) CollCount (SymInfos) - 1;
|
||||||
|
int Found = 0;
|
||||||
|
while (Lo <= Hi) {
|
||||||
|
|
||||||
|
/* Mid of range */
|
||||||
|
int Cur = (Lo + Hi) / 2;
|
||||||
|
|
||||||
|
/* Get item */
|
||||||
|
SymInfo* CurItem = CollAt (SymInfos, Cur);
|
||||||
|
|
||||||
|
/* Compare */
|
||||||
|
int Res = strcmp (CurItem->SymName, SymName);
|
||||||
|
|
||||||
|
/* Found? */
|
||||||
|
if (Res < 0) {
|
||||||
|
Lo = Cur + 1;
|
||||||
|
} else {
|
||||||
|
Hi = Cur - 1;
|
||||||
|
/* Since we may have duplicates, repeat the search until we've
|
||||||
|
* the first item that has a match.
|
||||||
|
*/
|
||||||
|
if (Res == 0) {
|
||||||
|
Found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pass back the index. This is also the insert position */
|
||||||
|
*Index = Lo;
|
||||||
|
return Found;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -2424,6 +2535,7 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc)
|
|||||||
ProcessSegInfo (&D);
|
ProcessSegInfo (&D);
|
||||||
ProcessFileInfo (&D);
|
ProcessFileInfo (&D);
|
||||||
ProcessLineInfo (&D);
|
ProcessLineInfo (&D);
|
||||||
|
ProcessSymInfo (&D);
|
||||||
|
|
||||||
/* Return the debug info struct that was created */
|
/* Return the debug info struct that was created */
|
||||||
return D.Info;
|
return D.Info;
|
||||||
@@ -2570,7 +2682,7 @@ cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle)
|
|||||||
for (I = 0; I < CollCount (FileInfoByName); ++I) {
|
for (I = 0; I < CollCount (FileInfoByName); ++I) {
|
||||||
|
|
||||||
/* Get this item */
|
/* Get this item */
|
||||||
FileInfo* F = CollAt (FileInfoByName, I);
|
const FileInfo* F = CollAt (FileInfoByName, I);
|
||||||
|
|
||||||
/* Copy the data */
|
/* Copy the data */
|
||||||
D->data[I].source_name = F->FileName;
|
D->data[I].source_name = F->FileName;
|
||||||
@@ -2610,7 +2722,7 @@ cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle)
|
|||||||
/* The handle is actually a pointer to a debug info struct */
|
/* The handle is actually a pointer to a debug info struct */
|
||||||
Info = (DbgInfo*) Handle;
|
Info = (DbgInfo*) Handle;
|
||||||
|
|
||||||
/* Get a pointer to the file list */
|
/* Get a pointer to the segment list */
|
||||||
SegInfoByName = &Info->SegInfoByName;
|
SegInfoByName = &Info->SegInfoByName;
|
||||||
|
|
||||||
/* Allocate memory for the data structure returned to the caller */
|
/* Allocate memory for the data structure returned to the caller */
|
||||||
@@ -2622,7 +2734,7 @@ cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle)
|
|||||||
for (I = 0; I < CollCount (SegInfoByName); ++I) {
|
for (I = 0; I < CollCount (SegInfoByName); ++I) {
|
||||||
|
|
||||||
/* Get this item */
|
/* Get this item */
|
||||||
SegInfo* S = CollAt (SegInfoByName, I);
|
const SegInfo* S = CollAt (SegInfoByName, I);
|
||||||
|
|
||||||
/* Copy the data */
|
/* Copy the data */
|
||||||
D->data[I].segment_name = S->SegName;
|
D->data[I].segment_name = S->SegName;
|
||||||
@@ -2650,3 +2762,76 @@ void cc65_free_segmentinfo (cc65_dbginfo Handle, cc65_segmentinfo* Info)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name)
|
||||||
|
/* Return a list of symbols with a given name. The function returns NULL if
|
||||||
|
* no symbol with this name was found.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
DbgInfo* Info;
|
||||||
|
Collection* SymInfoByName;
|
||||||
|
cc65_symbolinfo* D;
|
||||||
|
unsigned I;
|
||||||
|
int Index;
|
||||||
|
unsigned Count;
|
||||||
|
|
||||||
|
/* Check the parameter */
|
||||||
|
assert (Handle != 0);
|
||||||
|
|
||||||
|
/* The handle is actually a pointer to a debug info struct */
|
||||||
|
Info = (DbgInfo*) Handle;
|
||||||
|
|
||||||
|
/* Get a pointer to the symbol list */
|
||||||
|
SymInfoByName = &Info->SymInfoByName;
|
||||||
|
|
||||||
|
/* Search for the symbol */
|
||||||
|
if (!FindSymInfoByName (SymInfoByName, Name, &Index)) {
|
||||||
|
/* Not found */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Index contains the position. Count how many symbols with this name
|
||||||
|
* we have. Skip the first one, since we have at least one.
|
||||||
|
*/
|
||||||
|
Count = 1;
|
||||||
|
while ((unsigned) Index + Count < CollCount (SymInfoByName)) {
|
||||||
|
const SymInfo* S = CollAt (SymInfoByName, (unsigned) Index + Count);
|
||||||
|
if (strcmp (S->SymName, Name) != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate memory for the data structure returned to the caller */
|
||||||
|
D = xmalloc (sizeof (*D) + (Count - 1) * sizeof (D->data[0]));
|
||||||
|
|
||||||
|
/* Fill in the data */
|
||||||
|
D->count = Count;
|
||||||
|
while (Count--) {
|
||||||
|
|
||||||
|
/* Get this item */
|
||||||
|
const SymInfo* S = CollAt (SymInfoByName, Index);
|
||||||
|
|
||||||
|
/* Copy the data */
|
||||||
|
D->data[I].symbol_name = S->SymName;
|
||||||
|
D->data[I].symbol_type = S->Type;
|
||||||
|
D->data[I].symbol_value = S->Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the result */
|
||||||
|
return D;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cc65_free_symbolinfo (cc65_dbginfo Handle, cc65_symbolinfo* Info)
|
||||||
|
/* Free a symbol info record */
|
||||||
|
{
|
||||||
|
/* Just for completeness, check the handle */
|
||||||
|
assert (Handle != 0);
|
||||||
|
|
||||||
|
/* Free the memory */
|
||||||
|
xfree (Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -207,6 +207,14 @@ cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo handle);
|
|||||||
void cc65_free_segmentinfo (cc65_dbginfo handle, cc65_segmentinfo* info);
|
void cc65_free_segmentinfo (cc65_dbginfo handle, cc65_segmentinfo* info);
|
||||||
/* Free a segment info record */
|
/* Free a segment info record */
|
||||||
|
|
||||||
|
cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name);
|
||||||
|
/* Return a list of symbols with a given name. The function returns NULL if
|
||||||
|
* no symbol with this name was found.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cc65_free_symbolinfo (cc65_dbginfo Handle, cc65_symbolinfo* Info);
|
||||||
|
/* Free a symbol info record */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Allow usage from C++ */
|
/* Allow usage from C++ */
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ int main (int argc, char** argv)
|
|||||||
cc65_dbginfo Info;
|
cc65_dbginfo Info;
|
||||||
cc65_sourceinfo* Sources;
|
cc65_sourceinfo* Sources;
|
||||||
cc65_segmentinfo* Segments;
|
cc65_segmentinfo* Segments;
|
||||||
cc65_lineinfo* L;
|
cc65_lineinfo* Lines;
|
||||||
|
cc65_symbolinfo* Symbols;
|
||||||
unsigned I;
|
unsigned I;
|
||||||
unsigned long Addr;
|
unsigned long Addr;
|
||||||
|
|
||||||
@@ -113,14 +114,14 @@ int main (int argc, char** argv)
|
|||||||
|
|
||||||
/* Check one line */
|
/* Check one line */
|
||||||
printf ("Requesting line info for crt0.s(59):\n");
|
printf ("Requesting line info for crt0.s(59):\n");
|
||||||
L = cc65_lineinfo_byname (Info, "crt0.s", 59);
|
Lines = cc65_lineinfo_byname (Info, "crt0.s", 59);
|
||||||
if (L == 0) {
|
if (Lines == 0) {
|
||||||
printf (" Not found\n");
|
printf (" Not found\n");
|
||||||
} else {
|
} else {
|
||||||
printf (" Code range is $%04X-$%04X\n",
|
printf (" Code range is $%04X-$%04X\n",
|
||||||
L->data[0].line_start,
|
Lines->data[0].line_start,
|
||||||
L->data[0].line_end);
|
Lines->data[0].line_end);
|
||||||
cc65_free_lineinfo (Info, L);
|
cc65_free_lineinfo (Info, Lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output debug information for all addresses in the complete 6502 address
|
/* Output debug information for all addresses in the complete 6502 address
|
||||||
@@ -128,29 +129,45 @@ int main (int argc, char** argv)
|
|||||||
*/
|
*/
|
||||||
printf ("Line info:\n");
|
printf ("Line info:\n");
|
||||||
for (Addr = 0; Addr < 0x10000; ++Addr) {
|
for (Addr = 0; Addr < 0x10000; ++Addr) {
|
||||||
L = cc65_lineinfo_byaddr (Info, Addr);
|
Lines = cc65_lineinfo_byaddr (Info, Addr);
|
||||||
if (L) {
|
if (Lines) {
|
||||||
unsigned I;
|
unsigned I;
|
||||||
printf (" $%04lX: ", Addr);
|
printf (" $%04lX: ", Addr);
|
||||||
for (I = 0; I < L->count; ++I) {
|
for (I = 0; I < Lines->count; ++I) {
|
||||||
if (I > 0) {
|
if (I > 0) {
|
||||||
printf (", ");
|
printf (", ");
|
||||||
}
|
}
|
||||||
printf ("%s(%lu)",
|
printf ("%s(%lu)",
|
||||||
L->data[I].source_name,
|
Lines->data[I].source_name,
|
||||||
(unsigned long) L->data[I].source_line);
|
(unsigned long) Lines->data[I].source_line);
|
||||||
if (L->data[I].output_name) {
|
if (Lines->data[I].output_name) {
|
||||||
printf (" %s($%06lX)",
|
printf (" %s($%06lX)",
|
||||||
L->data[I].output_name,
|
Lines->data[I].output_name,
|
||||||
L->data[I].output_offs);
|
Lines->data[I].output_offs);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
cc65_free_lineinfo (Info, L);
|
cc65_free_lineinfo (Info, Lines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for address of main */
|
||||||
|
printf ("Requesting address of _main:\n");
|
||||||
|
Symbols = cc65_symbol_byname (Info, "_main");
|
||||||
|
if (Symbols == 0) {
|
||||||
|
printf (" Not found\n");
|
||||||
|
} else {
|
||||||
|
unsigned I;
|
||||||
|
for (I = 0; I < Symbols->count; ++I) {
|
||||||
|
printf (" %-20s = %04lX\n",
|
||||||
|
Symbols->data[I].symbol_name,
|
||||||
|
Symbols->data[I].symbol_value);
|
||||||
|
}
|
||||||
|
cc65_free_symbolinfo (Info, Symbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Free the debug info */
|
/* Free the debug info */
|
||||||
cc65_free_dbginfo (Info);
|
cc65_free_dbginfo (Info);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user