blob: 7e85bbbf83c6a1c65900637507738f91fa13e121 [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};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070093 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070094 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}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700101 bool finished;
102 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700103 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
104}
105
106TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
107 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700108 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700109 dwarf_loc_regs_t loc_regs;
110
111 regs.set_pc(0x100);
112 regs.set_sp(0x2000);
113 regs[5] = 0x20;
114 regs[9] = 0x3000;
115 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
116 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700117 bool finished;
118 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700119 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error());
120}
121
122TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
123 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700124 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700125 dwarf_loc_regs_t loc_regs;
126
127 regs.set_pc(0x100);
128 regs.set_sp(0x2000);
129 regs[5] = 0x20;
130 regs[9] = 0x3000;
131 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
132 TypeParam cfa_value = 0x12345;
133 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
134 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700135 bool finished;
136 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
137 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700138 EXPECT_EQ(0x12345U, regs.sp());
139 EXPECT_EQ(0x20U, regs.pc());
140}
141
142TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
143 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700144 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700145 dwarf_loc_regs_t loc_regs;
146
147 regs.set_pc(0x100);
148 regs.set_sp(0x2000);
149 regs[5] = 0x20;
150 regs[9] = 0x3000;
151 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
152 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700153 bool finished;
154 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
155 ASSERT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700156 EXPECT_EQ(0x80000000U, regs.sp());
157 EXPECT_EQ(0x20U, regs.pc());
158}
159
160TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
161 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700162 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700163 dwarf_loc_regs_t loc_regs;
164
165 regs.set_pc(0x100);
166 regs.set_sp(0x2000);
167 regs[5] = 0x20;
168 regs[9] = 0x3000;
169 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
170 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700171 bool finished;
172 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700173 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->last_error());
174}
175
176TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
177 DwarfCie cie{.return_address_register = 60};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700178 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700179 dwarf_loc_regs_t loc_regs;
180
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700181 bool finished;
182 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700183 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
184}
185
186TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
187 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700188 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700189 dwarf_loc_regs_t loc_regs;
190
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700191 bool finished;
192 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700193 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->last_error());
194}
195
196TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
197 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700198 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700199 dwarf_loc_regs_t loc_regs;
200
201 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700202 bool finished;
203 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700204 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
205
206 this->section_->TestClearError();
207 loc_regs.erase(CFA_REG);
208 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700209 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700210 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
211
212 this->section_->TestClearError();
213 loc_regs.erase(CFA_REG);
214 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700215 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700216 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
217
218 this->section_->TestClearError();
219 loc_regs.erase(CFA_REG);
220 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700221 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700222 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
223}
224
225TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
226 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700227 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700228 dwarf_loc_regs_t loc_regs;
229
230 regs.set_pc(0x100);
231 regs.set_sp(0x2000);
232 regs[5] = 0x20;
233 regs[9] = 0x3000;
234 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700235 bool finished;
236 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
237 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700238 EXPECT_EQ(0x20U, regs.pc());
239 EXPECT_EQ(0x2000U, regs.sp());
240}
241
242TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
243 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700244 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700245 dwarf_loc_regs_t loc_regs;
246
247 regs.set_pc(0x100);
248 regs.set_sp(0x2000);
249 regs[5] = 0x20;
250 regs[6] = 0x4000;
251 regs[9] = 0x3000;
252 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700253 bool finished;
254 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
255 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700256 EXPECT_EQ(0x20U, regs.pc());
257 EXPECT_EQ(0x4000U, regs.sp());
258}
259
260TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
261 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700262 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700263 dwarf_loc_regs_t loc_regs;
264
265 regs.set_pc(0x100);
266 regs.set_sp(0x2000);
267 regs[8] = 0x10;
268 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
269 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 0}};
270 loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700271 bool finished;
272 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700273 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error());
274}
275
276TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
277 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700278 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700279 dwarf_loc_regs_t loc_regs;
280
281 regs.set_pc(0x100);
282 regs.set_sp(0x2000);
283 regs[8] = 0x10;
284 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
285 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700286 bool finished;
287 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700288 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
289}
290
291TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
292 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700293 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700294 dwarf_loc_regs_t loc_regs;
295
296 if (sizeof(TypeParam) == sizeof(uint64_t)) {
297 this->memory_.SetData64(0x2150, 0x12345678abcdef00ULL);
298 } else {
299 this->memory_.SetData32(0x2150, 0x12345678);
300 }
301
302 regs.set_pc(0x100);
303 regs.set_sp(0x2000);
304 regs[3] = 0x234;
305 regs[5] = 0x10;
306 regs[8] = 0x2100;
307 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
308 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}};
309 loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}};
310 loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700311 bool finished;
312 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
313 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700314 EXPECT_EQ(0x10U, regs.pc());
315 EXPECT_EQ(0x2100U, regs.sp());
316 EXPECT_EQ(0x2200U, regs[1]);
317 EXPECT_EQ(0x234U, regs[3]);
318 if (sizeof(TypeParam) == sizeof(uint64_t)) {
319 EXPECT_EQ(0x12345678abcdef00ULL, regs[2]);
320 } else {
321 EXPECT_EQ(0x12345678U, regs[2]);
322 }
323}
324
325TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
326 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700327 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700328 dwarf_loc_regs_t loc_regs;
329
330 regs.set_pc(0x100);
331 regs.set_sp(0x2000);
332 regs[5] = 0x20;
333 regs[8] = 0x10;
334 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
335 loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700336 bool finished;
337 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
338 EXPECT_TRUE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700339 EXPECT_EQ(0U, regs.pc());
340 EXPECT_EQ(0x10U, regs.sp());
341}
342
Christopher Ferris2502a602017-10-23 13:51:54 -0700343TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
344 DwarfCie cie{.return_address_register = 5};
345 RegsImplFake<TypeParam> regs(10, 9);
346 dwarf_loc_regs_t loc_regs;
347
348 regs.set_pc(0x100);
349 regs.set_sp(0x2000);
350 regs[5] = 0;
351 regs[8] = 0x10;
352 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
353 bool finished;
354 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
355 EXPECT_TRUE(finished);
356 EXPECT_EQ(0U, regs.pc());
357 EXPECT_EQ(0x10U, regs.sp());
358}
359
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700360TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
361 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700362 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700363 dwarf_loc_regs_t loc_regs;
364
365 regs.set_pc(0x100);
366 regs.set_sp(0x2000);
367 regs[5] = 0x20;
368 regs[8] = 0x10;
369 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700370 bool finished;
371 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
372 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700373 EXPECT_EQ(0x20U, regs.pc());
374 EXPECT_EQ(0x10U, regs.sp());
375}
376
377TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
378 DwarfCie cie{.return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700379 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700380 dwarf_loc_regs_t loc_regs;
381
382 regs.set_pc(0x100);
383 regs.set_sp(0x2000);
384 regs[5] = 0x20;
385 regs[8] = 0x10;
386 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
387 // This should not result in any errors.
388 loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700389 bool finished;
390 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
391 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700392 EXPECT_EQ(0x20U, regs.pc());
393 EXPECT_EQ(0x10U, regs.sp());
394}
395
396TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
397 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700398 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700399 dwarf_loc_regs_t loc_regs;
400
401 regs.set_pc(0x100);
402 regs.set_sp(0x2000);
403 regs[8] = 0x3000;
404 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
405 TypeParam cfa_value = 0x12345;
406 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
407 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
408 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700409 bool finished;
410 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
411 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700412 EXPECT_EQ(0x3000U, regs.sp());
413 EXPECT_EQ(0x12345U, regs.pc());
414}
415
416TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
417 DwarfCie cie{.version = 3, .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[8] = 0x3000;
424 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
425 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
426 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700427 bool finished;
428 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
429 EXPECT_FALSE(finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700430 EXPECT_EQ(0x3000U, regs.sp());
431 EXPECT_EQ(0x80000000U, regs.pc());
432}
433
434TYPED_TEST_P(DwarfSectionImplTest, Eval_same_cfa_same_pc) {
435 DwarfCie cie{.version = 3, .return_address_register = 5};
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700436 RegsImplFake<TypeParam> regs(10, 9);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700437 dwarf_loc_regs_t loc_regs;
438
439 regs.set_pc(0x100);
440 regs.set_sp(0x2000);
441 regs[5] = 0x100;
442 regs[8] = 0x2000;
443 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700444 bool finished;
445 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700446 EXPECT_EQ(0x2000U, regs.sp());
447 EXPECT_EQ(0x100U, regs.pc());
448}
449
450TYPED_TEST_P(DwarfSectionImplTest, GetCie_fail_should_not_cache) {
451 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
452 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
453 this->section_->TestClearError();
454 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
455 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
456}
457
458TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) {
459 this->memory_.SetData32(0x5000, 0x100);
460 this->memory_.SetData32(0x5004, 0xffffffff);
461 this->memory_.SetData8(0x5008, 0x1);
462 this->memory_.SetData8(0x5009, '\0');
463 this->memory_.SetData8(0x500a, 4);
464 this->memory_.SetData8(0x500b, 8);
465 this->memory_.SetData8(0x500c, 0x20);
466
467 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
468
469 const DwarfCie* cie = this->section_->GetCie(0x5000);
470 ASSERT_TRUE(cie != nullptr);
471 EXPECT_EQ(1U, cie->version);
472 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
473 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
474 EXPECT_EQ(0U, cie->segment_size);
475 EXPECT_EQ(1U, cie->augmentation_string.size());
476 EXPECT_EQ('\0', cie->augmentation_string[0]);
477 EXPECT_EQ(0U, cie->personality_handler);
478 EXPECT_EQ(0x500dU, cie->cfa_instructions_offset);
479 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
480 EXPECT_EQ(4U, cie->code_alignment_factor);
481 EXPECT_EQ(8, cie->data_alignment_factor);
482 EXPECT_EQ(0x20U, cie->return_address_register);
483 EXPECT_EQ(DWARF_ERROR_NONE, this->section_->last_error());
484
485 this->section_->TestClearCachedCieEntry();
486 // Set version to 0, 2, 5 and verify we fail.
487 this->memory_.SetData8(0x5008, 0x0);
488 this->section_->TestClearError();
489 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
490 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error());
491
492 this->memory_.SetData8(0x5008, 0x2);
493 this->section_->TestClearError();
494 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
495 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error());
496
497 this->memory_.SetData8(0x5008, 0x5);
498 this->section_->TestClearError();
499 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
500 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error());
501}
502
503TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) {
504 this->memory_.SetData32(0x5000, 0x100);
505 this->memory_.SetData32(0x5004, 0xffffffff);
506 this->memory_.SetData8(0x5008, 0x1);
507 this->memory_.SetData8(0x5009, '\0');
508 this->memory_.SetData8(0x500a, 4);
509 this->memory_.SetMemory(0x500b, std::vector<uint8_t>{0xfc, 0xff, 0xff, 0xff, 0x7f});
510 this->memory_.SetData8(0x5010, 0x20);
511
512 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
513
514 const DwarfCie* cie = this->section_->GetCie(0x5000);
515 ASSERT_TRUE(cie != nullptr);
516 EXPECT_EQ(1U, cie->version);
517 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
518 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
519 EXPECT_EQ(0U, cie->segment_size);
520 EXPECT_EQ(1U, cie->augmentation_string.size());
521 EXPECT_EQ('\0', cie->augmentation_string[0]);
522 EXPECT_EQ(0U, cie->personality_handler);
523 EXPECT_EQ(0x5011U, cie->cfa_instructions_offset);
524 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
525 EXPECT_EQ(4U, cie->code_alignment_factor);
526 EXPECT_EQ(-4, cie->data_alignment_factor);
527 EXPECT_EQ(0x20U, cie->return_address_register);
528}
529
530TYPED_TEST_P(DwarfSectionImplTest, GetCie_64_no_augment) {
531 this->memory_.SetData32(0x8000, 0xffffffff);
532 this->memory_.SetData64(0x8004, 0x200);
533 this->memory_.SetData64(0x800c, 0xffffffff);
534 this->memory_.SetData8(0x8014, 0x1);
535 this->memory_.SetData8(0x8015, '\0');
536 this->memory_.SetData8(0x8016, 4);
537 this->memory_.SetData8(0x8017, 8);
538 this->memory_.SetData8(0x8018, 0x20);
539
540 EXPECT_CALL(*this->section_, IsCie64(0xffffffff)).WillRepeatedly(::testing::Return(true));
541
542 const DwarfCie* cie = this->section_->GetCie(0x8000);
543 ASSERT_TRUE(cie != nullptr);
544 EXPECT_EQ(1U, cie->version);
545 EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding);
546 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
547 EXPECT_EQ(0U, cie->segment_size);
548 EXPECT_EQ(1U, cie->augmentation_string.size());
549 EXPECT_EQ('\0', cie->augmentation_string[0]);
550 EXPECT_EQ(0U, cie->personality_handler);
551 EXPECT_EQ(0x8019U, cie->cfa_instructions_offset);
552 EXPECT_EQ(0x820cU, cie->cfa_instructions_end);
553 EXPECT_EQ(4U, cie->code_alignment_factor);
554 EXPECT_EQ(8, cie->data_alignment_factor);
555 EXPECT_EQ(0x20U, cie->return_address_register);
556}
557
558TYPED_TEST_P(DwarfSectionImplTest, GetCie_augment) {
559 this->memory_.SetData32(0x5000, 0x100);
560 this->memory_.SetData32(0x5004, 0xffffffff);
561 this->memory_.SetData8(0x5008, 0x1);
562 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
563 this->memory_.SetData8(0x500e, 4);
564 this->memory_.SetData8(0x500f, 8);
565 this->memory_.SetData8(0x5010, 0x10);
566 // Augment length.
567 this->memory_.SetData8(0x5011, 0xf);
568 // L data.
569 this->memory_.SetData8(0x5012, DW_EH_PE_textrel | DW_EH_PE_udata2);
570 // P data.
571 this->memory_.SetData8(0x5013, DW_EH_PE_udata4);
572 this->memory_.SetData32(0x5014, 0x12345678);
573 // R data.
574 this->memory_.SetData8(0x5018, DW_EH_PE_udata2);
575
576 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
577
578 const DwarfCie* cie = this->section_->GetCie(0x5000);
579 ASSERT_TRUE(cie != nullptr);
580 EXPECT_EQ(1U, cie->version);
581 EXPECT_EQ(DW_EH_PE_udata2, cie->fde_address_encoding);
582 EXPECT_EQ(DW_EH_PE_textrel | DW_EH_PE_udata2, cie->lsda_encoding);
583 EXPECT_EQ(0U, cie->segment_size);
584 EXPECT_EQ(5U, cie->augmentation_string.size());
585 EXPECT_EQ('z', cie->augmentation_string[0]);
586 EXPECT_EQ('L', cie->augmentation_string[1]);
587 EXPECT_EQ('P', cie->augmentation_string[2]);
588 EXPECT_EQ('R', cie->augmentation_string[3]);
589 EXPECT_EQ('\0', cie->augmentation_string[4]);
590 EXPECT_EQ(0x12345678U, cie->personality_handler);
591 EXPECT_EQ(0x5021U, cie->cfa_instructions_offset);
592 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
593 EXPECT_EQ(4U, cie->code_alignment_factor);
594 EXPECT_EQ(8, cie->data_alignment_factor);
595 EXPECT_EQ(0x10U, cie->return_address_register);
596}
597
598TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_3) {
599 this->memory_.SetData32(0x5000, 0x100);
600 this->memory_.SetData32(0x5004, 0xffffffff);
601 this->memory_.SetData8(0x5008, 0x3);
602 this->memory_.SetData8(0x5009, '\0');
603 this->memory_.SetData8(0x500a, 4);
604 this->memory_.SetData8(0x500b, 8);
605 this->memory_.SetMemory(0x500c, std::vector<uint8_t>{0x81, 0x03});
606
607 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
608
609 const DwarfCie* cie = this->section_->GetCie(0x5000);
610 ASSERT_TRUE(cie != nullptr);
611 EXPECT_EQ(3U, cie->version);
612 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
613 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
614 EXPECT_EQ(0U, cie->segment_size);
615 EXPECT_EQ(1U, cie->augmentation_string.size());
616 EXPECT_EQ('\0', cie->augmentation_string[0]);
617 EXPECT_EQ(0U, cie->personality_handler);
618 EXPECT_EQ(0x500eU, cie->cfa_instructions_offset);
619 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
620 EXPECT_EQ(4U, cie->code_alignment_factor);
621 EXPECT_EQ(8, cie->data_alignment_factor);
622 EXPECT_EQ(0x181U, cie->return_address_register);
623}
624
625TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_4) {
626 this->memory_.SetData32(0x5000, 0x100);
627 this->memory_.SetData32(0x5004, 0xffffffff);
628 this->memory_.SetData8(0x5008, 0x4);
629 this->memory_.SetData8(0x5009, '\0');
630 this->memory_.SetData8(0x500a, 4);
631 this->memory_.SetData8(0x500b, 0x13);
632 this->memory_.SetData8(0x500c, 4);
633 this->memory_.SetData8(0x500d, 8);
634 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x81, 0x03});
635
636 EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true));
637
638 const DwarfCie* cie = this->section_->GetCie(0x5000);
639 ASSERT_TRUE(cie != nullptr);
640 EXPECT_EQ(4U, cie->version);
641 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
642 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
643 EXPECT_EQ(0x13U, cie->segment_size);
644 EXPECT_EQ(1U, cie->augmentation_string.size());
645 EXPECT_EQ('\0', cie->augmentation_string[0]);
646 EXPECT_EQ(0U, cie->personality_handler);
647 EXPECT_EQ(0x5010U, cie->cfa_instructions_offset);
648 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
649 EXPECT_EQ(4U, cie->code_alignment_factor);
650 EXPECT_EQ(8, cie->data_alignment_factor);
651 EXPECT_EQ(0x181U, cie->return_address_register);
652}
653
654TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
655 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
656 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
657 this->section_->TestClearError();
658 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
659 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
660}
661
662TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) {
663 this->memory_.SetData32(0x4000, 0x20);
664 this->memory_.SetData32(0x4004, 0x8000);
665 this->memory_.SetData32(0x4008, 0x5000);
666 this->memory_.SetData32(0x400c, 0x100);
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 this->section_->TestSetCachedCieEntry(0x8000, cie);
673 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
674
675 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
676 ASSERT_TRUE(fde != nullptr);
677 ASSERT_TRUE(fde->cie != nullptr);
678 EXPECT_EQ(0x4010U, fde->cfa_instructions_offset);
679 EXPECT_EQ(0x4024U, fde->cfa_instructions_end);
680 EXPECT_EQ(0x5000U, fde->pc_start);
681 EXPECT_EQ(0x5100U, fde->pc_end);
682 EXPECT_EQ(0x8000U, fde->cie_offset);
683 EXPECT_EQ(0U, fde->lsda_address);
684}
685
686TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment_non_zero_segment_size) {
687 this->memory_.SetData32(0x4000, 0x30);
688 this->memory_.SetData32(0x4004, 0x8000);
689 this->memory_.SetData32(0x4018, 0x5000);
690 this->memory_.SetData32(0x401c, 0x100);
691
692 EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false));
693 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
694 DwarfCie cie{};
695 cie.fde_address_encoding = DW_EH_PE_udata4;
696 cie.segment_size = 0x10;
697 this->section_->TestSetCachedCieEntry(0x8000, cie);
698 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
699
700 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
701 ASSERT_TRUE(fde != nullptr);
702 ASSERT_TRUE(fde->cie != nullptr);
703 EXPECT_EQ(0x4020U, fde->cfa_instructions_offset);
704 EXPECT_EQ(0x4034U, fde->cfa_instructions_end);
705 EXPECT_EQ(0x5000U, fde->pc_start);
706 EXPECT_EQ(0x5100U, fde->pc_end);
707 EXPECT_EQ(0x8000U, fde->cie_offset);
708 EXPECT_EQ(0U, fde->lsda_address);
709}
710
711TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_augment) {
712 this->memory_.SetData32(0x4000, 0x100);
713 this->memory_.SetData32(0x4004, 0x8000);
714 this->memory_.SetData32(0x4008, 0x5000);
715 this->memory_.SetData32(0x400c, 0x100);
716 this->memory_.SetMemory(0x4010, std::vector<uint8_t>{0x82, 0x01});
717 this->memory_.SetData16(0x4012, 0x1234);
718
719 EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false));
720 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
721 DwarfCie cie{};
722 cie.fde_address_encoding = DW_EH_PE_udata4;
723 cie.augmentation_string.push_back('z');
724 cie.lsda_encoding = DW_EH_PE_udata2;
725 this->section_->TestSetCachedCieEntry(0x8000, cie);
726 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
727
728 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
729 ASSERT_TRUE(fde != nullptr);
730 ASSERT_TRUE(fde->cie != nullptr);
731 EXPECT_EQ(0x4094U, fde->cfa_instructions_offset);
732 EXPECT_EQ(0x4104U, fde->cfa_instructions_end);
733 EXPECT_EQ(0x5000U, fde->pc_start);
734 EXPECT_EQ(0x5100U, fde->pc_end);
735 EXPECT_EQ(0x8000U, fde->cie_offset);
736 EXPECT_EQ(0x1234U, fde->lsda_address);
737}
738
739TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_64_no_augment) {
740 this->memory_.SetData32(0x4000, 0xffffffff);
741 this->memory_.SetData64(0x4004, 0x100);
742 this->memory_.SetData64(0x400c, 0x12345678);
743 this->memory_.SetData32(0x4014, 0x5000);
744 this->memory_.SetData32(0x4018, 0x100);
745
746 EXPECT_CALL(*this->section_, IsCie64(0x12345678)).WillOnce(::testing::Return(false));
747 EXPECT_CALL(*this->section_, GetCieOffsetFromFde64(0x12345678))
748 .WillOnce(::testing::Return(0x12345678));
749 DwarfCie cie{};
750 cie.fde_address_encoding = DW_EH_PE_udata4;
751 this->section_->TestSetCachedCieEntry(0x12345678, cie);
752 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
753
754 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
755 ASSERT_TRUE(fde != nullptr);
756 ASSERT_TRUE(fde->cie != nullptr);
757 EXPECT_EQ(0x401cU, fde->cfa_instructions_offset);
758 EXPECT_EQ(0x410cU, fde->cfa_instructions_end);
759 EXPECT_EQ(0x5000U, fde->pc_start);
760 EXPECT_EQ(0x5100U, fde->pc_end);
761 EXPECT_EQ(0x12345678U, fde->cie_offset);
762 EXPECT_EQ(0U, fde->lsda_address);
763}
764
765TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_cached) {
766 DwarfCie cie{};
767 cie.fde_address_encoding = DW_EH_PE_udata4;
768 cie.augmentation_string.push_back('z');
769 cie.lsda_encoding = DW_EH_PE_udata2;
770
771 DwarfFde fde_cached{};
772 fde_cached.cfa_instructions_offset = 0x1000;
773 fde_cached.cfa_instructions_end = 0x1100;
774 fde_cached.pc_start = 0x9000;
775 fde_cached.pc_end = 0x9400;
776 fde_cached.cie_offset = 0x30000;
777 fde_cached.cie = &cie;
778 this->section_->TestSetCachedFdeEntry(0x6000, fde_cached);
779
780 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x6000);
781 ASSERT_TRUE(fde != nullptr);
782 ASSERT_EQ(&cie, fde->cie);
783 EXPECT_EQ(0x1000U, fde->cfa_instructions_offset);
784 EXPECT_EQ(0x1100U, fde->cfa_instructions_end);
785 EXPECT_EQ(0x9000U, fde->pc_start);
786 EXPECT_EQ(0x9400U, fde->pc_end);
787 EXPECT_EQ(0x30000U, fde->cie_offset);
788}
789
790TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
791 DwarfCie cie{};
792 cie.cfa_instructions_offset = 0x3000;
793 cie.cfa_instructions_end = 0x3002;
794 DwarfFde fde{};
795 fde.cie = &cie;
796 fde.cie_offset = 0x8000;
797 fde.cfa_instructions_offset = 0x6000;
798 fde.cfa_instructions_end = 0x6002;
799
800 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x09, 0x02, 0x01});
801 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
802
803 dwarf_loc_regs_t loc_regs;
804 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
805 ASSERT_EQ(2U, loc_regs.size());
806
807 auto entry = loc_regs.find(2);
808 ASSERT_NE(entry, loc_regs.end());
809 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
810 ASSERT_EQ(1U, entry->second.values[0]);
811
812 entry = loc_regs.find(4);
813 ASSERT_NE(entry, loc_regs.end());
814 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
815 ASSERT_EQ(3U, entry->second.values[0]);
816}
817
818TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) {
819 DwarfCie cie{};
820 cie.cfa_instructions_offset = 0x3000;
821 cie.cfa_instructions_end = 0x3002;
822 DwarfFde fde{};
823 fde.cie = &cie;
824 fde.cie_offset = 0x8000;
825 fde.cfa_instructions_offset = 0x6000;
826 fde.cfa_instructions_end = 0x6002;
827
828 dwarf_loc_regs_t cie_loc_regs{{6, {DWARF_LOCATION_REGISTER, {4, 0}}}};
829 this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs);
830 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
831
832 dwarf_loc_regs_t loc_regs;
833 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
834 ASSERT_EQ(2U, loc_regs.size());
835
836 auto entry = loc_regs.find(6);
837 ASSERT_NE(entry, loc_regs.end());
838 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
839 ASSERT_EQ(4U, entry->second.values[0]);
840
841 entry = loc_regs.find(4);
842 ASSERT_NE(entry, loc_regs.end());
843 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
844 ASSERT_EQ(3U, entry->second.values[0]);
845}
846
847TYPED_TEST_P(DwarfSectionImplTest, Log) {
848 DwarfCie cie{};
849 cie.cfa_instructions_offset = 0x5000;
850 cie.cfa_instructions_end = 0x5001;
851 DwarfFde fde{};
852 fde.cie = &cie;
853 fde.cfa_instructions_offset = 0x6000;
854 fde.cfa_instructions_end = 0x6001;
855
856 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00});
857 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2});
858 ASSERT_TRUE(this->section_->Log(2, 0x1000, 0x1000, &fde));
859
860 ASSERT_EQ(
861 "4 unwind DW_CFA_nop\n"
862 "4 unwind Raw Data: 0x00\n"
863 "4 unwind DW_CFA_restore register(2)\n"
864 "4 unwind Raw Data: 0xc2\n",
865 GetFakeLogPrint());
866 ASSERT_EQ("", GetFakeLogBuf());
867}
868
869REGISTER_TYPED_TEST_CASE_P(
870 DwarfSectionImplTest, Eval_cfa_expr_eval_fail, Eval_cfa_expr_no_stack,
871 Eval_cfa_expr_is_register, Eval_cfa_expr, Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa,
872 Eval_cfa_bad, Eval_cfa_register_prev, Eval_cfa_register_from_value, Eval_double_indirection,
873 Eval_invalid_register, Eval_different_reg_locations, Eval_return_address_undefined,
Christopher Ferris2502a602017-10-23 13:51:54 -0700874 Eval_pc_zero, Eval_return_address, Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700875 Eval_same_cfa_same_pc, GetCie_fail_should_not_cache, GetCie_32_version_check,
876 GetCie_negative_data_alignment_factor, GetCie_64_no_augment, GetCie_augment, GetCie_version_3,
877 GetCie_version_4, GetFdeFromOffset_fail_should_not_cache, GetFdeFromOffset_32_no_augment,
878 GetFdeFromOffset_32_no_augment_non_zero_segment_size, GetFdeFromOffset_32_augment,
879 GetFdeFromOffset_64_no_augment, GetFdeFromOffset_cached, GetCfaLocationInfo_cie_not_cached,
880 GetCfaLocationInfo_cie_cached, Log);
881
882typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
883INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes);
Christopher Ferrisd226a512017-07-14 10:37:19 -0700884
885} // namespace unwindstack