blob: b386ef49518d681da0fa1a976d584a6a26b1d523 [file] [log] [blame]
Christopher Ferris53a3c9b2017-05-10 18:34:15 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdint.h>
18
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070019#include <gtest/gtest.h>
20
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080021#include <unwindstack/DwarfError.h>
Christopher Ferrisd226a512017-07-14 10:37:19 -070022#include <unwindstack/DwarfSection.h>
23
24#include "DwarfEncoding.h"
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070025
26#include "LogFake.h"
27#include "MemoryFake.h"
28#include "RegsFake.h"
29
Christopher Ferrisd226a512017-07-14 10:37:19 -070030namespace unwindstack {
31
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070032template <typename TypeParam>
Christopher Ferris92acaac2018-06-21 10:44:02 -070033class TestDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070034 public:
Christopher Ferris92acaac2018-06-21 10:44:02 -070035 TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
36 virtual ~TestDwarfSectionImpl() = default;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070037
Christopher Ferris92acaac2018-06-21 10:44:02 -070038 bool Init(uint64_t, uint64_t, uint64_t) override { return false; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070039
Christopher Ferris92acaac2018-06-21 10:44:02 -070040 void GetFdes(std::vector<const DwarfFde*>*) override {}
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070041
Christopher Ferris92acaac2018-06-21 10:44:02 -070042 const DwarfFde* GetFdeFromPc(uint64_t) override { return nullptr; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070043
Christopher Ferris92acaac2018-06-21 10:44:02 -070044 uint64_t GetCieOffsetFromFde32(uint32_t) { return 0; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070045
Christopher Ferris92acaac2018-06-21 10:44:02 -070046 uint64_t GetCieOffsetFromFde64(uint64_t) { return 0; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070047
Christopher Ferris92acaac2018-06-21 10:44:02 -070048 uint64_t AdjustPcFromFde(uint64_t) override { return 0; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070049
50 void TestSetCachedCieLocRegs(uint64_t offset, const dwarf_loc_regs_t& loc_regs) {
51 this->cie_loc_regs_[offset] = loc_regs;
52 }
53 void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); }
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080054 void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070055};
56
57template <typename TypeParam>
58class DwarfSectionImplTest : public ::testing::Test {
59 protected:
60 void SetUp() override {
61 memory_.Clear();
Christopher Ferris92acaac2018-06-21 10:44:02 -070062 section_ = new TestDwarfSectionImpl<TypeParam>(&memory_);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070063 ResetLogs();
64 }
65
66 void TearDown() override { delete section_; }
67
68 MemoryFake memory_;
Christopher Ferris92acaac2018-06-21 10:44:02 -070069 TestDwarfSectionImpl<TypeParam>* section_ = nullptr;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070070};
Christopher Ferris7e21eba2019-06-20 16:16:42 -070071TYPED_TEST_SUITE_P(DwarfSectionImplTest);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070072
73// NOTE: All test class variables need to be referenced as this->.
74
Christopher Ferris92acaac2018-06-21 10:44:02 -070075TYPED_TEST_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache) {
76 ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
77 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
78 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
79
80 this->section_->TestClearError();
81 ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
82 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
83 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
84}
85
86TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
87 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
88 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
89 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
90
91 this->section_->TestClearError();
92 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
93 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
94 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
95}
96
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070097TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
98 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -070099 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700100 dwarf_loc_regs_t loc_regs;
101
102 regs.set_pc(0x100);
103 regs.set_sp(0x2000);
104 regs[5] = 0x20;
105 regs[9] = 0x3000;
David Srbecky3692f252018-03-08 16:57:19 +0000106 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700107 bool finished;
108 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800109 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
110 EXPECT_EQ(0x5000U, this->section_->LastErrorAddress());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700111}
112
113TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
114 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700115 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700116 dwarf_loc_regs_t loc_regs;
117
118 regs.set_pc(0x100);
119 regs.set_sp(0x2000);
120 regs[5] = 0x20;
121 regs[9] = 0x3000;
122 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
David Srbecky3692f252018-03-08 16:57:19 +0000123 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700124 bool finished;
125 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800126 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700127}
128
129TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
130 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700131 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700132 dwarf_loc_regs_t loc_regs;
133
134 regs.set_pc(0x100);
135 regs.set_sp(0x2000);
136 regs[5] = 0x20;
137 regs[9] = 0x3000;
138 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
139 TypeParam cfa_value = 0x12345;
140 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
Christopher Ferris559c7f22018-02-12 20:18:03 -0800141 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700142 bool finished;
David Srbecky3692f252018-03-08 16:57:19 +0000143 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
144 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700145}
146
147TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
148 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700149 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700150 dwarf_loc_regs_t loc_regs;
151
152 regs.set_pc(0x100);
153 regs.set_sp(0x2000);
154 regs[5] = 0x20;
155 regs[9] = 0x3000;
156 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
Christopher Ferris559c7f22018-02-12 20:18:03 -0800157 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700158 bool finished;
159 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
160 ASSERT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700161 EXPECT_EQ(0x80000000U, regs.sp());
162 EXPECT_EQ(0x20U, regs.pc());
163}
164
165TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
166 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700167 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700168 dwarf_loc_regs_t loc_regs;
169
170 regs.set_pc(0x100);
171 regs.set_sp(0x2000);
172 regs[5] = 0x20;
173 regs[9] = 0x3000;
174 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
David Srbecky3692f252018-03-08 16:57:19 +0000175 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700176 bool finished;
177 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800178 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700179}
180
181TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
182 DwarfCie cie{.return_address_register = 60};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700183 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700184 dwarf_loc_regs_t loc_regs;
185
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700186 bool finished;
187 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800188 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700189}
190
191TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
192 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700193 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700194 dwarf_loc_regs_t loc_regs;
195
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700196 bool finished;
197 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800198 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700199}
200
201TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
202 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700203 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700204 dwarf_loc_regs_t loc_regs;
205
206 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700207 bool finished;
208 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800209 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700210
211 this->section_->TestClearError();
212 loc_regs.erase(CFA_REG);
213 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700214 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800215 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700216
217 this->section_->TestClearError();
218 loc_regs.erase(CFA_REG);
219 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700220 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800221 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700222
223 this->section_->TestClearError();
224 loc_regs.erase(CFA_REG);
225 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700226 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800227 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700228}
229
230TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
231 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700232 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700233 dwarf_loc_regs_t loc_regs;
234
235 regs.set_pc(0x100);
236 regs.set_sp(0x2000);
237 regs[5] = 0x20;
238 regs[9] = 0x3000;
239 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700240 bool finished;
241 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
242 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700243 EXPECT_EQ(0x20U, regs.pc());
Yabin Cui11e96fe2018-03-14 18:16:22 -0700244 EXPECT_EQ(0x3000U, regs.sp());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700245}
246
247TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
248 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700249 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700250 dwarf_loc_regs_t loc_regs;
251
252 regs.set_pc(0x100);
253 regs.set_sp(0x2000);
254 regs[5] = 0x20;
255 regs[6] = 0x4000;
256 regs[9] = 0x3000;
257 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700258 bool finished;
259 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
260 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700261 EXPECT_EQ(0x20U, regs.pc());
262 EXPECT_EQ(0x4000U, regs.sp());
263}
264
265TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
266 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700267 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700268 dwarf_loc_regs_t loc_regs;
269
270 regs.set_pc(0x100);
271 regs.set_sp(0x2000);
Christopher Ferris98984b42018-01-17 12:59:45 -0800272 regs[1] = 0x100;
273 regs[3] = 0x300;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700274 regs[8] = 0x10;
275 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris98984b42018-01-17 12:59:45 -0800276 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 1}};
277 loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700278 bool finished;
Christopher Ferris98984b42018-01-17 12:59:45 -0800279 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
280 EXPECT_EQ(0x301U, regs[1]);
281 EXPECT_EQ(0x300U, regs[3]);
282 EXPECT_EQ(0x10U, regs[8]);
283 EXPECT_EQ(0x102U, regs[9]);
284}
285
286TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
287 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700288 RegsImplFake<TypeParam> regs(10);
Christopher Ferris98984b42018-01-17 12:59:45 -0800289 dwarf_loc_regs_t loc_regs;
290
291 regs.set_pc(0x100);
292 regs.set_sp(0x2000);
293 regs[0] = 0x10;
294 regs[1] = 0x20;
295 regs[2] = 0x30;
296 regs[3] = 0x40;
297 regs[4] = 0x50;
298 regs[5] = 0x60;
299 regs[8] = 0x20;
300 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
301 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}};
302 loc_regs[2] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
303 loc_regs[3] = DwarfLocation{DWARF_LOCATION_REGISTER, {2, 3}};
304 loc_regs[4] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 4}};
305 loc_regs[5] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 5}};
306 bool finished;
307 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
308 EXPECT_EQ(0x10U, regs[0]);
309 EXPECT_EQ(0x11U, regs[1]);
310 EXPECT_EQ(0x22U, regs[2]);
311 EXPECT_EQ(0x33U, regs[3]);
312 EXPECT_EQ(0x44U, regs[4]);
313 EXPECT_EQ(0x55U, regs[5]);
314 EXPECT_EQ(0x20U, regs[8]);
315}
316
317TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
318 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700319 RegsImplFake<TypeParam> regs(10);
Christopher Ferris98984b42018-01-17 12:59:45 -0800320 dwarf_loc_regs_t loc_regs;
321
322 regs.set_pc(0x100);
323 regs.set_sp(0x2000);
324 regs[0] = 0x10;
325 regs[8] = 0x20;
326 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris559c7f22018-02-12 20:18:03 -0800327 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x8, 0x5008}};
328 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13, 0x08, 0x11});
Christopher Ferris98984b42018-01-17 12:59:45 -0800329 bool finished;
330 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
331 EXPECT_EQ(0x10U, regs[0]);
332 EXPECT_EQ(0x20U, regs[8]);
333 EXPECT_EQ(0x11U, regs.dex_pc());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700334}
335
336TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
337 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700338 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700339 dwarf_loc_regs_t loc_regs;
340
341 regs.set_pc(0x100);
342 regs.set_sp(0x2000);
343 regs[8] = 0x10;
344 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
345 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700346 bool finished;
347 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800348 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700349}
350
351TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
352 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700353 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700354 dwarf_loc_regs_t loc_regs;
355
356 if (sizeof(TypeParam) == sizeof(uint64_t)) {
357 this->memory_.SetData64(0x2150, 0x12345678abcdef00ULL);
358 } else {
359 this->memory_.SetData32(0x2150, 0x12345678);
360 }
361
362 regs.set_pc(0x100);
363 regs.set_sp(0x2000);
364 regs[3] = 0x234;
365 regs[5] = 0x10;
366 regs[8] = 0x2100;
367 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
368 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}};
369 loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}};
370 loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700371 bool finished;
372 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
373 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700374 EXPECT_EQ(0x10U, regs.pc());
375 EXPECT_EQ(0x2100U, regs.sp());
376 EXPECT_EQ(0x2200U, regs[1]);
377 EXPECT_EQ(0x234U, regs[3]);
378 if (sizeof(TypeParam) == sizeof(uint64_t)) {
379 EXPECT_EQ(0x12345678abcdef00ULL, regs[2]);
380 } else {
381 EXPECT_EQ(0x12345678U, regs[2]);
382 }
383}
384
385TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
386 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700387 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700388 dwarf_loc_regs_t loc_regs;
389
390 regs.set_pc(0x100);
391 regs.set_sp(0x2000);
392 regs[5] = 0x20;
393 regs[8] = 0x10;
394 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
395 loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700396 bool finished;
397 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
398 EXPECT_TRUE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700399 EXPECT_EQ(0U, regs.pc());
400 EXPECT_EQ(0x10U, regs.sp());
401}
402
Christopher Ferris2502a602017-10-23 13:51:54 -0700403TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
404 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700405 RegsImplFake<TypeParam> regs(10);
Christopher Ferris2502a602017-10-23 13:51:54 -0700406 dwarf_loc_regs_t loc_regs;
407
408 regs.set_pc(0x100);
409 regs.set_sp(0x2000);
410 regs[5] = 0;
411 regs[8] = 0x10;
412 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
413 bool finished;
414 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
415 EXPECT_TRUE(finished);
416 EXPECT_EQ(0U, regs.pc());
417 EXPECT_EQ(0x10U, regs.sp());
418}
419
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700420TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
421 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700422 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700423 dwarf_loc_regs_t loc_regs;
424
425 regs.set_pc(0x100);
426 regs.set_sp(0x2000);
427 regs[5] = 0x20;
428 regs[8] = 0x10;
429 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700430 bool finished;
431 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
432 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700433 EXPECT_EQ(0x20U, regs.pc());
434 EXPECT_EQ(0x10U, regs.sp());
435}
436
437TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
438 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700439 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700440 dwarf_loc_regs_t loc_regs;
441
442 regs.set_pc(0x100);
443 regs.set_sp(0x2000);
444 regs[5] = 0x20;
445 regs[8] = 0x10;
446 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
447 // This should not result in any errors.
448 loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700449 bool finished;
450 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
451 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700452 EXPECT_EQ(0x20U, regs.pc());
453 EXPECT_EQ(0x10U, regs.sp());
454}
455
456TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
457 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700458 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700459 dwarf_loc_regs_t loc_regs;
460
461 regs.set_pc(0x100);
462 regs.set_sp(0x2000);
463 regs[8] = 0x3000;
464 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
465 TypeParam cfa_value = 0x12345;
466 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
467 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris559c7f22018-02-12 20:18:03 -0800468 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700469 bool finished;
470 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
471 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700472 EXPECT_EQ(0x3000U, regs.sp());
473 EXPECT_EQ(0x12345U, regs.pc());
474}
475
476TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
477 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700478 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700479 dwarf_loc_regs_t loc_regs;
480
481 regs.set_pc(0x100);
482 regs.set_sp(0x2000);
483 regs[8] = 0x3000;
484 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
485 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris559c7f22018-02-12 20:18:03 -0800486 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700487 bool finished;
488 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
489 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700490 EXPECT_EQ(0x3000U, regs.sp());
491 EXPECT_EQ(0x80000000U, regs.pc());
492}
493
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700494TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
495 DwarfCie cie{};
496 cie.cfa_instructions_offset = 0x3000;
497 cie.cfa_instructions_end = 0x3002;
498 DwarfFde fde{};
499 fde.cie = &cie;
500 fde.cie_offset = 0x8000;
501 fde.cfa_instructions_offset = 0x6000;
502 fde.cfa_instructions_end = 0x6002;
503
504 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x09, 0x02, 0x01});
505 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
506
507 dwarf_loc_regs_t loc_regs;
508 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
509 ASSERT_EQ(2U, loc_regs.size());
510
511 auto entry = loc_regs.find(2);
512 ASSERT_NE(entry, loc_regs.end());
513 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
514 ASSERT_EQ(1U, entry->second.values[0]);
515
516 entry = loc_regs.find(4);
517 ASSERT_NE(entry, loc_regs.end());
518 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
519 ASSERT_EQ(3U, entry->second.values[0]);
520}
521
522TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) {
523 DwarfCie cie{};
524 cie.cfa_instructions_offset = 0x3000;
525 cie.cfa_instructions_end = 0x3002;
526 DwarfFde fde{};
527 fde.cie = &cie;
528 fde.cie_offset = 0x8000;
529 fde.cfa_instructions_offset = 0x6000;
530 fde.cfa_instructions_end = 0x6002;
531
David Srbecky3386eba2018-03-14 21:30:25 +0000532 dwarf_loc_regs_t cie_loc_regs;
533 cie_loc_regs[6] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 0}};
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700534 this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs);
535 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
536
537 dwarf_loc_regs_t loc_regs;
538 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
539 ASSERT_EQ(2U, loc_regs.size());
540
541 auto entry = loc_regs.find(6);
542 ASSERT_NE(entry, loc_regs.end());
543 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
544 ASSERT_EQ(4U, entry->second.values[0]);
545
546 entry = loc_regs.find(4);
547 ASSERT_NE(entry, loc_regs.end());
548 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
549 ASSERT_EQ(3U, entry->second.values[0]);
550}
551
552TYPED_TEST_P(DwarfSectionImplTest, Log) {
553 DwarfCie cie{};
554 cie.cfa_instructions_offset = 0x5000;
555 cie.cfa_instructions_end = 0x5001;
556 DwarfFde fde{};
557 fde.cie = &cie;
558 fde.cfa_instructions_offset = 0x6000;
559 fde.cfa_instructions_end = 0x6001;
560
561 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00});
562 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2});
Christopher Ferris4cc36d22018-06-06 14:47:31 -0700563 ASSERT_TRUE(this->section_->Log(2, 0x1000, &fde));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700564
565 ASSERT_EQ(
566 "4 unwind DW_CFA_nop\n"
567 "4 unwind Raw Data: 0x00\n"
568 "4 unwind DW_CFA_restore register(2)\n"
569 "4 unwind Raw Data: 0xc2\n",
570 GetFakeLogPrint());
571 ASSERT_EQ("", GetFakeLogBuf());
572}
573
Christopher Ferris7e21eba2019-06-20 16:16:42 -0700574REGISTER_TYPED_TEST_SUITE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache,
575 GetFdeFromOffset_fail_should_not_cache, Eval_cfa_expr_eval_fail,
576 Eval_cfa_expr_no_stack, Eval_cfa_expr_is_register, Eval_cfa_expr,
577 Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, Eval_cfa_bad,
578 Eval_cfa_register_prev, Eval_cfa_register_from_value,
579 Eval_double_indirection, Eval_register_reference_chain, Eval_dex_pc,
580 Eval_invalid_register, Eval_different_reg_locations,
581 Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
582 Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
583 GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700584
585typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
Christopher Ferris7e21eba2019-06-20 16:16:42 -0700586INSTANTIATE_TYPED_TEST_SUITE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes);
Christopher Ferrisd226a512017-07-14 10:37:19 -0700587
588} // namespace unwindstack