]> git.sur5r.net Git - cc65/blob - src/ld65/library.c
If a symbol is an import, the corresponding export does only have a debug
[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 }
204
205
206
207 static ObjData* ReadIndexEntry (Library* L)
208 /* Read one entry in the index */
209 {
210     /* Create a new entry and insert it into the list */
211     ObjData* O  = NewObjData ();
212
213     /* Remember from which library this module is */
214     O->Lib = L;
215
216     /* Module name */
217     O->Name = ReadStr (L->F);
218
219     /* Module flags/MTime/Start/Size */
220     O->Flags    = Read16 (L->F);
221     O->MTime    = Read32 (L->F);
222     O->Start    = Read32 (L->F);
223     Read32 (L->F);                      /* Skip Size */
224
225     /* Done */
226     return O;
227 }
228
229
230
231 static void ReadBasicData (Library* L, ObjData* O)
232 /* Read basic data for an object file that is necessary to resolve external
233  * references.
234  */
235 {
236     /* Seek to the start of the object file and read the header */
237     LibSeek (L, O->Start);
238     LibReadObjHeader (L, O);
239
240     /* Read the string pool */
241     ObjReadStrPool (L->F, O->Start + O->Header.StrPoolOffs, O);
242
243     /* Read the files list */
244     ObjReadFiles (L->F, O->Start + O->Header.FileOffs, O);
245
246     /* Read the line infos */
247     ObjReadLineInfos (L->F, O->Start + O->Header.LineInfoOffs, O);
248
249     /* Read the imports */
250     ObjReadImports (L->F, O->Start + O->Header.ImportOffs, O);
251
252     /* Read the exports */
253     ObjReadExports (L->F, O->Start + O->Header.ExportOffs, O);
254 }
255
256
257
258 static void LibReadIndex (Library* L)
259 /* Read the index of a library file */
260 {
261     unsigned ModuleCount, I;
262
263     /* Seek to the start of the index */
264     LibSeek (L, L->Header.IndexOffs);
265
266     /* Read the object file count and allocate memory */
267     ModuleCount = ReadVar (L->F);
268     CollGrow (&L->Modules, ModuleCount);
269
270     /* Read all entries in the index */
271     while (ModuleCount--) {
272         CollAppend (&L->Modules, ReadIndexEntry (L));
273     }
274
275     /* Walk over the index and read basic data for all object files in the
276      * library.
277      */
278     for (I = 0; I < CollCount (&L->Modules); ++I) {
279         ReadBasicData (L, CollAtUnchecked (&L->Modules, I));
280     }
281 }
282
283
284
285 /*****************************************************************************/
286 /*                             High level stuff                              */
287 /*****************************************************************************/
288
289
290
291 static void LibCheckExports (ObjData* O)
292 /* Check if the exports from this file can satisfy any import requests. If so,
293  * insert the imports and exports from this file and mark the file as added.
294  */
295 {
296     unsigned I;
297
298     /* Check all exports */
299     for (I = 0; I < CollCount (&O->Exports); ++I) {
300         const Export* E = CollConstAt (&O->Exports, I);
301         if (IsUnresolved (E->Name)) {
302            /* We need this module, insert the imports and exports */
303             O->Flags |= OBJ_REF;
304             InsertObjGlobals (O);
305             break;
306         }
307     }
308 }
309
310
311
312 static void LibOpen (FILE* F, const char* Name)
313 /* Open the library for use */
314 {
315     /* Create a new library structure */
316     Library* L = NewLibrary (F, Name);
317
318     /* Read the remaining header fields (magic is already read) */
319     LibReadHeader (L);
320
321     /* Seek to the index position and read the index */
322     LibReadIndex (L);
323
324     /* Add the library to the list of open libraries */
325     CollAppend (&OpenLibs, L);
326 }
327
328
329
330 static void LibResolve (void)
331 /* Resolve all externals from the list of all currently open libraries */
332 {
333     unsigned I, J;
334     unsigned Additions;
335
336     /* Walk repeatedly over all open libraries until there's nothing more
337      * to add.
338      */
339     do {
340
341         Additions = 0;
342
343         /* Walk over all libraries */
344         for (I = 0; I < CollCount (&OpenLibs); ++I) {
345
346             /* Get the next library */
347             Library* L = CollAt (&OpenLibs, I);
348
349             /* Walk through all modules in this library and check for each
350              * module if there are unresolved externals in existing modules
351              * that may be resolved by adding the module.
352              */
353             for (J = 0; J < CollCount (&L->Modules); ++J) {
354
355                 /* Get the next module */
356                 ObjData* O = CollAtUnchecked (&L->Modules, J);
357
358                 /* We only need to check this module if it wasn't added before */
359                 if ((O->Flags & OBJ_REF) == 0) {
360                     LibCheckExports (O);
361                     if (O->Flags & OBJ_REF) {
362                         /* The routine added the file */
363                         ++Additions;
364                     }
365                 }
366             }
367         }
368
369     } while (Additions > 0);
370
371     /* We do know now which modules must be added, so we can load the data
372      * for these modues into memory. Since we're walking over all modules
373      * anyway, we will also remove data for unneeded modules.
374      */
375     for (I = 0; I < CollCount (&OpenLibs); ++I) {
376
377         /* Get the next library */
378         Library* L = CollAt (&OpenLibs, I);
379
380         /* Walk over all modules in this library and add the files list and
381          * sections for all referenced modules.
382          */
383         J = 0;
384         while (J < CollCount (&L->Modules)) {
385
386             /* Get the object data */
387             ObjData* O = CollAtUnchecked (&L->Modules, J);
388
389             /* Is this object file referenced? */
390             if (O->Flags & OBJ_REF) {
391
392                 /* Seek to the start of the debug info and read the debug info */
393                 ObjReadDbgSyms (L->F, O->Start + O->Header.DbgSymOffs, O);
394
395                 /* Read the assertions from the object file */
396                 ObjReadAssertions (L->F, O->Start + O->Header.AssertOffs, O);
397
398                 /* Seek to the start of the segment list and read the segments.
399                  * This must be late, since the data here may reference other
400                  * stuff.
401                  */
402                 ObjReadSections (L->F, O->Start + O->Header.SegOffs, O);
403
404                 /* Read the scope table from the object file. Scopes reference
405                  * segments, so we must read them after the sections.
406                  */
407                 ObjReadScopes (L->F, O->Start + O->Header.ScopeOffs, O);
408
409                 /* All references to strings are now resolved, so we can delete
410                  * the module string pool.
411                  */
412                 FreeObjStrings (O);
413
414                 /* Insert the object into the list of all used object files */
415                 InsertObjData (O);
416
417                 /* Process next object file in library */
418                 ++J;
419
420             } else {
421
422                 /* Unreferenced object file, remove it */
423                 FreeObjData (O);
424                 CollDelete (&L->Modules, J);
425
426             }
427         }
428
429         /* If we have referenced modules in this library, assign it an id
430          * (which is the index in the library collection) and keep it.
431          */
432         if (CollCount (&L->Modules) > 0) {
433             CloseLibrary (L);
434             L->Id = CollCount (&LibraryList);
435             CollAppend (&LibraryList, L);
436         } else {
437             /* Delete the library */
438             FreeLibrary (L);
439             CollDelete (&OpenLibs, I);
440         }
441     }
442
443     /* We're done with all open libraries, clear the OpenLibs collection */
444     CollDeleteAll (&OpenLibs);
445 }
446
447
448
449 void LibAdd (FILE* F, const char* Name)
450 /* Add files from the library to the list if there are references that could
451  * be satisfied.
452  */
453 {
454     /* Add the library to the list of open libraries */
455     LibOpen (F, Name);
456
457     /* If there is no library group open, just resolve all open symbols and
458      * close the library. Otherwise we will do nothing because resolving will
459      * be done when the group is closed.
460      */
461     if (!Grouping) {
462         LibResolve ();
463     }
464 }
465
466
467
468 void LibStartGroup (void)
469 /* Start a library group. Objects within a library group may reference each
470  * other, and libraries are searched repeatedly until all references are
471  * satisfied.
472  */
473 {
474     /* We cannot already have a group open */
475     if (Grouping) {
476         Error ("There's already a library group open");
477     }
478
479     /* Start a new group */
480     Grouping = 1;
481 }
482
483
484
485 void LibEndGroup (void)
486 /* End a library group and resolve all open references. Objects within a
487  * library group may reference each other, and libraries are searched
488  * repeatedly until all references are satisfied.
489  */
490 {
491     /* We must have a library group open */
492     if (!Grouping) {
493         Error ("There's no library group open");
494     }
495
496     /* Resolve symbols, end the group */
497     LibResolve ();
498     Grouping = 0;
499 }
500
501
502
503 void LibCheckGroup (void)
504 /* Check if there are open library groups */
505 {
506     if (Grouping) {
507         Error ("Library group was never closed");
508     }
509 }
510
511
512
513 const char* GetLibFileName (const Library* L)
514 /* Get the name of a library */
515 {
516     return GetString (L->Name);
517 }
518
519
520
521 unsigned GetLibId (const Library* L)
522 /* Get the id of a library file. */
523 {
524     return L->Id;
525 }
526
527
528
529 unsigned LibraryCount (void)
530 /* Return the total number of libraries */
531 {
532     return CollCount (&LibraryList);
533 }
534
535
536
537 void PrintDbgLibraries (FILE* F)
538 /* Output the libraries to a debug info file */
539 {
540     unsigned I;
541
542     /* Output information about all libraries */
543     for (I = 0; I < CollCount (&LibraryList); ++I) {
544         /* Get the library */
545         const Library* L = CollAtUnchecked (&LibraryList, I);
546
547         /* Output the info */
548         fprintf (F, "lib\tid=%u,name=\"%s\"\n", L->Id, GetString (L->Name));
549     }
550 }
551
552
553
554