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