1 /*****************************************************************************/
5 /* Library data structures and helpers for the ld65 linker */
9 /* (C) 1998-2011, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
59 /*****************************************************************************/
61 /*****************************************************************************/
65 /* Library data structure */
66 typedef struct Library 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 */
75 /* List of open libraries */
76 static Collection OpenLibs = STATIC_COLLECTION_INITIALIZER;
78 /* List of used libraries */
79 static Collection LibraryList = STATIC_COLLECTION_INITIALIZER;
81 /* Flag for library grouping */
82 static int Grouping = 0;
86 /*****************************************************************************/
88 /*****************************************************************************/
92 static Library* NewLibrary (FILE* F, const char* Name)
93 /* Create a new Library structure and return it */
96 Library* L = xmalloc (sizeof (*L));
98 /* Initialize the fields */
100 L->Name = GetStringId (Name);
102 L->Modules = EmptyCollection;
104 /* Return the new struct */
110 static void CloseLibrary (Library* L)
111 /* Close a library file and remove the list of modules */
113 /* Close the library file */
114 if (fclose (L->F) != 0) {
115 Error ("Error closing `%s': %s", GetString (L->Name), strerror (errno));
122 static void FreeLibrary (Library* L)
123 /* Free a library structure */
125 /* Close the library */
128 /* Free the module index */
129 DoneCollection (&L->Modules);
131 /* Free the library structure */
137 /*****************************************************************************/
138 /* Reading file data structures */
139 /*****************************************************************************/
143 static void LibSeek (Library* L, unsigned long Offs)
144 /* Do a seek in the library checking for errors */
146 if (fseek (L->F, Offs, SEEK_SET) != 0) {
147 Error ("Seek error in `%s' (%lu): %s",
148 GetString (L->Name), Offs, strerror (errno));
154 static void LibReadHeader (Library* L)
155 /* Read a library header */
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));
163 L->Header.Flags = Read16 (L->F);
164 L->Header.IndexOffs = Read32 (L->F);
169 static void LibReadObjHeader (Library* L, ObjData* O)
170 /* Read the header of the object file checking the signature */
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));
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));
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);
207 static ObjData* ReadIndexEntry (Library* L)
208 /* Read one entry in the index */
210 /* Create a new entry and insert it into the list */
211 ObjData* O = NewObjData ();
213 /* Remember from which library this module is */
217 O->Name = ReadStr (L->F);
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 */
231 static void ReadBasicData (Library* L, ObjData* O)
232 /* Read basic data for an object file that is necessary to resolve external
236 /* Seek to the start of the object file and read the header */
237 LibSeek (L, O->Start);
238 LibReadObjHeader (L, O);
240 /* Read the string pool */
241 ObjReadStrPool (L->F, O->Start + O->Header.StrPoolOffs, O);
243 /* Read the files list */
244 ObjReadFiles (L->F, O->Start + O->Header.FileOffs, O);
246 /* Read the line infos */
247 ObjReadLineInfos (L->F, O->Start + O->Header.LineInfoOffs, O);
249 /* Read the imports */
250 ObjReadImports (L->F, O->Start + O->Header.ImportOffs, O);
252 /* Read the exports */
253 ObjReadExports (L->F, O->Start + O->Header.ExportOffs, O);
258 static void LibReadIndex (Library* L)
259 /* Read the index of a library file */
261 unsigned ModuleCount, I;
263 /* Seek to the start of the index */
264 LibSeek (L, L->Header.IndexOffs);
266 /* Read the object file count and allocate memory */
267 ModuleCount = ReadVar (L->F);
268 CollGrow (&L->Modules, ModuleCount);
270 /* Read all entries in the index */
271 while (ModuleCount--) {
272 CollAppend (&L->Modules, ReadIndexEntry (L));
275 /* Walk over the index and read basic data for all object files in the
278 for (I = 0; I < CollCount (&L->Modules); ++I) {
279 ReadBasicData (L, CollAtUnchecked (&L->Modules, I));
285 /*****************************************************************************/
286 /* High level stuff */
287 /*****************************************************************************/
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.
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 */
304 InsertObjGlobals (O);
312 static void LibOpen (FILE* F, const char* Name)
313 /* Open the library for use */
315 /* Create a new library structure */
316 Library* L = NewLibrary (F, Name);
318 /* Read the remaining header fields (magic is already read) */
321 /* Seek to the index position and read the index */
324 /* Add the library to the list of open libraries */
325 CollAppend (&OpenLibs, L);
330 static void LibResolve (void)
331 /* Resolve all externals from the list of all currently open libraries */
336 /* Walk repeatedly over all open libraries until there's nothing more
343 /* Walk over all libraries */
344 for (I = 0; I < CollCount (&OpenLibs); ++I) {
346 /* Get the next library */
347 Library* L = CollAt (&OpenLibs, I);
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.
353 for (J = 0; J < CollCount (&L->Modules); ++J) {
355 /* Get the next module */
356 ObjData* O = CollAtUnchecked (&L->Modules, J);
358 /* We only need to check this module if it wasn't added before */
359 if ((O->Flags & OBJ_REF) == 0) {
361 if (O->Flags & OBJ_REF) {
362 /* The routine added the file */
369 } while (Additions > 0);
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.
375 for (I = 0; I < CollCount (&OpenLibs); ++I) {
377 /* Get the next library */
378 Library* L = CollAt (&OpenLibs, I);
380 /* Walk over all modules in this library and add the files list and
381 * sections for all referenced modules.
384 while (J < CollCount (&L->Modules)) {
386 /* Get the object data */
387 ObjData* O = CollAtUnchecked (&L->Modules, J);
389 /* Is this object file referenced? */
390 if (O->Flags & OBJ_REF) {
392 /* Seek to the start of the debug info and read the debug info */
393 ObjReadDbgSyms (L->F, O->Start + O->Header.DbgSymOffs, O);
395 /* Read the assertions from the object file */
396 ObjReadAssertions (L->F, O->Start + O->Header.AssertOffs, O);
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
402 ObjReadSections (L->F, O->Start + O->Header.SegOffs, O);
404 /* Read the scope table from the object file. Scopes reference
405 * segments, so we must read them after the sections.
407 ObjReadScopes (L->F, O->Start + O->Header.ScopeOffs, O);
409 /* All references to strings are now resolved, so we can delete
410 * the module string pool.
414 /* Insert the object into the list of all used object files */
417 /* Process next object file in library */
422 /* Unreferenced object file, remove it */
424 CollDelete (&L->Modules, J);
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.
432 if (CollCount (&L->Modules) > 0) {
434 L->Id = CollCount (&LibraryList);
435 CollAppend (&LibraryList, L);
437 /* Delete the library */
439 CollDelete (&OpenLibs, I);
443 /* We're done with all open libraries, clear the OpenLibs collection */
444 CollDeleteAll (&OpenLibs);
449 void LibAdd (FILE* F, const char* Name)
450 /* Add files from the library to the list if there are references that could
454 /* Add the library to the list of open libraries */
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.
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
474 /* We cannot already have a group open */
476 Error ("There's already a library group open");
479 /* Start a new group */
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.
491 /* We must have a library group open */
493 Error ("There's no library group open");
496 /* Resolve symbols, end the group */
503 void LibCheckGroup (void)
504 /* Check if there are open library groups */
507 Error ("Library group was never closed");
513 const char* GetLibFileName (const Library* L)
514 /* Get the name of a library */
516 return GetString (L->Name);
521 unsigned GetLibId (const Library* L)
522 /* Get the id of a library file. */
529 unsigned LibraryCount (void)
530 /* Return the total number of libraries */
532 return CollCount (&LibraryList);
537 void PrintDbgLibraries (FILE* F)
538 /* Output the libraries to a debug info file */
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);
547 /* Output the info */
548 fprintf (F, "lib\tid=%u,name=\"%s\"\n", L->Id, GetString (L->Name));