1 /* Disassembler for x86.
2 Copyright (C) 2007, 2008, 2009, 2011 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2007.
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.
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.
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.
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>. */
41 #include <sys/param.h>
43 #include "../libebl/libeblP.h"
45 #define MACHINE_ENCODING __LITTLE_ENDIAN
46 #include "memory-access.h"
50 # define MNEFILE "i386.mnemonics"
53 #define MNESTRFIELD(line) MNESTRFIELD1 (line)
54 #define MNESTRFIELD1(line) str##line
55 static const union mnestr_t
59 #define MNE(name) char MNESTRFIELD (__LINE__)[sizeof (#name)];
67 #define MNE(name) #name,
73 /* The index can be stored in the instrtab. */
76 #define MNE(name) MNE_##name,
82 static const unsigned short int mneidx[] =
85 [MNE_##name] = offsetof (union mnestr_t, MNESTRFIELD (__LINE__)),
113 #define prefbit(pref) has_##pref = 1 << idx_##pref
132 #define SEGMENT_PREFIXES \
133 (has_cs | has_ds | has_es | has_fs | has_gs | has_ss)
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
148 static const uint8_t known_prefixes[] =
150 #define newpref(pref) [idx_##pref] = prefix_##pref
164 #define nknown_prefixes (sizeof (known_prefixes) / sizeof (known_prefixes[0]))
168 static const char *prefix_str[] =
170 #define newpref(pref) [idx_##pref] = #pref
187 static const char amd3dnowstr[] =
188 #define MNE_3DNOW_PAVGUSB 1
190 #define MNE_3DNOW_PFADD (MNE_3DNOW_PAVGUSB + 8)
192 #define MNE_3DNOW_PFSUB (MNE_3DNOW_PFADD + 6)
194 #define MNE_3DNOW_PFSUBR (MNE_3DNOW_PFSUB + 6)
196 #define MNE_3DNOW_PFACC (MNE_3DNOW_PFSUBR + 7)
198 #define MNE_3DNOW_PFCMPGE (MNE_3DNOW_PFACC + 6)
200 #define MNE_3DNOW_PFCMPGT (MNE_3DNOW_PFCMPGE + 8)
202 #define MNE_3DNOW_PFCMPEQ (MNE_3DNOW_PFCMPGT + 8)
204 #define MNE_3DNOW_PFMIN (MNE_3DNOW_PFCMPEQ + 8)
206 #define MNE_3DNOW_PFMAX (MNE_3DNOW_PFMIN + 6)
208 #define MNE_3DNOW_PI2FD (MNE_3DNOW_PFMAX + 6)
210 #define MNE_3DNOW_PF2ID (MNE_3DNOW_PI2FD + 6)
212 #define MNE_3DNOW_PFRCP (MNE_3DNOW_PF2ID + 6)
214 #define MNE_3DNOW_PFRSQRT (MNE_3DNOW_PFRCP + 6)
216 #define MNE_3DNOW_PFMUL (MNE_3DNOW_PFRSQRT + 8)
218 #define MNE_3DNOW_PFRCPIT1 (MNE_3DNOW_PFMUL + 6)
220 #define MNE_3DNOW_PFRSQIT1 (MNE_3DNOW_PFRCPIT1 + 9)
222 #define MNE_3DNOW_PFRCPIT2 (MNE_3DNOW_PFRSQIT1 + 9)
224 #define MNE_3DNOW_PMULHRW (MNE_3DNOW_PFRCPIT2 + 9)
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[] =
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
265 const uint8_t **param_start;
282 # define DISFILE "i386_dis.h"
287 #define ADD_CHAR(ch) \
289 if (unlikely (bufcnt == bufsize)) \
291 buf[bufcnt++] = (ch); \
294 #define ADD_STRING(str) \
296 const char *_str0 = (str); \
297 size_t _len0 = strlen (_str0); \
298 ADD_NSTRING (_str0, _len0); \
301 #define ADD_NSTRING(str, len) \
303 const char *_str = (str); \
304 size_t _len = (len); \
305 if (unlikely (bufcnt + _len > bufsize)) \
307 memcpy (buf + bufcnt, _str, _len); \
313 i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
314 const char *fmt, DisasmOutputCB_t outcb, DisasmGetSymCB_t symcb,
315 void *outcbarg, void *symcbarg)
317 const char *save_fmt = fmt;
320 char initbuf[BUFSIZE];
323 size_t bufsize = BUFSIZE;
325 const uint8_t *param_start;
327 struct output_data output_data =
329 .prefixes = &prefixes,
333 .param_start = ¶m_start,
342 const uint8_t *data = *startp;
343 const uint8_t *begin = data;
345 /* Recognize all prefixes. */
346 int last_prefix_bit = 0;
350 for (i = idx_cs; i < nknown_prefixes; ++i)
351 if (known_prefixes[i] == *data)
353 if (i == nknown_prefixes)
356 prefixes |= last_prefix_bit = 1 << i;
362 if (data < end && (*data & 0xf0) == 0x40)
363 prefixes |= ((*data++) & 0xf) | has_rex;
369 const uint8_t *curr = match_data;
370 const uint8_t *const match_end = match_data + sizeof (match_data);
372 assert (data <= end);
383 while (curr < match_end)
385 uint_fast8_t len = *curr++;
386 uint_fast8_t clen = len >> 4;
388 const uint8_t *next_curr = curr + clen + (len - clen) * 2;
391 assert (curr + clen + 2 * (len - clen) <= match_end);
393 const uint8_t *codep = data;
394 int correct_prefix = 0;
397 if (data > begin && codep[-1] == *curr && clen > 0)
399 /* We match a prefix byte. This is exactly one byte and
400 is matched exactly, without a mask. */
407 assert (last_prefix_bit != 0);
408 correct_prefix = last_prefix_bit;
414 if (*codep++ != *curr++)
418 if (codep == end && avail > 0)
424 uint_fast8_t masked = *codep++ & *curr++;
425 if (masked != *curr++)
435 if (codep == end && avail > 0)
439 if (len > end - data)
440 /* There is not enough data for the entire instruction. The
441 caller can figure this out by looking at the pointer into
445 assert (correct_prefix == 0
446 || (prefixes & correct_prefix) != 0);
447 prefixes ^= correct_prefix;
451 /* Resize the buffer. */
456 buf = malloc (2 * bufsize);
458 buf = realloc (buf, 2 * bufsize);
467 output_data.bufp = buf;
468 output_data.bufsize = bufsize;
473 assert (prefixes != 0);
477 /* gcc is not clever enough to see the following variables
478 are not used uninitialized. */
480 : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep),
481 "=mr" (next_curr), "=mr" (len));
484 size_t prefix_size = 0;
486 // XXXonly print as prefix if valid?
487 if ((prefixes & has_lock) != 0)
489 ADD_STRING ("lock ");
493 if (instrtab[cnt].rep)
495 if ((prefixes & has_rep) != 0)
501 else if (instrtab[cnt].repe
502 && (prefixes & (has_rep | has_repne)) != 0)
504 if ((prefixes & has_repne) != 0)
506 ADD_STRING ("repne ");
509 else if ((prefixes & has_rep) != 0)
511 ADD_STRING ("repe ");
515 else if ((prefixes & (has_rep | has_repne)) != 0)
521 /* This is a prefix byte. Print it. */
528 ADD_STRING ("repne");
549 ADD_STRING ("data16");
552 ADD_STRING ("addr16");
576 puts ("unknown prefix");
585 /* We have a match. First determine how many bytes are
586 needed for the adressing mode. */
588 if (instrtab[cnt].modrm)
590 uint_fast8_t modrm = codep[-1];
593 if (likely ((prefixes & has_addr16) != 0))
595 /* Account for displacement. */
596 if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
598 else if ((modrm & 0xc0) == 0x40)
604 /* Account for SIB. */
605 if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4)
608 /* Account for displacement. */
609 if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
610 || ((modrm & 0xc7) == 0x4 && (codep[0] & 0x7) == 0x5))
612 else if ((modrm & 0xc0) == 0x40)
616 if (unlikely (param_start > end))
620 output_data.addr = addr + (data - begin);
621 output_data.data = data;
623 unsigned long string_end_idx = 0;
625 const char *deferred_start = NULL;
626 size_t deferred_len = 0;
627 // XXX Can we get this from color.c?
628 static const char color_off[] = "\e[0m";
636 switch ((ch = *fmt++))
642 if (ch >= '0' && ch <= '7')
647 if (ch >= '0' && ch <= '7' && val < 32)
671 else if (ch == '\e' && *fmt == '[')
673 deferred_start = fmt - 1;
676 while (*fmt != 'm' && *fmt != '\0');
680 deferred_len = ++fmt - deferred_start;
684 fmt = deferred_start + 1;
685 deferred_start = NULL;
693 while (isdigit (*fmt))
694 width = width * 10 + (*fmt++ - '0');
698 while (isdigit (*++fmt))
699 prec = prec * 10 + (*fmt - '0');
701 size_t start_idx = bufcnt;
702 size_t non_printing = 0;
711 if (unlikely (instrtab[cnt].mnemonic == MNE_INVALID))
717 if (prefixes & has_rex_b)
725 if (prefixes == (has_rex_w | has_rex))
731 if (prefixes & ~has_data16)
733 str = prefixes & has_data16 ? "cbtw" : "cwtl";
738 if (prefixes == (has_rex_w | has_rex))
744 if (prefixes & ~has_data16)
746 str = prefixes & has_data16 ? "cwtd" : "cltd";
750 if (prefixes & ~has_addr16)
753 str = prefixes & has_addr16 ? "jecxz" : "jrcxz";
755 str = prefixes & has_addr16 ? "jcxz" : "jecxz";
762 /* AMD 3DNOW. We need one more byte. */
763 if (param_start >= end)
765 if (*param_start < AMD3DNOW_LOW_IDX
766 || *param_start > AMD3DNOW_HIGH_IDX)
769 = amd3dnow[AMD3DNOW_IDX (*param_start)];
772 str = amd3dnowstr + idx - 1;
773 /* Eat the immediate byte indicating the
781 str = ((prefixes & has_rex_w)
782 ? "cmpxchg16b" : "cmpxchg8b");
788 if (param_start >= end)
790 if (*param_start > 7)
792 static const char cmpops[][9] =
803 char *cp = stpcpy (mnebuf, cmpops[*param_start]);
804 if (correct_prefix & (has_rep | has_repne))
808 if (correct_prefix & (has_data16 | has_repne))
814 /* Eat the immediate byte indicating the
821 assert (! "INVALID not handled");
825 str = mnestr.str + mneidx[instrtab[cnt].mnemonic];
827 if (deferred_start != NULL)
829 ADD_NSTRING (deferred_start, deferred_len);
830 non_printing += deferred_len;
835 switch (instrtab[cnt].suffix)
841 if ((codep[-1] & 0xc0) != 0xc0)
847 if (prefixes & has_data16)
850 else if (prefixes & has_rex_w)
864 if ((codep[-1] & 0xc0) != 0xc0)
869 if ((data[0] & 0x4) == 0)
874 if (prefixes & has_data16)
877 prefixes &= ~has_data16;
886 if (prefixes & has_data16)
889 prefixes &= ~has_data16;
892 else if (prefixes & has_rex_w)
898 static const char tttn[16][3] =
900 "o", "no", "b", "ae", "e", "ne", "be", "a",
901 "s", "ns", "p", "np", "l", "ge", "le", "g"
903 ADD_STRING (tttn[codep[-1 - instrtab[cnt].modrm] & 0x0f]);
907 if ((codep[-1] & 0xc0) != 0xc0)
908 ADD_CHAR ((data[0] & 0x04) == 0 ? 's' : 'l');
912 printf("unknown suffix %d\n", instrtab[cnt].suffix);
916 if (deferred_start != NULL)
918 ADD_STRING (color_off);
919 non_printing += strlen (color_off);
922 string_end_idx = bufcnt;
926 if (prec == 1 && instrtab[cnt].fct1 != 0)
928 /* First parameter. */
929 if (deferred_start != NULL)
931 ADD_NSTRING (deferred_start, deferred_len);
932 non_printing += deferred_len;
935 if (instrtab[cnt].str1 != 0)
937 + op1_str_idx[instrtab[cnt].str1 - 1]);
939 output_data.opoff1 = (instrtab[cnt].off1_1
940 + OFF1_1_BIAS - opoff);
941 output_data.opoff2 = (instrtab[cnt].off1_2
942 + OFF1_2_BIAS - opoff);
943 output_data.opoff3 = (instrtab[cnt].off1_3
944 + OFF1_3_BIAS - opoff);
945 int r = op1_fct[instrtab[cnt].fct1] (&output_data);
951 if (deferred_start != NULL)
953 ADD_STRING (color_off);
954 non_printing += strlen (color_off);
957 string_end_idx = bufcnt;
959 else if (prec == 2 && instrtab[cnt].fct2 != 0)
961 /* Second parameter. */
962 if (deferred_start != NULL)
964 ADD_NSTRING (deferred_start, deferred_len);
965 non_printing += deferred_len;
968 if (instrtab[cnt].str2 != 0)
970 + op2_str_idx[instrtab[cnt].str2 - 1]);
972 output_data.opoff1 = (instrtab[cnt].off2_1
973 + OFF2_1_BIAS - opoff);
974 output_data.opoff2 = (instrtab[cnt].off2_2
975 + OFF2_2_BIAS - opoff);
976 output_data.opoff3 = (instrtab[cnt].off2_3
977 + OFF2_3_BIAS - opoff);
978 int r = op2_fct[instrtab[cnt].fct2] (&output_data);
984 if (deferred_start != NULL)
986 ADD_STRING (color_off);
987 non_printing += strlen (color_off);
990 string_end_idx = bufcnt;
992 else if (prec == 3 && instrtab[cnt].fct3 != 0)
994 /* Third parameter. */
995 if (deferred_start != NULL)
997 ADD_NSTRING (deferred_start, deferred_len);
998 non_printing += deferred_len;
1001 if (instrtab[cnt].str3 != 0)
1003 + op3_str_idx[instrtab[cnt].str3 - 1]);
1005 output_data.opoff1 = (instrtab[cnt].off3_1
1006 + OFF3_1_BIAS - opoff);
1007 output_data.opoff2 = (instrtab[cnt].off3_2
1008 + OFF3_2_BIAS - opoff);
1010 output_data.opoff3 = (instrtab[cnt].off3_3
1011 + OFF3_3_BIAS - opoff);
1013 output_data.opoff3 = 0;
1015 int r = op3_fct[instrtab[cnt].fct3] (&output_data);
1021 if (deferred_start != NULL)
1023 ADD_STRING (color_off);
1024 non_printing += strlen (color_off);
1027 string_end_idx = bufcnt;
1030 bufcnt = string_end_idx;
1034 string_end_idx = bufcnt;
1038 /* Pad to requested column. */
1039 while (bufcnt - non_printing < (size_t) width)
1045 if (deferred_start != NULL)
1047 ADD_NSTRING (deferred_start, deferred_len);
1048 non_printing += deferred_len;
1051 if (output_data.labelbuf != NULL
1052 && output_data.labelbuf[0] != '\0')
1054 ADD_STRING (output_data.labelbuf);
1055 output_data.labelbuf[0] = '\0';
1056 string_end_idx = bufcnt;
1058 else if (output_data.symaddr_use != addr_none)
1060 GElf_Addr symaddr = output_data.symaddr;
1061 if (output_data.symaddr_use >= addr_rel_symbolic)
1062 symaddr += addr + param_start - begin;
1064 // XXX Lookup symbol based on symaddr
1065 const char *symstr = NULL;
1067 && symcb (0 /* XXX */, 0 /* XXX */, symaddr,
1068 &output_data.labelbuf,
1069 &output_data.labelbufsize, symcbarg) == 0)
1070 symstr = output_data.labelbuf;
1072 size_t bufavail = bufsize - bufcnt;
1075 r = snprintf (&buf[bufcnt], bufavail, "# <%s>",
1077 else if (output_data.symaddr_use == addr_abs_always
1078 || output_data.symaddr_use == addr_rel_always)
1079 r = snprintf (&buf[bufcnt], bufavail, "# %#" PRIx64,
1080 (uint64_t) symaddr);
1083 if ((size_t) r >= bufavail)
1086 string_end_idx = bufcnt;
1088 output_data.symaddr_use = addr_none;
1090 if (deferred_start != NULL)
1092 ADD_STRING (color_off);
1093 non_printing += strlen (color_off);
1101 deferred_start = NULL;
1103 /* Pad according to the specified width. */
1104 while (bufcnt + prefix_size - non_printing < start_idx + width)
1109 if ((prefixes & SEGMENT_PREFIXES) != 0)
1112 assert (string_end_idx != ~0ul);
1113 bufcnt = string_end_idx;
1115 addr += param_start - begin;
1121 /* Invalid (or at least unhandled) opcode. */
1124 assert (*startp == data);
1126 ADD_STRING ("(bad)");
1127 addr += data - begin;
1130 if (bufcnt == bufsize)
1135 retval = outcb (buf, bufcnt, outcbarg);
1141 free (output_data.labelbuf);