void ObjReadData (FILE* F, ObjData* O) /* Read object file data from the given file. The function expects the Name * and Start fields to be valid. Header and basic data are read. */ { unsigned long Count; /* Seek to the start of the object file data */ fseek (F, O->Start, SEEK_SET); /* Read the object file header */ ObjReadHeader (F, &O->Header, O->Name); /* Read the string pool */ fseek (F, O->Start + O->Header.StrPoolOffs, SEEK_SET); Count = ReadVar (F); CollGrow (&O->Strings, Count); while (Count--) { CollAppend (&O->Strings, ReadStr (F)); } /* Read the exports */ fseek (F, O->Start + O->Header.ExportOffs, SEEK_SET); Count = ReadVar (F); CollGrow (&O->Exports, Count); while (Count--) { unsigned char ConDes[CD_TYPE_COUNT]; /* Skip data until we get to the name */ unsigned Type = ReadVar (F); (void) Read8 (F); /* AddrSize */ ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type)); /* Now this is what we actually need: The name of the export */ CollAppend (&O->Exports, CollAt (&O->Strings, ReadVar (F))); /* Skip the export value */ if (SYM_IS_EXPR (Type)) { /* Expression tree */ SkipExpr (F); } else { /* Literal value */ (void) Read32 (F); } /* Skip the size if necessary */ if (SYM_HAS_SIZE (Type)) { (void) ReadVar (F); } /* Line info indices */ SkipLineInfoList (F); SkipLineInfoList (F); } }
void ObjAdd (const char* Name) /* Add an object file to the library */ { struct stat StatBuf; const char* Module; ObjHeader H; ObjData* O; /* Open the object file */ FILE* Obj = fopen (Name, "rb"); if (Obj == 0) { Error ("Could not open `%s': %s", Name, strerror (errno)); } /* Get the modification time of the object file. There a race condition * here, since we cannot use fileno() (non standard identifier in standard * header file), and therefore not fstat. When using stat with the * file name, there's a risk that the file was deleted and recreated * while it was open. Since mtime and size are only used to check * if a file has changed in the debugger, we will ignore this problem * here. */ if (FileStat (Name, &StatBuf) != 0) { Error ("Cannot stat object file `%s': %s", Name, strerror (errno)); } /* Read and check the header */ ObjReadHeader (Obj, &H, Name); /* Make a module name from the file name */ Module = GetModule (Name); /* Check if we already have a module with this name */ O = FindObjData (Module); if (O == 0) { /* Not found, create a new entry */ O = NewObjData (); } else { /* Found - check the file modification times of the internal copy * and the external one. */ if (difftime ((time_t)O->MTime, StatBuf.st_mtime) > 0.0) { Warning ("Replacing module `%s' by older version in library `%s'", O->Name, LibName); } /* Free data */ ClearObjData (O); } /* Initialize the object module data structure */ O->Name = xstrdup (Module); O->Flags = OBJ_HAVEDATA; O->MTime = StatBuf.st_mtime; O->Start = 0; /* Determine the file size. Note: Race condition here */ fseek (Obj, 0, SEEK_END); O->Size = ftell (Obj); /* Read the basic data from the object file */ ObjReadData (Obj, O); /* Copy the complete object data to the library file and update the * starting offset */ fseek (Obj, 0, SEEK_SET); O->Start = LibCopyTo (Obj, O->Size); /* Done, close the file (we read it only, so no error check) */ fclose (Obj); }
void ObjAdd (FILE* Obj, const char* Name) /* Add an object file to the module list */ { /* Create a new structure for the object file data */ ObjData* O = NewObjData (); /* The magic was already read and checked, so set it in the header */ O->Header.Magic = OBJ_MAGIC; /* Read and check the header */ ObjReadHeader (Obj, &O->Header, Name); /* Initialize the object module data structure */ O->Name = GetModule (Name); /* Read the string pool from the object file */ ObjReadStrPool (Obj, O->Header.StrPoolOffs, O); /* Read the files list from the object file */ ObjReadFiles (Obj, O->Header.FileOffs, O); /* Read the imports list from the object file */ ObjReadImports (Obj, O->Header.ImportOffs, O); /* Read the object file exports and insert them into the exports list */ ObjReadExports (Obj, O->Header.ExportOffs, O); /* Read the object debug symbols from the object file */ ObjReadDbgSyms (Obj, O->Header.DbgSymOffs, O); /* Read the line infos from the object file */ ObjReadLineInfos (Obj, O->Header.LineInfoOffs, O); /* Read the assertions from the object file */ ObjReadAssertions (Obj, O->Header.AssertOffs, O); /* Read the scope table from the object file */ ObjReadScopes (Obj, O->Header.ScopeOffs, O); /* Read the segment list from the object file. This must be last, since * the expressions stored in the code may reference segments or imported * symbols. */ ObjReadSections (Obj, O->Header.SegOffs, O); /* Mark this object file as needed */ O->Flags |= OBJ_REF; /* Done, close the file (we read it only, so no error check) */ fclose (Obj); /* Insert the imports and exports to the global lists */ InsertObjGlobals (O); /* Insert the object into the list of all used object files */ InsertObjData (O); /* All references to strings are now resolved, so we can delete the module * string pool. */ FreeObjStrings (O); }