diff options
Diffstat (limited to 'libcpu/i386_disasm.c')
| -rw-r--r-- | libcpu/i386_disasm.c | 137 |
1 files changed, 116 insertions, 21 deletions
diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c index c6bb0a58..832241f2 100644 --- a/libcpu/i386_disasm.c +++ b/libcpu/i386_disasm.c @@ -1,28 +1,31 @@ /* Disassembler for x86. - Copyright (C) 2007, 2008, 2009 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2007, 2008, 2009, 2011 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <[email protected]>, 2007. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of either - Red Hat elfutils is distributed in the hope that it will be useful, but + * 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 a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + 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> @@ -293,11 +296,18 @@ struct output_data #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 = strlen (_str); \ + size_t _len = (len); \ if (unlikely (bufcnt + _len > bufsize)) \ goto enomem; \ - memcpy (buf + bufcnt, str, _len); \ + memcpy (buf + bufcnt, _str, _len); \ bufcnt += _len; \ } while (0) @@ -615,6 +625,10 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 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 != '%') @@ -657,6 +671,22 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 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; } @@ -672,6 +702,7 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, prec = prec * 10 + (*fmt - '0'); size_t start_idx = bufcnt; + size_t non_printing = 0; switch (*fmt++) { char mnebuf[16]; @@ -796,6 +827,12 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 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) @@ -879,6 +916,12 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, abort (); } + if (deferred_start != NULL) + { + ADD_STRING (color_off); + non_printing += strlen (color_off); + } + string_end_idx = bufcnt; break; @@ -886,6 +929,12 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 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]); @@ -902,11 +951,23 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 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]); @@ -923,11 +984,23 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 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]); @@ -948,6 +1021,12 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, if (r > 0) goto enomem; + if (deferred_start != NULL) + { + ADD_STRING (color_off); + non_printing += strlen (color_off); + } + string_end_idx = bufcnt; } else @@ -960,12 +1039,18 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, case 'a': /* Pad to requested column. */ - while (bufcnt < (size_t) width) + 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') { @@ -1005,11 +1090,21 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 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 < start_idx + width) + while (bufcnt + prefix_size - non_printing < start_idx + width) ADD_CHAR (' '); prefix_size = 0; } |
