mirror of
https://github.com/cc65/cc65.git
synced 2025-01-30 12:33:15 +00:00
Read and manage additional line information for symbols.
git-svn-id: svn://svn.cc65.org/cc65/trunk@5215 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
f8e5463278
commit
1797235794
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2005-2010, Ullrich von Bassewitz */
|
||||
/* (C) 2005-2011, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
@ -75,7 +75,7 @@ static ExprNode* Factor (void)
|
||||
} else {
|
||||
N = NewExprNode (0, EXPR_SYMBOL);
|
||||
N->V.Imp = InsertImport (GenImport (Name, ADDR_SIZE_ABS));
|
||||
CollAppend (&N->V.Imp->LineInfos, GenLineInfo (&CfgErrorPos));
|
||||
CollAppend (&N->V.Imp->RefLines, GenLineInfo (&CfgErrorPos));
|
||||
}
|
||||
|
||||
/* Skip the symbol name */
|
||||
|
@ -358,7 +358,7 @@ static SegDesc* NewSegDesc (unsigned Name)
|
||||
|
||||
static void FreeSegDesc (SegDesc* S)
|
||||
/* Free a segment descriptor */
|
||||
{
|
||||
{
|
||||
FreeLineInfo (S->LI);
|
||||
xfree (S);
|
||||
}
|
||||
@ -1418,7 +1418,7 @@ static void ParseSymbols (void)
|
||||
AttrCheck (AttrFlags, atType, "TYPE");
|
||||
/* Create the export */
|
||||
Exp = CreateExprExport (Name, Value, AddrSize);
|
||||
CollAppend (&Exp->LineInfos, GenLineInfo (&CfgErrorPos));
|
||||
CollAppend (&Exp->DefLines, GenLineInfo (&CfgErrorPos));
|
||||
break;
|
||||
|
||||
case CfgSymImport:
|
||||
@ -1429,7 +1429,7 @@ static void ParseSymbols (void)
|
||||
/* Generate the import */
|
||||
Imp = InsertImport (GenImport (Name, AddrSize));
|
||||
/* Remember the file position */
|
||||
CollAppend (&Imp->LineInfos, GenLineInfo (&CfgErrorPos));
|
||||
CollAppend (&Imp->DefLines, GenLineInfo (&CfgErrorPos));
|
||||
break;
|
||||
|
||||
case CfgSymWeak:
|
||||
@ -1679,7 +1679,7 @@ static void ProcessSymbols (void)
|
||||
if ((E = FindExport (Sym->Name)) == 0 || IsUnresolvedExport (E)) {
|
||||
/* The symbol is undefined, generate an export */
|
||||
E = CreateExprExport (Sym->Name, Sym->Value, Sym->AddrSize);
|
||||
CollAppend (&E->LineInfos, Sym->LI);
|
||||
CollAppend (&E->DefLines, Sym->LI);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1702,12 +1702,12 @@ static void CreateRunDefines (SegDesc* S, unsigned long SegAddr)
|
||||
/* Define the run address of the segment */
|
||||
SB_Printf (&Buf, "__%s_RUN__", GetString (S->Name));
|
||||
E = CreateMemoryExport (GetStrBufId (&Buf), S->Run, SegAddr - S->Run->Start);
|
||||
CollAppend (&E->LineInfos, S->LI);
|
||||
CollAppend (&E->DefLines, S->LI);
|
||||
|
||||
/* Define the size of the segment */
|
||||
SB_Printf (&Buf, "__%s_SIZE__", GetString (S->Name));
|
||||
E = CreateConstExport (GetStrBufId (&Buf), S->Seg->Size);
|
||||
CollAppend (&E->LineInfos, S->LI);
|
||||
CollAppend (&E->DefLines, S->LI);
|
||||
|
||||
S->Flags |= SF_RUN_DEF;
|
||||
SB_Done (&Buf);
|
||||
@ -1724,7 +1724,7 @@ static void CreateLoadDefines (SegDesc* S, unsigned long SegAddr)
|
||||
/* Define the load address of the segment */
|
||||
SB_Printf (&Buf, "__%s_LOAD__", GetString (S->Name));
|
||||
E = CreateMemoryExport (GetStrBufId (&Buf), S->Load, SegAddr - S->Load->Start);
|
||||
CollAppend (&E->LineInfos, S->LI);
|
||||
CollAppend (&E->DefLines, S->LI);
|
||||
|
||||
S->Flags |= SF_LOAD_DEF;
|
||||
SB_Done (&Buf);
|
||||
@ -1789,7 +1789,7 @@ unsigned CfgProcess (void)
|
||||
/* Define the start of the memory area */
|
||||
SB_Printf (&Buf, "__%s_START__", GetString (M->Name));
|
||||
E = CreateMemoryExport (GetStrBufId (&Buf), M, 0);
|
||||
CollAppend (&E->LineInfos, M->LI);
|
||||
CollAppend (&E->DefLines, M->LI);
|
||||
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
@ -1906,12 +1906,12 @@ unsigned CfgProcess (void)
|
||||
/* Define the size of the memory area */
|
||||
SB_Printf (&Buf, "__%s_SIZE__", GetString (M->Name));
|
||||
E = CreateConstExport (GetStrBufId (&Buf), M->Size);
|
||||
CollAppend (&E->LineInfos, M->LI);
|
||||
CollAppend (&E->DefLines, M->LI);
|
||||
|
||||
/* Define the fill level of the memory area */
|
||||
SB_Printf (&Buf, "__%s_LAST__", GetString (M->Name));
|
||||
E = CreateMemoryExport (GetStrBufId (&Buf), M, M->FillLevel);
|
||||
CollAppend (&E->LineInfos, M->LI);
|
||||
CollAppend (&E->DefLines, M->LI);
|
||||
|
||||
SB_Done (&Buf);
|
||||
}
|
||||
|
@ -66,9 +66,9 @@ static void AssignIds (void)
|
||||
{
|
||||
/* Walk over all modules */
|
||||
unsigned I;
|
||||
unsigned SymBaseId = 0;
|
||||
unsigned ScopeBaseId = 0;
|
||||
unsigned SpanBaseId = 0;
|
||||
unsigned SymBaseId = 0;
|
||||
for (I = 0; I < CollCount (&ObjDataList); ++I) {
|
||||
|
||||
/* Get this module */
|
||||
@ -78,18 +78,21 @@ static void AssignIds (void)
|
||||
O->Id = I;
|
||||
|
||||
/* Assign base ids */
|
||||
O->SymBaseId = SymBaseId;
|
||||
O->ScopeBaseId = ScopeBaseId;
|
||||
O->SpanBaseId = SpanBaseId;
|
||||
O->SymBaseId = SymBaseId;
|
||||
|
||||
/* Bump the base ids */
|
||||
SymBaseId += CollCount (&O->DbgSyms);
|
||||
ScopeBaseId += CollCount (&O->Scopes);
|
||||
SpanBaseId += CollCount (&O->Spans);
|
||||
SymBaseId += CollCount (&O->DbgSyms);
|
||||
}
|
||||
|
||||
/* Assign the ids to the file infos */
|
||||
AssignFileInfoIds ();
|
||||
|
||||
/* Assign the ids to line infos */
|
||||
AssignLineInfoIds ();
|
||||
}
|
||||
|
||||
|
||||
@ -105,7 +108,7 @@ void CreateDbgFile (void)
|
||||
|
||||
/* Output version information */
|
||||
fprintf (F, "version\tmajor=2,minor=0\n");
|
||||
|
||||
|
||||
/* Output a line with the item numbers so the debug info module is able
|
||||
* to preallocate the required memory.
|
||||
*/
|
||||
|
@ -65,7 +65,8 @@ struct DbgSym {
|
||||
unsigned Id; /* Id of debug symbol */
|
||||
DbgSym* Next; /* Pool linear list link */
|
||||
ObjData* Obj; /* Object file that exports the name */
|
||||
Collection LineInfos; /* Line infos of definition */
|
||||
Collection DefLines; /* Line infos for definition */
|
||||
Collection RefLines; /* Line infos for references */
|
||||
ExprNode* Expr; /* Expression (0 if not def'd) */
|
||||
unsigned Size; /* Symbol size if any */
|
||||
unsigned OwnerId; /* Id of parent/owner */
|
||||
@ -99,7 +100,8 @@ static DbgSym* NewDbgSym (unsigned Id, unsigned Type, unsigned char AddrSize,
|
||||
D->Id = Id;
|
||||
D->Next = 0;
|
||||
D->Obj = O;
|
||||
D->LineInfos = EmptyCollection;
|
||||
D->DefLines = EmptyCollection;
|
||||
D->RefLines = EmptyCollection;
|
||||
D->Expr = 0;
|
||||
D->Size = 0;
|
||||
D->OwnerId = ~0U;
|
||||
@ -202,7 +204,8 @@ DbgSym* ReadDbgSym (FILE* F, ObjData* O, unsigned Id)
|
||||
}
|
||||
|
||||
/* Last is the list of line infos for this symbol */
|
||||
ReadLineInfoList (F, O, &D->LineInfos);
|
||||
ReadLineInfoList (F, O, &D->DefLines);
|
||||
ReadLineInfoList (F, O, &D->RefLines);
|
||||
|
||||
/* Return the new DbgSym */
|
||||
return D;
|
||||
@ -273,6 +276,17 @@ void PrintDbgSyms (FILE* F)
|
||||
fprintf (F, ",parent=%u", O->SymBaseId + S->OwnerId);
|
||||
}
|
||||
|
||||
/* Output line infos */
|
||||
if (CollCount (&S->DefLines) > 0) {
|
||||
unsigned K;
|
||||
const LineInfo* LI = CollConstAt (&S->DefLines, 0);
|
||||
fprintf (F, ",line=%u", LI->Id);
|
||||
for (K = 1; K < CollCount (&S->DefLines); ++K) {
|
||||
LI = CollConstAt (&S->DefLines, K);
|
||||
fprintf (F, "+%u", LI->Id);
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is an import, output the id of the matching export.
|
||||
* If this is not an import, output its value and - if we have
|
||||
* it - the segment.
|
||||
|
@ -108,7 +108,8 @@ static Import* NewImport (unsigned char AddrSize, ObjData* Obj)
|
||||
/* Initialize the fields */
|
||||
I->Next = 0;
|
||||
I->Obj = Obj;
|
||||
I->LineInfos = EmptyCollection;
|
||||
I->DefLines = EmptyCollection;
|
||||
I->RefLines = EmptyCollection;
|
||||
I->Exp = 0;
|
||||
I->Name = INVALID_STRING_ID;
|
||||
I->Flags = 0;
|
||||
@ -129,8 +130,9 @@ void FreeImport (Import* I)
|
||||
/* Safety */
|
||||
PRECONDITION ((I->Flags & IMP_INLIST) == 0);
|
||||
|
||||
/* Free the line info collection */
|
||||
DoneCollection (&I->LineInfos);
|
||||
/* Free the line info collections */
|
||||
DoneCollection (&I->DefLines);
|
||||
DoneCollection (&I->RefLines);
|
||||
|
||||
/* Free the struct */
|
||||
xfree (I);
|
||||
@ -153,7 +155,8 @@ Import* ReadImport (FILE* F, ObjData* Obj)
|
||||
I->Name = MakeGlobalStringId (Obj, ReadVar (F));
|
||||
|
||||
/* Read the line infos */
|
||||
ReadLineInfoList (F, Obj, &I->LineInfos);
|
||||
ReadLineInfoList (F, Obj, &I->DefLines);
|
||||
ReadLineInfoList (F, Obj, &I->RefLines);
|
||||
|
||||
/* Check the address size */
|
||||
if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) {
|
||||
@ -278,18 +281,12 @@ Import* InsertImport (Import* I)
|
||||
const LineInfo* GetImportPos (const Import* Imp)
|
||||
/* Return the basic line info of an import */
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Search for a line info of LI_TYPE_ASM */
|
||||
for (I = 0; I < CollCount (&Imp->LineInfos); ++I) {
|
||||
const LineInfo* LI = CollConstAt (&Imp->LineInfos, I);
|
||||
if (LI_GET_TYPE (LI->Type) == LI_TYPE_ASM) {
|
||||
return LI;
|
||||
}
|
||||
/* Search in DefLines, then in RefLines */
|
||||
const LineInfo* LI = GetAsmLineInfo (&Imp->DefLines);
|
||||
if (LI == 0) {
|
||||
LI = GetAsmLineInfo (&Imp->RefLines);
|
||||
}
|
||||
|
||||
/* Not found - return the one in slot zero */
|
||||
return CollConstAt (&Imp->LineInfos, 0);
|
||||
return LI;
|
||||
}
|
||||
|
||||
|
||||
@ -316,7 +313,8 @@ static Export* NewExport (unsigned Type, unsigned char AddrSize,
|
||||
E->ImpList = 0;
|
||||
E->Expr = 0;
|
||||
E->Size = 0;
|
||||
E->LineInfos = EmptyCollection;
|
||||
E->DefLines = EmptyCollection;
|
||||
E->RefLines = EmptyCollection;
|
||||
E->DbgSymId = ~0U;
|
||||
E->Type = Type | SYM_EXPORT;
|
||||
E->AddrSize = AddrSize;
|
||||
@ -338,7 +336,8 @@ void FreeExport (Export* E)
|
||||
PRECONDITION ((E->Flags & EXP_INLIST) == 0);
|
||||
|
||||
/* Free the line infos */
|
||||
DoneCollection (&E->LineInfos);
|
||||
DoneCollection (&E->DefLines);
|
||||
DoneCollection (&E->RefLines);
|
||||
|
||||
/* Free the export expression */
|
||||
FreeExpr (E->Expr);
|
||||
@ -402,8 +401,9 @@ Export* ReadExport (FILE* F, ObjData* O)
|
||||
E->Size = ReadVar (F);
|
||||
}
|
||||
|
||||
/* Last is the file position where the definition was done */
|
||||
ReadLineInfoList (F, O, &E->LineInfos);
|
||||
/* Last are the locations */
|
||||
ReadLineInfoList (F, O, &E->DefLines);
|
||||
ReadLineInfoList (F, O, &E->RefLines);
|
||||
|
||||
/* Return the new export */
|
||||
return E;
|
||||
@ -488,8 +488,12 @@ void InsertExport (Export* E)
|
||||
const LineInfo* GetExportPos (const Export* E)
|
||||
/* Return the basic line info of an export */
|
||||
{
|
||||
/* Source file position is always in slot zero */
|
||||
return CollConstAt (&E->LineInfos, 0);
|
||||
/* Search in DefLines, then in RefLines */
|
||||
const LineInfo* LI = GetAsmLineInfo (&E->DefLines);
|
||||
if (LI == 0) {
|
||||
LI = GetAsmLineInfo (&E->RefLines);
|
||||
}
|
||||
return LI;
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,7 +64,8 @@ typedef struct Import Import;
|
||||
struct Import {
|
||||
Import* Next; /* Single linked list */
|
||||
ObjData* Obj; /* Object file that imports the name */
|
||||
Collection LineInfos; /* Line info of reference */
|
||||
Collection DefLines; /* Line infos of definition */
|
||||
Collection RefLines; /* Line infos of reference */
|
||||
struct Export* Exp; /* Matching export for this import */
|
||||
unsigned Name; /* Name if not in table */
|
||||
unsigned short Flags; /* Generic flags */
|
||||
@ -84,7 +85,8 @@ struct Export {
|
||||
Import* ImpList; /* List of imports for this symbol */
|
||||
ExprNode* Expr; /* Expression (0 if not def'd) */
|
||||
unsigned Size; /* Size of the symbol if any */
|
||||
Collection LineInfos; /* Line info of definition */
|
||||
Collection DefLines; /* Line infos of definition */
|
||||
Collection RefLines; /* Line infos of reference */
|
||||
unsigned DbgSymId; /* Id of debug symbol for this export */
|
||||
unsigned short Type; /* Type of export */
|
||||
unsigned short AddrSize; /* Address size of export */
|
||||
|
@ -61,6 +61,7 @@ static LineInfo* NewLineInfo (void)
|
||||
LineInfo* LI = xmalloc (sizeof (LineInfo));
|
||||
|
||||
/* Initialize the fields */
|
||||
LI->Id = ~0U;
|
||||
LI->File = 0;
|
||||
LI->Type = LI_MAKE_TYPE (LI_TYPE_ASM, 0);
|
||||
LI->Pos.Name = INVALID_STRING_ID;
|
||||
@ -155,13 +156,59 @@ void ReadLineInfoList (FILE* F, ObjData* O, Collection* LineInfos)
|
||||
|
||||
|
||||
|
||||
const LineInfo* GetAsmLineInfo (const Collection* LineInfos)
|
||||
/* Find a line info of type LI_TYPE_ASM in the given collection and return it.
|
||||
* Return NULL if no such line info was found.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Search for a line info of LI_TYPE_ASM */
|
||||
for (I = 0; I < CollCount (LineInfos); ++I) {
|
||||
const LineInfo* LI = CollConstAt (LineInfos, I);
|
||||
if (LI_GET_TYPE (LI->Type) == LI_TYPE_ASM) {
|
||||
return LI;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AssignLineInfoIds (void)
|
||||
/* Assign the ids to the line infos */
|
||||
{
|
||||
unsigned I, J;
|
||||
|
||||
/* Walk over all line infos */
|
||||
unsigned Id = 0;
|
||||
for (I = 0; I < CollCount (&ObjDataList); ++I) {
|
||||
|
||||
/* Get the object file */
|
||||
ObjData* O = CollAtUnchecked (&ObjDataList, I);
|
||||
|
||||
/* Output the line infos */
|
||||
for (J = 0; J < CollCount (&O->LineInfos); ++J) {
|
||||
|
||||
/* Get this line info */
|
||||
LineInfo* LI = CollAtUnchecked (&O->LineInfos, J);
|
||||
|
||||
/* Assign the id */
|
||||
LI->Id = Id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PrintDbgLineInfo (FILE* F)
|
||||
/* Output the line infos to a debug info file */
|
||||
{
|
||||
unsigned I, J, K;
|
||||
|
||||
/* Print line infos from all modules we have linked into the output file */
|
||||
unsigned Id = 0;
|
||||
for (I = 0; I < CollCount (&ObjDataList); ++I) {
|
||||
|
||||
/* Get the object file */
|
||||
@ -183,7 +230,7 @@ void PrintDbgLineInfo (FILE* F)
|
||||
/* Print the start of the line */
|
||||
fprintf (F,
|
||||
"line\tid=%u,file=%u,line=%lu",
|
||||
Id++, LI->File->Id, GetSourceLine (LI));
|
||||
LI->Id, LI->File->Id, GetSourceLine (LI));
|
||||
|
||||
/* Print type if not LI_TYPE_ASM and count if not zero */
|
||||
if (Type != LI_TYPE_ASM) {
|
||||
|
@ -73,6 +73,7 @@ struct Segment;
|
||||
*/
|
||||
typedef struct LineInfo LineInfo;
|
||||
struct LineInfo {
|
||||
unsigned Id; /* Line info id */
|
||||
struct FileInfo* File; /* File struct for this line if any */
|
||||
unsigned Type; /* Type of line info */
|
||||
FilePos Pos; /* Position in file */
|
||||
@ -101,6 +102,11 @@ void ReadLineInfoList (FILE* F, struct ObjData* O, Collection* LineInfos);
|
||||
* make real line infos from them and place them into the passed collection.
|
||||
*/
|
||||
|
||||
const LineInfo* GetAsmLineInfo (const Collection* LineInfos);
|
||||
/* Find a line info of type LI_TYPE_ASM in the given collection and return it.
|
||||
* Return NULL if no such line info was found.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE const FilePos* GetSourcePos (const LineInfo* LI)
|
||||
/* Return the source file position from the given line info */
|
||||
@ -165,6 +171,9 @@ INLINE unsigned long GetSourceLineFromList (const Collection* LineInfos)
|
||||
GetSourceLine ((const LineInfo*) CollConstAt ((LineInfos), 0))
|
||||
#endif
|
||||
|
||||
void AssignLineInfoIds (void);
|
||||
/* Assign the ids to the line infos */
|
||||
|
||||
void PrintDbgLineInfo (FILE* F);
|
||||
/* Output the line infos to a debug info file */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user