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

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libdisasm/sparc/dis_sparc.c
          +++ new/usr/src/lib/libdisasm/common/dis_sparc.c
↓ open down ↓ 19 lines elided ↑ open up ↑
  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  
  27   27  /*
  28   28   * Copyright 2007 Jason King.  All rights reserved.
  29   29   * Use is subject to license terms.
       30 + * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
  30   31   */
  31   32  
  32   33  /*
  33   34   * The sparc disassembler is mostly straightforward, each instruction is
  34   35   * represented by an inst_t structure.  The inst_t definitions are organized
  35   36   * into tables.  The tables are correspond to the opcode maps documented in the
  36   37   * various sparc architecture manuals.  Each table defines the bit range of the
  37   38   * instruction whose value act as an index into the array of instructions.  A
  38   39   * table can also refer to another table if needed.  Each table also contains
  39   40   * a function pointer of type format_fcn that knows how to output the
↓ open down ↓ 55 lines elided ↑ open up ↑
  95   96  #include "dis_sparc.h"
  96   97  
  97   98  static const inst_t *dis_get_overlay(dis_handle_t *, const table_t *,
  98   99      uint32_t);
  99  100  static uint32_t dis_get_bits(uint32_t, int, int);
 100  101  
 101  102  #if !defined(DIS_STANDALONE)
 102  103  static void do_binary(uint32_t);
 103  104  #endif /* DIS_STANDALONE */
 104  105  
 105      -dis_handle_t *
 106      -dis_handle_create(int flags, void *data, dis_lookup_f lookup_func,
 107      -    dis_read_f read_func)
      106 +static void
      107 +dis_sparc_handle_detach(dis_handle_t *dhp)
      108 +{
      109 +        dis_free(dhp->dh_arch_private, sizeof (dis_handle_sparc_t));
      110 +        dhp->dh_arch_private = NULL;
      111 +}
      112 +
      113 +static int
      114 +dis_sparc_handle_attach(dis_handle_t *dhp)
 108  115  {
      116 +        dis_handle_sparc_t *dhx;
 109  117  
 110  118  #if !defined(DIS_STANDALONE)
 111  119          char *opt = NULL;
 112  120          char *opt2, *save, *end;
 113  121  #endif
 114      -        dis_handle_t *dhp;
 115  122  
 116      -        if ((flags & (DIS_SPARC_V8|DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0) {
      123 +        /* Validate architecture flags */
      124 +        if ((dhp->dh_flags & (DIS_SPARC_V8|DIS_SPARC_V9|DIS_SPARC_V9_SGI))
      125 +            == 0) {
 117  126                  (void) dis_seterrno(E_DIS_INVALFLAG);
 118      -                return (NULL);
      127 +                return (-1);
 119  128          }
 120  129  
 121      -        if ((dhp = dis_zalloc(sizeof (struct dis_handle))) == NULL) {
      130 +        if ((dhx = dis_zalloc(sizeof (dis_handle_sparc_t))) == NULL) {
 122  131                  (void) dis_seterrno(E_DIS_NOMEM);
 123  132                  return (NULL);
 124  133          }
 125      -
 126      -        dhp->dh_lookup = lookup_func;
 127      -        dhp->dh_read = read_func;
 128      -        dhp->dh_flags = flags;
 129      -        dhp->dh_data = data;
 130      -        dhp->dh_debug = DIS_DEBUG_COMPAT;
      134 +        dhx->dhx_debug = DIS_DEBUG_COMPAT;
      135 +        dhp->dh_arch_private = dhx;
 131  136  
 132  137  #if !defined(DIS_STANDALONE)
 133  138  
 134  139          opt = getenv("_LIBDISASM_DEBUG");
 135  140          if (opt == NULL)
 136      -                return (dhp);
      141 +                return (0);
 137  142  
 138  143          opt2 = strdup(opt);
 139  144          if (opt2 == NULL) {
 140  145                  dis_handle_destroy(dhp);
      146 +                dis_free(dhx, sizeof (dis_handle_sparc_t));
 141  147                  (void) dis_seterrno(E_DIS_NOMEM);
 142      -                return (NULL);
      148 +                return (-1);
 143  149          }
 144  150          save = opt2;
 145  151  
 146  152          while (opt2 != NULL) {
 147  153                  end = strchr(opt2, ',');
 148  154  
 149  155                  if (end != 0)
 150  156                          *end++ = '\0';
 151  157  
 152  158                  if (strcasecmp("synth-all", opt2) == 0)
 153      -                        dhp->dh_debug |= DIS_DEBUG_SYN_ALL;
      159 +                        dhx->dhx_debug |= DIS_DEBUG_SYN_ALL;
 154  160  
 155  161                  if (strcasecmp("compat", opt2) == 0)
 156      -                        dhp->dh_debug |= DIS_DEBUG_COMPAT;
      162 +                        dhx->dhx_debug |= DIS_DEBUG_COMPAT;
 157  163  
 158  164                  if (strcasecmp("synth-none", opt2) == 0)
 159      -                        dhp->dh_debug &= ~(DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT);
      165 +                        dhx->dhx_debug &= ~(DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT);
 160  166  
 161  167                  if (strcasecmp("binary", opt2) == 0)
 162      -                        dhp->dh_debug |= DIS_DEBUG_PRTBIN;
      168 +                        dhx->dhx_debug |= DIS_DEBUG_PRTBIN;
 163  169  
 164  170                  if (strcasecmp("format", opt2) == 0)
 165      -                        dhp->dh_debug |= DIS_DEBUG_PRTFMT;
      171 +                        dhx->dhx_debug |= DIS_DEBUG_PRTFMT;
 166  172  
 167  173                  if (strcasecmp("all", opt2) == 0)
 168      -                        dhp->dh_debug = DIS_DEBUG_ALL;
      174 +                        dhx->dhx_debug = DIS_DEBUG_ALL;
 169  175  
 170  176                  if (strcasecmp("none", opt2) == 0)
 171      -                        dhp->dh_debug = DIS_DEBUG_NONE;
      177 +                        dhx->dhx_debug = DIS_DEBUG_NONE;
 172  178  
 173  179                  opt2 = end;
 174  180          }
 175  181          free(save);
 176  182  #endif /* DIS_STANDALONE */
 177      -        return (dhp);
 178      -}
 179      -
 180      -void
 181      -dis_handle_destroy(dis_handle_t *dhp)
 182      -{
 183      -        dis_free(dhp, sizeof (dis_handle_t));
 184      -}
 185      -
 186      -void
 187      -dis_set_data(dis_handle_t *dhp, void *data)
 188      -{
 189      -        dhp->dh_data = data;
 190      -}
 191      -
 192      -void
 193      -dis_flags_set(dis_handle_t *dhp, int f)
 194      -{
 195      -        dhp->dh_flags |= f;
      183 +        return (0);
 196  184  }
 197  185  
 198      -void
 199      -dis_flags_clear(dis_handle_t *dhp, int f)
      186 +/* ARGSUSED */
      187 +static int
      188 +dis_sparc_max_instrlen(dis_handle_t *dhp)
 200  189  {
 201      -        dhp->dh_flags &= ~f;
      190 +        return (4);
 202  191  }
 203  192  
 204  193  /* ARGSUSED */
 205      -int
 206      -dis_max_instrlen(dis_handle_t *dhp)
      194 +static int
      195 +dis_sparc_min_instrlen(dis_handle_t *dhp)
 207  196  {
 208  197          return (4);
 209  198  }
 210  199  
 211  200  /*
 212  201   * The dis_i386.c comment for this says it returns the previous instruction,
 213  202   * however, I'm fairly sure it's actually returning the _address_ of the
 214  203   * nth previous instruction.
 215  204   */
 216  205  /* ARGSUSED */
 217      -uint64_t
 218      -dis_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
      206 +static uint64_t
      207 +dis_sparc_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
 219  208  {
 220  209          if (n <= 0)
 221  210                  return (pc);
 222  211  
 223  212          if (pc < n)
 224  213                  return (pc);
 225  214  
 226  215          return (pc - n*4);
 227  216  }
 228  217  
 229  218  /* ARGSUSED */
 230      -int
 231      -dis_instrlen(dis_handle_t *dhp, uint64_t pc)
      219 +static int
      220 +dis_sparc_instrlen(dis_handle_t *dhp, uint64_t pc)
 232  221  {
 233  222          return (4);
 234  223  }
 235  224  
 236      -int
 237      -dis_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen)
      225 +static int
      226 +dis_sparc_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf,
      227 +    size_t buflen)
 238  228  {
      229 +        dis_handle_sparc_t *dhx = dhp->dh_arch_private;
 239  230          const table_t *tp = &initial_table;
 240  231          const inst_t *inp = NULL;
 241  232  
 242  233          uint32_t instr;
 243  234          uint32_t idx = 0;
 244  235  
 245  236          if (dhp->dh_read(dhp->dh_data, addr, &instr, sizeof (instr)) !=
 246  237              sizeof (instr))
 247  238                  return (-1);
 248  239  
 249      -        dhp->dh_buf    = buf;
 250      -        dhp->dh_buflen = buflen;
 251      -        dhp->dh_addr   = addr;
      240 +        dhx->dhx_buf    = buf;
      241 +        dhx->dhx_buflen = buflen;
      242 +        dhp->dh_addr    = addr;
 252  243  
 253  244          buf[0] = '\0';
 254  245  
 255  246          /* this allows sparc code to be tested on x86 */
      247 +#if !defined(DIS_STANDALONE)
 256  248          instr = BE_32(instr);
      249 +#endif /* DIS_STANDALONE */
 257  250  
 258  251  #if !defined(DIS_STANDALONE)
 259      -        if ((dhp->dh_debug & DIS_DEBUG_PRTBIN) != 0)
      252 +        if ((dhx->dhx_debug & DIS_DEBUG_PRTBIN) != 0)
 260  253                  do_binary(instr);
 261  254  #endif /* DIS_STANDALONE */
 262  255  
 263  256          /* CONSTCOND */
 264  257          while (1) {
 265  258                  idx = dis_get_bits(instr, tp->tbl_field, tp->tbl_len);
 266  259                  inp = &tp->tbl_inp[idx];
 267  260  
 268  261                  inp = dis_get_overlay(dhp, tp, idx);
 269  262  
↓ open down ↓ 64 lines elided ↑ open up ↑
 334  327  
 335  328  #if !defined(DIS_STANDALONE)
 336  329  static void
 337  330  do_binary(uint32_t instr)
 338  331  {
 339  332          (void) fprintf(stderr, "DISASM: ");
 340  333          prt_binary(instr, 32);
 341  334          (void) fprintf(stderr, "\n");
 342  335  }
 343  336  #endif /* DIS_STANDALONE */
      337 +
      338 +static int
      339 +dis_sparc_supports_flags(int flags)
      340 +{
      341 +        int archflags = flags & DIS_ARCH_MASK;
      342 +
      343 +        if (archflags == DIS_SPARC_V8 ||
      344 +            (archflags & (DIS_SPARC_V9 | DIS_SPARC_V8)) == DIS_SPARC_V9)
      345 +                return (1);
      346 +
      347 +        return (0);
      348 +}
      349 +
      350 +const dis_arch_t dis_arch_sparc = {
      351 +        dis_sparc_supports_flags,
      352 +        dis_sparc_handle_attach,
      353 +        dis_sparc_handle_detach,
      354 +        dis_sparc_disassemble,
      355 +        dis_sparc_previnstr,
      356 +        dis_sparc_min_instrlen,
      357 +        dis_sparc_max_instrlen,
      358 +        dis_sparc_instrlen
      359 +};
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX