diff options
Diffstat (limited to 'src/libcpu/i386_disasm.c')
-rw-r--r-- | src/libcpu/i386_disasm.c | 1149 |
1 files changed, 0 insertions, 1149 deletions
diff --git a/src/libcpu/i386_disasm.c b/src/libcpu/i386_disasm.c deleted file mode 100644 index 832241f2..00000000 --- a/src/libcpu/i386_disasm.c +++ /dev/null @@ -1,1149 +0,0 @@ -/* Disassembler for x86. - Copyright (C) 2007, 2008, 2009, 2011 Red Hat, Inc. - This file is part of elfutils. - Written by Ulrich Drepper <drepper@redhat.com>, 2007. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - elfutils is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <assert.h> -#include <config.h> -#include <ctype.h> -#include <endian.h> -#include <errno.h> -#include <gelf.h> -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <sys/param.h> - -#include "../libebl/libeblP.h" - -#define MACHINE_ENCODING __LITTLE_ENDIAN -#include "memory-access.h" - - -#ifndef MNEFILE -# define MNEFILE "i386.mnemonics" -#endif - -#define MNESTRFIELD(line) MNESTRFIELD1 (line) -#define MNESTRFIELD1(line) str##line -static const union mnestr_t -{ - struct - { -#define MNE(name) char MNESTRFIELD (__LINE__)[sizeof (#name)]; -#include MNEFILE -#undef MNE - }; - char str[0]; -} mnestr = - { - { -#define MNE(name) #name, -#include MNEFILE -#undef MNE - } - }; - -/* The index can be stored in the instrtab. */ -enum - { -#define MNE(name) MNE_##name, -#include MNEFILE -#undef MNE - MNE_INVALID - }; - -static const unsigned short int mneidx[] = - { -#define MNE(name) \ - [MNE_##name] = offsetof (union mnestr_t, MNESTRFIELD (__LINE__)), -#include MNEFILE -#undef MNE - }; - - -enum - { - idx_rex_b = 0, - idx_rex_x, - idx_rex_r, - idx_rex_w, - idx_rex, - idx_cs, - idx_ds, - idx_es, - idx_fs, - idx_gs, - idx_ss, - idx_data16, - idx_addr16, - idx_rep, - idx_repne, - idx_lock - }; - -enum - { -#define prefbit(pref) has_##pref = 1 << idx_##pref - prefbit (rex_b), - prefbit (rex_x), - prefbit (rex_r), - prefbit (rex_w), - prefbit (rex), - prefbit (cs), - prefbit (ds), - prefbit (es), - prefbit (fs), - prefbit (gs), - prefbit (ss), - prefbit (data16), - prefbit (addr16), - prefbit (rep), - prefbit (repne), - prefbit (lock) -#undef prefbit - }; -#define SEGMENT_PREFIXES \ - (has_cs | has_ds | has_es | has_fs | has_gs | has_ss) - -#define prefix_cs 0x2e -#define prefix_ds 0x3e -#define prefix_es 0x26 -#define prefix_fs 0x64 -#define prefix_gs 0x65 -#define prefix_ss 0x36 -#define prefix_data16 0x66 -#define prefix_addr16 0x67 -#define prefix_rep 0xf3 -#define prefix_repne 0xf2 -#define prefix_lock 0xf0 - - -static const uint8_t known_prefixes[] = - { -#define newpref(pref) [idx_##pref] = prefix_##pref - newpref (cs), - newpref (ds), - newpref (es), - newpref (fs), - newpref (gs), - newpref (ss), - newpref (data16), - newpref (addr16), - newpref (rep), - newpref (repne), - newpref (lock) -#undef newpref - }; -#define nknown_prefixes (sizeof (known_prefixes) / sizeof (known_prefixes[0])) - - -#if 0 -static const char *prefix_str[] = - { -#define newpref(pref) [idx_##pref] = #pref - newpref (cs), - newpref (ds), - newpref (es), - newpref (fs), - newpref (gs), - newpref (ss), - newpref (data16), - newpref (addr16), - newpref (rep), - newpref (repne), - newpref (lock) -#undef newpref - }; -#endif - - -static const char amd3dnowstr[] = -#define MNE_3DNOW_PAVGUSB 1 - "pavgusb\0" -#define MNE_3DNOW_PFADD (MNE_3DNOW_PAVGUSB + 8) - "pfadd\0" -#define MNE_3DNOW_PFSUB (MNE_3DNOW_PFADD + 6) - "pfsub\0" -#define MNE_3DNOW_PFSUBR (MNE_3DNOW_PFSUB + 6) - "pfsubr\0" -#define MNE_3DNOW_PFACC (MNE_3DNOW_PFSUBR + 7) - "pfacc\0" -#define MNE_3DNOW_PFCMPGE (MNE_3DNOW_PFACC + 6) - "pfcmpge\0" -#define MNE_3DNOW_PFCMPGT (MNE_3DNOW_PFCMPGE + 8) - "pfcmpgt\0" -#define MNE_3DNOW_PFCMPEQ (MNE_3DNOW_PFCMPGT + 8) - "pfcmpeq\0" -#define MNE_3DNOW_PFMIN (MNE_3DNOW_PFCMPEQ + 8) - "pfmin\0" -#define MNE_3DNOW_PFMAX (MNE_3DNOW_PFMIN + 6) - "pfmax\0" -#define MNE_3DNOW_PI2FD (MNE_3DNOW_PFMAX + 6) - "pi2fd\0" -#define MNE_3DNOW_PF2ID (MNE_3DNOW_PI2FD + 6) - "pf2id\0" -#define MNE_3DNOW_PFRCP (MNE_3DNOW_PF2ID + 6) - "pfrcp\0" -#define MNE_3DNOW_PFRSQRT (MNE_3DNOW_PFRCP + 6) - "pfrsqrt\0" -#define MNE_3DNOW_PFMUL (MNE_3DNOW_PFRSQRT + 8) - "pfmul\0" -#define MNE_3DNOW_PFRCPIT1 (MNE_3DNOW_PFMUL + 6) - "pfrcpit1\0" -#define MNE_3DNOW_PFRSQIT1 (MNE_3DNOW_PFRCPIT1 + 9) - "pfrsqit1\0" -#define MNE_3DNOW_PFRCPIT2 (MNE_3DNOW_PFRSQIT1 + 9) - "pfrcpit2\0" -#define MNE_3DNOW_PMULHRW (MNE_3DNOW_PFRCPIT2 + 9) - "pmulhrw"; - -#define AMD3DNOW_LOW_IDX 0x0d -#define AMD3DNOW_HIGH_IDX (sizeof (amd3dnow) + AMD3DNOW_LOW_IDX - 1) -#define AMD3DNOW_IDX(val) ((val) - AMD3DNOW_LOW_IDX) -static const unsigned char amd3dnow[] = - { - [AMD3DNOW_IDX (0xbf)] = MNE_3DNOW_PAVGUSB, - [AMD3DNOW_IDX (0x9e)] = MNE_3DNOW_PFADD, - [AMD3DNOW_IDX (0x9a)] = MNE_3DNOW_PFSUB, - [AMD3DNOW_IDX (0xaa)] = MNE_3DNOW_PFSUBR, - [AMD3DNOW_IDX (0xae)] = MNE_3DNOW_PFACC, - [AMD3DNOW_IDX (0x90)] = MNE_3DNOW_PFCMPGE, - [AMD3DNOW_IDX (0xa0)] = MNE_3DNOW_PFCMPGT, - [AMD3DNOW_IDX (0xb0)] = MNE_3DNOW_PFCMPEQ, - [AMD3DNOW_IDX (0x94)] = MNE_3DNOW_PFMIN, - [AMD3DNOW_IDX (0xa4)] = MNE_3DNOW_PFMAX, - [AMD3DNOW_IDX (0x0d)] = MNE_3DNOW_PI2FD, - [AMD3DNOW_IDX (0x1d)] = MNE_3DNOW_PF2ID, - [AMD3DNOW_IDX (0x96)] = MNE_3DNOW_PFRCP, - [AMD3DNOW_IDX (0x97)] = MNE_3DNOW_PFRSQRT, - [AMD3DNOW_IDX (0xb4)] = MNE_3DNOW_PFMUL, - [AMD3DNOW_IDX (0xa6)] = MNE_3DNOW_PFRCPIT1, - [AMD3DNOW_IDX (0xa7)] = MNE_3DNOW_PFRSQIT1, - [AMD3DNOW_IDX (0xb6)] = MNE_3DNOW_PFRCPIT2, - [AMD3DNOW_IDX (0xb7)] = MNE_3DNOW_PMULHRW - }; - - -struct output_data -{ - GElf_Addr addr; - int *prefixes; - size_t opoff1; - size_t opoff2; - size_t opoff3; - char *bufp; - size_t *bufcntp; - size_t bufsize; - const uint8_t *data; - const uint8_t **param_start; - const uint8_t *end; - char *labelbuf; - size_t labelbufsize; - enum - { - addr_none = 0, - addr_abs_symbolic, - addr_abs_always, - addr_rel_symbolic, - addr_rel_always - } symaddr_use; - GElf_Addr symaddr; -}; - - -#ifndef DISFILE -# define DISFILE "i386_dis.h" -#endif -#include DISFILE - - -#define ADD_CHAR(ch) \ - do { \ - if (unlikely (bufcnt == bufsize)) \ - goto enomem; \ - buf[bufcnt++] = (ch); \ - } while (0) - -#define ADD_STRING(str) \ - do { \ - const char *_str0 = (str); \ - size_t _len0 = strlen (_str0); \ - ADD_NSTRING (_str0, _len0); \ - } while (0) - -#define ADD_NSTRING(str, len) \ - do { \ - const char *_str = (str); \ - size_t _len = (len); \ - if (unlikely (bufcnt + _len > bufsize)) \ - goto enomem; \ - memcpy (buf + bufcnt, _str, _len); \ - bufcnt += _len; \ - } while (0) - - -int -i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, - const char *fmt, DisasmOutputCB_t outcb, DisasmGetSymCB_t symcb, - void *outcbarg, void *symcbarg) -{ - const char *save_fmt = fmt; - -#define BUFSIZE 512 - char initbuf[BUFSIZE]; - int prefixes; - size_t bufcnt; - size_t bufsize = BUFSIZE; - char *buf = initbuf; - const uint8_t *param_start; - - struct output_data output_data = - { - .prefixes = &prefixes, - .bufp = buf, - .bufsize = bufsize, - .bufcntp = &bufcnt, - .param_start = ¶m_start, - .end = end - }; - - int retval = 0; - while (1) - { - prefixes = 0; - - const uint8_t *data = *startp; - const uint8_t *begin = data; - - /* Recognize all prefixes. */ - int last_prefix_bit = 0; - while (data < end) - { - unsigned int i; - for (i = idx_cs; i < nknown_prefixes; ++i) - if (known_prefixes[i] == *data) - break; - if (i == nknown_prefixes) - break; - - prefixes |= last_prefix_bit = 1 << i; - - ++data; - } - -#ifdef X86_64 - if (data < end && (*data & 0xf0) == 0x40) - prefixes |= ((*data++) & 0xf) | has_rex; -#endif - - bufcnt = 0; - size_t cnt = 0; - - const uint8_t *curr = match_data; - const uint8_t *const match_end = match_data + sizeof (match_data); - - assert (data <= end); - if (data == end) - { - if (prefixes != 0) - goto print_prefix; - - retval = -1; - goto do_ret; - } - - next_match: - while (curr < match_end) - { - uint_fast8_t len = *curr++; - uint_fast8_t clen = len >> 4; - len &= 0xf; - const uint8_t *next_curr = curr + clen + (len - clen) * 2; - - assert (len > 0); - assert (curr + clen + 2 * (len - clen) <= match_end); - - const uint8_t *codep = data; - int correct_prefix = 0; - int opoff = 0; - - if (data > begin && codep[-1] == *curr && clen > 0) - { - /* We match a prefix byte. This is exactly one byte and - is matched exactly, without a mask. */ - --len; - --clen; - opoff = 8; - - ++curr; - - assert (last_prefix_bit != 0); - correct_prefix = last_prefix_bit; - } - - size_t avail = len; - while (clen > 0) - { - if (*codep++ != *curr++) - goto not; - --avail; - --clen; - if (codep == end && avail > 0) - goto do_ret; - } - - while (avail > 0) - { - uint_fast8_t masked = *codep++ & *curr++; - if (masked != *curr++) - { - not: - curr = next_curr; - ++cnt; - bufcnt = 0; - goto next_match; - } - - --avail; - if (codep == end && avail > 0) - goto do_ret; - } - - if (len > end - data) - /* There is not enough data for the entire instruction. The - caller can figure this out by looking at the pointer into - the input data. */ - goto do_ret; - - assert (correct_prefix == 0 - || (prefixes & correct_prefix) != 0); - prefixes ^= correct_prefix; - - if (0) - { - /* Resize the buffer. */ - char *oldbuf; - enomem: - oldbuf = buf; - if (buf == initbuf) - buf = malloc (2 * bufsize); - else - buf = realloc (buf, 2 * bufsize); - if (buf == NULL) - { - buf = oldbuf; - retval = ENOMEM; - goto do_ret; - } - bufsize *= 2; - - output_data.bufp = buf; - output_data.bufsize = bufsize; - bufcnt = 0; - - if (data == end) - { - assert (prefixes != 0); - goto print_prefix; - } - - /* gcc is not clever enough to see the following variables - are not used uninitialized. */ - asm ("" - : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep), - "=mr" (next_curr), "=mr" (len)); - } - - size_t prefix_size = 0; - - // XXXonly print as prefix if valid? - if ((prefixes & has_lock) != 0) - { - ADD_STRING ("lock "); - prefix_size += 5; - } - - if (instrtab[cnt].rep) - { - if ((prefixes & has_rep) != 0) - { - ADD_STRING ("rep "); - prefix_size += 4; - } - } - else if (instrtab[cnt].repe - && (prefixes & (has_rep | has_repne)) != 0) - { - if ((prefixes & has_repne) != 0) - { - ADD_STRING ("repne "); - prefix_size += 6; - } - else if ((prefixes & has_rep) != 0) - { - ADD_STRING ("repe "); - prefix_size += 5; - } - } - else if ((prefixes & (has_rep | has_repne)) != 0) - { - uint_fast8_t byte; - print_prefix: - bufcnt = 0; - byte = *begin; - /* This is a prefix byte. Print it. */ - switch (byte) - { - case prefix_rep: - ADD_STRING ("rep"); - break; - case prefix_repne: - ADD_STRING ("repne"); - break; - case prefix_cs: - ADD_STRING ("cs"); - break; - case prefix_ds: - ADD_STRING ("ds"); - break; - case prefix_es: - ADD_STRING ("es"); - break; - case prefix_fs: - ADD_STRING ("fs"); - break; - case prefix_gs: - ADD_STRING ("gs"); - break; - case prefix_ss: - ADD_STRING ("ss"); - break; - case prefix_data16: - ADD_STRING ("data16"); - break; - case prefix_addr16: - ADD_STRING ("addr16"); - break; - case prefix_lock: - ADD_STRING ("lock"); - break; -#ifdef X86_64 - case 0x40 ... 0x4f: - ADD_STRING ("rex"); - if (byte != 0x40) - { - ADD_CHAR ('.'); - if (byte & 0x8) - ADD_CHAR ('w'); - if (byte & 0x4) - ADD_CHAR ('r'); - if (byte & 0x3) - ADD_CHAR ('x'); - if (byte & 0x1) - ADD_CHAR ('b'); - } - break; -#endif - default: - /* Cannot happen. */ - puts ("unknown prefix"); - abort (); - } - data = begin + 1; - ++addr; - - goto out; - } - - /* We have a match. First determine how many bytes are - needed for the adressing mode. */ - param_start = codep; - if (instrtab[cnt].modrm) - { - uint_fast8_t modrm = codep[-1]; - -#ifndef X86_64 - if (likely ((prefixes & has_addr16) != 0)) - { - /* Account for displacement. */ - if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80) - param_start += 2; - else if ((modrm & 0xc0) == 0x40) - param_start += 1; - } - else -#endif - { - /* Account for SIB. */ - if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4) - param_start += 1; - - /* Account for displacement. */ - if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80 - || ((modrm & 0xc7) == 0x4 && (codep[0] & 0x7) == 0x5)) - param_start += 4; - else if ((modrm & 0xc0) == 0x40) - param_start += 1; - } - - if (unlikely (param_start > end)) - goto not; - } - - output_data.addr = addr + (data - begin); - output_data.data = data; - - unsigned long string_end_idx = 0; - fmt = save_fmt; - const char *deferred_start = NULL; - size_t deferred_len = 0; - // XXX Can we get this from color.c? - static const char color_off[] = "\e[0m"; - while (*fmt != '\0') - { - if (*fmt != '%') - { - char ch = *fmt++; - if (ch == '\\') - { - switch ((ch = *fmt++)) - { - case '0' ... '7': - { - int val = ch - '0'; - ch = *fmt; - if (ch >= '0' && ch <= '7') - { - val *= 8; - val += ch - '0'; - ch = *++fmt; - if (ch >= '0' && ch <= '7' && val < 32) - { - val *= 8; - val += ch - '0'; - ++fmt; - } - } - ch = val; - } - break; - - case 'n': - ch = '\n'; - break; - - case 't': - ch = '\t'; - break; - - default: - retval = EINVAL; - goto do_ret; - } - } - else if (ch == '\e' && *fmt == '[') - { - deferred_start = fmt - 1; - do - ++fmt; - while (*fmt != 'm' && *fmt != '\0'); - - if (*fmt == 'm') - { - deferred_len = ++fmt - deferred_start; - continue; - } - - fmt = deferred_start + 1; - deferred_start = NULL; - } - ADD_CHAR (ch); - continue; - } - ++fmt; - - int width = 0; - while (isdigit (*fmt)) - width = width * 10 + (*fmt++ - '0'); - - int prec = 0; - if (*fmt == '.') - while (isdigit (*++fmt)) - prec = prec * 10 + (*fmt - '0'); - - size_t start_idx = bufcnt; - size_t non_printing = 0; - switch (*fmt++) - { - char mnebuf[16]; - const char *str; - - case 'm': - /* Mnemonic. */ - - if (unlikely (instrtab[cnt].mnemonic == MNE_INVALID)) - { - switch (*data) - { -#ifdef X86_64 - case 0x90: - if (prefixes & has_rex_b) - goto not; - str = "nop"; - break; -#endif - - case 0x98: -#ifdef X86_64 - if (prefixes == (has_rex_w | has_rex)) - { - str = "cltq"; - break; - } -#endif - if (prefixes & ~has_data16) - goto print_prefix; - str = prefixes & has_data16 ? "cbtw" : "cwtl"; - break; - - case 0x99: -#ifdef X86_64 - if (prefixes == (has_rex_w | has_rex)) - { - str = "cqto"; - break; - } -#endif - if (prefixes & ~has_data16) - goto print_prefix; - str = prefixes & has_data16 ? "cwtd" : "cltd"; - break; - - case 0xe3: - if (prefixes & ~has_addr16) - goto print_prefix; -#ifdef X86_64 - str = prefixes & has_addr16 ? "jecxz" : "jrcxz"; -#else - str = prefixes & has_addr16 ? "jcxz" : "jecxz"; -#endif - break; - - case 0x0f: - if (data[1] == 0x0f) - { - /* AMD 3DNOW. We need one more byte. */ - if (param_start >= end) - goto not; - if (*param_start < AMD3DNOW_LOW_IDX - || *param_start > AMD3DNOW_HIGH_IDX) - goto not; - unsigned int idx - = amd3dnow[AMD3DNOW_IDX (*param_start)]; - if (idx == 0) - goto not; - str = amd3dnowstr + idx - 1; - /* Eat the immediate byte indicating the - operation. */ - ++param_start; - break; - } -#ifdef X86_64 - if (data[1] == 0xc7) - { - str = ((prefixes & has_rex_w) - ? "cmpxchg16b" : "cmpxchg8b"); - break; - } -#endif - if (data[1] == 0xc2) - { - if (param_start >= end) - goto not; - if (*param_start > 7) - goto not; - static const char cmpops[][9] = - { - [0] = "cmpeq", - [1] = "cmplt", - [2] = "cmple", - [3] = "cmpunord", - [4] = "cmpneq", - [5] = "cmpnlt", - [6] = "cmpnle", - [7] = "cmpord" - }; - char *cp = stpcpy (mnebuf, cmpops[*param_start]); - if (correct_prefix & (has_rep | has_repne)) - *cp++ = 's'; - else - *cp++ = 'p'; - if (correct_prefix & (has_data16 | has_repne)) - *cp++ = 'd'; - else - *cp++ = 's'; - *cp = '\0'; - str = mnebuf; - /* Eat the immediate byte indicating the - operation. */ - ++param_start; - break; - } - - default: - assert (! "INVALID not handled"); - } - } - else - str = mnestr.str + mneidx[instrtab[cnt].mnemonic]; - - if (deferred_start != NULL) - { - ADD_NSTRING (deferred_start, deferred_len); - non_printing += deferred_len; - } - - ADD_STRING (str); - - switch (instrtab[cnt].suffix) - { - case suffix_none: - break; - - case suffix_w: - if ((codep[-1] & 0xc0) != 0xc0) - { - char ch; - - if (data[0] & 1) - { - if (prefixes & has_data16) - ch = 'w'; -#ifdef X86_64 - else if (prefixes & has_rex_w) - ch = 'q'; -#endif - else - ch = 'l'; - } - else - ch = 'b'; - - ADD_CHAR (ch); - } - break; - - case suffix_w0: - if ((codep[-1] & 0xc0) != 0xc0) - ADD_CHAR ('l'); - break; - - case suffix_w1: - if ((data[0] & 0x4) == 0) - ADD_CHAR ('l'); - break; - - case suffix_W: - if (prefixes & has_data16) - { - ADD_CHAR ('w'); - prefixes &= ~has_data16; - } -#ifdef X86_64 - else - ADD_CHAR ('q'); -#endif - break; - - case suffix_W1: - if (prefixes & has_data16) - { - ADD_CHAR ('w'); - prefixes &= ~has_data16; - } -#ifdef X86_64 - else if (prefixes & has_rex_w) - ADD_CHAR ('q'); -#endif - break; - - case suffix_tttn:; - static const char tttn[16][3] = - { - "o", "no", "b", "ae", "e", "ne", "be", "a", - "s", "ns", "p", "np", "l", "ge", "le", "g" - }; - ADD_STRING (tttn[codep[-1 - instrtab[cnt].modrm] & 0x0f]); - break; - - case suffix_D: - if ((codep[-1] & 0xc0) != 0xc0) - ADD_CHAR ((data[0] & 0x04) == 0 ? 's' : 'l'); - break; - - default: - printf("unknown suffix %d\n", instrtab[cnt].suffix); - abort (); - } - - if (deferred_start != NULL) - { - ADD_STRING (color_off); - non_printing += strlen (color_off); - } - - string_end_idx = bufcnt; - break; - - case 'o': - if (prec == 1 && instrtab[cnt].fct1 != 0) - { - /* First parameter. */ - if (deferred_start != NULL) - { - ADD_NSTRING (deferred_start, deferred_len); - non_printing += deferred_len; - } - - if (instrtab[cnt].str1 != 0) - ADD_STRING (op1_str - + op1_str_idx[instrtab[cnt].str1 - 1]); - - output_data.opoff1 = (instrtab[cnt].off1_1 - + OFF1_1_BIAS - opoff); - output_data.opoff2 = (instrtab[cnt].off1_2 - + OFF1_2_BIAS - opoff); - output_data.opoff3 = (instrtab[cnt].off1_3 - + OFF1_3_BIAS - opoff); - int r = op1_fct[instrtab[cnt].fct1] (&output_data); - if (r < 0) - goto not; - if (r > 0) - goto enomem; - - if (deferred_start != NULL) - { - ADD_STRING (color_off); - non_printing += strlen (color_off); - } - - string_end_idx = bufcnt; - } - else if (prec == 2 && instrtab[cnt].fct2 != 0) - { - /* Second parameter. */ - if (deferred_start != NULL) - { - ADD_NSTRING (deferred_start, deferred_len); - non_printing += deferred_len; - } - - if (instrtab[cnt].str2 != 0) - ADD_STRING (op2_str - + op2_str_idx[instrtab[cnt].str2 - 1]); - - output_data.opoff1 = (instrtab[cnt].off2_1 - + OFF2_1_BIAS - opoff); - output_data.opoff2 = (instrtab[cnt].off2_2 - + OFF2_2_BIAS - opoff); - output_data.opoff3 = (instrtab[cnt].off2_3 - + OFF2_3_BIAS - opoff); - int r = op2_fct[instrtab[cnt].fct2] (&output_data); - if (r < 0) - goto not; - if (r > 0) - goto enomem; - - if (deferred_start != NULL) - { - ADD_STRING (color_off); - non_printing += strlen (color_off); - } - - string_end_idx = bufcnt; - } - else if (prec == 3 && instrtab[cnt].fct3 != 0) - { - /* Third parameter. */ - if (deferred_start != NULL) - { - ADD_NSTRING (deferred_start, deferred_len); - non_printing += deferred_len; - } - - if (instrtab[cnt].str3 != 0) - ADD_STRING (op3_str - + op3_str_idx[instrtab[cnt].str3 - 1]); - - output_data.opoff1 = (instrtab[cnt].off3_1 - + OFF3_1_BIAS - opoff); - output_data.opoff2 = (instrtab[cnt].off3_2 - + OFF3_2_BIAS - opoff); -#ifdef OFF3_3_BITS - output_data.opoff3 = (instrtab[cnt].off3_3 - + OFF3_3_BIAS - opoff); -#else - output_data.opoff3 = 0; -#endif - int r = op3_fct[instrtab[cnt].fct3] (&output_data); - if (r < 0) - goto not; - if (r > 0) - goto enomem; - - if (deferred_start != NULL) - { - ADD_STRING (color_off); - non_printing += strlen (color_off); - } - - string_end_idx = bufcnt; - } - else - bufcnt = string_end_idx; - break; - - case 'e': - string_end_idx = bufcnt; - break; - - case 'a': - /* Pad to requested column. */ - while (bufcnt - non_printing < (size_t) width) - ADD_CHAR (' '); - width = 0; - break; - - case 'l': - if (deferred_start != NULL) - { - ADD_NSTRING (deferred_start, deferred_len); - non_printing += deferred_len; - } - - if (output_data.labelbuf != NULL - && output_data.labelbuf[0] != '\0') - { - ADD_STRING (output_data.labelbuf); - output_data.labelbuf[0] = '\0'; - string_end_idx = bufcnt; - } - else if (output_data.symaddr_use != addr_none) - { - GElf_Addr symaddr = output_data.symaddr; - if (output_data.symaddr_use >= addr_rel_symbolic) - symaddr += addr + param_start - begin; - - // XXX Lookup symbol based on symaddr - const char *symstr = NULL; - if (symcb != NULL - && symcb (0 /* XXX */, 0 /* XXX */, symaddr, - &output_data.labelbuf, - &output_data.labelbufsize, symcbarg) == 0) - symstr = output_data.labelbuf; - - size_t bufavail = bufsize - bufcnt; - int r = 0; - if (symstr != NULL) - r = snprintf (&buf[bufcnt], bufavail, "# <%s>", - symstr); - else if (output_data.symaddr_use == addr_abs_always - || output_data.symaddr_use == addr_rel_always) - r = snprintf (&buf[bufcnt], bufavail, "# %#" PRIx64, - (uint64_t) symaddr); - - assert (r >= 0); - if ((size_t) r >= bufavail) - goto enomem; - bufcnt += r; - string_end_idx = bufcnt; - - output_data.symaddr_use = addr_none; - } - if (deferred_start != NULL) - { - ADD_STRING (color_off); - non_printing += strlen (color_off); - } - break; - - default: - abort (); - } - - deferred_start = NULL; - - /* Pad according to the specified width. */ - while (bufcnt + prefix_size - non_printing < start_idx + width) - ADD_CHAR (' '); - prefix_size = 0; - } - - if ((prefixes & SEGMENT_PREFIXES) != 0) - goto print_prefix; - - assert (string_end_idx != ~0ul); - bufcnt = string_end_idx; - - addr += param_start - begin; - data = param_start; - - goto out; - } - - /* Invalid (or at least unhandled) opcode. */ - if (prefixes != 0) - goto print_prefix; - assert (*startp == data); - ++data; - ADD_STRING ("(bad)"); - addr += data - begin; - - out: - if (bufcnt == bufsize) - goto enomem; - buf[bufcnt] = '\0'; - - *startp = data; - retval = outcb (buf, bufcnt, outcbarg); - if (retval != 0) - goto do_ret; - } - - do_ret: - free (output_data.labelbuf); - if (buf != initbuf) - free (buf); - - return retval; -} |