blob: dfd2ce059f1065db16fb61d3c4b8ee6740ce993e [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 Ferrisd226a512017-07-14 10:37:19 -070022#include <unwindstack/DwarfSection.h>
23
24#include "DwarfEncoding.h"
25#include "DwarfError.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
70 void TestClearError() { this->last_error_ = DWARF_ERROR_NONE; }
71};
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;
102 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700103 bool finished;
104 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700105 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
106}
107
108TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
109 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700110 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700111 dwarf_loc_regs_t loc_regs;
112
113 regs.set_pc(0x100);
114 regs.set_sp(0x2000);
115 regs[5] = 0x20;
116 regs[9] = 0x3000;
117 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
118 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700119 bool finished;
120 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700121 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error());
122}
123
124TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
125 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700126 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700127 dwarf_loc_regs_t loc_regs;
128
129 regs.set_pc(0x100);
130 regs.set_sp(0x2000);
131 regs[5] = 0x20;
132 regs[9] = 0x3000;
133 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
134 TypeParam cfa_value = 0x12345;
135 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
136 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700137 bool finished;
138 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
139 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700140 EXPECT_EQ(0x12345U, regs.sp());
141 EXPECT_EQ(0x20U, regs.pc());
142}
143
144TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
145 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700146 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700147 dwarf_loc_regs_t loc_regs;
148
149 regs.set_pc(0x100);
150 regs.set_sp(0x2000);
151 regs[5] = 0x20;
152 regs[9] = 0x3000;
153 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
154 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700155 bool finished;
156 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
157 ASSERT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700158 EXPECT_EQ(0x80000000U, regs.sp());
159 EXPECT_EQ(0x20U, regs.pc());
160}
161
162TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
163 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700164 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700165 dwarf_loc_regs_t loc_regs;
166
167 regs.set_pc(0x100);
168 regs.set_sp(0x2000);
169 regs[5] = 0x20;
170 regs[9] = 0x3000;
171 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
172 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700173 bool finished;
174 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700175 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->last_error());
176}
177
178TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
179 DwarfCie cie{.return_address_register = 60};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700180 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700181 dwarf_loc_regs_t loc_regs;
182
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700183 bool finished;
184 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700185 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
186}
187
188TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
189 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700190 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700191 dwarf_loc_regs_t loc_regs;
192
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700193 bool finished;
194 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700195 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->last_error());
196}
197
198TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
199 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700200 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700201 dwarf_loc_regs_t loc_regs;
202
203 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700204 bool finished;
205 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700206 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
207
208 this->section_->TestClearError();
209 loc_regs.erase(CFA_REG);
210 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700211 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700212 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
213
214 this->section_->TestClearError();
215 loc_regs.erase(CFA_REG);
216 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700217 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700218 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
219
220 this->section_->TestClearError();
221 loc_regs.erase(CFA_REG);
222 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700223 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700224 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
225}
226
227TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
228 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700229 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700230 dwarf_loc_regs_t loc_regs;
231
232 regs.set_pc(0x100);
233 regs.set_sp(0x2000);
234 regs[5] = 0x20;
235 regs[9] = 0x3000;
236 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700237 bool finished;
238 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
239 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700240 EXPECT_EQ(0x20U, regs.pc());
241 EXPECT_EQ(0x2000U, regs.sp());
242}
243
244TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
245 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700246 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700247 dwarf_loc_regs_t loc_regs;
248
249 regs.set_pc(0x100);
250 regs.set_sp(0x2000);
251 regs[5] = 0x20;
252 regs[6] = 0x4000;
253 regs[9] = 0x3000;
254 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700255 bool finished;
256 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
257 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700258 EXPECT_EQ(0x20U, regs.pc());
259 EXPECT_EQ(0x4000U, regs.sp());
260}
261
262TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
263 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700264 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700265 dwarf_loc_regs_t loc_regs;
266
267 regs.set_pc(0x100);
268 regs.set_sp(0x2000);
Christopher Ferris98984b42018-01-17 12:59:45 -0800269 regs[1] = 0x100;
270 regs[3] = 0x300;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700271 regs[8] = 0x10;
272 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferris98984b42018-01-17 12:59:45 -0800273 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 1}};
274 loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700275 bool finished;
Christopher Ferris98984b42018-01-17 12:59:45 -0800276 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
277 EXPECT_EQ(0x301U, regs[1]);
278 EXPECT_EQ(0x300U, regs[3]);
279 EXPECT_EQ(0x10U, regs[8]);
280 EXPECT_EQ(0x102U, regs[9]);
281}
282
283TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
284 DwarfCie cie{.return_address_register = 5};
285 RegsImplFake<TypeParam> regs(10, 9);
286 dwarf_loc_regs_t loc_regs;
287
288 regs.set_pc(0x100);
289 regs.set_sp(0x2000);
290 regs[0] = 0x10;
291 regs[1] = 0x20;
292 regs[2] = 0x30;
293 regs[3] = 0x40;
294 regs[4] = 0x50;
295 regs[5] = 0x60;
296 regs[8] = 0x20;
297 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
298 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}};
299 loc_regs[2] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
300 loc_regs[3] = DwarfLocation{DWARF_LOCATION_REGISTER, {2, 3}};
301 loc_regs[4] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 4}};
302 loc_regs[5] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 5}};
303 bool finished;
304 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
305 EXPECT_EQ(0x10U, regs[0]);
306 EXPECT_EQ(0x11U, regs[1]);
307 EXPECT_EQ(0x22U, regs[2]);
308 EXPECT_EQ(0x33U, regs[3]);
309 EXPECT_EQ(0x44U, regs[4]);
310 EXPECT_EQ(0x55U, regs[5]);
311 EXPECT_EQ(0x20U, regs[8]);
312}
313
314TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
315 DwarfCie cie{.return_address_register = 5};
316 RegsImplFake<TypeParam> regs(10, 9);
317 dwarf_loc_regs_t loc_regs;
318
319 regs.set_pc(0x100);
320 regs.set_sp(0x2000);
321 regs[0] = 0x10;
322 regs[8] = 0x20;
323 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
324 loc_regs[0x20444558] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}};
325 bool finished;
326 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
327 EXPECT_EQ(0x10U, regs[0]);
328 EXPECT_EQ(0x20U, regs[8]);
329 EXPECT_EQ(0x11U, regs.dex_pc());
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700330}
331
332TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
333 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700334 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700335 dwarf_loc_regs_t loc_regs;
336
337 regs.set_pc(0x100);
338 regs.set_sp(0x2000);
339 regs[8] = 0x10;
340 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
341 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700342 bool finished;
343 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700344 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
345}
346
347TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
348 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700349 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700350 dwarf_loc_regs_t loc_regs;
351
352 if (sizeof(TypeParam) == sizeof(uint64_t)) {
353 this->memory_.SetData64(0x2150, 0x12345678abcdef00ULL);
354 } else {
355 this->memory_.SetData32(0x2150, 0x12345678);
356 }
357
358 regs.set_pc(0x100);
359 regs.set_sp(0x2000);
360 regs[3] = 0x234;
361 regs[5] = 0x10;
362 regs[8] = 0x2100;
363 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
364 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}};
365 loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}};
366 loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700367 bool finished;
368 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
369 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700370 EXPECT_EQ(0x10U, regs.pc());
371 EXPECT_EQ(0x2100U, regs.sp());
372 EXPECT_EQ(0x2200U, regs[1]);
373 EXPECT_EQ(0x234U, regs[3]);
374 if (sizeof(TypeParam) == sizeof(uint64_t)) {
375 EXPECT_EQ(0x12345678abcdef00ULL, regs[2]);
376 } else {
377 EXPECT_EQ(0x12345678U, regs[2]);
378 }
379}
380
381TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
382 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700383 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700384 dwarf_loc_regs_t loc_regs;
385
386 regs.set_pc(0x100);
387 regs.set_sp(0x2000);
388 regs[5] = 0x20;
389 regs[8] = 0x10;
390 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
391 loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700392 bool finished;
393 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
394 EXPECT_TRUE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700395 EXPECT_EQ(0U, regs.pc());
396 EXPECT_EQ(0x10U, regs.sp());
397}
398
Christopher Ferris2502a602017-10-23 13:51:54 -0700399TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
400 DwarfCie cie{.return_address_register = 5};
401 RegsImplFake<TypeParam> regs(10, 9);
402 dwarf_loc_regs_t loc_regs;
403
404 regs.set_pc(0x100);
405 regs.set_sp(0x2000);
406 regs[5] = 0;
407 regs[8] = 0x10;
408 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
409 bool finished;
410 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
411 EXPECT_TRUE(finished);
412 EXPECT_EQ(0U, regs.pc());
413 EXPECT_EQ(0x10U, regs.sp());
414}
415
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700416TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
417 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700418 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700419 dwarf_loc_regs_t loc_regs;
420
421 regs.set_pc(0x100);
422 regs.set_sp(0x2000);
423 regs[5] = 0x20;
424 regs[8] = 0x10;
425 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700426 bool finished;
427 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
428 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700429 EXPECT_EQ(0x20U, regs.pc());
430 EXPECT_EQ(0x10U, regs.sp());
431}
432
433TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
434 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700435 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700436 dwarf_loc_regs_t loc_regs;
437
438 regs.set_pc(0x100);
439 regs.set_sp(0x2000);
440 regs[5] = 0x20;
441 regs[8] = 0x10;
442 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
443 // This should not result in any errors.
444 loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700445 bool finished;
446 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
447 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700448 EXPECT_EQ(0x20U, regs.pc());
449 EXPECT_EQ(0x10U, regs.sp());
450}
451
452TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
453 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700454 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700455 dwarf_loc_regs_t loc_regs;
456
457 regs.set_pc(0x100);
458 regs.set_sp(0x2000);
459 regs[8] = 0x3000;
460 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
461 TypeParam cfa_value = 0x12345;
462 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
463 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
464 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700465 bool finished;
466 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
467 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700468 EXPECT_EQ(0x3000U, regs.sp());
469 EXPECT_EQ(0x12345U, regs.pc());
470}
471
472TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
473 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700474 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700475 dwarf_loc_regs_t loc_regs;
476
477 regs.set_pc(0x100);
478 regs.set_sp(0x2000);
479 regs[8] = 0x3000;
480 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
481 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
482 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700483 bool finished;
484 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
485 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700486 EXPECT_EQ(0x3000U, regs.sp());
487 EXPECT_EQ(0x80000000U, regs.pc());
488}
489
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700490TYPED_TEST_P(DwarfSectionImplTest, GetCie_fail_should_not_cache) {
491 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
492 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
493 this->section_->TestClearError();
494 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
495 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
496}
497
498TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) {
499 this->memory_.SetData32(0x5000, 0x100);
500 this->memory_.SetData32(0x5004, 0xffffffff);
501 this->memory_.SetData8(0x5008, 0x1);
502 this->memory_.SetData8(0x5009, '\0');
503 this->memory_.SetData8(0x500a, 4);
504 this->memory_.SetData8(0x500b, 8);
505 this->memory_.SetData8(0x500c, 0x20);
506
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700507 const DwarfCie* cie = this->section_->GetCie(0x5000);
508 ASSERT_TRUE(cie != nullptr);
509 EXPECT_EQ(1U, cie->version);
510 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
511 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
512 EXPECT_EQ(0U, cie->segment_size);
513 EXPECT_EQ(1U, cie->augmentation_string.size());
514 EXPECT_EQ('\0', cie->augmentation_string[0]);
515 EXPECT_EQ(0U, cie->personality_handler);
516 EXPECT_EQ(0x500dU, cie->cfa_instructions_offset);
517 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
518 EXPECT_EQ(4U, cie->code_alignment_factor);
519 EXPECT_EQ(8, cie->data_alignment_factor);
520 EXPECT_EQ(0x20U, cie->return_address_register);
521 EXPECT_EQ(DWARF_ERROR_NONE, this->section_->last_error());
522
523 this->section_->TestClearCachedCieEntry();
524 // Set version to 0, 2, 5 and verify we fail.
525 this->memory_.SetData8(0x5008, 0x0);
526 this->section_->TestClearError();
527 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
528 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error());
529
530 this->memory_.SetData8(0x5008, 0x2);
531 this->section_->TestClearError();
532 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
533 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error());
534
535 this->memory_.SetData8(0x5008, 0x5);
536 this->section_->TestClearError();
537 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
538 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error());
539}
540
541TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) {
542 this->memory_.SetData32(0x5000, 0x100);
543 this->memory_.SetData32(0x5004, 0xffffffff);
544 this->memory_.SetData8(0x5008, 0x1);
545 this->memory_.SetData8(0x5009, '\0');
546 this->memory_.SetData8(0x500a, 4);
547 this->memory_.SetMemory(0x500b, std::vector<uint8_t>{0xfc, 0xff, 0xff, 0xff, 0x7f});
548 this->memory_.SetData8(0x5010, 0x20);
549
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700550 const DwarfCie* cie = this->section_->GetCie(0x5000);
551 ASSERT_TRUE(cie != nullptr);
552 EXPECT_EQ(1U, cie->version);
553 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
554 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
555 EXPECT_EQ(0U, cie->segment_size);
556 EXPECT_EQ(1U, cie->augmentation_string.size());
557 EXPECT_EQ('\0', cie->augmentation_string[0]);
558 EXPECT_EQ(0U, cie->personality_handler);
559 EXPECT_EQ(0x5011U, cie->cfa_instructions_offset);
560 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
561 EXPECT_EQ(4U, cie->code_alignment_factor);
562 EXPECT_EQ(-4, cie->data_alignment_factor);
563 EXPECT_EQ(0x20U, cie->return_address_register);
564}
565
566TYPED_TEST_P(DwarfSectionImplTest, GetCie_64_no_augment) {
567 this->memory_.SetData32(0x8000, 0xffffffff);
568 this->memory_.SetData64(0x8004, 0x200);
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700569 this->memory_.SetData64(0x800c, 0xffffffffffffffffULL);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700570 this->memory_.SetData8(0x8014, 0x1);
571 this->memory_.SetData8(0x8015, '\0');
572 this->memory_.SetData8(0x8016, 4);
573 this->memory_.SetData8(0x8017, 8);
574 this->memory_.SetData8(0x8018, 0x20);
575
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700576 const DwarfCie* cie = this->section_->GetCie(0x8000);
577 ASSERT_TRUE(cie != nullptr);
578 EXPECT_EQ(1U, cie->version);
579 EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding);
580 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
581 EXPECT_EQ(0U, cie->segment_size);
582 EXPECT_EQ(1U, cie->augmentation_string.size());
583 EXPECT_EQ('\0', cie->augmentation_string[0]);
584 EXPECT_EQ(0U, cie->personality_handler);
585 EXPECT_EQ(0x8019U, cie->cfa_instructions_offset);
586 EXPECT_EQ(0x820cU, cie->cfa_instructions_end);
587 EXPECT_EQ(4U, cie->code_alignment_factor);
588 EXPECT_EQ(8, cie->data_alignment_factor);
589 EXPECT_EQ(0x20U, cie->return_address_register);
590}
591
592TYPED_TEST_P(DwarfSectionImplTest, GetCie_augment) {
593 this->memory_.SetData32(0x5000, 0x100);
594 this->memory_.SetData32(0x5004, 0xffffffff);
595 this->memory_.SetData8(0x5008, 0x1);
596 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
597 this->memory_.SetData8(0x500e, 4);
598 this->memory_.SetData8(0x500f, 8);
599 this->memory_.SetData8(0x5010, 0x10);
600 // Augment length.
601 this->memory_.SetData8(0x5011, 0xf);
602 // L data.
603 this->memory_.SetData8(0x5012, DW_EH_PE_textrel | DW_EH_PE_udata2);
604 // P data.
605 this->memory_.SetData8(0x5013, DW_EH_PE_udata4);
606 this->memory_.SetData32(0x5014, 0x12345678);
607 // R data.
608 this->memory_.SetData8(0x5018, DW_EH_PE_udata2);
609
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700610 const DwarfCie* cie = this->section_->GetCie(0x5000);
611 ASSERT_TRUE(cie != nullptr);
612 EXPECT_EQ(1U, cie->version);
613 EXPECT_EQ(DW_EH_PE_udata2, cie->fde_address_encoding);
614 EXPECT_EQ(DW_EH_PE_textrel | DW_EH_PE_udata2, cie->lsda_encoding);
615 EXPECT_EQ(0U, cie->segment_size);
616 EXPECT_EQ(5U, cie->augmentation_string.size());
617 EXPECT_EQ('z', cie->augmentation_string[0]);
618 EXPECT_EQ('L', cie->augmentation_string[1]);
619 EXPECT_EQ('P', cie->augmentation_string[2]);
620 EXPECT_EQ('R', cie->augmentation_string[3]);
621 EXPECT_EQ('\0', cie->augmentation_string[4]);
622 EXPECT_EQ(0x12345678U, cie->personality_handler);
623 EXPECT_EQ(0x5021U, cie->cfa_instructions_offset);
624 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
625 EXPECT_EQ(4U, cie->code_alignment_factor);
626 EXPECT_EQ(8, cie->data_alignment_factor);
627 EXPECT_EQ(0x10U, cie->return_address_register);
628}
629
630TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_3) {
631 this->memory_.SetData32(0x5000, 0x100);
632 this->memory_.SetData32(0x5004, 0xffffffff);
633 this->memory_.SetData8(0x5008, 0x3);
634 this->memory_.SetData8(0x5009, '\0');
635 this->memory_.SetData8(0x500a, 4);
636 this->memory_.SetData8(0x500b, 8);
637 this->memory_.SetMemory(0x500c, std::vector<uint8_t>{0x81, 0x03});
638
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700639 const DwarfCie* cie = this->section_->GetCie(0x5000);
640 ASSERT_TRUE(cie != nullptr);
641 EXPECT_EQ(3U, cie->version);
642 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
643 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
644 EXPECT_EQ(0U, cie->segment_size);
645 EXPECT_EQ(1U, cie->augmentation_string.size());
646 EXPECT_EQ('\0', cie->augmentation_string[0]);
647 EXPECT_EQ(0U, cie->personality_handler);
648 EXPECT_EQ(0x500eU, cie->cfa_instructions_offset);
649 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
650 EXPECT_EQ(4U, cie->code_alignment_factor);
651 EXPECT_EQ(8, cie->data_alignment_factor);
652 EXPECT_EQ(0x181U, cie->return_address_register);
653}
654
655TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_4) {
656 this->memory_.SetData32(0x5000, 0x100);
657 this->memory_.SetData32(0x5004, 0xffffffff);
658 this->memory_.SetData8(0x5008, 0x4);
659 this->memory_.SetData8(0x5009, '\0');
660 this->memory_.SetData8(0x500a, 4);
661 this->memory_.SetData8(0x500b, 0x13);
662 this->memory_.SetData8(0x500c, 4);
663 this->memory_.SetData8(0x500d, 8);
664 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x81, 0x03});
665
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700666 const DwarfCie* cie = this->section_->GetCie(0x5000);
667 ASSERT_TRUE(cie != nullptr);
668 EXPECT_EQ(4U, cie->version);
669 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
670 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
671 EXPECT_EQ(0x13U, cie->segment_size);
672 EXPECT_EQ(1U, cie->augmentation_string.size());
673 EXPECT_EQ('\0', cie->augmentation_string[0]);
674 EXPECT_EQ(0U, cie->personality_handler);
675 EXPECT_EQ(0x5010U, cie->cfa_instructions_offset);
676 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
677 EXPECT_EQ(4U, cie->code_alignment_factor);
678 EXPECT_EQ(8, cie->data_alignment_factor);
679 EXPECT_EQ(0x181U, cie->return_address_register);
680}
681
682TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
683 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
684 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
685 this->section_->TestClearError();
686 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
687 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
688}
689
690TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) {
691 this->memory_.SetData32(0x4000, 0x20);
692 this->memory_.SetData32(0x4004, 0x8000);
693 this->memory_.SetData32(0x4008, 0x5000);
694 this->memory_.SetData32(0x400c, 0x100);
695
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700696 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
697 DwarfCie cie{};
698 cie.fde_address_encoding = DW_EH_PE_udata4;
699 this->section_->TestSetCachedCieEntry(0x8000, cie);
700 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
701
702 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
703 ASSERT_TRUE(fde != nullptr);
704 ASSERT_TRUE(fde->cie != nullptr);
705 EXPECT_EQ(0x4010U, fde->cfa_instructions_offset);
706 EXPECT_EQ(0x4024U, fde->cfa_instructions_end);
707 EXPECT_EQ(0x5000U, fde->pc_start);
708 EXPECT_EQ(0x5100U, fde->pc_end);
709 EXPECT_EQ(0x8000U, fde->cie_offset);
710 EXPECT_EQ(0U, fde->lsda_address);
711}
712
713TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment_non_zero_segment_size) {
714 this->memory_.SetData32(0x4000, 0x30);
715 this->memory_.SetData32(0x4004, 0x8000);
716 this->memory_.SetData32(0x4018, 0x5000);
717 this->memory_.SetData32(0x401c, 0x100);
718
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700719 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
720 DwarfCie cie{};
721 cie.fde_address_encoding = DW_EH_PE_udata4;
722 cie.segment_size = 0x10;
723 this->section_->TestSetCachedCieEntry(0x8000, cie);
724 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
725
726 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
727 ASSERT_TRUE(fde != nullptr);
728 ASSERT_TRUE(fde->cie != nullptr);
729 EXPECT_EQ(0x4020U, fde->cfa_instructions_offset);
730 EXPECT_EQ(0x4034U, fde->cfa_instructions_end);
731 EXPECT_EQ(0x5000U, fde->pc_start);
732 EXPECT_EQ(0x5100U, fde->pc_end);
733 EXPECT_EQ(0x8000U, fde->cie_offset);
734 EXPECT_EQ(0U, fde->lsda_address);
735}
736
737TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_augment) {
738 this->memory_.SetData32(0x4000, 0x100);
739 this->memory_.SetData32(0x4004, 0x8000);
740 this->memory_.SetData32(0x4008, 0x5000);
741 this->memory_.SetData32(0x400c, 0x100);
742 this->memory_.SetMemory(0x4010, std::vector<uint8_t>{0x82, 0x01});
743 this->memory_.SetData16(0x4012, 0x1234);
744
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700745 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
746 DwarfCie cie{};
747 cie.fde_address_encoding = DW_EH_PE_udata4;
748 cie.augmentation_string.push_back('z');
749 cie.lsda_encoding = DW_EH_PE_udata2;
750 this->section_->TestSetCachedCieEntry(0x8000, cie);
751 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
752
753 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
754 ASSERT_TRUE(fde != nullptr);
755 ASSERT_TRUE(fde->cie != nullptr);
756 EXPECT_EQ(0x4094U, fde->cfa_instructions_offset);
757 EXPECT_EQ(0x4104U, fde->cfa_instructions_end);
758 EXPECT_EQ(0x5000U, fde->pc_start);
759 EXPECT_EQ(0x5100U, fde->pc_end);
760 EXPECT_EQ(0x8000U, fde->cie_offset);
761 EXPECT_EQ(0x1234U, fde->lsda_address);
762}
763
764TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_64_no_augment) {
765 this->memory_.SetData32(0x4000, 0xffffffff);
766 this->memory_.SetData64(0x4004, 0x100);
767 this->memory_.SetData64(0x400c, 0x12345678);
768 this->memory_.SetData32(0x4014, 0x5000);
769 this->memory_.SetData32(0x4018, 0x100);
770
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700771 EXPECT_CALL(*this->section_, GetCieOffsetFromFde64(0x12345678))
772 .WillOnce(::testing::Return(0x12345678));
773 DwarfCie cie{};
774 cie.fde_address_encoding = DW_EH_PE_udata4;
775 this->section_->TestSetCachedCieEntry(0x12345678, cie);
776 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
777
778 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
779 ASSERT_TRUE(fde != nullptr);
780 ASSERT_TRUE(fde->cie != nullptr);
781 EXPECT_EQ(0x401cU, fde->cfa_instructions_offset);
782 EXPECT_EQ(0x410cU, fde->cfa_instructions_end);
783 EXPECT_EQ(0x5000U, fde->pc_start);
784 EXPECT_EQ(0x5100U, fde->pc_end);
785 EXPECT_EQ(0x12345678U, fde->cie_offset);
786 EXPECT_EQ(0U, fde->lsda_address);
787}
788
789TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_cached) {
790 DwarfCie cie{};
791 cie.fde_address_encoding = DW_EH_PE_udata4;
792 cie.augmentation_string.push_back('z');
793 cie.lsda_encoding = DW_EH_PE_udata2;
794
795 DwarfFde fde_cached{};
796 fde_cached.cfa_instructions_offset = 0x1000;
797 fde_cached.cfa_instructions_end = 0x1100;
798 fde_cached.pc_start = 0x9000;
799 fde_cached.pc_end = 0x9400;
800 fde_cached.cie_offset = 0x30000;
801 fde_cached.cie = &cie;
802 this->section_->TestSetCachedFdeEntry(0x6000, fde_cached);
803
804 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x6000);
805 ASSERT_TRUE(fde != nullptr);
806 ASSERT_EQ(&cie, fde->cie);
807 EXPECT_EQ(0x1000U, fde->cfa_instructions_offset);
808 EXPECT_EQ(0x1100U, fde->cfa_instructions_end);
809 EXPECT_EQ(0x9000U, fde->pc_start);
810 EXPECT_EQ(0x9400U, fde->pc_end);
811 EXPECT_EQ(0x30000U, fde->cie_offset);
812}
813
814TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
815 DwarfCie cie{};
816 cie.cfa_instructions_offset = 0x3000;
817 cie.cfa_instructions_end = 0x3002;
818 DwarfFde fde{};
819 fde.cie = &cie;
820 fde.cie_offset = 0x8000;
821 fde.cfa_instructions_offset = 0x6000;
822 fde.cfa_instructions_end = 0x6002;
823
824 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x09, 0x02, 0x01});
825 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
826
827 dwarf_loc_regs_t loc_regs;
828 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
829 ASSERT_EQ(2U, loc_regs.size());
830
831 auto entry = loc_regs.find(2);
832 ASSERT_NE(entry, loc_regs.end());
833 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
834 ASSERT_EQ(1U, entry->second.values[0]);
835
836 entry = loc_regs.find(4);
837 ASSERT_NE(entry, loc_regs.end());
838 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
839 ASSERT_EQ(3U, entry->second.values[0]);
840}
841
842TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) {
843 DwarfCie cie{};
844 cie.cfa_instructions_offset = 0x3000;
845 cie.cfa_instructions_end = 0x3002;
846 DwarfFde fde{};
847 fde.cie = &cie;
848 fde.cie_offset = 0x8000;
849 fde.cfa_instructions_offset = 0x6000;
850 fde.cfa_instructions_end = 0x6002;
851
852 dwarf_loc_regs_t cie_loc_regs{{6, {DWARF_LOCATION_REGISTER, {4, 0}}}};
853 this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs);
854 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
855
856 dwarf_loc_regs_t loc_regs;
857 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
858 ASSERT_EQ(2U, loc_regs.size());
859
860 auto entry = loc_regs.find(6);
861 ASSERT_NE(entry, loc_regs.end());
862 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
863 ASSERT_EQ(4U, entry->second.values[0]);
864
865 entry = loc_regs.find(4);
866 ASSERT_NE(entry, loc_regs.end());
867 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
868 ASSERT_EQ(3U, entry->second.values[0]);
869}
870
871TYPED_TEST_P(DwarfSectionImplTest, Log) {
872 DwarfCie cie{};
873 cie.cfa_instructions_offset = 0x5000;
874 cie.cfa_instructions_end = 0x5001;
875 DwarfFde fde{};
876 fde.cie = &cie;
877 fde.cfa_instructions_offset = 0x6000;
878 fde.cfa_instructions_end = 0x6001;
879
880 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00});
881 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2});
882 ASSERT_TRUE(this->section_->Log(2, 0x1000, 0x1000, &fde));
883
884 ASSERT_EQ(
885 "4 unwind DW_CFA_nop\n"
886 "4 unwind Raw Data: 0x00\n"
887 "4 unwind DW_CFA_restore register(2)\n"
888 "4 unwind Raw Data: 0xc2\n",
889 GetFakeLogPrint());
890 ASSERT_EQ("", GetFakeLogBuf());
891}
892
893REGISTER_TYPED_TEST_CASE_P(
894 DwarfSectionImplTest, Eval_cfa_expr_eval_fail, Eval_cfa_expr_no_stack,
895 Eval_cfa_expr_is_register, Eval_cfa_expr, Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa,
896 Eval_cfa_bad, Eval_cfa_register_prev, Eval_cfa_register_from_value, Eval_double_indirection,
Christopher Ferris98984b42018-01-17 12:59:45 -0800897 Eval_register_reference_chain, Eval_dex_pc, Eval_invalid_register, Eval_different_reg_locations,
898 Eval_return_address_undefined, Eval_pc_zero, Eval_return_address, Eval_ignore_large_reg_loc,
899 Eval_reg_expr, Eval_reg_val_expr, GetCie_fail_should_not_cache, GetCie_32_version_check,
900 GetCie_negative_data_alignment_factor, GetCie_64_no_augment, GetCie_augment, GetCie_version_3,
901 GetCie_version_4, GetFdeFromOffset_fail_should_not_cache, GetFdeFromOffset_32_no_augment,
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700902 GetFdeFromOffset_32_no_augment_non_zero_segment_size, GetFdeFromOffset_32_augment,
903 GetFdeFromOffset_64_no_augment, GetFdeFromOffset_cached, GetCfaLocationInfo_cie_not_cached,
904 GetCfaLocationInfo_cie_cached, Log);
905
906typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
907INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes);
Christopher Ferrisd226a512017-07-14 10:37:19 -0700908
909} // namespace unwindstack