diff options
author | paulgazz@chromium.org <paulgazz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-23 21:18:19 +0000 |
---|---|---|
committer | paulgazz@chromium.org <paulgazz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-23 21:18:19 +0000 |
commit | 144c8e950add26b44467784568d0ca5387a1047d (patch) | |
tree | 74c55e162f2128d67552a654d1cc57fb21b91afe /courgette/disassembler_elf_32_arm.cc | |
parent | 63d353f9d7a70dc827bad25e0932967711d595f3 (diff) | |
download | chromium_src-144c8e950add26b44467784568d0ca5387a1047d.zip chromium_src-144c8e950add26b44467784568d0ca5387a1047d.tar.gz chromium_src-144c8e950add26b44467784568d0ca5387a1047d.tar.bz2 |
Added a TypedRVA to track what kind of branch instruction is used for
the jump and compute the target RVA accordingly. Also updated the
unit test to use TypedRVA and check that only X86 RVAs are found by
the X86 "disassembler".
BUG=258645
Review URL: https://chromiumcodereview.appspot.com/18055007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@213220 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'courgette/disassembler_elf_32_arm.cc')
-rw-r--r-- | courgette/disassembler_elf_32_arm.cc | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/courgette/disassembler_elf_32_arm.cc b/courgette/disassembler_elf_32_arm.cc index f271020..6270c64 100644 --- a/courgette/disassembler_elf_32_arm.cc +++ b/courgette/disassembler_elf_32_arm.cc @@ -17,6 +17,45 @@ namespace courgette { +CheckBool DisassemblerElf32ARM::TypedRVAARM::ComputeRelativeTarget( + const uint8* op_pointer) { + uint32 temp = 0; + + switch (type_) { + case ARM_OFF24: + // The offset is given by the lower 24-bits of the op, shifted + // left 2 bits, and sign extended. + temp = Read32LittleEndian(op_pointer); + temp = (temp & 0x00FFFFFF) << 2; + if (temp & 0x02000000) + temp |= 0xFC000000; + temp += 8; + break; + case ARM_OFF8: + // The offset is given by lower 8 bits of the op. It is a 9-bit + // offset, shifted right one bit and signed extended. + temp = (Read16LittleEndian(op_pointer) & 0x00FF) << 1; + if (temp & 0x0100) + temp |= 0xFFFFFE00; + temp += 4; // Offset from _next_ PC. + break; + case ARM_OFF11: + // The offset is given by lower 11 bits of the op, and is a + // 12-bit offset, shifted right one bit and sign extended. + temp = (Read16LittleEndian(op_pointer) & 0x07FF) << 1; + if (temp & 0x00000800) + temp |= 0xFFFFF000; + temp += 4; // Offset from _next_ PC. + break; + default: + return false; + } + + set_relative_target(temp); + + return true; +} + DisassemblerElf32ARM::DisassemblerElf32ARM(const void* start, size_t length) : DisassemblerElf32(start, length) { } |