From 44b829cc01baf2ad802a508d03c42a34b508defa Mon Sep 17 00:00:00 2001 From: uz Date: Tue, 14 Jun 2011 21:18:44 +0000 Subject: [PATCH] Read and allow access to the segment for (segment based) symbols. git-svn-id: svn://svn.cc65.org/cc65/trunk@5063 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/dbginfo/dbginfo.c | 194 +++++++++++++++++++++++++++++++++--------- src/dbginfo/dbginfo.h | 60 ++++++++++++- src/dbginfo/dbgtest.c | 20 ++++- 3 files changed, 229 insertions(+), 45 deletions(-) diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index 06a040cb4..7865f53a4 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -224,6 +224,7 @@ struct SymInfo { cc65_symbol_type Type; /* Type of symbol */ long Value; /* Value of symbol */ cc65_size Size; /* Size of symbol */ + unsigned Segment; /* Id of segment if any */ char SymName[1]; /* Name of symbol */ }; @@ -1038,17 +1039,19 @@ static int CompareFileInfoById (const void* L, const void* R) -static SymInfo* NewSymInfo (const StrBuf* Name, long Val, - cc65_symbol_type Type, cc65_size Size) +static SymInfo* NewSymInfo (const StrBuf* Name, long Val, + cc65_symbol_type Type, cc65_size Size, + unsigned Segment) /* Create a new SymInfo struct, intialize and return it */ { /* Allocate memory */ SymInfo* S = xmalloc (sizeof (SymInfo) + SB_GetLen (Name)); /* Initialize it */ - S->Type = Type; - S->Value = Val; - S->Size = Size; + S->Type = Type; + S->Value = Val; + S->Size = Size; + S->Segment = Segment; memcpy (S->SymName, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); /* Return it */ @@ -1357,9 +1360,7 @@ static void FreeDbgInfo (DbgInfo* Info) static void CopyLineInfo (cc65_linedata* D, const LineInfo* L) -/* Copy data from a LineInfo struct to the cc65_linedata struct returned to - * the caller. - */ +/* Copy data from a LineInfo struct to a cc65_linedata struct */ { D->source_name = L->File.Info->FileName; D->source_size = L->File.Info->Size; @@ -1380,15 +1381,38 @@ static void CopyLineInfo (cc65_linedata* D, const LineInfo* L) -static void CopySymInfo (cc65_symboldata* D, const SymInfo* S) -/* Copy data from a SymInfo struct to the cc65_symboldata struct returned to - * the caller. - */ +static void CopyFileInfo (cc65_sourcedata* D, const FileInfo* F) +/* Copy data from a FileInfo struct to a cc65_sourcedata struct */ { - D->symbol_name = S->SymName; - D->symbol_type = S->Type; - D->symbol_size = S->Size; - D->symbol_value = S->Value; + D->id = F->Id; + D->source_name = F->FileName; + D->source_size = F->Size; + D->source_mtime = F->MTime; +} + + + +static void CopySegInfo (cc65_segmentdata* D, const SegInfo* S) +/* Copy data from a SegInfo struct to a cc65_segmentdata struct */ +{ + D->id = S->Id; + D->segment_name = S->SegName; + D->segment_start = S->Start; + D->segment_size = S->Size; + D->output_name = S->OutputName; + D->output_offs = S->OutputOffs; +} + + + +static void CopySymInfo (cc65_symboldata* D, const SymInfo* S) +/* Copy data from a SymInfo struct to a cc65_symboldata struct */ +{ + D->symbol_name = S->SymName; + D->symbol_type = S->Type; + D->symbol_size = S->Size; + D->symbol_value = S->Value; + D->symbol_segment = S->Segment; } @@ -1459,7 +1483,7 @@ static void UnknownKeyword (InputData* D) /* Output a warning */ ParseError (D, CC65_WARNING, "Unknown keyword \"%s\" - skipping", SB_GetConstBuf (&D->SVal)); - + /* Skip the identifier */ NextToken (D); @@ -2211,6 +2235,7 @@ static void ParseSym (InputData* D) long Value; cc65_size Size = 0; StrBuf SymName = STRBUF_INITIALIZER; + unsigned Segment = CC65_INV_ID; SymInfo* S; enum { ibNone = 0x00, @@ -2234,8 +2259,8 @@ static void ParseSym (InputData* D) /* Something we know? */ if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_FILE && - D->Tok != TOK_NAME && D->Tok != TOK_SEGMENT&& - D->Tok != TOK_SIZE && D->Tok != TOK_TYPE && + D->Tok != TOK_NAME && D->Tok != TOK_SEGMENT&& + D->Tok != TOK_SIZE && D->Tok != TOK_TYPE && D->Tok != TOK_VALUE) { /* Try smart error recovery */ @@ -2286,7 +2311,7 @@ static void ParseSym (InputData* D) if (!IntConstFollows (D)) { goto ErrorExit; } - /* ### Drop value for now */ + Segment = (unsigned) D->IVal; InfoBits |= ibSegment; NextToken (D); break; @@ -2355,7 +2380,7 @@ static void ParseSym (InputData* D) } /* Create the symbol info and remember it */ - S = NewSymInfo (&SymName, Value, Type, Size); + S = NewSymInfo (&SymName, Value, Type, Size, Segment); CollAppend (&D->Info->SymInfoByName, S); CollAppend (&D->Info->SymInfoByVal, S); @@ -2454,11 +2479,11 @@ ErrorExit: -static SegInfo* FindSegInfoById (InputData* D, unsigned Id) +static SegInfo* FindSegInfoById (DbgInfo* D, unsigned Id) /* Find the SegInfo with a given Id */ { /* Get a pointer to the segment info collection */ - Collection* SegInfos = &D->Info->SegInfoById; + Collection* SegInfos = &D->SegInfoById; /* Do a binary search */ int Lo = 0; @@ -2532,9 +2557,12 @@ static int FindFileInfoByName (Collection* FileInfos, const char* FileName, -static FileInfo* FindFileInfoById (Collection* FileInfos, unsigned Id) +static FileInfo* FindFileInfoById (DbgInfo* D, unsigned Id) /* Find the FileInfo with a given Id */ { + /* Get a pointer to the collection */ + Collection* FileInfos = &D->FileInfoById; + /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (FileInfos) - 1; @@ -2637,7 +2665,7 @@ static void ProcessLineInfo (InputData* D) if (LastFileInfo && LastFileInfo->Id == L->File.Id) { F = LastFileInfo; } else { - F = FindFileInfoById (&D->Info->FileInfoById, L->File.Id); + F = FindFileInfoById (D->Info, L->File.Id); /* If we have no corresponding file info, print a warning and * remove the line info. @@ -2665,7 +2693,7 @@ static void ProcessLineInfo (InputData* D) if (LastSegInfo && LastSegInfo->Id == L->Seg.Id) { S = LastSegInfo; } else { - S = FindSegInfoById (D, L->Seg.Id); + S = FindSegInfoById (D->Info, L->Seg.Id); /* If we have no corresponding segment info, print a warning and * remove the line info. @@ -2884,7 +2912,7 @@ static int FindSymInfoByValue (Collection* SymInfos, long Value, unsigned* Index /*****************************************************************************/ -/* Code */ +/* Debug info files */ /*****************************************************************************/ @@ -3065,6 +3093,12 @@ void cc65_free_dbginfo (cc65_dbginfo Handle) +/*****************************************************************************/ +/* Line info */ +/*****************************************************************************/ + + + cc65_lineinfo* cc65_lineinfo_byaddr (cc65_dbginfo Handle, unsigned long Addr) /* Return line information for the given address. The function returns 0 * if no line information was found. @@ -3187,6 +3221,12 @@ void cc65_free_lineinfo (cc65_dbginfo Handle, cc65_lineinfo* Info) +/*****************************************************************************/ +/* Source files */ +/*****************************************************************************/ + + + cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle) /* Return a list of all source files */ { @@ -3226,9 +3266,7 @@ cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle) } /* Copy the data */ - D->data[D->count].source_name = F->FileName; - D->data[D->count].source_size = F->Size; - D->data[D->count].source_mtime = F->MTime; + CopyFileInfo (D->data + D->count, F); /* One more valid entry */ ++D->count; @@ -3240,6 +3278,44 @@ cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle) +cc65_sourceinfo* cc65_sourceinfo_byid (cc65_dbginfo Handle, unsigned Id) +/* Return information about a source file with a specific id. The function + * returns NULL if the id is invalid (no such source file) and otherwise a + * cc65_sourceinfo structure with one entry that contains the requested + * source file information. + */ +{ + DbgInfo* Info; + const FileInfo* F; + cc65_sourceinfo* D; + + /* Check the parameter */ + assert (Handle != 0); + + /* The handle is actually a pointer to a debug info struct */ + Info = (DbgInfo*) Handle; + + /* Search for the Id */ + F = FindFileInfoById (Info, Id); + + /* If not found return NULL */ + if (F == 0) { + return 0; + } + + /* Allocate memory for the data structure returned to the caller */ + D = new_cc65_sourceinfo (1); + + /* Fill in the data */ + CopyFileInfo (D->data, F); + + /* Return the result */ + return D; +} + + + + void cc65_free_sourceinfo (cc65_dbginfo Handle, cc65_sourceinfo* Info) /* Free a source info record */ { @@ -3252,6 +3328,12 @@ void cc65_free_sourceinfo (cc65_dbginfo Handle, cc65_sourceinfo* Info) +/*****************************************************************************/ +/* Segments */ +/*****************************************************************************/ + + + cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle) /* Return a list of all segments referenced in the debug information */ { @@ -3275,16 +3357,8 @@ cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle) /* Fill in the data */ D->count = CollCount (SegInfoByName); for (I = 0; I < CollCount (SegInfoByName); ++I) { - - /* Get this item */ - const SegInfo* S = CollAt (SegInfoByName, I); - /* Copy the data */ - D->data[I].segment_name = S->SegName; - D->data[I].segment_start = S->Start; - D->data[I].segment_size = S->Size; - D->data[I].output_name = S->OutputName; - D->data[I].output_offs = S->OutputOffs; + CopySegInfo (D->data + I, CollAt (SegInfoByName, I)); } /* Return the result */ @@ -3293,6 +3367,42 @@ cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle) +cc65_segmentinfo* cc65_segmentinfo_byid (cc65_dbginfo Handle, unsigned Id) +/* Return information about a segment with a specific id. The function returns + * NULL if the id is invalid (no such segment) and otherwise a segmentinfo + * structure with one entry that contains the requested segment information. + */ +{ + DbgInfo* Info; + const SegInfo* S; + cc65_segmentinfo* D; + + /* Check the parameter */ + assert (Handle != 0); + + /* The handle is actually a pointer to a debug info struct */ + Info = (DbgInfo*) Handle; + + /* Search for the Id */ + S = FindSegInfoById (Info, Id); + + /* If not found return NULL */ + if (S == 0) { + return 0; + } + + /* Allocate memory for the data structure returned to the caller */ + D = new_cc65_segmentinfo (1); + + /* Fill in the data */ + CopySegInfo (D->data, S); + + /* Return the result */ + return D; +} + + + void cc65_free_segmentinfo (cc65_dbginfo Handle, cc65_segmentinfo* Info) /* Free a segment info record */ { @@ -3305,6 +3415,12 @@ void cc65_free_segmentinfo (cc65_dbginfo Handle, cc65_segmentinfo* Info) +/*****************************************************************************/ +/* Symbols */ +/*****************************************************************************/ + + + 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. diff --git a/src/dbginfo/dbginfo.h b/src/dbginfo/dbginfo.h index b4c6375e9..d63bd68b2 100644 --- a/src/dbginfo/dbginfo.h +++ b/src/dbginfo/dbginfo.h @@ -46,12 +46,12 @@ extern "C" { /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ -/* Data types used for addresses, sizes and line numbers. Change to "unsigned +/* Data types used for addresses, sizes and line numbers. Change to "unsigned * long" if you ever want to run the code on a 16-bit machine. */ typedef unsigned cc65_line; /* Used to store line numbers */ @@ -63,6 +63,9 @@ typedef unsigned cc65_size; /* Used to store (65xx) sizes */ */ typedef void* cc65_dbginfo; +/* A value that is used to mark invalid ids */ +#define CC65_INV_ID (~0U) + /* Severity for cc65_parseerror */ typedef enum { CC65_WARNING, @@ -120,6 +123,7 @@ struct cc65_lineinfo { /* Source file information */ typedef struct cc65_sourcedata cc65_sourcedata; struct cc65_sourcedata { + unsigned id; /* The internal file id */ const char* source_name; /* Name of the file */ unsigned long source_size; /* Size of file */ unsigned long source_mtime; /* Modification time */ @@ -140,6 +144,7 @@ struct cc65_sourceinfo { */ typedef struct cc65_segmentdata cc65_segmentdata; struct cc65_segmentdata { + unsigned id; /* The internal segment id */ const char* segment_name; /* Name of the segment */ cc65_addr segment_start; /* Start address of segment */ cc65_addr segment_size; /* Size of segment */ @@ -165,6 +170,10 @@ struct cc65_symboldata { cc65_symbol_type symbol_type; /* Type of symbol */ cc65_size symbol_size; /* Size of symbol, 0 if unknown */ long symbol_value; /* Value of symbol */ + unsigned symbol_segment; /* If the symbol is segment relative, + * this contains the id of segment, + * otherwise CC65_INV_ID + */ }; typedef struct cc65_symbolinfo cc65_symbolinfo; @@ -176,7 +185,7 @@ struct cc65_symbolinfo { /*****************************************************************************/ -/* Code */ +/* Debug info files */ /*****************************************************************************/ @@ -192,6 +201,14 @@ cc65_dbginfo cc65_read_dbginfo (const char* filename, cc65_errorfunc errorfunc); void cc65_free_dbginfo (cc65_dbginfo Handle); /* Free debug information read from a file */ + + +/*****************************************************************************/ +/* Line info */ +/*****************************************************************************/ + + + cc65_lineinfo* cc65_lineinfo_byaddr (cc65_dbginfo handle, unsigned long addr); /* Return line information for the given address. The function returns NULL * if no line information was found. @@ -206,18 +223,55 @@ cc65_lineinfo* cc65_lineinfo_byname (cc65_dbginfo handle, const char* filename, void cc65_free_lineinfo (cc65_dbginfo handle, cc65_lineinfo* info); /* Free line info returned by one of the other functions */ + + +/*****************************************************************************/ +/* Source files */ +/*****************************************************************************/ + + + cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo handle); /* Return a list of all source files */ +cc65_sourceinfo* cc65_sourceinfo_byid (cc65_dbginfo handle, unsigned id); +/* Return information about a source file with a specific id. The function + * returns NULL if the id is invalid (no such source file) and otherwise a + * cc65_sourceinfo structure with one entry that contains the requested + * source file information. + */ + void cc65_free_sourceinfo (cc65_dbginfo handle, cc65_sourceinfo* info); /* Free a source info record */ + + +/*****************************************************************************/ +/* Segments */ +/*****************************************************************************/ + + + cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo handle); /* Return a list of all segments referenced in the debug information */ +cc65_segmentinfo* cc65_segmentinfo_byid (cc65_dbginfo handle, unsigned id); +/* Return information about a segment with a specific id. The function returns + * NULL if the id is invalid (no such segment) and otherwise a cc65_segmentinfo + * structure with one entry that contains the requested segment information. + */ + void cc65_free_segmentinfo (cc65_dbginfo handle, cc65_segmentinfo* info); /* Free a segment info record */ + + +/*****************************************************************************/ +/* Symbols */ +/*****************************************************************************/ + + + 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. diff --git a/src/dbginfo/dbgtest.c b/src/dbginfo/dbgtest.c index 9d7b7ad48..197816c14 100644 --- a/src/dbginfo/dbgtest.c +++ b/src/dbginfo/dbgtest.c @@ -39,6 +39,10 @@ +static cc65_dbginfo Info; + + + static void ErrorFunc (const struct cc65_parseerror* E) /* Handle errors or warnings that occur while parsing a debug file */ { @@ -113,9 +117,20 @@ static void PrintLineData (const cc65_linedata* D) static void PrintSymbolData (const cc65_symboldata* D) /* Print the data for one symbol */ { - printf (" %-20s = %04lX (size %u)\n", - D->symbol_name, + char Segment[256] = { 0 }; /* Needs dynamic alloc ### */ + if (D->symbol_segment != CC65_INV_ID) { + cc65_segmentinfo* I = cc65_segmentinfo_byid (Info, D->symbol_segment); + if (I && I->count == 1) { + sprintf (Segment, "segment=%s,", I->data[0].segment_name); + cc65_free_segmentinfo (Info, I); + } + } + + + printf (" %-20s = %04lX (%ssize=%u)\n", + D->symbol_name, D->symbol_value, + Segment, D->symbol_size); } @@ -176,7 +191,6 @@ static void PrintSymbolInfo (const cc65_symbolinfo* Symbols) int main (int argc, char** argv) { const char* Input; - cc65_dbginfo Info; cc65_sourceinfo* Sources; cc65_segmentinfo* Segments; cc65_lineinfo* Lines;