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 "DwarfEhFrame.h" 25 #include "DwarfEncoding.h" 26 27 #include "LogFake.h" 28 #include "MemoryFake.h" 29 30 namespace unwindstack { 31 32 template <typename TypeParam> 33 class MockDwarfEhFrame : public DwarfEhFrame<TypeParam> { 34 public: 35 MockDwarfEhFrame(Memory* memory) : DwarfEhFrame<TypeParam>(memory) {} 36 ~MockDwarfEhFrame() = default; 37 38 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; } 39 void TestSetOffset(uint64_t offset) { this->entries_offset_ = offset; } 40 void TestSetEndOffset(uint64_t offset) { this->entries_end_ = offset; } 41 void TestPushFdeInfo(const typename DwarfEhFrame<TypeParam>::FdeInfo& info) { 42 this->fdes_.push_back(info); 43 } 44 45 uint64_t TestGetFdeCount() { return this->fde_count_; } 46 uint8_t TestGetOffset() { return this->offset_; } 47 uint8_t TestGetEndOffset() { return this->end_offset_; } 48 void TestGetFdeInfo(size_t index, typename DwarfEhFrame<TypeParam>::FdeInfo* info) { 49 *info = this->fdes_[index]; 50 } 51 }; 52 53 template <typename TypeParam> 54 class DwarfEhFrameTest : public ::testing::Test { 55 protected: 56 void SetUp() override { 57 memory_.Clear(); 58 eh_frame_ = new MockDwarfEhFrame<TypeParam>(&memory_); 59 ResetLogs(); 60 } 61 62 void TearDown() override { delete eh_frame_; } 63 64 MemoryFake memory_; 65 MockDwarfEhFrame<TypeParam>* eh_frame_ = nullptr; 66 }; 67 TYPED_TEST_CASE_P(DwarfEhFrameTest); 68 69 // NOTE: All test class variables need to be referenced as this->. 70 71 TYPED_TEST_P(DwarfEhFrameTest, Init32) { 72 // CIE 32 information. 73 this->memory_.SetData32(0x5000, 0xfc); 74 this->memory_.SetData32(0x5004, 0); 75 this->memory_.SetData8(0x5008, 1); 76 this->memory_.SetData8(0x5009, '\0'); 77 78 // FDE 32 information. 79 this->memory_.SetData32(0x5100, 0xfc); 80 this->memory_.SetData32(0x5104, 0x104); 81 this->memory_.SetData32(0x5108, 0x1500); 82 this->memory_.SetData32(0x510c, 0x200); 83 84 this->memory_.SetData32(0x5200, 0xfc); 85 this->memory_.SetData32(0x5204, 0x204); 86 this->memory_.SetData32(0x5208, 0x2500); 87 this->memory_.SetData32(0x520c, 0x300); 88 89 // CIE 32 information. 90 this->memory_.SetData32(0x5300, 0xfc); 91 this->memory_.SetData32(0x5304, 0); 92 this->memory_.SetData8(0x5308, 1); 93 this->memory_.SetData8(0x5309, '\0'); 94 95 // FDE 32 information. 96 this->memory_.SetData32(0x5400, 0xfc); 97 this->memory_.SetData32(0x5404, 0x104); 98 this->memory_.SetData32(0x5408, 0x3500); 99 this->memory_.SetData32(0x540c, 0x400); 100 101 this->memory_.SetData32(0x5500, 0xfc); 102 this->memory_.SetData32(0x5504, 0x204); 103 this->memory_.SetData32(0x5508, 0x4500); 104 this->memory_.SetData32(0x550c, 0x500); 105 106 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600)); 107 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount()); 108 109 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); 110 111 this->eh_frame_->TestGetFdeInfo(0, &info); 112 EXPECT_EQ(0x5100U, info.offset); 113 EXPECT_EQ(0x6608U, info.start); 114 EXPECT_EQ(0x6808U, info.end); 115 116 this->eh_frame_->TestGetFdeInfo(1, &info); 117 EXPECT_EQ(0x5200U, info.offset); 118 EXPECT_EQ(0x7708U, info.start); 119 EXPECT_EQ(0x7a08U, info.end); 120 121 this->eh_frame_->TestGetFdeInfo(2, &info); 122 EXPECT_EQ(0x5400U, info.offset); 123 EXPECT_EQ(0x8908U, info.start); 124 EXPECT_EQ(0x8d08U, info.end); 125 126 this->eh_frame_->TestGetFdeInfo(3, &info); 127 EXPECT_EQ(0x5500U, info.offset); 128 EXPECT_EQ(0x9a08U, info.start); 129 EXPECT_EQ(0x9f08U, info.end); 130 } 131 132 TYPED_TEST_P(DwarfEhFrameTest, Init32_fde_not_following_cie) { 133 // CIE 32 information. 134 this->memory_.SetData32(0x5000, 0xfc); 135 this->memory_.SetData32(0x5004, 0); 136 this->memory_.SetData8(0x5008, 1); 137 this->memory_.SetData8(0x5009, '\0'); 138 139 // FDE 32 information. 140 this->memory_.SetData32(0x5100, 0xfc); 141 this->memory_.SetData32(0x5104, 0x1000); 142 this->memory_.SetData32(0x5108, 0x1500); 143 this->memory_.SetData32(0x510c, 0x200); 144 145 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600)); 146 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode()); 147 } 148 149 TYPED_TEST_P(DwarfEhFrameTest, Init64) { 150 // CIE 64 information. 151 this->memory_.SetData32(0x5000, 0xffffffff); 152 this->memory_.SetData64(0x5004, 0xf4); 153 this->memory_.SetData64(0x500c, 0); 154 this->memory_.SetData8(0x5014, 1); 155 this->memory_.SetData8(0x5015, '\0'); 156 157 // FDE 64 information. 158 this->memory_.SetData32(0x5100, 0xffffffff); 159 this->memory_.SetData64(0x5104, 0xf4); 160 this->memory_.SetData64(0x510c, 0x10c); 161 this->memory_.SetData64(0x5114, 0x1500); 162 this->memory_.SetData64(0x511c, 0x200); 163 164 this->memory_.SetData32(0x5200, 0xffffffff); 165 this->memory_.SetData64(0x5204, 0xf4); 166 this->memory_.SetData64(0x520c, 0x20c); 167 this->memory_.SetData64(0x5214, 0x2500); 168 this->memory_.SetData64(0x521c, 0x300); 169 170 // CIE 64 information. 171 this->memory_.SetData32(0x5300, 0xffffffff); 172 this->memory_.SetData64(0x5304, 0xf4); 173 this->memory_.SetData64(0x530c, 0); 174 this->memory_.SetData8(0x5314, 1); 175 this->memory_.SetData8(0x5315, '\0'); 176 177 // FDE 64 information. 178 this->memory_.SetData32(0x5400, 0xffffffff); 179 this->memory_.SetData64(0x5404, 0xf4); 180 this->memory_.SetData64(0x540c, 0x10c); 181 this->memory_.SetData64(0x5414, 0x3500); 182 this->memory_.SetData64(0x541c, 0x400); 183 184 this->memory_.SetData32(0x5500, 0xffffffff); 185 this->memory_.SetData64(0x5504, 0xf4); 186 this->memory_.SetData64(0x550c, 0x20c); 187 this->memory_.SetData64(0x5514, 0x4500); 188 this->memory_.SetData64(0x551c, 0x500); 189 190 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600)); 191 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount()); 192 193 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); 194 195 this->eh_frame_->TestGetFdeInfo(0, &info); 196 EXPECT_EQ(0x5100U, info.offset); 197 EXPECT_EQ(0x6618U, info.start); 198 EXPECT_EQ(0x6818U, info.end); 199 200 this->eh_frame_->TestGetFdeInfo(1, &info); 201 EXPECT_EQ(0x5200U, info.offset); 202 EXPECT_EQ(0x7718U, info.start); 203 EXPECT_EQ(0x7a18U, info.end); 204 205 this->eh_frame_->TestGetFdeInfo(2, &info); 206 EXPECT_EQ(0x5400U, info.offset); 207 EXPECT_EQ(0x8918U, info.start); 208 EXPECT_EQ(0x8d18U, info.end); 209 210 this->eh_frame_->TestGetFdeInfo(3, &info); 211 EXPECT_EQ(0x5500U, info.offset); 212 EXPECT_EQ(0x9a18U, info.start); 213 EXPECT_EQ(0x9f18U, info.end); 214 } 215 216 TYPED_TEST_P(DwarfEhFrameTest, Init64_fde_not_following_cie) { 217 // CIE 64 information. 218 this->memory_.SetData32(0x5000, 0xffffffff); 219 this->memory_.SetData64(0x5004, 0xf4); 220 this->memory_.SetData64(0x500c, 0); 221 this->memory_.SetData8(0x5014, 1); 222 this->memory_.SetData8(0x5015, '\0'); 223 224 // FDE 64 information. 225 this->memory_.SetData32(0x5100, 0xffffffff); 226 this->memory_.SetData64(0x5104, 0xf4); 227 this->memory_.SetData64(0x510c, 0x1000); 228 this->memory_.SetData64(0x5114, 0x1500); 229 this->memory_.SetData64(0x511c, 0x200); 230 231 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600)); 232 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode()); 233 } 234 235 TYPED_TEST_P(DwarfEhFrameTest, Init_version1) { 236 // CIE 32 information. 237 this->memory_.SetData32(0x5000, 0xfc); 238 this->memory_.SetData32(0x5004, 0); 239 this->memory_.SetData8(0x5008, 1); 240 // Augment string. 241 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'R', 'P', 'L', '\0'}); 242 // Code alignment factor. 243 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x80, 0x00}); 244 // Data alignment factor. 245 this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00}); 246 // Return address register 247 this->memory_.SetData8(0x5014, 0x84); 248 // Augmentation length 249 this->memory_.SetMemory(0x5015, std::vector<uint8_t>{0x84, 0x00}); 250 // R data. 251 this->memory_.SetData8(0x5017, DW_EH_PE_pcrel | DW_EH_PE_udata2); 252 253 // FDE 32 information. 254 this->memory_.SetData32(0x5100, 0xfc); 255 this->memory_.SetData32(0x5104, 0x104); 256 this->memory_.SetData16(0x5108, 0x1500); 257 this->memory_.SetData16(0x510a, 0x200); 258 259 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200)); 260 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount()); 261 262 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); 263 this->eh_frame_->TestGetFdeInfo(0, &info); 264 EXPECT_EQ(0x5100U, info.offset); 265 EXPECT_EQ(0x6606U, info.start); 266 EXPECT_EQ(0x6806U, info.end); 267 } 268 269 TYPED_TEST_P(DwarfEhFrameTest, Init_version4) { 270 // CIE 32 information. 271 this->memory_.SetData32(0x5000, 0xfc); 272 this->memory_.SetData32(0x5004, 0); 273 this->memory_.SetData8(0x5008, 4); 274 // Augment string. 275 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'}); 276 // Address size. 277 this->memory_.SetData8(0x500e, 4); 278 // Segment size. 279 this->memory_.SetData8(0x500f, 0); 280 // Code alignment factor. 281 this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x80, 0x00}); 282 // Data alignment factor. 283 this->memory_.SetMemory(0x5012, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00}); 284 // Return address register 285 this->memory_.SetMemory(0x5016, std::vector<uint8_t>{0x85, 0x10}); 286 // Augmentation length 287 this->memory_.SetMemory(0x5018, std::vector<uint8_t>{0x84, 0x00}); 288 // L data. 289 this->memory_.SetData8(0x501a, 0x10); 290 // P data. 291 this->memory_.SetData8(0x501b, DW_EH_PE_udata4); 292 this->memory_.SetData32(0x501c, 0x100); 293 // R data. 294 this->memory_.SetData8(0x5020, DW_EH_PE_pcrel | DW_EH_PE_udata2); 295 296 // FDE 32 information. 297 this->memory_.SetData32(0x5100, 0xfc); 298 this->memory_.SetData32(0x5104, 0x104); 299 this->memory_.SetData16(0x5108, 0x1500); 300 this->memory_.SetData16(0x510a, 0x200); 301 302 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200)); 303 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount()); 304 305 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); 306 this->eh_frame_->TestGetFdeInfo(0, &info); 307 EXPECT_EQ(0x5100U, info.offset); 308 EXPECT_EQ(0x6606U, info.start); 309 EXPECT_EQ(0x6806U, info.end); 310 } 311 312 TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc) { 313 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); 314 for (size_t i = 0; i < 9; i++) { 315 info.start = 0x1000 * (i + 1); 316 info.end = 0x1000 * (i + 2) - 0x10; 317 info.offset = 0x5000 + i * 0x20; 318 this->eh_frame_->TestPushFdeInfo(info); 319 } 320 321 this->eh_frame_->TestSetFdeCount(0); 322 uint64_t fde_offset; 323 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset)); 324 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); 325 326 this->eh_frame_->TestSetFdeCount(9); 327 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); 328 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); 329 // Odd number of elements. 330 for (size_t i = 0; i < 9; i++) { 331 TypeParam pc = 0x1000 * (i + 1); 332 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i; 333 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 334 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i; 335 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 336 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset)) 337 << "Failed at index " << i; 338 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 339 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)) 340 << "Failed at index " << i; 341 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); 342 } 343 344 // Even number of elements. 345 this->eh_frame_->TestSetFdeCount(10); 346 info.start = 0xa000; 347 info.end = 0xaff0; 348 info.offset = 0x5120; 349 this->eh_frame_->TestPushFdeInfo(info); 350 351 for (size_t i = 0; i < 10; i++) { 352 TypeParam pc = 0x1000 * (i + 1); 353 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i; 354 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 355 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i; 356 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 357 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset)) 358 << "Failed at index " << i; 359 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 360 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)) 361 << "Failed at index " << i; 362 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); 363 } 364 } 365 366 TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) { 367 this->eh_frame_->TestSetOffset(0x4000); 368 369 // CIE 32 information. 370 this->memory_.SetData32(0xf000, 0x100); 371 this->memory_.SetData32(0xf004, 0); 372 this->memory_.SetData8(0xf008, 0x1); 373 this->memory_.SetData8(0xf009, '\0'); 374 this->memory_.SetData8(0xf00a, 4); 375 this->memory_.SetData8(0xf00b, 8); 376 this->memory_.SetData8(0xf00c, 0x20); 377 378 // FDE 32 information. 379 this->memory_.SetData32(0x14000, 0x20); 380 this->memory_.SetData32(0x14004, 0x5004); 381 this->memory_.SetData32(0x14008, 0x9000); 382 this->memory_.SetData32(0x1400c, 0x100); 383 384 const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x14000); 385 ASSERT_TRUE(fde != nullptr); 386 EXPECT_EQ(0x14010U, fde->cfa_instructions_offset); 387 EXPECT_EQ(0x14024U, fde->cfa_instructions_end); 388 EXPECT_EQ(0x1d008U, fde->pc_start); 389 EXPECT_EQ(0x1d108U, fde->pc_end); 390 EXPECT_EQ(0xf000U, fde->cie_offset); 391 EXPECT_EQ(0U, fde->lsda_address); 392 393 ASSERT_TRUE(fde->cie != nullptr); 394 EXPECT_EQ(1U, fde->cie->version); 395 EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding); 396 EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding); 397 EXPECT_EQ(0U, fde->cie->segment_size); 398 EXPECT_EQ(1U, fde->cie->augmentation_string.size()); 399 EXPECT_EQ('\0', fde->cie->augmentation_string[0]); 400 EXPECT_EQ(0U, fde->cie->personality_handler); 401 EXPECT_EQ(0xf00dU, fde->cie->cfa_instructions_offset); 402 EXPECT_EQ(0xf104U, fde->cie->cfa_instructions_end); 403 EXPECT_EQ(4U, fde->cie->code_alignment_factor); 404 EXPECT_EQ(8, fde->cie->data_alignment_factor); 405 EXPECT_EQ(0x20U, fde->cie->return_address_register); 406 } 407 408 TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) { 409 this->eh_frame_->TestSetOffset(0x2000); 410 411 // CIE 64 information. 412 this->memory_.SetData32(0x6000, 0xffffffff); 413 this->memory_.SetData64(0x6004, 0x100); 414 this->memory_.SetData64(0x600c, 0); 415 this->memory_.SetData8(0x6014, 0x1); 416 this->memory_.SetData8(0x6015, '\0'); 417 this->memory_.SetData8(0x6016, 4); 418 this->memory_.SetData8(0x6017, 8); 419 this->memory_.SetData8(0x6018, 0x20); 420 421 // FDE 64 information. 422 this->memory_.SetData32(0x8000, 0xffffffff); 423 this->memory_.SetData64(0x8004, 0x200); 424 this->memory_.SetData64(0x800c, 0x200c); 425 this->memory_.SetData64(0x8014, 0x5000); 426 this->memory_.SetData64(0x801c, 0x300); 427 428 const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x8000); 429 ASSERT_TRUE(fde != nullptr); 430 EXPECT_EQ(0x8024U, fde->cfa_instructions_offset); 431 EXPECT_EQ(0x820cU, fde->cfa_instructions_end); 432 EXPECT_EQ(0xd018U, fde->pc_start); 433 EXPECT_EQ(0xd318U, fde->pc_end); 434 EXPECT_EQ(0x6000U, fde->cie_offset); 435 EXPECT_EQ(0U, fde->lsda_address); 436 437 ASSERT_TRUE(fde->cie != nullptr); 438 EXPECT_EQ(1U, fde->cie->version); 439 EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding); 440 EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding); 441 EXPECT_EQ(0U, fde->cie->segment_size); 442 EXPECT_EQ(1U, fde->cie->augmentation_string.size()); 443 EXPECT_EQ('\0', fde->cie->augmentation_string[0]); 444 EXPECT_EQ(0U, fde->cie->personality_handler); 445 EXPECT_EQ(0x6019U, fde->cie->cfa_instructions_offset); 446 EXPECT_EQ(0x610cU, fde->cie->cfa_instructions_end); 447 EXPECT_EQ(4U, fde->cie->code_alignment_factor); 448 EXPECT_EQ(8, fde->cie->data_alignment_factor); 449 EXPECT_EQ(0x20U, fde->cie->return_address_register); 450 } 451 452 REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init32, Init32_fde_not_following_cie, Init64, 453 Init64_fde_not_following_cie, Init_version1, Init_version4, 454 GetFdeOffsetFromPc, GetCieFde32, GetCieFde64); 455 456 typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; 457 INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes); 458 459 } // namespace unwindstack 460