Home | History | Annotate | Download | only in libcpu
      1 /* Disassembler for x86.
      2    Copyright (C) 2007, 2008 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 2007.
      5 
      6    Red Hat elfutils is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by the
      8    Free Software Foundation; version 2 of the License.
      9 
     10    Red Hat elfutils is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13    General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License along
     16    with Red Hat elfutils; if not, write to the Free Software Foundation,
     17    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     18 
     19    Red Hat elfutils is an included package of the Open Invention Network.
     20    An included package of the Open Invention Network is a package for which
     21    Open Invention Network licensees cross-license their patents.  No patent
     22    license is granted, either expressly or impliedly, by designation as an
     23    included package.  Should you wish to participate in the Open Invention
     24    Network licensing program, please visit www.openinventionnetwork.com
     25    <http://www.openinventionnetwork.com>.  */
     26 
     27 #ifdef HAVE_CONFIG_H
     28 # include <config.h>
     29 #endif
     30 
     31 #include <assert.h>
     32 #include <config.h>
     33 #include <ctype.h>
     34 #include <endian.h>
     35 #include <errno.h>
     36 #include <gelf.h>
     37 #include <stddef.h>
     38 #include <stdint.h>
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <sys/param.h>
     42 
     43 #include "../libebl/libeblP.h"
     44 
     45 #define MACHINE_ENCODING __LITTLE_ENDIAN
     46 #include "memory-access.h"
     47 
     48 
     49 #ifndef MNEFILE
     50 # define MNEFILE "i386.mnemonics"
     51 #endif
     52 
     53 #define MNESTRFIELD(line) MNESTRFIELD1 (line)
     54 #define MNESTRFIELD1(line) str##line
     55 static const union mnestr_t
     56 {
     57   struct
     58   {
     59 #define MNE(name) char MNESTRFIELD (__LINE__)[sizeof (#name)];
     60 #include MNEFILE
     61 #undef MNE
     62   };
     63   char str[0];
     64 } mnestr =
     65   {
     66     {
     67 #define MNE(name) #name,
     68 #include MNEFILE
     69 #undef MNE
     70     }
     71   };
     72 
     73 /* The index can be stored in the instrtab.  */
     74 enum
     75   {
     76 #define MNE(name) MNE_##name,
     77 #include MNEFILE
     78 #undef MNE
     79     MNE_INVALID
     80   };
     81 
     82 static const unsigned short int mneidx[] =
     83   {
     84 #define MNE(name) \
     85   [MNE_##name] = offsetof (union mnestr_t, MNESTRFIELD (__LINE__)),
     86 #include MNEFILE
     87 #undef MNE
     88   };
     89 
     90 
     91 enum
     92   {
     93     idx_rex_b = 0,
     94     idx_rex_x,
     95     idx_rex_r,
     96     idx_rex_w,
     97     idx_rex,
     98     idx_cs,
     99     idx_ds,
    100     idx_es,
    101     idx_fs,
    102     idx_gs,
    103     idx_ss,
    104     idx_data16,
    105     idx_addr16,
    106     idx_rep,
    107     idx_repne,
    108     idx_lock
    109   };
    110 
    111 enum
    112   {
    113 #define prefbit(pref) has_##pref = 1 << idx_##pref
    114     prefbit (rex_b),
    115     prefbit (rex_x),
    116     prefbit (rex_r),
    117     prefbit (rex_w),
    118     prefbit (rex),
    119     prefbit (cs),
    120     prefbit (ds),
    121     prefbit (es),
    122     prefbit (fs),
    123     prefbit (gs),
    124     prefbit (ss),
    125     prefbit (data16),
    126     prefbit (addr16),
    127     prefbit (rep),
    128     prefbit (repne),
    129     prefbit (lock)
    130 #undef prefbit
    131   };
    132 #define SEGMENT_PREFIXES \
    133   (has_cs | has_ds | has_es | has_fs | has_gs | has_ss)
    134 
    135 #define prefix_cs	0x2e
    136 #define prefix_ds	0x3e
    137 #define prefix_es	0x26
    138 #define prefix_fs	0x64
    139 #define prefix_gs	0x65
    140 #define prefix_ss	0x36
    141 #define prefix_data16	0x66
    142 #define prefix_addr16	0x67
    143 #define prefix_rep	0xf3
    144 #define prefix_repne	0xf2
    145 #define prefix_lock	0xf0
    146 
    147 
    148 static const uint8_t known_prefixes[] =
    149   {
    150 #define newpref(pref) [idx_##pref] = prefix_##pref
    151     newpref (cs),
    152     newpref (ds),
    153     newpref (es),
    154     newpref (fs),
    155     newpref (gs),
    156     newpref (ss),
    157     newpref (data16),
    158     newpref (addr16),
    159     newpref (rep),
    160     newpref (repne),
    161     newpref (lock)
    162 #undef newpref
    163   };
    164 #define nknown_prefixes (sizeof (known_prefixes) / sizeof (known_prefixes[0]))
    165 
    166 
    167 #if 0
    168 static const char *prefix_str[] =
    169   {
    170 #define newpref(pref) [idx_##pref] = #pref
    171     newpref (cs),
    172     newpref (ds),
    173     newpref (es),
    174     newpref (fs),
    175     newpref (gs),
    176     newpref (ss),
    177     newpref (data16),
    178     newpref (addr16),
    179     newpref (rep),
    180     newpref (repne),
    181     newpref (lock)
    182 #undef newpref
    183   };
    184 #endif
    185 
    186 
    187 static const char amd3dnowstr[] =
    188 #define MNE_3DNOW_PAVGUSB 1
    189   "pavgusb\0"
    190 #define MNE_3DNOW_PFADD (MNE_3DNOW_PAVGUSB + 8)
    191   "pfadd\0"
    192 #define MNE_3DNOW_PFSUB (MNE_3DNOW_PFADD + 6)
    193   "pfsub\0"
    194 #define MNE_3DNOW_PFSUBR (MNE_3DNOW_PFSUB + 6)
    195   "pfsubr\0"
    196 #define MNE_3DNOW_PFACC (MNE_3DNOW_PFSUBR + 7)
    197   "pfacc\0"
    198 #define MNE_3DNOW_PFCMPGE (MNE_3DNOW_PFACC + 6)
    199   "pfcmpge\0"
    200 #define MNE_3DNOW_PFCMPGT (MNE_3DNOW_PFCMPGE + 8)
    201   "pfcmpgt\0"
    202 #define MNE_3DNOW_PFCMPEQ (MNE_3DNOW_PFCMPGT + 8)
    203   "pfcmpeq\0"
    204 #define MNE_3DNOW_PFMIN (MNE_3DNOW_PFCMPEQ + 8)
    205   "pfmin\0"
    206 #define MNE_3DNOW_PFMAX (MNE_3DNOW_PFMIN + 6)
    207   "pfmax\0"
    208 #define MNE_3DNOW_PI2FD (MNE_3DNOW_PFMAX + 6)
    209   "pi2fd\0"
    210 #define MNE_3DNOW_PF2ID (MNE_3DNOW_PI2FD + 6)
    211   "pf2id\0"
    212 #define MNE_3DNOW_PFRCP (MNE_3DNOW_PF2ID + 6)
    213   "pfrcp\0"
    214 #define MNE_3DNOW_PFRSQRT (MNE_3DNOW_PFRCP + 6)
    215   "pfrsqrt\0"
    216 #define MNE_3DNOW_PFMUL (MNE_3DNOW_PFRSQRT + 8)
    217   "pfmul\0"
    218 #define MNE_3DNOW_PFRCPIT1 (MNE_3DNOW_PFMUL + 6)
    219   "pfrcpit1\0"
    220 #define MNE_3DNOW_PFRSQIT1 (MNE_3DNOW_PFRCPIT1 + 9)
    221   "pfrsqit1\0"
    222 #define MNE_3DNOW_PFRCPIT2 (MNE_3DNOW_PFRSQIT1 + 9)
    223   "pfrcpit2\0"
    224 #define MNE_3DNOW_PMULHRW (MNE_3DNOW_PFRCPIT2 + 9)
    225   "pmulhrw";
    226 
    227 #define AMD3DNOW_LOW_IDX 0x0d
    228 #define AMD3DNOW_HIGH_IDX (sizeof (amd3dnow) + AMD3DNOW_LOW_IDX - 1)
    229 #define AMD3DNOW_IDX(val) ((val) - AMD3DNOW_LOW_IDX)
    230 static const unsigned char amd3dnow[] =
    231   {
    232     [AMD3DNOW_IDX (0xbf)] = MNE_3DNOW_PAVGUSB,
    233     [AMD3DNOW_IDX (0x9e)] = MNE_3DNOW_PFADD,
    234     [AMD3DNOW_IDX (0x9a)] = MNE_3DNOW_PFSUB,
    235     [AMD3DNOW_IDX (0xaa)] = MNE_3DNOW_PFSUBR,
    236     [AMD3DNOW_IDX (0xae)] = MNE_3DNOW_PFACC,
    237     [AMD3DNOW_IDX (0x90)] = MNE_3DNOW_PFCMPGE,
    238     [AMD3DNOW_IDX (0xa0)] = MNE_3DNOW_PFCMPGT,
    239     [AMD3DNOW_IDX (0xb0)] = MNE_3DNOW_PFCMPEQ,
    240     [AMD3DNOW_IDX (0x94)] = MNE_3DNOW_PFMIN,
    241     [AMD3DNOW_IDX (0xa4)] = MNE_3DNOW_PFMAX,
    242     [AMD3DNOW_IDX (0x0d)] = MNE_3DNOW_PI2FD,
    243     [AMD3DNOW_IDX (0x1d)] = MNE_3DNOW_PF2ID,
    244     [AMD3DNOW_IDX (0x96)] = MNE_3DNOW_PFRCP,
    245     [AMD3DNOW_IDX (0x97)] = MNE_3DNOW_PFRSQRT,
    246     [AMD3DNOW_IDX (0xb4)] = MNE_3DNOW_PFMUL,
    247     [AMD3DNOW_IDX (0xa6)] = MNE_3DNOW_PFRCPIT1,
    248     [AMD3DNOW_IDX (0xa7)] = MNE_3DNOW_PFRSQIT1,
    249     [AMD3DNOW_IDX (0xb6)] = MNE_3DNOW_PFRCPIT2,
    250     [AMD3DNOW_IDX (0xb7)] = MNE_3DNOW_PMULHRW
    251   };
    252 
    253 
    254 struct output_data
    255 {
    256   GElf_Addr addr;
    257   int *prefixes;
    258   size_t opoff1;
    259   size_t opoff2;
    260   size_t opoff3;
    261   char *bufp;
    262   size_t *bufcntp;
    263   size_t bufsize;
    264   const uint8_t *data;
    265   const uint8_t **param_start;
    266   const uint8_t *end;
    267   char *labelbuf;
    268   size_t labelbufsize;
    269   enum
    270     {
    271       addr_none = 0,
    272       addr_abs_symbolic,
    273       addr_abs_always,
    274       addr_rel_symbolic,
    275       addr_rel_always
    276     } symaddr_use;
    277   GElf_Addr symaddr;
    278 };
    279 
    280 
    281 #ifndef DISFILE
    282 # define DISFILE "i386_dis.h"
    283 #endif
    284 #include DISFILE
    285 
    286 
    287 #define ADD_CHAR(ch) \
    288   do {									      \
    289     if (unlikely (bufcnt == bufsize))					      \
    290       goto enomem;							      \
    291     buf[bufcnt++] = (ch);						      \
    292   } while (0)
    293 
    294 #define ADD_STRING(str) \
    295   do {									      \
    296     const char *_str = (str);						      \
    297     size_t _len = strlen (_str);					      \
    298     if (unlikely (bufcnt + _len > bufsize))				      \
    299       goto enomem;							      \
    300     memcpy (buf + bufcnt, str, _len);					      \
    301     bufcnt += _len;							      \
    302   } while (0)
    303 
    304 
    305 int
    306 i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
    307 	     const char *fmt, DisasmOutputCB_t outcb, DisasmGetSymCB_t symcb,
    308 	     void *outcbarg, void *symcbarg)
    309 {
    310   const char *save_fmt = fmt;
    311 
    312 #define BUFSIZE 512
    313   char initbuf[BUFSIZE];
    314   int prefixes;
    315   size_t bufcnt;
    316   size_t bufsize = BUFSIZE;
    317   char *buf = initbuf;
    318   const uint8_t *param_start;
    319 
    320   struct output_data output_data =
    321     {
    322       .prefixes = &prefixes,
    323       .bufp = buf,
    324       .bufsize = bufsize,
    325       .bufcntp = &bufcnt,
    326       .param_start = &param_start,
    327       .end = end
    328     };
    329 
    330   int retval = 0;
    331   while (1)
    332     {
    333       prefixes = 0;
    334 
    335       const uint8_t *data = *startp;
    336       const uint8_t *begin = data;
    337 
    338       /* Recognize all prefixes.  */
    339       int last_prefix_bit = 0;
    340       while (data < end)
    341 	{
    342 	  unsigned int i;
    343 	  for (i = idx_cs; i < nknown_prefixes; ++i)
    344 	    if (known_prefixes[i] == *data)
    345 	      break;
    346 	  if (i == nknown_prefixes)
    347 	    break;
    348 
    349 	  prefixes |= last_prefix_bit = 1 << i;
    350 
    351 	  ++data;
    352 	}
    353 
    354 #ifdef X86_64
    355       if (data < end && (*data & 0xf0) == 0x40)
    356 	prefixes |= ((*data++) & 0xf) | has_rex;
    357 #endif
    358 
    359       bufcnt = 0;
    360       size_t cnt = 0;
    361 
    362       const uint8_t *curr = match_data;
    363       const uint8_t *const match_end = match_data + sizeof (match_data);
    364 
    365       assert (data <= end);
    366       if (data == end)
    367 	{
    368 	  if (prefixes != 0)
    369 	    goto print_prefix;
    370 
    371 	  retval = -1;
    372 	  goto do_ret;
    373 	}
    374 
    375     next_match:
    376       while (curr < match_end)
    377 	{
    378 	  uint_fast8_t len = *curr++;
    379 	  const uint8_t *start = curr;
    380 
    381 	  assert (len > 0);
    382 	  assert (curr + 2 * len <= match_end);
    383 
    384 	  const uint8_t *codep = data;
    385 	  int correct_prefix = 0;
    386 	  int opoff = 0;
    387 
    388 	  if (data > begin && codep[-1] == curr[1] && curr[0] == 0xff)
    389 	    {
    390 	      /* We match a prefix byte.  This is exactly one byte and
    391 		 is matched exactly, without a mask.  */
    392 	      --len;
    393 	      start += 2;
    394 	      opoff = 8;
    395 
    396 	      curr += 2;
    397 
    398 	      assert (last_prefix_bit != 0);
    399 	      correct_prefix = last_prefix_bit;
    400 	    }
    401 
    402 	  size_t avail = len;
    403 	  while (avail > 0)
    404 	    {
    405 	      uint_fast8_t masked = *codep++ & *curr++;
    406 	      if (masked != *curr++)
    407 		{
    408 		not:
    409 		  curr = start + 2 * len;
    410 		  ++cnt;
    411 		  goto next_match;
    412 		}
    413 
    414 	      --avail;
    415 	      if (codep == end && avail > 0)
    416 		goto do_ret;
    417 	    }
    418 
    419 	  if (len > end - data)
    420 	    /* There is not enough data for the entire instruction.  The
    421 	       caller can figure this out by looking at the pointer into
    422 	       the input data.  */
    423 	    goto do_ret;
    424 
    425 	  assert (correct_prefix == 0
    426 		  || (prefixes & correct_prefix) != 0);
    427 	  prefixes ^= correct_prefix;
    428 
    429 	  if (0)
    430 	    {
    431 	      /* Resize the buffer.  */
    432 	      char *oldbuf;
    433 	    enomem:
    434 	      oldbuf = buf;
    435 	      if (buf == initbuf)
    436 		buf = malloc (2 * bufsize);
    437 	      else
    438 		buf = realloc (buf, 2 * bufsize);
    439 	      if (buf == NULL)
    440 		{
    441 		  buf = oldbuf;
    442 		  retval = ENOMEM;
    443 		  goto do_ret;
    444 		}
    445 	      bufsize *= 2;
    446 
    447 	      output_data.bufp = buf;
    448 	      output_data.bufsize = bufsize;
    449 	      bufcnt = 0;
    450 
    451 	      if (data == end)
    452 		{
    453 		  assert (prefixes != 0);
    454 		  goto print_prefix;
    455 		}
    456 
    457 	      /* gcc is not clever enough to see the following variables
    458 		 are not used uninitialized.  */
    459 	      asm (""
    460 		   : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep),
    461 		     "=mr" (start), "=mr" (len));
    462 	    }
    463 
    464 	  size_t prefix_size = 0;
    465 
    466 	  // XXXonly print as prefix if valid?
    467 	  if ((prefixes & has_lock) != 0)
    468 	    {
    469 	      ADD_STRING ("lock ");
    470 	      prefix_size += 5;
    471 	    }
    472 
    473 	  if (instrtab[cnt].rep)
    474 	    {
    475 	      if ((prefixes & has_rep) !=  0)
    476 		{
    477 		  ADD_STRING ("rep ");
    478 		  prefix_size += 4;
    479 		}
    480 	    }
    481 	  else if (instrtab[cnt].repe
    482 		   && (prefixes & (has_rep | has_repne)) != 0)
    483 	    {
    484 	      if ((prefixes & has_repne) != 0)
    485 		{
    486 		  ADD_STRING ("repne ");
    487 		  prefix_size += 6;
    488 		}
    489 	      else if ((prefixes & has_rep) != 0)
    490 		{
    491 		  ADD_STRING ("repe ");
    492 		  prefix_size += 5;
    493 		}
    494 	    }
    495 	  else if ((prefixes & (has_rep | has_repne)) != 0)
    496 	    {
    497 	      uint_fast8_t byte;
    498 	    print_prefix:
    499 	      bufcnt = 0;
    500 	      byte = *begin;
    501 	      /* This is a prefix byte.  Print it.  */
    502 	      switch (byte)
    503 		{
    504 		case prefix_rep:
    505 		  ADD_STRING ("rep");
    506 		  break;
    507 		case prefix_repne:
    508 		  ADD_STRING ("repne");
    509 		  break;
    510 		case prefix_cs:
    511 		  ADD_STRING ("cs");
    512 		  break;
    513 		case prefix_ds:
    514 		  ADD_STRING ("ds");
    515 		  break;
    516 		case prefix_es:
    517 		  ADD_STRING ("es");
    518 		  break;
    519 		case prefix_fs:
    520 		  ADD_STRING ("fs");
    521 		  break;
    522 		case prefix_gs:
    523 		  ADD_STRING ("gs");
    524 		  break;
    525 		case prefix_ss:
    526 		  ADD_STRING ("ss");
    527 		  break;
    528 		case prefix_data16:
    529 		  ADD_STRING ("data16");
    530 		  break;
    531 		case prefix_addr16:
    532 		  ADD_STRING ("addr16");
    533 		  break;
    534 		case prefix_lock:
    535 		  ADD_STRING ("lock");
    536 		  break;
    537 #ifdef X86_64
    538 		case 0x40 ... 0x4f:
    539 		  ADD_STRING ("rex");
    540 		  if (byte != 0x40)
    541 		    {
    542 		      ADD_CHAR ('.');
    543 		      if (byte & 0x8)
    544 			ADD_CHAR ('w');
    545 		      if (byte & 0x4)
    546 			ADD_CHAR ('r');
    547 		      if (byte & 0x3)
    548 			ADD_CHAR ('x');
    549 		      if (byte & 0x1)
    550 			ADD_CHAR ('b');
    551 		    }
    552 		  break;
    553 #endif
    554 		default:
    555 		  /* Cannot happen.  */
    556 		  puts ("unknown prefix");
    557 		  abort ();
    558 		}
    559 	      data = begin + 1;
    560 	      ++addr;
    561 
    562 	      goto out;
    563 	    }
    564 
    565 	  /* We have a match.  First determine how many bytes are
    566 	     needed for the adressing mode.  */
    567 	  param_start = codep;
    568 	  if (instrtab[cnt].modrm)
    569 	    {
    570 	      uint_fast8_t modrm = codep[-1];
    571 
    572 #ifndef X86_64
    573 	      if (likely ((prefixes & has_addr16) != 0))
    574 		{
    575 		  /* Account for displacement.  */
    576 		  if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
    577 		    param_start += 2;
    578 		  else if ((modrm & 0xc0) == 0x40)
    579 		    param_start += 1;
    580 		}
    581 	      else
    582 #endif
    583 		{
    584 		  /* Account for SIB.  */
    585 		  if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4)
    586 		    param_start += 1;
    587 
    588 		  /* Account for displacement.  */
    589 		  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
    590 		      || ((modrm & 0xc7) == 0x4 && (codep[0] & 0x7) == 0x5))
    591 		    param_start += 4;
    592 		  else if ((modrm & 0xc0) == 0x40)
    593 		    param_start += 1;
    594 		}
    595 
    596 	      if (unlikely (param_start > end))
    597 		goto not;
    598 	    }
    599 
    600 	  output_data.addr = addr + (data - begin);
    601 	  output_data.data = data;
    602 
    603 	  unsigned long string_end_idx = 0;
    604 	  fmt = save_fmt;
    605 	  while (*fmt != '\0')
    606 	    {
    607 	      if (*fmt != '%')
    608 		{
    609 		  char ch = *fmt++;
    610 		  if (ch == '\\')
    611 		    {
    612 		      switch ((ch = *fmt++))
    613 			{
    614 			case '0' ... '7':
    615 			  {
    616 			    int val = ch - '0';
    617 			    ch = *fmt;
    618 			    if (ch >= '0' && ch <= '7')
    619 			      {
    620 				val *= 8;
    621 				val += ch - '0';
    622 				ch = *++fmt;
    623 				if (ch >= '0' && ch <= '7' && val < 32)
    624 				  {
    625 				    val *= 8;
    626 				    val += ch - '0';
    627 				    ++fmt;
    628 				  }
    629 			      }
    630 			    ch = val;
    631 			  }
    632 			  break;
    633 
    634 			case 'n':
    635 			  ch = '\n';
    636 			  break;
    637 
    638 			case 't':
    639 			  ch = '\t';
    640 			  break;
    641 
    642 			default:
    643 			  retval = EINVAL;
    644 			  goto do_ret;
    645 			}
    646 		    }
    647 		  ADD_CHAR (ch);
    648 		  continue;
    649 		}
    650 	      ++fmt;
    651 
    652 	      int width = 0;
    653 	      while (isdigit (*fmt))
    654 		width = width * 10 + (*fmt++ - '0');
    655 
    656 	      int prec = 0;
    657 	      if (*fmt == '.')
    658 		while (isdigit (*++fmt))
    659 		  prec = prec * 10 + (*fmt - '0');
    660 
    661 	      size_t start_idx = bufcnt;
    662 	      switch (*fmt++)
    663 		{
    664 		  char mnebuf[16];
    665 		  const char *str;
    666 
    667 		case 'm':
    668 		  /* Mnemonic.  */
    669 
    670 		  if (unlikely (instrtab[cnt].mnemonic == MNE_INVALID))
    671 		    {
    672 		      switch (*data)
    673 			{
    674 #ifdef X86_64
    675 			case 0x90:
    676 			  if (prefixes & has_rex_b)
    677 			    goto not;
    678 			  str = "nop";
    679 			  break;
    680 #endif
    681 
    682 			case 0x98:
    683 #ifdef X86_64
    684 			  if (prefixes == (has_rex_w | has_rex))
    685 			    {
    686 			      str = "cltq";
    687 			      break;
    688 			    }
    689 #endif
    690 			  if (prefixes & ~has_data16)
    691 			    goto print_prefix;
    692 			  str = prefixes & has_data16 ? "cbtw" : "cwtl";
    693 			  break;
    694 
    695 			case 0x99:
    696 #ifdef X86_64
    697 			  if (prefixes == (has_rex_w | has_rex))
    698 			    {
    699 			      str = "cqto";
    700 			      break;
    701 			    }
    702 #endif
    703 			  if (prefixes & ~has_data16)
    704 			    goto print_prefix;
    705 			  str = prefixes & has_data16 ? "cwtd" : "cltd";
    706 			  break;
    707 
    708 			case 0xe3:
    709 			  if (prefixes & ~has_addr16)
    710 			    goto print_prefix;
    711 #ifdef X86_64
    712 			  str = prefixes & has_addr16 ? "jecxz" : "jrcxz";
    713 #else
    714 			  str = prefixes & has_addr16 ? "jcxz" : "jecxz";
    715 #endif
    716 			  break;
    717 
    718 			case 0x0f:
    719 			  if (data[1] == 0x0f)
    720 			    {
    721 			      /* AMD 3DNOW.  We need one more byte.  */
    722 			      if (param_start >= end)
    723 				goto not;
    724 			      if (*param_start < AMD3DNOW_LOW_IDX
    725 				  || *param_start > AMD3DNOW_HIGH_IDX)
    726 				goto not;
    727 			      unsigned int idx
    728 				= amd3dnow[AMD3DNOW_IDX (*param_start)];
    729 			      if (idx == 0)
    730 				goto not;
    731 			      str = amd3dnowstr + idx - 1;
    732 			      /* Eat the immediate byte indicating the
    733 				 operation.  */
    734 			      ++param_start;
    735 			      break;
    736 			    }
    737 #ifdef X86_64
    738 			  if (data[1] == 0xc7)
    739 			    {
    740 			      str = ((prefixes & has_rex_w)
    741 				     ? "cmpxchg16b" : "cmpxchg8b");
    742 			      break;
    743 			    }
    744 #endif
    745 			  if (data[1] == 0xc2)
    746 			    {
    747 			      if (param_start >= end)
    748 				goto not;
    749 			      if (*param_start > 7)
    750 				goto not;
    751 			      static const char cmpops[][9] =
    752 				{
    753 				  [0] = "cmpeq",
    754 				  [1] = "cmplt",
    755 				  [2] = "cmple",
    756 				  [3] = "cmpunord",
    757 				  [4] = "cmpneq",
    758 				  [5] = "cmpnlt",
    759 				  [6] = "cmpnle",
    760 				  [7] = "cmpord"
    761 				};
    762 			      char *cp = stpcpy (mnebuf, cmpops[*param_start]);
    763 			      if (correct_prefix & (has_rep | has_repne))
    764 				*cp++ = 's';
    765 			      else
    766 				*cp++ = 'p';
    767 			      if (correct_prefix & (has_data16 | has_repne))
    768 				*cp++ = 'd';
    769 			      else
    770 				*cp++ = 's';
    771 			      *cp = '\0';
    772 			      str = mnebuf;
    773 			      /* Eat the immediate byte indicating the
    774 				 operation.  */
    775 			      ++param_start;
    776 			      break;
    777 			    }
    778 
    779 			default:
    780 			  assert (! "INVALID not handled");
    781 			}
    782 		    }
    783 		  else
    784 		    str = mnestr.str + mneidx[instrtab[cnt].mnemonic];
    785 
    786 		  ADD_STRING (str);
    787 
    788 		  switch (instrtab[cnt].suffix)
    789 		    {
    790 		    case suffix_none:
    791 		      break;
    792 
    793 		    case suffix_w:
    794 		      if ((codep[-1] & 0xc0) != 0xc0)
    795 			{
    796 			  char ch;
    797 
    798 			  if (data[0] & 1)
    799 			    {
    800 			      if (prefixes & has_data16)
    801 				ch = 'w';
    802 #ifdef X86_64
    803 			      else if (prefixes & has_rex_w)
    804 				ch = 'q';
    805 #endif
    806 			      else
    807 				ch = 'l';
    808 			    }
    809 			  else
    810 			    ch = 'b';
    811 
    812 			  ADD_CHAR (ch);
    813 			}
    814 		      break;
    815 
    816 		    case suffix_w0:
    817 		      if ((codep[-1] & 0xc0) != 0xc0)
    818 			ADD_CHAR ('l');
    819 		      break;
    820 
    821 		    case suffix_w1:
    822 		      if ((data[0] & 0x4) == 0)
    823 			ADD_CHAR ('l');
    824 		      break;
    825 
    826 		    case suffix_W:
    827 		      if (prefixes & has_data16)
    828 			{
    829 			  ADD_CHAR ('w');
    830 			  prefixes &= ~has_data16;
    831 			}
    832 #ifdef X86_64
    833 		      else
    834 			ADD_CHAR ('q');
    835 #endif
    836 		      break;
    837 
    838 		    case suffix_W1:
    839 		      if (prefixes & has_data16)
    840 			{
    841 			  ADD_CHAR ('w');
    842 			  prefixes &= ~has_data16;
    843 			}
    844 #ifdef X86_64
    845 		      else if (prefixes & has_rex_w)
    846 			ADD_CHAR ('q');
    847 #endif
    848 		      break;
    849 
    850 		    case suffix_tttn:;
    851 		      static const char tttn[16][3] =
    852 			{
    853 			  "o", "no", "b", "ae", "e", "ne", "be", "a",
    854 			  "s", "ns", "p", "np", "l", "ge", "le", "g"
    855 			};
    856 		      ADD_STRING (tttn[codep[-1 - instrtab[cnt].modrm] & 0x0f]);
    857 		      break;
    858 
    859 		    case suffix_D:
    860 		      if ((codep[-1] & 0xc0) != 0xc0)
    861 			ADD_CHAR ((data[0] & 0x04) == 0 ? 's' : 'l');
    862 		      break;
    863 
    864 		    default:
    865 		      printf("unknown suffix %d\n", instrtab[cnt].suffix);
    866 		      abort ();
    867 		    }
    868 
    869 		  string_end_idx = bufcnt;
    870 		  break;
    871 
    872 		case 'o':
    873 		  if (prec == 1 && instrtab[cnt].fct1 != 0)
    874 		    {
    875 		      /* First parameter.  */
    876 		      if (instrtab[cnt].str1 != 0)
    877 			ADD_STRING (op1_str
    878 				    + op1_str_idx[instrtab[cnt].str1 - 1]);
    879 
    880 		      output_data.opoff1 = (instrtab[cnt].off1_1
    881 					    + OFF1_1_BIAS - opoff);
    882 		      output_data.opoff2 = (instrtab[cnt].off1_2
    883 					    + OFF1_2_BIAS - opoff);
    884 		      output_data.opoff3 = (instrtab[cnt].off1_3
    885 					    + OFF1_3_BIAS - opoff);
    886 		      int r = op1_fct[instrtab[cnt].fct1] (&output_data);
    887 		      if (r < 0)
    888 			goto not;
    889 		      if (r > 0)
    890 			goto enomem;
    891 
    892 		      string_end_idx = bufcnt;
    893 		    }
    894 		  else if (prec == 2 && instrtab[cnt].fct2 != 0)
    895 		    {
    896 		      /* Second parameter.  */
    897 		      if (instrtab[cnt].str2 != 0)
    898 			ADD_STRING (op2_str
    899 				    + op2_str_idx[instrtab[cnt].str2 - 1]);
    900 
    901 		      output_data.opoff1 = (instrtab[cnt].off2_1
    902 					    + OFF2_1_BIAS - opoff);
    903 		      output_data.opoff2 = (instrtab[cnt].off2_2
    904 					    + OFF2_2_BIAS - opoff);
    905 		      output_data.opoff3 = (instrtab[cnt].off2_3
    906 					    + OFF2_3_BIAS - opoff);
    907 		      int r = op2_fct[instrtab[cnt].fct2] (&output_data);
    908 		      if (r < 0)
    909 			goto not;
    910 		      if (r > 0)
    911 			goto enomem;
    912 
    913 		      string_end_idx = bufcnt;
    914 		    }
    915 		  else if (prec == 3 && instrtab[cnt].fct3 != 0)
    916 		    {
    917 		      /* Third parameter.  */
    918 		      if (instrtab[cnt].str3 != 0)
    919 			ADD_STRING (op3_str
    920 				    + op3_str_idx[instrtab[cnt].str3 - 1]);
    921 
    922 		      output_data.opoff1 = (instrtab[cnt].off3_1
    923 					    + OFF3_1_BIAS - opoff);
    924 		      output_data.opoff2 = (instrtab[cnt].off3_2
    925 					    + OFF3_2_BIAS - opoff);
    926 #ifdef OFF3_3_BITS
    927 		      output_data.opoff3 = (instrtab[cnt].off3_3
    928 					    + OFF3_3_BIAS - opoff);
    929 #else
    930 		      output_data.opoff3 = 0;
    931 #endif
    932 		      int r = op3_fct[instrtab[cnt].fct3] (&output_data);
    933 		      if (r < 0)
    934 			goto not;
    935 		      if (r > 0)
    936 			goto enomem;
    937 
    938 		      string_end_idx = bufcnt;
    939 		    }
    940 		  else
    941 		    bufcnt = string_end_idx;
    942 		  break;
    943 
    944 		case 'e':
    945 		  string_end_idx = bufcnt;
    946 		  break;
    947 
    948 		case 'a':
    949 		  /* Pad to requested column.  */
    950 		  while (bufcnt < (size_t) width)
    951 		    ADD_CHAR (' ');
    952 		  width = 0;
    953 		  break;
    954 
    955 		case 'l':
    956 		  if (output_data.labelbuf != NULL
    957 		      && output_data.labelbuf[0] != '\0')
    958 		    {
    959 		      ADD_STRING (output_data.labelbuf);
    960 		      output_data.labelbuf[0] = '\0';
    961 		      string_end_idx = bufcnt;
    962 		    }
    963 		  else if (output_data.symaddr_use != addr_none)
    964 		    {
    965 		      GElf_Addr symaddr = output_data.symaddr;
    966 		      if (output_data.symaddr_use >= addr_rel_symbolic)
    967 			symaddr += addr + param_start - begin;
    968 
    969 		      // XXX Lookup symbol based on symaddr
    970 		      const char *symstr = NULL;
    971 		      if (symcb != NULL
    972 			  && symcb (0 /* XXX */, 0 /* XXX */, symaddr,
    973 				    &output_data.labelbuf,
    974 				    &output_data.labelbufsize, symcbarg) == 0)
    975 			symstr = output_data.labelbuf;
    976 
    977 		      size_t bufavail = bufsize - bufcnt;
    978 		      int r = 0;
    979 		      if (symstr != NULL)
    980 			r = snprintf (&buf[bufcnt], bufavail, "# <%s>",
    981 				      symstr);
    982 		      else if (output_data.symaddr_use == addr_abs_always
    983 			       || output_data.symaddr_use == addr_rel_always)
    984 			r = snprintf (&buf[bufcnt], bufavail, "# %#" PRIx64,
    985 				      (uint64_t) symaddr);
    986 
    987 		      if (r < 0)
    988 			goto not;
    989 		      if ((size_t) r >= bufavail)
    990 			goto enomem;
    991 		      bufcnt += r;
    992 		      string_end_idx = bufcnt;
    993 
    994 		      output_data.symaddr_use = addr_none;
    995 		    }
    996 		  break;
    997 		}
    998 
    999 	      /* Pad according to the specified width.  */
   1000 	      while (bufcnt + prefix_size < start_idx + width)
   1001 		ADD_CHAR (' ');
   1002 	      prefix_size = 0;
   1003 	    }
   1004 
   1005 	  if ((prefixes & SEGMENT_PREFIXES) != 0)
   1006 	    goto print_prefix;
   1007 
   1008 	  assert (string_end_idx != ~0ul);
   1009 	  bufcnt = string_end_idx;
   1010 
   1011 	  addr += param_start - begin;
   1012 	  data = param_start;
   1013 
   1014 	  goto out;
   1015 	}
   1016 
   1017       /* Invalid (or at least unhandled) opcode.  */
   1018       if (prefixes != 0)
   1019 	goto print_prefix;
   1020       assert (*startp == data);
   1021       ++data;
   1022       ADD_STRING ("(bad)");
   1023       addr += data - begin;
   1024 
   1025     out:
   1026       if (bufcnt == bufsize)
   1027 	goto enomem;
   1028       buf[bufcnt] = '\0';
   1029 
   1030       *startp = data;
   1031       retval = outcb (buf, bufcnt, outcbarg);
   1032       if (retval != 0)
   1033 	goto do_ret;
   1034     }
   1035 
   1036  do_ret:
   1037   free (output_data.labelbuf);
   1038   if (buf != initbuf)
   1039     free (buf);
   1040 
   1041   return retval;
   1042 }
   1043