diff options
Diffstat (limited to 'libcpu/i386_disasm.c')
-rw-r--r-- | libcpu/i386_disasm.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c index a656cdb4..c6bb0a58 100644 --- a/libcpu/i386_disasm.c +++ b/libcpu/i386_disasm.c @@ -1,5 +1,5 @@ /* Disassembler for x86. - Copyright (C) 2007, 2008 Red Hat, Inc. + Copyright (C) 2007, 2008, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2007. @@ -376,37 +376,49 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, while (curr < match_end) { uint_fast8_t len = *curr++; - const uint8_t *start = curr; + uint_fast8_t clen = len >> 4; + len &= 0xf; + const uint8_t *next_curr = curr + clen + (len - clen) * 2; assert (len > 0); - assert (curr + 2 * len <= match_end); + assert (curr + clen + 2 * (len - clen) <= match_end); const uint8_t *codep = data; int correct_prefix = 0; int opoff = 0; - if (data > begin && codep[-1] == curr[1] && curr[0] == 0xff) + if (data > begin && codep[-1] == *curr && clen > 0) { /* We match a prefix byte. This is exactly one byte and is matched exactly, without a mask. */ --len; - start += 2; + --clen; opoff = 8; - curr += 2; + ++curr; assert (last_prefix_bit != 0); correct_prefix = last_prefix_bit; } size_t avail = len; + while (clen > 0) + { + if (*codep++ != *curr++) + goto not; + --avail; + --clen; + if (codep == end && avail > 0) + goto do_ret; + } + while (avail > 0) { uint_fast8_t masked = *codep++ & *curr++; if (masked != *curr++) { not: - curr = start + 2 * len; + curr = next_curr; ++cnt; bufcnt = 0; goto next_match; @@ -459,7 +471,7 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, are not used uninitialized. */ asm ("" : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep), - "=mr" (start), "=mr" (len)); + "=mr" (next_curr), "=mr" (len)); } size_t prefix_size = 0; |