[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.35 and 1.36

version 1.35, 2013/10/21 02:59:52 version 1.36, 2013/10/24 18:28:03
Line 37 
Line 37 
 #include <sys/mman.h>  #include <sys/mman.h>
 #include <a.out.h>  #include <a.out.h>
 #include <elf_abi.h>  #include <elf_abi.h>
   #include <stab.h>
 #include <ar.h>  #include <ar.h>
 #include <ranlib.h>  #include <ranlib.h>
 #include <unistd.h>  #include <unistd.h>
Line 44 
Line 45 
 #include <errno.h>  #include <errno.h>
 #include <ctype.h>  #include <ctype.h>
 #include <link.h>  #include <link.h>
   #ifdef __ELF__
   #include <link_aout.h>
   #endif
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
Line 59 
Line 62 
 #define STRTABMAG       "//"  #define STRTABMAG       "//"
   
 union hdr {  union hdr {
           struct exec aout;
         Elf32_Ehdr elf32;          Elf32_Ehdr elf32;
         Elf64_Ehdr elf64;          Elf64_Ehdr elf64;
 };  };
Line 91 
Line 95 
 int fname(const void *, const void *);  int fname(const void *, const void *);
 int rname(const void *, const void *);  int rname(const void *, const void *);
 int value(const void *, const void *);  int value(const void *, const void *);
 char *otherstring(struct nlist *);  
 int (*sfunc)(const void *, const void *) = fname;  int (*sfunc)(const void *, const void *) = fname;
 char typeletter(struct nlist *);  char *otherstring(struct nlist *);
   char *typestring(unsigned int);
   char typeletter(struct nlist *, int);
   
 /* some macros for symbol type (nlist.n_type) handling */  /* some macros for symbol type (nlist.n_type) handling */
   #define IS_DEBUGGER_SYMBOL(x)   ((x) & N_STAB)
 #define IS_EXTERNAL(x)          ((x) & N_EXT)  #define IS_EXTERNAL(x)          ((x) & N_EXT)
 #define SYMBOL_TYPE(x)          ((x) & (N_TYPE | N_STAB))  #define SYMBOL_TYPE(x)          ((x) & (N_TYPE | N_STAB))
   
 void     pipe2cppfilt(void);  void     pipe2cppfilt(void);
 void     usage(void);  void     usage(void);
 char    *symname(struct nlist *);  char    *symname(struct nlist *, int);
 int     process_file(int, const char *);  int     process_file(int, const char *);
 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 *);  void    print_symbol(const char *, struct nlist *, int);
   
 #define OPTSTRING_NM    "aABCegnoprsuvw"  #define OPTSTRING_NM    "aABCegnoprsuvw"
 const struct option longopts_nm[] = {  const struct option longopts_nm[] = {
Line 250 
Line 256 
         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.elf32) || IS_ELF(exec_head.elf32)) {                  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 259 
Line 265 
         rewind(fp);          rewind(fp);
   
         /* this could be an archive */          /* this could be an archive */
         if (!IS_ELF(exec_head.elf32)) {          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 603 
Line 609 
 {  {
         u_long text, data, bss, total;          u_long text, data, bss, total;
         struct nlist *np, *names, **snames;          struct nlist *np, *names, **snames;
         int i, nrawnames, nnames;          int i, aout, nrawnames, nnames;
         size_t stabsize;          size_t stabsize;
         off_t staboff;          off_t staboff;
   
           aout = 0;
         if (IS_ELF(head->elf32) &&          if (IS_ELF(head->elf32) &&
             head->elf32.e_ident[EI_CLASS] == ELFCLASS32 &&              head->elf32.e_ident[EI_CLASS] == ELFCLASS32 &&
             head->elf32.e_ident[EI_VERSION] == ELF_TARG_VER) {              head->elf32.e_ident[EI_VERSION] == ELF_TARG_VER) {
Line 638 
Line 645 
                 free(shdr);                  free(shdr);
                 if (i)                  if (i)
                         return (i);                          return (i);
         }  
   
           } else if (BAD_OBJECT(head->aout)) {
                   if (warn_fmt)
                           warnx("%s: bad format", name);
                   return (1);
           } else do {
                   u_int32_t w;
   
                   aout++;
   
                   fix_header_order(&head->aout);
   
                   if (issize) {
                           text = head->aout.a_text;
                           data = head->aout.a_data;
                           bss = head->aout.a_bss;
                           break;
                   }
   
                   /* stop if the object file contains no symbol table */
                   if (!head->aout.a_syms) {
                           warnx("%s: no name list", name);
                           return(1);
                   }
   
                   if (fseeko(fp, foff + N_SYMOFF(head->aout), SEEK_SET)) {
                           warn("%s", name);
                           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 */
                   if ((names = calloc(nrawnames, sizeof(struct nlist))) == NULL) {
                           warn("%s: malloc names", name);
                           return (1);
                   }
   
                   if ((snames = calloc(nrawnames, sizeof(struct nlist *))) == NULL) {
                           warn("%s: malloc snames", name);
                           free(names);
                           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) {
                           warnx("%s: cannot read symbol table", name);
                           free(snames);
                           free(names);
                           return (1);
                   }
                   fix_nlists_order(names, nrawnames, N_GETMID(head->aout));
   #endif
   
                   staboff = ftello(fp);
                   /*
                    * Following the symbol table comes the string table.
                    * The first 4-byte-integer gives the total size of the
                    * string table _including_ the size specification itself.
                    */
                   if (fread(&w, sizeof(w), (size_t)1, fp) != 1) {
                           warnx("%s: cannot read stab size", name);
                           free(snames);
                           free(names);
                           return(1);
                   }
                   stabsize = fix_32_order(w, N_GETMID(head->aout));
                   MMAP(stab, stabsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
                       fileno(fp), staboff);
                   if (stab == MAP_FAILED) {
                           free(snames);
                           free(names);
                           return (1);
                   }
   
                   stabsize -= 4;          /* we already have the size */
           } while (0);
   
         if (issize) {          if (issize) {
                 static int first = 1;                  static int first = 1;
   
Line 691 
Line 799 
                         np->n_un.n_name = stab + np->n_un.n_strx;                          np->n_un.n_name = stab + np->n_un.n_strx;
                 else                  else
                         np->n_un.n_name = "";                          np->n_un.n_name = "";
                   if (aout && SYMBOL_TYPE(np->n_type) == N_UNDF && np->n_value)
                           np->n_type = N_COMM | (np->n_type & N_EXT);
                   if (!print_all_symbols && IS_DEBUGGER_SYMBOL(np->n_type))
                           continue;
                 if (print_only_external_symbols && !IS_EXTERNAL(np->n_type))                  if (print_only_external_symbols && !IS_EXTERNAL(np->n_type))
                         continue;                          continue;
                 if (print_only_undefined_symbols &&                  if (print_only_undefined_symbols &&
Line 712 
Line 824 
                 if (show_extensions && snames[i] != names &&                  if (show_extensions && snames[i] != names &&
                     SYMBOL_TYPE((snames[i] -1)->n_type) == N_INDR)                      SYMBOL_TYPE((snames[i] -1)->n_type) == N_INDR)
                         continue;                          continue;
                 print_symbol(name, snames[i]);                  print_symbol(name, snames[i], aout);
         }          }
   
         free(snames);          free(snames);
Line 722 
Line 834 
 }  }
   
 char *  char *
 symname(struct nlist *sym)  symname(struct nlist *sym, int aout)
 {  {
         return sym->n_un.n_name;          if (demangle && sym->n_un.n_name[0] == '_' && aout)
                   return sym->n_un.n_name + 1;
           else
                   return sym->n_un.n_name;
 }  }
   
 /*  /*
Line 732 
Line 847 
  *      show one symbol   *      show one symbol
  */   */
 void  void
 print_symbol(const char *name, struct nlist *sym)  print_symbol(const char *name, struct nlist *sym, int aout)
 {  {
         if (print_file_each_line)          if (print_file_each_line)
                 (void)printf("%s:", name);                  (void)printf("%s:", name);
Line 751 
Line 866 
                         (void)printf("%08lx", sym->n_value);                          (void)printf("%08lx", sym->n_value);
   
                 /* print type information */                  /* print type information */
                 if (show_extensions)                  if (IS_DEBUGGER_SYMBOL(sym->n_type))
                         (void)printf(" %c   ", typeletter(sym));                          (void)printf(" - %02x %04x %5s ", sym->n_other,
                               sym->n_desc&0xffff, typestring(sym->n_type));
                   else if (show_extensions)
                           (void)printf(" %c%2s ", typeletter(sym, aout),
                               otherstring(sym));
                 else                  else
                         (void)printf(" %c ", typeletter(sym));                          (void)printf(" %c ", typeletter(sym, aout));
         }          }
   
         if (SYMBOL_TYPE(sym->n_type) == N_INDR && show_extensions)          if (SYMBOL_TYPE(sym->n_type) == N_INDR && show_extensions) {
                 printf("%s -> %s\n", symname(sym), symname(sym+1));                  printf("%s -> %s\n", symname(sym, aout), symname(sym+1, aout));
           }
         else          else
                 (void)puts(symname(sym));                  (void)puts(symname(sym, aout));
 }  }
   
   char *
   otherstring(struct nlist *sym)
   {
           static char buf[3];
           char *result;
   
           result = buf;
   
           if (N_BIND(sym) == BIND_WEAK)
                   *result++ = 'w';
           if (N_AUX(sym) == AUX_OBJECT)
                   *result++ = 'o';
           else if (N_AUX(sym) == AUX_FUNC)
                   *result++ = 'f';
           *result++ = 0;
           return buf;
   }
   
 /*  /*
    * typestring()
    *      return the a description string for an STAB entry
    */
   char *
   typestring(unsigned int type)
   {
           switch(type) {
           case N_BCOMM:
                   return("BCOMM");
           case N_ECOML:
                   return("ECOML");
           case N_ECOMM:
                   return("ECOMM");
           case N_ENTRY:
                   return("ENTRY");
           case N_FNAME:
                   return("FNAME");
           case N_FUN:
                   return("FUN");
           case N_GSYM:
                   return("GSYM");
           case N_LBRAC:
                   return("LBRAC");
           case N_LCSYM:
                   return("LCSYM");
           case N_LENG:
                   return("LENG");
           case N_LSYM:
                   return("LSYM");
           case N_PC:
                   return("PC");
           case N_PSYM:
                   return("PSYM");
           case N_RBRAC:
                   return("RBRAC");
           case N_RSYM:
                   return("RSYM");
           case N_SLINE:
                   return("SLINE");
           case N_SO:
                   return("SO");
           case N_SOL:
                   return("SOL");
           case N_SSYM:
                   return("SSYM");
           case N_STSYM:
                   return("STSYM");
           }
           return("???");
   }
   
   /*
  * typeletter()   * typeletter()
  *      return a description letter for the given basic type code of an   *      return a description letter for the given basic type code of an
  *      symbol table entry.  The return value will be upper case for   *      symbol table entry.  The return value will be upper case for
  *      external, lower case for internal symbols.   *      external, lower case for internal symbols.
  */   */
 char  char
 typeletter(struct nlist *np)  typeletter(struct nlist *np, int aout)
 {  {
         int ext = IS_EXTERNAL(np->n_type);          int ext = IS_EXTERNAL(np->n_type);
   
         if (np->n_other)          if (!aout && !IS_DEBUGGER_SYMBOL(np->n_type) && np->n_other)
                 return np->n_other;                  return np->n_other;
   
         switch(SYMBOL_TYPE(np->n_type)) {          switch(SYMBOL_TYPE(np->n_type)) {

Legend:
Removed from v.1.35  
changed lines
  Added in v.1.36