summaryrefslogtreecommitdiff
path: root/libcpu/i386_disasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcpu/i386_disasm.c')
-rw-r--r--libcpu/i386_disasm.c65
1 files changed, 62 insertions, 3 deletions
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);