7 changes: 4 additions & 3 deletions lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class PlatformDarwinKernel : public PlatformDarwin {
GetSharedModule(const lldb_private::ModuleSpec &module_spec,
lldb_private::Process *process, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules,
bool *did_create_ptr) override;

bool GetSupportedArchitectureAtIndex(uint32_t idx,
Expand Down Expand Up @@ -143,13 +143,14 @@ class PlatformDarwinKernel : public PlatformDarwin {
GetSharedModuleKext(const lldb_private::ModuleSpec &module_spec,
lldb_private::Process *process, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr);
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules,
bool *did_create_ptr);

lldb_private::Status GetSharedModuleKernel(
const lldb_private::ModuleSpec &module_spec,
lldb_private::Process *process, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr);
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr);

lldb_private::Status
ExamineKextForMatchingUUID(const lldb_private::FileSpec &kext_bundle_path,
Expand Down
21 changes: 12 additions & 9 deletions lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,10 +306,10 @@ lldb_private::Status PlatformMacOSX::GetSharedModule(
const lldb_private::ModuleSpec &module_spec, Process *process,
lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
Status error = GetSharedModuleWithLocalCache(
module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr);
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) {
Status error = GetSharedModuleWithLocalCache(module_spec, module_sp,
module_search_paths_ptr,
old_modules, did_create_ptr);

if (module_sp) {
if (module_spec.GetArchitecture().GetCore() ==
Expand All @@ -320,15 +320,16 @@ lldb_private::Status PlatformMacOSX::GetSharedModule(
ModuleSpec module_spec_x86_64(module_spec);
module_spec_x86_64.GetArchitecture() = ArchSpec("x86_64-apple-macosx");
lldb::ModuleSP x86_64_module_sp;
lldb::ModuleSP old_x86_64_module_sp;
llvm::SmallVector<lldb::ModuleSP, 1> old_x86_64_modules;
bool did_create = false;
Status x86_64_error = GetSharedModuleWithLocalCache(
module_spec_x86_64, x86_64_module_sp, module_search_paths_ptr,
&old_x86_64_module_sp, &did_create);
&old_x86_64_modules, &did_create);
if (x86_64_module_sp && x86_64_module_sp->GetObjectFile()) {
module_sp = x86_64_module_sp;
if (old_module_sp_ptr)
*old_module_sp_ptr = old_x86_64_module_sp;
if (old_modules)
old_modules->append(old_x86_64_modules.begin(),
old_x86_64_modules.end());
if (did_create_ptr)
*did_create_ptr = did_create;
return x86_64_error;
Expand All @@ -338,7 +339,9 @@ lldb_private::Status PlatformMacOSX::GetSharedModule(
}

if (!module_sp) {
error = FindBundleBinaryInExecSearchPaths (module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
error = FindBundleBinaryInExecSearchPaths(module_spec, process, module_sp,
module_search_paths_ptr,
old_modules, did_create_ptr);
}
return error;
}
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class PlatformMacOSX : public PlatformDarwin {
GetSharedModule(const lldb_private::ModuleSpec &module_spec,
lldb_private::Process *process, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules,
bool *did_create_ptr) override;

const char *GetDescription() override {
Expand Down
19 changes: 10 additions & 9 deletions lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,8 +504,8 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,

Status PlatformRemoteDarwinDevice::GetSharedModule(
const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
bool *did_create_ptr) {
const FileSpecList *module_search_paths_ptr,
llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) {
// For iOS, the SDK files are all cached locally on the host system. So first
// we ask for the file in the cached SDK, then we attempt to get a shared
// module for the right architecture with the right UUID.
Expand Down Expand Up @@ -608,24 +608,25 @@ Status PlatformRemoteDarwinDevice::GetSharedModule(
// This may not be an SDK-related module. Try whether we can bring in the
// thing to our local cache.
error = GetSharedModuleWithLocalCache(module_spec, module_sp,
module_search_paths_ptr,
old_module_sp_ptr, did_create_ptr);
module_search_paths_ptr, old_modules,
did_create_ptr);
if (error.Success())
return error;

// See if the file is present in any of the module_search_paths_ptr
// directories.
if (!module_sp)
error = PlatformDarwin::FindBundleBinaryInExecSearchPaths (module_spec, process, module_sp,
module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
error = PlatformDarwin::FindBundleBinaryInExecSearchPaths(
module_spec, process, module_sp, module_search_paths_ptr, old_modules,
did_create_ptr);

if (error.Success())
return error;

const bool always_create = false;
error = ModuleList::GetSharedModule(
module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr, always_create);
error = ModuleList::GetSharedModule(module_spec, module_sp,
module_search_paths_ptr, old_modules,
did_create_ptr, always_create);

if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class PlatformRemoteDarwinDevice : public PlatformDarwin {
GetSharedModule(const lldb_private::ModuleSpec &module_spec,
lldb_private::Process *process, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules,
bool *did_create_ptr) override;

void
Expand Down
27 changes: 13 additions & 14 deletions lldb/source/Target/Platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,14 @@ Platform::LocateExecutableScriptingResources(Target *target, Module &module,
// return PlatformSP();
//}

Status Platform::GetSharedModule(const ModuleSpec &module_spec,
Process *process, ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
ModuleSP *old_module_sp_ptr,
bool *did_create_ptr) {
Status Platform::GetSharedModule(
const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) {
if (IsHost())
return ModuleList::GetSharedModule(
module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr, false);
return ModuleList::GetSharedModule(module_spec, module_sp,
module_search_paths_ptr, old_modules,
did_create_ptr, false);

// Module resolver lambda.
auto resolver = [&](const ModuleSpec &spec) {
Expand All @@ -239,17 +238,17 @@ Status Platform::GetSharedModule(const ModuleSpec &module_spec,
resolved_spec.GetFileSpec().PrependPathComponent(
m_sdk_sysroot.GetStringRef());
// Try to get shared module with resolved spec.
error = ModuleList::GetSharedModule(
resolved_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr, false);
error = ModuleList::GetSharedModule(resolved_spec, module_sp,
module_search_paths_ptr, old_modules,
did_create_ptr, false);
}
// If we don't have sysroot or it didn't work then
// try original module spec.
if (!error.Success()) {
resolved_spec = spec;
error = ModuleList::GetSharedModule(
resolved_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr, false);
error = ModuleList::GetSharedModule(resolved_spec, module_sp,
module_search_paths_ptr, old_modules,
did_create_ptr, false);
}
if (error.Success() && module_sp)
module_sp->SetPlatformFileSpec(resolved_spec.GetFileSpec());
Expand Down
98 changes: 76 additions & 22 deletions lldb/source/Target/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1973,8 +1973,9 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
module_sp = m_images.FindFirstModule(module_spec);

if (!module_sp) {
ModuleSP old_module_sp; // This will get filled in if we have a new version
// of the library
llvm::SmallVector<ModuleSP, 1>
old_modules; // This will get filled in if we have a new version
// of the library
bool did_create_module = false;
FileSpecList search_paths = GetExecutableSearchPaths();
// If there are image search path entries, try to use them first to acquire
Expand All @@ -1987,7 +1988,7 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
transformed_spec.GetFileSpec().GetFilename() =
module_spec.GetFileSpec().GetFilename();
error = ModuleList::GetSharedModule(transformed_spec, module_sp,
&search_paths, &old_module_sp,
&search_paths, &old_modules,
&did_create_module);
}
}
Expand All @@ -2005,7 +2006,7 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
// We have a UUID, it is OK to check the global module list...
error =
ModuleList::GetSharedModule(module_spec, module_sp, &search_paths,
&old_module_sp, &did_create_module);
&old_modules, &did_create_module);
}

if (!module_sp) {
Expand All @@ -2014,7 +2015,7 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
if (m_platform_sp) {
error = m_platform_sp->GetSharedModule(
module_spec, m_process_sp.get(), module_sp, &search_paths,
&old_module_sp, &did_create_module);
&old_modules, &did_create_module);
} else {
error.SetErrorString("no platform is currently set");
}
Expand Down Expand Up @@ -2065,33 +2066,86 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
// this target. So let's remove the UUID from the module list, and look
// in the target's module list. Only do this if there is SOMETHING else
// in the module spec...
if (!old_module_sp) {
if (module_spec.GetUUID().IsValid() &&
!module_spec.GetFileSpec().GetFilename().IsEmpty() &&
!module_spec.GetFileSpec().GetDirectory().IsEmpty()) {
ModuleSpec module_spec_copy(module_spec.GetFileSpec());
module_spec_copy.GetUUID().Clear();

ModuleList found_modules;
m_images.FindModules(module_spec_copy, found_modules);
if (found_modules.GetSize() == 1)
old_module_sp = found_modules.GetModuleAtIndex(0);
}
if (module_spec.GetUUID().IsValid() &&
!module_spec.GetFileSpec().GetFilename().IsEmpty() &&
!module_spec.GetFileSpec().GetDirectory().IsEmpty()) {
ModuleSpec module_spec_copy(module_spec.GetFileSpec());
module_spec_copy.GetUUID().Clear();

ModuleList found_modules;
m_images.FindModules(module_spec_copy, found_modules);
found_modules.ForEach([&](const ModuleSP &found_module) -> bool {
old_modules.push_back(found_module);
return true;
});
}

// Preload symbols outside of any lock, so hopefully we can do this for
// each library in parallel.
if (GetPreloadSymbols())
module_sp->PreloadSymbols();

if (old_module_sp && m_images.GetIndexForModule(old_module_sp.get()) !=
LLDB_INVALID_INDEX32) {
m_images.ReplaceModule(old_module_sp, module_sp);
llvm::SmallVector<ModuleSP, 1> replaced_modules;
for (ModuleSP &old_module_sp : old_modules) {
if (m_images.GetIndexForModule(old_module_sp.get()) !=
LLDB_INVALID_INDEX32) {
if (replaced_modules.empty())
m_images.ReplaceModule(old_module_sp, module_sp);
else
m_images.Remove(old_module_sp);

replaced_modules.push_back(std::move(old_module_sp));
}
}

if (replaced_modules.size() > 1) {
// The same new module replaced multiple old modules
// simultaneously. It's not clear this should ever
// happen (if we always replace old modules as we add
// new ones, presumably we should never have more than
// one old one). If there are legitimate cases where
// this happens, then the ModuleList::Notifier interface
// may need to be adjusted to allow reporting this.
// In the meantime, just log that this has happened; just
// above we called ReplaceModule on the first one, and Remove
// on the rest.
if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET |
LIBLLDB_LOG_MODULES)) {
StreamString message;
auto dump = [&message](Module &dump_module) -> void {
UUID dump_uuid = dump_module.GetUUID();

message << '[';
dump_module.GetDescription(message.AsRawOstream());
message << " (uuid ";

if (dump_uuid.IsValid())
dump_uuid.Dump(&message);
else
message << "not specified";

message << ")]";
};

message << "New module ";
dump(*module_sp);
message.AsRawOstream()
<< llvm::formatv(" simultaneously replaced {0} old modules: ",
replaced_modules.size());
for (ModuleSP &replaced_module_sp : replaced_modules)
dump(*replaced_module_sp);

log->PutString(message.GetString());
}
}

if (replaced_modules.empty())
m_images.Append(module_sp, notify);

for (ModuleSP &old_module_sp : replaced_modules) {
Module *old_module_ptr = old_module_sp.get();
old_module_sp.reset();
ModuleList::RemoveSharedModuleIfOrphaned(old_module_ptr);
} else {
m_images.Append(module_sp, notify);
}
} else
module_sp.reset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ def verify_module(self, module, verify_path, verify_uuid):
os.path.normcase(module.GetFileSpec().dirname or ""))
self.assertEqual(verify_uuid, module.GetUUIDString())

def get_minidump_modules(self, yaml_file):
def get_minidump_modules(self, yaml_file, exe = None):
minidump_path = self.getBuildArtifact(os.path.basename(yaml_file) + ".dmp")
self.yaml2obj(yaml_file, minidump_path)
self.target = self.dbg.CreateTarget(None)
self.target = self.dbg.CreateTarget(exe)
self.process = self.target.LoadCore(minidump_path)
return self.target.modules

Expand Down Expand Up @@ -266,6 +266,24 @@ def test_breakpad_overflow_hash_match(self):
# will check that this matches.
self.verify_module(modules[0], so_path, "48EB9FD7")

def test_breakpad_hash_match_exe_outside_sysroot(self):
"""
Check that we can match the breakpad .text section hash when the
module is specified as the exe during launch, and a syroot is
provided, which does not contain the exe.
"""
sysroot_path = os.path.join(self.getBuildDir(), "mock_sysroot")
lldbutil.mkdir_p(sysroot_path)
so_dir = os.path.join(self.getBuildDir(), "binary")
so_path = os.path.join(so_dir, "libbreakpad.so")
lldbutil.mkdir_p(so_dir)
self.yaml2obj("libbreakpad.yaml", so_path)
self.runCmd("platform select remote-linux --sysroot '%s'" % sysroot_path)
modules = self.get_minidump_modules("linux-arm-breakpad-uuid-match.yaml", so_path)
self.assertEqual(1, len(modules))
# LLDB makes up its own UUID as well when there is no build ID so we
# will check that this matches.
self.verify_module(modules[0], so_path, "D9C480E8")

def test_facebook_hash_match(self):
"""
Expand Down