summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-01-12 03:06:47 +0000
committerUlrich Drepper <drepper@redhat.com>2008-01-12 03:06:47 +0000
commitfd47989094090138b0c857d067ac7ff05e7b6d91 (patch)
tree8c2aff1c3a3b3586cbdf608ff1bef9ba4ac6f0fa /libcpu
parent5eee122f63233ad4df924fedceab5e2649922aeb (diff)
downloadelfutils-fd47989094090138b0c857d067ac7ff05e7b6d91.tar.gz
Add comment with absolute address to %rip based address modes.
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/ChangeLog7
-rw-r--r--libcpu/i386_data.h3
-rw-r--r--libcpu/i386_disasm.c65
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);