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 |