unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal) /* Return a set of flags used when writing symbol information into a file. ** If the SYM_CONST bit is set, ConstVal will contain the constant value ** of the symbol. The result does not include the condes count. ** See common/symdefs.h for more information. */ { /* Setup info flags */ unsigned Flags = 0; Flags |= SymIsConst (S, ConstVal)? SYM_CONST : SYM_EXPR; Flags |= (S->Flags & SF_LABEL)? SYM_LABEL : SYM_EQUATE; Flags |= (S->Flags & SF_LOCAL)? SYM_CHEAP_LOCAL : SYM_STD; if (S->Flags & SF_EXPORT) { Flags |= SYM_EXPORT; } if (S->Flags & SF_IMPORT) { Flags |= SYM_IMPORT; } /* Return the result */ return Flags; }
void WriteScopes (void) /* Write the scope table to the object file */ { /* Tell the object file module that we're about to start the scopes */ ObjStartScopes (); /* We will write scopes only if debug symbols are requested */ if (DbgSyms) { /* Get head of list */ SymTable* S = RootScope; /* Write the scope count to the file */ ObjWriteVar (ScopeCount); /* Walk through all scopes and write them to the file */ while (S) { /* Flags for this scope */ unsigned Flags = 0; /* Check if this scope has a size. If so, remember it in the ** flags. */ long Size; SymEntry* SizeSym = FindSizeOfScope (S); if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) { Flags |= SCOPE_SIZE; } /* Check if the scope has a label */ if (S->Label) { Flags |= SCOPE_LABELED; } /* Scope must be defined */ CHECK (S->Type != SCOPE_UNDEF); /* Id of parent scope */ if (S->Parent) { ObjWriteVar (S->Parent->Id); } else { ObjWriteVar (0); } /* Lexical level */ ObjWriteVar (S->Level); /* Scope flags */ ObjWriteVar (Flags); /* Type of scope */ ObjWriteVar (S->Type); /* Name of the scope */ ObjWriteVar (S->Name); /* If the scope has a size, write it to the file */ if (SCOPE_HAS_SIZE (Flags)) { ObjWriteVar (Size); } /* If the scope has a label, write its id to the file */ if (SCOPE_HAS_LABEL (Flags)) { ObjWriteVar (S->Label->DebugSymId); } /* Spans for this scope */ WriteSpanList (&S->Spans); /* Next scope */ S = S->Next; } } else { /* No debug info requested */ ObjWriteVar (0); } /* Done writing the scopes */ ObjEndScopes (); }
void WriteDbgSyms (void) /* Write a list of all symbols to the object file */ { unsigned Count; SymEntry* S; /* Tell the object file module that we're about to start the debug info */ ObjStartDbgSyms (); /* Check if debug info is requested */ if (DbgSyms) { /* Walk through the list, give each symbol an id and count them */ Count = 0; S = SymList; while (S) { if (IsDbgSym (S)) { S->DebugSymId = Count++; } S = S->List; } /* Write the symbol count to the list */ ObjWriteVar (Count); /* Walk through list and write all symbols to the file. Ignore size ** symbols. */ S = SymList; while (S) { if (IsDbgSym (S)) { /* Get the expression bits and the value */ long ConstVal; unsigned SymFlags = GetSymInfoFlags (S, &ConstVal); /* Check if this symbol has a size. If so, remember it in the ** flags. */ long Size; SymEntry* SizeSym = FindSizeOfSymbol (S); if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) { SymFlags |= SYM_SIZE; } /* Write the type */ ObjWriteVar (SymFlags); /* Write the address size */ ObjWrite8 (S->AddrSize); /* Write the id of the parent. For normal symbols, this is a ** scope (symbol table), for cheap locals, it's a symbol. */ if (SYM_IS_STD (SymFlags)) { ObjWriteVar (S->Sym.Tab->Id); } else { ObjWriteVar (S->Sym.Entry->DebugSymId); } /* Write the name */ ObjWriteVar (S->Name); /* Write the value */ if (SYM_IS_CONST (SymFlags)) { /* Constant value */ ObjWrite32 (ConstVal); } else { /* Expression involved */ WriteExpr (S->Expr); } /* If the symbol has a size, write it to the file */ if (SYM_HAS_SIZE (SymFlags)) { ObjWriteVar (Size); } /* If the symbol is an im- or export, write out the ids */ if (SYM_IS_IMPORT (SymFlags)) { ObjWriteVar (GetSymImportId (S)); } if (SYM_IS_EXPORT (SymFlags)) { ObjWriteVar (GetSymExportId (S)); } /* Write the line infos */ WriteLineInfo (&S->DefLines); WriteLineInfo (&S->RefLines); } S = S->List; } } else { /* No debug symbols */ ObjWriteVar (0); } /* Write the high level symbols */ WriteHLLDbgSyms (); /* Done writing debug symbols */ ObjEndDbgSyms (); }
void WriteExports (void) /* Write the exports list to the object file */ { SymEntry* S; unsigned Type; /* Tell the object file module that we're about to start the exports */ ObjStartExports (); /* Write the export count to the list */ ObjWriteVar (ExportCount); /* Walk throught list and write all exports to the file */ S = SymList; while (S) { if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) { /* Get the expression bits and the value */ long ConstVal; unsigned SymFlags = GetSymInfoFlags (S, &ConstVal); /* Check if this symbol has a size. If so, remember it in the ** flags. */ long Size; SymEntry* SizeSym = FindSizeOfSymbol (S); if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) { SymFlags |= SYM_SIZE; } /* Count the number of ConDes types */ for (Type = 0; Type < CD_TYPE_COUNT; ++Type) { if (S->ConDesPrio[Type] != CD_PRIO_NONE) { SYM_INC_CONDES_COUNT (SymFlags); } } /* Write the type and the export size */ ObjWriteVar (SymFlags); ObjWrite8 (S->ExportSize); /* Write any ConDes declarations */ if (SYM_GET_CONDES_COUNT (SymFlags) > 0) { for (Type = 0; Type < CD_TYPE_COUNT; ++Type) { unsigned char Prio = S->ConDesPrio[Type]; if (Prio != CD_PRIO_NONE) { ObjWrite8 (CD_BUILD (Type, Prio)); } } } /* Write the name */ ObjWriteVar (S->Name); /* Write the value */ if (SYM_IS_CONST (SymFlags)) { /* Constant value */ ObjWrite32 (ConstVal); } else { /* Expression involved */ WriteExpr (S->Expr); } /* If the symbol has a size, write it to the file */ if (SYM_HAS_SIZE (SymFlags)) { ObjWriteVar (Size); } /* Write the line infos */ WriteLineInfo (&S->DefLines); WriteLineInfo (&S->RefLines); } S = S->List; } /* Done writing exports */ ObjEndExports (); }
static long DoStructInternal (long Offs, unsigned Type) /* Handle the .STRUCT command */ { long Size = 0; /* Outside of other structs, we need a name. Inside another struct or ** union, the struct may be anonymous, in which case no new lexical level ** is started. */ int Anon = (CurTok.Tok != TOK_IDENT); if (!Anon) { /* Enter a new scope, then skip the name */ SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0); NextTok (); /* Start at zero offset in the new scope */ Offs = 0; } /* Test for end of line */ ConsumeSep (); /* Read until end of struct */ while (CurTok.Tok != TOK_ENDSTRUCT && CurTok.Tok != TOK_ENDUNION && CurTok.Tok != TOK_EOF) { long MemberSize; SymTable* Struct; SymEntry* Sym; /* Allow empty and comment lines */ if (CurTok.Tok == TOK_SEP) { NextTok (); continue; } /* The format is "[identifier] storage-allocator [, multiplicator]" */ Sym = 0; if (CurTok.Tok == TOK_IDENT) { /* Beware: An identifier may also be a macro, in which case we have ** to start over. */ Macro* M = FindMacro (&CurTok.SVal); if (M) { MacExpandStart (M); continue; } /* We have an identifier, generate a symbol */ Sym = SymFind (CurrentScope, &CurTok.SVal, SYM_ALLOC_NEW); /* Assign the symbol the offset of the current member */ SymDef (Sym, GenLiteralExpr (Offs), ADDR_SIZE_DEFAULT, SF_NONE); /* Skip the member name */ NextTok (); } /* Read storage allocators */ MemberSize = 0; /* In case of errors, use zero */ switch (CurTok.Tok) { case TOK_BYTE: NextTok (); MemberSize = Member (1); break; case TOK_DBYT: case TOK_WORD: case TOK_ADDR: NextTok (); MemberSize = Member (2); break; case TOK_FARADDR: NextTok (); MemberSize = Member (3); break; case TOK_DWORD: NextTok (); MemberSize = Member (4); break; case TOK_RES: NextTok (); if (CurTok.Tok == TOK_SEP) { ErrorSkip ("Size is missing"); } else { MemberSize = Member (1); } break; case TOK_TAG: NextTok (); Struct = ParseScopedSymTable (); if (Struct == 0) { ErrorSkip ("Unknown struct/union"); } else if (GetSymTabType (Struct) != SCOPE_STRUCT) { ErrorSkip ("Not a struct/union"); } else { SymEntry* SizeSym = GetSizeOfScope (Struct); if (!SymIsDef (SizeSym) || !SymIsConst (SizeSym, &MemberSize)) { ErrorSkip ("Size of struct/union is unknown"); } } MemberSize = Member (MemberSize); break; case TOK_STRUCT: NextTok (); MemberSize = DoStructInternal (Offs, STRUCT); break; case TOK_UNION: NextTok (); MemberSize = DoStructInternal (Offs, UNION); break; default: if (!CheckConditionals ()) { /* Not a conditional directive */ ErrorSkip ("Invalid storage allocator in struct/union"); } } /* Assign the size to the member if it has a name */ if (Sym) { DefSizeOfSymbol (Sym, MemberSize); } /* Next member */ if (Type == STRUCT) { /* Struct */ Offs += MemberSize; Size += MemberSize; } else { /* Union */ if (MemberSize > Size) { Size = MemberSize; } } /* Expect end of line */ ConsumeSep (); } /* If this is not a anon struct, enter a special symbol named ".size" ** into the symbol table of the struct that holds the size of the ** struct. Since the symbol starts with a dot, it cannot be accessed ** by user code. ** Leave the struct scope level. */ if (!Anon) { /* Add a symbol */ SymEntry* SizeSym = GetSizeOfScope (CurrentScope); SymDef (SizeSym, GenLiteralExpr (Size), ADDR_SIZE_DEFAULT, SF_NONE); /* Close the struct scope */ SymLeaveLevel (); } /* End of struct/union definition */ if (Type == STRUCT) { Consume (TOK_ENDSTRUCT, "'.ENDSTRUCT' expected"); } else { Consume (TOK_ENDUNION, "'.ENDUNION' expected"); } /* Return the size of the struct */ return Size; }