1 /* lkar.c - ar library format handling
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 3, 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, see <http://www.gnu.org/licenses/>. */
21 * With contributions for the
22 * object libraries from
24 * kenh@cmf.nrl.navy.mil
29 * Extensions: P. Felber
44 # define max(a,b) ((a) > (b) ? (a) : (b))
48 # define min(a,b) ((a) < (b) ? (a) : (b))
58 if (!(ret = fread (buf, 1, sizeof (buf), libfp) == sizeof (buf) && memcmp (buf, ARMAG, SARMAG) == 0))
65 static int sym_tab_size;
68 get_member_name (char *name, size_t *p_size, int allocate, FILE * libfp)
72 if (0 == memcmp (name, "#1/", 3))
75 size_t len = strtoul (&name [3], &p, 10);
78 /* BSD appends real file name to the file header */
84 char *n = (char *) malloc (len);
85 if (fread (n, 1, len, libfp) != len)
87 /* not an ar archive or broken ar archive */
95 /* just advance the file pointer */
96 fseek (libfp, len, SEEK_CUR);
102 /* not an ar archive or broken ar archive */
114 int name_offset = strtol (++name, &p, 0);
115 if (p != name && name_offset < sym_tab_size)
117 int len = p - name + 1;
118 while (len < AR_NAME_LEN && name[len++] == ' ')
120 if (len == AR_NAME_LEN)
124 /* long name: get it from the symbol table */
125 name = &sym_tab[name_offset];
126 for (p = name; *p != '/' && *p != '\n'; ++p)
127 assert (p < &sym_tab[sym_tab_size]);
129 if (p[0] != '/' || p[1] != '\n')
131 assert (p < &sym_tab[sym_tab_size]);
133 n = (char *) malloc (p - name + 1);
134 memcpy (n, name, p - name);
143 char *p = strrchr (name, '/');
148 while (name[++len] == ' ')
150 if (len == AR_NAME_LEN)
152 char *n = (char *) malloc (p - name + 1);
153 memcpy (n, name, p - name);
160 /* BSD formed member name:
161 trim trailing spaces */
164 p = name + AR_NAME_LEN;
165 while (*--p == ' ' && p >= name)
168 n = (char *) malloc (p - name + 1);
169 memcpy (n, name, p - name);
175 /* bad formed member name:
178 return strdup (name);
185 ar_get_header (struct ar_hdr *hdr, FILE * libfp, char **p_obj_name)
187 char header[ARHDR_LEN];
188 char buf[AR_DATE_LEN + 1];
192 if (fread (header, 1, sizeof (header), libfp) != sizeof (header)
193 || memcmp (header + AR_FMAG_OFFSET, ARFMAG, AR_FMAG_LEN) != 0)
195 /* not an ar archive */
199 memcpy (hdr->ar_name, &header[AR_NAME_OFFSET], AR_NAME_LEN);
200 hdr->ar_name[AR_NAME_LEN] = '\0';
202 memcpy (buf, &header[AR_DATE_OFFSET], AR_DATE_LEN);
203 buf[AR_DATE_LEN] = '\0';
204 hdr->ar_date = strtol (buf, NULL, 0);
206 memcpy (buf, &header[AR_UID_OFFSET], AR_GID_LEN);
207 buf[AR_GID_LEN] = '\0';
208 hdr->ar_uid = (uid_t) strtol (buf, NULL, 0);
210 memcpy (buf, &header[AR_GID_OFFSET], AR_DATE_LEN);
211 buf[AR_DATE_LEN] = '\0';
212 hdr->ar_gid = (gid_t) strtol (buf, NULL, 0);
214 memcpy (buf, &header[AR_MODE_OFFSET], AR_MODE_LEN);
215 buf[AR_MODE_LEN] = '\0';
216 hdr->ar_mode = (mode_t) strtoul (buf, NULL, 0);
218 memcpy (buf, &header[AR_SIZE_OFFSET], AR_SIZE_LEN);
219 buf[AR_SIZE_LEN] = '\0';
220 hdr->ar_size = strtol (buf, NULL, 0);
222 obj_name = get_member_name (hdr->ar_name, &size, p_obj_name != NULL, libfp);
224 if (p_obj_name != NULL)
225 *p_obj_name = obj_name;
227 /* treat BSD appended real file name as a part of the header */
228 hdr->ar_size -= size;
230 return size + ARHDR_LEN;
235 get_member_name_by_offset (FILE * fp, long offset)
240 fseek (fp, offset, SEEK_SET);
241 return (ar_get_header (&hdr, fp, &name) != 0) ? name : NULL;
245 find_member_by_offset (const char *libspc, long offset)
249 /* walk trough all archive members */
250 for (p = libr; p; p = p->next)
252 if (0 == strcmp (libspc, p->libspc) && p->offset == offset)
260 buildlibraryindex_ar (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int type)
266 /* walk trough all archive members */
267 while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0)
269 if (AR_IS_SYMBOL_TABLE (obj_name))
278 buf = (char *) new (hdr.ar_size);
280 if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
293 for (i = 0; i < nsym; ++i)
295 pmlibrarysymbol ThisSym;
304 ps += strlen (ps) + 1;
306 if ((entry = find_member_by_offset (lbnh->libspc, offset)) != NULL)
308 for (ThisSym = entry->symbols; ThisSym->next != NULL; ThisSym = ThisSym->next)
313 /* Opened OK - create a new libraryfile object for it */
316 assert (libr == NULL);
317 libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
321 This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
326 This->libspc = lbnh->libspc;
327 This->offset = offset;
328 This->relfil = get_member_name_by_offset (libfp, offset); /* member name */
329 This->filspc = strdup (This->relfil); /* member file name */
332 /* start a new linked list of symbols for this module. */
333 This->symbols = ThisSym = NULL;
337 ThisSym = This->symbols = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
340 ThisSym->next = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
341 ThisSym = ThisSym->next;
343 ThisSym->next = NULL;
348 fseek (libfp, pos, SEEK_SET);
351 else if (AR_IS_BSD_SYMBOL_TABLE (obj_name))
355 long nsym, tablesize;
360 buf = (char *) new (hdr.ar_size);
362 if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
370 tablesize = sgetl (buf);
371 nsym = tablesize / 8;
375 ps = po + tablesize + 4;
377 for (i = 0; i < nsym; ++i)
379 pmlibrarysymbol ThisSym;
384 sym = ps + sgetl (po);
391 if ((entry = find_member_by_offset (lbnh->libspc, offset)) != NULL)
393 for (ThisSym = entry->symbols; ThisSym->next != NULL; ThisSym = ThisSym->next)
398 /* Opened OK - create a new libraryfile object for it */
401 assert (libr == NULL);
402 libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
406 This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
411 This->libspc = lbnh->libspc;
412 This->offset = offset;
413 This->relfil = get_member_name_by_offset (libfp, offset); /* member name */
414 This->filspc = strdup (This->relfil); /* member file name */
417 /* start a new linked list of symbols for this module. */
418 This->symbols = ThisSym = NULL;
422 ThisSym = This->symbols = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
425 ThisSym->next = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
426 ThisSym = ThisSym->next;
428 ThisSym->next = NULL;
433 fseek (libfp, pos, SEEK_SET);
436 else if (AR_IS_STRING_TABLE (obj_name))
443 sym_tab = (char *) new (hdr.ar_size);
445 if (fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size)
451 sym_tab_size = hdr.ar_size;
455 long moduleOffset = ftell (libfp);
459 /* Opened OK - create a new libraryfile object for it */
462 assert (libr == NULL);
463 libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
467 This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
472 This->libspc = lbnh->libspc;
473 This->offset = moduleOffset - hdr_size;
475 This->relfil = obj_name; /* member name */
476 This->filspc = strdup (This->relfil); /* member file name */
478 D (" Indexing module: %s\n", This->relfil);
482 /* start a new linked list of symbols for this module. */
483 This->symbols = NULL;
485 add_rel_index (libfp, hdr.ar_size, This);
487 fseek (libfp, moduleOffset + hdr.ar_size, SEEK_SET);
492 int c = getc (libfp);
493 assert (c == EOF || c == '\n');
511 load_adb (FILE * libfp, struct lbfile *lbfh)
518 /* check if it is a .rel file */
519 if (0 != stricmp (&lbfh->relfil[strlen (lbfh->relfil) - 4], ".rel"))
523 adb_name = (char *) new (strlen (lbfh->relfil) + 1);
524 memcpy (adb_name, lbfh->relfil, strlen (lbfh->relfil) - 4);
525 memcpy (&adb_name[strlen (lbfh->relfil) - 4], ".adb", 5);
529 fprintf (stderr, "?ASlink-Error-%s is not an archive\n", lbfh->libspc);
535 /* walk trough all archive members */
536 while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0)
538 if (AR_IS_STRING_TABLE (obj_name))
545 sym_tab = (char *) new (hdr.ar_size);
547 if ((off_t) fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size)
553 sym_tab_size = hdr.ar_size;
555 if (AR_IS_SYMBOL_TABLE (obj_name) || 0 != stricmp (obj_name, adb_name))
559 /* skip the mamber */
560 fseek (libfp, hdr.ar_size + (hdr.ar_size & 1), SEEK_CUR);
564 long left = hdr.ar_size;
571 size_t n = min (left, sizeof buf);
573 if (fread (buf, 1, n, libfp) != n)
578 fwrite (buf, 1, n, dfp);
585 int c = getc (libfp);
586 assert (c == EOF || c == '\n');
600 fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type)
607 /* walk trough all archive members */
608 while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0)
610 char filspc[PATH_MAX];
612 if (lbnh->path != NULL)
614 strcpy (filspc, lbnh->path);
616 if (*filspc != '\0' && (filspc[strlen (filspc) - 1] != '/') && (filspc[strlen (filspc) - 1] != LKDIRSEP))
618 strcat (filspc, LKDIRSEPSTR);
623 if (AR_IS_SYMBOL_TABLE (obj_name))
631 buf = (char *) new (hdr.ar_size);
633 if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
644 for (i = 0; i < nsym; ++i)
653 while (*ps++ != '\0')
656 if (0 == strcmp (name, sym))
658 fseek (libfp, offset, SEEK_SET);
659 if (ar_get_header (&hdr, libfp, NULL))
661 sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
663 /* If this module has been loaded already don't load it again. */
664 if (!is_module_loaded (filspc))
666 struct lbfile *lbfh, *lbf;
668 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
669 lbfh->libspc = strdup (lbnh->libspc);
670 lbfh->relfil = strdup (hdr.ar_name);
671 lbfh->filspc = strdup (filspc);
672 lbfh->offset = offset;
681 for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
687 D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
688 load_rel (libfp, hdr.ar_size);
689 ///* if cdb information required & .adb file present */
692 // if (load_adb(FILE *libfp, struct lbfile *lbfh))
693 // SaveLinkedFilePath (filspc);
701 fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbnh->libspc, name);
711 else if (AR_IS_BSD_SYMBOL_TABLE (obj_name))
715 long nsym, tablesize;
719 buf = (char *) new (hdr.ar_size);
721 if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
727 tablesize = sgetl (buf);
728 nsym = tablesize / 8;
732 ps = po + tablesize + 4;
734 for (i = 0; i < nsym; ++i)
739 sym = ps + sgetl (po);
744 if (0 == strcmp (name, sym))
746 fseek (libfp, offset, SEEK_SET);
747 if (ar_get_header (&hdr, libfp, NULL))
749 sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
751 /* If this module has been loaded already don't load it again. */
752 if (!is_module_loaded (filspc))
754 struct lbfile *lbfh, *lbf;
756 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
757 lbfh->libspc = strdup (lbnh->libspc);
758 lbfh->relfil = strdup (hdr.ar_name);
759 lbfh->filspc = strdup (filspc);
760 lbfh->offset = offset;
769 for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
775 D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
776 load_rel (libfp, hdr.ar_size);
777 ///* if cdb information required & .adb file present */
780 // if (load_adb(FILE *libfp, struct lbfile *lbfh))
781 // SaveLinkedFilePath (filspc);
789 fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbnh->libspc, name);
799 else if (AR_IS_STRING_TABLE (obj_name))
806 sym_tab = (char *) new (hdr.ar_size);
808 if (fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size)
815 sym_tab_size = hdr.ar_size;
819 long moduleOffset = ftell (libfp);
823 D (" Module: %s\n", hdr.ar_name);
825 sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
827 /* Opened OK - create a new libraryfile object for it */
828 ret = add_rel_file (name, lbnh, hdr.ar_name, filspc, moduleOffset - hdr_size, libfp, hdr.ar_size, type);
829 ///* if cdb information required & .adb file present */
832 // if (load_adb(FILE *libfp, struct lbfile *lbfh))
833 // SaveLinkedFilePath (filspc);
838 fseek (libfp, moduleOffset + hdr.ar_size, SEEK_SET);
843 int c = getc (libfp);
844 assert (c == EOF || c == '\n');
860 loadfile_ar (struct lbfile *lbfh)
865 char posix_path[PATH_MAX];
866 void cygwin_conv_to_full_posix_path (char *win_path, char *posix_path);
867 cygwin_conv_to_full_posix_path (lbfh->libspc, posix_path);
868 fp = fopen (posix_path, "rb");
870 fp = fopen (lbfh->libspc, "rb");
877 fseek (fp, lbfh->offset, SEEK_SET);
878 if (ar_get_header (&hdr, fp, NULL) != 0)
880 D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
881 load_rel (fp, hdr.ar_size);
886 fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, lbfh->relfil);
893 fprintf (stderr, "?ASlink-Error-Opening library '%s'\n", lbfh->libspc);
898 struct aslib_target aslib_target_ar = {
901 &buildlibraryindex_ar,