Print this page
    
Cstyle cleanup
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/sgs/nm/common/nm.c
          +++ new/usr/src/cmd/sgs/nm/common/nm.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 1988 AT&T
  24   24   * Copyright (c) 1989 AT&T
  25   25   * All Rights Reserved
  26   26   *
  27   27   * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
  28   28   * Copyright 2018 Jason King
  29   29   */
  30   30  
  31   31  #include <stdio.h>
  32   32  #include <stdlib.h>
  33   33  #include <unistd.h>
  34   34  #include <ctype.h>
  35   35  #include <locale.h>
  36   36  #include <libelf.h>
  37   37  #include <sys/elf_SPARC.h>
  38   38  
  39   39  
  40   40  /* exit return codes */
  41   41  #define NOARGS  1
  42   42  #define BADELF  2
  43   43  #define NOALLOC 3
  44   44  
  45   45  #include <fcntl.h>
  46   46  #include <sys/stat.h>
  47   47  #include <errno.h>
  48   48  #include <string.h>
  49   49  #include <dlfcn.h>
  50   50  
  51   51  #include "sgs.h"
  52   52  #include "conv.h"
  53   53  #include "gelf.h"
  54   54  
  55   55  typedef struct {                /* structure to translate symbol table data */
  56   56          int  indx;
  57   57          char *name;
  58   58          GElf_Addr value;
  59   59          GElf_Xword size;
  60   60          int type;
  61   61          int bind;
  62   62          unsigned char other;
  63   63          unsigned int shndx;
  64   64          unsigned int flags;     /* flags relevant to entry */
  65   65  } SYM;
  66   66  
  67   67  #define FLG_SYM_SPECSEC 0x00000001      /* reserved scn index */
  68   68                                          /*      (SHN_ABS, SHN_COMMON, ...) */
  69   69  
  70   70  #define UNDEFINED "U"
  71   71  #define BSS_GLOB  "B"
  72   72  #define BSS_WEAK  "B*"
  73   73  #define BSS_LOCL  "b"
  74   74  #define BSS_SECN  ".bss"
  75   75  #define REG_GLOB  "R"
  76   76  #define REG_WEAK  "R*"
  77   77  #define REG_LOCL  "r"
  78   78  
  79   79  #define OPTSTR  ":APDoxhvnursplLCVefgRTt:" /* option string for getopt() */
  80   80  
  81   81  #define DATESIZE 60
  82   82  
  83   83  #define TYPE 7
  84   84  #define BIND 3
  85   85  
  86   86  #define DEF_MAX_SYM_SIZE 256
  87   87  
  88   88  static char *key[TYPE][BIND];
  89   89  
  90   90  /*
  91   91   * Format type used for printing value and size items.
  92   92   * The non-negative values here are used as array indices into
  93   93   * several arrays found below. Renumbering, or adding items,
  94   94   * will require changes to those arrays as well.
  95   95   */
  96   96  typedef enum {
  97   97          FMT_T_NONE = -1,        /* No format type yet assigned */
  98   98  
  99   99          /* The following are used as array indices */
 100  100          FMT_T_DEC = 0,
 101  101          FMT_T_HEX = 1,
 102  102          FMT_T_OCT = 2
 103  103  } FMT_T;
 104  104  
 105  105  /*
 106  106   * Determine whether a proposed format type is compatible with the current
 107  107   * setting. We allow setting the format as long as it hasn't already
 108  108   * been done, or if the new setting is the same as the current one.
 109  109   */
 110  110  #define COMPAT_FMT_FLAG(new_fmt_flag) \
 111  111          (fmt_flag == FMT_T_NONE) || (fmt_flag == new_fmt_flag)
 112  112  
 113  113  static FMT_T fmt_flag = FMT_T_NONE;     /* format style to use for value/size */
 114  114  
 115  115  static  int     /* flags: ?_flag corresponds to ? option */
 116  116          h_flag = 0,     /* suppress printing of headings */
 117  117          v_flag = 0,     /* sort external symbols by value */
 118  118          n_flag = 0,     /* sort external symbols by name */
 119  119          u_flag = 0,     /* print only undefined symbols */
 120  120          r_flag = 0,     /* prepend object file or archive name */
 121  121                          /* to each symbol name */
 122  122          R_flag = 0,     /* if "-R" issued then prepend archive name, */
 123  123                          /* object file name to each symbol */
 124  124          s_flag = 0,     /* print section name instead of section index */
 125  125          p_flag = 0,     /* produce terse output */
 126  126          P_flag = 0,     /* Portable format output */
 127  127          l_flag = 0,     /* produce long listing of output */
 128  128          L_flag = 0,     /* print SUNW_LDYNSYM instead of SYMTAB */
 129  129          D_flag = 0,     /* print DYNSYM instead of SYMTAB */
 130  130          C_flag = 0,     /* print decoded C++ names */
 131  131          A_flag = 0,     /* File name */
 132  132          e_flag = 0,     /* -e flag */
 133  133          g_flag = 0,     /* -g flag */
 134  134          V_flag = 0;     /* print version information */
 135  135  static char A_header[DEF_MAX_SYM_SIZE+1] = {0};
 136  136  
 137  137  static char *prog_name;
 138  138  static char *archive_name = (char *)0;
 139  139  static int errflag = 0;
 140  140  static void usage();
 141  141  static void each_file(char *);
 142  142  static void process(Elf *, char *);
 143  143  static Elf_Scn * get_scnfd(Elf *, int, int);
 144  144  static void get_symtab(Elf *, char *);
 145  145  static SYM * readsyms(Elf_Data *, GElf_Sxword, Elf *, unsigned int,
 146  146                          unsigned int);
 147  147  static int compare(SYM *, SYM *);
 148  148  static char *lookup(int, int);
 149  149  static int  is_bss_section(unsigned int, Elf *, unsigned int);
 150  150  static void print_ar_files(int, Elf *, char *);
 151  151  static void print_symtab(Elf *, unsigned int, Elf_Scn *, GElf_Shdr *, char *);
 152  152  static void parsename(char *);
 153  153  static void parse_fn_and_print(const char *, char *);
 154  154  static char d_buf[512];
 155  155  static char p_buf[512];
 156  156  static int exotic(const char *s);
 157  157  static void set_A_header(char *);
 158  158  static char *FormatName(char *, const char *);
 159  159  
 160  160  
 161  161  
 162  162  /*
 163  163   * Parses the command line options and then
 164  164   * calls each_file() to process each file.
 165  165   */
 166  166  int
 167  167  main(int argc, char *argv[], char *envp[])
 168  168  {
 169  169          char    *optstr = OPTSTR; /* option string used by getopt() */
 170  170          int     optchar;
 171  171          FMT_T   new_fmt_flag;
 172  172  
 173  173  #ifndef XPG4
 174  174          /*
 175  175           * Check for a binary that better fits this architecture.
 176  176           */
 177  177          (void) conv_check_native(argv, envp);
 178  178  #endif
 179  179  
 180  180          /* table of keyletters for use with -p and -P options */
 181  181          key[STT_NOTYPE][STB_LOCAL] = "n";
 182  182          key[STT_NOTYPE][STB_GLOBAL] = "N";
 183  183          key[STT_NOTYPE][STB_WEAK] = "N*";
 184  184          key[STT_OBJECT][STB_LOCAL] = "d";
 185  185          key[STT_OBJECT][STB_GLOBAL] = "D";
 186  186          key[STT_OBJECT][STB_WEAK] = "D*";
 187  187          key[STT_FUNC][STB_LOCAL] = "t";
 188  188          key[STT_FUNC][STB_GLOBAL] = "T";
 189  189          key[STT_FUNC][STB_WEAK] = "T*";
 190  190          key[STT_SECTION][STB_LOCAL] = "s";
 191  191          key[STT_SECTION][STB_GLOBAL] = "S";
 192  192          key[STT_SECTION][STB_WEAK] = "S*";
 193  193          key[STT_FILE][STB_LOCAL] = "f";
 194  194          key[STT_FILE][STB_GLOBAL] = "F";
 195  195          key[STT_FILE][STB_WEAK] = "F*";
 196  196          key[STT_COMMON][STB_LOCAL] = "c";
 197  197          key[STT_COMMON][STB_GLOBAL] = "C";
 198  198          key[STT_COMMON][STB_WEAK] = "C*";
 199  199          key[STT_TLS][STB_LOCAL] = "l";
 200  200          key[STT_TLS][STB_GLOBAL] = "L";
 201  201          key[STT_TLS][STB_WEAK] = "L*";
 202  202  
 203  203          prog_name = argv[0];
 204  204  
 205  205          (void) setlocale(LC_ALL, "");
 206  206  #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 207  207  #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 208  208  #endif
 209  209          (void) textdomain(TEXT_DOMAIN);
 210  210  
 211  211          while ((optchar = getopt(argc, argv, optstr)) != -1) {
 212  212                  switch (optchar) {
 213  213                  case 'o':       if (COMPAT_FMT_FLAG(FMT_T_OCT))
 214  214                                          fmt_flag = FMT_T_OCT;
 215  215                                  else
 216  216                                          (void) fprintf(stderr, gettext(
 217  217                                              "%s: -x or -t set, -o ignored\n"),
 218  218                                              prog_name);
 219  219                                  break;
 220  220                  case 'x':       if (COMPAT_FMT_FLAG(FMT_T_HEX))
 221  221                                          fmt_flag = FMT_T_HEX;
 222  222                                  else
 223  223                                          (void) fprintf(stderr, gettext(
 224  224                                              "%s: -o or -t set, -x ignored\n"),
 225  225                                              prog_name);
 226  226                                  break;
 227  227                  case 'h':       h_flag = 1;
 228  228                                  break;
 229  229                  case 'v':       if (!n_flag)
 230  230                                          v_flag = 1;
 231  231                                  else
 232  232                                          (void) fprintf(stderr, gettext(
 233  233                                              "%s: -n set, -v ignored\n"),
 234  234                                              prog_name);
 235  235                                  break;
 236  236                  case 'n':       if (!v_flag)
 237  237                                          n_flag = 1;
 238  238                                  else
 239  239                                          (void) fprintf(stderr, gettext(
 240  240                                              "%s: -v set, -n ignored\n"),
 241  241                                              prog_name);
 242  242                                  break;
 243  243                  case 'u':       if (!e_flag && !g_flag)
 244  244                                          u_flag = 1;
 245  245                                  else
 246  246                                          (void) fprintf(stderr, gettext(
 247  247                                              "%s: -e or -g set, -u ignored\n"),
 248  248                                              prog_name);
 249  249                                  break;
 250  250                  case 'e':       if (!u_flag && !g_flag)
 251  251                                          e_flag = 1;
 252  252                                  else
 253  253                                          (void) fprintf(stderr, gettext(
  
    | ↓ open down ↓ | 253 lines elided | ↑ open up ↑ | 
 254  254                                              "%s: -u or -g set, -e ignored\n"),
 255  255                                              prog_name);
 256  256                                  break;
 257  257                  case 'g':       if (!u_flag && !e_flag)
 258  258                                          g_flag = 1;
 259  259                                  else
 260  260                                          (void) fprintf(stderr, gettext(
 261  261                                              "%s: -u or -e set, -g ignored\n"),
 262  262                                              prog_name);
 263  263                                  break;
 264      -                case 'r':       if (R_flag) {
      264 +                case 'r':       if (R_flag) {
 265  265                                          R_flag = 0;
 266  266                                          (void) fprintf(stderr, gettext(
 267  267                                              "%s: -r set, -R ignored\n"),
 268  268                                              prog_name);
 269  269                                  }
 270  270                                  r_flag = 1;
 271  271                                  break;
 272  272                  case 's':       s_flag = 1;
 273  273                                  break;
 274  274                  case 'p':       if (P_flag == 1) {
 275  275                                          (void) fprintf(stderr, gettext(
 276  276                                              "nm: -P set. -p ignored\n"));
 277  277                                  } else
 278  278                                          p_flag = 1;
 279  279                                  break;
 280  280                  case 'P':       if (p_flag == 1) {
 281  281                                          (void) fprintf(stderr, gettext(
 282  282                                              "nm: -p set. -P ignored\n"));
 283  283                                  } else
 284  284                                          P_flag = 1;
 285  285                                  break;
 286  286                  case 'l':       l_flag = 1;
 287  287                                  break;
 288  288                  case 'L':       if (D_flag == 1) {
 289  289                                          (void) fprintf(stderr, gettext(
 290  290                                              "nm: -D set. -L ignored\n"));
 291  291                                  } else
 292  292                                          L_flag = 1;
 293  293                                  break;
 294  294                  case 'D':       if (L_flag == 1) {
 295  295                                          (void) fprintf(stderr, gettext(
 296  296                                              "nm: -L set. -D ignored\n"));
 297  297                                  } else
 298  298                                          D_flag = 1;
 299  299                                  break;
 300  300                  case 'C':
 301  301                                  C_flag = 1;
 302  302                                  break;
 303  303                  case 'A':       A_flag = 1;
 304  304                                  break;
 305  305                  case 'V':       V_flag = 1;
 306  306                                  (void) fprintf(stderr, "nm: %s %s\n",
 307  307                                      (const char *)SGU_PKG,
 308  308                                      (const char *)SGU_REL);
 309  309                                  break;
 310  310                  case 'f':       /* -f is a noop, see man page */
 311  311                                  break;
 312  312                  case 'R':       if (!r_flag)
 313  313                                          R_flag = 1;
 314  314                                  else
 315  315                                          (void) fprintf(stderr, gettext(
 316  316                                              "%s: -r set, -R ignored\n"),
 317  317                                              prog_name);
 318  318                                  break;
 319  319                  case 'T':
 320  320                                  break;
 321  321                  case 't':       if (strcmp(optarg, "o") == 0) {
 322  322                                          new_fmt_flag = FMT_T_OCT;
 323  323                                  } else if (strcmp(optarg, "d") == 0) {
 324  324                                          new_fmt_flag = FMT_T_DEC;
 325  325                                  } else if (strcmp(optarg, "x") == 0) {
 326  326                                          new_fmt_flag = FMT_T_HEX;
 327  327                                  } else {
 328  328                                          new_fmt_flag = FMT_T_NONE;
 329  329                                  }
 330  330                                  if (new_fmt_flag == FMT_T_NONE) {
 331  331                                          errflag += 1;
 332  332                                          (void) fprintf(stderr, gettext(
 333  333  "nm: -t requires radix value (d, o, x): %s\n"), optarg);
 334  334                                  } else if (COMPAT_FMT_FLAG(new_fmt_flag)) {
 335  335                                          fmt_flag = new_fmt_flag;
 336  336                                  } else {
 337  337                                          (void) fprintf(stderr, gettext(
 338  338                                  "nm: -t or -o or -x set. -t ignored.\n"));
 339  339                                  }
 340  340                                  break;
 341  341                  case ':':       errflag += 1;
 342  342                                  (void) fprintf(stderr, gettext(
 343  343                                      "nm: %c requires operand\n"), optopt);
 344  344                                  break;
 345  345                  case '?':       errflag += 1;
 346  346                                  break;
 347  347                  default:        break;
 348  348                  }
 349  349          }
 350  350  
 351  351          if (errflag || (optind >= argc)) {
 352  352                  if (!(V_flag && (argc == 2))) {
 353  353                          usage();
 354  354                          exit(NOARGS);
 355  355                  }
 356  356          }
 357  357  
 358  358          /*
 359  359           * If no explicit format style was specified, set the default
 360  360           * here. In general, the default is for value and size items
 361  361           * to be displayed in decimal format. The exception is that
 362  362           * the default for -P is hexidecimal.
 363  363           */
 364  364          if (fmt_flag == FMT_T_NONE)
 365  365                  fmt_flag = P_flag ? FMT_T_HEX : FMT_T_DEC;
 366  366  
 367  367  
 368  368          while (optind < argc) {
 369  369                  each_file(argv[optind]);
 370  370                  optind++;
 371  371          }
 372  372          return (errflag);
 373  373  }
 374  374  
 375  375  /*
 376  376   * Print out a usage message in short form when program is invoked
 377  377   * with insufficient or no arguments, and in long form when given
 378  378   * either a ? or an invalid option.
 379  379   */
 380  380  static void
 381  381  usage()
 382  382  {
 383  383          (void) fprintf(stderr, gettext(
 384  384  "Usage: nm [-ACDhLlnPpRrsTVv] [-efox] [-g | -u] [-t d|o|x] file ...\n"));
 385  385  }
 386  386  
 387  387  /*
 388  388   * Takes a filename as input.  Test first for a valid version
 389  389   * of libelf.a and exit on error.  Process each valid file
 390  390   * or archive given as input on the command line.  Check
 391  391   * for file type.  If it is an archive, call print_ar_files
 392  392   * to process each member of the archive in the same manner
 393  393   * as object files on the command line.  The same tests for
 394  394   * valid object file type apply to regular archive members.
 395  395   * If it is an ELF object file, process it; otherwise
 396  396   * warn that it is an invalid file type and return from
 397  397   * processing the file.
 398  398   */
 399  399  
 400  400  static void
 401  401  each_file(char *filename)
 402  402  {
 403  403          Elf     *elf_file;
 404  404          int     fd;
 405  405          Elf_Kind   file_type;
 406  406  
 407  407          struct stat64 buf;
 408  408  
 409  409          Elf_Cmd cmd;
 410  410          errno = 0;
 411  411          if (stat64(filename, &buf) == -1)       {
 412  412                  (void) fprintf(stderr, "%s: ", prog_name);
 413  413                  perror(filename);
 414  414                  errflag++;
 415  415                  return;
 416  416          }
 417  417          if (elf_version(EV_CURRENT) == EV_NONE) {
 418  418                  (void) fprintf(stderr, gettext(
 419  419                      "%s: %s: libelf is out of date\n"),
 420  420                      prog_name, filename);
 421  421                  exit(BADELF);
 422  422          }
 423  423  
 424  424          if ((fd = open((filename), O_RDONLY)) == -1) {
 425  425                  (void) fprintf(stderr, gettext("%s: %s: cannot read file\n"),
 426  426                      prog_name, filename);
 427  427                  errflag++;
 428  428                  return;
 429  429          }
 430  430          cmd = ELF_C_READ;
 431  431          if ((elf_file = elf_begin(fd, cmd, (Elf *) 0)) == NULL) {
 432  432                  (void) fprintf(stderr,
 433  433                      "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1));
 434  434                  errflag++;
 435  435                  (void) close(fd);
 436  436                  return;
 437  437          }
 438  438          file_type = elf_kind(elf_file);
 439  439          if (file_type == ELF_K_AR) {
 440  440                  print_ar_files(fd, elf_file, filename);
 441  441          } else {
 442  442                  if (file_type == ELF_K_ELF) {
 443  443  #ifndef XPG4
 444  444                          if (u_flag && !h_flag) {
 445  445                                  /*
 446  446                                   * u_flag is specified.
 447  447                                   */
 448  448                                  if (p_flag)
 449  449                                          (void) printf("\n\n%s:\n\n", filename);
 450  450                                  else
 451  451                                          (void) printf(gettext(
 452  452                                  "\n\nUndefined symbols from %s:\n\n"),
 453  453                                              filename);
 454  454                          } else if (!h_flag & !P_flag)
 455  455  #else
 456  456                          if (!h_flag & !P_flag)
 457  457  #endif
 458  458                          {
 459  459                                  if (p_flag)
 460  460                                          (void) printf("\n\n%s:\n", filename);
 461  461                                  else {
 462  462                                          if (A_flag != 0)
 463  463                                                  (void) printf("\n\n%s%s:\n",
 464  464                                                      A_header, filename);
 465  465                                          else
 466  466                                                  (void) printf("\n\n%s:\n",
 467  467                                                      filename);
 468  468                                  }
 469  469                          }
 470  470                          archive_name = (char *)0;
 471  471                          process(elf_file, filename);
 472  472                  } else {
 473  473                          (void) fprintf(stderr, gettext(
 474  474                              "%s: %s: invalid file type\n"),
 475  475                              prog_name, filename);
 476  476                          errflag++;
 477  477                  }
 478  478          }
 479  479          (void) elf_end(elf_file);
 480  480          (void) close(fd);
 481  481  }
 482  482  
 483  483  /*
 484  484   * Get the ELF header and, if it exists, call get_symtab()
 485  485   * to begin processing of the file; otherwise, return from
 486  486   * processing the file with a warning.
 487  487   */
 488  488  static void
 489  489  process(Elf *elf_file, char *filename)
 490  490  {
 491  491          GElf_Ehdr ehdr;
 492  492  
 493  493          if (gelf_getehdr(elf_file, &ehdr) == NULL) {
 494  494                  (void) fprintf(stderr,
 495  495                      "%s: %s: %s\n", prog_name, filename, elf_errmsg(-1));
 496  496                  return;
 497  497          }
 498  498  
 499  499          set_A_header(filename);
 500  500          get_symtab(elf_file, filename);
 501  501  }
 502  502  
 503  503  /*
 504  504   * Get section descriptor for the associated string table
 505  505   * and verify that the type of the section pointed to is
 506  506   * indeed of type STRTAB.  Returns a valid section descriptor
 507  507   * or NULL on error.
 508  508   */
 509  509  static Elf_Scn *
 510  510  get_scnfd(Elf * e_file, int shstrtab, int SCN_TYPE)
 511  511  {
 512  512          Elf_Scn *fd_scn;
 513  513          GElf_Shdr shdr;
 514  514  
 515  515          if ((fd_scn = elf_getscn(e_file, shstrtab)) == NULL) {
 516  516                  return (NULL);
 517  517          }
 518  518  
 519  519          (void) gelf_getshdr(fd_scn, &shdr);
 520  520          if (shdr.sh_type != SCN_TYPE) {
 521  521                  return (NULL);
 522  522          }
 523  523          return (fd_scn);
 524  524  }
 525  525  
 526  526  
 527  527  /*
 528  528   * Print the symbol table.  This function does not print the contents
 529  529   * of the symbol table but sets up the parameters and then calls
 530  530   * print_symtab to print the symbols.  This function does not assume
 531  531   * that there is only one section of type SYMTAB.  Input is an opened
 532  532   * ELF file, a pointer to the ELF header, and the filename.
 533  533   */
 534  534  static void
 535  535  get_symtab(Elf *elf_file, char *filename)
 536  536  {
 537  537          Elf_Scn *scn, *scnfd;
 538  538          Elf_Data *data;
 539  539          GElf_Word symtabtype;
 540  540          size_t shstrndx;
 541  541  
 542  542          if (elf_getshdrstrndx(elf_file, &shstrndx) == -1) {
 543  543                  (void) fprintf(stderr, gettext(
 544  544                      "%s: %s: cannot get e_shstrndx\n"),
 545  545                      prog_name, filename);
 546  546                  return;
 547  547          }
 548  548  
 549  549          /* get section header string table */
 550  550          scnfd = get_scnfd(elf_file, shstrndx, SHT_STRTAB);
 551  551          if (scnfd == NULL) {
 552  552                  (void) fprintf(stderr, gettext(
 553  553                      "%s: %s: cannot get string table\n"),
 554  554                      prog_name, filename);
 555  555                  return;
 556  556          }
 557  557  
 558  558          data = elf_getdata(scnfd, NULL);
 559  559          if (data->d_size == 0) {
 560  560                  (void) fprintf(stderr, gettext(
 561  561                      "%s: %s: no data in string table\n"),
 562  562                      prog_name, filename);
 563  563                  return;
 564  564          }
 565  565  
 566  566          if (D_flag)
 567  567                  symtabtype = SHT_DYNSYM;
 568  568          else if (L_flag)
 569  569                  symtabtype = SHT_SUNW_LDYNSYM;
 570  570          else
 571  571                  symtabtype = SHT_SYMTAB;
 572  572  
 573  573          scn = 0;
 574  574          while ((scn = elf_nextscn(elf_file, scn)) != 0) {
 575  575                  GElf_Shdr shdr;
 576  576  
 577  577                  if (gelf_getshdr(scn, &shdr) == NULL) {
 578  578                          (void) fprintf(stderr, "%s: %s: %s:\n",
 579  579                              prog_name, filename, elf_errmsg(-1));
 580  580                          return;
 581  581                  }
 582  582  
 583  583                  if (shdr.sh_type == symtabtype) {
 584  584                          print_symtab(elf_file, shstrndx, scn,
 585  585                              &shdr, filename);
 586  586                  }
 587  587          } /* end while */
 588  588  }
 589  589  
 590  590  /*
 591  591   * Process member files of an archive.  This function provides
 592  592   * a loop through an archive equivalent the processing of
 593  593   * each_file for individual object files.
 594  594   */
 595  595  static void
 596  596  print_ar_files(int fd, Elf * elf_file, char *filename)
 597  597  {
 598  598          Elf_Arhdr  *p_ar;
 599  599          Elf     *arf;
 600  600          Elf_Cmd    cmd;
 601  601          Elf_Kind   file_type;
 602  602  
 603  603  
 604  604          cmd = ELF_C_READ;
 605  605          archive_name = filename;
 606  606          while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
 607  607                  p_ar = elf_getarhdr(arf);
 608  608                  if (p_ar == NULL) {
 609  609                          (void) fprintf(stderr, "%s: %s: %s\n",
 610  610                              prog_name, filename, elf_errmsg(-1));
 611  611                          return;
 612  612                  }
 613  613                  if (p_ar->ar_name[0] == '/') {
 614  614                          cmd = elf_next(arf);
 615  615                          (void) elf_end(arf);
 616  616                          continue;
 617  617                  }
 618  618  
 619  619                  if (!h_flag & !P_flag) {
 620  620                          if (p_flag)
 621  621                                  (void) printf("\n\n%s[%s]:\n",
 622  622                                      filename, p_ar->ar_name);
 623  623                          else {
 624  624                                  if (A_flag != 0)
 625  625                                          (void) printf("\n\n%s%s[%s]:\n",
 626  626                                              A_header, filename, p_ar->ar_name);
 627  627                                  else
 628  628                                          (void) printf("\n\n%s[%s]:\n",
 629  629                                              filename, p_ar->ar_name);
 630  630                          }
 631  631                  }
 632  632                  file_type = elf_kind(arf);
 633  633                  if (file_type == ELF_K_ELF) {
 634  634                          process(arf, p_ar->ar_name);
 635  635                  } else {
 636  636                          (void) fprintf(stderr, gettext(
 637  637                              "%s: %s: invalid file type\n"),
 638  638                              prog_name, p_ar->ar_name);
 639  639                          cmd = elf_next(arf);
 640  640                          (void) elf_end(arf);
 641  641                          errflag++;
 642  642                          continue;
 643  643                  }
 644  644  
 645  645                  cmd = elf_next(arf);
 646  646                  (void) elf_end(arf);
 647  647          } /* end while */
 648  648  }
 649  649  
 650  650  static void print_header(int);
 651  651  #ifndef XPG4
 652  652  static void print_with_uflag(SYM *, char *);
 653  653  #endif
 654  654  static void print_with_pflag(int, Elf *, unsigned int, SYM *, char *);
 655  655  static void print_with_Pflag(int, Elf *, unsigned int, SYM *);
 656  656  static void print_with_otherflags(int, Elf *, unsigned int,
 657  657                  SYM *, char *);
 658  658  /*
 659  659   * Print the symbol table according to the flags that were
  
    | ↓ open down ↓ | 385 lines elided | ↑ open up ↑ | 
 660  660   * set, if any.  Input is an opened ELF file, the section name,
 661  661   * the section header, the section descriptor, and the filename.
 662  662   * First get the symbol table with a call to elf_getdata.
 663  663   * Then translate the symbol table data in memory by calling
 664  664   * readsyms().  This avoids duplication of function calls
 665  665   * and improves sorting efficiency.  qsort is used when sorting
 666  666   * is requested.
 667  667   */
 668  668  static void
 669  669  print_symtab(Elf *elf_file, unsigned int shstrndx,
 670      -        Elf_Scn *p_sd, GElf_Shdr *shdr, char *filename)
      670 +    Elf_Scn *p_sd, GElf_Shdr *shdr, char *filename)
 671  671  {
 672  672  
 673  673          Elf_Data * sd;
 674  674          SYM     *sym_data;
 675  675          SYM     *s;
 676  676          GElf_Sxword     count = 0;
 677  677          const int ndigits_arr[] = {
 678  678                  10,             /* FMT_T_DEC */
 679  679                  8,              /* FMT_T_HEX */
 680  680                  11,             /* FMT_T_OCT */
 681  681          };
 682  682          int ndigits;
 683  683  
 684  684          /*
 685  685           * Determine # of digits to use for each numeric value.
 686  686           */
 687  687          ndigits = ndigits_arr[fmt_flag];
 688  688          if (gelf_getclass(elf_file) == ELFCLASS64)
 689  689                  ndigits *= 2;
 690  690  
 691  691          /*
 692  692           * print header
 693  693           */
 694  694          print_header(ndigits);
 695  695  
 696  696          /*
 697  697           * get symbol table data
 698  698           */
 699  699          if (((sd = elf_getdata(p_sd, NULL)) == NULL) || (sd->d_size == 0)) {
 700  700                  (void) fprintf(stderr,
 701  701                      gettext("%s: %s: no symbol table data\n"),
 702  702                      prog_name, filename);
 703  703                  return;
 704  704          }
 705  705          count = shdr->sh_size / shdr->sh_entsize;
 706  706  
 707  707          /*
 708  708           * translate symbol table data
 709  709           */
 710  710          sym_data = readsyms(sd, count, elf_file, shdr->sh_link,
 711  711              (unsigned int)elf_ndxscn(p_sd));
 712  712          if (sym_data == NULL) {
 713  713                  (void) fprintf(stderr, gettext(
 714  714                      "%s: %s: problem reading symbol data\n"),
 715  715                      prog_name, filename);
 716  716                  return;
 717  717          }
 718  718          qsort((char *)sym_data, count-1, sizeof (SYM),
 719  719              (int (*)(const void *, const void *))compare);
 720  720          s = sym_data;
 721  721          while (count > 1) {
 722  722  #ifndef XPG4
 723  723                  if (u_flag) {
 724  724                          /*
 725  725                           * U_flag specified
 726  726                           */
 727  727                          print_with_uflag(sym_data, filename);
 728  728                  } else if (p_flag)
 729  729  #else
 730  730                  if (p_flag)
 731  731  #endif
 732  732                          print_with_pflag(ndigits, elf_file, shstrndx,
 733  733                              sym_data, filename);
 734  734                  else if (P_flag)
 735  735                          print_with_Pflag(ndigits, elf_file, shstrndx,
 736  736                              sym_data);
 737  737                  else
 738  738                          print_with_otherflags(ndigits, elf_file,
 739  739                              shstrndx, sym_data, filename);
 740  740                  sym_data++;
 741  741                  count--;
 742  742          }
 743  743  
 744  744          free(s);                /* allocated in readsym() */
 745  745  }
 746  746  
 747  747  /*
 748  748   * Return appropriate keyletter(s) for -p option.
 749  749   * Returns an index into the key[][] table or NULL if
 750  750   * the value of the keyletter is unknown.
 751  751   */
 752  752  static char *
 753  753  lookup(int a, int b)
 754  754  {
 755  755          return (((a < TYPE) && (b < BIND)) ? key[a][b] : NULL);
 756  756  }
 757  757  
 758  758  /*
 759  759   * Return TRUE(1) if the given section is ".bss" for "-p" option.
 760  760   * Return FALSE(0) if not ".bss" section.
 761  761   */
 762  762  static int
 763  763  is_bss_section(unsigned int shndx, Elf * elf_file, unsigned int shstrndx)
 764  764  {
 765  765          Elf_Scn *scn            = elf_getscn(elf_file, shndx);
 766  766          char    *sym_name;
 767  767  
 768  768          if (scn != NULL) {
 769  769                  GElf_Shdr shdr;
 770  770                  (void) gelf_getshdr(scn, &shdr);
 771  771                  sym_name = elf_strptr(elf_file, shstrndx, shdr.sh_name);
 772  772                  if (strcmp(BSS_SECN, sym_name) == 0)
 773  773                          return (1);
 774  774          }
  
    | ↓ open down ↓ | 94 lines elided | ↑ open up ↑ | 
 775  775          return (0);
 776  776  }
 777  777  
 778  778  /*
 779  779   * Translate symbol table data particularly for sorting.
 780  780   * Input is the symbol table data structure, number of symbols,
 781  781   * opened ELF file, and the string table link offset.
 782  782   */
 783  783  static SYM *
 784  784  readsyms(Elf_Data * data, GElf_Sxword num, Elf *elf,
 785      -        unsigned int link, unsigned int symscnndx)
      785 +    unsigned int link, unsigned int symscnndx)
 786  786  {
 787  787          SYM             *s, *buf;
 788  788          GElf_Sym        sym;
 789  789          Elf32_Word      *symshndx = 0;
 790  790          unsigned int    nosymshndx = 0;
 791  791          int             i;
 792  792  
 793  793          if ((buf = calloc(num, sizeof (SYM))) == NULL) {
 794  794                  (void) fprintf(stderr, gettext("%s: cannot allocate memory\n"),
 795  795                      prog_name);
 796  796                  return (NULL);
 797  797          }
 798  798  
 799  799          s = buf;        /* save pointer to head of array */
 800  800  
 801  801          for (i = 1; i < num; i++, buf++) {
 802  802                  (void) gelf_getsym(data, i, &sym);
 803  803  
 804  804                  buf->indx = i;
 805  805                  /* allow to work on machines where NULL-derefs dump core */
 806  806                  if (sym.st_name == 0)
 807  807                          buf->name = "";
 808  808                  else if (C_flag) {
 809  809                          const char *dn = NULL;
 810  810                          char *name = (char *)elf_strptr(elf, link, sym.st_name);
 811  811  
 812  812                          dn = conv_demangle_name(name);
 813  813                          if (dn != name) {
 814  814                                  name = FormatName(name, dn);
 815  815                                  free((void *)dn);
 816  816                          } else if (exotic(name)) {
 817  817                                  name = FormatName(name, d_buf);
 818  818                          }
 819  819                          buf->name = name;
 820  820                  }
 821  821                  else
 822  822                          buf->name = (char *)elf_strptr(elf, link, sym.st_name);
 823  823  
 824  824                  buf->value      = sym.st_value;
 825  825                  buf->size       = sym.st_size;
 826  826                  buf->type       = GELF_ST_TYPE(sym.st_info);
 827  827                  buf->bind       = GELF_ST_BIND(sym.st_info);
 828  828                  buf->other      = sym.st_other;
 829  829                  if ((sym.st_shndx == SHN_XINDEX) &&
 830  830                      (symshndx == 0) && (nosymshndx == 0)) {
 831  831                          Elf_Scn         *_scn;
 832  832                          GElf_Shdr       _shdr;
 833  833                          _scn = 0;
 834  834                          while ((_scn = elf_nextscn(elf, _scn)) != 0) {
 835  835                                  if (gelf_getshdr(_scn, &_shdr) == 0)
 836  836                                          break;
 837  837                                  if ((_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
 838  838                                      (_shdr.sh_link == symscnndx)) {
 839  839                                          Elf_Data        *_data;
 840  840                                          if ((_data = elf_getdata(_scn,
 841  841                                              0)) != 0) {
 842  842                                                  symshndx =
 843  843                                                      (Elf32_Word *)_data->d_buf;
 844  844                                                  break;
 845  845                                          }
 846  846                                  }
 847  847                          }
 848  848                          nosymshndx = 1;
 849  849                  }
 850  850                  if ((symshndx) && (sym.st_shndx == SHN_XINDEX)) {
 851  851                          buf->shndx = symshndx[i];
 852  852                  } else {
 853  853                          buf->shndx      = sym.st_shndx;
 854  854                          if (sym.st_shndx >= SHN_LORESERVE)
 855  855                                  buf->flags |= FLG_SYM_SPECSEC;
 856  856                  }
 857  857          }       /* end for loop */
 858  858          return (s);
 859  859  }
 860  860  
 861  861  /*
 862  862   * compare either by name or by value for sorting.
 863  863   * This is the comparison function called by qsort to
 864  864   * sort the symbols either by name or value when requested.
 865  865   */
 866  866  static int
 867  867  compare(SYM *a, SYM *b)
 868  868  {
 869  869          if (v_flag) {
 870  870                  if (a->value > b->value)
 871  871                          return (1);
 872  872                  else
 873  873                          return ((a->value == b->value) -1);
 874  874          } else
 875  875                  return ((int)strcoll(a->name, b->name));
 876  876  }
 877  877  
 878  878  /*
 879  879   * Set up a header line for -A option.
 880  880   */
 881  881  static void
 882  882  set_A_header(char *fname)
 883  883  {
 884  884          if (A_flag == 0)
 885  885                  return;
 886  886  
 887  887          if (archive_name == (char *)0) {
 888  888                  (void) snprintf(A_header, sizeof (A_header), "%s: ", fname);
 889  889          } else {
 890  890                  (void) snprintf(A_header, sizeof (A_header), "%s[%s]: ",
 891  891                      archive_name, fname);
 892  892          }
 893  893  }
 894  894  
 895  895  /*
 896  896   * output functions
 897  897   *      The following functions are called from
 898  898   *      print_symtab().
 899  899   */
 900  900  
 901  901  /*
 902  902   * Print header line if needed.
 903  903   *
 904  904   * entry:
 905  905   *      ndigits - # of digits to be used to format an integer
 906  906   *              value, not counting any '0x' (hex) or '0' (octal) prefix.
 907  907   */
 908  908  static void
 909  909  print_header(int ndigits)
 910  910  {
 911  911          const char *fmt;
 912  912          const char *section_title;
 913  913          const int pad[] = {     /* Extra prefix characters for format */
 914  914                  1,              /* FMT_T_DEC: '|' */
 915  915                  3,              /* FMT_T_HEX: '|0x' */
 916  916                  2,              /* FMT_T_OCT: '|0' */
 917  917          };
 918  918          if (
 919  919  #ifndef XPG4
 920  920              !u_flag &&
 921  921  #endif
 922  922              !h_flag && !p_flag && !P_flag) {
 923  923                  (void) printf("\n");
 924  924                  if (!s_flag) {
 925  925                          fmt = "%-9s%-*s%-*s%-6s%-6s%-6s%-8s%s\n\n";
 926  926                          section_title = "Shndx";
 927  927                  } else {
 928  928                          fmt = "%-9s%-*s%-*s%-6s%-6s%-6s%-15s%s\n\n";
 929  929                          section_title = "Shname";
 930  930                  }
 931  931                  if (A_flag != 0)
 932  932                          (void) printf("%s", A_header);
 933  933                  ndigits += pad[fmt_flag];
 934  934                  (void) printf(fmt, "[Index]", ndigits, " Value",
 935  935                      ndigits, " Size", "Type", "Bind",
 936  936                      "Other", section_title, "Name");
 937  937          }
 938  938  }
 939  939  
 940  940  /*
 941  941   * If the symbol can be printed, then return 1.
 942  942   * If the symbol can not be printed, then return 0.
 943  943   */
 944  944  static int
 945  945  is_sym_print(SYM *sym_data)
 946  946  {
 947  947          /*
 948  948           * If -u flag is specified,
 949  949           *      the symbol has to be undefined.
 950  950           */
 951  951          if (u_flag != 0) {
 952  952                  if ((sym_data->shndx == SHN_UNDEF) &&
 953  953                      (strlen(sym_data->name) != 0))
 954  954                          return (1);
 955  955                  else
 956  956                          return (0);
 957  957          }
 958  958  
 959  959          /*
 960  960           * If -e flag is specified,
 961  961           *      the symbol has to be global or static.
 962  962           */
 963  963          if (e_flag != 0) {
 964  964                  switch (sym_data->type) {
 965  965                  case STT_NOTYPE:
 966  966                  case STT_OBJECT:
 967  967                  case STT_FUNC:
 968  968                  case STT_COMMON:
 969  969                  case STT_TLS:
 970  970                          switch (sym_data->bind) {
 971  971                          case STB_LOCAL:
 972  972                          case STB_GLOBAL:
 973  973                          case STB_WEAK:
 974  974                                  return (1);
 975  975                          default:
 976  976                                  return (0);
 977  977                          }
 978  978                  default:
 979  979                          return (0);
 980  980                  }
 981  981          }
 982  982  
 983  983          /*
 984  984           * If -g is specified,
 985  985           *      the symbol has to be global.
 986  986           */
 987  987          if (g_flag != 0) {
 988  988                  switch (sym_data->type) {
 989  989                  case STT_NOTYPE:
 990  990                  case STT_OBJECT:
 991  991                  case STT_FUNC:
 992  992                  case STT_COMMON:
 993  993                  case STT_TLS:
 994  994                          switch (sym_data->bind) {
 995  995                          case STB_GLOBAL:
 996  996                          case STB_WEAK:
 997  997                                  return (1);
 998  998                          default:
 999  999                                  return (0);
1000 1000                          }
1001 1001                  default:
1002 1002                          return (0);
1003 1003                  }
1004 1004          }
1005 1005  
1006 1006          /*
1007 1007           * If it comes here, any symbol can be printed.
  
    | ↓ open down ↓ | 212 lines elided | ↑ open up ↑ | 
1008 1008           *      (So basically, -f is no-op.)
1009 1009           */
1010 1010          return (1);
1011 1011  }
1012 1012  
1013 1013  #ifndef XPG4
1014 1014  /*
1015 1015   * -u flag specified
1016 1016   */
1017 1017  static void
1018      -print_with_uflag(
1019      -        SYM *sym_data,
1020      -        char *filename
1021      -)
     1018 +print_with_uflag(SYM *sym_data, char *filename)
1022 1019  {
1023 1020          if ((sym_data->shndx == SHN_UNDEF) && (strlen(sym_data->name))) {
1024 1021                  if (!r_flag) {
1025 1022                          if (R_flag) {
1026 1023                                  if (archive_name != (char *)0)
1027 1024                                          (void) printf("   %s:%s:%s\n",
1028 1025                                              archive_name, filename,
1029 1026                                              sym_data->name);
1030 1027                                  else
1031 1028                                          (void) printf("    %s:%s\n",
1032 1029                                              filename, sym_data->name);
1033 1030                          }
1034 1031                          else
1035 1032                                  (void) printf("    %s\n", sym_data->name);
1036 1033                  }
1037 1034                  else
1038 1035                          (void) printf("    %s:%s\n", filename, sym_data->name);
1039 1036          }
1040 1037  }
1041 1038  #endif
1042 1039  
1043 1040  /*
1044 1041   * Print a symbol type representation suitable for the -p or -P formats.
1045 1042   */
1046 1043  static void
1047 1044  print_brief_sym_type(Elf *elf_file, unsigned int shstrndx, SYM *sym_data)
1048 1045  {
1049 1046          const char      *sym_key = NULL;
1050 1047  
1051 1048          if ((sym_data->shndx == SHN_UNDEF) && (strlen(sym_data->name)))
1052 1049                  sym_key = UNDEFINED;
1053 1050          else if (sym_data->type == STT_SPARC_REGISTER) {
1054 1051                  switch (sym_data->bind) {
1055 1052                          case STB_LOCAL  : sym_key = REG_LOCL;
1056 1053                                          break;
1057 1054                          case STB_GLOBAL : sym_key = REG_GLOB;
1058 1055                                          break;
1059 1056                          case STB_WEAK   : sym_key = REG_WEAK;
1060 1057                                          break;
1061 1058                          default : sym_key = REG_GLOB;
1062 1059                                          break;
1063 1060                  }
1064 1061          } else if (((sym_data->flags & FLG_SYM_SPECSEC) == 0) &&
1065 1062              is_bss_section((int)sym_data->shndx, elf_file, shstrndx)) {
1066 1063                  switch (sym_data->bind) {
1067 1064                          case STB_LOCAL  : sym_key = BSS_LOCL;
1068 1065                                          break;
1069 1066                          case STB_GLOBAL : sym_key = BSS_GLOB;
1070 1067                                          break;
1071 1068                          case STB_WEAK   : sym_key = BSS_WEAK;
1072 1069                                          break;
1073 1070                          default : sym_key = BSS_GLOB;
1074 1071                                          break;
1075 1072                  }
1076 1073  
1077 1074          } else {
1078 1075                  sym_key = lookup(sym_data->type, sym_data->bind);
1079 1076          }
1080 1077  
1081 1078          if (sym_key != NULL) {
1082 1079                  if (!l_flag)
1083 1080                          (void) printf("%c ", sym_key[0]);
1084 1081                  else
1085 1082                          (void) printf("%-3s", sym_key);
1086 1083          } else {
1087 1084                  if (!l_flag)
  
    | ↓ open down ↓ | 56 lines elided | ↑ open up ↑ | 
1088 1085                          (void) printf("%-2d", sym_data->type);
1089 1086                  else
1090 1087                          (void) printf("%-3d", sym_data->type);
1091 1088          }
1092 1089  }
1093 1090  
1094 1091  /*
1095 1092   * -p flag specified
1096 1093   */
1097 1094  static void
1098      -print_with_pflag(
1099      -        int ndigits,
1100      -        Elf *elf_file,
1101      -        unsigned int shstrndx,
1102      -        SYM *sym_data,
1103      -        char *filename
1104      -)
     1095 +print_with_pflag(int ndigits, Elf *elf_file, unsigned int shstrndx,
     1096 +    SYM *sym_data, char *filename)
1105 1097  {
1106 1098          const char * const fmt[] = {
1107      -                "%.*llu ",      /* FMT_T_DEC */
1108      -                "0x%.*llx ",    /* FMT_T_HEX */
1109      -                "0%.*llo "      /* FMT_T_OCT */
     1099 +            "%.*llu ",  /* FMT_T_DEC */
     1100 +            "0x%.*llx ",        /* FMT_T_HEX */
     1101 +            "0%.*llo "  /* FMT_T_OCT */
1110 1102          };
1111 1103  
1112 1104          if (is_sym_print(sym_data) != 1)
1113 1105                  return;
1114 1106          /*
1115 1107           * -A header
1116 1108           */
1117 1109          if (A_flag != 0)
1118 1110                  (void) printf("%s", A_header);
1119 1111  
1120 1112          /*
1121 1113           * Symbol Value.
1122 1114           *      (hex/octal/decimal)
1123 1115           */
1124 1116          (void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value));
1125 1117  
1126 1118  
1127 1119          /*
1128 1120           * Symbol Type.
1129 1121           */
1130 1122          print_brief_sym_type(elf_file, shstrndx, sym_data);
1131 1123  
1132 1124          if (!r_flag) {
1133 1125                  if (R_flag) {
1134 1126                          if (archive_name != (char *)0)
1135 1127                                  (void) printf("%s:%s:%s\n", archive_name,
1136 1128                                      filename, sym_data->name);
1137 1129                          else
1138 1130                                  (void) printf("%s:%s\n", filename,
1139 1131                                      sym_data->name);
1140 1132                  }
1141 1133                  else
  
    | ↓ open down ↓ | 22 lines elided | ↑ open up ↑ | 
1142 1134                          (void) printf("%s\n", sym_data->name);
1143 1135          }
1144 1136          else
1145 1137                  (void) printf("%s:%s\n", filename, sym_data->name);
1146 1138  }
1147 1139  
1148 1140  /*
1149 1141   * -P flag specified
1150 1142   */
1151 1143  static void
1152      -print_with_Pflag(
1153      -        int ndigits,
1154      -        Elf *elf_file,
1155      -        unsigned int shstrndx,
1156      -        SYM *sym_data
1157      -)
     1144 +print_with_Pflag(int ndigits, Elf *elf_file, unsigned int shstrndx,
     1145 +    SYM *sym_data)
