1
0
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:
uz 2010-08-09 22:05:44 +00:00
parent 03d3868d45
commit d627b1ac83
3 changed files with 233 additions and 23 deletions

View File

@ -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);
}

View File

@ -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++ */

View File

@ -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);