summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-12-31 12:03:45 -0800
committerUlrich Drepper <drepper@redhat.com>2008-12-31 12:03:45 -0800
commita492e8ec781c08bd233b2564e5c0f1a8cf0378cb (patch)
tree482a15773e67506661e7817cde4d616cecaeec93
parent4692d8160c29cd97fc1598d5c8e465bb0a2e36e2 (diff)
downloadelfutils-a492e8ec781c08bd233b2564e5c0f1a8cf0378cb.tar.gz
Replay output operations correctly when internal buffer in x86/x86-64
disasembler code is full.
-rw-r--r--libcpu/ChangeLog2
-rw-r--r--libcpu/i386_disasm.c62
2 files changed, 40 insertions, 24 deletions
diff --git a/libcpu/ChangeLog b/libcpu/ChangeLog
index b3abff7b..5bc89f9f 100644
--- a/libcpu/ChangeLog
+++ b/libcpu/ChangeLog
@@ -1,5 +1,7 @@
2008-12-31 Ulrich Drepper <drepper@redhat.com>
+ * i386_disasm.c (i386_disasm): Correct resizing of buffer.
+
* i386_parse.y (struct argstring): Add off element.
(off_op_str): New global variable.
(print_op_str): Print strings as concatenated strings. Keep track
diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c
index 3ba513b4..76b5a393 100644
--- a/libcpu/i386_disasm.c
+++ b/libcpu/i386_disasm.c
@@ -356,6 +356,9 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
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);
@@ -369,30 +372,6 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
goto do_ret;
}
- 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;
-
- size_t cnt = 0;
next_match:
while (curr < match_end)
{
@@ -447,6 +426,41 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
|| (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" (start), "=mr" (len));
+ }
+
size_t prefix_size = 0;
// XXXonly print as prefix if valid?