1158 1146  {
1159 1147  #define SYM_LEN 10
1160 1148          char sym_name[SYM_LEN+1];
1161 1149          size_t len;
1162 1150          const char * const fmt[] = {
1163 1151                  "%*llu %*llu \n",       /* FMT_T_DEC */
1164 1152                  "%*llx %*llx \n",       /* FMT_T_HEX */
1165 1153                  "%*llo %*llo \n"        /* FMT_T_OCT */
1166 1154          };
1167 1155  
1168 1156          if (is_sym_print(sym_data) != 1)
1169 1157                  return;
1170 1158          /*
1171 1159           * -A header
1172 1160           */
1173 1161          if (A_flag != 0)
1174 1162                  (void) printf("%s", A_header);
1175 1163  
1176 1164          /*
1177 1165           * Symbol name
1178 1166           */
1179 1167          len = strlen(sym_data->name);
1180 1168          if (len >= SYM_LEN)
1181 1169                  (void) printf("%s ", sym_data->name);
1182 1170          else {
1183 1171                  (void) sprintf(sym_name, "%-10s", sym_data->name);
1184 1172                  (void) printf("%s ", sym_name);
1185 1173          }
1186 1174  
1187 1175          /*
1188 1176           * Symbol Type.
1189 1177           */
1190 1178          print_brief_sym_type(elf_file, shstrndx, sym_data);
1191 1179  
1192 1180          /*
1193 1181           * Symbol Value & size
  
    | ↓ open down ↓ | 26 lines elided | ↑ open up ↑ | 
1194 1182           *      (hex/octal/decimal)
1195 1183           */
1196 1184          (void) printf(fmt[fmt_flag], ndigits, EC_ADDR(sym_data->value),
1197 1185              ndigits, EC_XWORD(sym_data->size));
1198 1186  }
1199 1187  
1200 1188  /*
1201 1189   * other flags specified
1202 1190   */
1203 1191  static void
1204      -print_with_otherflags(
1205      -        int ndigits,
1206      -        Elf *elf_file,
1207      -        unsigned int shstrndx,
1208      -        SYM *sym_data,
1209      -        char *filename
1210      -)
     1192 +print_with_otherflags(int ndigits, Elf *elf_file, unsigned int shstrndx,
     1193 +    SYM *sym_data, char *filename)
