[BACK]Return to nm.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / nm

Diff for /src/usr.bin/nm/nm.c between version 1.26 and 1.27

version 1.26, 2004/07/11 07:08:46 version 1.27, 2004/10/09 20:26:57
Line 63 
Line 63 
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <getopt.h>  #include <getopt.h>
 /* XXX get shared code to handle byte-order swaps */  #include "elfuncs.h"
   #include "util.h"
   
   /* XXX get shared code to handle a.out byte-order swaps */
 #include "byte.c"  #include "byte.c"
 #include "elf.c"  
   
 #ifdef MID_MACHINE_OVERRIDE  #ifdef MID_MACHINE_OVERRIDE
 #undef MID_MACHINE  #undef MID_MACHINE
Line 77 
Line 79 
   
 union hdr {  union hdr {
         struct exec aout;          struct exec aout;
         Elf_Ehdr elf;          Elf32_Ehdr elf32;
           Elf64_Ehdr elf64;
 };  };
   
   /* a funky nlist overload for reading 32bit a.out on 64bit toys */
   struct nlist32 {
           u_int32_t       strx;
           u_int8_t        type;
           u_int8_t        other;
           u_int16_t       desc;
           u_int32_t       value;
   } __packed;
   
 int armap;  int armap;
 int demangle;  int demangle;
 int non_object_warning;  int non_object_warning;
