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