@@ -510,6 +510,53 @@ bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list,
510
510
return new_thread_list.GetSize (false ) > 0 ;
511
511
}
512
512
513
+ ModuleSP ProcessMinidump::GetOrCreateModule (UUID minidump_uuid,
514
+ llvm::StringRef name,
515
+ ModuleSpec module_spec) {
516
+ Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
517
+ Status error;
518
+
519
+ ModuleSP module_sp =
520
+ GetTarget ().GetOrCreateModule (module_spec, true /* notify */ , &error);
521
+ if (!module_sp)
522
+ return module_sp;
523
+ // We consider the module to be a match if the minidump UUID is a
524
+ // prefix of the actual UUID, or if either of the UUIDs are empty.
525
+ const auto dmp_bytes = minidump_uuid.GetBytes ();
526
+ const auto mod_bytes = module_sp->GetUUID ().GetBytes ();
527
+ const bool match = dmp_bytes.empty () || mod_bytes.empty () ||
528
+ mod_bytes.take_front (dmp_bytes.size ()) == dmp_bytes;
529
+ if (match) {
530
+ LLDB_LOG (log, " Partial uuid match for {0}." , name);
531
+ return module_sp;
532
+ }
533
+
534
+ // Breakpad generates minindump files, and if there is no GNU build
535
+ // ID in the binary, it will calculate a UUID by hashing first 4096
536
+ // bytes of the .text section and using that as the UUID for a module
537
+ // in the minidump. Facebook uses a modified breakpad client that
538
+ // uses a slightly modified this hash to avoid collisions. Check for
539
+ // UUIDs from the minindump that match these cases and accept the
540
+ // module we find if they do match.
541
+ std::vector<uint8_t > breakpad_uuid;
542
+ std::vector<uint8_t > facebook_uuid;
543
+ HashElfTextSection (module_sp, breakpad_uuid, facebook_uuid);
544
+ if (dmp_bytes == llvm::ArrayRef<uint8_t >(breakpad_uuid)) {
545
+ LLDB_LOG (log, " Breakpad .text hash match for {0}." , name);
546
+ return module_sp;
547
+ }
548
+ if (dmp_bytes == llvm::ArrayRef<uint8_t >(facebook_uuid)) {
549
+ LLDB_LOG (log, " Facebook .text hash match for {0}." , name);
550
+ return module_sp;
551
+ }
552
+ // The UUID wasn't a partial match and didn't match the .text hash
553
+ // so remove the module from the target, we will need to create a
554
+ // placeholder object file.
555
+ GetTarget ().GetImages ().Remove (module_sp);
556
+ module_sp.reset ();
557
+ return module_sp;
558
+ }
559
+
513
560
void ProcessMinidump::ReadModuleList () {
514
561
std::vector<const minidump::Module *> filtered_modules =
515
562
m_minidump_parser->GetFilteredModuleList ();
@@ -539,54 +586,22 @@ void ProcessMinidump::ReadModuleList() {
539
586
// add the module to the target if it finds one.
540
587
lldb::ModuleSP module_sp = GetTarget ().GetOrCreateModule (module_spec,
541
588
true /* notify */ , &error);
542
- if (!module_sp) {
543
- // Try and find a module without specifying the UUID and only looking for
544
- // the file given a basename. We then will look for a partial UUID match
545
- // if we find any matches. This function will add the module to the
546
- // target if it finds one, so we need to remove the module from the target
547
- // if the UUID doesn't match during our manual UUID verification. This
548
- // allows the "target.exec-search-paths" setting to specify one or more
549
- // directories that contain executables that can be searched for matches.
550
- ModuleSpec basename_module_spec (module_spec);
551
- basename_module_spec.GetUUID ().Clear ();
552
- basename_module_spec.GetFileSpec ().GetDirectory ().Clear ();
553
- module_sp = GetTarget ().GetOrCreateModule (basename_module_spec,
554
- true /* notify */ , &error);
555
- if (module_sp) {
556
- // We consider the module to be a match if the minidump UUID is a
557
- // prefix of the actual UUID, or if either of the UUIDs are empty.
558
- const auto dmp_bytes = uuid.GetBytes ();
559
- const auto mod_bytes = module_sp->GetUUID ().GetBytes ();
560
- const bool match = dmp_bytes.empty () || mod_bytes.empty () ||
561
- mod_bytes.take_front (dmp_bytes.size ()) == dmp_bytes;
562
- if (!match) {
563
- // Breakpad generates minindump files, and if there is no GNU build
564
- // ID in the binary, it will calculate a UUID by hashing first 4096
565
- // bytes of the .text section and using that as the UUID for a module
566
- // in the minidump. Facebook uses a modified breakpad client that
567
- // uses a slightly modified this hash to avoid collisions. Check for
568
- // UUIDs from the minindump that match these cases and accept the
569
- // module we find if they do match.
570
- std::vector<uint8_t > breakpad_uuid;
571
- std::vector<uint8_t > facebook_uuid;
572
- HashElfTextSection (module_sp, breakpad_uuid, facebook_uuid);
573
- if (dmp_bytes == llvm::ArrayRef<uint8_t >(breakpad_uuid)) {
574
- LLDB_LOG (log, " Breakpad .text hash match for {0}." , name);
575
- } else if (dmp_bytes == llvm::ArrayRef<uint8_t >(facebook_uuid)) {
576
- LLDB_LOG (log, " Facebook .text hash match for {0}." , name);
577
- } else {
578
- // The UUID wasn't a partial match and didn't match the .text hash
579
- // so remove the module from the target, we will need to create a
580
- // placeholder object file.
581
- GetTarget ().GetImages ().Remove (module_sp);
582
- module_sp.reset ();
583
- }
584
- } else {
585
- LLDB_LOG (log, " Partial uuid match for {0}." , name);
586
- }
587
- }
588
- } else {
589
+ if (module_sp) {
589
590
LLDB_LOG (log, " Full uuid match for {0}." , name);
591
+ } else {
592
+ // We couldn't find a module with an exactly-matching UUID. Sometimes
593
+ // a minidump UUID is only a partial match or is a hash. So try again
594
+ // without specifying the UUID, then again without specifying the
595
+ // directory if that fails. This will allow us to find modules with
596
+ // partial matches or hash UUIDs in user-provided sysroots or search
597
+ // directories (target.exec-search-paths).
598
+ ModuleSpec partial_module_spec = module_spec;
599
+ partial_module_spec.GetUUID ().Clear ();
600
+ module_sp = GetOrCreateModule (uuid, name, partial_module_spec);
601
+ if (!module_sp) {
602
+ partial_module_spec.GetFileSpec ().GetDirectory ().Clear ();
603
+ module_sp = GetOrCreateModule (uuid, name, partial_module_spec);
604
+ }
590
605
}
591
606
if (module_sp) {
592
607
// Watch out for place holder modules that have different paths, but the
0 commit comments