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