3 Copyright (C) 1989-1995 Alan R. Baldwin
4 721 Berkeley St., Kent, Ohio 44240
5 Copyright (C) 2008-2009 Borut Razem, borut dot razem at siol dot net
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 * With contributions for the
23 * object libraries from
25 * kenh@cmf.nrl.navy.mil
30 * Extensions: P. Felber
45 * The module lklibr.c contains the functions which
46 * (1) specify the path(s) to library files [.LIB]
47 * (2) specify the library file(s) [.LIB] to search
48 * (3) search the library files for specific symbols
49 * and link the module containing this symbol
51 * lklibr.c contains the following functions:
62 #define EQ(A,B) !strcmp((A),(B))
63 #define NELEM(x) (sizeof (x) / sizeof (*x))
66 /* First entry in the library object symbol cache */
67 pmlibraryfile libr = NULL;
69 int buildlibraryindex (void);
70 void freelibraryindex (void);
73 struct aslib_target *aslib_targets[] = {
74 &aslib_target_sdcclib,
79 /*)Function VOID addpath()
81 * The function addpath() creates a linked structure containing
82 * the paths to various object module library files.
85 * lbpath *lbph pointer to new path structure
86 * lbpath *lbp temporary pointer
89 * lbpath *lbphead The pointer to the first
93 * char getnb() lklex.c
94 * VOID * new() lksym.c
95 * int strlen() c_library
96 * char * strcpy() c_library
97 * VOID unget() lklex.c
100 * An lbpath structure may be created.
106 struct lbpath *lbph, *lbp;
108 lbph = (struct lbpath *) new (sizeof (struct lbpath));
123 lbph->path = strdup (ip);
126 /*)Function VOID addlib()
128 * The function addlib() tests for the existance of a
129 * library path structure to determine the method of
130 * adding this library file to the library search structure.
132 * This function calls the function addfile() to actually
133 * add the library file to the search list.
136 * lbpath *lbph pointer to path structure
139 * lbpath *lbphead The pointer to the first
141 * ip a pointer to the library name
144 * VOID addfile() lklibr.c
145 * char getnb() lklex.c
146 * VOID unget() lklex.c
149 * The function addfile() may add the file to
150 * the library search list.
163 foundcount = addfile (NULL, ip);
167 for (lbph = lbphead; lbph; lbph = lbph->next)
169 foundcount += addfile (lbph->path, ip);
174 fprintf (stderr, "?ASlink-Warning-Couldn't find library '%s'\n", ip);
178 /*)Function int addfile(path,libfil)
180 * char *path library path specification
181 * char *libfil library file specification
183 * The function addfile() searches for the library file
184 * by concatenating the path and libfil specifications.
185 * if the library is found, an lbname structure is created
186 * and linked to any previously defined structures. This
187 * linked list is used by the function fndsym() to attempt
188 * to find any undefined symbols.
190 * The function does not give report an error on invalid
191 * path / file specifications or if the file is not found.
194 * lbname *lbnh pointer to new name structure
195 * lbname *lbn temporary pointer
198 * lbname *lbnhead The pointer to the first
202 * char getnb() lklex.c
203 * VOID * new() lksym.c
204 * int strlen() c_library
205 * char * strcpy() c_library
206 * VOID unget() lklex.c
209 * An lbname structure may be created.
212 * 1: the library was found
213 * 0: the library was not found
217 addfile (char *path, char *libfil)
221 struct lbname *lbnh, *lbn;
228 str = (char *) new (strlen (path) + strlen (libfil) + 6);
231 if (strlen (str) && (str[strlen (str) - 1] != '/') && (str[strlen (str) - 1] != LKDIRSEP))
233 strcat (str, LKDIRSEPSTR);
239 str = (char *) new (strlen (libfil) + 5);
243 if ((libfil[0] == '/') || (libfil[0] == LKDIRSEP))
250 strcat (str, libfil);
251 if (strchr (libfil, FSEPX) == NULL)
253 sprintf (&str[strlen (str)], "%clib", FSEPX);
256 fp = fopen (str, "rb");
259 /*Ok, that didn't work. Try with the 'libfil' name only */
264 fp = fopen (libfil, "rb");
267 /*Bingo! 'libfil' is the absolute path of the library */
268 strcpy (str, libfil);
269 path = NULL; /*This way 'libfil' and 'path' will be rebuilt from 'str' */
275 /*'path' can not be null since it is needed to find the object files associated with
276 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
277 That way putting 'path' and 'libfil' together will result into the original filepath
278 as contained in 'str'. */
281 for (j = strlen (path) - 1; j >= 0; j--)
283 if ((path[j] == '/') || (path[j] == LKDIRSEP))
285 strcpy (libfil, &path[j + 1]);
297 lbnh = (struct lbname *) new (sizeof (struct lbname));
313 lbnh->libfil = strdup (libfil);
324 /*)Function VOID search()
326 * The function search() looks through all the symbol tables
327 * at the end of pass 1. If any undefined symbols are found
328 * then the function fndsym() is called. Function fndsym()
329 * searches any specified library files to automagically
330 * import the object modules containing the needed symbol.
332 * After a symbol is found and imported by the function
333 * fndsym() the symbol tables are again searched. The
334 * symbol tables are search until no more symbols can be
335 * resolved within the library files. This ensures that
336 * back references from one library module to another are
340 * int i temporary counter
341 * sym *sp pointer to a symbol structure
342 * int symfnd found a symbol flag
345 * sym *symhash[] array of pointers to symbol tables
348 * int fndsym() lklibr.c
351 * If a symbol is found then the library object module
352 * containing the symbol will be imported and linked.
358 register struct sym *sp;
359 register int i, symfnd;
362 * Look for undefined symbols. Keep
363 * searching until no more symbols are resolved.
370 * Look through all the symbols
372 for (i = 0; i < NHASH; ++i)
377 /* If we find an undefined symbol
378 * (one where S_DEF is not set), then
379 * try looking for it. If we find it
380 * in any of the libraries then
381 * increment symfnd. This will force
382 * another pass of symbol searching and
383 * make sure that back references work.
385 if ((sp->s_type & S_DEF) == 0)
387 if (fndsym (sp->s_id))
398 /*)Function VOID fndsym(name)
400 * char *name symbol name to find
402 * The function fndsym() searches through all combinations of the
403 * library path specifications (input by the -k option) and the
404 * library file specifications (input by the -l option) that
405 * lead to an existing file.
407 * The file specicifation may be formed in one of two ways:
409 * (1) If the library file contained an absolute
410 * path/file specification then this becomes filspc.
413 * (2) If the library file contains a relative path/file
414 * specification then the concatenation of the path
415 * and this file specification becomes filspc.
418 * The structure lbfile is created for the first library
419 * object file which contains the definition for the
420 * specified undefined symbol.
422 * If the library file [.LIB] contains file specifications for
423 * non existant files, no errors are returned.
426 * char buf[] [.REL] file input line
427 * char c [.REL] file input character
428 * FILE *fp file handle for object file
429 * lbfile *lbf temporary pointer
430 * lbfile *lbfh pointer to lbfile structure
431 * FILE *libfp file handle for library file
432 * lbname *lbnh pointer to lbname structure
433 * char *path file specification path
434 * char relfil[] [.REL] file specification
435 * char *str combined path and file specification
436 * char symname[] [.REL] file symbol string
439 * lbname *lbnhead The pointer to the first
441 * lbfile *lbfhead The pointer to the first
445 * int fclose() c_library
446 * FILE *fopen() c_library
447 * VOID free() c_library
448 * char getnb() lklex.c
449 * VOID lkexit() lkmain.c
450 * VOID loadfile() lklibr.c
451 * VOID * new() lksym.c
452 * char * sprintf() c_library
453 * int sscanf() c_library
454 * char * strcat() c_library
455 * char * strchr() c_library
456 * char * strcpy() c_library
457 * int strlen() c_library
458 * int strncmp() c_library
459 * VOID unget() lklex.c
462 * If the symbol is found then a new lbfile structure
463 * is created and added to the linked list of lbfile
464 * structures. The file containing the found symbol
472 struct lbfile *lbfh, *lbf;
473 pmlibraryfile ThisLibr;
474 pmlibrarysymbol ThisSym = NULL;
476 pmlibraryfile FirstFound;
479 D ("Searching symbol: %s\n", name);
481 /* Build the index if this is the first call to fndsym */
483 buildlibraryindex ();
485 /* Iterate through all library object files */
486 FirstFound = libr; /* So gcc stops whining */
487 for (ThisLibr = libr; ThisLibr != NULL; ThisLibr = ThisLibr->next)
489 /* Iterate through all symbols in an object file */
490 for (ThisSym = ThisLibr->symbols; ThisSym != NULL; ThisSym = ThisSym->next)
492 if (!strcmp (ThisSym->name, name))
494 if ((!ThisLibr->loaded) && (numfound == 0))
496 /* Object file is not loaded - add it to the list */
497 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
504 for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
509 lbfh->libspc = ThisLibr->libspc;
510 lbfh->filspc = ThisLibr->filspc;
511 lbfh->relfil = strdup (ThisLibr->relfil);
512 lbfh->offset = ThisLibr->offset;
513 lbfh->type = ThisLibr->type;
515 (*aslib_targets[lbfh->type]->loadfile) (lbfh);
517 ThisLibr->loaded = 1;
523 FirstFound = ThisLibr;
527 char absPath1[PATH_MAX];
528 char absPath2[PATH_MAX];
529 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
532 _fullpath (absPath1, FirstFound->libspc, PATH_MAX);
533 _fullpath (absPath2, ThisLibr->libspc, PATH_MAX);
534 for (j = 0; absPath1[j] != 0; j++)
535 absPath1[j] = tolower ((unsigned char) absPath1[j]);
536 for (j = 0; absPath2[j] != 0; j++)
537 absPath2[j] = tolower ((unsigned char) absPath2[j]);
539 realpath (FirstFound->libspc, absPath1);
540 realpath (ThisLibr->libspc, absPath2);
542 if (!(EQ (absPath1, absPath2) && EQ (FirstFound->relfil, ThisLibr->relfil)))
546 fprintf (stderr, "?ASlink-Warning-Definition of public symbol '%s'" " found more than once:\n", name);
547 fprintf (stderr, " Library: '%s', Module: '%s'\n", FirstFound->libspc, FirstFound->relfil);
549 fprintf (stderr, " Library: '%s', Module: '%s'\n", ThisLibr->libspc, ThisLibr->relfil);
566 add_sybmol (const char *sym, void *param)
568 struct add_sym_s *as = (struct add_sym_s *) param;
569 pmlibrarysymbol ps = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
571 D (" Indexing symbol: %s\n", sym);
575 ps->name = strdup (sym);
579 as->pls = as->plf->symbols = ps;
584 as->pls = as->pls->next;
591 add_rel_index (FILE * fp, long size, pmlibraryfile This)
595 as.pls = This->symbols;
597 assert (This->symbols == NULL);
599 enum_symbols (fp, size, &add_sybmol, &as);
604 /* buildlibraryindex - build an in-memory cache of the symbols contained in
608 buildlibraryindex (void)
610 pmlibraryfile This = NULL;
614 * Search through every library in the linked list "lbnhead".
616 for (lbnh = lbnhead; lbnh; lbnh = lbnh->next)
621 D ("Indexing library: %s\n", lbnh->libspc);
623 if ((libfp = fopen (lbnh->libspc, "rb")) == NULL)
625 fprintf (stderr, "?ASlink-Error-Cannot open library file %s\n", lbnh->libspc);
629 for (i = 0; i < NELEM (aslib_targets); ++i)
631 if ((*aslib_targets[i]->is_lib) (libfp))
633 This = (*aslib_targets[i]->buildlibraryindex) (lbnh, libfp, This, i);
638 if (i >= NELEM (aslib_targets))
639 fprintf (stderr, "?ASlink-Error-Unknown library file format %s\n", lbnh->libspc);
647 /* Release all memory allocated for the in-memory library index */
649 freelibraryindex (void)
651 pmlibraryfile ThisLibr, ThisLibr2Free;
652 pmlibrarysymbol ThisSym, ThisSym2Free;
658 ThisSym = ThisLibr->symbols;
662 free (ThisSym->name);
663 ThisSym2Free = ThisSym;
664 ThisSym = ThisSym->next;
667 free (ThisLibr->filspc);
668 free (ThisLibr->relfil);
669 ThisLibr2Free = ThisLibr;
670 ThisLibr = ThisLibr->next;
671 free (ThisLibr2Free);
690 load_sybmol (const char *sym, void *params)
692 struct load_sym_s *ls = (struct load_sym_s *) params;
694 D (" Symbol: %s\n", sym);
696 if (strcmp (ls->name, sym) == 0)
698 struct lbfile *lbfh, *lbf;
700 D (" Symbol %s found in module %s!\n", sym, ls->relfil);
702 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
703 lbfh->libspc = ls->lbnh->libspc;
704 lbfh->relfil = strdup (ls->relfil);
705 lbfh->filspc = strdup (ls->filspc);
706 lbfh->offset = ls->offset;
707 lbfh->type = ls->type;
713 for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
717 (*aslib_targets[ls->type]->loadfile) (lbfh);
725 /*)Function int is_module_loaded(filspc)
727 * If this module has been already loaded
731 is_module_loaded (const char *filspc)
735 for (lbf = lbfhead; lbf != NULL; lbf = lbf->next)
737 if (EQ (filspc, lbf->filspc))
739 D (" Module %s already loaded!\n", filspc);
740 return 1; /* Module already loaded */
747 add_rel_file (const char *name, struct lbname *lbnh, const char *relfil,
748 const char *filspc, int offset, FILE * fp, long size, int type)
750 struct load_sym_s ls;
752 /* If this module has been loaded already don't load it again. */
753 if (is_module_loaded (filspc))
764 return enum_symbols (fp, size, &load_sybmol, &ls);
769 fndsym (const char *name)
776 * Search through every library in the linked list "lbnhead".
779 D ("Searching symbol: %s\n", name);
781 for (lbnh = lbnhead; lbnh; lbnh = lbnh->next)
785 D ("Library: %s\n", lbnh->libspc);
787 if ((libfp = fopen (lbnh->libspc, "rb")) == NULL)
789 fprintf (stderr, "?ASlink-Error-Cannot open library file %s\n", lbnh->libspc);
793 for (i = 0; i < NELEM (aslib_targets); ++i)
795 if ((*aslib_targets[i]->is_lib) (libfp))
797 ret = (*aslib_targets[i]->fndsym) (name, lbnh, libfp, i);
802 if (i >= NELEM (aslib_targets))
803 fprintf (stderr, "?ASlink-Error-Unknown library file format %s\n", lbnh->libspc);
810 } /* Ends good open of libr file */
813 #endif /* INDEXLIB */
815 /*)Function VOID library()
817 * The function library() links all the library object files
818 * contained in the lbfile structures.
821 * lbfile *lbfh pointer to lbfile structure
824 * lbfile *lbfhead pointer to first lbfile structure
827 * VOID loadfile lklibr.c
830 * Links all files contained in the lbfile structures.
838 for (lbfh = lbfhead; lbfh; lbfh = lbfh->next)
839 (*aslib_targets[lbfh->type]->loadfile) (lbfh);