1211 1194  {
1212 1195          const char * const fmt_value_size[] = {
1213 1196                  "%*llu|%*lld|",         /* FMT_T_DEC */
1214 1197                  "0x%.*llx|0x%.*llx|",   /* FMT_T_HEX */
1215 1198                  "0%.*llo|0%.*llo|"      /* FMT_T_OCT */
1216 1199          };
1217 1200          const char * const fmt_int[] = {
1218 1201                  "%-5d",                 /* FMT_T_DEC */
1219 1202                  "%#-5x",                /* FMT_T_HEX */
1220 1203                  "%#-5o"                 /* FMT_T_OCT */
1221 1204          };
1222 1205  
1223 1206          if (is_sym_print(sym_data) != 1)
1224 1207                  return;
1225 1208          (void) printf("%s", A_header);
1226 1209          (void) printf("[%d]\t|", sym_data->indx);
1227 1210          (void) printf(fmt_value_size[fmt_flag], ndigits,
1228 1211              EC_ADDR(sym_data->value), ndigits, EC_XWORD(sym_data->size));
1229 1212  
1230 1213          switch (sym_data->type) {
1231 1214          case STT_NOTYPE:(void) printf("%-5s", "NOTY"); break;
1232 1215          case STT_OBJECT:(void) printf("%-5s", "OBJT"); break;
1233 1216          case STT_FUNC:  (void) printf("%-5s", "FUNC"); break;
1234 1217          case STT_SECTION:(void) printf("%-5s", "SECT"); break;
1235 1218          case STT_FILE:  (void) printf("%-5s", "FILE"); break;
1236 1219          case STT_COMMON: (void) printf("%-5s", "COMM"); break;
1237 1220          case STT_TLS:   (void) printf("%-5s", "TLS "); break;
1238 1221          case STT_SPARC_REGISTER: (void) printf("%-5s", "REGI"); break;
1239 1222          default:
1240 1223                  (void) printf(fmt_int[fmt_flag], sym_data->type);
1241 1224          }
1242 1225          (void) printf("|");
1243 1226          switch (sym_data->bind) {
1244 1227          case STB_LOCAL: (void) printf("%-5s", "LOCL"); break;
1245 1228          case STB_GLOBAL:(void) printf("%-5s", "GLOB"); break;
1246 1229          case STB_WEAK:  (void) printf("%-5s", "WEAK"); break;
1247 1230          default:
1248 1231                  (void) printf("%-5d", sym_data->bind);
1249 1232                  (void) printf(fmt_int[fmt_flag], sym_data->bind);
1250 1233          }
1251 1234          (void) printf("|");
1252 1235          (void) printf(fmt_int[fmt_flag], sym_data->other);
1253 1236          (void)  printf("|");
1254 1237  
1255 1238          if (sym_data->shndx == SHN_UNDEF) {
1256 1239                  if (!s_flag)
1257 1240                          (void) printf("%-7s", "UNDEF");
1258 1241                  else
1259 1242                          (void) printf("%-14s", "UNDEF");
1260 1243          } else if (sym_data->shndx == SHN_SUNW_IGNORE) {
1261 1244                  if (!s_flag)
1262 1245                          (void) printf("%-7s", "IGNORE");
1263 1246                  else
1264 1247                          (void) printf("%-14s", "IGNORE");
1265 1248          } else if ((sym_data->flags & FLG_SYM_SPECSEC) &&
1266 1249              (sym_data->shndx == SHN_ABS)) {
1267 1250                  if (!s_flag)
1268 1251                          (void) printf("%-7s", "ABS");
1269 1252                  else
1270 1253                          (void) printf("%-14s", "ABS");
1271 1254          } else if ((sym_data->flags & FLG_SYM_SPECSEC) &&
1272 1255              (sym_data->shndx == SHN_COMMON)) {
1273 1256                  if (!s_flag)
1274 1257                          (void) printf("%-7s", "COMMON");
1275 1258                  else
1276 1259                          (void) printf("%-14s", "COMMON");
1277 1260          } else {
1278 1261                  if (s_flag) {
1279 1262                          Elf_Scn *scn = elf_getscn(elf_file, sym_data->shndx);
1280 1263                          GElf_Shdr shdr;
1281 1264  
1282 1265                          if ((gelf_getshdr(scn, &shdr) != 0) &&
1283 1266                              (shdr.sh_name != 0)) {
1284 1267                                  (void) printf("%-14s",
1285 1268                                      (char *)elf_strptr(elf_file,
1286 1269                                      shstrndx, shdr.sh_name));
1287 1270                          } else {
1288 1271                                  (void) printf("%-14d", sym_data->shndx);
1289 1272                          }
1290 1273                  } else {
1291 1274                          (void) printf("%-7d", sym_data->shndx);
1292 1275                  }
1293 1276          }
1294 1277          (void) printf("|");
1295 1278          if (!r_flag) {
1296 1279                  if (R_flag) {
1297 1280                          if (archive_name != (char *)0)
1298 1281                                  (void) printf("%s:%s:%s\n", archive_name,
1299 1282                                      filename, sym_data->name);
1300 1283                          else
1301 1284                                  (void) printf("%s:%s\n", filename,
1302 1285                                      sym_data->name);
1303 1286                  }
1304 1287                  else
1305 1288                          (void) printf("%s\n", sym_data->name);
1306 1289          }
1307 1290          else
1308 1291                  (void) printf("%s:%s\n", filename, sym_data->name);
1309 1292  }
1310 1293  
1311 1294  /*
1312 1295   * C++ name demangling supporting routines
1313 1296   */
1314 1297  static const char *ctor_str = "static constructor function for %s";
1315 1298  static const char *dtor_str = "static destructor function for %s";
1316 1299  static const char *ptbl_str = "pointer to the virtual table vector for %s";
1317 1300  static const char *vtbl_str = "virtual table for %s";
1318 1301  
1319 1302  /*
1320 1303   * alloc memory and create name in necessary format.
1321 1304   * Return name string
1322 1305   */
1323 1306  static char *
1324 1307  FormatName(char *OldName, const char *NewName)
1325 1308  {
1326 1309          char *s = p_flag ?
1327 1310              "%s\n             [%s]" :
1328 1311              "%s\n\t\t\t\t\t\t       [%s]";
1329 1312          size_t length = strlen(s)+strlen(NewName)+strlen(OldName)-3;
1330 1313          char *hold = OldName;
1331 1314          OldName = malloc(length);
1332 1315          /*LINTED*/
1333 1316          (void) snprintf(OldName, length, s, NewName, hold);
1334 1317          return (OldName);
1335 1318  }
1336 1319  
1337 1320  
1338 1321  /*
1339 1322   * Return 1 when s is an exotic name, 0 otherwise.  s remains unchanged,
1340 1323   * the exotic name, if exists, is saved in d_buf.
1341 1324   */
1342 1325  static int
1343 1326  exotic(const char *in_str)
1344 1327  {
1345 1328          static char     *buff = 0;
1346 1329          static size_t   buf_size;
1347 1330  
1348 1331          size_t          sym_len = strlen(in_str) + 1;
1349 1332          int             tag = 0;
1350 1333          char            *s;
1351 1334  
1352 1335          /*
1353 1336           * We will need to modify the symbol (in_str) as we are analyzing it,
1354 1337           * so copy it into a buffer so that we can play around with it.
1355 1338           */
1356 1339          if (buff == NULL) {
1357 1340                  buff = malloc(DEF_MAX_SYM_SIZE);
1358 1341                  buf_size = DEF_MAX_SYM_SIZE;
1359 1342          }
1360 1343  
1361 1344          if (sym_len > buf_size) {
1362 1345                  if (buff)
1363 1346                          free(buff);
1364 1347                  buff = malloc(sym_len);
1365 1348                  buf_size = sym_len;
1366 1349          }
1367 1350  
1368 1351          if (buff == NULL) {
1369 1352                  (void) fprintf(stderr, gettext(
1370 1353                      "%s: cannot allocate memory\n"), prog_name);
1371 1354                  exit(NOALLOC);
1372 1355          }
1373 1356          s = strcpy(buff, in_str);
1374 1357  
1375 1358  
1376 1359          if (strncmp(s, "__sti__", 7) == 0) {
1377 1360                  s += 7; tag = 1;
1378 1361                  parse_fn_and_print(ctor_str, s);
1379 1362          } else if (strncmp(s, "__std__", 7) == 0) {
1380 1363                  s += 7; tag = 1;
1381 1364                  parse_fn_and_print(dtor_str, s);
1382 1365          } else if (strncmp(s, "__vtbl__", 8) == 0) {
1383 1366                  s += 8; tag = 1;
1384 1367                  parsename(s);
1385 1368                  (void) sprintf(d_buf, vtbl_str, p_buf);
1386 1369          } else if (strncmp(s, "__ptbl_vec__", 12) == 0) {
1387 1370                  s += 12; tag = 1;
1388 1371                  parse_fn_and_print(ptbl_str, s);
1389 1372          }
1390 1373          return (tag);
1391 1374  }
1392 1375  
1393 1376  void
1394 1377  parsename(char *s)
1395 1378  {
1396 1379          register int len;
1397 1380          char c, *orig = s;
1398 1381          *p_buf = '\0';
1399 1382          (void) strcat(p_buf, "class ");
1400 1383          while (isdigit(*s)) s++;
1401 1384          c = *s;
1402 1385          *s = '\0';
1403 1386          len = atoi(orig);
1404 1387          *s = c;
1405 1388          if (*(s+len) == '\0') { /* only one class name */
1406 1389                  (void) strcat(p_buf, s);
1407 1390                  return;
1408 1391          } else
1409 1392          { /* two classname  %drootname__%dchildname */
1410 1393                  char *root, *child, *child_len_p;
1411 1394                  int child_len;
1412 1395                  root = s;
1413 1396                  child = s + len + 2;
1414 1397                  child_len_p = child;
1415 1398                  if (!isdigit(*child)) {
1416 1399                          /* ptbl file name */
1417 1400                          /*  %drootname__%filename */
1418 1401                          /* kludge for getting rid of '_' in file name */
1419 1402                          char *p;
1420 1403                          c = *(root + len);
1421 1404                          *(root + len) = '\0';
1422 1405                          (void) strcat(p_buf, root);
1423 1406                          *(root + len) = c;
1424 1407                          (void) strcat(p_buf, " in ");
1425 1408                          for (p = child; *p != '_'; ++p)
1426 1409                                  ;
1427 1410                          c = *p;
1428 1411                          *p = '.';
1429 1412                          (void) strcat(p_buf, child);
1430 1413                          *p = c;
1431 1414                          return;
1432 1415                  }
1433 1416  
1434 1417                  while (isdigit(*child))
1435 1418                          child++;
1436 1419                  c = *child;
1437 1420                  *child = '\0';
1438 1421                  child_len = atoi(child_len_p);
1439 1422                  *child = c;
1440 1423                  if (*(child + child_len) == '\0') {
1441 1424                          (void) strcat(p_buf, child);
1442 1425                          (void) strcat(p_buf, " derived from ");
1443 1426                          c = *(root + len);
1444 1427                          *(root + len) = '\0';
1445 1428                          (void) strcat(p_buf, root);
1446 1429                          *(root + len) = c;
1447 1430                          return;
1448 1431                  } else {
1449 1432                          /* %drootname__%dchildname__filename */
1450 1433                          /* kludge for getting rid of '_' in file name */
1451 1434                          char *p;
1452 1435                          c = *(child + child_len);
1453 1436                          *(child + child_len) = '\0';
1454 1437                          (void) strcat(p_buf, child);
1455 1438                          *(child+child_len) = c;
1456 1439                          (void) strcat(p_buf, " derived from ");
1457 1440                          c = *(root + len);
1458 1441                          *(root + len) = '\0';
1459 1442                          (void) strcat(p_buf, root);
1460 1443                          *(root + len) = c;
1461 1444                          (void) strcat(p_buf, " in ");
1462 1445                          for (p = child + child_len + 2; *p != '_'; ++p)
1463 1446                                  ;
1464 1447                          c = *p;
1465 1448                          *p = '.';
1466 1449                          (void) strcat(p_buf, child + child_len + 2);
1467 1450                          *p = c;
1468 1451                          return;
1469 1452                  }
1470 1453          }
1471 1454  }
1472 1455  
1473 1456  void
1474 1457  parse_fn_and_print(const char *str, char *s)
1475 1458  {
1476 1459          char            c, *p1, *p2;
1477 1460          int             yes = 1;
1478 1461  
1479 1462          if ((p1 = p2 =  strstr(s, "_c_")) == NULL)
1480 1463                  if ((p1 = p2 =  strstr(s, "_C_")) == NULL)
1481 1464                          if ((p1 = p2 =  strstr(s, "_cc_")) == NULL)
1482 1465                                  if ((p1 = p2 =  strstr(s, "_cxx_")) == NULL)
1483 1466                                          if ((p1 = p2 = strstr(s, "_h_")) ==
1484 1467                                              NULL)
1485 1468                          yes = 0;
1486 1469                          else
1487 1470                                                  p2 += 2;
1488 1471                                  else
1489 1472                                          p2 += 4;
1490 1473                          else
1491 1474                                  p2 += 3;
1492 1475                  else
1493 1476                          p2 += 2;
1494 1477          else
1495 1478                  p2 += 2;
1496 1479  
1497 1480          if (yes) {
1498 1481          *p1 = '.';
1499 1482                  c = *p2;
1500 1483                  *p2 = '\0';
1501 1484          }
1502 1485  
1503 1486          for (s = p1;  *s != '_';  --s)
1504 1487                  ;
1505 1488          ++s;
1506 1489  
1507 1490          (void) sprintf(d_buf, str, s);
1508 1491  
1509 1492          if (yes) {
1510 1493                  *p1 = '_';
1511 1494                  *p2 = c;
1512 1495          }
1513 1496  }
  
    | ↓ open down ↓ | 293 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX