| OLD | NEW |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 // structure. | 153 // structure. |
| 154 ASSERT_EQ(sizeof(*expect_segment) + expect_segment->nsects * sizeof(Section), | 154 ASSERT_EQ(sizeof(*expect_segment) + expect_segment->nsects * sizeof(Section), |
| 155 expect_segment->cmdsize); | 155 expect_segment->cmdsize); |
| 156 const Section* expect_sections = | 156 const Section* expect_sections = |
| 157 reinterpret_cast<const Section*>(&expect_segment[1]); | 157 reinterpret_cast<const Section*>(&expect_segment[1]); |
| 158 | 158 |
| 159 for (size_t index = 0; index < actual_segment->nsects(); ++index) { | 159 for (size_t index = 0; index < actual_segment->nsects(); ++index) { |
| 160 const Section* expect_section = &expect_sections[index]; | 160 const Section* expect_section = &expect_sections[index]; |
| 161 const process_types::section* actual_section = | 161 const process_types::section* actual_section = |
| 162 actual_segment->GetSectionAtIndex(index, NULL); | 162 actual_segment->GetSectionAtIndex(index, NULL); |
| 163 ExpectSection(&expect_sections[index], actual_section); | 163 ASSERT_NO_FATAL_FAILURE( |
| 164 if (testing::Test::HasFatalFailure()) { | 164 ExpectSection(&expect_sections[index], actual_section)); |
| 165 return; | |
| 166 } | |
| 167 | 165 |
| 168 // Make sure that the section is accessible by GetSectionByName as well. | 166 // Make sure that the section is accessible by GetSectionByName as well. |
| 169 std::string section_name = | 167 std::string section_name = |
| 170 MachOImageSegmentReader::SectionNameString(expect_section->sectname); | 168 MachOImageSegmentReader::SectionNameString(expect_section->sectname); |
| 171 const process_types::section* actual_section_by_name = | 169 const process_types::section* actual_section_by_name = |
| 172 actual_segment->GetSectionByName(section_name, NULL); | 170 actual_segment->GetSectionByName(section_name, NULL); |
| 173 EXPECT_EQ(actual_section, actual_section_by_name); | 171 EXPECT_EQ(actual_section, actual_section_by_name); |
| 174 | 172 |
| 175 // Make sure that the section is accessible by the parent MachOImageReader’s | 173 // Make sure that the section is accessible by the parent MachOImageReader’s |
| 176 // GetSectionByName. | 174 // GetSectionByName. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 reinterpret_cast<const load_command*>(&commands_base[position]); | 238 reinterpret_cast<const load_command*>(&commands_base[position]); |
| 241 ASSERT_LE(position + command->cmdsize, expect_image->sizeofcmds); | 239 ASSERT_LE(position + command->cmdsize, expect_image->sizeofcmds); |
| 242 if (command->cmd == kSegmentCommand) { | 240 if (command->cmd == kSegmentCommand) { |
| 243 ASSERT_GE(command->cmdsize, sizeof(SegmentCommand)); | 241 ASSERT_GE(command->cmdsize, sizeof(SegmentCommand)); |
| 244 const SegmentCommand* expect_segment = | 242 const SegmentCommand* expect_segment = |
| 245 reinterpret_cast<const SegmentCommand*>(command); | 243 reinterpret_cast<const SegmentCommand*>(command); |
| 246 std::string segment_name = | 244 std::string segment_name = |
| 247 MachOImageSegmentReader::SegmentNameString(expect_segment->segname); | 245 MachOImageSegmentReader::SegmentNameString(expect_segment->segname); |
| 248 const MachOImageSegmentReader* actual_segment = | 246 const MachOImageSegmentReader* actual_segment = |
| 249 actual_image->GetSegmentByName(segment_name); | 247 actual_image->GetSegmentByName(segment_name); |
| 250 ExpectSegmentCommand(expect_segment, | 248 ASSERT_NO_FATAL_FAILURE(ExpectSegmentCommand(expect_segment, |
| 251 expect_image, | 249 expect_image, |
| 252 actual_segment, | 250 actual_segment, |
| 253 actual_image, | 251 actual_image, |
| 254 §ion_index); | 252 §ion_index)); |
| 255 if (testing::Test::HasFatalFailure()) { | |
| 256 return; | |
| 257 } | |
| 258 } | 253 } |
| 259 position += command->cmdsize; | 254 position += command->cmdsize; |
| 260 } | 255 } |
| 261 EXPECT_EQ(expect_image->sizeofcmds, position); | 256 EXPECT_EQ(expect_image->sizeofcmds, position); |
| 262 | 257 |
| 263 if (test_section_index_bounds) { | 258 if (test_section_index_bounds) { |
| 264 // GetSectionAtIndex uses a 1-based index. Make sure that the range is | 259 // GetSectionAtIndex uses a 1-based index. Make sure that the range is |
| 265 // correct. | 260 // correct. |
| 266 EXPECT_EQ(NULL, actual_image->GetSectionAtIndex(0, NULL, NULL)); | 261 EXPECT_EQ(NULL, actual_image->GetSectionAtIndex(0, NULL, NULL)); |
| 267 EXPECT_EQ(NULL, | 262 EXPECT_EQ(NULL, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 if (MachOImageSegmentReader::SegmentNameString(section->segname) == | 294 if (MachOImageSegmentReader::SegmentNameString(section->segname) == |
| 300 SEG_TEXT) { | 295 SEG_TEXT) { |
| 301 test_segment = SEG_DATA; | 296 test_segment = SEG_DATA; |
| 302 } else { | 297 } else { |
| 303 test_segment = SEG_TEXT; | 298 test_segment = SEG_TEXT; |
| 304 } | 299 } |
| 305 test_section = | 300 test_section = |
| 306 MachOImageSegmentReader::SectionNameString(section->sectname); | 301 MachOImageSegmentReader::SectionNameString(section->sectname); |
| 307 | 302 |
| 308 // It should be possible to look up the first section by name. | 303 // It should be possible to look up the first section by name. |
| 309 EXPECT_EQ(section, actual_image->GetSectionByName( | 304 EXPECT_EQ(section, |
| 310 section->segname, section->sectname, NULL)); | 305 actual_image->GetSectionByName( |
| 306 section->segname, section->sectname, NULL)); |
| 311 } | 307 } |
| 312 EXPECT_FALSE( | 308 EXPECT_FALSE( |
| 313 actual_image->GetSectionByName("NoSuchSegment", test_section, NULL)); | 309 actual_image->GetSectionByName("NoSuchSegment", test_section, NULL)); |
| 314 EXPECT_FALSE( | 310 EXPECT_FALSE( |
| 315 actual_image->GetSectionByName(test_segment, test_section, NULL)); | 311 actual_image->GetSectionByName(test_segment, test_section, NULL)); |
| 316 | 312 |
| 317 // The __LINKEDIT segment normally does exist but doesn’t have any sections. | 313 // The __LINKEDIT segment normally does exist but doesn’t have any sections. |
| 318 EXPECT_FALSE( | 314 EXPECT_FALSE( |
| 319 actual_image->GetSectionByName(SEG_LINKEDIT, "NoSuchSection", NULL)); | 315 actual_image->GetSectionByName(SEG_LINKEDIT, "NoSuchSection", NULL)); |
| 320 EXPECT_FALSE(actual_image->GetSectionByName(SEG_LINKEDIT, SECT_TEXT, NULL)); | 316 EXPECT_FALSE(actual_image->GetSectionByName(SEG_LINKEDIT, SECT_TEXT, NULL)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 } | 365 } |
| 370 | 366 |
| 371 // For these, just don’t crash or anything. | 367 // For these, just don’t crash or anything. |
| 372 if (file_type == MH_DYLIB) { | 368 if (file_type == MH_DYLIB) { |
| 373 actual_image->DylibVersion(); | 369 actual_image->DylibVersion(); |
| 374 } | 370 } |
| 375 actual_image->SourceVersion(); | 371 actual_image->SourceVersion(); |
| 376 UUID uuid; | 372 UUID uuid; |
| 377 actual_image->UUID(&uuid); | 373 actual_image->UUID(&uuid); |
| 378 | 374 |
| 379 ExpectSegmentCommands(expect_image, actual_image, test_section_index_bounds); | 375 ASSERT_NO_FATAL_FAILURE(ExpectSegmentCommands( |
| 380 if (testing::Test::HasFatalFailure()) { | 376 expect_image, actual_image, test_section_index_bounds)); |
| 381 return; | |
| 382 } | |
| 383 } | 377 } |
| 384 | 378 |
| 385 // Verifies the symbol whose Nlist structure is |entry| and whose name is |name| | 379 // Verifies the symbol whose Nlist structure is |entry| and whose name is |name| |
| 386 // matches the value of a symbol by the same name looked up in |actual_image|. | 380 // matches the value of a symbol by the same name looked up in |actual_image|. |
| 387 // MachOImageReader::LookUpExternalDefinedSymbol() is used for this purpose. | 381 // MachOImageReader::LookUpExternalDefinedSymbol() is used for this purpose. |
| 388 // Only external defined symbols are considered, other types of symbols are | 382 // Only external defined symbols are considered, other types of symbols are |
| 389 // excluded because LookUpExternalDefinedSymbol() only deals with external | 383 // excluded because LookUpExternalDefinedSymbol() only deals with external |
| 390 // defined symbols. | 384 // defined symbols. |
| 391 void ExpectSymbol(const Nlist* entry, | 385 void ExpectSymbol(const Nlist* entry, |
| 392 const char* name, | 386 const char* name, |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 | 473 |
| 480 const char* linkedit_base = | 474 const char* linkedit_base = |
| 481 reinterpret_cast<const char*>(linkedit->vmaddr + actual_image->Slide()); | 475 reinterpret_cast<const char*>(linkedit->vmaddr + actual_image->Slide()); |
| 482 const Nlist* nlist = reinterpret_cast<const Nlist*>( | 476 const Nlist* nlist = reinterpret_cast<const Nlist*>( |
| 483 linkedit_base + symtab->symoff - linkedit->fileoff); | 477 linkedit_base + symtab->symoff - linkedit->fileoff); |
| 484 const char* strtab = linkedit_base + symtab->stroff - linkedit->fileoff; | 478 const char* strtab = linkedit_base + symtab->stroff - linkedit->fileoff; |
| 485 | 479 |
| 486 for (uint32_t index = 0; index < symtab->nsyms; ++index) { | 480 for (uint32_t index = 0; index < symtab->nsyms; ++index) { |
| 487 const Nlist* entry = nlist + index; | 481 const Nlist* entry = nlist + index; |
| 488 const char* name = strtab + entry->n_un.n_strx; | 482 const char* name = strtab + entry->n_un.n_strx; |
| 489 ExpectSymbol(entry, name, actual_image); | 483 ASSERT_NO_FATAL_FAILURE(ExpectSymbol(entry, name, actual_image)); |
| 490 if (testing::Test::HasFatalFailure()) { | |
| 491 return; | |
| 492 } | |
| 493 } | 484 } |
| 494 } | 485 } |
| 495 | 486 |
| 496 mach_vm_address_t ignore; | 487 mach_vm_address_t ignore; |
| 497 EXPECT_FALSE(actual_image->LookUpExternalDefinedSymbol("", &ignore)); | 488 EXPECT_FALSE(actual_image->LookUpExternalDefinedSymbol("", &ignore)); |
| 498 EXPECT_FALSE( | 489 EXPECT_FALSE( |
| 499 actual_image->LookUpExternalDefinedSymbol("NoSuchSymbolName", &ignore)); | 490 actual_image->LookUpExternalDefinedSymbol("NoSuchSymbolName", &ignore)); |
| 500 EXPECT_FALSE( | 491 EXPECT_FALSE( |
| 501 actual_image->LookUpExternalDefinedSymbol("_NoSuchSymbolName", &ignore)); | 492 actual_image->LookUpExternalDefinedSymbol("_NoSuchSymbolName", &ignore)); |
| 502 } | 493 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 513 | 504 |
| 514 MachOImageReader image_reader; | 505 MachOImageReader image_reader; |
| 515 ASSERT_TRUE(image_reader.Initialize( | 506 ASSERT_TRUE(image_reader.Initialize( |
| 516 &process_reader, mh_execute_header_address, "executable")); | 507 &process_reader, mh_execute_header_address, "executable")); |
| 517 | 508 |
| 518 EXPECT_EQ(static_cast<uint32_t>(MH_EXECUTE), image_reader.FileType()); | 509 EXPECT_EQ(static_cast<uint32_t>(MH_EXECUTE), image_reader.FileType()); |
| 519 | 510 |
| 520 // The main executable has image index 0. | 511 // The main executable has image index 0. |
| 521 intptr_t image_slide = _dyld_get_image_vmaddr_slide(0); | 512 intptr_t image_slide = _dyld_get_image_vmaddr_slide(0); |
| 522 | 513 |
| 523 ExpectMachImage(mh_execute_header, | 514 ASSERT_NO_FATAL_FAILURE(ExpectMachImage(mh_execute_header, |
| 524 mh_execute_header_address, | 515 mh_execute_header_address, |
| 525 image_slide, | 516 image_slide, |
| 526 &image_reader, | 517 &image_reader, |
| 527 true); | 518 true)); |
| 528 if (Test::HasFatalFailure()) { | |
| 529 return; | |
| 530 } | |
| 531 | 519 |
| 532 // This symbol, __mh_execute_header, is known to exist in all MH_EXECUTE | 520 // This symbol, __mh_execute_header, is known to exist in all MH_EXECUTE |
| 533 // Mach-O files. | 521 // Mach-O files. |
| 534 mach_vm_address_t symbol_address; | 522 mach_vm_address_t symbol_address; |
| 535 ASSERT_TRUE(image_reader.LookUpExternalDefinedSymbol(_MH_EXECUTE_SYM, | 523 ASSERT_TRUE(image_reader.LookUpExternalDefinedSymbol(_MH_EXECUTE_SYM, |
| 536 &symbol_address)); | 524 &symbol_address)); |
| 537 EXPECT_EQ(mh_execute_header_address, symbol_address); | 525 EXPECT_EQ(mh_execute_header_address, symbol_address); |
| 538 | 526 |
| 539 ExpectSymbolTable(mh_execute_header, &image_reader); | 527 ASSERT_NO_FATAL_FAILURE(ExpectSymbolTable(mh_execute_header, &image_reader)); |
| 540 if (Test::HasFatalFailure()) { | |
| 541 return; | |
| 542 } | |
| 543 } | 528 } |
| 544 | 529 |
| 545 TEST(MachOImageReader, Self_DyldImages) { | 530 TEST(MachOImageReader, Self_DyldImages) { |
| 546 ProcessReader process_reader; | 531 ProcessReader process_reader; |
| 547 ASSERT_TRUE(process_reader.Initialize(mach_task_self())); | 532 ASSERT_TRUE(process_reader.Initialize(mach_task_self())); |
| 548 | 533 |
| 549 uint32_t count = _dyld_image_count(); | 534 uint32_t count = _dyld_image_count(); |
| 550 ASSERT_GE(count, 1u); | 535 ASSERT_GE(count, 1u); |
| 551 | 536 |
| 552 for (uint32_t index = 0; index < count; ++index) { | 537 for (uint32_t index = 0; index < count; ++index) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 566 image_reader.Initialize(&process_reader, image_address, image_name)); | 551 image_reader.Initialize(&process_reader, image_address, image_name)); |
| 567 | 552 |
| 568 uint32_t file_type = image_reader.FileType(); | 553 uint32_t file_type = image_reader.FileType(); |
| 569 if (index == 0) { | 554 if (index == 0) { |
| 570 EXPECT_EQ(static_cast<uint32_t>(MH_EXECUTE), file_type); | 555 EXPECT_EQ(static_cast<uint32_t>(MH_EXECUTE), file_type); |
| 571 } else { | 556 } else { |
| 572 EXPECT_TRUE(file_type == MH_DYLIB || file_type == MH_BUNDLE); | 557 EXPECT_TRUE(file_type == MH_DYLIB || file_type == MH_BUNDLE); |
| 573 } | 558 } |
| 574 | 559 |
| 575 intptr_t image_slide = _dyld_get_image_vmaddr_slide(index); | 560 intptr_t image_slide = _dyld_get_image_vmaddr_slide(index); |
| 576 ExpectMachImage( | 561 ASSERT_NO_FATAL_FAILURE(ExpectMachImage( |
| 577 mach_header, image_address, image_slide, &image_reader, false); | 562 mach_header, image_address, image_slide, &image_reader, false)); |
| 578 if (Test::HasFatalFailure()) { | |
| 579 return; | |
| 580 } | |
| 581 | 563 |
| 582 ExpectSymbolTable(mach_header, &image_reader); | 564 ASSERT_NO_FATAL_FAILURE(ExpectSymbolTable(mach_header, &image_reader)); |
| 583 if (Test::HasFatalFailure()) { | |
| 584 return; | |
| 585 } | |
| 586 } | 565 } |
| 587 | 566 |
| 588 // Now that all of the modules have been verified, make sure that dyld itself | 567 // Now that all of the modules have been verified, make sure that dyld itself |
| 589 // can be read properly too. | 568 // can be read properly too. |
| 590 const struct dyld_all_image_infos* dyld_image_infos = | 569 const struct dyld_all_image_infos* dyld_image_infos = |
| 591 _dyld_get_all_image_infos(); | 570 _dyld_get_all_image_infos(); |
| 592 ASSERT_GE(dyld_image_infos->version, 1u); | 571 ASSERT_GE(dyld_image_infos->version, 1u); |
| 593 EXPECT_EQ(count, dyld_image_infos->infoArrayCount); | 572 EXPECT_EQ(count, dyld_image_infos->infoArrayCount); |
| 594 | 573 |
| 595 if (dyld_image_infos->version >= 2) { | 574 if (dyld_image_infos->version >= 2) { |
| 596 SCOPED_TRACE("dyld"); | 575 SCOPED_TRACE("dyld"); |
| 597 | 576 |
| 598 // dyld_all_image_infos::dyldImageLoadAddress is poorly-declared too. | 577 // dyld_all_image_infos::dyldImageLoadAddress is poorly-declared too. |
| 599 const MachHeader* mach_header = reinterpret_cast<const MachHeader*>( | 578 const MachHeader* mach_header = reinterpret_cast<const MachHeader*>( |
| 600 dyld_image_infos->dyldImageLoadAddress); | 579 dyld_image_infos->dyldImageLoadAddress); |
| 601 mach_vm_address_t image_address = | 580 mach_vm_address_t image_address = |
| 602 reinterpret_cast<mach_vm_address_t>(mach_header); | 581 reinterpret_cast<mach_vm_address_t>(mach_header); |
| 603 | 582 |
| 604 MachOImageReader image_reader; | 583 MachOImageReader image_reader; |
| 605 ASSERT_TRUE( | 584 ASSERT_TRUE( |
| 606 image_reader.Initialize(&process_reader, image_address, "dyld")); | 585 image_reader.Initialize(&process_reader, image_address, "dyld")); |
| 607 | 586 |
| 608 EXPECT_EQ(static_cast<uint32_t>(MH_DYLINKER), image_reader.FileType()); | 587 EXPECT_EQ(static_cast<uint32_t>(MH_DYLINKER), image_reader.FileType()); |
| 609 | 588 |
| 610 // There’s no good API to get dyld’s slide, so don’t bother checking it. | 589 // There’s no good API to get dyld’s slide, so don’t bother checking it. |
| 611 ExpectMachImage( | 590 ASSERT_NO_FATAL_FAILURE(ExpectMachImage( |
| 612 mach_header, image_address, kSlideUnknown, &image_reader, false); | 591 mach_header, image_address, kSlideUnknown, &image_reader, false)); |
| 613 if (Test::HasFatalFailure()) { | |
| 614 return; | |
| 615 } | |
| 616 | 592 |
| 617 ExpectSymbolTable(mach_header, &image_reader); | 593 ASSERT_NO_FATAL_FAILURE(ExpectSymbolTable(mach_header, &image_reader)); |
| 618 if (Test::HasFatalFailure()) { | |
| 619 return; | |
| 620 } | |
| 621 } | 594 } |
| 622 | 595 |
| 623 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 | 596 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 |
| 624 // If dyld is new enough to record UUIDs, check the UUID of any module that | 597 // If dyld is new enough to record UUIDs, check the UUID of any module that |
| 625 // it says has one. Note that dyld doesn’t record UUIDs of anything that | 598 // it says has one. Note that dyld doesn’t record UUIDs of anything that |
| 626 // loaded out of the shared cache, but it should at least have a UUID for the | 599 // loaded out of the shared cache, but it should at least have a UUID for the |
| 627 // main executable if it has one. | 600 // main executable if it has one. |
| 628 if (dyld_image_infos->version >= 8 && dyld_image_infos->uuidArray) { | 601 if (dyld_image_infos->version >= 8 && dyld_image_infos->uuidArray) { |
| 629 for (uint32_t index = 0; | 602 for (uint32_t index = 0; |
| 630 index < dyld_image_infos->uuidArrayCount; | 603 index < dyld_image_infos->uuidArrayCount; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 654 image_reader.UUID(&actual_uuid); | 627 image_reader.UUID(&actual_uuid); |
| 655 EXPECT_EQ(expected_uuid, actual_uuid); | 628 EXPECT_EQ(expected_uuid, actual_uuid); |
| 656 } | 629 } |
| 657 } | 630 } |
| 658 #endif | 631 #endif |
| 659 } | 632 } |
| 660 | 633 |
| 661 } // namespace | 634 } // namespace |
| 662 } // namespace test | 635 } // namespace test |
| 663 } // namespace crashpad | 636 } // namespace crashpad |
| OLD | NEW |