Print this page
3317 dis(1) should support cross-target disassembly

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/dis/dis_main.c
          +++ new/usr/src/cmd/dis/dis_main.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  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 2007 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   *
  26   26   * Copyright 2011 Jason King.  All rights reserved.
       27 + * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
  27   28   */
  28   29  
  29   30  #include <ctype.h>
  30   31  #include <getopt.h>
  31   32  #include <stdio.h>
  32   33  #include <stdlib.h>
  33   34  #include <string.h>
  34   35  #include <sys/sysmacros.h>
  35   36  #include <sys/elf_SPARC.h>
  36   37  
↓ open down ↓ 53 lines elided ↑ open up ↑
  90   91                  if (offset == 0)
  91   92                          (void) snprintf(buf, buflen, "%s", symbol);
  92   93                  else if (g_flags & DIS_OCTAL)
  93   94                          (void) snprintf(buf, buflen, "%s+0%o", symbol, offset);
  94   95                  else
  95   96                          (void) snprintf(buf, buflen, "%s+0x%x", symbol, offset);
  96   97          }
  97   98  }
  98   99  
  99  100  /*
      101 + * Determine if we are on an architecture with fixed-size instructions,
      102 + * and if so, what size they are.
      103 + */
      104 +static int
      105 +insn_size(dis_handle_t *dhp)
      106 +{
      107 +        int min = dis_min_instrlen(dhp);
      108 +        int max = dis_max_instrlen(dhp);
      109 +
      110 +        if (min == max)
      111 +                return (min);
      112 +
      113 +        return (0);
      114 +}
      115 +
      116 +/*
 100  117   * The main disassembly routine.  Given a fixed-sized buffer and starting
 101  118   * address, disassemble the data using the supplied target and libdisasm handle.
 102  119   */
 103  120  void
 104  121  dis_data(dis_tgt_t *tgt, dis_handle_t *dhp, uint64_t addr, void *data,
 105  122      size_t datalen)
 106  123  {
 107  124          dis_buffer_t db = { 0 };
 108  125          char buf[BUFSIZE];
 109  126          char symbuf[BUFSIZE];
 110  127          const char *symbol;
 111  128          const char *last_symbol;
 112  129          off_t symoffset;
 113  130          int i;
 114  131          int bytesperline;
 115  132          size_t symsize;
 116  133          int isfunc;
 117  134          size_t symwidth = 0;
      135 +        int ret;
      136 +        int insz = insn_size(dhp);
 118  137  
 119  138          db.db_tgt = tgt;
 120  139          db.db_data = data;
 121  140          db.db_addr = addr;
 122  141          db.db_size = datalen;
 123  142  
 124  143          dis_set_data(dhp, &db);
 125  144  
 126  145          if ((bytesperline = dis_max_instrlen(dhp)) > 6)
 127  146                  bytesperline = 6;
 128  147  
 129  148          symbol = NULL;
 130  149  
 131  150          while (addr < db.db_addr + db.db_size) {
 132  151  
 133      -                if (dis_disassemble(dhp, addr, buf, BUFSIZE) != 0) {
 134      -#if defined(__sparc)
      152 +                ret = dis_disassemble(dhp, addr, buf, BUFSIZE);
      153 +                if (ret != 0 && insz > 0) {
 135  154                          /*
 136      -                         * Since sparc instructions are fixed size, we
      155 +                         * Since we know instructions are fixed size, we
 137  156                           * always know the address of the next instruction
 138  157                           */
 139  158                          (void) snprintf(buf, sizeof (buf),
 140  159                              "*** invalid opcode ***");
 141      -                        db.db_nextaddr = addr + 4;
      160 +                        db.db_nextaddr = addr + insz;
 142  161  
 143      -#else
      162 +                } else if (ret != 0) {
 144  163                          off_t next;
 145  164  
 146  165                          (void) snprintf(buf, sizeof (buf),
 147  166                              "*** invalid opcode ***");
 148  167  
 149  168                          /*
 150  169                           * On architectures with variable sized instructions
 151  170                           * we have no way to figure out where the next
 152  171                           * instruction starts if we encounter an invalid
 153  172                           * instruction.  Instead we print the rest of the
↓ open down ↓ 2 lines elided ↑ open up ↑
 156  175                           */
 157  176                          if ((next = dis_tgt_next_symbol(tgt, addr)) == 0) {
 158  177                                  db.db_nextaddr = db.db_addr + db.db_size;
 159  178                          } else {
 160  179                                  if (next > db.db_size)
 161  180                                          db.db_nextaddr = db.db_addr +
 162  181                                              db.db_size;
 163  182                                  else
 164  183                                          db.db_nextaddr = addr + next;
 165  184                          }
 166      -#endif
 167  185                  }
 168  186  
 169  187                  /*
 170  188                   * Print out the line as:
 171  189                   *
 172  190                   *      address:        bytes   text
 173  191                   *
 174  192                   * If there are more than 6 bytes in any given instruction,
 175  193                   * spread the bytes across two lines.  We try to get symbolic
 176  194                   * information for the address, but if that fails we print out
↓ open down ↓ 298 lines elided ↑ open up ↑
 475  493          for (current = tgt; current != NULL; current = dis_tgt_next(current)) {
 476  494                  dis_tgt_ehdr(current, &ehdr);
 477  495  
 478  496                  /*
 479  497                   * Eventually, this should probably live within libdisasm, and
 480  498                   * we should be able to disassemble targets from different
 481  499                   * architectures.  For now, we only support objects as the
 482  500                   * native machine type.
 483  501                   */
 484  502                  switch (ehdr.e_machine) {
 485      -#ifdef __sparc
 486  503                  case EM_SPARC:
 487  504                          if (ehdr.e_ident[EI_CLASS] != ELFCLASS32 ||
 488  505                              ehdr.e_ident[EI_DATA] != ELFDATA2MSB) {
 489  506                                  warn("invalid E_IDENT field for SPARC object");
 490  507                                  return;
 491  508                          }
 492  509                          g_flags |= DIS_SPARC_V8;
 493  510                          break;
 494  511  
 495  512                  case EM_SPARC32PLUS:
↓ open down ↓ 17 lines elided ↑ open up ↑
 513  530  
 514  531                  case EM_SPARCV9:
 515  532                          if (ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
 516  533                              ehdr.e_ident[EI_DATA] != ELFDATA2MSB) {
 517  534                                  warn("invalid E_IDENT field for SPARC object");
 518  535                                  return;
 519  536                          }
 520  537  
 521  538                          g_flags |= DIS_SPARC_V9 | DIS_SPARC_V9_SGI;
 522  539                          break;
 523      -#endif /* __sparc */
 524  540  
 525      -#if defined(__i386) || defined(__amd64)
 526  541                  case EM_386:
 527  542                          g_flags |= DIS_X86_SIZE32;
 528  543                          break;
 529  544  
 530  545                  case EM_AMD64:
 531  546                          g_flags |= DIS_X86_SIZE64;
 532  547                          break;
 533      -#endif /* __i386 || __amd64 */
 534  548  
 535  549                  default:
 536  550                          die("%s: unsupported ELF machine 0x%x", filename,
 537  551                              ehdr.e_machine);
 538  552                  }
 539  553  
 540  554                  /*
 541  555                   * If ET_REL (.o), printing immediate symbols is likely to
 542  556                   * result in garbage, as symbol lookups on unrelocated
 543  557                   * immediates find false and useless matches.
↓ open down ↓ 177 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX