Home | History | Annotate | Download | only in courgette
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "courgette/base_test_unittest.h"
      6 #include "courgette/disassembler_elf_32_arm.h"
      7 #include "courgette/disassembler_elf_32_x86.h"
      8 
      9 class TypedRVATest : public BaseTest {
     10  public:
     11   void TestRelativeTargetX86(courgette::RVA word, courgette::RVA expected)
     12     const;
     13 
     14   void TestRelativeTargetARM(courgette::ARM_RVA arm_rva,
     15                              courgette::RVA rva,
     16                              uint32 op,
     17                              courgette::RVA expected) const;
     18 
     19   void TestARMOPEncode(courgette::ARM_RVA arm_rva,
     20                        courgette::RVA rva,
     21                        uint32 op,
     22                        courgette::RVA expected) const;
     23 };
     24 
     25 void TypedRVATest::TestRelativeTargetX86(courgette::RVA word,
     26                                          courgette::RVA expected) const {
     27   courgette::DisassemblerElf32X86::TypedRVAX86* typed_rva
     28     = new courgette::DisassemblerElf32X86::TypedRVAX86(0);
     29   const uint8* op_pointer = reinterpret_cast<const uint8*>(&word);
     30 
     31   EXPECT_TRUE(typed_rva->ComputeRelativeTarget(op_pointer));
     32   EXPECT_EQ(typed_rva->relative_target(), expected);
     33 
     34   delete typed_rva;
     35 }
     36 
     37 uint32 Read32LittleEndian(const void* address) {
     38   return *reinterpret_cast<const uint32*>(address);
     39 }
     40 
     41 void TypedRVATest::TestRelativeTargetARM(courgette::ARM_RVA arm_rva,
     42                                          courgette::RVA rva,
     43                                          uint32 op,
     44                                          courgette::RVA expected) const {
     45   courgette::DisassemblerElf32ARM::TypedRVAARM* typed_rva
     46     = new courgette::DisassemblerElf32ARM::TypedRVAARM(arm_rva, rva);
     47   uint8* op_pointer = reinterpret_cast<uint8*>(&op);
     48 
     49   EXPECT_TRUE(typed_rva->ComputeRelativeTarget(op_pointer));
     50   EXPECT_EQ(rva + typed_rva->relative_target(), expected);
     51 
     52   delete typed_rva;
     53 }
     54 
     55 void TypedRVATest::TestARMOPEncode(courgette::ARM_RVA arm_rva,
     56                              courgette::RVA rva,
     57                              uint32 op,
     58                              courgette::RVA expected) const {
     59   uint16 c_op;
     60   uint32 addr;
     61   EXPECT_TRUE(courgette::DisassemblerElf32ARM::Compress(arm_rva, op, rva,
     62                                                         &c_op, &addr));
     63   EXPECT_EQ(rva + addr, expected);
     64 
     65   uint32 new_op;
     66   EXPECT_TRUE(courgette::DisassemblerElf32ARM::Decompress(arm_rva, c_op, addr,
     67                                                           &new_op));
     68   EXPECT_EQ(new_op, op);
     69 }
     70 
     71 TEST_F(TypedRVATest, TestX86) {
     72   TestRelativeTargetX86(0x0, 0x4);
     73 }
     74 
     75 // ARM opcodes taken from and tested against the output of
     76 // "arm-linux-gnueabi-objdump -d daisy_3701.98.0/bin/ls"
     77 
     78 TEST_F(TypedRVATest, TestARM_OFF8_PREFETCH) {
     79   TestRelativeTargetARM(courgette::ARM_OFF8, 0x0, 0x0, 0x4);
     80 }
     81 
     82 TEST_F(TypedRVATest, TestARM_OFF8_FORWARDS) {
     83   TestRelativeTargetARM(courgette::ARM_OFF8, 0x2bcc, 0xd00e, 0x2bec);
     84   TestRelativeTargetARM(courgette::ARM_OFF8, 0x3752, 0xd910, 0x3776);
     85 }
     86 
     87 TEST_F(TypedRVATest, TestARM_OFF8_BACKWARDS) {
     88   TestRelativeTargetARM(courgette::ARM_OFF8, 0x3774, 0xd1f6, 0x3764);
     89 }
     90 
     91 TEST_F(TypedRVATest, TestARM_OFF11_PREFETCH) {
     92   TestRelativeTargetARM(courgette::ARM_OFF11, 0x0, 0x0, 0x4);
     93 }
     94 
     95 TEST_F(TypedRVATest, TestARM_OFF11_FORWARDS) {
     96   TestRelativeTargetARM(courgette::ARM_OFF11, 0x2bea, 0xe005, 0x2bf8);
     97 }
     98 
     99 TEST_F(TypedRVATest, TestARM_OFF11_BACKWARDS) {
    100   TestRelativeTargetARM(courgette::ARM_OFF11, 0x2f80, 0xe6cd, 0x2d1e);
    101   TestRelativeTargetARM(courgette::ARM_OFF11, 0x3610, 0xe56a, 0x30e8);
    102 }
    103 
    104 TEST_F(TypedRVATest, TestARM_OFF24_PREFETCH) {
    105   TestRelativeTargetARM(courgette::ARM_OFF24, 0x0, 0x0, 0x8);
    106 }
    107 
    108 TEST_F(TypedRVATest, TestARM_OFF24_FORWARDS) {
    109   TestRelativeTargetARM(courgette::ARM_OFF24, 0x2384, 0x4af3613a, 0xffcda874);
    110   TestRelativeTargetARM(courgette::ARM_OFF24, 0x23bc, 0x6af961b9, 0xffe5aaa8);
    111   TestRelativeTargetARM(courgette::ARM_OFF24, 0x23d4, 0x2b006823, 0x1c468);
    112 }
    113 
    114 TEST_F(TypedRVATest, TestARM_OFF24_BACKWARDS) {
    115   // TODO(paulgazz): find a real-world example of an non-thumb ARM
    116   // branch op that jumps backwards.
    117 }
    118 
    119 TEST_F(TypedRVATest, TestARM_OFF25_FORWARDS) {
    120   TestRelativeTargetARM(courgette::ARM_OFF25, 0x2bf4, 0xfe06f008, 0xb804);
    121   TestRelativeTargetARM(courgette::ARM_OFF25, 0x2c58, 0xfeacf005, 0x89b4);
    122 }
    123 
    124 TEST_F(TypedRVATest, TestARM_OFF25_BACKWARDS) {
    125   TestRelativeTargetARM(courgette::ARM_OFF25, 0x2bd2, 0xeb9ef7ff, 0x2310);
    126   TestRelativeTargetARM(courgette::ARM_OFF25, 0x2bd8, 0xeb8ef7ff, 0x22f8);
    127   TestRelativeTargetARM(courgette::ARM_OFF25, 0x2c3e, 0xea2ef7ff, 0x209c);
    128 }
    129 
    130 TEST_F(TypedRVATest, TestARM_OFF21_FORWARDS) {
    131   TestRelativeTargetARM(courgette::ARM_OFF21, 0x2bc6, 0x84c7f000, 0x3558);
    132   TestRelativeTargetARM(courgette::ARM_OFF21, 0x2bde, 0x871df000, 0x3a1c);
    133   TestRelativeTargetARM(courgette::ARM_OFF21, 0x2c5e, 0x86c1f2c0, 0x39e4);
    134 }
    135 
    136 TEST_F(TypedRVATest, TestARM_OFF21_BACKWARDS) {
    137   TestRelativeTargetARM(courgette::ARM_OFF21, 0x67e4, 0xaee9f43f, 0x65ba);
    138   TestRelativeTargetARM(courgette::ARM_OFF21, 0x67ee, 0xaee4f47f, 0x65ba);
    139 }
    140 
    141 TEST_F(TypedRVATest, TestARMOPEncode) {
    142   TestARMOPEncode(courgette::ARM_OFF8, 0x2bcc, 0xd00e, 0x2bec);
    143   TestARMOPEncode(courgette::ARM_OFF8, 0x3752, 0xd910, 0x3776);
    144   TestARMOPEncode(courgette::ARM_OFF8, 0x3774, 0xd1f6, 0x3764);
    145   TestARMOPEncode(courgette::ARM_OFF11, 0x0, 0x0, 0x4);
    146   TestARMOPEncode(courgette::ARM_OFF11, 0x2bea, 0xe005, 0x2bf8);
    147   TestARMOPEncode(courgette::ARM_OFF11, 0x2f80, 0xe6cd, 0x2d1e);
    148   TestARMOPEncode(courgette::ARM_OFF11, 0x3610, 0xe56a, 0x30e8);
    149   TestARMOPEncode(courgette::ARM_OFF24, 0x0, 0x0, 0x8);
    150   TestARMOPEncode(courgette::ARM_OFF24, 0x2384, 0x4af3613a, 0xffcda874);
    151   TestARMOPEncode(courgette::ARM_OFF24, 0x23bc, 0x6af961b9, 0xffe5aaa8);
    152   TestARMOPEncode(courgette::ARM_OFF24, 0x23d4, 0x2b006823, 0x1c468);
    153   TestARMOPEncode(courgette::ARM_OFF25, 0x2bf4, 0xf008fe06, 0xb804);
    154   TestARMOPEncode(courgette::ARM_OFF25, 0x2c58, 0xf005feac, 0x89b4);
    155   TestARMOPEncode(courgette::ARM_OFF25, 0x2bd2, 0xf7ffeb9e, 0x2310);
    156   TestARMOPEncode(courgette::ARM_OFF25, 0x2bd8, 0xf7ffeb8e, 0x22f8);
    157   TestARMOPEncode(courgette::ARM_OFF25, 0x2c3e, 0xf7ffea2e, 0x209c);
    158   TestARMOPEncode(courgette::ARM_OFF21, 0x2bc6, 0xf00084c7, 0x3558);
    159   TestARMOPEncode(courgette::ARM_OFF21, 0x2bde, 0xf000871d, 0x3a1c);
    160   TestARMOPEncode(courgette::ARM_OFF21, 0x2c5e, 0xf2c086c1, 0x39e4);
    161   TestARMOPEncode(courgette::ARM_OFF21, 0x67e4, 0xf43faee9, 0x65ba);
    162   TestARMOPEncode(courgette::ARM_OFF21, 0x67ee, 0xf47faee4, 0x65ba);
    163 }
    164