1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-11 11:30:13 +00:00

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
This commit is contained in:
uz 2011-01-28 15:42:32 +00:00
parent 8386b47074
commit 5855137d8c
6 changed files with 214 additions and 318 deletions

View File

@ -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;
unsigned I;
/* Get the export count */
unsigned Count = GetVar (&Exports);
/* Let the user know what we do */
Print (stdout, 1, "Module `%s' (%u exports):\n", O->Name, CollCount (&O->Exports));
/* Read the exports */
Print (stdout, 1, "Module `%s' (%u exports):\n", O->Name, Count);
while (Count--) {
/* Insert the exports into the global table */
for (I = 0; I < CollCount (&O->Exports); ++I) {
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);
/* Next thing is index of name of symbol */
Name = GetObjString (O, GetVar (&Exports));
/* Skip value of symbol */
if (SYM_IS_EXPR (Type)) {
/* Expression tree */
SkipExpr (&Exports);
} else {
/* Constant 32 bit value */
Exports += 4;
}
/* 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));
}
}
}

View File

@ -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];
}

View File

@ -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 */

View File

@ -46,7 +46,10 @@
#include <sys/stat.h>
/* 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);
O->Name = xstrdup (Module);
O->Flags = OBJ_HAVEDATA;
O->MTime = StatBuf.st_mtime;
O->Start = 0;
/* 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);
/* Determine the file size. Note: Race condition here */
fseek (Obj, 0, SEEK_END);
O->Size = ftell (Obj);
/* 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);
}
/* Read the basic data from the object file */
ObjReadData (Obj, O);
/* 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);
/* 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));

View File

@ -40,8 +40,15 @@
#include <stdio.h>
/* 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

View File

@ -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