From 3b61ee2f5a1a676f334e613f63693b81cbf1fd83 Mon Sep 17 00:00:00 2001 From: uz Date: Mon, 22 Aug 2011 19:37:10 +0000 Subject: [PATCH] Track types, parse the extended debug info format with "type" lines. git-svn-id: svn://svn.cc65.org/cc65/trunk@5264 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/dbginfo/dbginfo.c | 238 ++++++++++++++++++++++++++++++++++++++++-- src/dbginfo/dbginfo.h | 1 + 2 files changed, 228 insertions(+), 11 deletions(-) diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index 88923c8fe..f0a902190 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -192,6 +192,7 @@ struct DbgInfo { Collection SegInfoById; /* Segment infos sorted by id */ Collection SpanInfoById; /* Span infos sorted by id */ Collection SymInfoById; /* Symbol infos sorted by id */ + Collection TypeInfoById; /* Type infos sorted by id */ /* Collections with other sort criteria */ Collection FileInfoByName; /* File infos sorted by name */ @@ -238,6 +239,7 @@ typedef struct ScopeInfo ScopeInfo; typedef struct SegInfo SegInfo; typedef struct SpanInfo SpanInfo; typedef struct SymInfo SymInfo; +typedef struct TypeInfo TypeInfo; /* Internally used file info struct */ struct FileInfo { @@ -327,6 +329,10 @@ struct SpanInfo { unsigned Id; /* Id of segment */ SegInfo* Info; /* Pointer to segment */ } Seg; + union { + unsigned Id; /* Id of type */ + TypeInfo* Info; /* Pointer to type */ + } Type; Collection* ScopeInfoList; /* Scopes for this span */ Collection* LineInfoList; /* Lines for this span */ }; @@ -360,6 +366,13 @@ struct SymInfo { char Name[1]; /* Name of symbol */ }; +/* Internally used type info struct */ +struct TypeInfo { + unsigned Id; /* Id of type */ + unsigned Length; /* Length of following data */ + unsigned char Data[1]; /* Data, dynamically allocated */ +}; + /*****************************************************************************/ @@ -1485,6 +1498,11 @@ static void CopySpanInfo (cc65_spandata* D, const SpanInfo* S) D->span_start = S->Start; D->span_end = S->End; D->segment_id = S->Seg.Info->Id; + if (S->Type.Info) { + D->type_id = S->Type.Info->Id; + } else { + D->type_id = CC65_INV_ID; + } if (S->ScopeInfoList) { D->scope_count = CollCount (S->ScopeInfoList); } else { @@ -1639,6 +1657,62 @@ static int CompareSymInfoByVal (const void* L, const void* R) +/*****************************************************************************/ +/* Type info */ +/*****************************************************************************/ + + + +static unsigned HexValue (char C) +/* Convert the ascii representation of a hex nibble into the hex nibble */ +{ + if (isdigit (C)) { + return C - '0'; + } else if (islower (C)) { + return C - 'a' + 10; + } else { + return C - 'A' + 10; + } +} + + + +static TypeInfo* NewTypeInfo (const StrBuf* ReadableValue) +/* Create a new TypeInfo struct, intialize and return it */ +{ + unsigned I; + const char* P; + + /* Calculate the length of the final data. Since we have hex encoding, it + * is half of the length of ReadableValue. + */ + unsigned Length = SB_GetLen (ReadableValue) / 2; + + /* Allocate memory */ + TypeInfo* T = xmalloc (sizeof (TypeInfo) + Length - 1); + + /* Initialize it as necessary */ + T->Length = Length; + P = SB_GetConstBuf (ReadableValue); + for (I = 0; I < Length; ++I) { + unsigned char V = (HexValue (*P++) << 4); + T->Data[I] = (V | HexValue (*P++)); + } + + /* Return it */ + return T; +} + + + +static void FreeTypeInfo (TypeInfo* T) +/* Free a TypeInfo struct */ +{ + xfree (T); +} + + + /*****************************************************************************/ /* SpanInfoList */ /*****************************************************************************/ @@ -1854,6 +1928,7 @@ static DbgInfo* NewDbgInfo (const char* FileName) CollInit (&Info->SegInfoById); CollInit (&Info->SpanInfoById); CollInit (&Info->SymInfoById); + CollInit (&Info->TypeInfoById); CollInit (&Info->FileInfoByName); CollInit (&Info->ModInfoByName); @@ -1905,6 +1980,9 @@ static void FreeDbgInfo (DbgInfo* Info) for (I = 0; I < CollCount (&Info->SymInfoById); ++I) { FreeSymInfo (CollAt (&Info->SymInfoById, I)); } + for (I = 0; I < CollCount (&Info->TypeInfoById); ++I) { + FreeTypeInfo (CollAt (&Info->TypeInfoById, I)); + } /* Free the memory used by the id collections */ CollDone (&Info->FileInfoById); @@ -1915,6 +1993,7 @@ static void FreeDbgInfo (DbgInfo* Info) CollDone (&Info->SegInfoById); CollDone (&Info->SpanInfoById); CollDone (&Info->SymInfoById); + CollDone (&Info->TypeInfoById); /* Free the memory used by the other collections */ CollDone (&Info->FileInfoByName); @@ -2471,7 +2550,8 @@ static void ParseInfo (InputData* D) if (D->Tok != TOK_FILE && D->Tok != TOK_LIBRARY && D->Tok != TOK_LINE && D->Tok != TOK_MODULE && D->Tok != TOK_SCOPE && D->Tok != TOK_SEGMENT && - D->Tok != TOK_SPAN && D->Tok != TOK_SYM) { + D->Tok != TOK_SPAN && D->Tok != TOK_SYM && + D->Tok != TOK_TYPE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { @@ -2536,6 +2616,10 @@ static void ParseInfo (InputData* D) CollGrow (&D->Info->SymInfoByVal, D->IVal); break; + case TOK_TYPE: + CollGrow (&D->Info->TypeInfoById, D->IVal); + break; + default: /* NOTREACHED */ UnexpectedToken (D); @@ -3351,7 +3435,7 @@ static void ParseSpan (InputData* D) cc65_addr Start = 0; cc65_addr Size = 0; unsigned SegId = CC65_INV_ID; - StrBuf Type = STRBUF_INITIALIZER; + unsigned TypeId = CC65_INV_ID; SpanInfo* S; enum { ibNone = 0x000, @@ -3434,13 +3518,12 @@ static void ParseSpan (InputData* D) break; case TOK_TYPE: - if (!StrConstFollows (D)) { + if (!IntConstFollows (D)) { goto ErrorExit; } - SB_Copy (&Type, &D->SVal); - SB_Terminate (&Type); - InfoBits |= ibType; + TypeId = D->IVal; NextToken (D); + InfoBits |= ibType; break; default: @@ -3472,15 +3555,15 @@ static void ParseSpan (InputData* D) /* Create the span info and remember it */ S = NewSpanInfo (); - S->Id = Id; - S->Seg.Id = SegId; - S->Start = Start; - S->End = Start + Size - 1; + S->Id = Id; + S->Start = Start; + S->End = Start + Size - 1; + S->Seg.Id = SegId; + S->Type.Id = TypeId; CollReplaceExpand (&D->Info->SpanInfoById, S, Id); ErrorExit: /* Entry point in case of errors */ - SB_Done (&Type); return; } @@ -3755,6 +3838,122 @@ ErrorExit: +static void ParseType (InputData* D) +/* Parse a TYPE line */ +{ + /* Most of the following variables are initialized with a value that is + * overwritten later. This is just to avoid compiler warnings. + */ + unsigned Id = CC65_INV_ID; + StrBuf Value = STRBUF_INITIALIZER; + + TypeInfo* T; + enum { + ibNone = 0x0000, + + ibId = 0x01, + ibValue = 0x02, + + ibRequired = ibId | ibValue, + } InfoBits = ibNone; + + /* Skip the SYM token */ + NextToken (D); + + /* More stuff follows */ + while (1) { + + Token Tok; + + /* Something we know? */ + if (D->Tok != TOK_ID && D->Tok != TOK_VALUE) { + + /* Try smart error recovery */ + if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { + UnknownKeyword (D); + continue; + } + + /* Done */ + break; + } + + /* Remember the token, skip it, check for equal */ + Tok = D->Tok; + NextToken (D); + if (!ConsumeEqual (D)) { + goto ErrorExit; + } + + /* Check what the token was */ + switch (Tok) { + + case TOK_ID: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + Id = D->IVal; + NextToken (D); + InfoBits |= ibId; + break; + + case TOK_VALUE: + if (!StrConstFollows (D)) { + goto ErrorExit; + } + SB_Copy (&Value, &D->SVal); + InfoBits |= ibValue; + NextToken (D); + break; + + default: + /* NOTREACHED */ + UnexpectedToken (D); + goto ErrorExit; + + } + + /* Comma or done */ + if (D->Tok != TOK_COMMA) { + break; + } + NextToken (D); + } + + /* Check for end of line */ + if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { + UnexpectedToken (D); + SkipLine (D); + goto ErrorExit; + } + + /* Check for required and/or matched information */ + if ((InfoBits & ibRequired) != ibRequired) { + ParseError (D, CC65_ERROR, "Required attributes missing"); + goto ErrorExit; + } + + /* Check Value */ + if (SB_GetLen (&Value) < 2 || (SB_GetLen (&Value) & 0x01) != 0) { + ParseError (D, CC65_ERROR, "Invalid type value"); + goto ErrorExit; + } + + /* Create the type info */ + T = NewTypeInfo (&Value); + T->Id = Id; + + /* Remember it */ + CollReplaceExpand (&D->Info->TypeInfoById, T, Id); + +ErrorExit: + /* Entry point in case of errors */ + SB_Done (&Value); + return; +} + + + static void ParseVersion (InputData* D) /* Parse a VERSION line */ { @@ -4458,6 +4657,19 @@ static void ProcessSpanInfo (InputData* D) S->End += S->Seg.Info->Start; } + /* Resolve the type if we have it */ + if (S->Type.Id == CC65_INV_ID) { + S->Type.Info = 0; + } else if (S->Type.Id >= CollCount (&D->Info->TypeInfoById)) { + ParseError (D, + CC65_ERROR, + "Invalid type id %u for span with id %u", + S->Type.Id, S->Id); + S->Type.Info = 0; + } else { + S->Type.Info = CollAt (&D->Info->TypeInfoById, S->Type.Id); + } + /* Append this span info to the temporary collection that is later * sorted by address. */ @@ -4772,6 +4984,10 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc) ParseSym (&D); break; + case TOK_TYPE: + ParseType (&D); + break; + case TOK_IDENT: /* Output a warning, then skip the line with the unknown * keyword that may have been added by a later version. diff --git a/src/dbginfo/dbginfo.h b/src/dbginfo/dbginfo.h index aa38e29a0..48d398299 100644 --- a/src/dbginfo/dbginfo.h +++ b/src/dbginfo/dbginfo.h @@ -270,6 +270,7 @@ struct cc65_spandata { cc65_addr span_start; /* Start of the span */ cc65_addr span_end; /* End of the span (inclusive!) */ unsigned segment_id; /* Id of the segment */ + unsigned type_id; /* Id of the type of this span */ unsigned line_count; /* Number of lines attached */ unsigned scope_count; /* Number of scopes attached */ }; -- 2.39.5