1
0
mirror of https://github.com/cc65/cc65.git synced 2024-11-19 06:31:31 +00:00

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
This commit is contained in:
uz 2011-06-14 21:18:44 +00:00
parent c768fc7373
commit 44b829cc01
3 changed files with 229 additions and 45 deletions

View File

@ -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.

View File

@ -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.

View File

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