]> git.sur5r.net Git - cc65/blob - src/ld65/library.c
Corrected indentation - no code change.
[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-2010, 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 "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 < CollCount (&O->Exports); ++I) {
263         const Export* E = CollConstAt (&O->Exports, I);
264         if (IsUnresolved (E->Name)) {
265            /* We need this module, insert the imports and exports */
266             O->Flags |= OBJ_REF;
267             InsertObjGlobals (O);
268             break;
269         }
270     }
271 }
272
273
274
275 static void LibOpen (FILE* F, const char* Name)
276 /* Open the library for use */
277 {
278     /* Create a new library structure */
279     Library* L = NewLibrary (F, Name);
280
281     /* Read the remaining header fields (magic is already read) */
282     LibReadHeader (L);
283
284     /* Seek to the index position and read the index */
285     LibReadIndex (L);
286
287     /* Add the library to the list of open libraries */
288     CollAppend (&OpenLibs, L);
289 }
290
291
292
293 static void LibResolve (void)
294 /* Resolve all externals from the list of all currently open libraries */
295 {
296     unsigned I, J;
297     unsigned Additions;
298
299     /* Walk repeatedly over all open libraries until there's nothing more
300      * to add.
301      */
302     do {
303
304         Additions = 0;
305
306         /* Walk over all libraries */
307         for (I = 0; I < CollCount (&OpenLibs); ++I) {
308
309             /* Get the next library */
310             Library* L = CollAt (&OpenLibs, I);
311
312             /* Walk through all modules in this library and check for each
313              * module if there are unresolved externals in existing modules
314              * that may be resolved by adding the module.
315              */
316             for (J = 0; J < L->ModCount; ++J) {
317
318                 /* Get the next module */
319                 ObjData* O = L->Modules[J];
320
321                 /* We only need to check this module if it wasn't added before */
322                 if ((O->Flags & OBJ_REF) == 0) {
323                     LibCheckExports (O);
324                     if (O->Flags & OBJ_REF) {
325                         /* The routine added the file */
326                         ++Additions;
327                     }
328                 }
329             }
330         }
331
332     } while (Additions > 0);
333
334     /* We do know now which modules must be added, so we can load the data
335      * for these modues into memory. Since we're walking over all modules
336      * anyway, we will also remove data for unneeded modules.
337      */
338     for (I = 0; I < CollCount (&OpenLibs); ++I) {
339
340         /* Get the next library */
341         Library* L = CollAt (&OpenLibs, I);
342
343         /* Walk over all modules in this library and add the files list and
344          * sections for all referenced modules.
345          */
346         for (J = 0; J < L->ModCount; ++J) {
347
348             /* Get the object data */
349             ObjData* O = L->Modules[J];
350
351             /* Is this object file referenced? */
352             if (O->Flags & OBJ_REF) {
353
354                 /* Seek to the start of the object file and read the header */
355                 LibSeek (L, O->Start);
356                 LibReadObjHeader (L, O);
357
358                 /* Seek to the start of the files list and read the files list */
359                 ObjReadFiles (L->F, O->Start + O->Header.FileOffs, O);
360
361                 /* Seek to the start of the debug info and read the debug info */
362                 ObjReadDbgSyms (L->F, O->Start + O->Header.DbgSymOffs, O);
363
364                 /* Seek to the start of the line infos and read them */
365                 ObjReadLineInfos (L->F, O->Start + O->Header.LineInfoOffs, O);
366
367                 /* Read the assertions from the object file */
368                 ObjReadAssertions (L->F, O->Start + O->Header.AssertOffs, O);
369
370                 /* Read the scope table from the object file */
371                 ObjReadScopes (L->F, O->Start + O->Header.ScopeOffs, O);
372
373                 /* Seek to the start of the segment list and read the segments.
374                  * This must be last, since the data here may reference other
375                  * stuff.
376                  */
377                 ObjReadSections (L->F, O->Start + O->Header.SegOffs, O);
378
379                 /* Remember from which library this module is */
380                 O->LibName = L->Name;
381
382                 /* All references to strings are now resolved, so we can delete
383                  * the module string pool.
384                  */
385                 FreeObjStrings (O);
386
387                 /* Insert the object into the list of all used object files */
388                 InsertObjData (O);
389
390             } else {
391
392                 /* Unreferenced object file, remove it */
393                 FreeObjData (O);
394
395             }
396         }
397
398         /* Close the file and delete the library data */
399         FreeLibrary (L);
400     }
401
402     /* We're done with all open libraries, clear the OpenLibs collection */
403     CollDeleteAll (&OpenLibs);
404 }
405
406
407
408 void LibAdd (FILE* F, const char* Name)
409 /* Add files from the library to the list if there are references that could
410  * be satisfied.
411  */
412 {
413     /* Add the library to the list of open libraries */
414     LibOpen (F, Name);
415
416     /* If there is no library group open, just resolve all open symbols and
417      * close the library. Otherwise we will do nothing because resolving will
418      * be done when the group is closed.
419      */
420     if (!Grouping) {
421         LibResolve ();
422     }
423 }
424
425
426
427 void LibStartGroup (void)
428 /* Start a library group. Objects within a library group may reference each
429  * other, and libraries are searched repeatedly until all references are
430  * satisfied.
431  */
432 {
433     /* We cannot already have a group open */
434     if (Grouping) {
435         Error ("There's already a library group open");
436     }
437
438     /* Start a new group */
439     Grouping = 1;
440 }
441
442
443
444 void LibEndGroup (void)
445 /* End a library group and resolve all open references. Objects within a
446  * library group may reference each other, and libraries are searched
447  * repeatedly until all references are satisfied.
448  */
449 {
450     /* We must have a library group open */
451     if (!Grouping) {
452         Error ("There's no library group open");
453     }
454
455     /* Resolve symbols, end the group */
456     LibResolve ();
457     Grouping = 0;
458 }
459
460
461
462 void LibCheckGroup (void)
463 /* Check if there are open library groups */
464 {
465     if (Grouping) {
466         Error ("Library group was never closed");
467     }
468 }
469
470
471