1 /*
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 <memory>
20 #include <vector>
21
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24
25 #include <unwindstack/DwarfError.h>
26 #include <unwindstack/Elf.h>
27 #include <unwindstack/ElfInterface.h>
28
29 #include "DwarfEhFrameWithHdr.h"
30 #include "DwarfEncoding.h"
31
32 #include "LogFake.h"
33 #include "utils/MemoryFake.h"
34
35 namespace unwindstack {
36
37 template <typename TypeParam>
38 class TestDwarfEhFrameWithHdr : public DwarfEhFrameWithHdr<TypeParam> {
39 public:
TestDwarfEhFrameWithHdr(std::shared_ptr<Memory> & memory)40 TestDwarfEhFrameWithHdr(std::shared_ptr<Memory>& memory)
41 : DwarfEhFrameWithHdr<TypeParam>(memory) {}
42 ~TestDwarfEhFrameWithHdr() = default;
43
TestSetTableEncoding(uint8_t encoding)44 void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; }
TestSetHdrEntriesOffset(uint64_t offset)45 void TestSetHdrEntriesOffset(uint64_t offset) { this->hdr_entries_offset_ = offset; }
TestSetHdrEntriesDataOffset(uint64_t offset)46 void TestSetHdrEntriesDataOffset(uint64_t offset) { this->hdr_entries_data_offset_ = offset; }
TestSetTableEntrySize(size_t size)47 void TestSetTableEntrySize(size_t size) { this->table_entry_size_ = size; }
48
TestSetFdeCount(uint64_t count)49 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
TestSetFdeInfo(uint64_t index,const typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo & info)50 void TestSetFdeInfo(uint64_t index, const typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo& info) {
51 this->fde_info_[index] = info;
52 }
53
TestGetVersion()54 uint8_t TestGetVersion() { return this->version_; }
TestGetTableEncoding()55 uint8_t TestGetTableEncoding() { return this->table_encoding_; }
TestGetTableEntrySize()56 uint64_t TestGetTableEntrySize() { return this->table_entry_size_; }
TestGetFdeCount()57 uint64_t TestGetFdeCount() { return this->fde_count_; }
TestGetHdrEntriesOffset()58 uint64_t TestGetHdrEntriesOffset() { return this->hdr_entries_offset_; }
TestGetHdrEntriesDataOffset()59 uint64_t TestGetHdrEntriesDataOffset() { return this->hdr_entries_data_offset_; }
60 };
61
62 template <typename TypeParam>
63 class DwarfEhFrameWithHdrTest : public ::testing::Test {
64 protected:
SetUp()65 void SetUp() override {
66 fake_memory_ = new MemoryFake;
67 std::shared_ptr<Memory> memory(fake_memory_);
68 eh_frame_.reset(new TestDwarfEhFrameWithHdr<TypeParam>(memory));
69 ResetLogs();
70 }
71
72 MemoryFake* fake_memory_;
73 std::unique_ptr<TestDwarfEhFrameWithHdr<TypeParam>> eh_frame_;
74 };
75 TYPED_TEST_SUITE_P(DwarfEhFrameWithHdrTest);
76
77 // NOTE: All test class variables need to be referenced as this->.
78
TYPED_TEST_P(DwarfEhFrameWithHdrTest,Init)79 TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init) {
80 this->fake_memory_->SetMemory(
81 0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4});
82 this->fake_memory_->SetData16(0x1004, 0x500);
83 this->fake_memory_->SetData32(0x1006, 126);
84
85 ASSERT_TRUE(this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100}));
86 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
87 EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding());
88 EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
89 EXPECT_EQ(126U, this->eh_frame_->TestGetFdeCount());
90 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
91 EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
92
93 // Verify a zero table entry size fails to init.
94 this->fake_memory_->SetData8(0x1003, 0x1);
95 ASSERT_FALSE(this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100}));
96 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode());
97 // Reset the value back to the original.
98 this->fake_memory_->SetData8(0x1003, DW_EH_PE_sdata4);
99
100 // Verify a zero fde count fails to init.
101 this->fake_memory_->SetData32(0x1006, 0);
102 ASSERT_FALSE(this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100}));
103 ASSERT_EQ(DWARF_ERROR_NO_FDES, this->eh_frame_->LastErrorCode());
104
105 // Verify an unexpected version will cause a fail.
106 this->fake_memory_->SetData32(0x1006, 126);
107 this->fake_memory_->SetData8(0x1000, 0);
108 ASSERT_FALSE(this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100}));
109 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode());
110 this->fake_memory_->SetData8(0x1000, 2);
111 ASSERT_FALSE(this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100}));
112 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode());
113 }
114
TYPED_TEST_P(DwarfEhFrameWithHdrTest,Init_non_zero_load_bias)115 TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias) {
116 this->fake_memory_->SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
117 DW_EH_PE_pcrel | DW_EH_PE_sdata4});
118 this->fake_memory_->SetData16(0x1004, 0x500);
119 this->fake_memory_->SetData32(0x1006, 1);
120 this->fake_memory_->SetData32(0x100a, 0x2500);
121 this->fake_memory_->SetData32(0x100e, 0x1400);
122
123 // CIE 32 information.
124 this->fake_memory_->SetData32(0x1300, 0xfc);
125 this->fake_memory_->SetData32(0x1304, 0);
126 this->fake_memory_->SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
127
128 // FDE 32 information.
129 this->fake_memory_->SetData32(0x1400, 0xfc);
130 this->fake_memory_->SetData32(0x1404, 0x104);
131 this->fake_memory_->SetData32(0x1408, 0x10f8);
132 this->fake_memory_->SetData32(0x140c, 0x200);
133 this->fake_memory_->SetData16(0x1410, 0);
134
135 ASSERT_TRUE(
136 this->eh_frame_->EhFrameInit(SectionInfo{.offset = 0x1300, .size = 0x200, .bias = 0x2000}));
137 ASSERT_TRUE(this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100, .bias = 0x2000}));
138 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
139 EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding());
140 EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
141 EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount());
142 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
143 EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
144
145 const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
146 ASSERT_TRUE(fde != nullptr);
147 EXPECT_EQ(0x4500U, fde->pc_start);
148 EXPECT_EQ(0x4700U, fde->pc_end);
149 }
150
TYPED_TEST_P(DwarfEhFrameWithHdrTest,Init_non_zero_load_bias_different_from_eh_frame_bias)151 TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias_different_from_eh_frame_bias) {
152 this->fake_memory_->SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
153 DW_EH_PE_pcrel | DW_EH_PE_sdata4});
154 this->fake_memory_->SetData16(0x1004, 0x500);
155 this->fake_memory_->SetData32(0x1006, 1);
156 this->fake_memory_->SetData32(0x100a, 0x2500);
157 this->fake_memory_->SetData32(0x100e, 0x1400);
158
159 // CIE 32 information.
160 this->fake_memory_->SetData32(0x1300, 0xfc);
161 this->fake_memory_->SetData32(0x1304, 0);
162 this->fake_memory_->SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
163
164 // FDE 32 information.
165 this->fake_memory_->SetData32(0x1400, 0xfc);
166 this->fake_memory_->SetData32(0x1404, 0x104);
167 this->fake_memory_->SetData32(0x1408, 0x20f8);
168 this->fake_memory_->SetData32(0x140c, 0x200);
169 this->fake_memory_->SetData16(0x1410, 0);
170
171 ASSERT_TRUE(
172 this->eh_frame_->EhFrameInit(SectionInfo{.offset = 0x1300, .size = 0x200, .bias = 0x1000}));
173 ASSERT_TRUE(this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100, .bias = 0x2000}));
174 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
175 EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding());
176 EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
177 EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount());
178 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
179 EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
180
181 const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
182 ASSERT_TRUE(fde != nullptr);
183 EXPECT_EQ(0x4500U, fde->pc_start);
184 EXPECT_EQ(0x4700U, fde->pc_end);
185 }
186
TYPED_TEST_P(DwarfEhFrameWithHdrTest,Init_compressed)187 TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_compressed) {
188 this->fake_memory_->SetMemory(
189 0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4});
190 this->fake_memory_->SetData16(0x1004, 0x500);
191 this->fake_memory_->SetData32(0x1006, 126);
192
193 ASSERT_FALSE(
194 this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100, .flags = SHF_COMPRESSED}));
195 }
196
TYPED_TEST_P(DwarfEhFrameWithHdrTest,EhFrameInit_compressed)197 TYPED_TEST_P(DwarfEhFrameWithHdrTest, EhFrameInit_compressed) {
198 this->fake_memory_->SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
199 DW_EH_PE_pcrel | DW_EH_PE_sdata4});
200 this->fake_memory_->SetData16(0x1004, 0x500);
201 this->fake_memory_->SetData32(0x1006, 1);
202 this->fake_memory_->SetData32(0x100a, 0x2500);
203 this->fake_memory_->SetData32(0x100e, 0x1400);
204
205 // CIE 32 information.
206 this->fake_memory_->SetData32(0x1300, 0xfc);
207 this->fake_memory_->SetData32(0x1304, 0);
208 this->fake_memory_->SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
209
210 // FDE 32 information.
211 this->fake_memory_->SetData32(0x1400, 0xfc);
212 this->fake_memory_->SetData32(0x1404, 0x104);
213 this->fake_memory_->SetData32(0x1408, 0x30f8);
214 this->fake_memory_->SetData32(0x140c, 0);
215 this->fake_memory_->SetData16(0x1410, 0);
216
217 // FDE 32 information.
218 this->fake_memory_->SetData32(0x1500, 0xfc);
219 this->fake_memory_->SetData32(0x1504, 0x204);
220 this->fake_memory_->SetData32(0x1508, 0x2ff8);
221 this->fake_memory_->SetData32(0x150c, 0x200);
222 this->fake_memory_->SetData16(0x1510, 0);
223
224 ASSERT_FALSE(this->eh_frame_->EhFrameInit(
225 SectionInfo{.offset = 0x1300, .size = 0x300, .flags = SHF_COMPRESSED}));
226 }
227
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdeFromPc_wtih_empty_fde)228 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_wtih_empty_fde) {
229 this->fake_memory_->SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
230 DW_EH_PE_pcrel | DW_EH_PE_sdata4});
231 this->fake_memory_->SetData16(0x1004, 0x500);
232 this->fake_memory_->SetData32(0x1006, 1);
233 this->fake_memory_->SetData32(0x100a, 0x2500);
234 this->fake_memory_->SetData32(0x100e, 0x1400);
235
236 // CIE 32 information.
237 this->fake_memory_->SetData32(0x1300, 0xfc);
238 this->fake_memory_->SetData32(0x1304, 0);
239 this->fake_memory_->SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
240
241 // FDE 32 information.
242 this->fake_memory_->SetData32(0x1400, 0xfc);
243 this->fake_memory_->SetData32(0x1404, 0x104);
244 this->fake_memory_->SetData32(0x1408, 0x30f8);
245 this->fake_memory_->SetData32(0x140c, 0);
246 this->fake_memory_->SetData16(0x1410, 0);
247
248 // FDE 32 information.
249 this->fake_memory_->SetData32(0x1500, 0xfc);
250 this->fake_memory_->SetData32(0x1504, 0x204);
251 this->fake_memory_->SetData32(0x1508, 0x2ff8);
252 this->fake_memory_->SetData32(0x150c, 0x200);
253 this->fake_memory_->SetData16(0x1510, 0);
254
255 ASSERT_TRUE(this->eh_frame_->EhFrameInit(SectionInfo{.offset = 0x1300, .size = 0x300}));
256 ASSERT_TRUE(this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100}));
257
258 const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
259 ASSERT_TRUE(fde != nullptr);
260 EXPECT_EQ(0x4500U, fde->pc_start);
261 EXPECT_EQ(0x4700U, fde->pc_end);
262 }
263
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdes_with_empty_fde)264 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes_with_empty_fde) {
265 this->fake_memory_->SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
266 DW_EH_PE_pcrel | DW_EH_PE_sdata4});
267 this->fake_memory_->SetData16(0x1004, 0x500);
268 this->fake_memory_->SetData32(0x1006, 1);
269 this->fake_memory_->SetData32(0x100a, 0x2500);
270 this->fake_memory_->SetData32(0x100e, 0x1400);
271
272 // CIE 32 information.
273 this->fake_memory_->SetData32(0x1300, 0xfc);
274 this->fake_memory_->SetData32(0x1304, 0);
275 this->fake_memory_->SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
276
277 // FDE 32 information.
278 this->fake_memory_->SetData32(0x1400, 0xfc);
279 this->fake_memory_->SetData32(0x1404, 0x104);
280 this->fake_memory_->SetData32(0x1408, 0x30f8);
281 this->fake_memory_->SetData32(0x140c, 0);
282 this->fake_memory_->SetData16(0x1410, 0);
283
284 // FDE 32 information.
285 this->fake_memory_->SetData32(0x1500, 0xfc);
286 this->fake_memory_->SetData32(0x1504, 0x204);
287 this->fake_memory_->SetData32(0x1508, 0x2ff8);
288 this->fake_memory_->SetData32(0x150c, 0x200);
289 this->fake_memory_->SetData16(0x1510, 0);
290
291 ASSERT_TRUE(this->eh_frame_->EhFrameInit(SectionInfo{.offset = 0x1300, .size = 0x300}));
292 ASSERT_TRUE(this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100}));
293
294 std::vector<const DwarfFde*> fdes;
295 this->eh_frame_->GetFdes(&fdes);
296 ASSERT_FALSE(fdes.empty());
297 ASSERT_EQ(1U, fdes.size());
298 EXPECT_EQ(0x4500U, fdes[0]->pc_start);
299 EXPECT_EQ(0x4700U, fdes[0]->pc_end);
300 }
301
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdes)302 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes) {
303 this->fake_memory_->SetMemory(
304 0x1000, std::vector<uint8_t>{1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4});
305 this->fake_memory_->SetData16(0x1004, 0x500);
306 this->fake_memory_->SetData32(0x1006, 4);
307
308 // Header information.
309 this->fake_memory_->SetData32(0x100a, 0x4600);
310 this->fake_memory_->SetData32(0x100e, 0x1500);
311 this->fake_memory_->SetData32(0x1012, 0x5500);
312 this->fake_memory_->SetData32(0x1016, 0x1400);
313 this->fake_memory_->SetData32(0x101a, 0x6800);
314 this->fake_memory_->SetData32(0x101e, 0x1700);
315 this->fake_memory_->SetData32(0x1022, 0x7700);
316 this->fake_memory_->SetData32(0x1026, 0x1600);
317
318 // CIE 32 information.
319 this->fake_memory_->SetData32(0x1300, 0xfc);
320 this->fake_memory_->SetData32(0x1304, 0);
321 this->fake_memory_->SetMemory(0x1308, std::vector<uint8_t>{1, '\0', 0, 0, 0});
322
323 // FDE 32 information.
324 // pc 0x5500 - 0x5700
325 this->fake_memory_->SetData32(0x1400, 0xfc);
326 this->fake_memory_->SetData32(0x1404, 0x104);
327 this->fake_memory_->SetData32(0x1408, 0x40f8);
328 this->fake_memory_->SetData32(0x140c, 0x200);
329
330 // pc 0x4600 - 0x4800
331 this->fake_memory_->SetData32(0x1500, 0xfc);
332 this->fake_memory_->SetData32(0x1504, 0x204);
333 this->fake_memory_->SetData32(0x1508, 0x30f8);
334 this->fake_memory_->SetData32(0x150c, 0x200);
335
336 // pc 0x7700 - 0x7900
337 this->fake_memory_->SetData32(0x1600, 0xfc);
338 this->fake_memory_->SetData32(0x1604, 0x304);
339 this->fake_memory_->SetData32(0x1608, 0x60f8);
340 this->fake_memory_->SetData32(0x160c, 0x200);
341
342 // pc 0x6800 - 0x6a00
343 this->fake_memory_->SetData32(0x1700, 0xfc);
344 this->fake_memory_->SetData32(0x1704, 0x404);
345 this->fake_memory_->SetData32(0x1708, 0x50f8);
346 this->fake_memory_->SetData32(0x170c, 0x200);
347
348 ASSERT_TRUE(this->eh_frame_->Init(SectionInfo{.offset = 0x1000, .size = 0x100}));
349
350 std::vector<const DwarfFde*> fdes;
351 this->eh_frame_->GetFdes(&fdes);
352 ASSERT_EQ(4U, fdes.size());
353
354 EXPECT_EQ(0x4600U, fdes[0]->pc_start);
355 EXPECT_EQ(0x4800U, fdes[0]->pc_end);
356 EXPECT_EQ(0x5500U, fdes[1]->pc_start);
357 EXPECT_EQ(0x5700U, fdes[1]->pc_end);
358 EXPECT_EQ(0x6800U, fdes[2]->pc_start);
359 EXPECT_EQ(0x6a00U, fdes[2]->pc_end);
360 EXPECT_EQ(0x7700U, fdes[3]->pc_start);
361 EXPECT_EQ(0x7900U, fdes[3]->pc_end);
362 }
363
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdeInfoFromIndex_expect_cache_fail)364 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) {
365 this->eh_frame_->TestSetTableEntrySize(0x10);
366 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
367 this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
368
369 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
370 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->LastErrorCode());
371 EXPECT_EQ(0x1000U, this->eh_frame_->LastErrorAddress());
372 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
373 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->LastErrorCode());
374 EXPECT_EQ(0x1000U, this->eh_frame_->LastErrorAddress());
375 }
376
377 // We are assuming that pc rel, is really relative to the load_bias.
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdeInfoFromIndex_read_pcrel)378 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) {
379 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4);
380 this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
381 this->eh_frame_->TestSetHdrEntriesDataOffset(0x3000);
382 this->eh_frame_->TestSetTableEntrySize(0x10);
383
384 this->fake_memory_->SetData32(0x1040, 0x340);
385 this->fake_memory_->SetData32(0x1044, 0x500);
386
387 auto info = this->eh_frame_->GetFdeInfoFromIndex(2);
388 ASSERT_TRUE(info != nullptr);
389 EXPECT_EQ(0x340U, info->pc);
390 EXPECT_EQ(0x500U, info->offset);
391 }
392
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdeInfoFromIndex_read_datarel)393 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_datarel) {
394 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_datarel | DW_EH_PE_udata4);
395 this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
396 this->eh_frame_->TestSetHdrEntriesDataOffset(0x3000);
397 this->eh_frame_->TestSetTableEntrySize(0x10);
398
399 this->fake_memory_->SetData32(0x1040, 0x340);
400 this->fake_memory_->SetData32(0x1044, 0x500);
401
402 auto info = this->eh_frame_->GetFdeInfoFromIndex(2);
403 ASSERT_TRUE(info != nullptr);
404 EXPECT_EQ(0x3340U, info->pc);
405 EXPECT_EQ(0x3500U, info->offset);
406 }
407
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdeInfoFromIndex_cached)408 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_cached) {
409 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
410 this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
411 this->eh_frame_->TestSetTableEntrySize(0x10);
412
413 this->fake_memory_->SetData32(0x1040, 0x340);
414 this->fake_memory_->SetData32(0x1044, 0x500);
415
416 auto info = this->eh_frame_->GetFdeInfoFromIndex(2);
417 ASSERT_TRUE(info != nullptr);
418 EXPECT_EQ(0x340U, info->pc);
419 EXPECT_EQ(0x500U, info->offset);
420
421 // Clear the memory so that this will fail if it doesn't read cached data.
422 this->fake_memory_->Clear();
423
424 info = this->eh_frame_->GetFdeInfoFromIndex(2);
425 ASSERT_TRUE(info != nullptr);
426 EXPECT_EQ(0x340U, info->pc);
427 EXPECT_EQ(0x500U, info->offset);
428 }
429
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdeOffsetFromPc_verify)430 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_verify) {
431 this->eh_frame_->TestSetTableEntrySize(0x10);
432
433 typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
434 for (size_t i = 0; i < 10; i++) {
435 info.pc = 0x1000 * (i + 1);
436 info.offset = 0x5000 + i * 0x20;
437 this->eh_frame_->TestSetFdeInfo(i, info);
438 }
439
440 uint64_t fde_offset;
441 this->eh_frame_->TestSetFdeCount(10);
442 EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
443 // Not an error, just not found.
444 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
445 // Even number of elements.
446 for (size_t i = 0; i < 10; i++) {
447 SCOPED_TRACE(testing::Message() << "Failed at index " << i);
448 TypeParam pc = 0x1000 * (i + 1);
449 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset));
450 EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
451 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset));
452 EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
453 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset));
454 EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
455 }
456
457 // Odd number of elements.
458 this->eh_frame_->TestSetFdeCount(9);
459 for (size_t i = 0; i < 9; i++) {
460 SCOPED_TRACE(testing::Message() << "Failed at index " << i);
461 TypeParam pc = 0x1000 * (i + 1);
462 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset));
463 EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
464 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset));
465 EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
466 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset));
467 EXPECT_EQ(0x5000 + i * 0x20, fde_offset);
468 }
469 }
470
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdeOffsetFromPc_index_fail)471 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_index_fail) {
472 this->eh_frame_->TestSetTableEntrySize(0x10);
473 this->eh_frame_->TestSetFdeCount(10);
474
475 uint64_t fde_offset;
476 EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset));
477 }
478
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdeOffsetFromPc_fail_fde_count)479 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) {
480 this->eh_frame_->TestSetFdeCount(0);
481
482 uint64_t fde_offset;
483 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
484 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
485 }
486
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdeOffsetFromPc_search)487 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_search) {
488 this->eh_frame_->TestSetTableEntrySize(16);
489 this->eh_frame_->TestSetFdeCount(10);
490
491 typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
492 info.pc = 0x550;
493 info.offset = 0x10500;
494 this->eh_frame_->TestSetFdeInfo(5, info);
495 info.pc = 0x750;
496 info.offset = 0x10700;
497 this->eh_frame_->TestSetFdeInfo(7, info);
498 info.pc = 0x850;
499 info.offset = 0x10800;
500 this->eh_frame_->TestSetFdeInfo(8, info);
501
502 uint64_t fde_offset;
503 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x800, &fde_offset));
504 EXPECT_EQ(0x10700U, fde_offset);
505 }
506
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetCieFde32)507 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) {
508 // CIE 32 information.
509 this->fake_memory_->SetData32(0xf000, 0x100);
510 this->fake_memory_->SetData32(0xf004, 0);
511 this->fake_memory_->SetMemory(0xf008, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
512
513 // FDE 32 information.
514 this->fake_memory_->SetData32(0x14000, 0x20);
515 this->fake_memory_->SetData32(0x14004, 0x5004);
516 this->fake_memory_->SetData32(0x14008, 0x9000);
517 this->fake_memory_->SetData32(0x1400c, 0x100);
518
519 const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x14000);
520 ASSERT_TRUE(fde != nullptr);
521 EXPECT_EQ(0x14010U, fde->cfa_instructions_offset);
522 EXPECT_EQ(0x14024U, fde->cfa_instructions_end);
523 EXPECT_EQ(0x1d008U, fde->pc_start);
524 EXPECT_EQ(0x1d108U, fde->pc_end);
525 EXPECT_EQ(0xf000U, fde->cie_offset);
526 EXPECT_EQ(0U, fde->lsda_address);
527
528 ASSERT_TRUE(fde->cie != nullptr);
529 EXPECT_EQ(1U, fde->cie->version);
530 EXPECT_EQ(DW_EH_PE_udata4, fde->cie->fde_address_encoding);
531 EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
532 EXPECT_EQ(0U, fde->cie->segment_size);
533 EXPECT_EQ(1U, fde->cie->augmentation_string.size());
534 EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
535 EXPECT_EQ(0U, fde->cie->personality_handler);
536 EXPECT_EQ(0xf00dU, fde->cie->cfa_instructions_offset);
537 EXPECT_EQ(0xf104U, fde->cie->cfa_instructions_end);
538 EXPECT_EQ(4U, fde->cie->code_alignment_factor);
539 EXPECT_EQ(8, fde->cie->data_alignment_factor);
540 EXPECT_EQ(0x20U, fde->cie->return_address_register);
541 }
542
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetCieFde64)543 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde64) {
544 // CIE 64 information.
545 this->fake_memory_->SetData32(0x6000, 0xffffffff);
546 this->fake_memory_->SetData64(0x6004, 0x100);
547 this->fake_memory_->SetData64(0x600c, 0);
548 this->fake_memory_->SetMemory(0x6014, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
549
550 // FDE 64 information.
551 this->fake_memory_->SetData32(0x8000, 0xffffffff);
552 this->fake_memory_->SetData64(0x8004, 0x200);
553 this->fake_memory_->SetData64(0x800c, 0x200c);
554 this->fake_memory_->SetData64(0x8014, 0x5000);
555 this->fake_memory_->SetData64(0x801c, 0x300);
556
557 const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x8000);
558 ASSERT_TRUE(fde != nullptr);
559 EXPECT_EQ(0x8024U, fde->cfa_instructions_offset);
560 EXPECT_EQ(0x820cU, fde->cfa_instructions_end);
561 EXPECT_EQ(0xd018U, fde->pc_start);
562 EXPECT_EQ(0xd318U, fde->pc_end);
563 EXPECT_EQ(0x6000U, fde->cie_offset);
564 EXPECT_EQ(0U, fde->lsda_address);
565
566 ASSERT_TRUE(fde->cie != nullptr);
567 EXPECT_EQ(1U, fde->cie->version);
568 EXPECT_EQ(DW_EH_PE_udata8, fde->cie->fde_address_encoding);
569 EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
570 EXPECT_EQ(0U, fde->cie->segment_size);
571 EXPECT_EQ(1U, fde->cie->augmentation_string.size());
572 EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
573 EXPECT_EQ(0U, fde->cie->personality_handler);
574 EXPECT_EQ(0x6019U, fde->cie->cfa_instructions_offset);
575 EXPECT_EQ(0x610cU, fde->cie->cfa_instructions_end);
576 EXPECT_EQ(4U, fde->cie->code_alignment_factor);
577 EXPECT_EQ(8, fde->cie->data_alignment_factor);
578 EXPECT_EQ(0x20U, fde->cie->return_address_register);
579 }
580
TYPED_TEST_P(DwarfEhFrameWithHdrTest,GetFdeFromPc_fde_not_found)581 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_fde_not_found) {
582 this->eh_frame_->TestSetTableEntrySize(16);
583 this->eh_frame_->TestSetFdeCount(1);
584
585 typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info;
586 info.pc = 0x550;
587 info.offset = 0x10500;
588 this->eh_frame_->TestSetFdeInfo(0, info);
589
590 ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800));
591 }
592
593 REGISTER_TYPED_TEST_SUITE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias,
594 Init_non_zero_load_bias_different_from_eh_frame_bias, Init_compressed,
595 EhFrameInit_compressed, GetFdeFromPc_wtih_empty_fde,
596 GetFdes_with_empty_fde, GetFdes, GetFdeInfoFromIndex_expect_cache_fail,
597 GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_read_datarel,
598 GetFdeInfoFromIndex_cached, GetFdeOffsetFromPc_verify,
599 GetFdeOffsetFromPc_index_fail, GetFdeOffsetFromPc_fail_fde_count,
600 GetFdeOffsetFromPc_search, GetCieFde32, GetCieFde64,
601 GetFdeFromPc_fde_not_found);
602
603 typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes;
604 INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfEhFrameWithHdrTest, DwarfEhFrameWithHdrTestTypes);
605
606 } // namespace unwindstack
607