]> git.sur5r.net Git - cc65/blob - src/ld65/library.c
Removed the - now unused - empty builtin configuration (was used for the ace
[cc65] / src / ld65 / library.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 library.c                                 */
4 /*                                                                           */
5 /*          Library data structures and helpers for the ld65 linker          */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2005 Ullrich von Bassewitz                                       */
10 /*               Römerstraße 52                                              */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
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.                                    */
18 /*                                                                           */
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:                            */
22 /*                                                                           */
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              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <errno.h>
39
40 /* common */
41 #include "exprdefs.h"
42 #include "filepos.h"
43 #include "libdefs.h"
44 #include "objdefs.h"
45 #include "symdefs.h"
46 #include "xmalloc.h"
47
48 /* ld65 */
49 #include "error.h"
50 #include "exports.h"
51 #include "fileio.h"
52 #include "library.h"
53 #include "objdata.h"
54 #include "objfile.h"
55 #include "spool.h"
56
57
58
59 /*****************************************************************************/
60 /*                                   Data                                    */
61 /*****************************************************************************/
62
63
64
65 /* Library data structure */
66 typedef struct Library Library;
67 struct Library {
68     Library*    Next;
69     unsigned    Name;           /* String id of the name */
70     FILE*       F;              /* Open file stream */
71     LibHeader   Header;         /* Library header */
72     unsigned    ModCount;       /* Number of modules in the library */
73     ObjData**   Modules;        /* Modules */
74 };
75
76 /* List of open libraries */
77 static Collection OpenLibs = STATIC_COLLECTION_INITIALIZER;
78
79 /* Flag for library grouping */
80 static int Grouping = 0;
81
82
83
84 /*****************************************************************************/
85 /*                              struct Library                               */
86 /*****************************************************************************/
87
88
89
90 static Library* NewLibrary (FILE* F, const char* Name)
91 /* Create a new Library structure and return it */
92 {
93     /* Allocate memory */
94     Library* L = xmalloc (sizeof (*L));
95
96     /* Initialize the fields */
97     L->Next     = 0;
98     L->Name     = GetStringId (Name);
99     L->F        = F;
100     L->ModCount = 0;
101     L->Modules  = 0;
102
103     /* Return the new struct */
104     return L;
105 }
106
107
108
109 static void FreeLibrary (Library* L)
110 /* Free a library structure */
111 {
112     /* Close the library file */
113     if (fclose (L->F) != 0) {
114         Error ("Error closing `%s': %s", GetString (L->Name), strerror (errno));
115     }
116
117     /* Free the module index */
118     xfree (L->Modules);
119
120     /* Free the library structure */
121     xfree (L);
122 }
123
124
125
126 /*****************************************************************************/
127 /*                       Reading file data structures                        */
128 /*****************************************************************************/
129
130
131
132 static void LibSeek (Library* L, unsigned long Offs)
133 /* Do a seek in the library checking for errors */
134 {
135     if (fseek (L->F, Offs, SEEK_SET) != 0) {
136         Error ("Seek error in `%s' (%lu): %s",
137                GetString (L->Name), Offs, strerror (errno));
138     }
139 }
140
141
142
143 static void LibReadHeader (Library* L)
144 /* Read a library header */
145 {
146     /* Read the remaining header fields (magic is already read) */
147     L->Header.Magic   = LIB_MAGIC;
148     L->Header.Version = Read16 (L->F);
149     if (L->Header.Version != LIB_VERSION) {
150         Error ("Wrong data version in `%s'", GetString (L->Name));
151     }
152     L->Header.Flags   = Read16 (L->F);
153     L->Header.IndexOffs = Read32 (L->F);
154 }
155
156
157
158 static void LibReadObjHeader (Library* L, ObjData* O)
159 /* Read the header of the object file checking the signature */
160 {
161     O->Header.Magic = Read32 (L->F);
162     if (O->Header.Magic != OBJ_MAGIC) {
163         Error ("Object file `%s' in library `%s' is invalid",
164                GetObjFileName (O), GetString (L->Name));
165     }
166     O->Header.Version = Read16 (L->F);
167     if (O->Header.Version != OBJ_VERSION) {
168         Error ("Object file `%s' in library `%s' has wrong version",
169                GetObjFileName (O), GetString (L->Name));
170     }
171     O->Header.Flags        = Read16 (L->F);
172     O->Header.OptionOffs   = Read32 (L->F);
173     O->Header.OptionSize   = Read32 (L->F);
174     O->Header.FileOffs     = Read32 (L->F);
175     O->Header.FileSize     = Read32 (L->F);
176     O->Header.SegOffs      = Read32 (L->F);
177     O->Header.SegSize      = Read32 (L->F);
178     O->Header.ImportOffs   = Read32 (L->F);
179     O->Header.ImportSize   = Read32 (L->F);
180     O->Header.ExportOffs   = Read32 (L->F);
181     O->Header.ExportSize   = Read32 (L->F);
182     O->Header.DbgSymOffs   = Read32 (L->F);
183     O->Header.DbgSymSize   = Read32 (L->F);
184     O->Header.LineInfoOffs = Read32 (L->F);
185     O->Header.LineInfoSize = Read32 (L->F);
186     O->Header.StrPoolOffs  = Read32 (L->F);
187     O->Header.StrPoolSize  = Read32 (L->F);
188     O->Header.AssertOffs   = Read32 (L->F);
189     O->Header.AssertSize   = Read32 (L->F);
190     O->Header.ScopeOffs    = Read32 (L->F);
191     O->Header.ScopeSize    = Read32 (L->F);
192 }
193
194
195
196 static ObjData* ReadIndexEntry (Library* L)
197 /* Read one entry in the index */
198 {
199     /* Create a new entry and insert it into the list */
200     ObjData* O  = NewObjData ();
201
202     /* Module name */
203     O->Name = ReadStr (L->F);
204
205     /* Module flags/MTime/Start/Size */
206     O->Flags    = Read16 (L->F);
207     O->MTime    = Read32 (L->F);
208     O->Start    = Read32 (L->F);
209     Read32 (L->F);                      /* Skip Size */
210
211     /* Read the string pool */
212     ObjReadStrPool (L->F, FileGetPos (L->F), O);
213
214     /* Skip the export size, then read the exports */
215     (void) ReadVar (L->F);
216     ObjReadExports (L->F, FileGetPos (L->F), O);
217
218     /* Skip the import size, then read the imports */
219     (void) ReadVar (L->F);
220     ObjReadImports (L->F, FileGetPos (L->F), O);
221
222     /* Done */
223     return O;
224 }
225
226
227
228 static void LibReadIndex (Library* L)
229 /* Read the index of a library file */
230 {
231     unsigned I;
232
233     /* Seek to the start of the index */
234     LibSeek (L, L->Header.IndexOffs);
235
236     /* Read the object file count and allocate memory */
237     L->ModCount = ReadVar (L->F);
238     L->Modules  = xmalloc (L->ModCount * sizeof (L->Modules[0]));
239
240     /* Read all entries in the index */
241     for (I = 0; I < L->ModCount; ++I) {
242         L->Modules[I] = ReadIndexEntry (L);
243     }
244 }
245
246
247
248 /*****************************************************************************/
249 /*                             High level stuff                              */
250 /*****************************************************************************/
251
252
253
254 static void LibCheckExports (ObjData* O)
255 /* Check if the exports from this file can satisfy any import requests. If so,
256  * insert the imports and exports from this file and mark the file as added.
257  */
258 {
259     unsigned I;
260
261     /* Check all exports */
262     for (I = 0; I < O->ExportCount; ++I) {
263         if (IsUnresolved (O->Exports[I]->Name)) {
264             /* We need this module */
265             O->Flags |= OBJ_REF;            break;
266         }
267     }
268
269     /* If we need this module, insert the imports and exports */
270     if (O->Flags & OBJ_REF) {
271         InsertObjGlobals (O);
272     }
273 }
274
275
276
277 static void LibOpen (FILE* F, const char* Name)
278 /* Open the library for use */
279 {
280     /* Create a new library structure */
281     Library* L = NewLibrary (F, Name);
282
283     /* Read the remaining header fields (magic is already read) */
284     LibReadHeader (L);
285
286     /* Seek to the index position and read the index */
287     LibReadIndex (L);
288
289     /* Add the library to the list of open libraries */
290     CollAppend (&OpenLibs, L);
291 }
292
293
294
295 static void LibResolve (void)
296 /* Resolve all externals from the list of all currently open libraries */
297 {
298     unsigned I, J;
299     unsigned Additions;
300
301     /* Walk repeatedly over all open libraries until there's nothing more
302      * to add.
303      */
304     do {
305
306         Additions = 0;
307
308         /* Walk over all libraries */
309         for (I = 0; I < CollCount (&OpenLibs); ++I) {
310
311             /* Get the next library */
312             Library* L = CollAt (&OpenLibs, I);
313
314             /* Walk through all modules in this library and check for each
315              * module if there are unresolved externals in existing modules
316              * that may be resolved by adding the module.
317              */
318             for (J = 0; J < L->ModCount; ++J) {
319
320                 /* Get the next module */
321                 ObjData* O = L->Modules[J];
322
323                 /* We only need to check this module if it wasn't added before */
324                 if ((O->Flags & OBJ_REF) == 0) {
325                     LibCheckExports (O);
326                     if (O->Flags & OBJ_REF) {
327                         /* The routine added the file */
328                         ++Additions;
329                     }
330                 }
331             }
332         }
333
334     } while (Additions > 0);
335
336     /* We do know now which modules must be added, so we can load the data
337      * for these modues into memory. Since we're walking over all modules
338      * anyway, we will also remove data for unneeded modules.
339      */
340     for (I = 0; I < CollCount (&OpenLibs); ++I) {
341
342         /* Get the next library */
343         Library* L = CollAt (&OpenLibs, I);
344
345         /* Walk over all modules in this library and add the files list and
346          * sections for all referenced modules.
347          */
348         for (J = 0; J < L->ModCount; ++J) {
349
350             /* Get the object data */
351             ObjData* O = L->Modules[J];
352
353             /* Is this object file referenced? */
354             if (O->Flags & OBJ_REF) {
355
356                 /* Seek to the start of the object file and read the header */
357                 LibSeek (L, O->Start);
358                 LibReadObjHeader (L, O);
359
360                 /* Seek to the start of the files list and read the files list */
361                 ObjReadFiles (L->F, O->Start + O->Header.FileOffs, O);
362
363                 /* Seek to the start of the debug info and read the debug info */
364                 ObjReadDbgSyms (L->F, O->Start + O->Header.DbgSymOffs, O);
365
366                 /* Seek to the start of the line infos and read them */
367                 ObjReadLineInfos (L->F, O->Start + O->Header.LineInfoOffs, O);
368
369                 /* Read the assertions from the object file */
370                 ObjReadAssertions (L->F, O->Start + O->Header.AssertOffs, O);
371
372                 /* Read the scope table from the object file */
373                 ObjReadScopes (L->F, O->Start + O->Header.ScopeOffs, O);
374
375                 /* Seek to the start of the segment list and read the segments.
376                  * This must be last, since the data here may reference other
377                  * stuff.
378                  */
379                 ObjReadSections (L->F, O->Start + O->Header.SegOffs, O);
380
381                 /* Remember from which library this module is */
382                 O->LibName = L->Name;
383
384                 /* All references to strings are now resolved, so we can delete
385                  * the module string pool.
386                  */
387                 FreeObjStrings (O);
388
389                 /* Insert the object into the list of all used object files */
390                 InsertObjData (O);
391
392             } else {
393
394                 /* Unreferenced object file, remove it */
395                 FreeObjData (O);
396
397             }
398         }
399
400         /* Close the file and delete the library data */
401         FreeLibrary (L);
402     }
403
404     /* We're done with all open libraries, clear the OpenLibs collection */
405     CollDeleteAll (&OpenLibs);
406 }
407
408
409
410 void LibAdd (FILE* F, const char* Name)
411 /* Add files from the library to the list if there are references that could
412  * be satisfied.
413  */
414 {
415     /* Add the library to the list of open libraries */
416     LibOpen (F, Name);
417
418     /* If there is no library group open, just resolve all open symbols and
419      * close the library. Otherwise we will do nothing because resolving will
420      * be done when the group is closed.
421      */
422     if (!Grouping) {
423         LibResolve ();
424     }
425 }
426
427
428
429 void LibStartGroup (void)
430 /* Start a library group. Objects within a library group may reference each
431  * other, and libraries are searched repeatedly until all references are
432  * satisfied.
433  */
434 {
435     /* We cannot already have a group open */
436     if (Grouping) {
437         Error ("There's already a library group open");
438     }
439
440     /* Start a new group */
441     Grouping = 1;
442 }
443
444
445
446 void LibEndGroup (void)
447 /* End a library group and resolve all open references. Objects within a
448  * library group may reference each other, and libraries are searched
449  * repeatedly until all references are satisfied.
450  */
451 {
452     /* We must have a library group open */
453     if (!Grouping) {
454         Error ("There's no library group open");
455     }
456
457     /* Resolve symbols, end the group */
458     LibResolve ();
459     Grouping = 0;
460 }
461
462
463
464 void LibCheckGroup (void)
465 /* Check if there are open library groups */
466 {
467     if (Grouping) {
468         Error ("Library group was never closed");
469     }
470 }
471
472
473