Rename Target::GetSharedModule to Target::GetOrCreateModule.

Add a flag to control whether the ModulesDidLoad notification is
called when a module is added.  If the notifications are disabled,
the caller must call ModulesDidLoad after adding all the new modules,
but postponing this notification until they're all batched up can
allow for better efficiency than notifying one-by-one.

Change the name of the ModuleList notifier functions that a subclass
can implement to start with 'Notify' to make it clear what they are.
Add a NotifyModulesRemoved.

Add header documentation for the changed/updated methods.

Added defaulted-value 'notify' argument to ModuleList Append,
AppendIfNeeded, and Remove because callers working with a local
ModuleList don't have an obvious idea of what notify means in this
context.  When the ModuleList is a part of the Target class, the
notify behavior matters.

DynamicLoaderDarwin has been updated so that libraries being
added/removed are correctly batched up before notifications are
sent.  Added the TestModuleLoadedNotifys.py test to run on 
Darwin to test this.

<rdar://problem/48293064> 

Differential Revision: https://reviews.llvm.org/D60172

llvm-svn: 357955
This commit is contained in:
Jason Molenda
2019-04-08 23:03:02 +00:00
parent e794752bdf
commit 1724a179e7
19 changed files with 305 additions and 68 deletions

View File

@@ -96,14 +96,16 @@ public:
public:
virtual ~Notifier() = default;
virtual void ModuleAdded(const ModuleList &module_list,
const lldb::ModuleSP &module_sp) = 0;
virtual void ModuleRemoved(const ModuleList &module_list,
const lldb::ModuleSP &module_sp) = 0;
virtual void ModuleUpdated(const ModuleList &module_list,
const lldb::ModuleSP &old_module_sp,
const lldb::ModuleSP &new_module_sp) = 0;
virtual void WillClearList(const ModuleList &module_list) = 0;
virtual void NotifyModuleAdded(const ModuleList &module_list,
const lldb::ModuleSP &module_sp) = 0;
virtual void NotifyModuleRemoved(const ModuleList &module_list,
const lldb::ModuleSP &module_sp) = 0;
virtual void NotifyModuleUpdated(const ModuleList &module_list,
const lldb::ModuleSP &old_module_sp,
const lldb::ModuleSP &new_module_sp) = 0;
virtual void NotifyWillClearList(const ModuleList &module_list) = 0;
virtual void NotifyModulesRemoved(lldb_private::ModuleList &module_list) = 0;
};
//------------------------------------------------------------------
@@ -146,12 +148,20 @@ public:
//------------------------------------------------------------------
/// Append a module to the module list.
///
/// Appends the module to the collection.
///
/// \param[in] module_sp
/// A shared pointer to a module to add to this collection.
///
/// \param[in] notify
/// If true, and a notifier function is set, the notifier function
/// will be called. Defaults to true.
///
/// When this ModuleList is the Target's ModuleList, the notifier
/// function is Target::ModulesDidLoad -- the call to
/// ModulesDidLoad may be deferred when adding multiple Modules
/// to the Target, but it must be called at the end,
/// before resuming execution.
//------------------------------------------------------------------
void Append(const lldb::ModuleSP &module_sp);
void Append(const lldb::ModuleSP &module_sp, bool notify = true);
//------------------------------------------------------------------
/// Append a module to the module list and remove any equivalent modules.
@@ -165,7 +175,22 @@ public:
//------------------------------------------------------------------
void ReplaceEquivalent(const lldb::ModuleSP &module_sp);
bool AppendIfNeeded(const lldb::ModuleSP &module_sp);
//------------------------------------------------------------------
/// Append a module to the module list, if it is not already there.
///
/// \param[in] module_sp
///
/// \param[in] notify
/// If true, and a notifier function is set, the notifier function
/// will be called. Defaults to true.
///
/// When this ModuleList is the Target's ModuleList, the notifier
/// function is Target::ModulesDidLoad -- the call to
/// ModulesDidLoad may be deferred when adding multiple Modules
/// to the Target, but it must be called at the end,
/// before resuming execution.
//------------------------------------------------------------------
bool AppendIfNeeded(const lldb::ModuleSP &module_sp, bool notify = true);
void Append(const ModuleList &module_list);
@@ -481,7 +506,23 @@ public:
std::vector<Address> &output_local,
std::vector<Address> &output_extern);
bool Remove(const lldb::ModuleSP &module_sp);
//------------------------------------------------------------------
/// Remove a module from the module list.
///
/// \param[in] module_sp
/// A shared pointer to a module to remove from this collection.
///
/// \param[in] notify
/// If true, and a notifier function is set, the notifier function
/// will be called. Defaults to true.
///
/// When this ModuleList is the Target's ModuleList, the notifier
/// function is Target::ModulesDidUnload -- the call to
/// ModulesDidUnload may be deferred when removing multiple Modules
/// from the Target, but it must be called at the end,
/// before resuming execution.
//------------------------------------------------------------------
bool Remove(const lldb::ModuleSP &module_sp, bool notify = true);
size_t Remove(ModuleList &module_list);

