1 /*****************************************************************************/
5 /* Library data structures and helpers for the ar65 archiver */
9 /* (C) 1998 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
40 #include "../common/libdefs.h"
41 #include "../common/symdefs.h"
42 #include "../common/exprdefs.h"
43 #include "../common/filepos.h"
44 #include "../common/bitops.h"
56 /*****************************************************************************/
58 /*****************************************************************************/
62 /* File descriptor for the library file */
65 static const char* LibName = 0;
67 /* The library header */
68 static LibHeader Header = {
75 /*****************************************************************************/
76 /* Writing file data structures */
77 /*****************************************************************************/
81 static void ReadHeader (void)
82 /* Read the header of a library file */
84 /* Seek to position zero */
85 fseek (Lib, 0, SEEK_SET);
87 /* Read the header fields, checking magic and version */
88 Header.Magic = Read32 (Lib);
89 if (Header.Magic != LIB_MAGIC) {
90 Error ("`%s' is not a valid library file", LibName);
92 Header.Version = Read16 (Lib);
93 if (Header.Version != LIB_VERSION) {
94 Error ("Wrong data version in `%s'", LibName);
96 Header.Flags = Read16 (Lib);
97 Header.IndexOffs = Read32 (Lib);
102 static void ReadIndexEntry (void)
103 /* Read one entry in the index */
105 /* Create a new entry and insert it into the list */
106 ObjData* O = NewObjData ();
108 /* Module name/flags/MTime/Start/Size */
109 O->Name = ReadStr (Lib);
110 O->Flags = Read16 (Lib);
111 O->MTime = Read32 (Lib);
112 O->Start = Read32 (Lib);
113 O->Size = Read32 (Lib);
116 O->ExportSize = Read16 (Lib);
117 O->Exports = Xmalloc (O->ExportSize);
118 ReadData (Lib, O->Exports, O->ExportSize);
121 O->ImportSize = Read16 (Lib);
122 O->Imports = Xmalloc (O->ImportSize);
123 ReadData (Lib, O->Imports, O->ImportSize);
128 static void ReadIndex (void)
129 /* Read the index of a library file */
133 /* Seek to the start of the index */
134 fseek (Lib, Header.IndexOffs, SEEK_SET);
136 /* Read the object file count and calculate the cross ref size */
137 Count = Read16 (Lib);
139 /* Read all entries in the index */
147 /*****************************************************************************/
148 /* Writing file data structures */
149 /*****************************************************************************/
153 static void WriteHeader (void)
154 /* Write the header to the library file */
156 /* Seek to position zero */
157 fseek (NewLib, 0, SEEK_SET);
159 /* Write the header fields */
160 Write32 (NewLib, Header.Magic);
161 Write16 (NewLib, Header.Version);
162 Write16 (NewLib, Header.Flags);
163 Write32 (NewLib, Header.IndexOffs);
168 static void WriteIndexEntry (ObjData* O)
169 /* Write one index entry */
171 /* Module name/flags/MTime/start/size */
172 WriteStr (NewLib, O->Name);
173 Write16 (NewLib, O->Flags & ~OBJ_HAVEDATA);
174 Write32 (NewLib, O->MTime);
175 Write32 (NewLib, O->Start);
176 Write32 (NewLib, O->Size);
179 Write16 (NewLib, O->ExportSize);
180 WriteData (NewLib, O->Exports, O->ExportSize);
183 Write16 (NewLib, O->ImportSize);
184 WriteData (NewLib, O->Imports, O->ImportSize);
189 static void WriteIndex (void)
190 /* Write the index of a library file */
194 /* Sync I/O in case the last operation was a read */
195 fseek (NewLib, 0, SEEK_CUR);
197 /* Remember the current offset in the header */
198 Header.IndexOffs = ftell (NewLib);
200 /* Write the object file count */
201 Write16 (NewLib, ObjCount);
203 /* Write the object files */
213 /*****************************************************************************/
214 /* High level stuff */
215 /*****************************************************************************/
219 void LibOpen (const char* Name, int MustExist, int NeedTemp)
220 /* Open an existing library and a temporary copy. If MustExist is true, the
221 * old library is expected to exist. If NeedTemp is true, a temporary library
225 /* Remember the name */
226 LibName = StrDup (Name);
228 /* Open the existing library for reading */
229 Lib = fopen (Name, "rb");
232 /* File does not exist */
234 Error ("Library `%s' does not exist", Name);
236 Warning ("Library `%s' not found - will be created", Name);
241 /* We have an existing file: Read the header */
244 /* Now read the existing index */
250 /* Create the temporary library */
253 Error ("Cannot create temporary file: %s", strerror (errno));
256 /* Write a dummy header to the temp file */
263 unsigned long LibCopyTo (FILE* F, unsigned long Bytes)
264 /* Copy data from F to the temp library file, return the start position in
265 * the temporary library file.
268 unsigned char Buf [4096];
270 /* Remember the position */
271 unsigned long Pos = ftell (NewLib);
275 unsigned Count = (Bytes > sizeof (Buf))? sizeof (Buf) : Bytes;
276 ReadData (F, Buf, Count);
277 WriteData (NewLib, Buf, Count);
281 /* Return the start position */
287 void LibCopyFrom (unsigned long Pos, unsigned long Bytes, FILE* F)
288 /* Copy data from the library file into another file */
290 unsigned char Buf [4096];
292 /* Seek to the correct position */
293 fseek (Lib, Pos, SEEK_SET);
297 unsigned Count = (Bytes > sizeof (Buf))? sizeof (Buf) : Bytes;
298 ReadData (Lib, Buf, Count);
299 WriteData (F, Buf, Count);
306 static void SkipExpr (unsigned char** Buf)
307 /* Skip an expression in Buf */
309 /* Get the operation and skip it */
310 unsigned char Op = **Buf;
313 /* Filter leaf nodes */
320 /* 32 bit literal value */
325 /* 16 bit symbol index */
330 /* 8 bit segment number */
335 /* What's left are unary and binary nodes */
336 SkipExpr (Buf); /* Skip left */
337 SkipExpr (Buf); /* Skip right */
342 static void LibCheckExports (ObjData* O)
343 /* Insert all exports from the given object file into the global list
344 * checking for duplicates.
349 /* Get a pointer to the buffer */
350 unsigned char* Exports = O->Exports;
352 /* First two bytes are export count */
353 unsigned Lo = *Exports++;
354 unsigned Hi = *Exports++;
355 unsigned Count = (Hi << 8) + Lo;
357 /* Read the exports */
359 printf ("Module `%s' (%u exports):\n", O->Name, Count);
365 /* Get the export tag */
366 unsigned char Tag = *Exports++;
368 /* Next thing is name of symbol */
370 memcpy (Name, Exports, Len);
374 /* Skip value of symbol */
375 if (Tag & EXP_EXPR) {
376 /* Expression tree */
379 /* Constant 32 bit value */
383 /* Skip the position */
386 /* Insert the name into the hash table */
388 printf (" %s\n", Name);
390 ExpInsert (Name, O->Index);
397 /* Write remaining data, close both files and copy the temp file to the old
401 /* Do we have a temporary library? */
405 unsigned char Buf [4096];
408 /* Index the object files and make an array containing the objects */
411 /* Walk through the object file list, inserting exports into the
412 * export list checking for duplicates. Copy any data that is still
413 * in the old library into the new one.
415 for (I = 0; I < ObjCount; ++I) {
417 /* Get a pointer to the object */
418 ObjData* O = ObjPool [I];
420 /* Check exports, make global export table */
423 /* Copy data if needed */
424 if ((O->Flags & OBJ_HAVEDATA) == 0) {
425 /* Data is still in the old library */
426 fseek (Lib, O->Start, SEEK_SET);
427 O->Start = ftell (NewLib);
428 LibCopyTo (Lib, O->Size);
429 O->Flags |= OBJ_HAVEDATA;
433 /* Write the index */
436 /* Write the updated header */
440 if (Lib && fclose (Lib) != 0) {
441 Error ("Error closing library: %s", strerror (errno));
444 /* Reopen the library and truncate it */
445 Lib = fopen (LibName, "wb");
447 Error ("Cannot open library `%s' for writing: %s",
448 LibName, strerror (errno));
451 /* Copy the new library to the new one */
452 fseek (NewLib, 0, SEEK_SET);
453 while ((Count = fread (Buf, 1, sizeof (Buf), NewLib)) != 0) {
454 if (fwrite (Buf, 1, Count, Lib) != Count) {
455 Error ("Cannot write to `%s': %s", LibName, strerror (errno));
460 /* Close both files */
461 if (Lib && fclose (Lib) != 0) {
462 Error ("Problem closing `%s': %s", LibName, strerror (errno));
464 if (NewLib && fclose (NewLib) != 0) {
465 Error ("Problem closing temporary library file: %s", strerror (errno));