void PrintImportMap (FILE* F) /* Print an import map to the given file */ { unsigned I; const Import* Imp; /* Loop over all exports */ for (I = 0; I < ExpCount; ++I) { /* Get the export */ const Export* Exp = ExpPool [I]; /* Print the symbol only if there are imports, or if a verbose map ** file is requested. */ if (VerboseMap || Exp->ImpCount > 0) { /* Print the export */ fprintf (F, "%s (%s):\n", GetString (Exp->Name), GetObjFileName (Exp->Obj)); /* Print all imports for this symbol */ Imp = Exp->ImpList; while (Imp) { /* Print the import. Beware: The import might be linker ** generated, in which case there is no object file and ** sometimes no line information. */ const LineInfo* LI = GetImportPos (Imp); if (LI) { fprintf (F, " %-25s %s(%u)\n", GetObjFileName (Imp->Obj), GetSourceName (LI), GetSourceLine (LI)); } else { fprintf (F, " %-25s\n", GetObjFileName (Imp->Obj)); } /* Next import */ Imp = Imp->Next; } } } fprintf (F, "\n"); }
Import* GenImport (const char* Name, unsigned char AddrSize) /* Generate a new import with the given name and address size and return it */ { /* Create a new import */ Import* I = NewImport (AddrSize, 0); /* Read the name */ I->Name = GetStringId (Name); /* Check the address size */ if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) { /* Beware: This function may be called in cases where the object file * is not read completely into memory. In this case, the file list is * invalid. Be sure not to access it in this case. */ if (ObjHasFiles (I->Obj)) { Error ("Invalid import size in for `%s', imported from %s(%lu): 0x%02X", GetString (I->Name), GetSourceFileName (I->Obj, I->Pos.Name), I->Pos.Line, I->AddrSize); } else { Error ("Invalid import size in for `%s', imported from %s: 0x%02X", GetString (I->Name), GetObjFileName (I->Obj), I->AddrSize); } } /* Return the new import */ return I; }
void PrintDbgModules (FILE* F) /* Output the modules to a debug info file */ { unsigned I; /* Output modules */ for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get this object file */ const ObjData* O = CollConstAt (&ObjDataList, I); /* The main source file is the one at index zero */ const FileInfo* Source = CollConstAt (&O->Files, 0); /* Output the module line */ fprintf (F, "mod\tid=%u,name=\"%s\",file=%u", I, GetObjFileName (O), Source->Id); /* Add library if any */ if (O->Lib != 0) { fprintf (F, ",lib=%u", GetLibId (O->Lib)); } /* Terminate the output line */ fputc ('\n', F); } }
static void DumpSection(IDiaSectionContrib *item) { DWORD sectionNo; DWORD offset; DWORD length; item->get_addressSection(§ionNo); item->get_addressOffset(&offset); item->get_length(&length); //DWORD compilandId; //item->get_compilandId(&compilandId); const char *sectionType = GetSectionType(item); const char *objFileName = GetObjFileName(item); if (g_compact) { // type | sectionNo | length | offset | objFileId int objFileId = InternString(objFileName); g_report.AppendFmt("%s|%d|%d|%d|%d\n", sectionType, sectionNo, length, offset, objFileId); } else { // type | sectionNo | length | offset | objFile g_report.AppendFmt("%s|%d|%d|%d|%s\n", sectionType, sectionNo, length, offset, objFileName); } }
struct Scope* GetObjScope (const ObjData* O, unsigned Id) /* Get a scope from an object file checking for a valid index */ { if (Id >= CollCount (&O->Scopes)) { Error ("Invalid scope index (%u) in module `%s'", Id, GetObjFileName (O)); } return CollAtUnchecked (&O->Scopes, Id); }
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 Export* GetObjExport (const ObjData* O, unsigned Id) /* Get an export from an object file checking for a valid index */ { if (Id >= CollCount (&O->Exports)) { Error ("Invalid export index (%u) in module `%s'", Id, GetObjFileName (O)); } return CollAtUnchecked (&O->Exports, Id); }
unsigned MakeGlobalStringId (const ObjData* O, unsigned Index) /* Convert a local string id into a global one and return it. */ { if (Index >= O->StringCount) { Error ("Invalid string index (%u) in module `%s'", Index, GetObjFileName (O)); } return O->Strings[Index]; }
void PrintImportMap (FILE* F) /* Print an import map to the given file */ { unsigned I; const Import* Imp; /* Loop over all exports */ for (I = 0; I < ExpCount; ++I) { /* Get the export */ const Export* Exp = ExpPool [I]; /* Print the symbol only if there are imports, or if a verbose map * file is requested. */ if (VerboseMap || Exp->ImpCount > 0) { /* Print the export */ fprintf (F, "%s (%s):\n", GetString (Exp->Name), GetObjFileName (Exp->Obj)); /* Print all imports for this symbol */ Imp = Exp->ImpList; while (Imp) { /* Print the import */ fprintf (F, " %-25s %s(%lu)\n", GetObjFileName (Imp->Obj), GetSourceFileName (Imp->Obj, Imp->Pos.Name), Imp->Pos.Line); /* Next import */ Imp = Imp->Next; } } } fprintf (F, "\n"); }
static void CheckSymType (const Export* E) /* Check the types for one export */ { /* External with matching imports */ Import* Imp = E->ImpList; while (Imp) { if (E->AddrSize != Imp->AddrSize) { /* Export is ZP, import is abs or the other way round */ const char* ExpAddrSize = AddrSizeToStr (E->AddrSize); const char* ImpAddrSize = AddrSizeToStr (Imp->AddrSize); const char* ExpObjName = GetObjFileName (E->Obj); const char* ImpObjName = GetObjFileName (Imp->Obj); if (E->Obj) { /* User defined export */ Warning ("Address size mismatch for `%s': Exported from %s, " "%s(%lu) as `%s', import in %s, %s(%lu) as `%s'", GetString (E->Name), ExpObjName, GetSourceFileName (E->Obj, E->Pos.Name), E->Pos.Line, ExpAddrSize, ImpObjName, GetSourceFileName (Imp->Obj, Imp->Pos.Name), Imp->Pos.Line, ImpAddrSize); } else { /* Export created by the linker */ Warning ("Address size mismatch for `%s': Symbol is `%s'" ", but imported from %s, %s(%lu) as `%s'", GetString (E->Name), ExpAddrSize, ImpObjName, GetSourceFileName (Imp->Obj, Imp->Pos.Name), Imp->Pos.Line, ImpAddrSize); } } Imp = Imp->Next; } }
Import* ReadImport (FILE* F, ObjData* Obj) /* Read an import from a file and return it */ { Import* I; /* Read the import address size */ unsigned char AddrSize = Read8 (F); /* Create a new import */ I = NewImport (AddrSize, Obj); /* Read the name */ I->Name = MakeGlobalStringId (Obj, ReadVar (F)); /* Read the line infos */ 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) { /* Beware: This function may be called in cases where the object file ** is not read completely into memory. In this case, the file list is ** invalid. Be sure not to access it in this case. */ if (ObjHasFiles (I->Obj)) { const LineInfo* LI = GetImportPos (I); Error ("Invalid import size in for `%s', imported from %s(%u): 0x%02X", GetString (I->Name), GetSourceName (LI), GetSourceLine (LI), I->AddrSize); } else { Error ("Invalid import size in for `%s', imported from %s: 0x%02X", GetString (I->Name), GetObjFileName (I->Obj), I->AddrSize); } } /* Return the new import */ return I; }
static void CheckSymType (const Export* E) /* Check the types for one export */ { /* External with matching imports */ Import* I = E->ImpList; while (I) { if (E->AddrSize != I->AddrSize) { /* Export and import address sizes do not match */ StrBuf ExportLoc = STATIC_STRBUF_INITIALIZER; StrBuf ImportLoc = STATIC_STRBUF_INITIALIZER; const char* ExpAddrSize = AddrSizeToStr ((unsigned char) E->AddrSize); const char* ImpAddrSize = AddrSizeToStr ((unsigned char) I->AddrSize); const LineInfo* ExportLI = GetExportPos (E); const LineInfo* ImportLI = GetImportPos (I); /* Generate strings that describe the location of the im- and ** exports. This depends on the place from where they come: ** Object file or linker config. */ if (E->Obj) { /* The export comes from an object file */ SB_Printf (&ExportLoc, "%s, %s(%u)", GetString (E->Obj->Name), GetSourceName (ExportLI), GetSourceLine (ExportLI)); } else { SB_Printf (&ExportLoc, "%s(%u)", GetSourceName (ExportLI), GetSourceLine (ExportLI)); } if (I->Obj) { /* The import comes from an object file */ SB_Printf (&ImportLoc, "%s, %s(%u)", GetString (I->Obj->Name), GetSourceName (ImportLI), GetSourceLine (ImportLI)); } else if (ImportLI) { /* The import is linker generated and we have line ** information */ SB_Printf (&ImportLoc, "%s(%u)", GetSourceName (ImportLI), GetSourceLine (ImportLI)); } else { /* The import is linker generated and we don't have line ** information */ SB_Printf (&ImportLoc, "%s", GetObjFileName (I->Obj)); } /* Output the diagnostic */ Warning ("Address size mismatch for `%s': " "Exported from %s as `%s', " "import in %s as `%s'", GetString (E->Name), SB_GetConstBuf (&ExportLoc), ExpAddrSize, SB_GetConstBuf (&ImportLoc), ImpAddrSize); /* Free the temporary strings */ SB_Done (&ExportLoc); SB_Done (&ImportLoc); } I = I->Next; } }
void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) /* Write the data from the given segment to a file. For expressions, F is ** called (see description of SegWriteFunc above). */ { unsigned I; int Sign; unsigned long Offs = 0; /* Remember the output file and offset for the segment */ S->OutputName = TgtName; S->OutputOffs = (unsigned long) ftell (Tgt); /* Loop over all sections in this segment */ for (I = 0; I < CollCount (&S->Sections); ++I) { Section* Sec = CollAtUnchecked (&S->Sections, I); Fragment* Frag; unsigned char FillVal; /* Output were this section is from */ Print (stdout, 2, " Section from \"%s\"\n", GetObjFileName (Sec->Obj)); /* If we have fill bytes, write them now. Beware: If this is the ** first section, the fill value is not considered part of the segment ** and therefore taken from the memory area. */ FillVal = (I == 0)? S->MemArea->FillVal : S->FillVal; Print (stdout, 2, " Filling 0x%lx bytes with 0x%02x\n", Sec->Fill, FillVal); WriteMult (Tgt, FillVal, Sec->Fill); Offs += Sec->Fill; /* Loop over all fragments in this section */ Frag = Sec->FragRoot; while (Frag) { /* Output fragment data */ switch (Frag->Type) { case FRAG_LITERAL: WriteData (Tgt, Frag->LitBuf, Frag->Size); break; case FRAG_EXPR: case FRAG_SEXPR: Sign = (Frag->Type == FRAG_SEXPR); /* Call the users function and evaluate the result */ switch (F (Frag->Expr, Sign, Frag->Size, Offs, Data)) { case SEG_EXPR_OK: break; case SEG_EXPR_RANGE_ERROR: Error ("Range error in module '%s', line %u", GetFragmentSourceName (Frag), GetFragmentSourceLine (Frag)); break; case SEG_EXPR_TOO_COMPLEX: Error ("Expression too complex in module '%s', line %u", GetFragmentSourceName (Frag), GetFragmentSourceLine (Frag)); break; case SEG_EXPR_INVALID: Error ("Invalid expression in module '%s', line %u", GetFragmentSourceName (Frag), GetFragmentSourceLine (Frag)); break; default: Internal ("Invalid return code from SegWriteFunc"); } break; case FRAG_FILL: WriteMult (Tgt, S->FillVal, Frag->Size); break; default: Internal ("Invalid fragment type: %02X", Frag->Type); } /* Update the offset */ Print (stdout, 2, " Fragment with 0x%x bytes\n", Frag->Size); Offs += Frag->Size; /* Next fragment */ Frag = Frag->Next; } } }
Section* ReadSection (FILE* F, ObjData* O) /* Read a section from a file */ { unsigned Name; unsigned Size; unsigned long Alignment; unsigned char Type; unsigned FragCount; Segment* S; Section* Sec; /* Read the segment data */ (void) Read32 (F); /* File size of data */ Name = MakeGlobalStringId (O, ReadVar (F)); /* Segment name */ ReadVar (F); /* Segment flags (currently unused) */ Size = ReadVar (F); /* Size of data */ Alignment = ReadVar (F); /* Alignment */ Type = Read8 (F); /* Segment type */ FragCount = ReadVar (F); /* Number of fragments */ /* Print some data */ Print (stdout, 2, "Module '%s': Found segment '%s', size = %u, alignment = %lu, type = %u\n", GetObjFileName (O), GetString (Name), Size, Alignment, Type); /* Get the segment for this section */ S = GetSegment (Name, Type, GetObjFileName (O)); /* Allocate the section we will return later */ Sec = NewSection (S, Alignment, Type); /* Remember the object file this section was from */ Sec->Obj = O; /* Set up the combined segment alignment */ if (Sec->Alignment > 1) { Alignment = LeastCommonMultiple (S->Alignment, Sec->Alignment); if (Alignment > MAX_ALIGNMENT) { Error ("Combined alignment for segment '%s' is %lu which exceeds " "%lu. Last module requiring alignment was '%s'.", GetString (Name), Alignment, MAX_ALIGNMENT, GetObjFileName (O)); } else if (Alignment >= LARGE_ALIGNMENT) { Warning ("Combined alignment for segment '%s' is suspiciously " "large (%lu). Last module requiring alignment was '%s'.", GetString (Name), Alignment, GetObjFileName (O)); } S->Alignment = Alignment; } /* Start reading fragments from the file and insert them into the section . */ while (FragCount--) { Fragment* Frag; /* Read the fragment type */ unsigned char Type = Read8 (F); /* Extract the check mask from the type */ unsigned char Bytes = Type & FRAG_BYTEMASK; Type &= FRAG_TYPEMASK; /* Handle the different fragment types */ switch (Type) { case FRAG_LITERAL: Frag = NewFragment (Type, ReadVar (F), Sec); ReadData (F, Frag->LitBuf, Frag->Size); break; case FRAG_EXPR: case FRAG_SEXPR: Frag = NewFragment (Type, Bytes, Sec); Frag->Expr = ReadExpr (F, O); break; case FRAG_FILL: /* Will allocate memory, but we don't care... */ Frag = NewFragment (Type, ReadVar (F), Sec); break; default: Error ("Unknown fragment type in module '%s', segment '%s': %02X", GetObjFileName (O), GetString (S->Name), Type); /* NOTREACHED */ return 0; } /* Read the line infos into the list of the fragment */ ReadLineInfoList (F, O, &Frag->LineInfos); /* Remember the module we had this fragment from */ Frag->Obj = O; } /* Return the section */ return Sec; }