/* common */
#include "coll.h"
+#include "filepos.h"
#include "hlldbgsym.h"
+#include "scopedefs.h"
#include "strbuf.h"
/* ca65 */
#include "lineinfo.h"
#include "objfile.h"
#include "nexttok.h"
+#include "symentry.h"
#include "symtab.h"
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
+/* Structure used for a high level language function or symbol */
+typedef struct HLLDbgSym HLLDbgSym;
+struct HLLDbgSym {
+ unsigned Flags; /* See above */
+ unsigned Name; /* String id of name */
+ unsigned AsmName; /* String id of asm symbol name */
+ SymEntry* Sym; /* The assembler symbol */
+ int Offs; /* Offset if any */
+ unsigned Type; /* String id of type */
+ SymTable* Scope; /* Parent scope */
+ unsigned FuncId; /* Id of hll function if any */
+ FilePos Pos; /* Position of statement */
+};
+
/* The current line info */
static LineInfo* CurLineInfo = 0;
S->Flags = Flags;
S->Name = Name;
S->AsmName = EMPTY_STRING_ID;
+ S->Sym = 0;
S->Offs = 0;
S->Type = Type;
- S->ScopeId = CurrentScope->Id;
+ S->Scope = CurrentScope;
+ S->FuncId = ~0U;
+ S->Pos = CurTok.Pos;
/* Return the result */
return S;
if (CurrentScope == RootScope) {
ErrorSkip ("Functions may not be used in the root scope");
return;
- } else if (CurrentScope->Flags & ST_EXTFUNC) {
- ErrorSkip ("Only one function per scope allowed");
+ } else if (CurrentScope->Type != SCOPE_SCOPE || CurrentScope->Label == 0) {
+ ErrorSkip ("Functions can only be tagged to .PROC scopes");
+ return;
+ } else if (CurrentScope->Label->HLLSym != 0) {
+ ErrorSkip ("Only one HLL symbol per asm symbol is allowed");
+ return;
+ } else if (CurrentScope->Label->Name != AsmName) {
+ ErrorSkip ("Scope label and asm name for function must match");
return;
}
- CurrentScope->Flags |= ST_EXTFUNC;
/* Add the function */
S = NewHLLDbgSym (Flags, Name, Type);
- S->AsmName = AsmName;
+ S->Sym = CurrentScope->Label;
+ CurrentScope->Label->HLLSym = S;
CollAppend (&HLLDbgSyms, S);
}
+void DbgInfoCheck (void)
+/* Do checks on all hll debug info symbols when assembly is complete */
+{
+ /* When parsing the debug statements for HLL symbols, we have already
+ * tagged the functions to their asm counterparts. This wasn't done for
+ * C symbols, since we will allow forward declarations. So we have to
+ * resolve the normal C symbols now.
+ */
+ unsigned I;
+ for (I = 0; I < CollCount (&HLLDbgSyms); ++I) {
+
+ /* Get the next symbol */
+ HLLDbgSym* S = CollAtUnchecked (&HLLDbgSyms, I);
+
+ /* Ignore functions and auto symbols, because the later live on the
+ * stack and don't have corresponding asm symbols.
+ */
+ if (HLL_IS_FUNC (S->Flags) || HLL_GET_SC (S->Flags) == HLL_SC_AUTO) {
+ continue;
+ }
+
+ /* Safety */
+ CHECK (S->Sym == 0 && S->Scope != 0);
+
+ /* Search for the symbol name */
+ S->Sym = SymFindAny (S->Scope, GetStrBuf (S->AsmName));
+ if (S->Sym == 0) {
+ PError (&S->Pos, "Assembler symbol `%s' not found",
+ GetString (S->AsmName));
+ } else {
+ /* Set the backlink */
+ S->Sym->HLLSym = S;
+ }
+
+ }
+}
+
+
+
void WriteHLLDbgSyms (void)
/* Write a list of all high level language symbols to the object file. */
{
/* Get the next symbol */
const HLLDbgSym* S = CollAtUnchecked (&HLLDbgSyms, I);
+ /* Get the type of the symbol */
+ unsigned SC = HLL_GET_SC (S->Flags);
+
/* Write the symbol data */
ObjWriteVar (S->Flags);
ObjWriteVar (S->Name);
- ObjWriteVar (S->AsmName);
- ObjWriteVar (S->Offs);
+ if (SC != HLL_SC_AUTO) {
+ CHECK (S->Sym->DebugSymId != ~0U);
+ ObjWriteVar (S->Sym->DebugSymId);
+ }
+ if (SC == HLL_SC_AUTO || SC == HLL_SC_REG) {
+ ObjWriteVar (S->Offs);
+ }
ObjWriteVar (S->Type);
- ObjWriteVar (S->ScopeId);
+ ObjWriteVar (S->Scope->Id);
}
} else {
void DbgInfoSym (void);
/* Parse and handle SYM subcommand of the .dbg pseudo instruction */
+void DbgInfoCheck (void);
+/* Do checks on all hll debug info symbols when assembly is complete */
+
void WriteHLLDbgSyms (void);
/* Write a list of all high level language symbols to the object file. */
+void PError (const FilePos* Pos, const char* Format, ...)
+/* Print an error message giving an explicit file and position. */
+{
+ va_list ap;
+ va_start (ap, Format);
+ VPrintMsg (Pos, "Error", Format, ap);
+ va_end (ap);
+
+ /* Count errors */
+ ++ErrorCount;
+}
+
+
+
void LIError (const Collection* LineInfos, const char* Format, ...)
/* Print an error message using the given line infos. */
{
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print an error message */
+void PError (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3)));
+/* Print an error message giving an explicit file and position. */
+
void LIError (const Collection* LineInfos, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print an error message using the given line infos. */
/* ca65 */
#include "abend.h"
#include "asserts.h"
+#include "dbginfo.h"
#include "error.h"
#include "expr.h"
#include "feature.h"
SymCheck ();
}
+ /* If we didn't have any errors, check the hll debug symbols */
+ if (ErrorCount == 0) {
+ DbgInfoCheck ();
+ }
+
/* If we didn't have any errors, close the file scope lexical level */
if (ErrorCount == 0) {
SymLeaveLevel ();
S->RefLines = EmptyCollection;
for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) {
S->GuessedUse[I] = 0;
- }
+ }
+ S->HLLSym = 0;
S->Flags = Flags;
S->DebugSymId = ~0U;
S->ImportId = ~0U;
+/* Forwards */
+struct HLLDbgSym;
+
/* Bits for the Flags value in SymEntry */
#define SF_NONE 0x0000 /* Empty flag set */
-#define SF_USER 0x0001 /* User bit */
+#define SF_USER 0x0001 /* User bit */
#define SF_UNUSED 0x0002 /* Unused entry */
#define SF_EXPORT 0x0004 /* Export this symbol */
#define SF_IMPORT 0x0008 /* Import this symbol */
SymEntry* Locals; /* Root of subtree for local symbols */
union {
struct SymTable* Tab; /* Table this symbol is in */
- struct SymEntry* Entry;
+ struct SymEntry* Entry; /* Parent for cheap locals */
} Sym;
Collection DefLines; /* Line infos for definition */
Collection RefLines; /* Line infos for references */
* used. Currently only for zero page
* addressing
*/
+ struct HLLDbgSym* HLLSym; /* Symbol from high level language */
unsigned Flags; /* Symbol flags */
unsigned DebugSymId; /* Debug symbol id */
unsigned ImportId; /* Id of import if this is one */
{
SymEntry* Sym;
do {
- /* Search in the current table */
- Sym = SymFind (Scope, Name, SYM_FIND_EXISTING);
- if (Sym) {
- /* Found, return it */
- break;
- }
+ /* Search in the current table. Ignore entries flagged with SF_UNUSED,
+ * because for such symbols there is a real entry in one of the parent
+ * scopes.
+ */
+ Sym = SymFind (Scope, Name, SYM_FIND_EXISTING);
+ if (Sym) {
+ if (Sym->Flags & SF_UNUSED) {
+ Sym = 0;
+ } else {
+ /* Found, return it */
+ break;
+ }
+ }
/* Not found, search in the parent scope, if we have one */
- Scope = Scope->Parent;
+ Scope = Scope->Parent;
} while (Sym == 0 && Scope != 0);
/* Symbol table flags */
#define ST_NONE 0x00 /* No flags */
#define ST_DEFINED 0x01 /* Scope has been defined */
-#define ST_EXTFUNC 0x02 /* External debug function assigned */
/* A symbol table */
typedef struct SymTable SymTable;
#define HLL_TYPE_FUNC 0x0000U /* Function */
#define HLL_TYPE_SYM 0x0001U /* Symbol */
#define HLL_TYPE_MASK 0x0007U
-#define HLL_GET_TYPE(x) ((x) & HL_TYPE_MASK)
-#define HLL_IS_FUNC(x) (HL_GET_TYPE(x) == HL_TYPE_FUNC)
-#define HLL_IS_SYM(x) (HL_GET_TYPE(x) == HL_TYPE_SYM)
+#define HLL_GET_TYPE(x) ((x) & HLL_TYPE_MASK)
+#define HLL_IS_FUNC(x) (HLL_GET_TYPE(x) == HLL_TYPE_FUNC)
+#define HLL_IS_SYM(x) (HLL_GET_TYPE(x) == HLL_TYPE_SYM)
/* Storage class */
#define HLL_SC_AUTO 0x0000U /* On stack */
#define HLL_SC_STATIC 0x0010U /* Static linkage */
#define HLL_SC_EXTERN 0x0018U /* External linkage */
#define HLL_SC_MASK 0x0078U
-#define HLL_GET_SC(x) ((x) & HL_SC_MASK)
-
-/* Structure used for a high level language function or symbol */
-typedef struct HLLDbgSym HLLDbgSym;
-struct HLLDbgSym {
- unsigned Flags; /* See above */
- unsigned Name; /* String id of name */
- unsigned AsmName; /* String id of assembler name */
- int Offs; /* Offset if any */
- unsigned Type; /* String id of type */
- unsigned ScopeId; /* Id of parent scope */
-};
+#define HLL_GET_SC(x) ((x) & HLL_SC_MASK)
{
/* Walk over all modules */
unsigned I;
- unsigned ScopeBaseId = 0;
- unsigned SpanBaseId = 0;
- unsigned SymBaseId = 0;
+ unsigned HLLSymBaseId = 0;
+ unsigned ScopeBaseId = 0;
+ unsigned SpanBaseId = 0;
+ unsigned SymBaseId = 0;
for (I = 0; I < CollCount (&ObjDataList); ++I) {
/* Get this module */
O->Id = I;
/* Assign base ids */
- O->ScopeBaseId = ScopeBaseId;
- O->SpanBaseId = SpanBaseId;
- O->SymBaseId = SymBaseId;
+ O->HLLSymBaseId = HLLSymBaseId;
+ O->ScopeBaseId = ScopeBaseId;
+ O->SpanBaseId = SpanBaseId;
+ O->SymBaseId = SymBaseId;
/* Bump the base ids */
+ HLLSymBaseId += CollCount (&O->HLLDbgSyms);
ScopeBaseId += CollCount (&O->Scopes);
SpanBaseId += CollCount (&O->Spans);
SymBaseId += CollCount (&O->DbgSyms);
*/
fprintf (
F,
- "info\tfile=%u,lib=%u,line=%u,mod=%u,scope=%u,seg=%u,span=%u,type=%u\n",
+ "info\tcsym=%u,file=%u,lib=%u,line=%u,mod=%u,scope=%u,seg=%u,span=%u,sym=%u,type=%u\n",
+ HLLDbgSymCount (),
FileInfoCount (),
LibraryCount (),
LineInfoCount (),
ScopeCount (),
SegmentCount (),
SpanCount (),
+ DbgSymCount (),
TypeCount ()
);
/* Assign the ids to the items */
AssignIds ();
+ /* Output high level language symbols */
+ PrintHLLDbgSyms (F);
+
/* Output files */
PrintDbgFileInfo (F);
/* common */
#include "addrsize.h"
+#include "attrib.h"
#include "check.h"
+#include "hlldbgsym.h"
#include "symdefs.h"
#include "xmalloc.h"
#include "lineinfo.h"
#include "objdata.h"
#include "spool.h"
+#include "tpool.h"
unsigned short AddrSize; /* Address size of symbol */
};
+/* Structure used for a high level language function or symbol */
+typedef struct HLLDbgSym HLLDbgSym;
+struct HLLDbgSym {
+ unsigned Flags; /* See above */
+ unsigned Name; /* String id of name */
+ DbgSym* Sym; /* Assembler symbol */
+ int Offs; /* Offset if any */
+ unsigned Type; /* String id of type */
+ unsigned ScopeId; /* Parent scope */
+};
+
/* We will collect all debug symbols in the following array and remove
- * duplicates before outputing them.
+ * duplicates before outputing them into a label file.
*/
static DbgSym* DbgSymPool[256];
+static HLLDbgSym* NewHLLDbgSym (void)
+/* Create a new HLLDbgSym and return it */
+{
+ /* Allocate memory and return it */
+ return xmalloc (sizeof (HLLDbgSym));
+}
+
+
+
static DbgSym* GetDbgSym (DbgSym* D, long Val)
/* Check if we find the same debug symbol in the table. If we find it, return
* a pointer to the other occurrence, if we didn't find it, return NULL.
+HLLDbgSym* ReadHLLDbgSym (FILE* F, ObjData* O, unsigned Id attribute ((unused)))
+/* Read a hll debug symbol from a file, insert and return it */
+{
+ unsigned SC;
+
+ /* Create a new HLLDbgSym */
+ HLLDbgSym* S = NewHLLDbgSym ();
+
+ /* Read the data */
+ S->Flags = ReadVar (F);
+ SC = HLL_GET_SC (S->Flags);
+ S->Name = MakeGlobalStringId (O, ReadVar (F));
+ if (SC != HLL_SC_AUTO) {
+ S->Sym = GetObjDbgSym (O, ReadVar (F));
+ } else {
+ /* Auto variables aren't attached to asm symbols */
+ S->Sym = 0;
+ }
+ if (SC == HLL_SC_AUTO || SC == HLL_SC_REG) {
+ S->Offs = ReadVar (F);
+ } else {
+ S->Offs = 0;
+ }
+ S->Type = GetTypeId (GetObjString (O, ReadVar (F)));
+ S->ScopeId = ReadVar (F);
+
+ /* Return the (now initialized) hll debug symbol */
+ return S;
+}
+
+
+
static void ClearDbgSymTable (void)
/* Clear the debug symbol table */
{
+unsigned DbgSymCount (void)
+/* Return the total number of debug symbols */
+{
+ /* Walk over all object files */
+ unsigned I;
+ unsigned Count = 0;
+ for (I = 0; I < CollCount (&ObjDataList); ++I) {
+
+ /* Get this object file */
+ const ObjData* O = CollAtUnchecked (&ObjDataList, I);
+
+ /* Count debug symbols */
+ Count += CollCount (&O->DbgSyms);
+ }
+ return Count;
+}
+
+
+
+unsigned HLLDbgSymCount (void)
+/* Return the total number of high level language debug symbols */
+{
+ /* Walk over all object files */
+ unsigned I;
+ unsigned Count = 0;
+ for (I = 0; I < CollCount (&ObjDataList); ++I) {
+
+ /* Get this object file */
+ const ObjData* O = CollAtUnchecked (&ObjDataList, I);
+
+ /* Count debug symbols */
+ Count += CollCount (&O->HLLDbgSyms);
+ }
+ return Count;
+}
+
+
+
void PrintDbgSyms (FILE* F)
/* Print the debug symbols in a debug file */
{
+void PrintHLLDbgSyms (FILE* F)
+/* Print the high level language debug symbols in a debug file */
+{
+ unsigned I, J;
+
+ for (I = 0; I < CollCount (&ObjDataList); ++I) {
+
+ /* Get the object file */
+ ObjData* O = CollAtUnchecked (&ObjDataList, I);
+
+ /* Walk through all hll debug symbols in this module */
+ for (J = 0; J < CollCount (&O->HLLDbgSyms); ++J) {
+
+ /* Get the next debug symbol */
+ const HLLDbgSym* S = CollConstAt (&O->HLLDbgSyms, J);
+
+ /* Get the storage class */
+ unsigned SC = HLL_GET_SC (S->Flags);
+
+ /* Output the base info */
+ fprintf (F, "csym\tid=%u,name=\"%s\",scope=%u,type=%u,sc=",
+ O->HLLSymBaseId + J,
+ GetString (S->Name),
+ O->ScopeBaseId + S->ScopeId,
+ S->Type);
+ switch (SC) {
+ case HLL_SC_AUTO: fputs ("auto", F); break;
+ case HLL_SC_REG: fputs ("reg", F); break;
+ case HLL_SC_STATIC: fputs ("static", F); break;
+ case HLL_SC_EXTERN: fputs ("extern", F); break;
+ default:
+ Error ("Invalid storage class %u for hll symbol", SC);
+ break;
+ }
+
+ /* Output the offset if it is not zero */
+ if (S->Offs) {
+ fprintf (F, ",offs=%d", S->Offs);
+ }
+
+ /* For non auto symbols output the debug symbol id of the asm sym */
+ if (SC != HLL_SC_AUTO) {
+ fprintf (F, ",sym=%u", S->Sym->Id);
+ }
+
+ /* Terminate the output line */
+ fputc ('\n', F);
+ }
+ }
+}
+
+
+
void PrintDbgSymLabels (FILE* F)
/* Print the debug symbols in a VICE label file */
{
/* Forwards */
struct Scope;
+struct HLLDbgSym;
/* Opaque debug symbol structure */
typedef struct DbgSym DbgSym;
DbgSym* ReadDbgSym (FILE* F, ObjData* Obj, unsigned Id);
/* Read a debug symbol from a file, insert and return it */
+struct HLLDbgSym* ReadHLLDbgSym (FILE* F, ObjData* Obj, unsigned Id);
+/* Read a hll debug symbol from a file, insert and return it */
+
void PrintDbgSyms (FILE* F);
/* Print the debug symbols in a debug file */
+unsigned DbgSymCount (void);
+/* Return the total number of debug symbols */
+
+unsigned HLLDbgSymCount (void);
+/* Return the total number of high level language debug symbols */
+
+void PrintHLLDbgSyms (FILE* F);
+/* Print the high level language debug symbols in a debug file */
+
void PrintDbgSymLabels (FILE* F);
/* Print the debug symbols in a VICE label file */
O->MTime = 0;
O->Start = 0;
O->Flags = 0;
+ O->HLLSymBaseId = 0;
O->SymBaseId = 0;
O->ScopeBaseId = 0;
O->SpanBaseId = 0;
O->Exports = EmptyCollection;
O->Imports = EmptyCollection;
O->DbgSyms = EmptyCollection;
+ O->HLLDbgSyms = EmptyCollection;
O->LineInfos = EmptyCollection;
O->StringCount = 0;
O->Strings = 0;
}
DoneCollection (&O->Imports);
DoneCollection (&O->DbgSyms);
+ DoneCollection (&O->HLLDbgSyms);
for (I = 0; I < CollCount (&O->LineInfos); ++I) {
FreeLineInfo (CollAtUnchecked (&O->LineInfos, I));
+struct DbgSym* GetObjDbgSym (const ObjData* O, unsigned Id)
+/* Get a debug symbol from an object file checking for a valid index */
+{
+ if (Id >= CollCount (&O->DbgSyms)) {
+ Error ("Invalid debug symbol index (%u) in module `%s'",
+ Id, GetObjFileName (O));
+ }
+ return CollAtUnchecked (&O->DbgSyms, Id);
+}
+
+
+
struct Scope* GetObjScope (const ObjData* O, unsigned Id)
/* Get a scope from an object file checking for a valid index */
{
+
unsigned long Start; /* Start offset of data in library */
unsigned Flags;
+ unsigned HLLSymBaseId; /* Debug info base id for hll symbols */
unsigned SymBaseId; /* Debug info base id for symbols */
unsigned ScopeBaseId; /* Debug info base id for scopes */
unsigned SpanBaseId; /* Debug info base id for spans */
Collection Exports; /* List of all exports */
Collection Imports; /* List of all imports */
Collection DbgSyms; /* List of debug symbols */
+ Collection HLLDbgSyms; /* List of hll debug symbols */
Collection LineInfos; /* List of line infos */
unsigned StringCount; /* Count of strings */
unsigned* Strings; /* List of global string indices */
struct Export* GetObjExport (const ObjData* Obj, unsigned Id);
/* Get an export from an object file checking for a valid index */
+struct DbgSym* GetObjDbgSym (const ObjData* Obj, unsigned Id);
+/* Get a debug symbol from an object file checking for a valid index */
+
struct Scope* GetObjScope (const ObjData* Obj, unsigned Id);
/* Get a scope from an object file checking for a valid index */
/* Seek to the correct position */
FileSetPos (F, Pos);
- /* Read the data */
+ /* Read the asm debug symbols */
DbgSymCount = ReadVar (F);
CollGrow (&O->DbgSyms, DbgSymCount);
for (I = 0; I < DbgSymCount; ++I) {
- CollAppend (&O->DbgSyms, ReadDbgSym (F, O, I));
+ CollAppend (&O->DbgSyms, ReadDbgSym (F, O, I));
+ }
+
+ /* Read the hll debug symbols */
+ DbgSymCount = ReadVar (F);
+ CollGrow (&O->HLLDbgSyms, DbgSymCount);
+ for (I = 0; I < DbgSymCount; ++I) {
+ CollAppend (&O->HLLDbgSyms, ReadHLLDbgSym (F, O, I));
}
}