Export* ReadExport (FILE* F, ObjData* O) /* Read an export from a file */ { unsigned ConDesCount; Export* E; /* Read the type */ unsigned char Type = Read8 (F); /* Read the address size */ unsigned char AddrSize = Read8 (F); /* Create a new export without a name */ E = NewExport (Type, AddrSize, INVALID_STRING_ID, O); /* Read the constructor/destructor decls if we have any */ ConDesCount = GET_EXP_CONDES_COUNT (Type); if (ConDesCount > 0) { unsigned char ConDes[CD_TYPE_COUNT]; unsigned I; /* Read the data into temp storage */ ReadData (F, ConDes, ConDesCount); /* Re-order the data. In the file, each decl is encoded into a byte * which contains the type and the priority. In memory, we will use * an array of types which contain the priority. This array was * cleared by the constructor (NewExport), so we must only set the * fields that contain values. */ for (I = 0; I < ConDesCount; ++I) { unsigned ConDesType = CD_GET_TYPE (ConDes[I]); unsigned ConDesPrio = CD_GET_PRIO (ConDes[I]); E->ConDes[ConDesType] = ConDesPrio; } } /* Read the name */ E->Name = MakeGlobalStringId (O, ReadVar (F)); /* Read the value */ if (IS_EXP_EXPR (Type)) { E->Expr = ReadExpr (F, O); } else { E->Expr = LiteralExpr (Read32 (F), O); } /* Last is the file position where the definition was done */ ReadFilePos (F, &E->Pos); /* Return the new export */ return E; }
FileInfo* ReadFileInfo (FILE* F, ObjData* O) /* Read a file info from a file and return it */ { /* Allocate a new FileInfo structure */ FileInfo* FI = NewFileInfo (); /* Read the fields from the file */ FI->Name = MakeGlobalStringId (O, ReadVar (F)); FI->MTime = Read32 (F); FI->Size = Read32 (F); /* Return the new struct */ return FI; }
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; }
Assertion* ReadAssertion (FILE* F, struct ObjData* O) /* Read an assertion from the given file */ { /* Allocate memory */ Assertion* A = xmalloc (sizeof (Assertion)); /* Read the fields from the file */ A->LineInfos = EmptyCollection; A->Expr = ReadExpr (F, O); A->Action = (AssertAction) ReadVar (F); A->Msg = MakeGlobalStringId (O, ReadVar (F)); ReadLineInfoList (F, O, &A->LineInfos); /* Set remaining fields */ A->Obj = O; /* Add the assertion to the global list */ CollAppend (&Assertions, A); /* Return the new struct */ return A; }
Export* ReadExport (FILE* F, ObjData* O) /* Read an export from a file */ { unsigned ConDesCount; unsigned I; Export* E; /* Read the type */ unsigned Type = ReadVar (F); /* Read the address size */ unsigned char AddrSize = Read8 (F); /* Create a new export without a name */ E = NewExport (Type, AddrSize, INVALID_STRING_ID, O); /* Read the constructor/destructor decls if we have any */ ConDesCount = SYM_GET_CONDES_COUNT (Type); if (ConDesCount > 0) { unsigned char ConDes[CD_TYPE_COUNT]; /* Read the data into temp storage */ ReadData (F, ConDes, ConDesCount); /* Re-order the data. In the file, each decl is encoded into a byte ** which contains the type and the priority. In memory, we will use ** an array of types which contain the priority. */ for (I = 0; I < ConDesCount; ++I) { E->ConDes[CD_GET_TYPE (ConDes[I])] = CD_GET_PRIO (ConDes[I]); } } /* Read the name */ E->Name = MakeGlobalStringId (O, ReadVar (F)); /* Read the value */ if (SYM_IS_EXPR (Type)) { E->Expr = ReadExpr (F, O); } else { E->Expr = LiteralExpr (Read32 (F), O); } /* Read the size */ if (SYM_HAS_SIZE (Type)) { E->Size = ReadVar (F); } /* Last are the locations */ ReadLineInfoList (F, O, &E->DefLines); ReadLineInfoList (F, O, &E->RefLines); /* If this symbol is exported as a condes, and the condes type declares a ** forced import, add this import to the object module. */ for (I = 0; I < CD_TYPE_COUNT; ++I) { const ConDesImport* CDI; if (E->ConDes[I] != CD_PRIO_NONE && (CDI = ConDesGetImport (I)) != 0) { unsigned J; /* Generate a new import, and add it to the module's import list. */ Import* Imp = GenImport (CDI->Name, CDI->AddrSize); Imp->Obj = O; CollAppend (&O->Imports, Imp); /* Add line info for the export that is actually the condes that ** forces the import. Then, add line info for the config. file. ** The export's info is added first because the import pretends ** that it came from the object module instead of the config. file. */ for (J = 0; J < CollCount (&E->DefLines); ++J) { CollAppend (&Imp->RefLines, DupLineInfo (CollAt (&E->DefLines, J))); } CollAppend (&Imp->RefLines, GenLineInfo (&CDI->Pos)); } } /* Return the new export */ return E; }
const struct StrBuf* GetObjString (const ObjData* Obj, unsigned Id) /* Get a string from an object file checking for an invalid index */ { return GetStrBuf (MakeGlobalStringId (Obj, Id)); }
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; }