/* ar65 */
#include "error.h"
-#include "global.h"
-#include "fileio.h"
-#include "objdata.h"
#include "exports.h"
+#include "fileio.h"
+#include "global.h"
#include "library.h"
+#include "objdata.h"
+#include "objfile.h"
/* File descriptor for the library file */
-FILE* NewLib = 0;
-static FILE* Lib = 0;
+FILE* NewLib = 0;
+static FILE* Lib = 0;
static const char* LibName = 0;
/* The library header */
static void ReadIndexEntry (void)
/* Read one entry in the index */
{
- unsigned I;
-
/* Create a new entry and insert it into the list */
ObjData* O = NewObjData ();
/* Module name/flags/MTime/Start/Size */
- O->Name = ReadStr (Lib);
- O->Flags = Read16 (Lib);
+ O->Name = ReadStr (Lib);
+ O->Flags = Read16 (Lib);
O->MTime = Read32 (Lib);
O->Start = Read32 (Lib);
O->Size = Read32 (Lib);
-
- /* Strings */
- O->StringCount = ReadVar (Lib);
- O->Strings = xmalloc (O->StringCount * sizeof (char*));
- for (I = 0; I < O->StringCount; ++I) {
- O->Strings[I] = ReadStr (Lib);
- }
-
- /* Imports */
- O->ImportSize = ReadVar (Lib);
- O->Imports = xmalloc (O->ImportSize);
- ReadData (Lib, O->Imports, O->ImportSize);
-
- /* Exports */
- O->ExportSize = ReadVar (Lib);
- O->Exports = xmalloc (O->ExportSize);
- ReadData (Lib, O->Exports, O->ExportSize);
}
static void ReadIndex (void)
/* Read the index of a library file */
{
- unsigned Count;
+ unsigned Count, I;
/* Seek to the start of the index */
fseek (Lib, Header.IndexOffs, SEEK_SET);
/* Read all entries in the index */
while (Count--) {
- ReadIndexEntry ();
+ ReadIndexEntry ();
+ }
+
+ /* Read basic object file data from the actual entries */
+ for (I = 0; I < CollCount (&ObjPool); ++I) {
+
+ /* Get the object file entry */
+ ObjData* O = CollAtUnchecked (&ObjPool, I);
+
+ /* Read data */
+ ObjReadData (Lib, O);
}
}
/*****************************************************************************/
-/* Writing file data structures */
+/* Writing file data structures */
/*****************************************************************************/
static void WriteIndexEntry (const ObjData* O)
/* Write one index entry */
{
- unsigned I;
-
/* Module name/flags/MTime/start/size */
WriteStr (NewLib, O->Name);
Write16 (NewLib, O->Flags & ~OBJ_HAVEDATA);
Write32 (NewLib, O->MTime);
Write32 (NewLib, O->Start);
Write32 (NewLib, O->Size);
-
- /* Strings */
- WriteVar (NewLib, O->StringCount);
- for (I = 0; I < O->StringCount; ++I) {
- WriteStr (NewLib, O->Strings[I]);
- }
-
- /* Imports */
- WriteVar (NewLib, O->ImportSize);
- WriteData (NewLib, O->Imports, O->ImportSize);
-
- /* Exports */
- WriteVar (NewLib, O->ExportSize);
- WriteData (NewLib, O->Exports, O->ExportSize);
}
/*****************************************************************************/
-/* High level stuff */
+/* High level stuff */
/*****************************************************************************/
-static unsigned long GetVar (unsigned char** Buf)
-/* Get a variable sized value from Buf */
-{
- unsigned char C;
- unsigned long V = 0;
- unsigned Shift = 0;
- do {
- /* Read one byte */
- C = **Buf;
- ++(*Buf);
- /* Add this char to the value */
- V |= ((unsigned long)(C & 0x7F)) << Shift;
- /* Next value */
- Shift += 7;
- } while (C & 0x80);
-
- /* Return the result */
- return V;
-}
-
-
-
-static void SkipExpr (unsigned char** Buf)
-/* Skip an expression in Buf */
-{
- /* Get the operation and skip it */
- unsigned char Op = **Buf;
- ++(*Buf);
-
- /* Filter leaf nodes */
- switch (Op) {
-
- case EXPR_NULL:
- return;
-
- case EXPR_LITERAL:
- /* 32 bit literal value */
- *Buf += 4;
- return;
-
- case EXPR_SYMBOL:
- /* Variable seized symbol index */
- (void) GetVar (Buf);
- return;
-
- case EXPR_SECTION:
- /* 8 bit segment number */
- *Buf += 1;
- return;
- }
-
- /* What's left are unary and binary nodes */
- SkipExpr (Buf); /* Skip left */
- SkipExpr (Buf); /* Skip right */
-}
-
-
-
-static void SkipLineInfoList (unsigned char** Buf)
-/* Skip a list of line infos in Buf */
-{
- /* Number of indices preceeds the list */
- unsigned long Count = GetVar (Buf);
-
- /* Skip indices */
- while (Count--) {
- (void) GetVar (Buf);
- }
-}
-
-
-
static void LibCheckExports (ObjData* O)
/* Insert all exports from the given object file into the global list
* checking for duplicates.
*/
{
- /* Get a pointer to the buffer */
- unsigned char* Exports = O->Exports;
-
- /* Get the export count */
- unsigned Count = GetVar (&Exports);
-
- /* Read the exports */
- Print (stdout, 1, "Module `%s' (%u exports):\n", O->Name, Count);
- while (Count--) {
-
- const char* Name;
-
- /* Get the export tag and skip the address size */
- unsigned Type = GetVar (&Exports);
- ++Exports;
-
- /* condes decls may follow */
- Exports += SYM_GET_CONDES_COUNT (Type);
+ unsigned I;
- /* Next thing is index of name of symbol */
- Name = GetObjString (O, GetVar (&Exports));
+ /* Let the user know what we do */
+ Print (stdout, 1, "Module `%s' (%u exports):\n", O->Name, CollCount (&O->Exports));
- /* Skip value of symbol */
- if (SYM_IS_EXPR (Type)) {
- /* Expression tree */
- SkipExpr (&Exports);
- } else {
- /* Constant 32 bit value */
- Exports += 4;
- }
+ /* Insert the exports into the global table */
+ for (I = 0; I < CollCount (&O->Exports); ++I) {
- /* Skip the line info */
- SkipLineInfoList (&Exports);
+ /* Get the name of the export */
+ const char* Name = CollConstAt (&O->Exports, I);
/* Insert the name into the hash table */
Print (stdout, 1, " %s\n", Name);
*/
for (I = 0; I < CollCount (&ObjPool); ++I) {
- /* Get a pointer to the object */
- ObjData* O = CollAt (&ObjPool, I);
+ /* Get a pointer to the object */
+ ObjData* O = CollAtUnchecked (&ObjPool, I);
/* Check exports, make global export table */
LibCheckExports (O);
}
if (NewLib && fclose (NewLib) != 0) {
Error ("Problem closing temporary library file: %s", strerror (errno));
- }
+ }
}
/* common */
#include "coll.h"
+#include "objdefs.h"
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* Values for the Flags field */
-#define OBJ_HAVEDATA 0x0001 /* The object data is in the tmp file */
-#define OBJ_MARKED 0x0002 /* Generic marker bit */
+#define OBJ_HAVEDATA 0x0001 /* The object data is in the tmp file */
/* Internal structure holding object file data */
typedef struct ObjData ObjData;
struct ObjData {
char* Name; /* Module name */
+
+ /* Index entry */
unsigned Flags;
unsigned long MTime; /* Modifiation time of object file */
- unsigned long Start; /* Start offset of data in library */
- unsigned long Size; /* Size of data in library */
- unsigned StringCount; /* Number of strings */
- char** Strings; /* Strings from the object file */
- unsigned long ImportSize; /* Size of imports */
- void* Imports; /* Imports as raw data */
- unsigned long ExportSize; /* Size of exports */
- void* Exports; /* Exports as raw data */
+ unsigned long Start; /* Start offset of data in library */
+ unsigned long Size; /* Size of data in library */
+
+ /* Object file header */
+ ObjHeader Header;
+
+ /* Basic data needed for simple checks */
+ Collection Strings; /* Strings from the object file */
+ Collection Exports; /* Exports list from object file */
};
-/* Collection with object files */
+/* Collection with all object files */
extern Collection ObjPool;
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
void FreeObjData (ObjData* O);
/* Free a complete struct */
+void ClearObjData (ObjData* O);
+/* Remove any data stored in O */
+
ObjData* FindObjData (const char* Module);
/* Search for the module with the given name and return it. Return NULL if the
* module is not in the list.
void DelObjData (const char* Module);
/* Delete the object module from the list */
-const char* GetObjString (const ObjData* O, unsigned Index);
-/* Get a string from the string pool of an object file */
-
/* End of objdata.h */
#include <sys/stat.h>
/* common */
+#include "cddefs.h"
+#include "exprdefs.h"
#include "fname.h"
+#include "symdefs.h"
#include "xmalloc.h"
/* ar65 */
-void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
+static void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
/* Read the header of the object file checking the signature */
{
H->Magic = Read32 (Obj);
-void ObjWriteHeader (FILE* Obj, ObjHeader* H)
-/* Write the header of the object file */
+static void SkipExpr (FILE* F)
+/* Skip an expression in F */
{
- Write32 (Obj, H->Magic);
- Write16 (Obj, H->Version);
- Write16 (Obj, H->Flags);
- Write32 (Obj, H->OptionOffs);
- Write32 (Obj, H->OptionSize);
- Write32 (Obj, H->FileOffs);
- Write32 (Obj, H->FileSize);
- Write32 (Obj, H->SegOffs);
- Write32 (Obj, H->SegSize);
- Write32 (Obj, H->ImportOffs);
- Write32 (Obj, H->ImportSize);
- Write32 (Obj, H->ExportOffs);
- Write32 (Obj, H->ExportSize);
- Write32 (Obj, H->DbgSymOffs);
- Write32 (Obj, H->DbgSymSize);
- Write32 (Obj, H->LineInfoOffs);
- Write32 (Obj, H->LineInfoSize);
- Write32 (Obj, H->StrPoolOffs);
- Write32 (Obj, H->StrPoolSize);
- Write32 (Obj, H->AssertOffs);
- Write32 (Obj, H->AssertSize);
- Write32 (Obj, H->ScopeOffs);
- Write32 (Obj, H->ScopeSize);
+ /* Get the operation and skip it */
+ unsigned char Op = Read8 (F);
+
+ /* Handle then different expression nodes */
+ switch (Op) {
+
+ case EXPR_NULL:
+ break;
+
+ case EXPR_LITERAL:
+ /* 32 bit literal value */
+ (void) Read32 (F);
+ break;
+
+ case EXPR_SYMBOL:
+ /* Variable seized symbol index */
+ (void) ReadVar (F);
+ break;
+
+ case EXPR_SECTION:
+ /* 8 bit segment number */
+ (void) Read8 (F);
+ break;
+
+ default:
+ /* What's left are unary and binary nodes */
+ SkipExpr (F); /* Left */
+ SkipExpr (F); /* right */
+ break;
+ }
+}
+
+
+
+static void SkipLineInfoList (FILE* F)
+/* Skip a list of line infos in F */
+{
+ /* Number of indices preceeds the list */
+ unsigned long Count = ReadVar (F);
+
+ /* Skip indices */
+ while (Count--) {
+ (void) ReadVar (F);
+ }
+}
+
+
+
+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);
+ }
+
+ /* Line info indices */
+ SkipLineInfoList (F);
+ }
}
const char* Module;
ObjHeader H;
ObjData* O;
- unsigned I;
/* Open the object file */
FILE* Obj = fopen (Name, "rb");
if (difftime ((time_t)O->MTime, StatBuf.st_mtime) > 0.0) {
Warning ("Replacing module `%s' by older version", O->Name);
}
+
+ /* Free data */
+ ClearObjData (O);
}
/* Initialize the object module data structure */
- O->Name = xstrdup (Module);
- O->Flags = OBJ_HAVEDATA;
- O->MTime = StatBuf.st_mtime;
- O->ImportSize = H.ImportSize;
- O->Imports = xmalloc (O->ImportSize);
- O->ExportSize = H.ExportSize;
- O->Exports = xmalloc (O->ExportSize);
-
- /* Read imports and exports */
- fseek (Obj, H.ImportOffs, SEEK_SET);
- ReadData (Obj, O->Imports, O->ImportSize);
- fseek (Obj, H.ExportOffs, SEEK_SET);
- ReadData (Obj, O->Exports, O->ExportSize);
+ O->Name = xstrdup (Module);
+ O->Flags = OBJ_HAVEDATA;
+ O->MTime = StatBuf.st_mtime;
+ O->Start = 0;
- /* Read the string pool */
- fseek (Obj, H.StrPoolOffs, SEEK_SET);
- O->StringCount = ReadVar (Obj);
- O->Strings = xmalloc (O->StringCount * sizeof (char*));
- for (I = 0; I < O->StringCount; ++I) {
- O->Strings[I] = ReadStr (Obj);
- }
+ /* Determine the file size. Note: Race condition here */
+ fseek (Obj, 0, SEEK_END);
+ O->Size = ftell (Obj);
- /* Skip the object file header */
- O->Start = ftell (NewLib);
- fseek (NewLib, OBJ_HDR_SIZE, SEEK_CUR);
-
- /* Copy the remaining sections */
- fseek (Obj, H.DbgSymOffs, SEEK_SET);
- H.DbgSymOffs = LibCopyTo (Obj, H.DbgSymSize) - O->Start;
- fseek (Obj, H.OptionOffs, SEEK_SET);
- H.OptionOffs = LibCopyTo (Obj, H.OptionSize) - O->Start;
- fseek (Obj, H.SegOffs, SEEK_SET);
- H.SegOffs = LibCopyTo (Obj, H.SegSize) - O->Start;
- fseek (Obj, H.FileOffs, SEEK_SET);
- H.FileOffs = LibCopyTo (Obj, H.FileSize) - O->Start;
- fseek (Obj, H.LineInfoOffs, SEEK_SET);
- H.LineInfoOffs = LibCopyTo (Obj, H.LineInfoSize) - O->Start;
- fseek (Obj, H.AssertOffs, SEEK_SET);
- H.AssertOffs = LibCopyTo (Obj, H.AssertSize) - O->Start;
- fseek (Obj, H.ScopeOffs, SEEK_SET);
- H.ScopeOffs = LibCopyTo (Obj, H.ScopeSize) - O->Start;
-
- /* Calculate the amount of data written */
- O->Size = ftell (NewLib) - O->Start;
-
- /* Clear the remaining header fields */
- H.ImportOffs = H.ImportSize = 0;
- H.ExportOffs = H.ExportSize = 0;
- H.StrPoolOffs = H.StrPoolSize = 0;
-
- /* Seek back and write the updated header */
- fseek (NewLib, O->Start, SEEK_SET);
- ObjWriteHeader (NewLib, &H);
-
- /* Now seek again to end of file */
- fseek (NewLib, 0, SEEK_END);
+ /* 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 ObjExtract (const char* Name)
/* Extract a module from the library */
{
- unsigned long ImportStart;
- unsigned long ExportStart;
- unsigned long StrPoolStart;
- unsigned long StrPoolSize;
struct utimbuf U;
- ObjHeader H;
FILE* Obj;
- unsigned I;
/* Make a module name from the file name */
const char* Module = GetModule (Name);
/* Try to find the module in the library */
- ObjData* O = FindObjData (Module);
+ const ObjData* O = FindObjData (Module);
/* Bail out if the module does not exist */
if (O == 0) {
Error ("Cannot open target file `%s': %s", Name, strerror (errno));
}
- /* Copy anything to the new file that has no special handling */
+ /* Copy the complete object file data from the library to the new object
+ * file.
+ */
LibCopyFrom (O->Start, O->Size, Obj);
- /* Write imports and exports */
- ImportStart = ftell (Obj);
- WriteData (Obj, O->Imports, O->ImportSize);
- ExportStart = ftell (Obj);
- WriteData (Obj, O->Exports, O->ExportSize);
-
- /* Write the string pool */
- StrPoolStart = ftell (Obj);
- WriteVar (Obj, O->StringCount);
- for (I = 0; I < O->StringCount; ++I) {
- WriteStr (Obj, O->Strings[I]);
- }
- StrPoolSize = ftell (Obj) - StrPoolStart;
-
- /* Seek back and read the header */
- fseek (Obj, 0, SEEK_SET);
- ObjReadHeader (Obj, &H, Name);
-
- /* Update the header fields */
- H.ImportOffs = ImportStart;
- H.ImportSize = O->ImportSize;
- H.ExportOffs = ExportStart;
- H.ExportSize = O->ExportSize;
- H.StrPoolOffs = StrPoolStart;
- H.StrPoolSize = StrPoolSize;
-
- /* Write the changed header */
- fseek (Obj, 0, SEEK_SET);
- ObjWriteHeader (Obj, &H);
-
/* Close the file */
if (fclose (Obj) != 0) {
Error ("Problem closing object file `%s': %s", Name, strerror (errno));