blob: 37305b26b0ce7466591f7ff558e876d7a5432ebc [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
19#include <gmock/gmock.h>
20#include <gtest/gtest.h>
21
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080022#include <unwindstack/DwarfError.h>
Christopher Ferrisd226a512017-07-14 10:37:19 -070023#include <unwindstack/DwarfSection.h>
24
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>
34class MockDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
35 public:
36 MockDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
37 virtual ~MockDwarfSectionImpl() = default;
38
39 MOCK_METHOD2(Init, bool(uint64_t, uint64_t));
40
41 MOCK_METHOD2(GetFdeOffsetFromPc, bool(uint64_t, uint64_t*));
42
43 MOCK_METHOD1(GetFdeFromIndex, const DwarfFde*(size_t));
44
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070045 MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t));
46
47 MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t));
48
49 MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t));
50
Christopher Ferrisc9dee842017-11-03 14:50:27 -070051 void TestSetCie32Value(uint32_t value32) { this->cie32_value_ = value32; }
52
53 void TestSetCie64Value(uint64_t value64) { this->cie64_value_ = value64; }
54
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070055 void TestSetCachedCieEntry(uint64_t offset, const DwarfCie& cie) {
56 this->cie_entries_[offset] = cie;
57 }
58 void TestClearCachedCieEntry() { this->cie_entries_.clear(); }
59
60 void TestSetCachedFdeEntry(uint64_t offset, const DwarfFde& fde) {
61 this->fde_entries_[offset] = fde;
62 }
63 void TestClearCachedFdeEntry() { this->fde_entries_.clear(); }
64
65 void TestSetCachedCieLocRegs(uint64_t offset, const dwarf_loc_regs_t& loc_regs) {
66 this->cie_loc_regs_[offset] = loc_regs;
67 }
68 void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); }
69
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080070 void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070071};
72
73template <typename TypeParam>
74class DwarfSectionImplTest : public ::testing::Test {
75 protected:
76 void SetUp() override {
77 memory_.Clear();
78 section_ = new MockDwarfSectionImpl<TypeParam>(&memory_);
79 ResetLogs();
Christopher Ferrisc9dee842017-11-03 14:50:27 -070080 section_->TestSetCie32Value(static_cast<uint32_t>(-1));
81 section_->TestSetCie64Value(static_cast<uint64_t>(-1));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070082 }
83
84 void TearDown() override { delete section_; }
85
86 MemoryFake memory_;
87 MockDwarfSectionImpl<TypeParam>* section_ = nullptr;
88};
89TYPED_TEST_CASE_P(DwarfSectionImplTest);
90
91// NOTE: All test class variables need to be referenced as this->.
92
93TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
94 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070095 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070096 dwarf_loc_regs_t loc_regs;
97
98 regs.set_pc(0x100);
99 regs.set_sp(0x2000);
100 regs[5] = 0x20;
101 regs[9] = 0x3000;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800102 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5002}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700103 bool finished;
104 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800105 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
106 EXPECT_EQ(0x5000U, this->section_->LastErrorAddress());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700107}
108
109TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
110 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700111 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700112 dwarf_loc_regs_t loc_regs;
113
114 regs.set_pc(0x100);
115 regs.set_sp(0x2000);
116 regs[5] = 0x20;
117 regs[9] = 0x3000;
118 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
Christopher Ferris559c7f22018-02-12 20:18:03 -0800119 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5002}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700120 bool finished;
121 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800122 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700123}
124
125TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
126 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700127 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700128 dwarf_loc_regs_t loc_regs;
129
130 regs.set_pc(0x100);
131 regs.set_sp(0x2000);
132 regs[5] = 0x20;
133 regs[9] = 0x3000;
134 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
135 TypeParam cfa_value = 0x12345;
136 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
Christopher Ferris559c7f22018-02-12 20:18:03 -0800137 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700138 bool finished;
139 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
140 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700141 EXPECT_EQ(0x12345U, regs.sp());
142 EXPECT_EQ(0x20U, regs.pc());
143}
144
145TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
146 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700147 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700148 dwarf_loc_regs_t loc_regs;
149
150 regs.set_pc(0x100);
151 regs.set_sp(0x2000);
152 regs[5] = 0x20;
153 regs[9] = 0x3000;
154 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
Christopher Ferris559c7f22018-02-12 20:18:03 -0800155 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700156 bool finished;
157 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
158 ASSERT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700159 EXPECT_EQ(0x80000000U, regs.sp());
160 EXPECT_EQ(0x20U, regs.pc());
161}
162
163TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
164 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700165 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700166 dwarf_loc_regs_t loc_regs;
167
168 regs.set_pc(0x100);
169 regs.set_sp(0x2000);
170 regs[5] = 0x20;
171 regs[9] = 0x3000;
172 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
Christopher Ferris559c7f22018-02-12 20:18:03 -0800173 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5002}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700174 bool finished;
175 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800176 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700177}
178
179TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
180 DwarfCie cie{.return_address_register = 60};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700181 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700182 dwarf_loc_regs_t loc_regs;
183
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700184 bool finished;
185 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800186 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700187}
188
189TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
190 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700191 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700192 dwarf_loc_regs_t loc_regs;
193
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700194 bool finished;
195 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800196 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700197}
198
199TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
200 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700201 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700202 dwarf_loc_regs_t loc_regs;
203
204 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700205 bool finished;
206 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800207 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700208
209 this->section_->TestClearError();
210 loc_regs.erase(CFA_REG);
211 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700212 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800213 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700214
215 this->section_->TestClearError();
216 loc_regs.erase(CFA_REG);
217 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700218 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800219 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700220
221 this->section_->TestClearError();
222 loc_regs.erase(CFA_REG);
223 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700224 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800225 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700226}
227
228TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
229 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700230 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700231 dwarf_loc_regs_t loc_regs;
232
233 regs.set_pc(0x100);
234 regs.set_sp(0x2000);
235 regs[5] = 0x20;
236 regs[9] = 0x3000;
237 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700238 bool finished;
239 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
240 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700241 EXPECT_EQ(0x20U, regs.pc());
242 EXPECT_EQ(0x2000U, regs.sp());
243}
244
245TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
246 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700247 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700248 dwarf_loc_regs_t loc_regs;
249
250 regs.set_pc(0x100);
251 regs.set_sp(0x2000);
252 regs[5] = 0x20;
253 regs[6] = 0x4000;
254 regs[9] = 0x3000;
255 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700256 bool finished;
257 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
258 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700259 EXPECT_EQ(0x20U, regs.pc());
260 EXPECT_EQ(0x4000U, regs.sp());
261}
262
263TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
264 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700265 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700266 dwarf_loc_regs_t loc_regs;
267
268 regs.set_pc(0x100);
269 regs.set_sp(0x2000);
Christopher Ferris98984b42018-01-17 12:59:45 -0800270 regs[1] = 0x100;
271 regs[3] = 0x300;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700272 regs[8] = 0x10;
273 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris98984b42018-01-17 12:59:45 -0800274 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 1}};
275 loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700276 bool finished;
Christopher Ferris98984b42018-01-17 12:59:45 -0800277 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
278 EXPECT_EQ(0x301U, regs[1]);
279 EXPECT_EQ(0x300U, regs[3]);
280 EXPECT_EQ(0x10U, regs[8]);
281 EXPECT_EQ(0x102U, regs[9]);
282}
283
284TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
285 DwarfCie cie{.return_address_register = 5};
286 RegsImplFake<TypeParam> regs(10, 9);
287 dwarf_loc_regs_t loc_regs;
288
289 regs.set_pc(0x100);
290 regs.set_sp(0x2000);
291 regs[0] = 0x10;
292 regs[1] = 0x20;
293 regs[2] = 0x30;
294 regs[3] = 0x40;
295 regs[4] = 0x50;
296 regs[5] = 0x60;
297 regs[8] = 0x20;
298 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
299 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}};
300 loc_regs[2] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
301 loc_regs[3] = DwarfLocation{DWARF_LOCATION_REGISTER, {2, 3}};
302 loc_regs[4] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 4}};
303 loc_regs[5] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 5}};
304 bool finished;
305 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
306 EXPECT_EQ(0x10U, regs[0]);
307 EXPECT_EQ(0x11U, regs[1]);
308 EXPECT_EQ(0x22U, regs[2]);
309 EXPECT_EQ(0x33U, regs[3]);
310 EXPECT_EQ(0x44U, regs[4]);
311 EXPECT_EQ(0x55U, regs[5]);
312 EXPECT_EQ(0x20U, regs[8]);
313}
314
315TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
316 DwarfCie cie{.return_address_register = 5};
317 RegsImplFake<TypeParam> regs(10, 9);
318 dwarf_loc_regs_t loc_regs;
319
320 regs.set_pc(0x100);
321 regs.set_sp(0x2000);
322 regs[0] = 0x10;
323 regs[8] = 0x20;
324 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris559c7f22018-02-12 20:18:03 -0800325 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x8, 0x5008}};
326 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13, 0x08, 0x11});
Christopher Ferris98984b42018-01-17 12:59:45 -0800327 bool finished;
328 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
329 EXPECT_EQ(0x10U, regs[0]);
330 EXPECT_EQ(0x20U, regs[8]);
331 EXPECT_EQ(0x11U, regs.dex_pc());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700332}
333
334TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
335 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700336 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700337 dwarf_loc_regs_t loc_regs;
338
339 regs.set_pc(0x100);
340 regs.set_sp(0x2000);
341 regs[8] = 0x10;
342 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
343 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700344 bool finished;
345 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800346 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700347}
348
349TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
350 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700351 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700352 dwarf_loc_regs_t loc_regs;
353
354 if (sizeof(TypeParam) == sizeof(uint64_t)) {
355 this->memory_.SetData64(0x2150, 0x12345678abcdef00ULL);
356 } else {
357 this->memory_.SetData32(0x2150, 0x12345678);
358 }
359
360 regs.set_pc(0x100);
361 regs.set_sp(0x2000);
362 regs[3] = 0x234;
363 regs[5] = 0x10;
364 regs[8] = 0x2100;
365 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
366 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}};
367 loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}};
368 loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700369 bool finished;
370 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
371 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700372 EXPECT_EQ(0x10U, regs.pc());
373 EXPECT_EQ(0x2100U, regs.sp());
374 EXPECT_EQ(0x2200U, regs[1]);
375 EXPECT_EQ(0x234U, regs[3]);
376 if (sizeof(TypeParam) == sizeof(uint64_t)) {
377 EXPECT_EQ(0x12345678abcdef00ULL, regs[2]);
378 } else {
379 EXPECT_EQ(0x12345678U, regs[2]);
380 }
381}
382
383TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
384 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700385 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700386 dwarf_loc_regs_t loc_regs;
387
388 regs.set_pc(0x100);
389 regs.set_sp(0x2000);
390 regs[5] = 0x20;
391 regs[8] = 0x10;
392 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
393 loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700394 bool finished;
395 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
396 EXPECT_TRUE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700397 EXPECT_EQ(0U, regs.pc());
398 EXPECT_EQ(0x10U, regs.sp());
399}
400
Christopher Ferris2502a602017-10-23 13:51:54 -0700401TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
402 DwarfCie cie{.return_address_register = 5};
403 RegsImplFake<TypeParam> regs(10, 9);
404 dwarf_loc_regs_t loc_regs;
405
406 regs.set_pc(0x100);
407 regs.set_sp(0x2000);
408 regs[5] = 0;
409 regs[8] = 0x10;
410 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
411 bool finished;
412 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
413 EXPECT_TRUE(finished);
414 EXPECT_EQ(0U, regs.pc());
415 EXPECT_EQ(0x10U, regs.sp());
416}
417
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700418TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
419 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700420 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700421 dwarf_loc_regs_t loc_regs;
422
423 regs.set_pc(0x100);
424 regs.set_sp(0x2000);
425 regs[5] = 0x20;
426 regs[8] = 0x10;
427 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700428 bool finished;
429 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
430 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700431 EXPECT_EQ(0x20U, regs.pc());
432 EXPECT_EQ(0x10U, regs.sp());
433}
434
435TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
436 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700437 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700438 dwarf_loc_regs_t loc_regs;
439
440 regs.set_pc(0x100);
441 regs.set_sp(0x2000);
442 regs[5] = 0x20;
443 regs[8] = 0x10;
444 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
445 // This should not result in any errors.
446 loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700447 bool finished;
448 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
449 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700450 EXPECT_EQ(0x20U, regs.pc());
451 EXPECT_EQ(0x10U, regs.sp());
452}
453
454TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
455 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700456 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700457 dwarf_loc_regs_t loc_regs;
458
459 regs.set_pc(0x100);
460 regs.set_sp(0x2000);
461 regs[8] = 0x3000;
462 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
463 TypeParam cfa_value = 0x12345;
464 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
465 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris559c7f22018-02-12 20:18:03 -0800466 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700467 bool finished;
468 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
469 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700470 EXPECT_EQ(0x3000U, regs.sp());
471 EXPECT_EQ(0x12345U, regs.pc());
472}
473
474TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
475 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700476 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700477 dwarf_loc_regs_t loc_regs;
478
479 regs.set_pc(0x100);
480 regs.set_sp(0x2000);
481 regs[8] = 0x3000;
482 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
483 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris559c7f22018-02-12 20:18:03 -0800484 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700485 bool finished;
486 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
487 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700488 EXPECT_EQ(0x3000U, regs.sp());
489 EXPECT_EQ(0x80000000U, regs.pc());
490}
491
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700492TYPED_TEST_P(DwarfSectionImplTest, GetCie_fail_should_not_cache) {
493 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800494 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
495 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700496 this->section_->TestClearError();
497 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800498 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
499 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700500}
501
502TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) {
503 this->memory_.SetData32(0x5000, 0x100);
504 this->memory_.SetData32(0x5004, 0xffffffff);
505 this->memory_.SetData8(0x5008, 0x1);
506 this->memory_.SetData8(0x5009, '\0');
507 this->memory_.SetData8(0x500a, 4);
508 this->memory_.SetData8(0x500b, 8);
509 this->memory_.SetData8(0x500c, 0x20);
510
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700511 const DwarfCie* cie = this->section_->GetCie(0x5000);
512 ASSERT_TRUE(cie != nullptr);
513 EXPECT_EQ(1U, cie->version);
514 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
515 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
516 EXPECT_EQ(0U, cie->segment_size);
517 EXPECT_EQ(1U, cie->augmentation_string.size());
518 EXPECT_EQ('\0', cie->augmentation_string[0]);
519 EXPECT_EQ(0U, cie->personality_handler);
520 EXPECT_EQ(0x500dU, cie->cfa_instructions_offset);
521 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
522 EXPECT_EQ(4U, cie->code_alignment_factor);
523 EXPECT_EQ(8, cie->data_alignment_factor);
524 EXPECT_EQ(0x20U, cie->return_address_register);
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800525 EXPECT_EQ(DWARF_ERROR_NONE, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700526
527 this->section_->TestClearCachedCieEntry();
528 // Set version to 0, 2, 5 and verify we fail.
529 this->memory_.SetData8(0x5008, 0x0);
530 this->section_->TestClearError();
531 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800532 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700533
534 this->memory_.SetData8(0x5008, 0x2);
535 this->section_->TestClearError();
536 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800537 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700538
539 this->memory_.SetData8(0x5008, 0x5);
540 this->section_->TestClearError();
541 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800542 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700543}
544
545TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) {
546 this->memory_.SetData32(0x5000, 0x100);
547 this->memory_.SetData32(0x5004, 0xffffffff);
548 this->memory_.SetData8(0x5008, 0x1);
549 this->memory_.SetData8(0x5009, '\0');
550 this->memory_.SetData8(0x500a, 4);
551 this->memory_.SetMemory(0x500b, std::vector<uint8_t>{0xfc, 0xff, 0xff, 0xff, 0x7f});
552 this->memory_.SetData8(0x5010, 0x20);
553
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700554 const DwarfCie* cie = this->section_->GetCie(0x5000);
555 ASSERT_TRUE(cie != nullptr);
556 EXPECT_EQ(1U, cie->version);
557 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
558 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
559 EXPECT_EQ(0U, cie->segment_size);
560 EXPECT_EQ(1U, cie->augmentation_string.size());
561 EXPECT_EQ('\0', cie->augmentation_string[0]);
562 EXPECT_EQ(0U, cie->personality_handler);
563 EXPECT_EQ(0x5011U, cie->cfa_instructions_offset);
564 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
565 EXPECT_EQ(4U, cie->code_alignment_factor);
566 EXPECT_EQ(-4, cie->data_alignment_factor);
567 EXPECT_EQ(0x20U, cie->return_address_register);
568}
569
570TYPED_TEST_P(DwarfSectionImplTest, GetCie_64_no_augment) {
571 this->memory_.SetData32(0x8000, 0xffffffff);
572 this->memory_.SetData64(0x8004, 0x200);
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700573 this->memory_.SetData64(0x800c, 0xffffffffffffffffULL);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700574 this->memory_.SetData8(0x8014, 0x1);
575 this->memory_.SetData8(0x8015, '\0');
576 this->memory_.SetData8(0x8016, 4);
577 this->memory_.SetData8(0x8017, 8);
578 this->memory_.SetData8(0x8018, 0x20);
579
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700580 const DwarfCie* cie = this->section_->GetCie(0x8000);
581 ASSERT_TRUE(cie != nullptr);
582 EXPECT_EQ(1U, cie->version);
583 EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding);
584 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
585 EXPECT_EQ(0U, cie->segment_size);
586 EXPECT_EQ(1U, cie->augmentation_string.size());
587 EXPECT_EQ('\0', cie->augmentation_string[0]);
588 EXPECT_EQ(0U, cie->personality_handler);
589 EXPECT_EQ(0x8019U, cie->cfa_instructions_offset);
590 EXPECT_EQ(0x820cU, cie->cfa_instructions_end);
591 EXPECT_EQ(4U, cie->code_alignment_factor);
592 EXPECT_EQ(8, cie->data_alignment_factor);
593 EXPECT_EQ(0x20U, cie->return_address_register);
594}
595
596TYPED_TEST_P(DwarfSectionImplTest, GetCie_augment) {
597 this->memory_.SetData32(0x5000, 0x100);
598 this->memory_.SetData32(0x5004, 0xffffffff);
599 this->memory_.SetData8(0x5008, 0x1);
600 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
601 this->memory_.SetData8(0x500e, 4);
602 this->memory_.SetData8(0x500f, 8);
603 this->memory_.SetData8(0x5010, 0x10);
604 // Augment length.
605 this->memory_.SetData8(0x5011, 0xf);
606 // L data.
607 this->memory_.SetData8(0x5012, DW_EH_PE_textrel | DW_EH_PE_udata2);
608 // P data.
609 this->memory_.SetData8(0x5013, DW_EH_PE_udata4);
610 this->memory_.SetData32(0x5014, 0x12345678);
611 // R data.
612 this->memory_.SetData8(0x5018, DW_EH_PE_udata2);
613
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700614 const DwarfCie* cie = this->section_->GetCie(0x5000);
615 ASSERT_TRUE(cie != nullptr);
616 EXPECT_EQ(1U, cie->version);
617 EXPECT_EQ(DW_EH_PE_udata2, cie->fde_address_encoding);
618 EXPECT_EQ(DW_EH_PE_textrel | DW_EH_PE_udata2, cie->lsda_encoding);
619 EXPECT_EQ(0U, cie->segment_size);
620 EXPECT_EQ(5U, cie->augmentation_string.size());
621 EXPECT_EQ('z', cie->augmentation_string[0]);
622 EXPECT_EQ('L', cie->augmentation_string[1]);
623 EXPECT_EQ('P', cie->augmentation_string[2]);
624 EXPECT_EQ('R', cie->augmentation_string[3]);
625 EXPECT_EQ('\0', cie->augmentation_string[4]);
626 EXPECT_EQ(0x12345678U, cie->personality_handler);
627 EXPECT_EQ(0x5021U, cie->cfa_instructions_offset);
628 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
629 EXPECT_EQ(4U, cie->code_alignment_factor);
630 EXPECT_EQ(8, cie->data_alignment_factor);
631 EXPECT_EQ(0x10U, cie->return_address_register);
632}
633
634TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_3) {
635 this->memory_.SetData32(0x5000, 0x100);
636 this->memory_.SetData32(0x5004, 0xffffffff);
637 this->memory_.SetData8(0x5008, 0x3);
638 this->memory_.SetData8(0x5009, '\0');
639 this->memory_.SetData8(0x500a, 4);
640 this->memory_.SetData8(0x500b, 8);
641 this->memory_.SetMemory(0x500c, std::vector<uint8_t>{0x81, 0x03});
642
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700643 const DwarfCie* cie = this->section_->GetCie(0x5000);
644 ASSERT_TRUE(cie != nullptr);
645 EXPECT_EQ(3U, cie->version);
646 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
647 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
648 EXPECT_EQ(0U, cie->segment_size);
649 EXPECT_EQ(1U, cie->augmentation_string.size());
650 EXPECT_EQ('\0', cie->augmentation_string[0]);
651 EXPECT_EQ(0U, cie->personality_handler);
652 EXPECT_EQ(0x500eU, cie->cfa_instructions_offset);
653 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
654 EXPECT_EQ(4U, cie->code_alignment_factor);
655 EXPECT_EQ(8, cie->data_alignment_factor);
656 EXPECT_EQ(0x181U, cie->return_address_register);
657}
658
659TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_4) {
660 this->memory_.SetData32(0x5000, 0x100);
661 this->memory_.SetData32(0x5004, 0xffffffff);
662 this->memory_.SetData8(0x5008, 0x4);
663 this->memory_.SetData8(0x5009, '\0');
664 this->memory_.SetData8(0x500a, 4);
665 this->memory_.SetData8(0x500b, 0x13);
666 this->memory_.SetData8(0x500c, 4);
667 this->memory_.SetData8(0x500d, 8);
668 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x81, 0x03});
669
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700670 const DwarfCie* cie = this->section_->GetCie(0x5000);
671 ASSERT_TRUE(cie != nullptr);
672 EXPECT_EQ(4U, cie->version);
673 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
674 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
675 EXPECT_EQ(0x13U, cie->segment_size);
676 EXPECT_EQ(1U, cie->augmentation_string.size());
677 EXPECT_EQ('\0', cie->augmentation_string[0]);
678 EXPECT_EQ(0U, cie->personality_handler);
679 EXPECT_EQ(0x5010U, cie->cfa_instructions_offset);
680 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
681 EXPECT_EQ(4U, cie->code_alignment_factor);
682 EXPECT_EQ(8, cie->data_alignment_factor);
683 EXPECT_EQ(0x181U, cie->return_address_register);
684}
685
686TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
687 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800688 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
689 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700690 this->section_->TestClearError();
691 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800692 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
693 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700694}
695
696TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) {
697 this->memory_.SetData32(0x4000, 0x20);
698 this->memory_.SetData32(0x4004, 0x8000);
699 this->memory_.SetData32(0x4008, 0x5000);
700 this->memory_.SetData32(0x400c, 0x100);
701
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700702 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
703 DwarfCie cie{};
704 cie.fde_address_encoding = DW_EH_PE_udata4;
705 this->section_->TestSetCachedCieEntry(0x8000, cie);
706 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
707
708 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
709 ASSERT_TRUE(fde != nullptr);
710 ASSERT_TRUE(fde->cie != nullptr);
711 EXPECT_EQ(0x4010U, fde->cfa_instructions_offset);
712 EXPECT_EQ(0x4024U, fde->cfa_instructions_end);
713 EXPECT_EQ(0x5000U, fde->pc_start);
714 EXPECT_EQ(0x5100U, fde->pc_end);
715 EXPECT_EQ(0x8000U, fde->cie_offset);
716 EXPECT_EQ(0U, fde->lsda_address);
717}
718
719TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment_non_zero_segment_size) {
720 this->memory_.SetData32(0x4000, 0x30);
721 this->memory_.SetData32(0x4004, 0x8000);
722 this->memory_.SetData32(0x4018, 0x5000);
723 this->memory_.SetData32(0x401c, 0x100);
724
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700725 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
726 DwarfCie cie{};
727 cie.fde_address_encoding = DW_EH_PE_udata4;
728 cie.segment_size = 0x10;
729 this->section_->TestSetCachedCieEntry(0x8000, cie);
730 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
731
732 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
733 ASSERT_TRUE(fde != nullptr);
734 ASSERT_TRUE(fde->cie != nullptr);
735 EXPECT_EQ(0x4020U, fde->cfa_instructions_offset);
736 EXPECT_EQ(0x4034U, fde->cfa_instructions_end);
737 EXPECT_EQ(0x5000U, fde->pc_start);
738 EXPECT_EQ(0x5100U, fde->pc_end);
739 EXPECT_EQ(0x8000U, fde->cie_offset);
740 EXPECT_EQ(0U, fde->lsda_address);
741}
742
743TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_augment) {
744 this->memory_.SetData32(0x4000, 0x100);
745 this->memory_.SetData32(0x4004, 0x8000);
746 this->memory_.SetData32(0x4008, 0x5000);
747 this->memory_.SetData32(0x400c, 0x100);
748 this->memory_.SetMemory(0x4010, std::vector<uint8_t>{0x82, 0x01});
749 this->memory_.SetData16(0x4012, 0x1234);
750
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700751 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
752 DwarfCie cie{};
753 cie.fde_address_encoding = DW_EH_PE_udata4;
754 cie.augmentation_string.push_back('z');
755 cie.lsda_encoding = DW_EH_PE_udata2;
756 this->section_->TestSetCachedCieEntry(0x8000, cie);
757 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
758
759 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
760 ASSERT_TRUE(fde != nullptr);
761 ASSERT_TRUE(fde->cie != nullptr);
762 EXPECT_EQ(0x4094U, fde->cfa_instructions_offset);
763 EXPECT_EQ(0x4104U, fde->cfa_instructions_end);
764 EXPECT_EQ(0x5000U, fde->pc_start);
765 EXPECT_EQ(0x5100U, fde->pc_end);
766 EXPECT_EQ(0x8000U, fde->cie_offset);
767 EXPECT_EQ(0x1234U, fde->lsda_address);
768}
769
770TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_64_no_augment) {
771 this->memory_.SetData32(0x4000, 0xffffffff);
772 this->memory_.SetData64(0x4004, 0x100);
773 this->memory_.SetData64(0x400c, 0x12345678);
774 this->memory_.SetData32(0x4014, 0x5000);
775 this->memory_.SetData32(0x4018, 0x100);
776
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700777 EXPECT_CALL(*this->section_, GetCieOffsetFromFde64(0x12345678))
778 .WillOnce(::testing::Return(0x12345678));
779 DwarfCie cie{};
780 cie.fde_address_encoding = DW_EH_PE_udata4;
781 this->section_->TestSetCachedCieEntry(0x12345678, cie);
782 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
783
784 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
785 ASSERT_TRUE(fde != nullptr);
786 ASSERT_TRUE(fde->cie != nullptr);
787 EXPECT_EQ(0x401cU, fde->cfa_instructions_offset);
788 EXPECT_EQ(0x410cU, fde->cfa_instructions_end);
789 EXPECT_EQ(0x5000U, fde->pc_start);
790 EXPECT_EQ(0x5100U, fde->pc_end);
791 EXPECT_EQ(0x12345678U, fde->cie_offset);
792 EXPECT_EQ(0U, fde->lsda_address);
793}
794
795TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_cached) {
796 DwarfCie cie{};
797 cie.fde_address_encoding = DW_EH_PE_udata4;
798 cie.augmentation_string.push_back('z');
799 cie.lsda_encoding = DW_EH_PE_udata2;
800
801 DwarfFde fde_cached{};
802 fde_cached.cfa_instructions_offset = 0x1000;
803 fde_cached.cfa_instructions_end = 0x1100;
804 fde_cached.pc_start = 0x9000;
805 fde_cached.pc_end = 0x9400;
806 fde_cached.cie_offset = 0x30000;
807 fde_cached.cie = &cie;
808 this->section_->TestSetCachedFdeEntry(0x6000, fde_cached);
809
810 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x6000);
811 ASSERT_TRUE(fde != nullptr);
812 ASSERT_EQ(&cie, fde->cie);
813 EXPECT_EQ(0x1000U, fde->cfa_instructions_offset);
814 EXPECT_EQ(0x1100U, fde->cfa_instructions_end);
815 EXPECT_EQ(0x9000U, fde->pc_start);
816 EXPECT_EQ(0x9400U, fde->pc_end);
817 EXPECT_EQ(0x30000U, fde->cie_offset);
818}
819
820TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
821 DwarfCie cie{};
822 cie.cfa_instructions_offset = 0x3000;
823 cie.cfa_instructions_end = 0x3002;
824 DwarfFde fde{};
825 fde.cie = &cie;
826 fde.cie_offset = 0x8000;
827 fde.cfa_instructions_offset = 0x6000;
828 fde.cfa_instructions_end = 0x6002;
829
830 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x09, 0x02, 0x01});
831 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
832
833 dwarf_loc_regs_t loc_regs;
834 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
835 ASSERT_EQ(2U, loc_regs.size());
836
837 auto entry = loc_regs.find(2);
838 ASSERT_NE(entry, loc_regs.end());
839 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
840 ASSERT_EQ(1U, entry->second.values[0]);
841
842 entry = loc_regs.find(4);
843 ASSERT_NE(entry, loc_regs.end());
844 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
845 ASSERT_EQ(3U, entry->second.values[0]);
846}
847
848TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) {
849 DwarfCie cie{};
850 cie.cfa_instructions_offset = 0x3000;
851 cie.cfa_instructions_end = 0x3002;
852 DwarfFde fde{};
853 fde.cie = &cie;
854 fde.cie_offset = 0x8000;
855 fde.cfa_instructions_offset = 0x6000;
856 fde.cfa_instructions_end = 0x6002;
857
858 dwarf_loc_regs_t cie_loc_regs{{6, {DWARF_LOCATION_REGISTER, {4, 0}}}};
859 this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs);
860 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
861
862 dwarf_loc_regs_t loc_regs;
863 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
864 ASSERT_EQ(2U, loc_regs.size());
865
866 auto entry = loc_regs.find(6);
867 ASSERT_NE(entry, loc_regs.end());
868 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
869 ASSERT_EQ(4U, entry->second.values[0]);
870
871 entry = loc_regs.find(4);
872 ASSERT_NE(entry, loc_regs.end());
873 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
874 ASSERT_EQ(3U, entry->second.values[0]);
875}
876
877TYPED_TEST_P(DwarfSectionImplTest, Log) {
878 DwarfCie cie{};
879 cie.cfa_instructions_offset = 0x5000;
880 cie.cfa_instructions_end = 0x5001;
881 DwarfFde fde{};
882 fde.cie = &cie;
883 fde.cfa_instructions_offset = 0x6000;
884 fde.cfa_instructions_end = 0x6001;
885
886 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00});
887 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2});
888 ASSERT_TRUE(this->section_->Log(2, 0x1000, 0x1000, &fde));
889
890 ASSERT_EQ(
891 "4 unwind DW_CFA_nop\n"
892 "4 unwind Raw Data: 0x00\n"
893 "4 unwind DW_CFA_restore register(2)\n"
894 "4 unwind Raw Data: 0xc2\n",
895 GetFakeLogPrint());
896 ASSERT_EQ("", GetFakeLogBuf());
897}
898
899REGISTER_TYPED_TEST_CASE_P(
900 DwarfSectionImplTest, Eval_cfa_expr_eval_fail, Eval_cfa_expr_no_stack,
901 Eval_cfa_expr_is_register, Eval_cfa_expr, Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa,
902 Eval_cfa_bad, Eval_cfa_register_prev, Eval_cfa_register_from_value, Eval_double_indirection,
Christopher Ferris98984b42018-01-17 12:59:45 -0800903 Eval_register_reference_chain, Eval_dex_pc, Eval_invalid_register, Eval_different_reg_locations,
904 Eval_return_address_undefined, Eval_pc_zero, Eval_return_address, Eval_ignore_large_reg_loc,
905 Eval_reg_expr, Eval_reg_val_expr, GetCie_fail_should_not_cache, GetCie_32_version_check,
906 GetCie_negative_data_alignment_factor, GetCie_64_no_augment, GetCie_augment, GetCie_version_3,
907 GetCie_version_4, GetFdeFromOffset_fail_should_not_cache, GetFdeFromOffset_32_no_augment,
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700908 GetFdeFromOffset_32_no_augment_non_zero_segment_size, GetFdeFromOffset_32_augment,
909 GetFdeFromOffset_64_no_augment, GetFdeFromOffset_cached, GetCfaLocationInfo_cie_not_cached,
910 GetCfaLocationInfo_cie_cached, Log);
911
912typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
913INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes);
Christopher Ferrisd226a512017-07-14 10:37:19 -0700914
915} // namespace unwindstack