mirror of
https://github.com/cc65/cc65.git
synced 2024-11-18 15:05:14 +00:00
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:
parent
03d3868d45
commit
d627b1ac83
@ -90,6 +90,7 @@ struct DbgInfo {
|
||||
Collection FileInfoByName; /* File infos sorted by name */
|
||||
Collection FileInfoById; /* File infos sorted by id */
|
||||
Collection LineInfoByAddr; /* Line information sorted by address */
|
||||
Collection SymInfoByName; /* Symbol information sorted by name */
|
||||
};
|
||||
|
||||
/* Input tokens */
|
||||
@ -196,6 +197,14 @@ struct LineInfo {
|
||||
} 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 */
|
||||
/*****************************************************************************/
|
||||
@ -855,6 +905,7 @@ static DbgInfo* NewDbgInfo (void)
|
||||
InitCollection (&Info->FileInfoByName);
|
||||
InitCollection (&Info->FileInfoById);
|
||||
InitCollection (&Info->LineInfoByAddr);
|
||||
InitCollection (&Info->SymInfoByName);
|
||||
|
||||
/* Return it */
|
||||
return Info;
|
||||
@ -884,6 +935,12 @@ static void FreeDbgInfo (DbgInfo* Info)
|
||||
/* Free line info */
|
||||
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 */
|
||||
xfree (Info);
|
||||
}
|
||||
@ -1704,6 +1761,7 @@ static void ParseSym (InputData* D)
|
||||
cc65_symbol_type Type;
|
||||
long Value;
|
||||
StrBuf SymName = STRBUF_INITIALIZER;
|
||||
SymInfo* S;
|
||||
enum {
|
||||
ibNone = 0x00,
|
||||
ibSymName = 0x01,
|
||||
@ -1814,10 +1872,8 @@ static void ParseSym (InputData* D)
|
||||
}
|
||||
|
||||
/* Create the symbol info and remember it */
|
||||
#if 0
|
||||
S = NewSegInfo (&SegName, Id, Start, Size, &OutputName, OutputOffs);
|
||||
CollAppend (&D->Info->SegInfoByName, S);
|
||||
#endif
|
||||
S = NewSymInfo (&SymName, Value, Type);
|
||||
CollAppend (&D->Info->SymInfoByName, S);
|
||||
|
||||
ErrorExit:
|
||||
/* 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 */
|
||||
/*****************************************************************************/
|
||||
@ -2424,6 +2535,7 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc)
|
||||
ProcessSegInfo (&D);
|
||||
ProcessFileInfo (&D);
|
||||
ProcessLineInfo (&D);
|
||||
ProcessSymInfo (&D);
|
||||
|
||||
/* Return the debug info struct that was created */
|
||||
return D.Info;
|
||||
@ -2570,7 +2682,7 @@ cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle)
|
||||
for (I = 0; I < CollCount (FileInfoByName); ++I) {
|
||||
|
||||
/* Get this item */
|
||||
FileInfo* F = CollAt (FileInfoByName, I);
|
||||
const FileInfo* F = CollAt (FileInfoByName, I);
|
||||
|
||||
/* Copy the data */
|
||||
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 */
|
||||
Info = (DbgInfo*) Handle;
|
||||
|
||||
/* Get a pointer to the file list */
|
||||
/* Get a pointer to the segment list */
|
||||
SegInfoByName = &Info->SegInfoByName;
|
||||
|
||||
/* 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) {
|
||||
|
||||
/* Get this item */
|
||||
SegInfo* S = CollAt (SegInfoByName, I);
|
||||
const SegInfo* S = CollAt (SegInfoByName, I);
|
||||
|
||||
/* Copy the data */
|
||||
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);
|
||||
/* 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++ */
|
||||
|
@ -67,7 +67,8 @@ int main (int argc, char** argv)
|
||||
cc65_dbginfo Info;
|
||||
cc65_sourceinfo* Sources;
|
||||
cc65_segmentinfo* Segments;
|
||||
cc65_lineinfo* L;
|
||||
cc65_lineinfo* Lines;
|
||||
cc65_symbolinfo* Symbols;
|
||||
unsigned I;
|
||||
unsigned long Addr;
|
||||
|
||||
@ -113,14 +114,14 @@ int main (int argc, char** argv)
|
||||
|
||||
/* Check one line */
|
||||
printf ("Requesting line info for crt0.s(59):\n");
|
||||
L = cc65_lineinfo_byname (Info, "crt0.s", 59);
|
||||
if (L == 0) {
|
||||
Lines = cc65_lineinfo_byname (Info, "crt0.s", 59);
|
||||
if (Lines == 0) {
|
||||
printf (" Not found\n");
|
||||
} else {
|
||||
printf (" Code range is $%04X-$%04X\n",
|
||||
L->data[0].line_start,
|
||||
L->data[0].line_end);
|
||||
cc65_free_lineinfo (Info, L);
|
||||
Lines->data[0].line_start,
|
||||
Lines->data[0].line_end);
|
||||
cc65_free_lineinfo (Info, Lines);
|
||||
}
|
||||
|
||||
/* 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");
|
||||
for (Addr = 0; Addr < 0x10000; ++Addr) {
|
||||
L = cc65_lineinfo_byaddr (Info, Addr);
|
||||
if (L) {
|
||||
Lines = cc65_lineinfo_byaddr (Info, Addr);
|
||||
if (Lines) {
|
||||
unsigned I;
|
||||
printf (" $%04lX: ", Addr);
|
||||
for (I = 0; I < L->count; ++I) {
|
||||
for (I = 0; I < Lines->count; ++I) {
|
||||
if (I > 0) {
|
||||
printf (", ");
|
||||
}
|
||||
printf ("%s(%lu)",
|
||||
L->data[I].source_name,
|
||||
(unsigned long) L->data[I].source_line);
|
||||
if (L->data[I].output_name) {
|
||||
printf ("%s(%lu)",
|
||||
Lines->data[I].source_name,
|
||||
(unsigned long) Lines->data[I].source_line);
|
||||
if (Lines->data[I].output_name) {
|
||||
printf (" %s($%06lX)",
|
||||
L->data[I].output_name,
|
||||
L->data[I].output_offs);
|
||||
Lines->data[I].output_name,
|
||||
Lines->data[I].output_offs);
|
||||
|
||||
}
|
||||
}
|
||||
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 */
|
||||
cc65_free_dbginfo (Info);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user