From 5855137d8c4d7d3a70679df3fa04bd6a04bf1cee Mon Sep 17 00:00:00 2001 From: uz Date: Fri, 28 Jan 2011 15:42:32 +0000 Subject: [PATCH] Change how data is stored in the library. To simplify things, the index (=directory) entry is now shorter, and additional data necessary for checking in the archiver is not stored in the directory but read from the object file data in the library. git-svn-id: svn://svn.cc65.org/cc65/trunk@4944 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ar65/library.c | 183 ++++++-------------------------- src/ar65/objdata.c | 46 ++++---- src/ar65/objdata.h | 35 ++++--- src/ar65/objfile.c | 244 ++++++++++++++++++++++--------------------- src/ar65/objfile.h | 22 ++-- src/common/libdefs.h | 4 +- 6 files changed, 215 insertions(+), 319 deletions(-) diff --git a/src/ar65/library.c b/src/ar65/library.c index 4b03a4e1d..cffb85cd1 100644 --- a/src/ar65/library.c +++ b/src/ar65/library.c @@ -46,11 +46,12 @@ /* 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" @@ -61,8 +62,8 @@ /* 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 */ @@ -105,34 +106,15 @@ static void ReadHeader (void) 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); } @@ -140,7 +122,7 @@ static void ReadIndexEntry (void) 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); @@ -150,14 +132,24 @@ static void ReadIndex (void) /* 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 */ /*****************************************************************************/ @@ -180,28 +172,12 @@ static void WriteHeader (void) 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); } @@ -229,7 +205,7 @@ static void WriteIndex (void) /*****************************************************************************/ -/* High level stuff */ +/* High level stuff */ /*****************************************************************************/ @@ -321,116 +297,21 @@ void LibCopyFrom (unsigned long Pos, unsigned long Bytes, FILE* F) -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); @@ -458,8 +339,8 @@ void LibClose (void) */ 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); @@ -507,7 +388,7 @@ void LibClose (void) } if (NewLib && fclose (NewLib) != 0) { Error ("Problem closing temporary library file: %s", strerror (errno)); - } + } } diff --git a/src/ar65/objdata.c b/src/ar65/objdata.c index 5b53513aa..e6c8372b7 100644 --- a/src/ar65/objdata.c +++ b/src/ar65/objdata.c @@ -70,16 +70,14 @@ ObjData* NewObjData (void) /* Initialize the data */ O->Name = 0; + O->Flags = 0; O->MTime = 0; O->Start = 0; O->Size = 0; - O->StringCount = 0; - O->Strings = 0; - O->ImportSize = 0; - O->Imports = 0; - O->ExportSize = 0; - O->Exports = 0; + + O->Strings = EmptyCollection; + O->Exports = EmptyCollection; /* Add it to the list */ CollAppend (&ObjPool, O); @@ -96,17 +94,31 @@ void FreeObjData (ObjData* O) unsigned I; xfree (O->Name); - xfree (O->Imports); - xfree (O->Exports); - for (I = 0; I < O->StringCount; ++I) { - xfree (O->Strings[I]); + for (I = 0; I < CollCount (&O->Strings); ++I) { + xfree (CollAt (&O->Strings, I)); } - xfree (O->Strings); + DoneCollection (&O->Strings); + DoneCollection (&O->Exports); xfree (O); } +void ClearObjData (ObjData* O) +/* Remove any data stored in O */ +{ + unsigned I; + xfree (O->Name); + O->Name = 0; + for (I = 0; I < CollCount (&O->Strings); ++I) { + xfree (CollAt (&O->Strings, I)); + } + CollDeleteAll (&O->Strings); + CollDeleteAll (&O->Exports); +} + + + 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. @@ -157,15 +169,3 @@ void DelObjData (const char* Module) -const char* GetObjString (const ObjData* O, unsigned Index) -/* Get a string from the string pool of an object file */ -{ - if (Index >= O->StringCount) { - Error ("Invalid string index (%u) in module `%s'", - Index, O->Name); - } - return O->Strings[Index]; -} - - - diff --git a/src/ar65/objdata.h b/src/ar65/objdata.h index 499cf76ab..5d191339b 100644 --- a/src/ar65/objdata.h +++ b/src/ar65/objdata.h @@ -40,45 +40,48 @@ /* 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 */ /*****************************************************************************/ @@ -89,6 +92,9 @@ ObjData* NewObjData (void); 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. @@ -97,9 +103,6 @@ ObjData* FindObjData (const char* Module); 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 */ diff --git a/src/ar65/objfile.c b/src/ar65/objfile.c index 662834705..c8df70e59 100644 --- a/src/ar65/objfile.c +++ b/src/ar65/objfile.c @@ -46,7 +46,10 @@ #include /* common */ +#include "cddefs.h" +#include "exprdefs.h" #include "fname.h" +#include "symdefs.h" #include "xmalloc.h" /* ar65 */ @@ -81,7 +84,7 @@ static const char* GetModule (const char* Name) -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); @@ -117,32 +120,106 @@ void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name) -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); + } } @@ -154,7 +231,6 @@ void ObjAdd (const char* Name) const char* Module; ObjHeader H; ObjData* O; - unsigned I; /* Open the object file */ FILE* Obj = fopen (Name, "rb"); @@ -192,65 +268,29 @@ void ObjAdd (const char* Name) 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); @@ -261,20 +301,14 @@ void ObjAdd (const char* Name) 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) { @@ -287,39 +321,11 @@ void ObjExtract (const char* Name) 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)); diff --git a/src/ar65/objfile.h b/src/ar65/objfile.h index d4c62307c..a1db14e82 100644 --- a/src/ar65/objfile.h +++ b/src/ar65/objfile.h @@ -40,8 +40,15 @@ #include -/* common */ -#include "objdefs.h" + + +/*****************************************************************************/ +/* Forwards */ +/*****************************************************************************/ + + + +struct ObjData; @@ -51,11 +58,10 @@ -void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name); -/* Read the header of the object file checking the signature */ - -void ObjWriteHeader (FILE* Obj, ObjHeader* H); -/* Write the header of the object file */ +void ObjReadData (FILE* F, struct 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. + */ void ObjAdd (const char* Name); /* Add an object file to the library */ @@ -67,7 +73,7 @@ void ObjExtract (const char* Name); /* End of objfile.h */ -#endif +#endif diff --git a/src/common/libdefs.h b/src/common/libdefs.h index c7086cbbe..6324ff4fd 100644 --- a/src/common/libdefs.h +++ b/src/common/libdefs.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2010, Ullrich von Bassewitz */ +/* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -46,7 +46,7 @@ /* Defines for magic and version */ #define LIB_MAGIC 0x7A55616E -#define LIB_VERSION 0x000C +#define LIB_VERSION 0x000D /* Size of an library file header */ #define LIB_HDR_SIZE 12 -- 2.39.5