View File

@@ -505,8 +505,42 @@ public:
static void SetDefaultArchitecture(const ArchSpec &arch);
lldb::ModuleSP GetSharedModule(const ModuleSpec &module_spec,
Status *error_ptr = nullptr);
//------------------------------------------------------------------
/// Find a binary on the system and return its Module,
/// or return an existing Module that is already in the Target.
///
/// Given a ModuleSpec, find a binary satisifying that specification,
/// or identify a matching Module already present in the Target,
/// and return a shared pointer to it.
///
/// \param[in] module_spec
/// The criteria that must be matched for the binary being loaded.
/// e.g. UUID, architecture, file path.
///
/// \param[in] notify
/// If notify is true, and the Module is new to this Target,
/// Target::ModulesDidLoad will be called.
/// If notify is false, it is assumed that the caller is adding
/// multiple Modules and will call ModulesDidLoad with the
/// full list at the end.
/// ModulesDidLoad must be called when a Module/Modules have
/// been added to the target, one way or the other.
///
/// \param[out] error_ptr
/// Optional argument, pointing to a Status object to fill in
/// with any results / messages while attempting to find/load
/// this binary. Many callers will be internal functions that
/// will handle / summarize the failures in a custom way and
/// don't use these messages.
///
/// \return
/// An empty ModuleSP will be returned if no matching file
/// was found. If error_ptr was non-nullptr, an error message
/// will likely be provided.
//------------------------------------------------------------------
lldb::ModuleSP GetOrCreateModule(const ModuleSpec &module_spec,
bool notify,
Status *error_ptr = nullptr);
//----------------------------------------------------------------------
// Settings accessors
@@ -1250,16 +1284,19 @@ protected:
/// Implementing of ModuleList::Notifier.
//------------------------------------------------------------------
void ModuleAdded(const ModuleList &module_list,
const lldb::ModuleSP &module_sp) override;
void NotifyModuleAdded(const ModuleList &module_list,
const lldb::ModuleSP &module_sp) override;
void ModuleRemoved(const ModuleList &module_list,
const lldb::ModuleSP &module_sp) override;
void NotifyModuleRemoved(const ModuleList &module_list,
const lldb::ModuleSP &module_sp) override;
void ModuleUpdated(const ModuleList &module_list,
const lldb::ModuleSP &old_module_sp,
const lldb::ModuleSP &new_module_sp) override;
void WillClearList(const ModuleList &module_list) override;
void NotifyModuleUpdated(const ModuleList &module_list,
const lldb::ModuleSP &old_module_sp,
const lldb::ModuleSP &new_module_sp) override;
void NotifyWillClearList(const ModuleList &module_list) override;
void NotifyModulesRemoved(lldb_private::ModuleList &module_list) override;
class Arch {
public:

View File

@@ -0,0 +1,5 @@
LEVEL = ../../make
CXX_SOURCES := main.cpp
include $(LEVEL)/Makefile.rules

View File

@@ -0,0 +1,114 @@
"""
Test how many times newly loaded binaries are notified;
they should be delivered in batches instead of one-by-one.
"""
from __future__ import print_function
import os
import time
import re
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class ModuleLoadedNotifysTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
NO_DEBUG_INFO_TESTCASE = True
# DyanmicLoaderDarwin should batch up notifications about
# newly added/removed libraries. Other DynamicLoaders may
# not be written this way.
@skipUnlessDarwin
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
# Find the line number to break inside main().
self.line = line_number('main.cpp', '// breakpoint')
def test_launch_notifications(self):
"""Test that lldb broadcasts newly loaded libraries in batches."""
self.build()
exe = self.getBuildArtifact("a.out")
self.dbg.SetAsync(False)
listener = self.dbg.GetListener()
listener.StartListeningForEventClass(
self.dbg,
lldb.SBTarget.GetBroadcasterClassName(),
lldb.SBTarget.eBroadcastBitModulesLoaded | lldb.SBTarget.eBroadcastBitModulesUnloaded)
# Create a target by the debugger.
target = self.dbg.CreateTarget(exe)
self.assertTrue(target, VALID_TARGET)
# break on main
breakpoint = target.BreakpointCreateByName('main', 'a.out')
event = lldb.SBEvent()
# CreateTarget() generated modules-loaded events; consume them & toss
while listener.GetNextEvent(event):
True
error = lldb.SBError()
process = target.Launch(listener,
None, # argv
None, # envp
None, # stdin_path
None, # stdout_path
None, # stderr_path
None, # working directory
0, # launch flags
False, # Stop at entry
error) # error
self.assertTrue(
process.GetState() == lldb.eStateStopped,
PROCESS_STOPPED)
total_solibs_added = 0
total_solibs_removed = 0
total_modules_added_events = 0
total_modules_removed_events = 0
while listener.GetNextEvent(event):
if lldb.SBTarget.EventIsTargetEvent(event):
if event.GetType() == lldb.SBTarget.eBroadcastBitModulesLoaded:
solib_count = lldb.SBTarget.GetNumModulesFromEvent(event)
total_modules_added_events += 1
total_solibs_added += solib_count
if self.TraceOn():
# print all of the binaries that have been added
added_files = []
i = 0
while i < solib_count:
module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event)
added_files.append(module.GetFileSpec().GetFilename())
i = i + 1
print("Loaded files: %s" % (', '.join(added_files)))
if event.GetType() == lldb.SBTarget.eBroadcastBitModulesUnloaded:
solib_count = lldb.SBTarget.GetNumModulesFromEvent(event)
total_modules_removed_events += 1
total_solibs_removed += solib_count
if self.TraceOn():
# print all of the binaries that have been removed
removed_files = []
i = 0
while i < solib_count:
module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event)
removed_files.append(module.GetFileSpec().GetFilename())
i = i + 1
print("Unloaded files: %s" % (', '.join(removed_files)))
# This is testing that we get back a small number of events with the loaded
# binaries in batches. Check that we got back more than 1 solib per event.
# In practice on Darwin today, we get back two events for a do-nothing c
# program: a.out and dyld, and then all the rest of the system libraries.
avg_solibs_added_per_event = int(float(total_solibs_added) / float(total_modules_added_events))
self.assertGreater(avg_solibs_added_per_event, 1)

