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