blob: a08a8d070198d627c4440353dae3ea0d4f9ceafb [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>
Tamas Petz6835d012020-01-22 14:22:41 +010023#include <unwindstack/Elf.h>
Christopher Ferrisd226a512017-07-14 10:37:19 -070024
25#include "DwarfEncoding.h"
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070026
27#include "LogFake.h"
28#include "MemoryFake.h"
29#include "RegsFake.h"
30
Christopher Ferrisd226a512017-07-14 10:37:19 -070031namespace unwindstack {
32
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070033template <typename TypeParam>
Christopher Ferris92acaac2018-06-21 10:44:02 -070034class TestDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070035 public:
Christopher Ferris92acaac2018-06-21 10:44:02 -070036 TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
37 virtual ~TestDwarfSectionImpl() = default;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070038
Christopher Ferris819f1312019-10-03 13:35:48 -070039 bool Init(uint64_t, uint64_t, int64_t) override { return false; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070040
Christopher Ferris92acaac2018-06-21 10:44:02 -070041 void GetFdes(std::vector<const DwarfFde*>*) override {}
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070042
Christopher Ferris92acaac2018-06-21 10:44:02 -070043 const DwarfFde* GetFdeFromPc(uint64_t) override { return nullptr; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070044
Christopher Ferris92acaac2018-06-21 10:44:02 -070045 uint64_t GetCieOffsetFromFde32(uint32_t) { return 0; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070046
Christopher Ferris92acaac2018-06-21 10:44:02 -070047 uint64_t GetCieOffsetFromFde64(uint64_t) { return 0; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070048
Christopher Ferris92acaac2018-06-21 10:44:02 -070049 uint64_t AdjustPcFromFde(uint64_t) override { return 0; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070050
51 void TestSetCachedCieLocRegs(uint64_t offset, const dwarf_loc_regs_t& loc_regs) {
52 this->cie_loc_regs_[offset] = loc_regs;
53 }
54 void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); }
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080055 void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070056};
57
58template <typename TypeParam>
59class DwarfSectionImplTest : public ::testing::Test {
60 protected:
61 void SetUp() override {
62 memory_.Clear();
Christopher Ferris92acaac2018-06-21 10:44:02 -070063 section_ = new TestDwarfSectionImpl<TypeParam>(&memory_);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070064 ResetLogs();
65 }
66
67 void TearDown() override { delete section_; }
68
69 MemoryFake memory_;
Christopher Ferris92acaac2018-06-21 10:44:02 -070070 TestDwarfSectionImpl<TypeParam>* section_ = nullptr;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070071};
Christopher Ferris7e21eba2019-06-20 16:16:42 -070072TYPED_TEST_SUITE_P(DwarfSectionImplTest);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070073
74// NOTE: All test class variables need to be referenced as this->.
75
Christopher Ferris92acaac2018-06-21 10:44:02 -070076TYPED_TEST_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache) {
77 ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
78 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
79 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
80
81 this->section_->TestClearError();
82 ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
83 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
84 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
85}
86
87TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
88 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
89 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
90 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
91
92 this->section_->TestClearError();
93 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
94 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
95 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
96}
97
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070098TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
99 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700100 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700101 dwarf_loc_regs_t loc_regs;
102
103 regs.set_pc(0x100);
104 regs.set_sp(0x2000);
105 regs[5] = 0x20;
106 regs[9] = 0x3000;
David Srbecky3692f252018-03-08 16:57:19 +0000107 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700108 bool finished;
109 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800110 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
111 EXPECT_EQ(0x5000U, this->section_->LastErrorAddress());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700112}
113
114TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
115 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700116 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700117 dwarf_loc_regs_t loc_regs;
118
119 regs.set_pc(0x100);
120 regs.set_sp(0x2000);
121 regs[5] = 0x20;
122 regs[9] = 0x3000;
123 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
David Srbecky3692f252018-03-08 16:57:19 +0000124 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700125 bool finished;
126 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800127 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700128}
129
130TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
131 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700132 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700133 dwarf_loc_regs_t loc_regs;
134
135 regs.set_pc(0x100);
136 regs.set_sp(0x2000);
137 regs[5] = 0x20;
138 regs[9] = 0x3000;
139 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
140 TypeParam cfa_value = 0x12345;
141 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
Christopher Ferris559c7f22018-02-12 20:18:03 -0800142 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700143 bool finished;
David Srbecky3692f252018-03-08 16:57:19 +0000144 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
145 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700146}
147
148TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
149 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700150 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700151 dwarf_loc_regs_t loc_regs;
152
153 regs.set_pc(0x100);
154 regs.set_sp(0x2000);
155 regs[5] = 0x20;
156 regs[9] = 0x3000;
157 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
Christopher Ferris559c7f22018-02-12 20:18:03 -0800158 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700159 bool finished;
160 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
161 ASSERT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700162 EXPECT_EQ(0x80000000U, regs.sp());
163 EXPECT_EQ(0x20U, regs.pc());
164}
165
166TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
167 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700168 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700169 dwarf_loc_regs_t loc_regs;
170
171 regs.set_pc(0x100);
172 regs.set_sp(0x2000);
173 regs[5] = 0x20;
174 regs[9] = 0x3000;
175 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
David Srbecky3692f252018-03-08 16:57:19 +0000176 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700177 bool finished;
178 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800179 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700180}
181
182TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
183 DwarfCie cie{.return_address_register = 60};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700184 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700185 dwarf_loc_regs_t loc_regs;
186
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700187 bool finished;
188 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800189 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700190}
191
192TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
193 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700194 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700195 dwarf_loc_regs_t loc_regs;
196
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700197 bool finished;
198 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800199 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700200}
201
202TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
203 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700204 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700205 dwarf_loc_regs_t loc_regs;
206
207 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700208 bool finished;
209 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800210 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700211
212 this->section_->TestClearError();
213 loc_regs.erase(CFA_REG);
214 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700215 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800216 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700217
218 this->section_->TestClearError();
219 loc_regs.erase(CFA_REG);
220 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700221 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800222 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700223
224 this->section_->TestClearError();
225 loc_regs.erase(CFA_REG);
226 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700227 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800228 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700229}
230
231TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
232 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700233 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700234 dwarf_loc_regs_t loc_regs;
235
236 regs.set_pc(0x100);
237 regs.set_sp(0x2000);
238 regs[5] = 0x20;
239 regs[9] = 0x3000;
240 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700241 bool finished;
242 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
243 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700244 EXPECT_EQ(0x20U, regs.pc());
Yabin Cui11e96fe2018-03-14 18:16:22 -0700245 EXPECT_EQ(0x3000U, regs.sp());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700246}
247
248TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
249 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700250 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700251 dwarf_loc_regs_t loc_regs;
252
253 regs.set_pc(0x100);
254 regs.set_sp(0x2000);
255 regs[5] = 0x20;
256 regs[6] = 0x4000;
257 regs[9] = 0x3000;
258 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700259 bool finished;
260 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
261 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700262 EXPECT_EQ(0x20U, regs.pc());
263 EXPECT_EQ(0x4000U, regs.sp());
264}
265
266TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
267 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700268 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700269 dwarf_loc_regs_t loc_regs;
270
271 regs.set_pc(0x100);
272 regs.set_sp(0x2000);
Christopher Ferris98984b42018-01-17 12:59:45 -0800273 regs[1] = 0x100;
274 regs[3] = 0x300;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700275 regs[8] = 0x10;
276 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris98984b42018-01-17 12:59:45 -0800277 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 1}};
278 loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700279 bool finished;
Christopher Ferris98984b42018-01-17 12:59:45 -0800280 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
281 EXPECT_EQ(0x301U, regs[1]);
282 EXPECT_EQ(0x300U, regs[3]);
283 EXPECT_EQ(0x10U, regs[8]);
284 EXPECT_EQ(0x102U, regs[9]);
285}
286
287TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
288 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700289 RegsImplFake<TypeParam> regs(10);
Christopher Ferris98984b42018-01-17 12:59:45 -0800290 dwarf_loc_regs_t loc_regs;
291
292 regs.set_pc(0x100);
293 regs.set_sp(0x2000);
294 regs[0] = 0x10;
295 regs[1] = 0x20;
296 regs[2] = 0x30;
297 regs[3] = 0x40;
298 regs[4] = 0x50;
299 regs[5] = 0x60;
300 regs[8] = 0x20;
301 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
302 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}};
303 loc_regs[2] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
304 loc_regs[3] = DwarfLocation{DWARF_LOCATION_REGISTER, {2, 3}};
305 loc_regs[4] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 4}};
306 loc_regs[5] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 5}};
307 bool finished;
308 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
309 EXPECT_EQ(0x10U, regs[0]);
310 EXPECT_EQ(0x11U, regs[1]);
311 EXPECT_EQ(0x22U, regs[2]);
312 EXPECT_EQ(0x33U, regs[3]);
313 EXPECT_EQ(0x44U, regs[4]);
314 EXPECT_EQ(0x55U, regs[5]);
315 EXPECT_EQ(0x20U, regs[8]);
316}
317
318TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
319 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700320 RegsImplFake<TypeParam> regs(10);
Christopher Ferris98984b42018-01-17 12:59:45 -0800321 dwarf_loc_regs_t loc_regs;
322
323 regs.set_pc(0x100);
324 regs.set_sp(0x2000);
325 regs[0] = 0x10;
326 regs[8] = 0x20;
327 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris559c7f22018-02-12 20:18:03 -0800328 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x8, 0x5008}};
329 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13, 0x08, 0x11});
Christopher Ferris98984b42018-01-17 12:59:45 -0800330 bool finished;
331 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
332 EXPECT_EQ(0x10U, regs[0]);
333 EXPECT_EQ(0x20U, regs[8]);
334 EXPECT_EQ(0x11U, regs.dex_pc());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700335}
336
337TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
338 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700339 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700340 dwarf_loc_regs_t loc_regs;
341
342 regs.set_pc(0x100);
343 regs.set_sp(0x2000);
344 regs[8] = 0x10;
345 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
346 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700347 bool finished;
348 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800349 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700350}
351
352TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
353 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700354 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700355 dwarf_loc_regs_t loc_regs;
356
357 if (sizeof(TypeParam) == sizeof(uint64_t)) {
358 this->memory_.SetData64(0x2150, 0x12345678abcdef00ULL);
359 } else {
360 this->memory_.SetData32(0x2150, 0x12345678);
361 }
362
363 regs.set_pc(0x100);
364 regs.set_sp(0x2000);
365 regs[3] = 0x234;
366 regs[5] = 0x10;
367 regs[8] = 0x2100;
368 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
369 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}};
370 loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}};
371 loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700372 bool finished;
373 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
374 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700375 EXPECT_EQ(0x10U, regs.pc());
376 EXPECT_EQ(0x2100U, regs.sp());
377 EXPECT_EQ(0x2200U, regs[1]);
378 EXPECT_EQ(0x234U, regs[3]);
379 if (sizeof(TypeParam) == sizeof(uint64_t)) {
380 EXPECT_EQ(0x12345678abcdef00ULL, regs[2]);
381 } else {
382 EXPECT_EQ(0x12345678U, regs[2]);
383 }
384}
385
386TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
387 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700388 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700389 dwarf_loc_regs_t loc_regs;
390
391 regs.set_pc(0x100);
392 regs.set_sp(0x2000);
393 regs[5] = 0x20;
394 regs[8] = 0x10;
395 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
396 loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700397 bool finished;
398 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
399 EXPECT_TRUE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700400 EXPECT_EQ(0U, regs.pc());
401 EXPECT_EQ(0x10U, regs.sp());
402}
403
Christopher Ferris2502a602017-10-23 13:51:54 -0700404TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
405 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700406 RegsImplFake<TypeParam> regs(10);
Christopher Ferris2502a602017-10-23 13:51:54 -0700407 dwarf_loc_regs_t loc_regs;
408
409 regs.set_pc(0x100);
410 regs.set_sp(0x2000);
411 regs[5] = 0;
412 regs[8] = 0x10;
413 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
414 bool finished;
415 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
416 EXPECT_TRUE(finished);
417 EXPECT_EQ(0U, regs.pc());
418 EXPECT_EQ(0x10U, regs.sp());
419}
420
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700421TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
422 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700423 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700424 dwarf_loc_regs_t loc_regs;
425
426 regs.set_pc(0x100);
427 regs.set_sp(0x2000);
428 regs[5] = 0x20;
429 regs[8] = 0x10;
430 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700431 bool finished;
432 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
433 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700434 EXPECT_EQ(0x20U, regs.pc());
435 EXPECT_EQ(0x10U, regs.sp());
436}
437
438TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
439 DwarfCie cie{.return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700440 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700441 dwarf_loc_regs_t loc_regs;
442
443 regs.set_pc(0x100);
444 regs.set_sp(0x2000);
445 regs[5] = 0x20;
446 regs[8] = 0x10;
447 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
448 // This should not result in any errors.
449 loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700450 bool finished;
451 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
452 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700453 EXPECT_EQ(0x20U, regs.pc());
454 EXPECT_EQ(0x10U, regs.sp());
455}
456
457TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
458 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700459 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700460 dwarf_loc_regs_t loc_regs;
461
462 regs.set_pc(0x100);
463 regs.set_sp(0x2000);
464 regs[8] = 0x3000;
465 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
466 TypeParam cfa_value = 0x12345;
467 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
468 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris559c7f22018-02-12 20:18:03 -0800469 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700470 bool finished;
471 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
472 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700473 EXPECT_EQ(0x3000U, regs.sp());
474 EXPECT_EQ(0x12345U, regs.pc());
475}
476
477TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
478 DwarfCie cie{.version = 3, .return_address_register = 5};
Yabin Cui11e96fe2018-03-14 18:16:22 -0700479 RegsImplFake<TypeParam> regs(10);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700480 dwarf_loc_regs_t loc_regs;
481
482 regs.set_pc(0x100);
483 regs.set_sp(0x2000);
484 regs[8] = 0x3000;
485 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
486 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris559c7f22018-02-12 20:18:03 -0800487 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700488 bool finished;
489 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
490 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700491 EXPECT_EQ(0x3000U, regs.sp());
492 EXPECT_EQ(0x80000000U, regs.pc());
493}
494
Tamas Zsoldosf30a46f2020-08-18 12:04:56 +0200495TYPED_TEST_P(DwarfSectionImplTest, Eval_pseudo_register_invalid) {
496 DwarfCie cie{.return_address_register = 5};
497 RegsImplFake<TypeParam> regs(10);
498 regs.set_pseudo_reg(11);
499 dwarf_loc_regs_t loc_regs;
500
501 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
502 loc_regs[1] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
503 bool finished;
504 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
505 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
506
507 loc_regs.clear();
508 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
509 loc_regs[12] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
510 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
511 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
512}
513
514TYPED_TEST_P(DwarfSectionImplTest, Eval_pseudo_register) {
515 DwarfCie cie{.return_address_register = 5};
516 RegsImplFake<TypeParam> regs(10);
517 regs.set_pseudo_reg(11);
518 dwarf_loc_regs_t loc_regs;
519
520 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
521 loc_regs[11] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
522 bool finished;
523 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
524 uint64_t pseudo_value = 0;
525 ASSERT_TRUE(regs.GetPseudoRegister(11, &pseudo_value));
526 EXPECT_EQ(20U, pseudo_value);
527}
528
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700529TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
530 DwarfCie cie{};
531 cie.cfa_instructions_offset = 0x3000;
532 cie.cfa_instructions_end = 0x3002;
533 DwarfFde fde{};
534 fde.cie = &cie;
535 fde.cie_offset = 0x8000;
536 fde.cfa_instructions_offset = 0x6000;
537 fde.cfa_instructions_end = 0x6002;
538
539 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x09, 0x02, 0x01});
540 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
541
542 dwarf_loc_regs_t loc_regs;
Tamas Petz6835d012020-01-22 14:22:41 +0100543 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs, ARCH_UNKNOWN));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700544 ASSERT_EQ(2U, loc_regs.size());
545
546 auto entry = loc_regs.find(2);
547 ASSERT_NE(entry, loc_regs.end());
548 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
549 ASSERT_EQ(1U, entry->second.values[0]);
550
551 entry = loc_regs.find(4);
552 ASSERT_NE(entry, loc_regs.end());
553 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
554 ASSERT_EQ(3U, entry->second.values[0]);
555}
556
557TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) {
558 DwarfCie cie{};
559 cie.cfa_instructions_offset = 0x3000;
560 cie.cfa_instructions_end = 0x3002;
561 DwarfFde fde{};
562 fde.cie = &cie;
563 fde.cie_offset = 0x8000;
564 fde.cfa_instructions_offset = 0x6000;
565 fde.cfa_instructions_end = 0x6002;
566
David Srbecky3386eba2018-03-14 21:30:25 +0000567 dwarf_loc_regs_t cie_loc_regs;
568 cie_loc_regs[6] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 0}};
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700569 this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs);
570 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
571
572 dwarf_loc_regs_t loc_regs;
Tamas Petz6835d012020-01-22 14:22:41 +0100573 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs, ARCH_UNKNOWN));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700574 ASSERT_EQ(2U, loc_regs.size());
575
576 auto entry = loc_regs.find(6);
577 ASSERT_NE(entry, loc_regs.end());
578 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
579 ASSERT_EQ(4U, entry->second.values[0]);
580
581 entry = loc_regs.find(4);
582 ASSERT_NE(entry, loc_regs.end());
583 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
584 ASSERT_EQ(3U, entry->second.values[0]);
585}
586
587TYPED_TEST_P(DwarfSectionImplTest, Log) {
588 DwarfCie cie{};
589 cie.cfa_instructions_offset = 0x5000;
590 cie.cfa_instructions_end = 0x5001;
591 DwarfFde fde{};
592 fde.cie = &cie;
593 fde.cfa_instructions_offset = 0x6000;
594 fde.cfa_instructions_end = 0x6001;
595
596 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00});
597 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2});
Tamas Petz6835d012020-01-22 14:22:41 +0100598 ASSERT_TRUE(this->section_->Log(2, 0x1000, &fde, ARCH_UNKNOWN));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700599
600 ASSERT_EQ(
601 "4 unwind DW_CFA_nop\n"
602 "4 unwind Raw Data: 0x00\n"
603 "4 unwind DW_CFA_restore register(2)\n"
604 "4 unwind Raw Data: 0xc2\n",
605 GetFakeLogPrint());
606 ASSERT_EQ("", GetFakeLogBuf());
607}
608
Christopher Ferris7e21eba2019-06-20 16:16:42 -0700609REGISTER_TYPED_TEST_SUITE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache,
610 GetFdeFromOffset_fail_should_not_cache, Eval_cfa_expr_eval_fail,
611 Eval_cfa_expr_no_stack, Eval_cfa_expr_is_register, Eval_cfa_expr,
612 Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, Eval_cfa_bad,
613 Eval_cfa_register_prev, Eval_cfa_register_from_value,
614 Eval_double_indirection, Eval_register_reference_chain, Eval_dex_pc,
615 Eval_invalid_register, Eval_different_reg_locations,
616 Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
617 Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
Tamas Zsoldosf30a46f2020-08-18 12:04:56 +0200618 Eval_pseudo_register_invalid, Eval_pseudo_register,
Christopher Ferris7e21eba2019-06-20 16:16:42 -0700619 GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700620
621typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
Haibo Huang0c01bb62019-12-11 12:46:20 -0800622INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfSectionImplTest, DwarfSectionImplTestTypes);
Christopher Ferrisd226a512017-07-14 10:37:19 -0700623
624} // namespace unwindstack