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
9class 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
25void 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
37uint32 Read32LittleEndian(const void* address) {
38  return *reinterpret_cast<const uint32*>(address);
39}
40
41void 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
55void 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
71TEST_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
78TEST_F(TypedRVATest, TestARM_OFF8_PREFETCH) {
79  TestRelativeTargetARM(courgette::ARM_OFF8, 0x0, 0x0, 0x4);
80}
81
82TEST_F(TypedRVATest, TestARM_OFF8_FORWARDS) {
83  TestRelativeTargetARM(courgette::ARM_OFF8, 0x2bcc, 0xd00e, 0x2bec);
84  TestRelativeTargetARM(courgette::ARM_OFF8, 0x3752, 0xd910, 0x3776);
85}
86
87TEST_F(TypedRVATest, TestARM_OFF8_BACKWARDS) {
88  TestRelativeTargetARM(courgette::ARM_OFF8, 0x3774, 0xd1f6, 0x3764);
89}
90
91TEST_F(TypedRVATest, TestARM_OFF11_PREFETCH) {
92  TestRelativeTargetARM(courgette::ARM_OFF11, 0x0, 0x0, 0x4);
93}
94
95TEST_F(TypedRVATest, TestARM_OFF11_FORWARDS) {
96  TestRelativeTargetARM(courgette::ARM_OFF11, 0x2bea, 0xe005, 0x2bf8);
97}
98
99TEST_F(TypedRVATest, TestARM_OFF11_BACKWARDS) {
100  TestRelativeTargetARM(courgette::ARM_OFF11, 0x2f80, 0xe6cd, 0x2d1e);
101  TestRelativeTargetARM(courgette::ARM_OFF11, 0x3610, 0xe56a, 0x30e8);
102}
103
104TEST_F(TypedRVATest, TestARM_OFF24_PREFETCH) {
105  TestRelativeTargetARM(courgette::ARM_OFF24, 0x0, 0x0, 0x8);
106}
107
108TEST_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
114TEST_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
119TEST_F(TypedRVATest, TestARM_OFF25_FORWARDS) {
120  TestRelativeTargetARM(courgette::ARM_OFF25, 0x2bf4, 0xfe06f008, 0xb804);
121  TestRelativeTargetARM(courgette::ARM_OFF25, 0x2c58, 0xfeacf005, 0x89b4);
122}
123
124TEST_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
130TEST_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
136TEST_F(TypedRVATest, TestARM_OFF21_BACKWARDS) {
137  TestRelativeTargetARM(courgette::ARM_OFF21, 0x67e4, 0xaee9f43f, 0x65ba);
138  TestRelativeTargetARM(courgette::ARM_OFF21, 0x67ee, 0xaee4f47f, 0x65ba);
139}
140
141TEST_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