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);
203 O->Header.SpanOffs = Read32 (L->F);
204 O->Header.SpanSize = Read32 (L->F);
209 static ObjData* ReadIndexEntry (Library* L)
210 /* Read one entry in the index */
212 /* Create a new entry and insert it into the list */
213 ObjData* O = NewObjData ();
215 /* Remember from which library this module is */
219 O->Name = ReadStr (L->F);
221 /* Module flags/MTime/Start/Size */
222 O->Flags = Read16 (L->F);
223 O->MTime = Read32 (L->F);
224 O->Start = Read32 (L->F);
225 Read32 (L->F); /* Skip Size */
233 static void ReadBasicData (Library* L, ObjData* O)
234 /* Read basic data for an object file that is necessary to resolve external
238 /* Seek to the start of the object file and read the header */
239 LibSeek (L, O->Start);
240 LibReadObjHeader (L, O);
242 /* Read the string pool */
243 ObjReadStrPool (L->F, O->Start + O->Header.StrPoolOffs, O);
245 /* Read the files list */
246 ObjReadFiles (L->F, O->Start + O->Header.FileOffs, O);
248 /* Read the line infos */
249 ObjReadLineInfos (L->F, O->Start + O->Header.LineInfoOffs, O);
251 /* Read the imports */
252 ObjReadImports (L->F, O->Start + O->Header.ImportOffs, O);
254 /* Read the exports */
255 ObjReadExports (L->F, O->Start + O->Header.ExportOffs, O);
260 static void LibReadIndex (Library* L)
261 /* Read the index of a library file */
263 unsigned ModuleCount, I;
265 /* Seek to the start of the index */
266 LibSeek (L, L->Header.IndexOffs);
268 /* Read the object file count and allocate memory */
269 ModuleCount = ReadVar (L->F);
270 CollGrow (&L->Modules, ModuleCount);
272 /* Read all entries in the index */
273 while (ModuleCount--) {
274 CollAppend (&L->Modules, ReadIndexEntry (L));
277 /* Walk over the index and read basic data for all object files in the
280 for (I = 0; I < CollCount (&L->Modules); ++I) {
281 ReadBasicData (L, CollAtUnchecked (&L->Modules, I));
287 /*****************************************************************************/
288 /* High level stuff */
289 /*****************************************************************************/
293 static void LibCheckExports (ObjData* O)
294 /* Check if the exports from this file can satisfy any import requests. If so,
295 * insert the imports and exports from this file and mark the file as added.
300 /* Check all exports */
301 for (I = 0; I < CollCount (&O->Exports); ++I) {
302 const Export* E = CollConstAt (&O->Exports, I);
303 if (IsUnresolved (E->Name)) {
304 /* We need this module, insert the imports and exports */
306 InsertObjGlobals (O);
314 static void LibOpen (FILE* F, const char* Name)
315 /* Open the library for use */
317 /* Create a new library structure */
318 Library* L = NewLibrary (F, Name);
320 /* Read the remaining header fields (magic is already read) */
323 /* Seek to the index position and read the index */
326 /* Add the library to the list of open libraries */
327 CollAppend (&OpenLibs, L);
332 static void LibResolve (void)
333 /* Resolve all externals from the list of all currently open libraries */
338 /* Walk repeatedly over all open libraries until there's nothing more
345 /* Walk over all libraries */
346 for (I = 0; I < CollCount (&OpenLibs); ++I) {
348 /* Get the next library */
349 Library* L = CollAt (&OpenLibs, I);
351 /* Walk through all modules in this library and check for each
352 * module if there are unresolved externals in existing modules
353 * that may be resolved by adding the module.
355 for (J = 0; J < CollCount (&L->Modules); ++J) {
357 /* Get the next module */
358 ObjData* O = CollAtUnchecked (&L->Modules, J);
360 /* We only need to check this module if it wasn't added before */
361 if ((O->Flags & OBJ_REF) == 0) {
363 if (O->Flags & OBJ_REF) {
364 /* The routine added the file */
371 } while (Additions > 0);
373 /* We do know now which modules must be added, so we can load the data
374 * for these modues into memory. Since we're walking over all modules
375 * anyway, we will also remove data for unneeded modules.
377 for (I = 0; I < CollCount (&OpenLibs); ++I) {
379 /* Get the next library */
380 Library* L = CollAt (&OpenLibs, I);
382 /* Walk over all modules in this library and add the files list and
383 * sections for all referenced modules.
386 while (J < CollCount (&L->Modules)) {
388 /* Get the object data */
389 ObjData* O = CollAtUnchecked (&L->Modules, J);
391 /* Is this object file referenced? */
392 if (O->Flags & OBJ_REF) {
394 /* Seek to the start of the debug info and read the debug info */
395 ObjReadDbgSyms (L->F, O->Start + O->Header.DbgSymOffs, O);
397 /* Read the assertions from the object file */
398 ObjReadAssertions (L->F, O->Start + O->Header.AssertOffs, O);
400 /* Seek to the start of the segment list and read the segments.
401 * This must be late, since the data here may reference other
404 ObjReadSections (L->F, O->Start + O->Header.SegOffs, O);
406 /* Read the scope table from the object file. Scopes reference
407 * segments, so we must read them after the sections.
409 ObjReadScopes (L->F, O->Start + O->Header.ScopeOffs, O);
412 ObjReadSpans (L->F, O->Start + O->Header.SpanOffs, O);
414 /* All references to strings are now resolved, so we can delete
415 * the module string pool.
419 /* Insert the object into the list of all used object files */
422 /* Process next object file in library */
427 /* Unreferenced object file, remove it */
429 CollDelete (&L->Modules, J);
434 /* If we have referenced modules in this library, assign it an id
435 * (which is the index in the library collection) and keep it.
437 if (CollCount (&L->Modules) > 0) {
439 L->Id = CollCount (&LibraryList);
440 CollAppend (&LibraryList, L);
442 /* Delete the library */
444 CollDelete (&OpenLibs, I);
448 /* We're done with all open libraries, clear the OpenLibs collection */
449 CollDeleteAll (&OpenLibs);
454 void LibAdd (FILE* F, const char* Name)
455 /* Add files from the library to the list if there are references that could
459 /* Add the library to the list of open libraries */
462 /* If there is no library group open, just resolve all open symbols and
463 * close the library. Otherwise we will do nothing because resolving will
464 * be done when the group is closed.
473 void LibStartGroup (void)
474 /* Start a library group. Objects within a library group may reference each
475 * other, and libraries are searched repeatedly until all references are
479 /* We cannot already have a group open */
481 Error ("There's already a library group open");
484 /* Start a new group */
490 void LibEndGroup (void)
491 /* End a library group and resolve all open references. Objects within a
492 * library group may reference each other, and libraries are searched
493 * repeatedly until all references are satisfied.
496 /* We must have a library group open */
498 Error ("There's no library group open");
501 /* Resolve symbols, end the group */
508 void LibCheckGroup (void)
509 /* Check if there are open library groups */
512 Error ("Library group was never closed");
518 const char* GetLibFileName (const Library* L)
519 /* Get the name of a library */
521 return GetString (L->Name);
526 unsigned GetLibId (const Library* L)
527 /* Get the id of a library file. */
534 unsigned LibraryCount (void)
535 /* Return the total number of libraries */
537 return CollCount (&LibraryList);
542 void PrintDbgLibraries (FILE* F)
543 /* Output the libraries to a debug info file */
547 /* Output information about all libraries */
548 for (I = 0; I < CollCount (&LibraryList); ++I) {
549 /* Get the library */
550 const Library* L = CollAtUnchecked (&LibraryList, I);
552 /* Output the info */
553 fprintf (F, "lib\tid=%u,name=\"%s\"\n", L->Id, GetString (L->Name));