View File

@@ -0,0 +1,6 @@
#include <stdio.h>
int main ()
{
puts("running"); // breakpoint here
return 0;
}

View File

@@ -1591,7 +1591,7 @@ lldb::SBModule SBTarget::AddModule(const char *path, const char *triple,
if (symfile)
module_spec.GetSymbolFileSpec().SetFile(symfile, FileSpec::Style::native);
sb_module.SetSP(target_sp->GetSharedModule(module_spec));
sb_module.SetSP(target_sp->GetOrCreateModule(module_spec, true /* notify */));
}
return LLDB_RECORD_RESULT(sb_module);
}
@@ -1603,7 +1603,8 @@ lldb::SBModule SBTarget::AddModule(const SBModuleSpec &module_spec) {
lldb::SBModule sb_module;
TargetSP target_sp(GetSP());
if (target_sp)
sb_module.SetSP(target_sp->GetSharedModule(*module_spec.m_opaque_up));
sb_module.SetSP(target_sp->GetOrCreateModule(*module_spec.m_opaque_up,
true /* notify */));
return LLDB_RECORD_RESULT(sb_module);
}

View File

@@ -395,7 +395,8 @@ protected:
debugger.GetTargetList().SetSelectedTarget(target_sp.get());
if (must_set_platform_path) {
ModuleSpec main_module_spec(file_spec);
ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec);
ModuleSP module_sp = target_sp->GetOrCreateModule(main_module_spec,
true /* notify */);
if (module_sp)
module_sp->SetPlatformFileSpec(remote_file);
}
@@ -2598,7 +2599,8 @@ protected:
module_spec.GetSymbolFileSpec() =
m_symbol_file.GetOptionValue().GetCurrentValue();
if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
ModuleSP module_sp(target->GetSharedModule(module_spec));
ModuleSP module_sp(target->GetOrCreateModule(module_spec,
true /* notify */));
if (module_sp) {
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
@@ -2660,7 +2662,8 @@ protected:
if (!module_spec.GetArchitecture().IsValid())
module_spec.GetArchitecture() = target->GetArchitecture();
Status error;
ModuleSP module_sp(target->GetSharedModule(module_spec, &error));
ModuleSP module_sp(target->GetOrCreateModule(module_spec,
true /* notify */, &error));
if (!module_sp) {
const char *error_cstr = error.AsCString();
if (error_cstr)

View File

@@ -96,7 +96,7 @@ ModuleSP DynamicLoader::GetTargetExecutable() {
}
if (!executable) {
executable = target.GetSharedModule(module_spec);
executable = target.GetOrCreateModule(module_spec, true /* notify */);
if (executable.get() != target.GetExecutableModulePointer()) {
// Don't load dependent images since we are in dyld where we will
// know and find out about all images that are loaded
@@ -166,7 +166,8 @@ ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
return module_sp;
}
if ((module_sp = target.GetSharedModule(module_spec))) {
if ((module_sp = target.GetOrCreateModule(module_spec,
true /* notify */))) {
UpdateLoadedSections(module_sp, link_map_addr, base_addr,
base_addr_is_offset);
return module_sp;
@@ -202,7 +203,8 @@ ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
return module_sp;
}
if ((module_sp = target.GetSharedModule(new_module_spec))) {
if ((module_sp = target.GetOrCreateModule(new_module_spec,
true /* notify */))) {
UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
return module_sp;
}

View File

@@ -147,11 +147,13 @@ void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
m_modules.push_back(module_sp);
if (use_notifier && m_notifier)
m_notifier->ModuleAdded(*this, module_sp);
m_notifier->NotifyModuleAdded(*this, module_sp);
}
}
void ModuleList::Append(const ModuleSP &module_sp) { AppendImpl(module_sp); }
void ModuleList::Append(const ModuleSP &module_sp, bool notify) {
AppendImpl(module_sp, notify);
}
void ModuleList::ReplaceEquivalent(const ModuleSP &module_sp) {
if (module_sp) {
@@ -177,7 +179,7 @@ void ModuleList::ReplaceEquivalent(const ModuleSP &module_sp) {
}
}
bool ModuleList::AppendIfNeeded(const ModuleSP &module_sp) {
bool ModuleList::AppendIfNeeded(const ModuleSP &module_sp, bool notify) {
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
collection::iterator pos, end = m_modules.end();
@@ -186,7 +188,7 @@ bool ModuleList::AppendIfNeeded(const ModuleSP &module_sp) {
return false; // Already in the list
}
// Only push module_sp on the list if it wasn't already in there.
Append(module_sp);
Append(module_sp, notify);
return true;
}
return false;
@@ -214,7 +216,7 @@ bool ModuleList::RemoveImpl(const ModuleSP &module_sp, bool use_notifier) {
if (pos->get() == module_sp.get()) {
m_modules.erase(pos);
if (use_notifier && m_notifier)
m_notifier->ModuleRemoved(*this, module_sp);
m_notifier->NotifyModuleRemoved(*this, module_sp);
return true;
}
}
@@ -228,12 +230,12 @@ ModuleList::RemoveImpl(ModuleList::collection::iterator pos,
ModuleSP module_sp(*pos);
collection::iterator retval = m_modules.erase(pos);
if (use_notifier && m_notifier)
m_notifier->ModuleRemoved(*this, module_sp);
m_notifier->NotifyModuleRemoved(*this, module_sp);
return retval;
}
bool ModuleList::Remove(const ModuleSP &module_sp) {
return RemoveImpl(module_sp);
bool ModuleList::Remove(const ModuleSP &module_sp, bool notify) {
return RemoveImpl(module_sp, notify);
}
bool ModuleList::ReplaceModule(const lldb::ModuleSP &old_module_sp,
@@ -242,7 +244,7 @@ bool ModuleList::ReplaceModule(const lldb::ModuleSP &old_module_sp,
return false;
AppendImpl(new_module_sp, false);
if (m_notifier)
m_notifier->ModuleUpdated(*this, old_module_sp, new_module_sp);
m_notifier->NotifyModuleUpdated(*this, old_module_sp, new_module_sp);
return true;
}
@@ -291,9 +293,11 @@ size_t ModuleList::Remove(ModuleList &module_list) {
size_t num_removed = 0;
collection::iterator pos, end = module_list.m_modules.end();
for (pos = module_list.m_modules.begin(); pos != end; ++pos) {
if (Remove(*pos))
if (Remove(*pos, false /* notify */))
++num_removed;
}
if (m_notifier)
m_notifier->NotifyModulesRemoved(module_list);
return num_removed;
}
@@ -304,7 +308,7 @@ void ModuleList::Destroy() { ClearImpl(); }
void ModuleList::ClearImpl(bool use_notifier) {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
if (use_notifier && m_notifier)
m_notifier->WillClearList(*this);
m_notifier->NotifyWillClearList(*this);
m_modules.clear();
}

View File

@@ -103,7 +103,8 @@ bool FunctionCaller::WriteFunctionWrapper(
jit_file.GetFilename() = const_func_name;
jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
m_jit_module_wp = jit_module_sp;
process->GetTarget().GetImages().Append(jit_module_sp);
process->GetTarget().GetImages().Append(jit_module_sp,
true /* notify */);
}
}
if (process && m_jit_start_addr)

View File

@@ -841,7 +841,7 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
// the DebugSymbols framework with the UUID to find the binary via its
// search methods.
if (!m_module_sp) {
m_module_sp = target.GetSharedModule(module_spec);
m_module_sp = target.GetOrCreateModule(module_spec, true /* notify */);
}
if (IsKernel() && !m_module_sp) {

View File

@@ -199,7 +199,7 @@ ModuleSP DynamicLoaderHexagonDYLD::GetTargetExecutable() {
return executable;
// TODO: What case is this code used?
executable = target.GetSharedModule(module_spec);
executable = target.GetOrCreateModule(module_spec, true /* notify */);
if (executable.get() != target.GetExecutableModulePointer()) {
// Don't load dependent images since we are in dyld where we will know and
// find out about all images that are loaded

View File

@@ -122,7 +122,9 @@ ModuleSP DynamicLoaderDarwin::FindTargetModuleForImageInfo(
if (!module_sp) {
if (can_create) {
module_sp = target.GetSharedModule(module_spec);
// We'll call Target::ModulesDidLoad after all the modules have been
// added to the target, don't let it be called for every one.
module_sp = target.GetOrCreateModule(module_spec, false /* notify */);
if (!module_sp || module_sp->GetObjectFile() == NULL)
module_sp = m_process->ReadModuleFromMemory(image_info.file_spec,
image_info.address);
@@ -637,7 +639,8 @@ bool DynamicLoaderDarwin::AddModulesUsingImageInfos(
module_spec.SetObjectOffset(objfile->GetFileOffset() +
commpage_section->GetFileOffset());
module_spec.SetObjectSize(objfile->GetByteSize());
commpage_image_module_sp = target.GetSharedModule(module_spec);
commpage_image_module_sp = target.GetOrCreateModule(module_spec,
true /* notify */);
if (!commpage_image_module_sp ||
commpage_image_module_sp->GetObjectFile() == NULL) {
commpage_image_module_sp = m_process->ReadModuleFromMemory(

View File

@@ -543,7 +543,8 @@ ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {
FileSpec file(info.GetName().GetCString());
ModuleSpec module_spec(file, target.GetArchitecture());
if (ModuleSP module_sp = target.GetSharedModule(module_spec)) {
if (ModuleSP module_sp = target.GetOrCreateModule(module_spec,
true /* notify */)) {
UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base,
false);
return module_sp;

View File

@@ -68,11 +68,9 @@ void DynamicLoaderWindowsDYLD::OnLoadModule(lldb::ModuleSP module_sp,
// Resolve the module unless we already have one.
if (!module_sp) {
// Confusingly, there is no Target::AddSharedModule. Instead, calling
// GetSharedModule() with a new module will add it to the module list and
// return a corresponding ModuleSP.
Status error;
module_sp = m_process->GetTarget().GetSharedModule(module_spec, &error);
module_sp = m_process->GetTarget().GetOrCreateModule(module_spec,
true /* notify */, &error);
if (error.Fail())
return;
}

View File

@@ -915,7 +915,8 @@ void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
FileSystem::Instance().Resolve(executable_file);
ModuleSpec module_spec(executable_file);
Status error;
module = GetTarget().GetSharedModule(module_spec, &error);
module = GetTarget().GetOrCreateModule(module_spec,
true /* notify */, &error);
if (!module) {
return;
}

View File

@@ -244,7 +244,8 @@ Status ProcessElfCore::DoLoadCore() {
exe_module_spec.GetFileSpec().SetFile(
m_nt_file_entries[0].path.GetCString(), FileSpec::Style::native);
if (exe_module_spec.GetFileSpec()) {
exe_module_sp = GetTarget().GetSharedModule(exe_module_spec);
exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec,
true /* notify */);
if (exe_module_sp)
GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo);
}

View File

@@ -388,7 +388,8 @@ void ProcessMinidump::ReadModuleList() {
Status error;
// Try and find a module with a full UUID that matches. This function will
// add the module to the target if it finds one.
lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error);
lldb::ModuleSP module_sp = GetTarget().GetOrCreateModule(module_spec,
true /* notify */, &error);
if (!module_sp) {
// Try and find a module without specifying the UUID and only looking for
// the file given a basename. We then will look for a partial UUID match
@@ -400,7 +401,8 @@ void ProcessMinidump::ReadModuleList() {
ModuleSpec basename_module_spec(module_spec);
basename_module_spec.GetUUID().Clear();
basename_module_spec.GetFileSpec().GetDirectory().Clear();
module_sp = GetTarget().GetSharedModule(basename_module_spec, &error);
module_sp = GetTarget().GetOrCreateModule(basename_module_spec,
true /* notify */, &error);
if (module_sp) {
// We consider the module to be a match if the minidump UUID is a
// prefix of the actual UUID, or if either of the UUIDs are empty.
@@ -430,7 +432,7 @@ void ProcessMinidump::ReadModuleList() {
module_sp = Module::CreateModuleFromObjectFile<PlaceholderObjectFile>(
module_spec, module->base_of_image, module->size_of_image);
GetTarget().GetImages().Append(module_sp);
GetTarget().GetImages().Append(module_sp, true /* notify */);
}
bool load_addr_changed = false;

View File

@@ -1442,7 +1442,8 @@ void Target::SetExecutableModule(ModuleSP &executable_sp,
"Target::SetExecutableModule (executable = '%s')",
executable_sp->GetFileSpec().GetPath().c_str());
m_images.Append(executable_sp); // The first image is our executable file
const bool notify = true;
m_images.Append(executable_sp, notify); // The first image is our executable file
// If we haven't set an architecture yet, reset our architecture based on
// what we found in the executable module.
@@ -1470,6 +1471,7 @@ void Target::SetExecutableModule(ModuleSP &executable_sp,
}
if (executable_objfile && load_dependents) {
ModuleList added_modules;
executable_objfile->GetDependentModules(dependent_files);
for (uint32_t i = 0; i < dependent_files.GetSize(); i++) {
FileSpec dependent_file_spec(
@@ -1482,13 +1484,16 @@ void Target::SetExecutableModule(ModuleSP &executable_sp,
platform_dependent_file_spec = dependent_file_spec;
ModuleSpec module_spec(platform_dependent_file_spec, m_arch.GetSpec());
ModuleSP image_module_sp(GetSharedModule(module_spec));
ModuleSP image_module_sp(GetOrCreateModule(module_spec,
false /* notify */));
if (image_module_sp) {
added_modules.AppendIfNeeded (image_module_sp, false);
ObjectFile *objfile = image_module_sp->GetObjectFile();
if (objfile)
objfile->GetDependentModules(dependent_files);
}
}
ModulesDidLoad(added_modules);
}
}
}
@@ -1606,20 +1611,19 @@ bool Target::MergeArchitecture(const ArchSpec &arch_spec) {
return false;
}
void Target::WillClearList(const ModuleList &module_list) {}
void Target::NotifyWillClearList(const ModuleList &module_list) {}
void Target::ModuleAdded(const ModuleList &module_list,
void Target::NotifyModuleAdded(const ModuleList &module_list,
const ModuleSP &module_sp) {
// A module is being added to this target for the first time
if (m_valid) {
ModuleList my_module_list;
my_module_list.Append(module_sp);
LoadScriptingResourceForModule(module_sp, this);
ModulesDidLoad(my_module_list);
}
}
void Target::ModuleRemoved(const ModuleList &module_list,
void Target::NotifyModuleRemoved(const ModuleList &module_list,
const ModuleSP &module_sp) {
// A module is being removed from this target.
if (m_valid) {
@@ -1629,7 +1633,7 @@ void Target::ModuleRemoved(const ModuleList &module_list,
}
}
void Target::ModuleUpdated(const ModuleList &module_list,
void Target::NotifyModuleUpdated(const ModuleList &module_list,
const ModuleSP &old_module_sp,
const ModuleSP &new_module_sp) {
// A module is replacing an already added module
@@ -1641,8 +1645,20 @@ void Target::ModuleUpdated(const ModuleList &module_list,
}
}
void Target::NotifyModulesRemoved(lldb_private::ModuleList &module_list) {
ModulesDidUnload (module_list, false);
}
void Target::ModulesDidLoad(ModuleList &module_list) {
if (m_valid && module_list.GetSize()) {
const ModuleList &modules = GetImages();
const size_t num_images = modules.GetSize();
for (size_t idx = 0; idx < num_images; ++idx) {
ModuleSP module_sp(modules.GetModuleAtIndex(idx));
LoadScriptingResourceForModule(module_sp, this);
}
m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false);
if (m_process_sp) {
@@ -1984,8 +2000,8 @@ bool Target::ReadPointerFromMemory(const Address &addr, bool prefer_file_cache,
return false;
}
ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec,
Status *error_ptr) {
ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
Status *error_ptr) {
ModuleSP module_sp;
Status error;
@@ -2118,8 +2134,9 @@ ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec,
Module *old_module_ptr = old_module_sp.get();
old_module_sp.reset();
ModuleList::RemoveSharedModuleIfOrphaned(old_module_ptr);
} else
m_images.Append(module_sp);
} else {
m_images.Append(module_sp, notify);
}
} else
module_sp.reset();
}