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