diff options
Diffstat (limited to 'libunwindstack/tests/DwarfEhFrameTest.cpp')
-rw-r--r-- | libunwindstack/tests/DwarfEhFrameTest.cpp | 517 |
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 | ||
61 | template <typename TypeParam> | 52 | template <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 | ||
79 | TYPED_TEST_P(DwarfEhFrameTest, Init) { | 70 | TYPED_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 | ||
106 | TYPED_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 | ||
115 | TYPED_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 | ||
130 | TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_read_datarel) { | 131 | TYPED_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 | ||
145 | TYPED_TEST_P(DwarfEhFrameTest, GetFdeInfoFromIndex_cached) { | 148 | TYPED_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. | 215 | TYPED_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 | ||
167 | TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetBinary_verify) { | 234 | TYPED_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 | |||
268 | TYPED_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 | |||
311 | TYPED_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 | ||
208 | TYPED_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 | |||
237 | TYPED_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 | |||
255 | TYPED_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 | |||
272 | TYPED_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 | |||
280 | TYPED_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 | |||
300 | TYPED_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 | |||
320 | TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) { | 365 | TYPED_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 | ||
360 | TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) { | 407 | TYPED_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 | ||
402 | TYPED_TEST_P(DwarfEhFrameTest, GetFdeFromPc_fde_not_found) { | 451 | REGISTER_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 | |||
414 | REGISTER_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 | ||
422 | typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; | 455 | typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; |
423 | INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes); | 456 | INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes); |