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);