From 89cfbf54f2bfdb6644f63ffe57298207a602e8bf Mon Sep 17 00:00:00 2001 From: borutr Date: Thu, 5 Feb 2009 19:10:08 +0000 Subject: [PATCH] * asranlib/asranlib.c, link/lkar.h, link/lkar.c: added support for BSD (Mac OS X) ar format git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@5354 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 5 + as/asranlib/asranlib.c | 443 +++++++++++++++++++++++++++++++---- as/link/lkar.c | 510 +++++++++++++++++++++++++++++++---------- as/link/lkar.h | 18 +- 4 files changed, 795 insertions(+), 181 deletions(-) diff --git a/ChangeLog b/ChangeLog index dc2d8322..5891d3c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-02-05 Borut Razem + + * asranlib/asranlib.c, link/lkar.h, link/lkar.c: + added support for BSD (Mac OS X) ar format + 2009-02-02 Borut Razem * device/lib/gbz80/Makefile.in, device/lib/hc08/Makefile.in, diff --git a/as/asranlib/asranlib.c b/as/asranlib/asranlib.c index e5449cfd..ba92f7e1 100644 --- a/as/asranlib/asranlib.c +++ b/as/asranlib/asranlib.c @@ -5,7 +5,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any +Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,8 +14,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +along with this program. If not, see . */ #include #include @@ -33,6 +32,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define NELEM(x) (sizeof (x) / sizeof (*x)) +int verbose = 0; +int list = 0; +int print_index = 0; + int is_ar (FILE * libfp) { @@ -45,17 +48,139 @@ is_ar (FILE * libfp) return ret; } -static struct ar_hdr * -ar_get_header (struct ar_hdr *hdr, FILE * libfp) +static char *sym_tab; +static int sym_tab_size; + +char * +get_member_name (char *name, size_t *p_size, int allocate, FILE * libfp) +{ + *p_size = 0; + + if (0 == memcmp (name, "#1/", 3)) + { + char *p; + size_t len = strtoul (&name [3], &p, 10); + if (p > &name [3]) + { + /* BSD appends real file name to the file header */ + if (p_size != NULL) + *p_size = len; + + if (allocate) + { + char *n = (char *) malloc (len); + if (fread (n, 1, len, libfp) != len) + { + /* not an ar archive or broken ar archive */ + return NULL; + } + else + return n; + } + else + { + /* just advance the file pointer */ + fseek (libfp, len, SEEK_CUR); + return NULL; + } + } + else + { + /* not an ar archive or broken ar archive */ + return NULL; + } + } + else if (allocate) + { + if (name[0] == '/') + { + if (NULL != sym_tab) + { + char *p; + + int name_offset = strtol (++name, &p, 0); + if (p != name && name_offset < sym_tab_size) + { + int len = p - name + 1; + while (len < AR_NAME_LEN && name[len++] == ' ') + ; + if (len == AR_NAME_LEN) + { + char *n; + + /* long name: get it from the symbol table */ + name = &sym_tab[name_offset]; + for (p = name; *p != '/' && *p != '\n'; ++p) + assert (p < &sym_tab[sym_tab_size]); + + if (p[0] != '/' || p[1] != '\n') + while (*++p != '\n') + assert (p < &sym_tab[sym_tab_size]); + + n = (char *) malloc (p - name + 1); + memcpy (n, name, p - name); + n[p - name] = '\0'; + return n; + } + } + } + } + else + { + char *p = strrchr (name, '/'); + + if (NULL != p) + { + int len = p - name; + while (name[++len] == ' ') + ; + if (len == AR_NAME_LEN) + { + char *n = (char *) malloc (p - name + 1); + memcpy (n, name, p - name); + n[p - name] = '\0'; + return n; + } + } + else + { + /* BSD formed member name: + trim trailing spaces */ + char *n; + + p = name + AR_NAME_LEN; + while (*--p == ' ' && p >= name) + ; + ++p; + n = (char *) malloc (p - name + 1); + memcpy (n, name, p - name); + n[p - name] = '\0'; + return n; + } + } + + /* bad formed member name: + just return it */ + + return strdup (name); + } + else + return NULL; +} + +size_t +ar_get_header (struct ar_hdr *hdr, FILE * libfp, char **p_obj_name) { char header[ARHDR_LEN]; char buf[AR_DATE_LEN + 1]; + char *obj_name; + size_t size; - if (fread (header, 1, sizeof (header), libfp) != sizeof (header) || - memcmp (header + AR_FMAG_OFFSET, ARFMAG, AR_FMAG_LEN) != 0) + if (fread (header, 1, sizeof (header), libfp) != sizeof (header) + || memcmp (header + AR_FMAG_OFFSET, ARFMAG, AR_FMAG_LEN) != 0) { /* not an ar archive */ - return NULL; + return 0; } memcpy (hdr->ar_name, &header[AR_NAME_OFFSET], AR_NAME_LEN); @@ -81,9 +206,26 @@ ar_get_header (struct ar_hdr *hdr, FILE * libfp) buf[AR_SIZE_LEN] = '\0'; hdr->ar_size = strtol (buf, NULL, 0); - return hdr; + obj_name = get_member_name (hdr->ar_name, &size, p_obj_name != NULL, libfp); + + if (p_obj_name != NULL) + *p_obj_name = obj_name; + + /* treat BSD appended real file name as a part of the header */ + hdr->ar_size -= size; + + return size + ARHDR_LEN; } +static char * +get_member_name_by_offset (FILE * fp, long offset) +{ + struct ar_hdr hdr; + char *name; + + fseek (fp, offset, SEEK_SET); + return (ar_get_header (&hdr, fp, &name) != 0) ? name : NULL; +} struct symbol_s { @@ -103,6 +245,9 @@ add_symbol (const char *sym, void *param) if ((s = (struct symbol_s *) malloc (sizeof (struct symbol_s))) == NULL) return 0; + if (verbose) + printf ("%s\n", sym); + s->name = strdup (sym); s->offset = offset - first_member_offset; s->next = NULL; @@ -212,21 +357,152 @@ enum_symbols (FILE * fp, long size, int (*func) (const char *sym, void *param), return 0; } + +static int +process_symbol_table (struct ar_hdr *hdr, FILE *fp) +{ + if (print_index) + { + char *buf, *po, *ps; + int i; + long nsym; + long pos; + + printf ("Archive index:\n"); + + buf = (char *) malloc (hdr->ar_size); + + if (fread (buf, 1, hdr->ar_size, fp) != hdr->ar_size) + { + free (buf); + return 0; + } + + pos = ftell (fp); + + nsym = sgetl (buf); + + po = buf + 4; + ps = po + nsym * 4; + + for (i = 0; i < nsym; ++i) + { + char *obj; + + offset = sgetl (po); + po += 4; + + printf ("%s in ", ps); + ps += strlen(ps) + 1; + + obj = get_member_name_by_offset (fp, offset); /* member name */ + printf ("%s\n", obj); + free (obj); + + } + free (buf); + + fseek (fp, pos, SEEK_SET); + + putchar ('\n'); + } + else + { + /* skip the symbol table */ + fseek (fp, hdr->ar_size + (hdr->ar_size & 1), SEEK_CUR); + } + + return 1; +} + +static int +process_bsd_symbol_table (struct ar_hdr *hdr, FILE *fp) +{ + if (print_index) + { + char *buf, *po, *ps; + int i; + long tablesize; + long nsym; + long pos; + + printf ("Archive index:\n"); + + buf = (char *) malloc (hdr->ar_size); + + if (fread (buf, 1, hdr->ar_size, fp) != hdr->ar_size) + { + free (buf); + return 0; + } + + pos = ftell (fp); + + tablesize = sgetl (buf); + nsym = tablesize / 8; + + po = buf + 4; + + ps = po + tablesize + 4; + + for (i = 0; i < nsym; ++i) + { + char *obj; + long sym; + + sym = sgetl (po); + po += 4; + offset = sgetl (po); + po += 4; + + printf ("%s in ", ps + sym); + + obj = get_member_name_by_offset (fp, offset); /* member name */ + printf ("%s\n", obj); + free (obj); + } + free (buf); + + fseek (fp, pos, SEEK_SET); + + putchar ('\n'); + } + else + { + /* skip the symbol table */ + fseek (fp, hdr->ar_size + (hdr->ar_size & 1), SEEK_CUR); + } + + return 1; +} + int get_symbols (FILE * fp, const char *archive) { struct ar_hdr hdr; + char *name; - if (!is_ar (fp) || !ar_get_header (&hdr, fp)) + if (!is_ar (fp) || !ar_get_header (&hdr, fp, &name)) { fprintf (stderr, "asranlib: %s: File format not recognized\n", archive); exit (1); } - if (AR_IS_SYMBOL_TABLE (hdr)) + if (AR_IS_SYMBOL_TABLE (name)) { - /* skip the symbol table */ - fseek (fp, hdr.ar_size + (hdr.ar_size & 1), SEEK_CUR); + free (name); + + process_symbol_table (&hdr, fp); + if (!ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL)) + return 1; + } + else if (AR_IS_BSD_SYMBOL_TABLE (name)) + { + free (name); + + process_bsd_symbol_table (&hdr, fp); + if (!ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL)) + return 1; } first_member_offset = ftell (fp) - ARHDR_LEN; @@ -236,32 +512,49 @@ get_symbols (FILE * fp, const char *archive) { if (is_rel (fp)) { - long mdule_offset = ftell (fp); + if (verbose || list) + { + printf ("%s%s\n", name, verbose ? ":" : ""); + free (name); + } - offset = mdule_offset - ARHDR_LEN; + if (!list) + { + long mdule_offset = ftell (fp); - enum_symbols (fp, hdr.ar_size, add_symbol, NULL); + offset = mdule_offset - ARHDR_LEN; - fseek (fp, mdule_offset + hdr.ar_size, SEEK_SET); + enum_symbols (fp, hdr.ar_size, add_symbol, NULL); - if (hdr.ar_size & 1) - { - int c = getc (fp); - assert (c == EOF || c == '\n'); + fseek (fp, mdule_offset + hdr.ar_size, SEEK_SET); + + if (hdr.ar_size & 1) + { + int c = getc (fp); + assert (c == EOF || c == '\n'); + } } + + if (verbose) + putchar ('\n'); } else { + if (verbose || list) + { + fprintf (stderr, "asranlib: %s: File format not recognized\n", name); + free (name); + } + /* skip if the member is not a .REL format */ fseek (fp, hdr.ar_size + (hdr.ar_size & 1), SEEK_CUR); } } - while (ar_get_header (&hdr, fp)); + while (ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL)); return 1; } - void do_ranlib (const char *archive) { @@ -276,25 +569,43 @@ do_ranlib (const char *archive) if (get_symbols (infp, archive)) { - FILE *outfp = NULL; + FILE *outfp; struct symbol_s *symp; char buf[4]; - int str_length = 0; - int pad = 0; + int str_length; + int pad; int nsym; int symtab_size; char tmpfile[] = "arXXXXXX"; - if (NULL == mktemp (tmpfile) || NULL == (outfp = fopen (tmpfile, "wb"))) +#ifdef _WIN32 + if (NULL == _mktemp (tmpfile) || NULL == (outfp = fopen (tmpfile, "wb"))) { fclose (infp); fprintf (stderr, "asranlib: %s: ", tmpfile); perror (NULL); exit (1); } +#else + if ((pad = mkstemp (tmpfile)) < 0) + { + fclose (infp); + fprintf (stderr, "asranlib: %s: ", tmpfile); + perror (NULL); + exit (1); + } + + if (NULL == (outfp = fdopen (pad, "wb"))) + { + close (pad); + fclose (infp); + perror ("asranlib"); + exit (1); + } +#endif /* calculate the size of symbol table */ - for (nsym = 0, symp = symlist; symp; ++nsym, symp = symp->next) + for (str_length = 0, nsym = 0, symp = symlist; symp; ++nsym, symp = symp->next) { str_length += strlen (symp->name) + 1; } @@ -355,6 +666,11 @@ do_ranlib (const char *archive) fclose (infp); } +void +do_verbose (void) +{ + verbose = 1; +} void print_version (void) @@ -363,35 +679,64 @@ print_version (void) exit (0); } - void -usage (void) +do_list (void) { - printf ("Usage: asranlib [options] archive\n" - " Generate an index to speed access to archives\n" - " The options are:\n" - " -h --help Print this help message\n" - " -V --version Print version information\n" - "asranlib: supported targets: asxxxx\n"); + list = 1; +} - exit (1); +void +print_armap (void) +{ + print_index = 1; } +void usage (void); struct opt_s { - const char *opt; + const char *short_opt; + const char *long_opt; void (*optfnc) (void); + const char *comment; } opts[] = { - { "-v", &print_version, }, - { "-V", &print_version, }, - { "--version", &print_version, }, - { "-h", &usage, }, - { "--help", &usage, }, + { "-v", "--verbose", &do_verbose, "Be more verbose about the operation" }, + { "-V", "--version", &print_version, "Print this help message" }, + { "-h", "--help", &usage, "Print version information" }, + { "-t", "--list", &do_list, "List the contents of an archive" }, + { "-s", "--print-armap", &print_armap, "Print the archive index" }, }; +void +usage (void) +{ + int i; + + printf ("Usage: asranlib [options] archive\n" + " Generate an index to speed access to archives\n" + " The options are:\n"); + + for (i = 0; i < NELEM (opts); ++i) + { + int len = 3; + printf (" %s ", (NULL != opts[i].short_opt) ? opts[i].short_opt : " "); + if (NULL != opts[i].long_opt) + { + printf ("%s ", opts[i].long_opt); + len += strlen (opts[i].long_opt); + } + + while (len++ < 32) + putchar (' '); + printf ("%s\n", opts[i].comment); + } + + printf ("asranlib: supported targets: asxxxx\n"); + + exit (1); +} void process_options (int argc, char *argv[]) @@ -413,26 +758,28 @@ process_options (int argc, char *argv[]) for (i = 0; i < NELEM (opts); ++i) { - if (0 == strcmp (*argp, opts[i].opt)) + if (0 == strcmp (*argp, opts[i].short_opt) || 0 == strcmp (*argp, opts[i].long_opt)) { if (NULL != opts[i].optfnc) { (*opts[i].optfnc) (); - continue; + break; } } } } - do_ranlib (*argp); - ++narch; + else + { + do_ranlib (*argp); + ++narch; + } } if (!narch) usage (); } - int main (int argc, char *argv[]) { diff --git a/as/link/lkar.c b/as/link/lkar.c index b137ffde..3334b29d 100644 --- a/as/link/lkar.c +++ b/as/link/lkar.c @@ -6,7 +6,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any +Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -15,8 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +along with this program. If not, see . */ /* * With contributions for the @@ -62,17 +61,139 @@ is_ar (FILE * libfp) return ret; } -static struct ar_hdr * -ar_get_header (struct ar_hdr *hdr, FILE * libfp) +static char *sym_tab; +static int sym_tab_size; + +char * +get_member_name (char *name, size_t *p_size, int allocate, FILE * libfp) +{ + *p_size = 0; + + if (0 == memcmp (name, "#1/", 3)) + { + char *p; + size_t len = strtoul (&name [3], &p, 10); + if (p > &name [3]) + { + /* BSD appends real file name to the file header */ + if (p_size != NULL) + *p_size = len; + + if (allocate) + { + char *n = (char *) malloc (len); + if (fread (n, 1, len, libfp) != len) + { + /* not an ar archive or broken ar archive */ + return NULL; + } + else + return n; + } + else + { + /* just advance the file pointer */ + fseek (libfp, len, SEEK_CUR); + return NULL; + } + } + else + { + /* not an ar archive or broken ar archive */ + return NULL; + } + } + else if (allocate) + { + if (name[0] == '/') + { + if (NULL != sym_tab) + { + char *p; + + int name_offset = strtol (++name, &p, 0); + if (p != name && name_offset < sym_tab_size) + { + int len = p - name + 1; + while (len < AR_NAME_LEN && name[len++] == ' ') + ; + if (len == AR_NAME_LEN) + { + char *n; + + /* long name: get it from the symbol table */ + name = &sym_tab[name_offset]; + for (p = name; *p != '/' && *p != '\n'; ++p) + assert (p < &sym_tab[sym_tab_size]); + + if (p[0] != '/' || p[1] != '\n') + while (*++p != '\n') + assert (p < &sym_tab[sym_tab_size]); + + n = (char *) malloc (p - name + 1); + memcpy (n, name, p - name); + n[p - name] = '\0'; + return n; + } + } + } + } + else + { + char *p = strrchr (name, '/'); + + if (NULL != p) + { + int len = p - name; + while (name[++len] == ' ') + ; + if (len == AR_NAME_LEN) + { + char *n = (char *) malloc (p - name + 1); + memcpy (n, name, p - name); + n[p - name] = '\0'; + return n; + } + } + else + { + /* BSD formed member name: + trim trailing spaces */ + char *n; + + p = name + AR_NAME_LEN; + while (*--p == ' ' && p >= name) + ; + ++p; + n = (char *) malloc (p - name + 1); + memcpy (n, name, p - name); + n[p - name] = '\0'; + return n; + } + } + + /* bad formed member name: + just return it */ + + return strdup (name); + } + else + return NULL; +} + +size_t +ar_get_header (struct ar_hdr *hdr, FILE * libfp, char **p_obj_name) { char header[ARHDR_LEN]; char buf[AR_DATE_LEN + 1]; + char *obj_name; + size_t size; if (fread (header, 1, sizeof (header), libfp) != sizeof (header) || memcmp (header + AR_FMAG_OFFSET, ARFMAG, AR_FMAG_LEN) != 0) { /* not an ar archive */ - return NULL; + return 0; } memcpy (hdr->ar_name, &header[AR_NAME_OFFSET], AR_NAME_LEN); @@ -98,122 +219,26 @@ ar_get_header (struct ar_hdr *hdr, FILE * libfp) buf[AR_SIZE_LEN] = '\0'; hdr->ar_size = strtol (buf, NULL, 0); - return hdr; -} + obj_name = get_member_name (hdr->ar_name, &size, p_obj_name != NULL, libfp); -static char *sym_tab; -static int sym_tab_size; + if (p_obj_name != NULL) + *p_obj_name = obj_name; -static void -loadfile_ar (struct lbfile *lbfh) -{ - FILE *fp; + /* treat BSD appended real file name as a part of the header */ + hdr->ar_size -= size; -#ifdef __CYGWIN__ - char posix_path[PATH_MAX]; - void cygwin_conv_to_full_posix_path (char *win_path, char *posix_path); - cygwin_conv_to_full_posix_path (lbfh->libspc, posix_path); - fp = fopen (posix_path, "rb"); -#else - fp = fopen (lbfh->libspc, "rb"); -#endif - - if (fp != NULL) - { - struct ar_hdr hdr; - - fseek (fp, lbfh->offset, SEEK_SET); - if (ar_get_header (&hdr, fp)) - { - D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc); - load_rel (fp, hdr.ar_size); - fclose (fp); - } - else - { - fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, lbfh->relfil); - fclose (fp); - lkexit (1); - } - } - else - { - fprintf (stderr, "?ASlink-Error-Opening library '%s'\n", lbfh->libspc); - lkexit (1); - } + return size + ARHDR_LEN; } #if INDEXLIB -char * -get_member_name (char *name) -{ - if (name[0] == '/') - { - if (NULL != sym_tab) - { - char *p; - - int name_offset = strtol (++name, &p, 0); - if (p != name && name_offset < sym_tab_size) - { - int len = p - name + 1; - while (len < AR_NAME_LEN && name[len++] == ' ') - ; - if (len == AR_NAME_LEN) - { - char *n; - - /* long name: get it from the symbol table */ - name = &sym_tab[name_offset]; - for (p = name; *p != '/' && *p != '\n'; ++p) - assert (p < &sym_tab[sym_tab_size]); - - if (p[0] != '/' || p[1] != '\n') - while (*++p != '\n') - assert (p < &sym_tab[sym_tab_size]); - - n = (char *) malloc (p - name + 1); - memcpy (n, name, p - name); - n[p - name] = '\0'; - return n; - } - } - } - } - else - { - char *p = strrchr (name, '/'); - - if (NULL != p) - { - int len = p - name; - while (name[++len] == ' ') - ; - if (len == AR_NAME_LEN) - { - char *n = (char *) malloc (p - name + 1); - memcpy (n, name, p - name); - n[p - name] = '\0'; - return n; - } - } - } - - /* bad formed member name: - just return it */ - - return strdup (name); -} - static char * get_member_name_by_offset (FILE * fp, long offset) { struct ar_hdr hdr; + char *name; fseek (fp, offset, SEEK_SET); - - /* walk trough all archive members */ - return (NULL != ar_get_header (&hdr, fp)) ? get_member_name (hdr.ar_name) : NULL; + return (ar_get_header (&hdr, fp, &name) != 0) ? name : NULL; } static pmlibraryfile @@ -221,6 +246,7 @@ find_member_by_offset (const char *libspc, long offset) { pmlibraryfile p; + /* walk trough all archive members */ for (p = libr; p; p = p->next) { if (0 == strcmp (libspc, p->libspc) && p->offset == offset) @@ -234,24 +260,31 @@ static pmlibraryfile buildlibraryindex_ar (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int type) { struct ar_hdr hdr; + char *obj_name; + size_t hdr_size; /* walk trough all archive members */ - while (ar_get_header (&hdr, libfp)) + while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0) { - if (AR_IS_SYMBOL_TABLE (hdr)) + if (AR_IS_SYMBOL_TABLE (obj_name)) { char *buf, *po, *ps; int i; long nsym; + long pos; + + free (obj_name); buf = (char *) new (hdr.ar_size); - if ((off_t) fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size) + if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size) { free (buf); return This; } + pos = ftell (libfp); + nsym = sgetl (buf); po = buf + 4; @@ -268,8 +301,92 @@ buildlibraryindex_ar (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int po += 4; sym = strdup (ps); - while (*ps++ != '\0') - ; + ps += strlen (ps) + 1; + + if ((entry = find_member_by_offset (lbnh->libspc, offset)) != NULL) + { + for (ThisSym = entry->symbols; ThisSym->next != NULL; ThisSym = ThisSym->next) + ; + } + else + { + /* Opened OK - create a new libraryfile object for it */ + if (This == NULL) + { + assert (libr == NULL); + libr = This = (pmlibraryfile) new (sizeof (mlibraryfile)); + } + else + { + This->next = (pmlibraryfile) new (sizeof (mlibraryfile)); + This = This->next; + } + This->next = NULL; + This->loaded = 0; + This->libspc = lbnh->libspc; + This->offset = offset; + This->relfil = get_member_name_by_offset (libfp, offset); /* member name */ + This->filspc = strdup (This->relfil); /* member file name */ + This->type = type; + + /* start a new linked list of symbols for this module. */ + This->symbols = ThisSym = NULL; + } + + if (ThisSym == NULL) + ThisSym = This->symbols = (pmlibrarysymbol) new (sizeof (mlibrarysymbol)); + else + { + ThisSym->next = (pmlibrarysymbol) new (sizeof (mlibrarysymbol)); + ThisSym = ThisSym->next; + } + ThisSym->next = NULL; + ThisSym->name = sym; + } + free (buf); + + fseek (libfp, pos, SEEK_SET); + break; + } + else if (AR_IS_BSD_SYMBOL_TABLE (obj_name)) + { + char *buf, *po, *ps; + int i; + long nsym, tablesize; + long pos; + + free (obj_name); + + buf = (char *) new (hdr.ar_size); + + if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size) + { + free (buf); + return This; + } + + pos = ftell (libfp); + + tablesize = sgetl (buf); + nsym = tablesize / 8; + + po = buf + 4; + + ps = po + tablesize + 4; + + for (i = 0; i < nsym; ++i) + { + pmlibrarysymbol ThisSym; + char *sym; + long offset; + pmlibraryfile entry; + + sym = ps + sgetl (po); + po += 4; + offset = sgetl (po); + po += 4; + + sym = strdup (ps); if ((entry = find_member_by_offset (lbnh->libspc, offset)) != NULL) { @@ -313,16 +430,19 @@ buildlibraryindex_ar (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int } free (buf); + fseek (libfp, pos, SEEK_SET); break; } - else if (AR_IS_STRING_TABLE (hdr)) + else if (AR_IS_STRING_TABLE (obj_name)) { + free (obj_name); + if (sym_tab) free (sym_tab); sym_tab = (char *) new (hdr.ar_size); - if ((off_t) fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size) + if (fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size) { free (sym_tab); sym_tab_size = 0; @@ -348,9 +468,9 @@ buildlibraryindex_ar (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int This->next = NULL; This->loaded = -1; This->libspc = lbnh->libspc; - This->offset = moduleOffset - ARHDR_LEN; + This->offset = moduleOffset - hdr_size; - This->relfil = get_member_name (hdr.ar_name); /* member name */ + This->relfil = obj_name; /* member name */ This->filspc = strdup (This->relfil); /* member file name */ D (" Indexing module: %s\n", This->relfil); @@ -390,6 +510,8 @@ load_adb (FILE * libfp, struct lbfile *lbfh) { struct ar_hdr hdr; char *adb_name; + char *obj_name; + size_t hdr_size; /* check if it is a .rel file */ if (0 != stricmp (&lbfh->relfil[strlen (lbfh->relfil) - 4], ".rel")) @@ -409,10 +531,12 @@ load_adb (FILE * libfp, struct lbfile *lbfh) /* walk trough all archive members */ - while (ar_get_header (&hdr, libfp)) + while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0) { - if (AR_IS_STRING_TABLE (hdr)) + if (AR_IS_STRING_TABLE (obj_name)) { + free (obj_name); + if (sym_tab) free (sym_tab); @@ -426,8 +550,10 @@ load_adb (FILE * libfp, struct lbfile *lbfh) } sym_tab_size = hdr.ar_size; } - if (AR_IS_SYMBOL_TABLE (hdr) || 0 != stricmp (get_member_name (hdr.ar_name), adb_name)) + if (AR_IS_SYMBOL_TABLE (obj_name) || 0 != stricmp (obj_name, adb_name)) { + free (obj_name); + /* skip the mamber */ fseek (libfp, hdr.ar_size + (hdr.ar_size & 1), SEEK_CUR); } @@ -436,6 +562,8 @@ load_adb (FILE * libfp, struct lbfile *lbfh) long left = hdr.ar_size; char buf[4096]; + free (obj_name); + while (left) { size_t n = min (left, sizeof buf); @@ -471,9 +599,10 @@ fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type) { struct ar_hdr hdr; int ret = 0; + size_t hdr_size; /* walk trough all archive members */ - while (ar_get_header (&hdr, libfp)) + while ((hdr_size = ar_get_header (&hdr, libfp, NULL)) != 0) { char filspc[PATH_MAX]; @@ -488,12 +617,14 @@ fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type) #endif } - if (AR_IS_SYMBOL_TABLE (hdr)) + if (AR_IS_SYMBOL_TABLE (obj_name)) { char *buf, *po, *ps; int i; long nsym; + free (obj_name); + buf = (char *) new (hdr.ar_size); if ((off_t) fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size) @@ -574,7 +705,95 @@ fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type) break; } - else if (AR_IS_STRING_TABLE (hdr)) + else if (AR_IS_BSD_SYMBOL_TABLE (obj_name)) + { + char *buf, *po, *ps; + int i; + long nsym, tablesize; + + free (obj_name); + + buf = (char *) new (hdr.ar_size); + + if ((off_t) fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size) + { + free (buf); + return 0; + } + + tablesize = sgetl (buf); + nsym = tablesize / 8; + + po = buf + 4; + + ps = po + tablesize + 4; + + for (i = 0; i < nsym; ++i) + { + char *sym; + long offset; + + sym = ps + sgetl (po); + po += 4; + offset = sgetl (po); + po += 4; + + if (0 == strcmp (name, sym)) + { + fseek (libfp, offset, SEEK_SET); + if (ar_get_header (&hdr, libfp)) + { + sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name); + + /* If this module has been loaded already don't load it again. */ + if (!is_module_loaded (filspc)) + { + struct lbfile *lbfh, *lbf; + + lbfh = (struct lbfile *) new (sizeof (struct lbfile)); + lbfh->libspc = strdup (lbnh->libspc); + lbfh->relfil = strdup (hdr.ar_name); + lbfh->filspc = strdup (filspc); + lbfh->offset = offset; + lbfh->type = type; + + if (lbfhead == NULL) + { + lbfhead = lbfh; + } + else + { + for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next) + ; + + lbf->next = lbfh; + } + + D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc); + load_rel (libfp, hdr.ar_size); + ///* if cdb information required & .adb file present */ + //if (dflag && dfp) + // { + // if (load_adb(FILE *libfp, struct lbfile *lbfh)) + // SaveLinkedFilePath (filspc); + // } + ret = 1; + break; + } + } + else + { + fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbnh->libspc, name); + fclose (libfp); + lkexit (1); + } + } + } + free (buf); + + break; + } + else if (AR_IS_STRING_TABLE (obj_name)) { if (sym_tab) free (sym_tab); @@ -599,7 +818,7 @@ fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type) sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name); /* Opened OK - create a new libraryfile object for it */ - ret = add_rel_file (name, lbnh, hdr.ar_name, filspc, moduleOffset - ARHDR_LEN, libfp, hdr.ar_size, type); + ret = add_rel_file (name, lbnh, hdr.ar_name, filspc, moduleOffset - hdr_size, libfp, hdr.ar_size, type); ///* if cdb information required & .adb file present */ //if (dflag && dfp) // { @@ -630,6 +849,45 @@ fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type) } #endif +static void +loadfile_ar (struct lbfile *lbfh) +{ + FILE *fp; + +#ifdef __CYGWIN__ + char posix_path[PATH_MAX]; + void cygwin_conv_to_full_posix_path (char *win_path, char *posix_path); + cygwin_conv_to_full_posix_path (lbfh->libspc, posix_path); + fp = fopen (posix_path, "rb"); +#else + fp = fopen (lbfh->libspc, "rb"); +#endif + + if (fp != NULL) + { + struct ar_hdr hdr; + + fseek (fp, lbfh->offset, SEEK_SET); + if (ar_get_header (&hdr, fp, NULL) != 0) + { + D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc); + load_rel (fp, hdr.ar_size); + fclose (fp); + } + else + { + fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, lbfh->relfil); + fclose (fp); + lkexit (1); + } + } + else + { + fprintf (stderr, "?ASlink-Error-Opening library '%s'\n", lbfh->libspc); + lkexit (1); + } +} + struct aslib_target aslib_target_ar = { &is_ar, #ifdef INDEXLIB diff --git a/as/link/lkar.h b/as/link/lkar.h index 748c7f44..af77754b 100644 --- a/as/link/lkar.h +++ b/as/link/lkar.h @@ -4,7 +4,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any +Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -13,8 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +along with this program. If not, see . */ #ifndef __LKAR_H #define __LKAR_H @@ -61,11 +60,16 @@ typedef _off_t off_t; #define ARHDR_LEN (AR_NAME_LEN + AR_DATE_LEN + AR_UID_LEN + AR_GID_LEN + AR_MODE_LEN + AR_SIZE_LEN + AR_FMAG_LEN) -#define AR_SYMBOL_TABLE_NAME "/ " -#define AR_STRING_TABLE_NAME "// " +#define AR_SYMBOL_TABLE_NAME "/ " +#define AR_STRING_TABLE_NAME "// " -#define AR_IS_SYMBOL_TABLE(hdr) (0 == strcmp((hdr).ar_name, AR_SYMBOL_TABLE_NAME)) -#define AR_IS_STRING_TABLE(hdr) (0 == strcmp((hdr).ar_name, AR_STRING_TABLE_NAME)) +#define AR_BSD_SYMBOL_TABLE_NAME "__.SYMDEF " +#define AR_BSD_SORTED_SYMBOL_TABLE_NAME "__.SYMDEF SORTED" + +#define AR_IS_SYMBOL_TABLE(name) (0 == strcmp((name), AR_SYMBOL_TABLE_NAME)) +#define AR_IS_STRING_TABLE(name) (0 == strcmp((name), AR_STRING_TABLE_NAME)) + +#define AR_IS_BSD_SYMBOL_TABLE(name) (0 == strcmp((name), AR_BSD_SYMBOL_TABLE_NAME) || 0 == strcmp((name), AR_BSD_SORTED_SYMBOL_TABLE_NAME)) struct ar_hdr /* archive member header */ -- 2.30.2