]> git.sur5r.net Git - cc65/blob - src/ld65/library.c
Removed (pretty inconsistently used) tab chars from source code base.
[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-2011, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 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 "coll.h"
42 #include "exprdefs.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     unsigned    Id;             /* Id of library */
69     unsigned    Name;           /* String id of the name */
70     FILE*       F;              /* Open file stream */
71     LibHeader   Header;         /* Library header */
72     Collection  Modules;        /* Modules */
73 };
74
75 /* List of open libraries */
76 static Collection OpenLibs = STATIC_COLLECTION_INITIALIZER;
77
78 /* List of used libraries */
79 static Collection LibraryList = STATIC_COLLECTION_INITIALIZER;
80
81 /* Flag for library grouping */
82 static int Grouping = 0;
83
84
85
86 /*****************************************************************************/
87 /*                              struct Library                               */
88 /*****************************************************************************/
89
90
91
92 static Library* NewLibrary (FILE* F, const char* Name)
93 /* Create a new Library structure and return it */
94 {
95     /* Allocate memory */
96     Library* L = xmalloc (sizeof (*L));
97
98     /* Initialize the fields */
99     L->Id       = ~0U;
100     L->Name     = GetStringId (Name);
101     L->F        = F;
102     L->Modules  = EmptyCollection;
103
104     /* Return the new struct */
105     return L;
106 }
107
108
109
110 static void CloseLibrary (Library* L)
111 /* Close a library file and remove the list of modules */
112 {
113     /* Close the library file */
114     if (fclose (L->F) != 0) {
115         Error ("Error closing `%s': %s", GetString (L->Name), strerror (errno));
116     }
117     L->F = 0;
118 }
119
120
121
122 static void FreeLibrary (Library* L)
123 /* Free a library structure */
124 {
125     /* Close the library */
126     CloseLibrary (L);
127
128     /* Free the module index */
129     DoneCollection (&L->Modules);
130
131     /* Free the library structure */
132     xfree (L);
133 }
134
135
136
137 /*****************************************************************************/
138 /*                       Reading file data structures                        */
139 /*****************************************************************************/
140
141
142
143 static void LibSeek (Library* L, unsigned long Offs)
144 /* Do a seek in the library checking for errors */
145 {
146     if (fseek (L->F, Offs, SEEK_SET) != 0) {
147         Error ("Seek error in `%s' (%lu): %s",
148                GetString (L->Name), Offs, strerror (errno));
149     }
150 }
151
152
153
154 static void LibReadHeader (Library* L)
155 /* Read a library header */
156 {
157     /* Read the remaining header fields (magic is already read) */
158     L->Header.Magic   = LIB_MAGIC;
159     L->Header.Version = Read16 (L->F);
160     if (L->Header.Version != LIB_VERSION) {
161         Error ("Wrong data version in `%s'", GetString (L->Name));
162     }
163     L->Header.Flags   = Read16 (L->F);
164     L->Header.IndexOffs = Read32 (L->F);
165 }
166
167
168
169 static void LibReadObjHeader (Library* L, ObjData* O)
170 /* Read the header of the object file checking the signature */
171 {
172     O->Header.Magic = Read32 (L->F);
173     if (O->Header.Magic != OBJ_MAGIC) {
174         Error ("Object file `%s' in library `%s' is invalid",
175                GetObjFileName (O), GetString (L->Name));
176     }
177     O->Header.Version = Read16 (L->F);
178     if (O->Header.Version != OBJ_VERSION) {
179         Error ("Object file `%s' in library `%s' has wrong version",
180                GetObjFileName (O), GetString (L->Name));
181     }
182     O->Header.Flags        = Read16 (L->F);
183     O->Header.OptionOffs   = Read32 (L->F);
184     O->Header.OptionSize   = Read32 (L->F);
185     O->Header.FileOffs     = Read32 (L->F);
186     O->Header.FileSize     = Read32 (L->F);
187     O->Header.SegOffs      = Read32 (L->F);
188     O->Header.SegSize      = Read32 (L->F);
189     O->Header.ImportOffs   = Read32 (L->F);
190     O->Header.ImportSize   = Read32 (L->F);
191     O->Header.ExportOffs   = Read32 (L->F);
192     O->Header.ExportSize   = Read32 (L->F);
193     O->Header.DbgSymOffs   = Read32 (L->F);
194     O->Header.DbgSymSize   = Read32 (L->F);
195     O->Header.LineInfoOffs = Read32 (L->F);
196     O->Header.LineInfoSize = Read32 (L->F);
197     O->Header.StrPoolOffs  = Read32 (L->F);
198     O->Header.StrPoolSize  = Read32 (L->F);
199     O->Header.AssertOffs   = Read32 (L->F);
200     O->Header.AssertSize   = Read32 (L->F);
201     O->Header.ScopeOffs    = Read32 (L->F);
202     O->Header.ScopeSize    = Read32 (L->F);
203     O->Header.SpanOffs     = Read32 (L->F);
204     O->Header.SpanSize     = Read32 (L->F);
205 }
206
207
208
209 static ObjData* ReadIndexEntry (Library* L)
210 /* Read one entry in the index */
211 {
212     /* Create a new entry and insert it into the list */
213     ObjData* O  = NewObjData ();
214
215     /* Remember from which library this module is */
216     O->Lib = L;
217
218     /* Module name */
219     O->Name = ReadStr (L->F);
220
221     /* Module flags/MTime/Start/Size */
222     O->Flags    = Read16 (L->F);
223     O->MTime    = Read32 (L->F);
224     O->Start    = Read32 (L->F);
225     Read32 (L->F);                      /* Skip Size */
226
227     /* Done */
228     return O;
229 }
230
231
232
233 static void ReadBasicData (Library* L, ObjData* O)
234 /* Read basic data for an object file that is necessary to resolve external
235  * references.
236  */
237 {
238     /* Seek to the start of the object file and read the header */
239     LibSeek (L, O->Start);
240     LibReadObjHeader (L, O);
241
242     /* Read the string pool */
243     ObjReadStrPool (L->F, O->Start + O->Header.StrPoolOffs, O);
244
245     /* Read the files list */
246     ObjReadFiles (L->F, O->Start + O->Header.FileOffs, O);
247
248     /* Read the line infos */
249     ObjReadLineInfos (L->F, O->Start + O->Header.LineInfoOffs, O);
250
251     /* Read the imports */
252     ObjReadImports (L->F, O->Start + O->Header.ImportOffs, O);
253
254     /* Read the exports */
255     ObjReadExports (L->F, O->Start + O->Header.ExportOffs, O);
256 }
257
258
259
260 static void LibReadIndex (Library* L)
261 /* Read the index of a library file */
262 {
263     unsigned ModuleCount, I;
264
265     /* Seek to the start of the index */
266     LibSeek (L, L->Header.IndexOffs);
267
268     /* Read the object file count and allocate memory */
269     ModuleCount = ReadVar (L->F);
270     CollGrow (&L->Modules, ModuleCount);
271
272     /* Read all entries in the index */
273     while (ModuleCount--) {
274         CollAppend (&L->Modules, ReadIndexEntry (L));
275     }
276
277     /* Walk over the index and read basic data for all object files in the
278      * library.
279      */
280     for (I = 0; I < CollCount (&L->Modules); ++I) {
281         ReadBasicData (L, CollAtUnchecked (&L->Modules, I));
282     }
283 }
284
285
286
287 /*****************************************************************************/
288 /*                             High level stuff                              */
289 /*****************************************************************************/
290
291
292
293 static void LibCheckExports (ObjData* O)
294 /* Check if the exports from this file can satisfy any import requests. If so,
295  * insert the imports and exports from this file and mark the file as added.
296  */
297 {
298     unsigned I;
299
300     /* Check all exports */
301     for (I = 0; I < CollCount (&O->Exports); ++I) {
302         const Export* E = CollConstAt (&O->Exports, I);
303         if (IsUnresolved (E->Name)) {
304            /* We need this module, insert the imports and exports */
305             O->Flags |= OBJ_REF;
306             InsertObjGlobals (O);
307             break;
308         }
309     }
310 }
311
312
313
314 static void LibOpen (FILE* F, const char* Name)
315 /* Open the library for use */
316 {
317     /* Create a new library structure */
318     Library* L = NewLibrary (F, Name);
319
320     /* Read the remaining header fields (magic is already read) */
321     LibReadHeader (L);
322
323     /* Seek to the index position and read the index */
324     LibReadIndex (L);
325
326     /* Add the library to the list of open libraries */
327     CollAppend (&OpenLibs, L);
328 }
329
330
331
332 static void LibResolve (void)
333 /* Resolve all externals from the list of all currently open libraries */
334 {
335     unsigned I, J;
336     unsigned Additions;
337
338     /* Walk repeatedly over all open libraries until there's nothing more
339      * to add.
340      */
341     do {
342
343         Additions = 0;
344
345         /* Walk over all libraries */
346         for (I = 0; I < CollCount (&OpenLibs); ++I) {
347
348             /* Get the next library */
349             Library* L = CollAt (&OpenLibs, I);
350
351             /* Walk through all modules in this library and check for each
352              * module if there are unresolved externals in existing modules
353              * that may be resolved by adding the module.
354              */
355             for (J = 0; J < CollCount (&L->Modules); ++J) {
356
357                 /* Get the next module */
358                 ObjData* O = CollAtUnchecked (&L->Modules, J);
359
360                 /* We only need to check this module if it wasn't added before */
361                 if ((O->Flags & OBJ_REF) == 0) {
362                     LibCheckExports (O);
363                     if (O->Flags & OBJ_REF) {
364                         /* The routine added the file */
365                         ++Additions;
366                     }
367                 }
368             }
369         }
370
371     } while (Additions > 0);
372
373     /* We do know now which modules must be added, so we can load the data
374      * for these modues into memory. Since we're walking over all modules
375      * anyway, we will also remove data for unneeded modules.
376      */
377     for (I = 0; I < CollCount (&OpenLibs); ++I) {
378
379         /* Get the next library */
380         Library* L = CollAt (&OpenLibs, I);
381
382         /* Walk over all modules in this library and add the files list and
383          * sections for all referenced modules.
384          */
385         J = 0;
386         while (J < CollCount (&L->Modules)) {
387
388             /* Get the object data */
389             ObjData* O = CollAtUnchecked (&L->Modules, J);
390
391             /* Is this object file referenced? */
392             if (O->Flags & OBJ_REF) {
393
394                 /* Seek to the start of the debug info and read the debug info */
395                 ObjReadDbgSyms (L->F, O->Start + O->Header.DbgSymOffs, O);
396
397                 /* Read the assertions from the object file */
398                 ObjReadAssertions (L->F, O->Start + O->Header.AssertOffs, O);
399
400                 /* Seek to the start of the segment list and read the segments.
401                  * This must be late, since the data here may reference other
402                  * stuff.
403                  */
404                 ObjReadSections (L->F, O->Start + O->Header.SegOffs, O);
405
406                 /* Read the scope table from the object file. Scopes reference
407                  * segments, so we must read them after the sections.
408                  */
409                 ObjReadScopes (L->F, O->Start + O->Header.ScopeOffs, O);
410
411                 /* Read the spans */
412                 ObjReadSpans (L->F, O->Start + O->Header.SpanOffs, O);
413
414                 /* All references to strings are now resolved, so we can delete
415                  * the module string pool.
416                  */
417                 FreeObjStrings (O);
418
419                 /* Insert the object into the list of all used object files */
420                 InsertObjData (O);
421
422                 /* Process next object file in library */
423                 ++J;
424
425             } else {
426
427                 /* Unreferenced object file, remove it */
428                 FreeObjData (O);
429                 CollDelete (&L->Modules, J);
430
431             }
432         }
433
434         /* If we have referenced modules in this library, assign it an id
435          * (which is the index in the library collection) and keep it.
436          */
437         if (CollCount (&L->Modules) > 0) {
438             CloseLibrary (L);
439             L->Id = CollCount (&LibraryList);
440             CollAppend (&LibraryList, L);
441         } else {
442             /* Delete the library */
443             FreeLibrary (L);
444             CollDelete (&OpenLibs, I);
445         }
446     }
447
448     /* We're done with all open libraries, clear the OpenLibs collection */
449     CollDeleteAll (&OpenLibs);
450 }
451
452
453
454 void LibAdd (FILE* F, const char* Name)
455 /* Add files from the library to the list if there are references that could
456  * be satisfied.
457  */
458 {
459     /* Add the library to the list of open libraries */
460     LibOpen (F, Name);
461
462     /* If there is no library group open, just resolve all open symbols and
463      * close the library. Otherwise we will do nothing because resolving will
464      * be done when the group is closed.
465      */
466     if (!Grouping) {
467         LibResolve ();
468     }
469 }
470
471
472
473 void LibStartGroup (void)
474 /* Start a library group. Objects within a library group may reference each
475  * other, and libraries are searched repeatedly until all references are
476  * satisfied.
477  */
478 {
479     /* We cannot already have a group open */
480     if (Grouping) {
481         Error ("There's already a library group open");
482     }
483
484     /* Start a new group */
485     Grouping = 1;
486 }
487
488
489
490 void LibEndGroup (void)
491 /* End a library group and resolve all open references. Objects within a
492  * library group may reference each other, and libraries are searched
493  * repeatedly until all references are satisfied.
494  */
495 {
496     /* We must have a library group open */
497     if (!Grouping) {
498         Error ("There's no library group open");
499     }
500
501     /* Resolve symbols, end the group */
502     LibResolve ();
503     Grouping = 0;
504 }
505
506
507
508 void LibCheckGroup (void)
509 /* Check if there are open library groups */
510 {
511     if (Grouping) {
512         Error ("Library group was never closed");
513     }
514 }
515
516
517
518 const char* GetLibFileName (const Library* L)
519 /* Get the name of a library */
520 {
521     return GetString (L->Name);
522 }
523
524
525
526 unsigned GetLibId (const Library* L)
527 /* Get the id of a library file. */
528 {
529     return L->Id;
530 }
531
532
533
534 unsigned LibraryCount (void)
535 /* Return the total number of libraries */
536 {
537     return CollCount (&LibraryList);
538 }
539
540
541
542 void PrintDbgLibraries (FILE* F)
543 /* Output the libraries to a debug info file */
544 {
545     unsigned I;
546
547     /* Output information about all libraries */
548     for (I = 0; I < CollCount (&LibraryList); ++I) {
549         /* Get the library */
550         const Library* L = CollAtUnchecked (&LibraryList, I);
551
552         /* Output the info */
553         fprintf (F, "lib\tid=%u,name=\"%s\"\n", L->Id, GetString (L->Name));
554     }
555 }
556
557
558
559