1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker *
4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker *
8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker *
10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker */
16*eb293b8fSAndroid Build Coastguard Worker
17*eb293b8fSAndroid Build Coastguard Worker #include <elf.h>
18*eb293b8fSAndroid Build Coastguard Worker
19*eb293b8fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
20*eb293b8fSAndroid Build Coastguard Worker
21*eb293b8fSAndroid Build Coastguard Worker #include <memory>
22*eb293b8fSAndroid Build Coastguard Worker #include <vector>
23*eb293b8fSAndroid Build Coastguard Worker
24*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineArm.h>
25*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsArm.h>
26*eb293b8fSAndroid Build Coastguard Worker
27*eb293b8fSAndroid Build Coastguard Worker #include "ElfInterfaceArm.h"
28*eb293b8fSAndroid Build Coastguard Worker
29*eb293b8fSAndroid Build Coastguard Worker #include "ElfFake.h"
30*eb293b8fSAndroid Build Coastguard Worker #include "utils/MemoryFake.h"
31*eb293b8fSAndroid Build Coastguard Worker
32*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
33*eb293b8fSAndroid Build Coastguard Worker
34*eb293b8fSAndroid Build Coastguard Worker class ElfInterfaceArmTest : public ::testing::Test {
35*eb293b8fSAndroid Build Coastguard Worker protected:
SetUp()36*eb293b8fSAndroid Build Coastguard Worker void SetUp() override {
37*eb293b8fSAndroid Build Coastguard Worker fake_memory_ = new MemoryFake;
38*eb293b8fSAndroid Build Coastguard Worker memory_.reset(fake_memory_);
39*eb293b8fSAndroid Build Coastguard Worker process_memory_.Clear();
40*eb293b8fSAndroid Build Coastguard Worker }
41*eb293b8fSAndroid Build Coastguard Worker
42*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> memory_;
43*eb293b8fSAndroid Build Coastguard Worker MemoryFake* fake_memory_;
44*eb293b8fSAndroid Build Coastguard Worker MemoryFake process_memory_;
45*eb293b8fSAndroid Build Coastguard Worker };
46*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,GetPrel32Addr)47*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, GetPrel32Addr) {
48*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
49*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x230000);
50*eb293b8fSAndroid Build Coastguard Worker
51*eb293b8fSAndroid Build Coastguard Worker uint32_t value;
52*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.GetPrel31Addr(0x1000, &value));
53*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x231000U, value);
54*eb293b8fSAndroid Build Coastguard Worker
55*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x80001000);
56*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.GetPrel31Addr(0x1000, &value));
57*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x2000U, value);
58*eb293b8fSAndroid Build Coastguard Worker
59*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x70001000);
60*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.GetPrel31Addr(0x1000, &value));
61*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0xf0002000U, value);
62*eb293b8fSAndroid Build Coastguard Worker }
63*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,FindEntry_start_zero)64*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, FindEntry_start_zero) {
65*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
66*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0);
67*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(10);
68*eb293b8fSAndroid Build Coastguard Worker
69*eb293b8fSAndroid Build Coastguard Worker uint64_t entry_offset;
70*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
71*eb293b8fSAndroid Build Coastguard Worker }
72*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,FindEntry_no_entries)73*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, FindEntry_no_entries) {
74*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
75*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x100);
76*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(0);
77*eb293b8fSAndroid Build Coastguard Worker
78*eb293b8fSAndroid Build Coastguard Worker uint64_t entry_offset;
79*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
80*eb293b8fSAndroid Build Coastguard Worker }
81*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,FindEntry_no_valid_memory)82*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, FindEntry_no_valid_memory) {
83*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
84*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x100);
85*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(2);
86*eb293b8fSAndroid Build Coastguard Worker
87*eb293b8fSAndroid Build Coastguard Worker uint64_t entry_offset;
88*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
89*eb293b8fSAndroid Build Coastguard Worker }
90*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,FindEntry_ip_before_first)91*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, FindEntry_ip_before_first) {
92*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
93*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
94*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(1);
95*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x6000);
96*eb293b8fSAndroid Build Coastguard Worker
97*eb293b8fSAndroid Build Coastguard Worker uint64_t entry_offset;
98*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
99*eb293b8fSAndroid Build Coastguard Worker }
100*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,FindEntry_single_entry_negative_value)101*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, FindEntry_single_entry_negative_value) {
102*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
103*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x8000);
104*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(1);
105*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x8000, 0x7fffff00);
106*eb293b8fSAndroid Build Coastguard Worker
107*eb293b8fSAndroid Build Coastguard Worker uint64_t entry_offset;
108*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.FindEntry(0x7ff0, &entry_offset));
109*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x8000U, entry_offset);
110*eb293b8fSAndroid Build Coastguard Worker }
111*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,FindEntry_two_entries)112*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, FindEntry_two_entries) {
113*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
114*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
115*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(2);
116*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x6000);
117*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x7000);
118*eb293b8fSAndroid Build Coastguard Worker
119*eb293b8fSAndroid Build Coastguard Worker uint64_t entry_offset;
120*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.FindEntry(0x7000, &entry_offset));
121*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000U, entry_offset);
122*eb293b8fSAndroid Build Coastguard Worker }
123*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,FindEntry_last_check_single_entry)124*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, FindEntry_last_check_single_entry) {
125*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
126*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
127*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(1);
128*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x6000);
129*eb293b8fSAndroid Build Coastguard Worker
130*eb293b8fSAndroid Build Coastguard Worker uint64_t entry_offset;
131*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.FindEntry(0x7000, &entry_offset));
132*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000U, entry_offset);
133*eb293b8fSAndroid Build Coastguard Worker
134*eb293b8fSAndroid Build Coastguard Worker // To guarantee that we are using the cache on the second run,
135*eb293b8fSAndroid Build Coastguard Worker // set the memory to a different value.
136*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x8000);
137*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.FindEntry(0x7004, &entry_offset));
138*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000U, entry_offset);
139*eb293b8fSAndroid Build Coastguard Worker }
140*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,FindEntry_last_check_multiple_entries)141*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, FindEntry_last_check_multiple_entries) {
142*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
143*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
144*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(2);
145*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x6000);
146*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x8000);
147*eb293b8fSAndroid Build Coastguard Worker
148*eb293b8fSAndroid Build Coastguard Worker uint64_t entry_offset;
149*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.FindEntry(0x9008, &entry_offset));
150*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1008U, entry_offset);
151*eb293b8fSAndroid Build Coastguard Worker
152*eb293b8fSAndroid Build Coastguard Worker // To guarantee that we are using the cache on the second run,
153*eb293b8fSAndroid Build Coastguard Worker // set the memory to a different value.
154*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x16000);
155*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x18000);
156*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.FindEntry(0x9100, &entry_offset));
157*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1008U, entry_offset);
158*eb293b8fSAndroid Build Coastguard Worker }
159*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,FindEntry_multiple_entries_even)160*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, FindEntry_multiple_entries_even) {
161*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
162*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
163*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(4);
164*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x6000);
165*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x7000);
166*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1010, 0x8000);
167*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1018, 0x9000);
168*eb293b8fSAndroid Build Coastguard Worker
169*eb293b8fSAndroid Build Coastguard Worker uint64_t entry_offset;
170*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.FindEntry(0x9100, &entry_offset));
171*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1010U, entry_offset);
172*eb293b8fSAndroid Build Coastguard Worker
173*eb293b8fSAndroid Build Coastguard Worker // To guarantee that we are using the cache on the second run,
174*eb293b8fSAndroid Build Coastguard Worker // set the memory to a different value.
175*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x16000);
176*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x17000);
177*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1010, 0x18000);
178*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1018, 0x19000);
179*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.FindEntry(0x9100, &entry_offset));
180*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1010U, entry_offset);
181*eb293b8fSAndroid Build Coastguard Worker }
182*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,FindEntry_multiple_entries_odd)183*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, FindEntry_multiple_entries_odd) {
184*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
185*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
186*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(5);
187*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x5000);
188*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x6000);
189*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1010, 0x7000);
190*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1018, 0x8000);
191*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1020, 0x9000);
192*eb293b8fSAndroid Build Coastguard Worker
193*eb293b8fSAndroid Build Coastguard Worker uint64_t entry_offset;
194*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.FindEntry(0x8100, &entry_offset));
195*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1010U, entry_offset);
196*eb293b8fSAndroid Build Coastguard Worker
197*eb293b8fSAndroid Build Coastguard Worker // To guarantee that we are using the cache on the second run,
198*eb293b8fSAndroid Build Coastguard Worker // set the memory to a different value.
199*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x15000);
200*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x16000);
201*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1010, 0x17000);
202*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1018, 0x18000);
203*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1020, 0x19000);
204*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.FindEntry(0x8100, &entry_offset));
205*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1010U, entry_offset);
206*eb293b8fSAndroid Build Coastguard Worker }
207*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,iterate)208*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, iterate) {
209*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
210*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
211*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(5);
212*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x5000);
213*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x6000);
214*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1010, 0x7000);
215*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1018, 0x8000);
216*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1020, 0x9000);
217*eb293b8fSAndroid Build Coastguard Worker
218*eb293b8fSAndroid Build Coastguard Worker std::vector<uint32_t> entries;
219*eb293b8fSAndroid Build Coastguard Worker for (auto addr : interface) {
220*eb293b8fSAndroid Build Coastguard Worker entries.push_back(addr);
221*eb293b8fSAndroid Build Coastguard Worker }
222*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(5U, entries.size());
223*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x6000U, entries[0]);
224*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x7008U, entries[1]);
225*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x8010U, entries[2]);
226*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x9018U, entries[3]);
227*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0xa020U, entries[4]);
228*eb293b8fSAndroid Build Coastguard Worker
229*eb293b8fSAndroid Build Coastguard Worker // Make sure the iterate cached the entries.
230*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x11000);
231*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x12000);
232*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1010, 0x13000);
233*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1018, 0x14000);
234*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1020, 0x15000);
235*eb293b8fSAndroid Build Coastguard Worker
236*eb293b8fSAndroid Build Coastguard Worker entries.clear();
237*eb293b8fSAndroid Build Coastguard Worker for (auto addr : interface) {
238*eb293b8fSAndroid Build Coastguard Worker entries.push_back(addr);
239*eb293b8fSAndroid Build Coastguard Worker }
240*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(5U, entries.size());
241*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x6000U, entries[0]);
242*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x7008U, entries[1]);
243*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x8010U, entries[2]);
244*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x9018U, entries[3]);
245*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0xa020U, entries[4]);
246*eb293b8fSAndroid Build Coastguard Worker }
247*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,HandleUnknownType_arm_exidx)248*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, HandleUnknownType_arm_exidx) {
249*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
250*eb293b8fSAndroid Build Coastguard Worker
251*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
252*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(100);
253*eb293b8fSAndroid Build Coastguard Worker
254*eb293b8fSAndroid Build Coastguard Worker // Verify that if the type is not the one we want, we don't set the values.
255*eb293b8fSAndroid Build Coastguard Worker interface.HandleUnknownType(0x70000000, 0x2000, 320);
256*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000U, interface.start_offset());
257*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(100U, interface.total_entries());
258*eb293b8fSAndroid Build Coastguard Worker
259*eb293b8fSAndroid Build Coastguard Worker // Everything is correct and present.
260*eb293b8fSAndroid Build Coastguard Worker interface.HandleUnknownType(0x70000001, 0x2000, 320);
261*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x2000U, interface.start_offset());
262*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(40U, interface.total_entries());
263*eb293b8fSAndroid Build Coastguard Worker }
264*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,StepExidx)265*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, StepExidx) {
266*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
267*eb293b8fSAndroid Build Coastguard Worker
268*eb293b8fSAndroid Build Coastguard Worker // FindEntry fails.
269*eb293b8fSAndroid Build Coastguard Worker bool finished;
270*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(interface.StepExidx(0x7000, nullptr, nullptr, &finished));
271*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
272*eb293b8fSAndroid Build Coastguard Worker
273*eb293b8fSAndroid Build Coastguard Worker // ExtractEntry should fail.
274*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
275*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(2);
276*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x6000);
277*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x8000);
278*eb293b8fSAndroid Build Coastguard Worker
279*eb293b8fSAndroid Build Coastguard Worker RegsArm regs;
280*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_SP] = 0x1000;
281*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_LR] = 0x20000;
282*eb293b8fSAndroid Build Coastguard Worker regs.set_sp(regs[ARM_REG_SP]);
283*eb293b8fSAndroid Build Coastguard Worker regs.set_pc(0x1234);
284*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
285*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_MEMORY_INVALID, interface.LastErrorCode());
286*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x1004U, interface.LastErrorAddress());
287*eb293b8fSAndroid Build Coastguard Worker
288*eb293b8fSAndroid Build Coastguard Worker // Eval should fail.
289*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1004, 0x81000000);
290*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
291*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
292*eb293b8fSAndroid Build Coastguard Worker
293*eb293b8fSAndroid Build Coastguard Worker // Everything should pass.
294*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1004, 0x80b0b0b0);
295*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
296*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
297*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(finished);
298*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000U, regs.sp());
299*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000U, regs[ARM_REG_SP]);
300*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x20000U, regs.pc());
301*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x20000U, regs[ARM_REG_PC]);
302*eb293b8fSAndroid Build Coastguard Worker
303*eb293b8fSAndroid Build Coastguard Worker // Load bias is non-zero.
304*eb293b8fSAndroid Build Coastguard Worker interface.set_load_bias(0x1000);
305*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.StepExidx(0x8000, ®s, &process_memory_, &finished));
306*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
307*eb293b8fSAndroid Build Coastguard Worker
308*eb293b8fSAndroid Build Coastguard Worker // Pc too small.
309*eb293b8fSAndroid Build Coastguard Worker interface.set_load_bias(0x9000);
310*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(interface.StepExidx(0x8000, ®s, &process_memory_, &finished));
311*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
312*eb293b8fSAndroid Build Coastguard Worker }
313*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,StepExidx_pc_set)314*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) {
315*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
316*eb293b8fSAndroid Build Coastguard Worker
317*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
318*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(2);
319*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x6000);
320*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1004, 0x808800b0);
321*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1008, 0x8000);
322*eb293b8fSAndroid Build Coastguard Worker process_memory_.SetData32(0x10000, 0x10);
323*eb293b8fSAndroid Build Coastguard Worker
324*eb293b8fSAndroid Build Coastguard Worker RegsArm regs;
325*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_SP] = 0x10000;
326*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_LR] = 0x20000;
327*eb293b8fSAndroid Build Coastguard Worker regs.set_sp(regs[ARM_REG_SP]);
328*eb293b8fSAndroid Build Coastguard Worker regs.set_pc(0x1234);
329*eb293b8fSAndroid Build Coastguard Worker
330*eb293b8fSAndroid Build Coastguard Worker // Everything should pass.
331*eb293b8fSAndroid Build Coastguard Worker bool finished;
332*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
333*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
334*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(finished);
335*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x10004U, regs.sp());
336*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x10004U, regs[ARM_REG_SP]);
337*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x10U, regs.pc());
338*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x10U, regs[ARM_REG_PC]);
339*eb293b8fSAndroid Build Coastguard Worker }
340*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,StepExidx_cant_unwind)341*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, StepExidx_cant_unwind) {
342*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
343*eb293b8fSAndroid Build Coastguard Worker
344*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
345*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(1);
346*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x6000);
347*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1004, 1);
348*eb293b8fSAndroid Build Coastguard Worker
349*eb293b8fSAndroid Build Coastguard Worker RegsArm regs;
350*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_SP] = 0x10000;
351*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_LR] = 0x20000;
352*eb293b8fSAndroid Build Coastguard Worker regs.set_sp(regs[ARM_REG_SP]);
353*eb293b8fSAndroid Build Coastguard Worker regs.set_pc(0x1234);
354*eb293b8fSAndroid Build Coastguard Worker
355*eb293b8fSAndroid Build Coastguard Worker bool finished;
356*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
357*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
358*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(finished);
359*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x10000U, regs.sp());
360*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x10000U, regs[ARM_REG_SP]);
361*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1234U, regs.pc());
362*eb293b8fSAndroid Build Coastguard Worker }
363*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,StepExidx_refuse_unwind)364*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, StepExidx_refuse_unwind) {
365*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
366*eb293b8fSAndroid Build Coastguard Worker
367*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
368*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(1);
369*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x6000);
370*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1004, 0x808000b0);
371*eb293b8fSAndroid Build Coastguard Worker
372*eb293b8fSAndroid Build Coastguard Worker RegsArm regs;
373*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_SP] = 0x10000;
374*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_LR] = 0x20000;
375*eb293b8fSAndroid Build Coastguard Worker regs.set_sp(regs[ARM_REG_SP]);
376*eb293b8fSAndroid Build Coastguard Worker regs.set_pc(0x1234);
377*eb293b8fSAndroid Build Coastguard Worker
378*eb293b8fSAndroid Build Coastguard Worker bool finished;
379*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
380*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
381*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(finished);
382*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x10000U, regs.sp());
383*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x10000U, regs[ARM_REG_SP]);
384*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1234U, regs.pc());
385*eb293b8fSAndroid Build Coastguard Worker }
386*eb293b8fSAndroid Build Coastguard Worker
TEST_F(ElfInterfaceArmTest,StepExidx_pc_zero)387*eb293b8fSAndroid Build Coastguard Worker TEST_F(ElfInterfaceArmTest, StepExidx_pc_zero) {
388*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceArmFake interface(memory_);
389*eb293b8fSAndroid Build Coastguard Worker
390*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetStartOffset(0x1000);
391*eb293b8fSAndroid Build Coastguard Worker interface.FakeSetTotalEntries(1);
392*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1000, 0x6000);
393*eb293b8fSAndroid Build Coastguard Worker // Set the pc using a pop r15 command.
394*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1004, 0x808800b0);
395*eb293b8fSAndroid Build Coastguard Worker
396*eb293b8fSAndroid Build Coastguard Worker // pc value of zero.
397*eb293b8fSAndroid Build Coastguard Worker process_memory_.SetData32(0x10000, 0);
398*eb293b8fSAndroid Build Coastguard Worker
399*eb293b8fSAndroid Build Coastguard Worker RegsArm regs;
400*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_SP] = 0x10000;
401*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_LR] = 0x20000;
402*eb293b8fSAndroid Build Coastguard Worker regs.set_sp(regs[ARM_REG_SP]);
403*eb293b8fSAndroid Build Coastguard Worker regs.set_pc(0x1234);
404*eb293b8fSAndroid Build Coastguard Worker
405*eb293b8fSAndroid Build Coastguard Worker bool finished;
406*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
407*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
408*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(finished);
409*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0U, regs.pc());
410*eb293b8fSAndroid Build Coastguard Worker
411*eb293b8fSAndroid Build Coastguard Worker // Now set the pc from the lr register (pop r14).
412*eb293b8fSAndroid Build Coastguard Worker fake_memory_->SetData32(0x1004, 0x808400b0);
413*eb293b8fSAndroid Build Coastguard Worker
414*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_SP] = 0x10000;
415*eb293b8fSAndroid Build Coastguard Worker regs[ARM_REG_LR] = 0x20000;
416*eb293b8fSAndroid Build Coastguard Worker regs.set_sp(regs[ARM_REG_SP]);
417*eb293b8fSAndroid Build Coastguard Worker regs.set_pc(0x1234);
418*eb293b8fSAndroid Build Coastguard Worker
419*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
420*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
421*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(finished);
422*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0U, regs.pc());
423*eb293b8fSAndroid Build Coastguard Worker }
424*eb293b8fSAndroid Build Coastguard Worker
425*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack
426