summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'libunwindstack/tests/DwarfEhFrameTest.cpp')
-rw-r--r--libunwindstack/tests/DwarfEhFrameTest.cpp517
1 files changed, 275 insertions, 242 deletions
diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp
index 3dbabe185..53ee719d2 100644
--- a/libunwindstack/tests/DwarfEhFrameTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameTest.cpp
@@ -34,28 +34,19 @@ class MockDwarfEhFrame : public DwarfEhFrame<TypeParam> {
34 MockDwarfEhFrame(Memory* memory) : DwarfEhFrame<TypeParam>(memory) {} 34 MockDwarfEhFrame(Memory* memory) : DwarfEhFrame<TypeParam>(memory) {}
35 ~MockDwarfEhFrame() = default; 35 ~MockDwarfEhFrame() = default;
36 36
37 void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; }
38 void TestSetEntriesOffset(uint64_t offset) { this->entries_offset_ = offset; }
39 void TestSetEntriesEnd(uint64_t end) { this->entries_end_ = end; }
40 void TestSetEntriesDataOffset(uint64_t offset) { this->entries_data_offset_ = offset; }
41 void TestSetCurEntriesOffset(uint64_t offset) { this->cur_entries_offset_ = offset; }
42 void TestSetTableEntrySize(size_t size) { this->table_entry_size_ = size; }
43
44 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; } 37 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
45 void TestSetFdeInfo(uint64_t index, const typename DwarfEhFrame<TypeParam>::FdeInfo& info) { 38 void TestSetOffset(uint64_t offset) { this->entries_offset_ = offset; }
46 this->fde_info_[index] = info; 39 void TestSetEndOffset(uint64_t offset) { this->entries_end_ = offset; }
40 void TestPushFdeInfo(const typename DwarfEhFrame<TypeParam>::FdeInfo& info) {
41 this->fdes_.push_back(info);
47 } 42 }
48 43
49 uint8_t TestGetVersion() { return this->version_; }
50 uint8_t TestGetPtrEncoding() { return this->ptr_encoding_; }
51 uint64_t TestGetPtrOffset() { return this->ptr_offset_; }
52 uint8_t TestGetTableEncoding() { return this->table_encoding_; }
53 uint64_t TestGetTableEntrySize() { return this->table_entry_size_; }
54 uint64_t TestGetFdeCount() { return this->fde_count_; } 44 uint64_t TestGetFdeCount() { return this->fde_count_; }
55 uint64_t TestGetEntriesOffset() { return this->entries_offset_; } 45 uint8_t TestGetOffset() { return this->offset_; }
56 uint64_t TestGetEntriesEnd() { return this->entries_end_; } 46 uint8_t TestGetEndOffset() { return this->end_offset_; }
57 uint64_t TestGetEntriesDataOffset() { return this->entries_data_offset_; } 47 void TestGetFdeInfo(size_t index, typename DwarfEhFrame<TypeParam>::FdeInfo* info) {
58 uint64_t TestGetCurEntriesOffset() { return this->cur_entries_offset_; } 48 *info = this->fdes_[index];
49 }
59}; 50};
60 51
61template <typename TypeParam> 52template <typename TypeParam>
@@ -76,248 +67,304 @@ TYPED_TEST_CASE_P(DwarfEhFrameTest);
76 67
77// NOTE: All test class variables need to be referenced as this->. 68// NOTE: All test class variables need to be referenced as this->.
78 69
79TYPED_TEST_P(DwarfEhFrameTest, Init) { 70TYPED_TEST_P(DwarfEhFrameTest, Init32) {
80 this->memory_.SetMemory( 71 // CIE 32 information.
81 0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4}); 72 this->memory_.SetData32(0x5000, 0xfc);
82 this->memory_.SetData16(0x1004, 0x500); 73 this->memory_.SetData32(0x5004, 0);
83 this->memory_.SetData32(0x1006, 126); 74 this->memory_.SetData8(0x5008, 1);
84 75 this->memory_.SetData8(0x5009, '\0');
85 ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100));
86 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
87 EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding());
88 EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding());
89 EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
90 EXPECT_EQ(126U, this->eh_frame_->TestGetFdeCount());
91 EXPECT_EQ(0x500U, this->eh_frame_->TestGetPtrOffset());
92 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetEntriesOffset());
93 EXPECT_EQ(0x1100U, this->eh_frame_->TestGetEntriesEnd());
94 EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset());
95 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset());
96
97 // Verify an unexpected version will cause a fail.
98 this->memory_.SetData8(0x1000, 0);
99 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100));
100 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error());
101 this->memory_.SetData8(0x1000, 2);
102 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100));
103 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error());
104}
105 76
106TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_expect_cache_fail) { 77 // FDE 32 information.
107 this->eh_frame_->TestSetTableEntrySize(0x10); 78 this->memory_.SetData32(0x5100, 0xfc);
108 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); 79 this->memory_.SetData32(0x5104, 0x104);
109 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr); 80 this->memory_.SetData32(0x5108, 0x1500);
110 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error()); 81 this->memory_.SetData32(0x510c, 0x200);
111 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
112 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error());
113}
114 82
115TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_read_pcrel) { 83 this->memory_.SetData32(0x5200, 0xfc);
116 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4); 84 this->memory_.SetData32(0x5204, 0x204);
117 this->eh_frame_->TestSetEntriesOffset(0x1000); 85 this->memory_.SetData32(0x5208, 0x2500);
118 this->eh_frame_->TestSetEntriesDataOffset(0x3000); 86 this->memory_.SetData32(0x520c, 0x300);
119 this->eh_frame_->TestSetTableEntrySize(0x10);
120 87
121 this->memory_.SetData32(0x1040, 0x340); 88 // CIE 32 information.
122 this->memory_.SetData32(0x1044, 0x500); 89 this->memory_.SetData32(0x5300, 0xfc);
90 this->memory_.SetData32(0x5304, 0);
91 this->memory_.SetData8(0x5308, 1);
92 this->memory_.SetData8(0x5309, '\0');
123 93
124 auto info = this->eh_frame_->GetFdeInfoFromIndex(2); 94 // FDE 32 information.
125 ASSERT_TRUE(info != nullptr); 95 this->memory_.SetData32(0x5400, 0xfc);
126 EXPECT_EQ(0x1384U, info->pc); 96 this->memory_.SetData32(0x5404, 0x104);
127 EXPECT_EQ(0x1540U, info->offset); 97 this->memory_.SetData32(0x5408, 0x3500);
98 this->memory_.SetData32(0x540c, 0x400);
99
100 this->memory_.SetData32(0x5500, 0xfc);
101 this->memory_.SetData32(0x5504, 0x204);
102 this->memory_.SetData32(0x5508, 0x4500);
103 this->memory_.SetData32(0x550c, 0x500);
104
105 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600));
106 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount());
107
108 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
109
110 this->eh_frame_->TestGetFdeInfo(0, &info);
111 EXPECT_EQ(0x5100U, info.offset);
112 EXPECT_EQ(0x660cU, info.start);
113 EXPECT_EQ(0x680cU, info.end);
114
115 this->eh_frame_->TestGetFdeInfo(1, &info);
116 EXPECT_EQ(0x5200U, info.offset);
117 EXPECT_EQ(0x770cU, info.start);
118 EXPECT_EQ(0x7a0cU, info.end);
119
120 this->eh_frame_->TestGetFdeInfo(2, &info);
121 EXPECT_EQ(0x5400U, info.offset);
122 EXPECT_EQ(0x890cU, info.start);
123 EXPECT_EQ(0x8d0cU, info.end);
124
125 this->eh_frame_->TestGetFdeInfo(3, &info);
126 EXPECT_EQ(0x5500U, info.offset);
127 EXPECT_EQ(0x9a0cU, info.start);
128 EXPECT_EQ(0x9f0cU, info.end);
128} 129}
129 130
130TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_read_datarel) { 131TYPED_TEST_P(DwarfEhFrameTest, Init32_fde_not_following_cie) {
131 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_datarel | DW_EH_PE_udata4); 132 // CIE 32 information.
132 this->eh_frame_->TestSetEntriesOffset(0x1000); 133 this->memory_.SetData32(0x5000, 0xfc);
133 this->eh_frame_->TestSetEntriesDataOffset(0x3000); 134 this->memory_.SetData32(0x5004, 0);
134 this->eh_frame_->TestSetTableEntrySize(0x10); 135 this->memory_.SetData8(0x5008, 1);
136 this->memory_.SetData8(0x5009, '\0');
135 137
136 this->memory_.SetData32(0x1040, 0x340); 138 // FDE 32 information.
137 this->memory_.SetData32(0x1044, 0x500); 139 this->memory_.SetData32(0x5100, 0xfc);
140 this->memory_.SetData32(0x5104, 0x1000);
141 this->memory_.SetData32(0x5108, 0x1500);
142 this->memory_.SetData32(0x510c, 0x200);
138 143
139 auto info = this->eh_frame_->GetFdeInfoFromIndex(2); 144 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600));
140 ASSERT_TRUE(info != nullptr); 145 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->last_error());
141 EXPECT_EQ(0x3344U, info->pc);
142 EXPECT_EQ(0x3500U, info->offset);
143} 146}
144 147
145TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_cached) { 148TYPED_TEST_P(DwarfEhFrameTest, Init64) {
146 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); 149 // CIE 64 information.
147 this->eh_frame_->TestSetEntriesOffset(0x1000); 150 this->memory_.SetData32(0x5000, 0xffffffff);
148 this->eh_frame_->TestSetTableEntrySize(0x10); 151 this->memory_.SetData64(0x5004, 0xf4);
152 this->memory_.SetData64(0x500c, 0);
153 this->memory_.SetData8(0x5014, 1);
154 this->memory_.SetData8(0x5015, '\0');
155
156 // FDE 64 information.
157 this->memory_.SetData32(0x5100, 0xffffffff);
158 this->memory_.SetData64(0x5104, 0xf4);
159 this->memory_.SetData64(0x510c, 0x10c);
160 this->memory_.SetData64(0x5114, 0x1500);
161 this->memory_.SetData64(0x511c, 0x200);
162
163 this->memory_.SetData32(0x5200, 0xffffffff);
164 this->memory_.SetData64(0x5204, 0xf4);
165 this->memory_.SetData64(0x520c, 0x20c);
166 this->memory_.SetData64(0x5214, 0x2500);
167 this->memory_.SetData64(0x521c, 0x300);
149 168
150 this->memory_.SetData32(0x1040, 0x340); 169 // CIE 64 information.
151 this->memory_.SetData32(0x1044, 0x500); 170 this->memory_.SetData32(0x5300, 0xffffffff);
171 this->memory_.SetData64(0x5304, 0xf4);
172 this->memory_.SetData64(0x530c, 0);
173 this->memory_.SetData8(0x5314, 1);
174 this->memory_.SetData8(0x5315, '\0');
152 175
153 auto info = this->eh_frame_->GetFdeInfoFromIndex(2); 176 // FDE 64 information.
154 ASSERT_TRUE(info != nullptr); 177 this->memory_.SetData32(0x5400, 0xffffffff);
155 EXPECT_EQ(0x344U, info->pc); 178 this->memory_.SetData64(0x5404, 0xf4);
156 EXPECT_EQ(0x500U, info->offset); 179 this->memory_.SetData64(0x540c, 0x10c);
180 this->memory_.SetData64(0x5414, 0x3500);
181 this->memory_.SetData64(0x541c, 0x400);
182
183 this->memory_.SetData32(0x5500, 0xffffffff);
184 this->memory_.SetData64(0x5504, 0xf4);
185 this->memory_.SetData64(0x550c, 0x20c);
186 this->memory_.SetData64(0x5514, 0x4500);
187 this->memory_.SetData64(0x551c, 0x500);
188
189 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600));
190 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount());
191
192 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
193
194 this->eh_frame_->TestGetFdeInfo(0, &info);
195 EXPECT_EQ(0x5100U, info.offset);
196 EXPECT_EQ(0x661cU, info.start);
197 EXPECT_EQ(0x681cU, info.end);
198
199 this->eh_frame_->TestGetFdeInfo(1, &info);
200 EXPECT_EQ(0x5200U, info.offset);
201 EXPECT_EQ(0x771cU, info.start);
202 EXPECT_EQ(0x7a1cU, info.end);
203
204 this->eh_frame_->TestGetFdeInfo(2, &info);
205 EXPECT_EQ(0x5400U, info.offset);
206 EXPECT_EQ(0x891cU, info.start);
207 EXPECT_EQ(0x8d1cU, info.end);
208
209 this->eh_frame_->TestGetFdeInfo(3, &info);
210 EXPECT_EQ(0x5500U, info.offset);
211 EXPECT_EQ(0x9a1cU, info.start);
212 EXPECT_EQ(0x9f1cU, info.end);
213}
157 214
158 // Clear the memory so that this will fail if it doesn't read cached data. 215TYPED_TEST_P(DwarfEhFrameTest, Init64_fde_not_following_cie) {
159 this->memory_.Clear(); 216 // CIE 64 information.
217 this->memory_.SetData32(0x5000, 0xffffffff);
218 this->memory_.SetData64(0x5004, 0xf4);
219 this->memory_.SetData64(0x500c, 0);
220 this->memory_.SetData8(0x5014, 1);
221 this->memory_.SetData8(0x5015, '\0');
160 222
161 info = this->eh_frame_->GetFdeInfoFromIndex(2); 223 // FDE 64 information.
162 ASSERT_TRUE(info != nullptr); 224 this->memory_.SetData32(0x5100, 0xffffffff);
163 EXPECT_EQ(0x344U, info->pc); 225 this->memory_.SetData64(0x5104, 0xf4);
164 EXPECT_EQ(0x500U, info->offset); 226 this->memory_.SetData64(0x510c, 0x1000);
227 this->memory_.SetData64(0x5114, 0x1500);
228 this->memory_.SetData64(0x511c, 0x200);
229
230 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600));
231 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->last_error());
165} 232}
166 233
167TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetBinary_verify) { 234TYPED_TEST_P(DwarfEhFrameTest, Init_version1) {
168 this->eh_frame_->TestSetTableEntrySize(0x10); 235 // CIE 32 information.
169 this->eh_frame_->TestSetFdeCount(10); 236 this->memory_.SetData32(0x5000, 0xfc);
237 this->memory_.SetData32(0x5004, 0);
238 this->memory_.SetData8(0x5008, 1);
239 // Augment string.
240 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'R', 'P', 'L', '\0'});
241 // Code alignment factor.
242 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x80, 0x00});
243 // Data alignment factor.
244 this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00});
245 // Return address register
246 this->memory_.SetData8(0x5014, 0x84);
247 // Augmentation length
248 this->memory_.SetMemory(0x5015, std::vector<uint8_t>{0x84, 0x00});
249 // R data.
250 this->memory_.SetData8(0x5017, DW_EH_PE_pcrel | DW_EH_PE_udata2);
170 251
171 typename DwarfEhFrame<TypeParam>::FdeInfo info; 252 // FDE 32 information.
172 for (size_t i = 0; i < 10; i++) { 253 this->memory_.SetData32(0x5100, 0xfc);
173 info.pc = 0x1000 * (i + 1); 254 this->memory_.SetData32(0x5104, 0x104);
255 this->memory_.SetData16(0x5108, 0x1500);
256 this->memory_.SetData16(0x510a, 0x200);
257
258 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200));
259 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
260
261 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
262 this->eh_frame_->TestGetFdeInfo(0, &info);
263 EXPECT_EQ(0x5100U, info.offset);
264 EXPECT_EQ(0x660aU, info.start);
265 EXPECT_EQ(0x680aU, info.end);
266}
267
268TYPED_TEST_P(DwarfEhFrameTest, Init_version4) {
269 // CIE 32 information.
270 this->memory_.SetData32(0x5000, 0xfc);
271 this->memory_.SetData32(0x5004, 0);
272 this->memory_.SetData8(0x5008, 4);
273 // Augment string.
274 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
275 // Address size.
276 this->memory_.SetData8(0x500e, 4);
277 // Segment size.
278 this->memory_.SetData8(0x500f, 0);
279 // Code alignment factor.
280 this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x80, 0x00});
281 // Data alignment factor.
282 this->memory_.SetMemory(0x5012, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00});
283 // Return address register
284 this->memory_.SetMemory(0x5016, std::vector<uint8_t>{0x85, 0x10});
285 // Augmentation length
286 this->memory_.SetMemory(0x5018, std::vector<uint8_t>{0x84, 0x00});
287 // L data.
288 this->memory_.SetData8(0x501a, 0x10);
289 // P data.
290 this->memory_.SetData8(0x501b, DW_EH_PE_udata4);
291 this->memory_.SetData32(0x501c, 0x100);
292 // R data.
293 this->memory_.SetData8(0x5020, DW_EH_PE_pcrel | DW_EH_PE_udata2);
294
295 // FDE 32 information.
296 this->memory_.SetData32(0x5100, 0xfc);
297 this->memory_.SetData32(0x5104, 0x104);
298 this->memory_.SetData16(0x5108, 0x1500);
299 this->memory_.SetData16(0x510a, 0x200);
300
301 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200));
302 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
303
304 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
305 this->eh_frame_->TestGetFdeInfo(0, &info);
306 EXPECT_EQ(0x5100U, info.offset);
307 EXPECT_EQ(0x660aU, info.start);
308 EXPECT_EQ(0x680aU, info.end);
309}
310
311TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc) {
312 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
313 for (size_t i = 0; i < 9; i++) {
314 info.start = 0x1000 * (i + 1);
315 info.end = 0x1000 * (i + 2) - 0x10;
174 info.offset = 0x5000 + i * 0x20; 316 info.offset = 0x5000 + i * 0x20;
175 this->eh_frame_->TestSetFdeInfo(i, info); 317 this->eh_frame_->TestPushFdeInfo(info);
176 } 318 }
177 319
320 this->eh_frame_->TestSetFdeCount(0);
178 uint64_t fde_offset; 321 uint64_t fde_offset;
179 EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x100, &fde_offset, 10)); 322 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset));
180 // Not an error, just not found.
181 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); 323 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
182 // Even number of elements. 324
183 for (size_t i = 0; i < 10; i++) { 325 this->eh_frame_->TestSetFdeCount(9);
326 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
327 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
328 // Odd number of elements.
329 for (size_t i = 0; i < 9; i++) {
184 TypeParam pc = 0x1000 * (i + 1); 330 TypeParam pc = 0x1000 * (i + 1);
185 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 10)) << "Failed at index " << i; 331 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i;
186 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 332 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
187 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 10)) << "Failed at index " 333 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i;
188 << i;
189 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 334 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
190 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 10)) 335 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset))
191 << "Failed at index " << i; 336 << "Failed at index " << i;
192 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 337 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
338 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
339 << "Failed at index " << i;
340 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
193 } 341 }
194 // Odd number of elements. 342
195 for (size_t i = 0; i < 9; i++) { 343 // Even number of elements.
344 this->eh_frame_->TestSetFdeCount(10);
345 info.start = 0xa000;
346 info.end = 0xaff0;
347 info.offset = 0x5120;
348 this->eh_frame_->TestPushFdeInfo(info);
349
350 for (size_t i = 0; i < 10; i++) {
196 TypeParam pc = 0x1000 * (i + 1); 351 TypeParam pc = 0x1000 * (i + 1);
197 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 9)) << "Failed at index " << i; 352 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i;
198 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 353 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
199 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 9)) << "Failed at index " 354 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i;
200 << i;
201 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 355 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
202 EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 9)) 356 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset))
203 << "Failed at index " << i; 357 << "Failed at index " << i;
204 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 358 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
359 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
360 << "Failed at index " << i;
361 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
205 } 362 }
206} 363}
207 364
208TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetSequential) {
209 this->eh_frame_->TestSetFdeCount(10);
210 this->eh_frame_->TestSetEntriesDataOffset(0x100);
211 this->eh_frame_->TestSetEntriesEnd(0x2000);
212 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
213
214 this->memory_.SetData32(0x1040, 0x340);
215 this->memory_.SetData32(0x1044, 0x500);
216
217 this->memory_.SetData32(0x1048, 0x440);
218 this->memory_.SetData32(0x104c, 0x600);
219
220 // Verify that if entries is zero, that it fails.
221 uint64_t fde_offset;
222 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset));
223 this->eh_frame_->TestSetCurEntriesOffset(0x1040);
224
225 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset));
226 EXPECT_EQ(0x500U, fde_offset);
227
228 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset));
229 EXPECT_EQ(0x600U, fde_offset);
230
231 // Expect that the data is cached so no more memory reads will occur.
232 this->memory_.Clear();
233 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset));
234 EXPECT_EQ(0x600U, fde_offset);
235}
236
237TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetSequential_last_element) {
238 this->eh_frame_->TestSetFdeCount(2);
239 this->eh_frame_->TestSetEntriesDataOffset(0x100);
240 this->eh_frame_->TestSetEntriesEnd(0x2000);
241 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
242 this->eh_frame_->TestSetCurEntriesOffset(0x1040);
243
244 this->memory_.SetData32(0x1040, 0x340);
245 this->memory_.SetData32(0x1044, 0x500);
246
247 this->memory_.SetData32(0x1048, 0x440);
248 this->memory_.SetData32(0x104c, 0x600);
249
250 uint64_t fde_offset;
251 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset));
252 EXPECT_EQ(0x600U, fde_offset);
253}
254
255TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetSequential_end_check) {
256 this->eh_frame_->TestSetFdeCount(2);
257 this->eh_frame_->TestSetEntriesDataOffset(0x100);
258 this->eh_frame_->TestSetEntriesEnd(0x1048);
259 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
260
261 this->memory_.SetData32(0x1040, 0x340);
262 this->memory_.SetData32(0x1044, 0x500);
263
264 this->memory_.SetData32(0x1048, 0x440);
265 this->memory_.SetData32(0x104c, 0x600);
266
267 uint64_t fde_offset;
268 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset));
269 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
270}
271
272TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc_fail_fde_count) {
273 this->eh_frame_->TestSetFdeCount(0);
274
275 uint64_t fde_offset;
276 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
277 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error());
278}
279
280TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc_binary_search) {
281 this->eh_frame_->TestSetTableEntrySize(16);
282 this->eh_frame_->TestSetFdeCount(10);
283
284 typename DwarfEhFrame<TypeParam>::FdeInfo info;
285 info.pc = 0x550;
286 info.offset = 0x10500;
287 this->eh_frame_->TestSetFdeInfo(5, info);
288 info.pc = 0x750;
289 info.offset = 0x10700;
290 this->eh_frame_->TestSetFdeInfo(7, info);
291 info.pc = 0x850;
292 info.offset = 0x10800;
293 this->eh_frame_->TestSetFdeInfo(8, info);
294
295 uint64_t fde_offset;
296 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x800, &fde_offset));
297 EXPECT_EQ(0x10700U, fde_offset);
298}
299
300TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc_sequential_search) {
301 this->eh_frame_->TestSetFdeCount(10);
302 this->eh_frame_->TestSetTableEntrySize(0);
303
304 typename DwarfEhFrame<TypeParam>::FdeInfo info;
305 info.pc = 0x50;
306 info.offset = 0x10000;
307 this->eh_frame_->TestSetFdeInfo(0, info);
308 info.pc = 0x150;
309 info.offset = 0x10100;
310 this->eh_frame_->TestSetFdeInfo(1, info);
311 info.pc = 0x250;
312 info.offset = 0x10200;
313 this->eh_frame_->TestSetFdeInfo(2, info);
314
315 uint64_t fde_offset;
316 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x200, &fde_offset));
317 EXPECT_EQ(0x10100U, fde_offset);
318}
319
320TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) { 365TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) {
366 this->eh_frame_->TestSetOffset(0x4000);
367
321 // CIE 32 information. 368 // CIE 32 information.
322 this->memory_.SetData32(0xf000, 0x100); 369 this->memory_.SetData32(0xf000, 0x100);
323 this->memory_.SetData32(0xf004, 0); 370 this->memory_.SetData32(0xf004, 0);
@@ -358,6 +405,8 @@ TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) {
358} 405}
359 406
360TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) { 407TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) {
408 this->eh_frame_->TestSetOffset(0x2000);
409
361 // CIE 64 information. 410 // CIE 64 information.
362 this->memory_.SetData32(0x6000, 0xffffffff); 411 this->memory_.SetData32(0x6000, 0xffffffff);
363 this->memory_.SetData64(0x6004, 0x100); 412 this->memory_.SetData64(0x6004, 0x100);
@@ -399,25 +448,9 @@ TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) {
399 EXPECT_EQ(0x20U, fde->cie->return_address_register); 448 EXPECT_EQ(0x20U, fde->cie->return_address_register);
400} 449}
401 450
402TYPED_TEST_P(DwarfEhFrameTest, GetFdeFromPc_fde_not_found) { 451REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init32, Init32_fde_not_following_cie, Init64,
403 this->eh_frame_->TestSetTableEntrySize(16); 452 Init64_fde_not_following_cie, Init_version1, Init_version4,
404 this->eh_frame_->TestSetFdeCount(1); 453 GetFdeOffsetFromPc, GetCieFde32, GetCieFde64);
405
406 typename DwarfEhFrame<TypeParam>::FdeInfo info;
407 info.pc = 0x550;
408 info.offset = 0x10500;
409 this->eh_frame_->TestSetFdeInfo(0, info);
410
411 ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800));
412}
413
414REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init, GetFdeInfoFromIndex_expect_cache_fail,
415 GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_read_datarel,
416 GetFdeInfoFromIndex_cached, GetFdeOffsetBinary_verify,
417 GetFdeOffsetSequential, GetFdeOffsetSequential_last_element,
418 GetFdeOffsetSequential_end_check, GetFdeOffsetFromPc_fail_fde_count,
419 GetFdeOffsetFromPc_binary_search, GetFdeOffsetFromPc_sequential_search,
420 GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found);
421 454
422typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; 455typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes;
423INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes); 456INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes);