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