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:
@@ -46,11 +46,12 @@
|
|||||||
|
|
||||||
/* ar65 */
|
/* ar65 */
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "global.h"
|
|
||||||
#include "fileio.h"
|
|
||||||
#include "objdata.h"
|
|
||||||
#include "exports.h"
|
#include "exports.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "global.h"
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
|
#include "objdata.h"
|
||||||
|
#include "objfile.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -105,8 +106,6 @@ static void ReadHeader (void)
|
|||||||
static void ReadIndexEntry (void)
|
static void ReadIndexEntry (void)
|
||||||
/* Read one entry in the index */
|
/* Read one entry in the index */
|
||||||
{
|
{
|
||||||
unsigned I;
|
|
||||||
|
|
||||||
/* Create a new entry and insert it into the list */
|
/* Create a new entry and insert it into the list */
|
||||||
ObjData* O = NewObjData ();
|
ObjData* O = NewObjData ();
|
||||||
|
|
||||||
@@ -116,23 +115,6 @@ static void ReadIndexEntry (void)
|
|||||||
O->MTime = Read32 (Lib);
|
O->MTime = Read32 (Lib);
|
||||||
O->Start = Read32 (Lib);
|
O->Start = Read32 (Lib);
|
||||||
O->Size = 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)
|
static void ReadIndex (void)
|
||||||
/* Read the index of a library file */
|
/* Read the index of a library file */
|
||||||
{
|
{
|
||||||
unsigned Count;
|
unsigned Count, I;
|
||||||
|
|
||||||
/* Seek to the start of the index */
|
/* Seek to the start of the index */
|
||||||
fseek (Lib, Header.IndexOffs, SEEK_SET);
|
fseek (Lib, Header.IndexOffs, SEEK_SET);
|
||||||
@@ -152,6 +134,16 @@ static void ReadIndex (void)
|
|||||||
while (Count--) {
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -180,28 +172,12 @@ static void WriteHeader (void)
|
|||||||
static void WriteIndexEntry (const ObjData* O)
|
static void WriteIndexEntry (const ObjData* O)
|
||||||
/* Write one index entry */
|
/* Write one index entry */
|
||||||
{
|
{
|
||||||
unsigned I;
|
|
||||||
|
|
||||||
/* Module name/flags/MTime/start/size */
|
/* Module name/flags/MTime/start/size */
|
||||||
WriteStr (NewLib, O->Name);
|
WriteStr (NewLib, O->Name);
|
||||||
Write16 (NewLib, O->Flags & ~OBJ_HAVEDATA);
|
Write16 (NewLib, O->Flags & ~OBJ_HAVEDATA);
|
||||||
Write32 (NewLib, O->MTime);
|
Write32 (NewLib, O->MTime);
|
||||||
Write32 (NewLib, O->Start);
|
Write32 (NewLib, O->Start);
|
||||||
Write32 (NewLib, O->Size);
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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)
|
static void LibCheckExports (ObjData* O)
|
||||||
/* Insert all exports from the given object file into the global list
|
/* Insert all exports from the given object file into the global list
|
||||||
* checking for duplicates.
|
* checking for duplicates.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Get a pointer to the buffer */
|
unsigned I;
|
||||||
unsigned char* Exports = O->Exports;
|
|
||||||
|
|
||||||
/* Get the export count */
|
/* Let the user know what we do */
|
||||||
unsigned Count = GetVar (&Exports);
|
Print (stdout, 1, "Module `%s' (%u exports):\n", O->Name, CollCount (&O->Exports));
|
||||||
|
|
||||||
/* Read the exports */
|
/* Insert the exports into the global table */
|
||||||
Print (stdout, 1, "Module `%s' (%u exports):\n", O->Name, Count);
|
for (I = 0; I < CollCount (&O->Exports); ++I) {
|
||||||
while (Count--) {
|
|
||||||
|
|
||||||
const char* Name;
|
/* Get the name of the export */
|
||||||
|
const char* Name = CollConstAt (&O->Exports, I);
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* Insert the name into the hash table */
|
/* Insert the name into the hash table */
|
||||||
Print (stdout, 1, " %s\n", Name);
|
Print (stdout, 1, " %s\n", Name);
|
||||||
@@ -459,7 +340,7 @@ void LibClose (void)
|
|||||||
for (I = 0; I < CollCount (&ObjPool); ++I) {
|
for (I = 0; I < CollCount (&ObjPool); ++I) {
|
||||||
|
|
||||||
/* Get a pointer to the object */
|
/* Get a pointer to the object */
|
||||||
ObjData* O = CollAt (&ObjPool, I);
|
ObjData* O = CollAtUnchecked (&ObjPool, I);
|
||||||
|
|
||||||
/* Check exports, make global export table */
|
/* Check exports, make global export table */
|
||||||
LibCheckExports (O);
|
LibCheckExports (O);
|
||||||
|
|||||||
@@ -70,16 +70,14 @@ ObjData* NewObjData (void)
|
|||||||
|
|
||||||
/* Initialize the data */
|
/* Initialize the data */
|
||||||
O->Name = 0;
|
O->Name = 0;
|
||||||
|
|
||||||
O->Flags = 0;
|
O->Flags = 0;
|
||||||
O->MTime = 0;
|
O->MTime = 0;
|
||||||
O->Start = 0;
|
O->Start = 0;
|
||||||
O->Size = 0;
|
O->Size = 0;
|
||||||
O->StringCount = 0;
|
|
||||||
O->Strings = 0;
|
O->Strings = EmptyCollection;
|
||||||
O->ImportSize = 0;
|
O->Exports = EmptyCollection;
|
||||||
O->Imports = 0;
|
|
||||||
O->ExportSize = 0;
|
|
||||||
O->Exports = 0;
|
|
||||||
|
|
||||||
/* Add it to the list */
|
/* Add it to the list */
|
||||||
CollAppend (&ObjPool, O);
|
CollAppend (&ObjPool, O);
|
||||||
@@ -96,17 +94,31 @@ void FreeObjData (ObjData* O)
|
|||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
xfree (O->Name);
|
xfree (O->Name);
|
||||||
xfree (O->Imports);
|
for (I = 0; I < CollCount (&O->Strings); ++I) {
|
||||||
xfree (O->Exports);
|
xfree (CollAt (&O->Strings, I));
|
||||||
for (I = 0; I < O->StringCount; ++I) {
|
|
||||||
xfree (O->Strings[I]);
|
|
||||||
}
|
}
|
||||||
xfree (O->Strings);
|
DoneCollection (&O->Strings);
|
||||||
|
DoneCollection (&O->Exports);
|
||||||
xfree (O);
|
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)
|
ObjData* FindObjData (const char* Module)
|
||||||
/* Search for the module with the given name and return it. Return NULL if the
|
/* Search for the module with the given name and return it. Return NULL if the
|
||||||
* module is not in the list.
|
* 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];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "coll.h"
|
#include "coll.h"
|
||||||
|
#include "objdefs.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -51,28 +52,30 @@
|
|||||||
|
|
||||||
/* Values for the Flags field */
|
/* Values for the Flags field */
|
||||||
#define OBJ_HAVEDATA 0x0001 /* The object data is in the tmp file */
|
#define OBJ_HAVEDATA 0x0001 /* The object data is in the tmp file */
|
||||||
#define OBJ_MARKED 0x0002 /* Generic marker bit */
|
|
||||||
|
|
||||||
|
|
||||||
/* Internal structure holding object file data */
|
/* Internal structure holding object file data */
|
||||||
typedef struct ObjData ObjData;
|
typedef struct ObjData ObjData;
|
||||||
struct ObjData {
|
struct ObjData {
|
||||||
char* Name; /* Module name */
|
char* Name; /* Module name */
|
||||||
|
|
||||||
|
/* Index entry */
|
||||||
unsigned Flags;
|
unsigned Flags;
|
||||||
unsigned long MTime; /* Modifiation time of object file */
|
unsigned long MTime; /* Modifiation time of object file */
|
||||||
unsigned long Start; /* Start offset of data in library */
|
unsigned long Start; /* Start offset of data in library */
|
||||||
unsigned long Size; /* Size of data in library */
|
unsigned long Size; /* Size of data in library */
|
||||||
unsigned StringCount; /* Number of strings */
|
|
||||||
char** Strings; /* Strings from the object file */
|
/* Object file header */
|
||||||
unsigned long ImportSize; /* Size of imports */
|
ObjHeader Header;
|
||||||
void* Imports; /* Imports as raw data */
|
|
||||||
unsigned long ExportSize; /* Size of exports */
|
/* Basic data needed for simple checks */
|
||||||
void* Exports; /* Exports as raw data */
|
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;
|
extern Collection ObjPool;
|
||||||
|
|
||||||
|
|
||||||
@@ -89,6 +92,9 @@ ObjData* NewObjData (void);
|
|||||||
void FreeObjData (ObjData* O);
|
void FreeObjData (ObjData* O);
|
||||||
/* Free a complete struct */
|
/* Free a complete struct */
|
||||||
|
|
||||||
|
void ClearObjData (ObjData* O);
|
||||||
|
/* Remove any data stored in O */
|
||||||
|
|
||||||
ObjData* FindObjData (const char* Module);
|
ObjData* FindObjData (const char* Module);
|
||||||
/* Search for the module with the given name and return it. Return NULL if the
|
/* Search for the module with the given name and return it. Return NULL if the
|
||||||
* module is not in the list.
|
* module is not in the list.
|
||||||
@@ -97,9 +103,6 @@ ObjData* FindObjData (const char* Module);
|
|||||||
void DelObjData (const char* Module);
|
void DelObjData (const char* Module);
|
||||||
/* Delete the object module from the list */
|
/* 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 */
|
/* End of objdata.h */
|
||||||
|
|||||||
@@ -46,7 +46,10 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "cddefs.h"
|
||||||
|
#include "exprdefs.h"
|
||||||
#include "fname.h"
|
#include "fname.h"
|
||||||
|
#include "symdefs.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* ar65 */
|
/* 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 */
|
/* Read the header of the object file checking the signature */
|
||||||
{
|
{
|
||||||
H->Magic = Read32 (Obj);
|
H->Magic = Read32 (Obj);
|
||||||
@@ -117,32 +120,106 @@ void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjWriteHeader (FILE* Obj, ObjHeader* H)
|
static void SkipExpr (FILE* F)
|
||||||
/* Write the header of the object file */
|
/* Skip an expression in F */
|
||||||
{
|
{
|
||||||
Write32 (Obj, H->Magic);
|
/* Get the operation and skip it */
|
||||||
Write16 (Obj, H->Version);
|
unsigned char Op = Read8 (F);
|
||||||
Write16 (Obj, H->Flags);
|
|
||||||
Write32 (Obj, H->OptionOffs);
|
/* Handle then different expression nodes */
|
||||||
Write32 (Obj, H->OptionSize);
|
switch (Op) {
|
||||||
Write32 (Obj, H->FileOffs);
|
|
||||||
Write32 (Obj, H->FileSize);
|
case EXPR_NULL:
|
||||||
Write32 (Obj, H->SegOffs);
|
break;
|
||||||
Write32 (Obj, H->SegSize);
|
|
||||||
Write32 (Obj, H->ImportOffs);
|
case EXPR_LITERAL:
|
||||||
Write32 (Obj, H->ImportSize);
|
/* 32 bit literal value */
|
||||||
Write32 (Obj, H->ExportOffs);
|
(void) Read32 (F);
|
||||||
Write32 (Obj, H->ExportSize);
|
break;
|
||||||
Write32 (Obj, H->DbgSymOffs);
|
|
||||||
Write32 (Obj, H->DbgSymSize);
|
case EXPR_SYMBOL:
|
||||||
Write32 (Obj, H->LineInfoOffs);
|
/* Variable seized symbol index */
|
||||||
Write32 (Obj, H->LineInfoSize);
|
(void) ReadVar (F);
|
||||||
Write32 (Obj, H->StrPoolOffs);
|
break;
|
||||||
Write32 (Obj, H->StrPoolSize);
|
|
||||||
Write32 (Obj, H->AssertOffs);
|
case EXPR_SECTION:
|
||||||
Write32 (Obj, H->AssertSize);
|
/* 8 bit segment number */
|
||||||
Write32 (Obj, H->ScopeOffs);
|
(void) Read8 (F);
|
||||||
Write32 (Obj, H->ScopeSize);
|
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;
|
const char* Module;
|
||||||
ObjHeader H;
|
ObjHeader H;
|
||||||
ObjData* O;
|
ObjData* O;
|
||||||
unsigned I;
|
|
||||||
|
|
||||||
/* Open the object file */
|
/* Open the object file */
|
||||||
FILE* Obj = fopen (Name, "rb");
|
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) {
|
if (difftime ((time_t)O->MTime, StatBuf.st_mtime) > 0.0) {
|
||||||
Warning ("Replacing module `%s' by older version", O->Name);
|
Warning ("Replacing module `%s' by older version", O->Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free data */
|
||||||
|
ClearObjData (O);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the object module data structure */
|
/* Initialize the object module data structure */
|
||||||
O->Name = xstrdup (Module);
|
O->Name = xstrdup (Module);
|
||||||
O->Flags = OBJ_HAVEDATA;
|
O->Flags = OBJ_HAVEDATA;
|
||||||
O->MTime = StatBuf.st_mtime;
|
O->MTime = StatBuf.st_mtime;
|
||||||
O->ImportSize = H.ImportSize;
|
O->Start = 0;
|
||||||
O->Imports = xmalloc (O->ImportSize);
|
|
||||||
O->ExportSize = H.ExportSize;
|
|
||||||
O->Exports = xmalloc (O->ExportSize);
|
|
||||||
|
|
||||||
/* Read imports and exports */
|
/* Determine the file size. Note: Race condition here */
|
||||||
fseek (Obj, H.ImportOffs, SEEK_SET);
|
fseek (Obj, 0, SEEK_END);
|
||||||
ReadData (Obj, O->Imports, O->ImportSize);
|
O->Size = ftell (Obj);
|
||||||
fseek (Obj, H.ExportOffs, SEEK_SET);
|
|
||||||
ReadData (Obj, O->Exports, O->ExportSize);
|
|
||||||
|
|
||||||
/* Read the string pool */
|
/* Read the basic data from the object file */
|
||||||
fseek (Obj, H.StrPoolOffs, SEEK_SET);
|
ObjReadData (Obj, O);
|
||||||
O->StringCount = ReadVar (Obj);
|
|
||||||
O->Strings = xmalloc (O->StringCount * sizeof (char*));
|
|
||||||
for (I = 0; I < O->StringCount; ++I) {
|
|
||||||
O->Strings[I] = ReadStr (Obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip the object file header */
|
/* Copy the complete object data to the library file and update the
|
||||||
O->Start = ftell (NewLib);
|
* starting offset
|
||||||
fseek (NewLib, OBJ_HDR_SIZE, SEEK_CUR);
|
*/
|
||||||
|
fseek (Obj, 0, SEEK_SET);
|
||||||
/* Copy the remaining sections */
|
O->Start = LibCopyTo (Obj, O->Size);
|
||||||
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);
|
|
||||||
|
|
||||||
/* Done, close the file (we read it only, so no error check) */
|
/* Done, close the file (we read it only, so no error check) */
|
||||||
fclose (Obj);
|
fclose (Obj);
|
||||||
@@ -261,20 +301,14 @@ void ObjAdd (const char* Name)
|
|||||||
void ObjExtract (const char* Name)
|
void ObjExtract (const char* Name)
|
||||||
/* Extract a module from the library */
|
/* Extract a module from the library */
|
||||||
{
|
{
|
||||||
unsigned long ImportStart;
|
|
||||||
unsigned long ExportStart;
|
|
||||||
unsigned long StrPoolStart;
|
|
||||||
unsigned long StrPoolSize;
|
|
||||||
struct utimbuf U;
|
struct utimbuf U;
|
||||||
ObjHeader H;
|
|
||||||
FILE* Obj;
|
FILE* Obj;
|
||||||
unsigned I;
|
|
||||||
|
|
||||||
/* Make a module name from the file name */
|
/* Make a module name from the file name */
|
||||||
const char* Module = GetModule (Name);
|
const char* Module = GetModule (Name);
|
||||||
|
|
||||||
/* Try to find the module in the library */
|
/* 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 */
|
/* Bail out if the module does not exist */
|
||||||
if (O == 0) {
|
if (O == 0) {
|
||||||
@@ -287,39 +321,11 @@ void ObjExtract (const char* Name)
|
|||||||
Error ("Cannot open target file `%s': %s", Name, strerror (errno));
|
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);
|
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 */
|
/* Close the file */
|
||||||
if (fclose (Obj) != 0) {
|
if (fclose (Obj) != 0) {
|
||||||
Error ("Problem closing object file `%s': %s", Name, strerror (errno));
|
Error ("Problem closing object file `%s': %s", Name, strerror (errno));
|
||||||
|
|||||||
@@ -40,8 +40,15 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/* common */
|
|
||||||
#include "objdefs.h"
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Forwards */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct ObjData;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -51,11 +58,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name);
|
void ObjReadData (FILE* F, struct ObjData* O);
|
||||||
/* Read the header of the object file checking the signature */
|
/* 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 ObjWriteHeader (FILE* Obj, ObjHeader* H);
|
*/
|
||||||
/* Write the header of the object file */
|
|
||||||
|
|
||||||
void ObjAdd (const char* Name);
|
void ObjAdd (const char* Name);
|
||||||
/* Add an object file to the library */
|
/* Add an object file to the library */
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2010, Ullrich von Bassewitz */
|
/* (C) 1998-2011, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
/* Defines for magic and version */
|
/* Defines for magic and version */
|
||||||
#define LIB_MAGIC 0x7A55616E
|
#define LIB_MAGIC 0x7A55616E
|
||||||
#define LIB_VERSION 0x000C
|
#define LIB_VERSION 0x000D
|
||||||
|
|
||||||
/* Size of an library file header */
|
/* Size of an library file header */
|
||||||
#define LIB_HDR_SIZE 12
|
#define LIB_HDR_SIZE 12
|
||||||
|
|||||||
Reference in New Issue
Block a user