blob: b8715399522dd9da8983b56eb6abafb457ab8580 [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
45 MOCK_METHOD1(IsCie32, bool(uint32_t));
46
47 MOCK_METHOD1(IsCie64, bool(uint64_t));
48
49 MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t));
50
51 MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t));
52
53 MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t));
54
55 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();
80 }
81
82 void TearDown() override { delete section_; }
83
84 MemoryFake memory_;
85 MockDwarfSectionImpl<TypeParam>* section_ = nullptr;
86};
87TYPED_TEST_CASE_P(DwarfSectionImplTest);
88
89// NOTE: All test class variables need to be referenced as this->.
90
91TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
92 DwarfCie cie{.version = 3, .return_address_register = 5};
93 RegsFake<TypeParam> regs(10, 9);
94 dwarf_loc_regs_t loc_regs;
95
96 regs.set_pc(0x100);
97 regs.set_sp(0x2000);
98 regs[5] = 0x20;
99 regs[9] = 0x3000;
100 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
101 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
102 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
103}
104
105TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
106 DwarfCie cie{.version = 3, .return_address_register = 5};
107 RegsFake<TypeParam> regs(10, 9);
108 dwarf_loc_regs_t loc_regs;
109
110 regs.set_pc(0x100);
111 regs.set_sp(0x2000);
112 regs[5] = 0x20;
113 regs[9] = 0x3000;
114 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
115 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
116 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
117 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error());
118}
119
120TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
121 DwarfCie cie{.version = 3, .return_address_register = 5};
122 RegsFake<TypeParam> regs(10, 9);
123 dwarf_loc_regs_t loc_regs;
124
125 regs.set_pc(0x100);
126 regs.set_sp(0x2000);
127 regs[5] = 0x20;
128 regs[9] = 0x3000;
129 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
130 TypeParam cfa_value = 0x12345;
131 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
132 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}};
133 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
134 EXPECT_EQ(0x12345U, regs.sp());
135 EXPECT_EQ(0x20U, regs.pc());
136}
137
138TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
139 DwarfCie cie{.version = 3, .return_address_register = 5};
140 RegsFake<TypeParam> regs(10, 9);
141 dwarf_loc_regs_t loc_regs;
142
143 regs.set_pc(0x100);
144 regs.set_sp(0x2000);
145 regs[5] = 0x20;
146 regs[9] = 0x3000;
147 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
148 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}};
149 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
150 EXPECT_EQ(0x80000000U, regs.sp());
151 EXPECT_EQ(0x20U, regs.pc());
152}
153
154TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
155 DwarfCie cie{.version = 3, .return_address_register = 5};
156 RegsFake<TypeParam> regs(10, 9);
157 dwarf_loc_regs_t loc_regs;
158
159 regs.set_pc(0x100);
160 regs.set_sp(0x2000);
161 regs[5] = 0x20;
162 regs[9] = 0x3000;
163 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
164 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
165 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
166 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->last_error());
167}
168
169TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
170 DwarfCie cie{.return_address_register = 60};
171 RegsFake<TypeParam> regs(10, 9);
172 dwarf_loc_regs_t loc_regs;
173
174 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
175 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
176}
177
178TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
179 DwarfCie cie{.return_address_register = 5};
180 RegsFake<TypeParam> regs(10, 9);
181 dwarf_loc_regs_t loc_regs;
182
183 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
184 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->last_error());
185}
186
187TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
188 DwarfCie cie{.return_address_register = 5};
189 RegsFake<TypeParam> regs(10, 9);
190 dwarf_loc_regs_t loc_regs;
191
192 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
193 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
194 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
195
196 this->section_->TestClearError();
197 loc_regs.erase(CFA_REG);
198 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
199 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
200 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
201
202 this->section_->TestClearError();
203 loc_regs.erase(CFA_REG);
204 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
205 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
206 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_VAL_OFFSET, {0, 0}};
211 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
212 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
213}
214
215TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
216 DwarfCie cie{.return_address_register = 5};
217 RegsFake<TypeParam> regs(10, 9);
218 dwarf_loc_regs_t loc_regs;
219
220 regs.set_pc(0x100);
221 regs.set_sp(0x2000);
222 regs[5] = 0x20;
223 regs[9] = 0x3000;
224 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}};
225 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
226 EXPECT_EQ(0x20U, regs.pc());
227 EXPECT_EQ(0x2000U, regs.sp());
228}
229
230TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
231 DwarfCie cie{.return_address_register = 5};
232 RegsFake<TypeParam> regs(10, 9);
233 dwarf_loc_regs_t loc_regs;
234
235 regs.set_pc(0x100);
236 regs.set_sp(0x2000);
237 regs[5] = 0x20;
238 regs[6] = 0x4000;
239 regs[9] = 0x3000;
240 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}};
241 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
242 EXPECT_EQ(0x20U, regs.pc());
243 EXPECT_EQ(0x4000U, regs.sp());
244}
245
246TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
247 DwarfCie cie{.return_address_register = 5};
248 RegsFake<TypeParam> regs(10, 9);
249 dwarf_loc_regs_t loc_regs;
250
251 regs.set_pc(0x100);
252 regs.set_sp(0x2000);
253 regs[8] = 0x10;
254 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
255 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 0}};
256 loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 0}};
257 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
258 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error());
259}
260
261TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
262 DwarfCie cie{.return_address_register = 5};
263 RegsFake<TypeParam> regs(10, 9);
264 dwarf_loc_regs_t loc_regs;
265
266 regs.set_pc(0x100);
267 regs.set_sp(0x2000);
268 regs[8] = 0x10;
269 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
270 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
271 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
272 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
273}
274
275TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
276 DwarfCie cie{.return_address_register = 5};
277 RegsFake<TypeParam> regs(10, 9);
278 dwarf_loc_regs_t loc_regs;
279
280 if (sizeof(TypeParam) == sizeof(uint64_t)) {
281 this->memory_.SetData64(0x2150, 0x12345678abcdef00ULL);
282 } else {
283 this->memory_.SetData32(0x2150, 0x12345678);
284 }
285
286 regs.set_pc(0x100);
287 regs.set_sp(0x2000);
288 regs[3] = 0x234;
289 regs[5] = 0x10;
290 regs[8] = 0x2100;
291 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
292 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}};
293 loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}};
294 loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
295 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
296 EXPECT_EQ(0x10U, regs.pc());
297 EXPECT_EQ(0x2100U, regs.sp());
298 EXPECT_EQ(0x2200U, regs[1]);
299 EXPECT_EQ(0x234U, regs[3]);
300 if (sizeof(TypeParam) == sizeof(uint64_t)) {
301 EXPECT_EQ(0x12345678abcdef00ULL, regs[2]);
302 } else {
303 EXPECT_EQ(0x12345678U, regs[2]);
304 }
305}
306
307TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
308 DwarfCie cie{.return_address_register = 5};
309 RegsFake<TypeParam> regs(10, 9);
310 dwarf_loc_regs_t loc_regs;
311
312 regs.set_pc(0x100);
313 regs.set_sp(0x2000);
314 regs[5] = 0x20;
315 regs[8] = 0x10;
316 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
317 loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
318 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
319 EXPECT_EQ(0U, regs.pc());
320 EXPECT_EQ(0x10U, regs.sp());
321}
322
323TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
324 DwarfCie cie{.return_address_register = 5};
325 RegsFake<TypeParam> regs(10, 9);
326 dwarf_loc_regs_t loc_regs;
327
328 regs.set_pc(0x100);
329 regs.set_sp(0x2000);
330 regs[5] = 0x20;
331 regs[8] = 0x10;
332 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
333 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
334 EXPECT_EQ(0x20U, regs.pc());
335 EXPECT_EQ(0x10U, regs.sp());
336}
337
338TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
339 DwarfCie cie{.return_address_register = 5};
340 RegsFake<TypeParam> regs(10, 9);
341 dwarf_loc_regs_t loc_regs;
342
343 regs.set_pc(0x100);
344 regs.set_sp(0x2000);
345 regs[5] = 0x20;
346 regs[8] = 0x10;
347 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
348 // This should not result in any errors.
349 loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
350 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
351 EXPECT_EQ(0x20U, regs.pc());
352 EXPECT_EQ(0x10U, regs.sp());
353}
354
355TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
356 DwarfCie cie{.version = 3, .return_address_register = 5};
357 RegsFake<TypeParam> regs(10, 9);
358 dwarf_loc_regs_t loc_regs;
359
360 regs.set_pc(0x100);
361 regs.set_sp(0x2000);
362 regs[8] = 0x3000;
363 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
364 TypeParam cfa_value = 0x12345;
365 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
366 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
367 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}};
368 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
369 EXPECT_EQ(0x3000U, regs.sp());
370 EXPECT_EQ(0x12345U, regs.pc());
371}
372
373TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
374 DwarfCie cie{.version = 3, .return_address_register = 5};
375 RegsFake<TypeParam> regs(10, 9);
376 dwarf_loc_regs_t loc_regs;
377
378 regs.set_pc(0x100);
379 regs.set_sp(0x2000);
380 regs[8] = 0x3000;
381 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
382 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
383 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}};
384 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
385 EXPECT_EQ(0x3000U, regs.sp());
386 EXPECT_EQ(0x80000000U, regs.pc());
387}
388
389TYPED_TEST_P(DwarfSectionImplTest, Eval_same_cfa_same_pc) {
390 DwarfCie cie{.version = 3, .return_address_register = 5};
391 RegsFake<TypeParam> regs(10, 9);
392 dwarf_loc_regs_t loc_regs;
393
394 regs.set_pc(0x100);
395 regs.set_sp(0x2000);
396 regs[5] = 0x100;
397 regs[8] = 0x2000;
398 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
399 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs));
400 EXPECT_EQ(0x2000U, regs.sp());
401 EXPECT_EQ(0x100U, regs.pc());
402}
403
404TYPED_TEST_P(DwarfSectionImplTest, GetCie_fail_should_not_cache) {
405 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
406 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
407 this->section_->TestClearError();
408 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
409 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
410}
411
412TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) {
413 this->memory_.SetData32(0x5000, 0x100);
414 this->memory_.SetData32(0x5004, 0xffffffff);
415 this->memory_.SetData8(0x5008, 0x1);
416 this->memory_.SetData8(0x5009, '\0');
417 this->memory_.SetData8(0x500a, 4);
418 this->memory_.SetData8(0x500b, 8);
419 this->memory_.SetData8(0x500c, 0x20);
420
421 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
422
423 const DwarfCie* cie = this->section_->GetCie(0x5000);
424 ASSERT_TRUE(cie != nullptr);
425 EXPECT_EQ(1U, cie->version);
426 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
427 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
428 EXPECT_EQ(0U, cie->segment_size);
429 EXPECT_EQ(1U, cie->augmentation_string.size());
430 EXPECT_EQ('\0', cie->augmentation_string[0]);
431 EXPECT_EQ(0U, cie->personality_handler);
432 EXPECT_EQ(0x500dU, cie->cfa_instructions_offset);
433 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
434 EXPECT_EQ(4U, cie->code_alignment_factor);
435 EXPECT_EQ(8, cie->data_alignment_factor);
436 EXPECT_EQ(0x20U, cie->return_address_register);
437 EXPECT_EQ(DWARF_ERROR_NONE, this->section_->last_error());
438
439 this->section_->TestClearCachedCieEntry();
440 // Set version to 0, 2, 5 and verify we fail.
441 this->memory_.SetData8(0x5008, 0x0);
442 this->section_->TestClearError();
443 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
444 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error());
445
446 this->memory_.SetData8(0x5008, 0x2);
447 this->section_->TestClearError();
448 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
449 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error());
450
451 this->memory_.SetData8(0x5008, 0x5);
452 this->section_->TestClearError();
453 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
454 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error());
455}
456
457TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) {
458 this->memory_.SetData32(0x5000, 0x100);
459 this->memory_.SetData32(0x5004, 0xffffffff);
460 this->memory_.SetData8(0x5008, 0x1);
461 this->memory_.SetData8(0x5009, '\0');
462 this->memory_.SetData8(0x500a, 4);
463 this->memory_.SetMemory(0x500b, std::vector<uint8_t>{0xfc, 0xff, 0xff, 0xff, 0x7f});
464 this->memory_.SetData8(0x5010, 0x20);
465
466 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
467
468 const DwarfCie* cie = this->section_->GetCie(0x5000);
469 ASSERT_TRUE(cie != nullptr);
470 EXPECT_EQ(1U, cie->version);
471 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
472 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
473 EXPECT_EQ(0U, cie->segment_size);
474 EXPECT_EQ(1U, cie->augmentation_string.size());
475 EXPECT_EQ('\0', cie->augmentation_string[0]);
476 EXPECT_EQ(0U, cie->personality_handler);
477 EXPECT_EQ(0x5011U, cie->cfa_instructions_offset);
478 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
479 EXPECT_EQ(4U, cie->code_alignment_factor);
480 EXPECT_EQ(-4, cie->data_alignment_factor);
481 EXPECT_EQ(0x20U, cie->return_address_register);
482}
483
484TYPED_TEST_P(DwarfSectionImplTest, GetCie_64_no_augment) {
485 this->memory_.SetData32(0x8000, 0xffffffff);
486 this->memory_.SetData64(0x8004, 0x200);
487 this->memory_.SetData64(0x800c, 0xffffffff);
488 this->memory_.SetData8(0x8014, 0x1);
489 this->memory_.SetData8(0x8015, '\0');
490 this->memory_.SetData8(0x8016, 4);
491 this->memory_.SetData8(0x8017, 8);
492 this->memory_.SetData8(0x8018, 0x20);
493
494 EXPECT_CALL(*this->section_, IsCie64(0xffffffff)).WillRepeatedly(::testing::Return(true));
495
496 const DwarfCie* cie = this->section_->GetCie(0x8000);
497 ASSERT_TRUE(cie != nullptr);
498 EXPECT_EQ(1U, cie->version);
499 EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding);
500 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
501 EXPECT_EQ(0U, cie->segment_size);
502 EXPECT_EQ(1U, cie->augmentation_string.size());
503 EXPECT_EQ('\0', cie->augmentation_string[0]);
504 EXPECT_EQ(0U, cie->personality_handler);
505 EXPECT_EQ(0x8019U, cie->cfa_instructions_offset);
506 EXPECT_EQ(0x820cU, cie->cfa_instructions_end);
507 EXPECT_EQ(4U, cie->code_alignment_factor);
508 EXPECT_EQ(8, cie->data_alignment_factor);
509 EXPECT_EQ(0x20U, cie->return_address_register);
510}
511
512TYPED_TEST_P(DwarfSectionImplTest, GetCie_augment) {
513 this->memory_.SetData32(0x5000, 0x100);
514 this->memory_.SetData32(0x5004, 0xffffffff);
515 this->memory_.SetData8(0x5008, 0x1);
516 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
517 this->memory_.SetData8(0x500e, 4);
518 this->memory_.SetData8(0x500f, 8);
519 this->memory_.SetData8(0x5010, 0x10);
520 // Augment length.
521 this->memory_.SetData8(0x5011, 0xf);
522 // L data.
523 this->memory_.SetData8(0x5012, DW_EH_PE_textrel | DW_EH_PE_udata2);
524 // P data.
525 this->memory_.SetData8(0x5013, DW_EH_PE_udata4);
526 this->memory_.SetData32(0x5014, 0x12345678);
527 // R data.
528 this->memory_.SetData8(0x5018, DW_EH_PE_udata2);
529
530 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
531
532 const DwarfCie* cie = this->section_->GetCie(0x5000);
533 ASSERT_TRUE(cie != nullptr);
534 EXPECT_EQ(1U, cie->version);
535 EXPECT_EQ(DW_EH_PE_udata2, cie->fde_address_encoding);
536 EXPECT_EQ(DW_EH_PE_textrel | DW_EH_PE_udata2, cie->lsda_encoding);
537 EXPECT_EQ(0U, cie->segment_size);
538 EXPECT_EQ(5U, cie->augmentation_string.size());
539 EXPECT_EQ('z', cie->augmentation_string[0]);
540 EXPECT_EQ('L', cie->augmentation_string[1]);
541 EXPECT_EQ('P', cie->augmentation_string[2]);
542 EXPECT_EQ('R', cie->augmentation_string[3]);
543 EXPECT_EQ('\0', cie->augmentation_string[4]);
544 EXPECT_EQ(0x12345678U, cie->personality_handler);
545 EXPECT_EQ(0x5021U, cie->cfa_instructions_offset);
546 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
547 EXPECT_EQ(4U, cie->code_alignment_factor);
548 EXPECT_EQ(8, cie->data_alignment_factor);
549 EXPECT_EQ(0x10U, cie->return_address_register);
550}
551
552TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_3) {
553 this->memory_.SetData32(0x5000, 0x100);
554 this->memory_.SetData32(0x5004, 0xffffffff);
555 this->memory_.SetData8(0x5008, 0x3);
556 this->memory_.SetData8(0x5009, '\0');
557 this->memory_.SetData8(0x500a, 4);
558 this->memory_.SetData8(0x500b, 8);
559 this->memory_.SetMemory(0x500c, std::vector<uint8_t>{0x81, 0x03});
560
561 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
562
563 const DwarfCie* cie = this->section_->GetCie(0x5000);
564 ASSERT_TRUE(cie != nullptr);
565 EXPECT_EQ(3U, cie->version);
566 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
567 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
568 EXPECT_EQ(0U, cie->segment_size);
569 EXPECT_EQ(1U, cie->augmentation_string.size());
570 EXPECT_EQ('\0', cie->augmentation_string[0]);
571 EXPECT_EQ(0U, cie->personality_handler);
572 EXPECT_EQ(0x500eU, cie->cfa_instructions_offset);
573 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
574 EXPECT_EQ(4U, cie->code_alignment_factor);
575 EXPECT_EQ(8, cie->data_alignment_factor);
576 EXPECT_EQ(0x181U, cie->return_address_register);
577}
578
579TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_4) {
580 this->memory_.SetData32(0x5000, 0x100);
581 this->memory_.SetData32(0x5004, 0xffffffff);
582 this->memory_.SetData8(0x5008, 0x4);
583 this->memory_.SetData8(0x5009, '\0');
584 this->memory_.SetData8(0x500a, 4);
585 this->memory_.SetData8(0x500b, 0x13);
586 this->memory_.SetData8(0x500c, 4);
587 this->memory_.SetData8(0x500d, 8);
588 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x81, 0x03});
589
590 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
591
592 const DwarfCie* cie = this->section_->GetCie(0x5000);
593 ASSERT_TRUE(cie != nullptr);
594 EXPECT_EQ(4U, cie->version);
595 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
596 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
597 EXPECT_EQ(0x13U, cie->segment_size);
598 EXPECT_EQ(1U, cie->augmentation_string.size());
599 EXPECT_EQ('\0', cie->augmentation_string[0]);
600 EXPECT_EQ(0U, cie->personality_handler);
601 EXPECT_EQ(0x5010U, cie->cfa_instructions_offset);
602 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
603 EXPECT_EQ(4U, cie->code_alignment_factor);
604 EXPECT_EQ(8, cie->data_alignment_factor);
605 EXPECT_EQ(0x181U, cie->return_address_register);
606}
607
608TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
609 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
610 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
611 this->section_->TestClearError();
612 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
613 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
614}
615
616TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) {
617 this->memory_.SetData32(0x4000, 0x20);
618 this->memory_.SetData32(0x4004, 0x8000);
619 this->memory_.SetData32(0x4008, 0x5000);
620 this->memory_.SetData32(0x400c, 0x100);
621
622 EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false));
623 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
624 DwarfCie cie{};
625 cie.fde_address_encoding = DW_EH_PE_udata4;
626 this->section_->TestSetCachedCieEntry(0x8000, cie);
627 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
628
629 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
630 ASSERT_TRUE(fde != nullptr);
631 ASSERT_TRUE(fde->cie != nullptr);
632 EXPECT_EQ(0x4010U, fde->cfa_instructions_offset);
633 EXPECT_EQ(0x4024U, fde->cfa_instructions_end);
634 EXPECT_EQ(0x5000U, fde->pc_start);
635 EXPECT_EQ(0x5100U, fde->pc_end);
636 EXPECT_EQ(0x8000U, fde->cie_offset);
637 EXPECT_EQ(0U, fde->lsda_address);
638}
639
640TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment_non_zero_segment_size) {
641 this->memory_.SetData32(0x4000, 0x30);
642 this->memory_.SetData32(0x4004, 0x8000);
643 this->memory_.SetData32(0x4018, 0x5000);
644 this->memory_.SetData32(0x401c, 0x100);
645
646 EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false));
647 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
648 DwarfCie cie{};
649 cie.fde_address_encoding = DW_EH_PE_udata4;
650 cie.segment_size = 0x10;
651 this->section_->TestSetCachedCieEntry(0x8000, cie);
652 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
653
654 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
655 ASSERT_TRUE(fde != nullptr);
656 ASSERT_TRUE(fde->cie != nullptr);
657 EXPECT_EQ(0x4020U, fde->cfa_instructions_offset);
658 EXPECT_EQ(0x4034U, fde->cfa_instructions_end);
659 EXPECT_EQ(0x5000U, fde->pc_start);
660 EXPECT_EQ(0x5100U, fde->pc_end);
661 EXPECT_EQ(0x8000U, fde->cie_offset);
662 EXPECT_EQ(0U, fde->lsda_address);
663}
664
665TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_augment) {
666 this->memory_.SetData32(0x4000, 0x100);
667 this->memory_.SetData32(0x4004, 0x8000);
668 this->memory_.SetData32(0x4008, 0x5000);
669 this->memory_.SetData32(0x400c, 0x100);
670 this->memory_.SetMemory(0x4010, std::vector<uint8_t>{0x82, 0x01});
671 this->memory_.SetData16(0x4012, 0x1234);
672
673 EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false));
674 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
675 DwarfCie cie{};
676 cie.fde_address_encoding = DW_EH_PE_udata4;
677 cie.augmentation_string.push_back('z');
678 cie.lsda_encoding = DW_EH_PE_udata2;
679 this->section_->TestSetCachedCieEntry(0x8000, cie);
680 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
681
682 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
683 ASSERT_TRUE(fde != nullptr);
684 ASSERT_TRUE(fde->cie != nullptr);
685 EXPECT_EQ(0x4094U, fde->cfa_instructions_offset);
686 EXPECT_EQ(0x4104U, fde->cfa_instructions_end);
687 EXPECT_EQ(0x5000U, fde->pc_start);
688 EXPECT_EQ(0x5100U, fde->pc_end);
689 EXPECT_EQ(0x8000U, fde->cie_offset);
690 EXPECT_EQ(0x1234U, fde->lsda_address);
691}
692
693TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_64_no_augment) {
694 this->memory_.SetData32(0x4000, 0xffffffff);
695 this->memory_.SetData64(0x4004, 0x100);
696 this->memory_.SetData64(0x400c, 0x12345678);
697 this->memory_.SetData32(0x4014, 0x5000);
698 this->memory_.SetData32(0x4018, 0x100);
699
700 EXPECT_CALL(*this->section_, IsCie64(0x12345678)).WillOnce(::testing::Return(false));
701 EXPECT_CALL(*this->section_, GetCieOffsetFromFde64(0x12345678))
702 .WillOnce(::testing::Return(0x12345678));
703 DwarfCie cie{};
704 cie.fde_address_encoding = DW_EH_PE_udata4;
705 this->section_->TestSetCachedCieEntry(0x12345678, 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(0x401cU, fde->cfa_instructions_offset);
712 EXPECT_EQ(0x410cU, fde->cfa_instructions_end);
713 EXPECT_EQ(0x5000U, fde->pc_start);
714 EXPECT_EQ(0x5100U, fde->pc_end);
715 EXPECT_EQ(0x12345678U, fde->cie_offset);
716 EXPECT_EQ(0U, fde->lsda_address);
717}
718
719TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_cached) {
720 DwarfCie cie{};
721 cie.fde_address_encoding = DW_EH_PE_udata4;
722 cie.augmentation_string.push_back('z');
723 cie.lsda_encoding = DW_EH_PE_udata2;
724
725 DwarfFde fde_cached{};
726 fde_cached.cfa_instructions_offset = 0x1000;
727 fde_cached.cfa_instructions_end = 0x1100;
728 fde_cached.pc_start = 0x9000;
729 fde_cached.pc_end = 0x9400;
730 fde_cached.cie_offset = 0x30000;
731 fde_cached.cie = &cie;
732 this->section_->TestSetCachedFdeEntry(0x6000, fde_cached);
733
734 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x6000);
735 ASSERT_TRUE(fde != nullptr);
736 ASSERT_EQ(&cie, fde->cie);
737 EXPECT_EQ(0x1000U, fde->cfa_instructions_offset);
738 EXPECT_EQ(0x1100U, fde->cfa_instructions_end);
739 EXPECT_EQ(0x9000U, fde->pc_start);
740 EXPECT_EQ(0x9400U, fde->pc_end);
741 EXPECT_EQ(0x30000U, fde->cie_offset);
742}
743
744TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
745 DwarfCie cie{};
746 cie.cfa_instructions_offset = 0x3000;
747 cie.cfa_instructions_end = 0x3002;
748 DwarfFde fde{};
749 fde.cie = &cie;
750 fde.cie_offset = 0x8000;
751 fde.cfa_instructions_offset = 0x6000;
752 fde.cfa_instructions_end = 0x6002;
753
754 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x09, 0x02, 0x01});
755 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
756
757 dwarf_loc_regs_t loc_regs;
758 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
759 ASSERT_EQ(2U, loc_regs.size());
760
761 auto entry = loc_regs.find(2);
762 ASSERT_NE(entry, loc_regs.end());
763 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
764 ASSERT_EQ(1U, entry->second.values[0]);
765
766 entry = loc_regs.find(4);
767 ASSERT_NE(entry, loc_regs.end());
768 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
769 ASSERT_EQ(3U, entry->second.values[0]);
770}
771
772TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) {
773 DwarfCie cie{};
774 cie.cfa_instructions_offset = 0x3000;
775 cie.cfa_instructions_end = 0x3002;
776 DwarfFde fde{};
777 fde.cie = &cie;
778 fde.cie_offset = 0x8000;
779 fde.cfa_instructions_offset = 0x6000;
780 fde.cfa_instructions_end = 0x6002;
781
782 dwarf_loc_regs_t cie_loc_regs{{6, {DWARF_LOCATION_REGISTER, {4, 0}}}};
783 this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs);
784 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
785
786 dwarf_loc_regs_t loc_regs;
787 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
788 ASSERT_EQ(2U, loc_regs.size());
789
790 auto entry = loc_regs.find(6);
791 ASSERT_NE(entry, loc_regs.end());
792 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
793 ASSERT_EQ(4U, entry->second.values[0]);
794
795 entry = loc_regs.find(4);
796 ASSERT_NE(entry, loc_regs.end());
797 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
798 ASSERT_EQ(3U, entry->second.values[0]);
799}
800
801TYPED_TEST_P(DwarfSectionImplTest, Log) {
802 DwarfCie cie{};
803 cie.cfa_instructions_offset = 0x5000;
804 cie.cfa_instructions_end = 0x5001;
805 DwarfFde fde{};
806 fde.cie = &cie;
807 fde.cfa_instructions_offset = 0x6000;
808 fde.cfa_instructions_end = 0x6001;
809
810 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00});
811 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2});
812 ASSERT_TRUE(this->section_->Log(2, 0x1000, 0x1000, &fde));
813
814 ASSERT_EQ(
815 "4 unwind DW_CFA_nop\n"
816 "4 unwind Raw Data: 0x00\n"
817 "4 unwind DW_CFA_restore register(2)\n"
818 "4 unwind Raw Data: 0xc2\n",
819 GetFakeLogPrint());
820 ASSERT_EQ("", GetFakeLogBuf());
821}
822
823REGISTER_TYPED_TEST_CASE_P(
824 DwarfSectionImplTest, Eval_cfa_expr_eval_fail, Eval_cfa_expr_no_stack,
825 Eval_cfa_expr_is_register, Eval_cfa_expr, Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa,
826 Eval_cfa_bad, Eval_cfa_register_prev, Eval_cfa_register_from_value, Eval_double_indirection,
827 Eval_invalid_register, Eval_different_reg_locations, Eval_return_address_undefined,
828 Eval_return_address, Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
829 Eval_same_cfa_same_pc, GetCie_fail_should_not_cache, GetCie_32_version_check,
830 GetCie_negative_data_alignment_factor, GetCie_64_no_augment, GetCie_augment, GetCie_version_3,
831 GetCie_version_4, GetFdeFromOffset_fail_should_not_cache, GetFdeFromOffset_32_no_augment,
832 GetFdeFromOffset_32_no_augment_non_zero_segment_size, GetFdeFromOffset_32_augment,
833 GetFdeFromOffset_64_no_augment, GetFdeFromOffset_cached, GetCfaLocationInfo_cie_not_cached,
834 GetCfaLocationInfo_cie_cached, Log);
835
836typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
837INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes);
Christopher Ferrisd226a512017-07-14 10:37:19 -0700838
839} // namespace unwindstack