diff options
author | Ulrich Drepper <drepper@redhat.com> | 2008-01-12 03:06:47 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2008-01-12 03:06:47 +0000 |
commit | fd47989094090138b0c857d067ac7ff05e7b6d91 (patch) | |
tree | 8c2aff1c3a3b3586cbdf608ff1bef9ba4ac6f0fa /libcpu | |
parent | 5eee122f63233ad4df924fedceab5e2649922aeb (diff) | |
download | elfutils-fd47989094090138b0c857d067ac7ff05e7b6d91.tar.gz |
Add comment with absolute address to %rip based address modes.
Diffstat (limited to 'libcpu')
-rw-r--r-- | libcpu/ChangeLog | 7 | ||||
-rw-r--r-- | libcpu/i386_data.h | 3 | ||||
-rw-r--r-- | libcpu/i386_disasm.c | 65 |
3 files changed, 72 insertions, 3 deletions
diff --git a/libcpu/ChangeLog b/libcpu/ChangeLog index cb0f4edf..f4478795 100644 --- a/libcpu/ChangeLog +++ b/libcpu/ChangeLog @@ -1,5 +1,12 @@ 2008-01-11 Ulrich Drepper <drepper@redhat.com> + * i386_disasm.c (struct output)buffer): Add labelbuf, labelbufsize, + symaddr_use, and symaddr fields. + (i386_disasm): Remove labelbuf and labelbufsize variables. + Add back %e format. Implement %a and %l formats. + * i386_data.h (general_mod$r_m): Set symaddr_use and symaddr for %rip + base addressing. + * i386_disasm.c (i386_disasm): Resize output buffer if necessary. Optimize output_data initialization. Free buffers before return. (struct output_data): Remove op1str field. Adjust code. diff --git a/libcpu/i386_data.h b/libcpu/i386_data.h index 89fa3089..43eb13f9 100644 --- a/libcpu/i386_data.h +++ b/libcpu/i386_data.h @@ -264,6 +264,9 @@ general_mod$r_m (struct output_data *d) #ifdef X86_64 n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)", disp < 0 ? "-" : "", disp < 0 ? -disp : disp); + + d->symaddr_use = addr_rel_always; + d->symaddr = disp; #else n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp); #endif diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c index 2a843923..57a870f1 100644 --- a/libcpu/i386_disasm.c +++ b/libcpu/i386_disasm.c @@ -199,6 +199,17 @@ struct output_data const uint8_t *end; DisasmGetSymCB_t symcb; void *symcbarg; + 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; }; @@ -233,8 +244,6 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, void *outcbarg, void *symcbarg) { const char *save_fmt = fmt; - char *labelbuf = NULL; - //size_t labelbufsize = 0; #define BUFSIZE 512 char initbuf[BUFSIZE]; @@ -800,6 +809,56 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 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 < (size_t) width) + ADD_CHAR (' '); + width = 0; + break; + + case 'l': + 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; + + 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); + + if (r < 0) + goto not; + if ((size_t) r >= bufavail) + goto enomem; + bufcnt += r; + string_end_idx = bufcnt; + + output_data.symaddr_use = addr_none; + } break; } @@ -841,7 +900,7 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, } do_ret: - free (labelbuf); + free (output_data.labelbuf); if (buf != initbuf) free (buf); |