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