Line 116 
Line 128 
 int     show_archive(int, const char *, FILE *);  int     show_archive(int, const char *, FILE *);
 int     show_file(int, int, const char *, FILE *fp, off_t, union hdr *);  int     show_file(int, int, const char *, FILE *fp, off_t, union hdr *);
 void    print_symbol(const char *, struct nlist *, int);  void    print_symbol(const char *, struct nlist *, int);
 int     elf_symload(const char *, FILE *, off_t, Elf_Ehdr *, Elf_Shdr *);  
   
 #define OPTSTRING_NM    "aABCegnoprsuvVw"  #define OPTSTRING_NM    "aABCegnoprsuvVw"
 const struct option longopts_nm[] = {  const struct option longopts_nm[] = {
Line 265 
Line 276 
         bzero(&exec_head, sizeof(exec_head));          bzero(&exec_head, sizeof(exec_head));
         bytes = fread((char *)&exec_head, 1, sizeof(exec_head), fp);          bytes = fread((char *)&exec_head, 1, sizeof(exec_head), fp);
         if (bytes < sizeof(exec_head)) {          if (bytes < sizeof(exec_head)) {
                 if (bytes < sizeof(exec_head.aout) || IS_ELF(exec_head.elf)) {                  if (bytes < sizeof(exec_head.aout) || IS_ELF(exec_head.elf32)) {
                         warnx("%s: bad format", fname);                          warnx("%s: bad format", fname);
                         (void)fclose(fp);                          (void)fclose(fp);
                         return(1);                          return(1);
Line 274 
Line 285 
         rewind(fp);          rewind(fp);
   
         /* this could be an archive */          /* this could be an archive */
         if (!IS_ELF(exec_head.elf) && N_BADMAG(exec_head.aout)) {          if (!IS_ELF(exec_head.elf32) && N_BADMAG(exec_head.aout)) {
                 if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||                  if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||
                     strncmp(magic, ARMAG, SARMAG)) {                      strncmp(magic, ARMAG, SARMAG)) {
                         warnx("%s: not object file or archive", fname);                          warnx("%s: not object file or archive", fname);
Line 351 
Line 362 
         return (0);          return (0);
 }  }
   
 #define MMAP(ptr, len, prot, flags, fd, off)    do {            \  
         if ((ptr = mmap(NULL, len, prot, flags, fd, off)) == MAP_FAILED) { \  
                 usemmap = 0;                                            \  
                 if (errno != EINVAL)                                    \  
                         warn("mmap");                                   \  
                 else if ((ptr = malloc(len)) == NULL) {                 \  
                         ptr = MAP_FAILED;                               \  
                         warn("malloc");                                 \  
                 } else if (pread(fd, ptr, len, off) != len) {           \  
                         free(ptr);                                      \  
                         ptr = MAP_FAILED;                               \  
                         warn("pread");                                  \  
                 }                                                       \  
         }                                                               \  
 } while (0)  
   
 #define MUNMAP(addr, len)       do {                                    \  
         if (usemmap)                                                    \  
                 munmap(addr, len);                                      \  
         else                                                            \  
                 free(addr);                                             \  
 } while (0)  
   
 /*  /*
  * show_symtab()   * show_symtab()
  *      show archive ranlib index (fs5)   *      show archive ranlib index (fs5)
Line 624 
Line 612 
         return(rval);          return(rval);
 }  }
   
 struct nlist *names;  
 struct nlist **snames;  
 char *stab;  char *stab;
 int nnames, nrawnames, stabsize;  
   
 /*  /*
  * show_file()   * show_file()
Line 639 
Line 624 
 show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union hdr *head)  show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union hdr *head)
 {  {
         u_long text, data, bss, total;          u_long text, data, bss, total;
         struct nlist *np;          struct nlist *np, *names, **snames;
         Elf_Shdr *shdr;          int i, aout, nrawnames, nnames;
           size_t stabsize;
         off_t staboff;          off_t staboff;
         int i, aout;  
   
         aout = 0;          aout = 0;
         if (IS_ELF(head->elf) &&          if (IS_ELF(head->elf32) &&
             head->elf.e_ident[EI_CLASS] == ELF_TARG_CLASS &&              head->elf32.e_ident[EI_CLASS] == ELFCLASS32 &&
             head->elf.e_ident[EI_VERSION] == ELF_TARG_VER) {              head->elf32.e_ident[EI_VERSION] == ELF_TARG_VER) {
                   void *shdr;
   
                 elf_fix_header(&head->elf);                  if (!(shdr = elf32_load_shdrs(name, fp, foff, &head->elf32)))
   
                 if ((shdr = malloc(head->elf.e_shentsize *  
                     head->elf.e_shnum)) == NULL) {  
                         warn("%s: malloc shdr", name);  
                         return (1);                          return (1);
                 }  
   
                 if (fseeko(fp, foff + head->elf.e_shoff, SEEK_SET)) {                  i = issize?
                         warn("%s: fseeko", name);                      elf32_size(&head->elf32, shdr, &text, &data, &bss) :
                         free(shdr);                      elf32_symload(name, fp, foff, &head->elf32, shdr,
                         return (1);                          &names, &snames, &stabsize, &nrawnames);
                 }                  free(shdr);
                   if (i)
                           return (i);
   
                 if (fread(shdr, head->elf.e_shentsize, head->elf.e_shnum,          } else if (IS_ELF(head->elf64) &&
                     fp) != head->elf.e_shnum) {              head->elf64.e_ident[EI_CLASS] == ELFCLASS64 &&
                         warnx("%s: premature EOF", name);              head->elf64.e_ident[EI_VERSION] == ELF_TARG_VER) {
                         free(shdr);                  void *shdr;
                         return(1);  
                 }  
   
                 elf_fix_shdrs(&head->elf, shdr);                  if (!(shdr = elf64_load_shdrs(name, fp, foff, &head->elf64)))
                           return (1);
   
                 if (issize) {                  i = issize?
                         text = data = bss = 0;                      elf64_size(&head->elf64, shdr, &text, &data, &bss) :
                         for (i = 0; i < head->elf.e_shnum; i++) {                      elf64_symload(name, fp, foff, &head->elf64, shdr,
                                 if (!(shdr[i].sh_flags & SHF_ALLOC))                          &names, &snames, &stabsize, &nrawnames);
                                         ;                  free(shdr);
                                 else if (shdr[i].sh_flags & SHF_EXECINSTR ||                  if (i)
                                     !(shdr[i].sh_flags & SHF_WRITE))                          return (i);
                                         text += shdr[i].sh_size;  
                                 else if (shdr[i].sh_type == SHT_NOBITS)  
                                         bss += shdr[i].sh_size;  
                                 else  
                                         data += shdr[i].sh_size;  
                         }  
                         free(shdr);  
                 } else {  
                         i = elf_symload(name, fp, foff, &head->elf, shdr);  
                         free(shdr);  
                         if (i)  
                                 return (i);  
                 }  
   
         } else if (BAD_OBJECT(head->aout)) {          } else if (BAD_OBJECT(head->aout)) {
                 if (warn_fmt)                  if (warn_fmt)
                         warnx("%s: bad format", name);                          warnx("%s: bad format", name);
                 return (1);                  return (1);
         } else do {          } else do {
                   u_int32_t w;
   
                 aout++;                  aout++;
   
                 fix_header_order(&head->aout);                  fix_header_order(&head->aout);
Line 720 
Line 691 
                         return(1);                          return(1);
                 }                  }
   
   #ifdef __LP64__
                   nrawnames = head->aout.a_syms / sizeof(struct nlist32);
   #else
                   nrawnames = head->aout.a_syms / sizeof(*names);
   #endif
                 /* get memory for the symbol table */                  /* get memory for the symbol table */
                 if ((names = malloc(head->aout.a_syms)) == NULL) {                  if ((names = malloc(nrawnames * sizeof(struct nlist))) == NULL) {
                         warn("%s: malloc names", name);                          warn("%s: malloc names", name);
                         return (1);                          return (1);
                 }                  }
                 nrawnames = head->aout.a_syms / sizeof(*names);  
                 if ((snames = malloc(nrawnames * sizeof(struct nlist *))) == NULL) {                  if ((snames = malloc(nrawnames * sizeof(struct nlist *))) == NULL) {
                         warn("%s: malloc snames", name);                          warn("%s: malloc snames", name);
                         free(names);                          free(names);
                         return (1);                          return (1);
                 }                  }
   
   #ifdef __LP64__
                   for (np = names, i = nrawnames; i--; np++) {
                           struct nlist32 nl32;
   
                           if (fread(&nl32, sizeof(nl32), 1, fp) != 1) {
                                   warnx("%s: cannot read symbol table", name);
                                   free(snames);
                                   free(names);
                                   return (1);
                           }
                           np->n_type = nl32.type;
                           np->n_other = nl32.other;
                           if (byte_sex(N_GETMID(head->aout)) != BYTE_ORDER) {
                                   np->n_un.n_strx = swap32(nl32.strx);
                                   np->n_desc = swap16(nl32.desc);
                                   np->n_value = swap32(nl32.value);
                           } else {
                                   np->n_un.n_strx = nl32.strx;
                                   np->n_desc = nl32.desc;
                                   np->n_value = nl32.value;
                           }
                   }
   #else
                 if (fread(names, head->aout.a_syms, 1, fp) != 1) {                  if (fread(names, head->aout.a_syms, 1, fp) != 1) {
                         warnx("%s: cannot read symbol table", name);                          warnx("%s: cannot read symbol table", name);
                         free(snames);                          free(snames);
                         free(names);                          free(names);
                         return(1);                          return (1);
                 }                  }
                 fix_nlists_order(names, nrawnames, N_GETMID(head->aout));                  fix_nlists_order(names, nrawnames, N_GETMID(head->aout));
   #endif
   
                 staboff = ftello(fp);                  staboff = ftello(fp);
                 /*                  /*
Line 746 
Line 746 
                  * The first 4-byte-integer gives the total size of the                   * The first 4-byte-integer gives the total size of the
                  * string table _including_ the size specification itself.                   * string table _including_ the size specification itself.
                  */                   */
                 if (fread(&stabsize, sizeof(stabsize), (size_t)1, fp) != 1) {                  if (fread(&w, sizeof(w), (size_t)1, fp) != 1) {
                         warnx("%s: cannot read stab size", name);                          warnx("%s: cannot read stab size", name);
                         free(snames);                          free(snames);
                         free(names);                          free(names);
                         return(1);                          return(1);
                 }                  }
                 stabsize = fix_long_order(stabsize, N_GETMID(head->aout));                  stabsize = fix_32_order(w, N_GETMID(head->aout));
                 MMAP(stab, stabsize, PROT_READ, MAP_PRIVATE|MAP_FILE,                  MMAP(stab, stabsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
                     fileno(fp), staboff);                      fileno(fp), staboff);
                 if (stab == MAP_FAILED) {                  if (stab == MAP_FAILED) {
Line 847 
Line 847 
         free(names);          free(names);
         MUNMAP(stab, stabsize);          MUNMAP(stab, stabsize);
         return(0);          return(0);
 }  
   
 int  
 elf_symload(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, Elf_Shdr *shdr)  
 {  
         long symsize, shstrsize;  
         struct nlist *np;  
         Elf_Sym sbuf;  
         char *shstr;  
         int i;  
   
         shstrsize = shdr[eh->e_shstrndx].sh_size;  
         if ((shstr = malloc(shstrsize)) == NULL) {  
                 warn("%s: malloc shsrt", name);  
                 return (1);  
         }  
   
         if (fseeko(fp, foff + shdr[eh->e_shstrndx].sh_offset, SEEK_SET)) {  
                 warn("%s: fseeko", name);  
                 free(shstr);  
                 return (1);  
         }  
   
         if (fread(shstr, 1, shstrsize, fp) != shstrsize) {  
                 warnx("%s: premature EOF", name);  
                 free(shstr);  
                 return(1);  
         }  
   
         stab = NULL;  
         names = NULL; snames = NULL;  
         for (i = 0; i < eh->e_shnum; i++) {  
                 if (!strcmp(shstr + shdr[i].sh_name, ELF_STRTAB)) {  
                         stabsize = shdr[i].sh_size;  
                         if (stabsize > SIZE_T_MAX) {  
                                 warnx("%s: corrupt file", name);  
                                 free(shstr);  
                                 return (1);  
                         }  
   
                         MMAP(stab, stabsize, PROT_READ, MAP_PRIVATE|MAP_FILE,  
                             fileno(fp), foff + shdr[i].sh_offset);  
                         if (stab == MAP_FAILED) {  
                                 free(shstr);  
                                 return (1);  
                         }  
                 }  
         }  
         for (i = 0; i < eh->e_shnum; i++) {  
                 if (!strcmp(shstr + shdr[i].sh_name, ELF_SYMTAB)) {  
                         symsize = shdr[i].sh_size;  
                         if (fseeko(fp, foff + shdr[i].sh_offset, SEEK_SET)) {  
                                 warn("%s: fseeko", name);  
                                 if (stab)  
                                         MUNMAP(stab, stabsize);  
                                 free(shstr);  
                                 return (1);  
                         }  
   
                         nrawnames = symsize / sizeof(sbuf);  
                         if ((names = calloc(nrawnames, sizeof(*np))) == NULL) {  
                                 warn("%s: malloc names", name);  
                                 if (stab)  
                                         MUNMAP(stab, stabsize);  
                                 free(names);  
                                 free(shstr);  
                                 return (1);  
                         }  
                         if ((snames = malloc(nrawnames * sizeof(np))) == NULL) {  
                                 warn("%s: malloc snames", name);  
                                 if (stab)  
                                         MUNMAP(stab, stabsize);  
                                 free(shstr);  
                                 free(names);  
                                 free(snames);  
                                 return (1);  
                         }  
   
                         for (np = names; symsize > 0; symsize -= sizeof(sbuf)) {  
                                 if (fread(&sbuf, 1, sizeof(sbuf),  
                                     fp) != sizeof(sbuf)) {  
                                         warn("%s: read symbol", name);  
                                         if (stab)  
                                                 MUNMAP(stab, stabsize);  
                                         free(shstr);  
                                         free(names);  
                                         free(snames);  
                                         return (1);  
                                 }  
   
                                 elf_fix_sym(eh, &sbuf);  
   
                                 if (!sbuf.st_name)  
                                         continue;  
   
                                 elf2nlist(&sbuf, eh, shdr, shstr, np);  
                                 np->n_value = sbuf.st_value;  
                                 np->n_un.n_strx = sbuf.st_name;  
                                 np++;  
                         }  
                         nrawnames = np - names;  
                 }  
         }  
   
         free(shstr);  
         if (stab == NULL) {  
                 warnx("%s: no name list", name);  
                 if (names)  
                         free(names);  
                 if (snames)  
                         free(snames);  
                 return (1);  
         }  
   
         return (0);  
 }  }
   
 char *  char *

Legend:
Removed from v.1.26  
changed lines
  Added in v.1.27