Two diffs below to fix the use of nm -s when reading a __symdef archive
on a 64bits machine and/or with a different endianness (ie m68k on amd64
or vax on ppc).

To detect the archive index endianness without looking at the first
object I assumed that the first time we have a fseek error we should be
trying with a wrong offset. So I try again the values swapped. It's a
bit scary but I couldn't see a different approach without looking at 
the first object.

As for strings(1), tested on macppc, amd64 and vax.

Comments ?

Martin

commit 36d80b16fb2f5e2c5c345ed31caee4959bd30270
Author: Martin Pieuchot <mpieuc...@nolizard.org>
Date:   Fri Apr 8 17:19:21 2011 +0530

    Support the -s option for 32bits symdef archives on 64bits machines
    with the same endianness.

diff --git a/nm.c b/nm.c
index 34e2f52..832e03a 100644
--- a/nm.c
+++ b/nm.c
@@ -76,6 +76,13 @@ struct nlist32 {
        u_int32_t       value;
 } __packed;
 
+struct ranlib32 {
+       union {
+               u_int32_t       ran_strx;
+       } ran_un;
+       u_int32_t       ran_off;
+} __packed;
+
 int armap;
 int demangle;
 int non_object_warning;
@@ -408,7 +415,11 @@ show_symtab(off_t off, u_long len, const char *name, FILE 
*fp)
 int
 show_symdef(off_t off, u_long len, const char *name, FILE *fp)
 {
+#ifdef __LP64__
+       struct ranlib32 *prn, *eprn;
+#else
        struct ranlib *prn, *eprn;
+#endif
        struct ar_hdr ar_head;
        void *symdef;
        char *strtab, *p;
@@ -429,9 +440,9 @@ show_symdef(off_t off, u_long len, const char *name, FILE 
*fp)
        }
 
        size = *(u_long *)symdef;
-       prn = symdef + sizeof(u_long);
+       prn = symdef + sizeof(u_int32_t);
        eprn = prn + size / sizeof(*prn);
-       strtab = symdef + sizeof(u_long) + size + sizeof(u_long);
+       strtab = symdef + sizeof(u_int32_t) + size + sizeof(u_int32_t);
 
        printf("\nArchive index:\n");
        for (; prn < eprn; prn++) {


commit 67409c3501f5aa9ea7c1e327faad2baab1eb2969
Author: Martin Pieuchot <mpieuc...@nolizard.org>
Date:   Fri Apr 8 21:16:22 2011 +0530

    Add support for displaying the index (nm -s) of a.out archives on
    machine with a different endianess.

diff --git a/nm.c b/nm.c
index 832e03a..ff307b7 100644
--- a/nm.c
+++ b/nm.c
@@ -424,7 +424,8 @@ show_symdef(off_t off, u_long len, const char *name, FILE 
*fp)
        void *symdef;
        char *strtab, *p;
        u_long size;
-       int namelen, rval = 0;
+       long roff, rstrx;
+       int namelen, rval = 0, endianess = 0;
 
        MMAP(symdef, len, PROT_READ, MAP_PRIVATE|MAP_FILE, fileno(fp), off);
        if (symdef == MAP_FAILED)
@@ -439,14 +440,31 @@ show_symdef(off_t off, u_long len, const char *name, FILE 
*fp)
                return (1);
        }
 
-       size = *(u_long *)symdef;
+       printf("\nArchive index:\n");
+init:
+       if (endianess)
+               size = swap32(*(u_long *)symdef);
+       else
+               size = *(u_long *)symdef;
+
        prn = symdef + sizeof(u_int32_t);
        eprn = prn + size / sizeof(*prn);
        strtab = symdef + sizeof(u_int32_t) + size + sizeof(u_int32_t);
 
-       printf("\nArchive index:\n");
        for (; prn < eprn; prn++) {
-               if (fseeko(fp, prn->ran_off, SEEK_SET)) {
+               if (endianess) {
+                       roff = swap32(prn->ran_off);
+                       rstrx = swap32(prn->ran_un.ran_strx);
+               } else {
+                       roff = prn->ran_off;
+                       rstrx = prn->ran_un.ran_strx;
+               }
+
+               if (fseeko(fp, roff, SEEK_SET)) {
+                       if (!endianess) {
+                               endianess = 1;
+                               goto init;
+                       }
                        warn("%s: fseeko", name);
                        rval = 1;
                        break;
@@ -454,6 +472,10 @@ show_symdef(off_t off, u_long len, const char *name, FILE 
*fp)
 
                if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||
                    memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) {
+                       if (!endianess) {
+                               endianess = 1;
+                               goto init;
+                       }
                        warnx("%s: member fseeko", name);
                        rval = 1;
                        break;
@@ -465,7 +487,7 @@ show_symdef(off_t off, u_long len, const char *name, FILE 
*fp)
                        break;
                }
 
-               printf("%s in %s\n", strtab + prn->ran_un.ran_strx, p);
+               printf("%s in %s\n", strtab + rstrx, p);
        }
 
        free(p);

Reply via email to