<rdar://problem/10103468>
I started work on being able to add symbol files after a debug session
had started with a new "target symfile add" command and quickly ran into
problems with stale Address objects in breakpoint locations that had
lldb_private::Section pointers into modules that had been removed or
replaced. This also let to grabbing stale modules from those sections.
So I needed to thread harded the Address, Section and related objects.
To do this I modified the ModuleChild class to now require a ModuleSP
on initialization so that a weak reference can created. I also changed
all places that were handing out "Section *" to have them hand out SectionSP.
All ObjectFile, SymbolFile and SymbolVendors were inheriting from ModuleChild
so all of the find plug-in, static creation function and constructors now
require ModuleSP references instead of Module *.
Address objects now have weak references to their sections which can
safely go stale when a module gets destructed.
This checkin doesn't complete the "target symfile add" command, but it
does get us a lot clioser to being able to do such things without a high
risk of crashing or memory corruption.
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@151336 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp
index 5d8cb5b..df2f080 100644
--- a/source/Commands/CommandObjectTarget.cpp
+++ b/source/Commands/CommandObjectTarget.cpp
@@ -1361,16 +1361,13 @@
}
static bool
-LookupAddressInModule
-(
- CommandInterpreter &interpreter,
- Stream &strm,
- Module *module,
- uint32_t resolve_mask,
- lldb::addr_t raw_addr,
- lldb::addr_t offset,
- bool verbose
- )
+LookupAddressInModule (CommandInterpreter &interpreter,
+ Stream &strm,
+ Module *module,
+ uint32_t resolve_mask,
+ lldb::addr_t raw_addr,
+ lldb::addr_t offset,
+ bool verbose)
{
if (module)
{
@@ -1382,7 +1379,7 @@
{
if (!target->GetSectionLoadList().ResolveLoadAddress (addr, so_addr))
return false;
- else if (so_addr.GetModulePtr() != module)
+ else if (so_addr.GetModule().get() != module)
return false;
}
else
@@ -2821,10 +2818,10 @@
Address module_address;
if (module_address.SetLoadAddress(m_options.m_module_addr, target))
{
- Module *module = module_address.GetModulePtr();
- if (module)
+ ModuleSP module_sp (module_address.GetModule());
+ if (module_sp)
{
- PrintModule (target, module, UINT32_MAX, 0, strm);
+ PrintModule (target, module_sp.get(), UINT32_MAX, 0, strm);
result.SetStatus (eReturnStatusSuccessFinishResult);
}
else
@@ -3511,6 +3508,205 @@
};
+
+class CommandObjectTargetSymbolsAdd : public CommandObject
+{
+public:
+ CommandObjectTargetSymbolsAdd (CommandInterpreter &interpreter) :
+ CommandObject (interpreter,
+ "target symbols add",
+ "Add a debug symbol file to one of the target's current modules.",
+ "target symbols add [<symfile>]")
+ {
+ }
+
+ virtual
+ ~CommandObjectTargetSymbolsAdd ()
+ {
+ }
+
+ virtual bool
+ Execute (Args& args,
+ CommandReturnObject &result)
+ {
+ Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, create a debug target using the 'target create' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ const size_t argc = args.GetArgumentCount();
+ if (argc == 0)
+ {
+ result.AppendError ("one or more symbol file paths must be specified");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ for (size_t i=0; i<argc; ++i)
+ {
+ const char *symfile_path = args.GetArgumentAtIndex(i);
+ if (symfile_path)
+ {
+ FileSpec symfile_spec(symfile_path, true);
+ ArchSpec arch;
+ if (symfile_spec.Exists())
+ {
+ ModuleSP symfile_module_sp (new Module (symfile_spec, target->GetArchitecture()));
+ if (symfile_module_sp)
+ {
+ // We now have a module that represents a symbol file
+ // that can be used for a module that might exist in the
+ // current target, so we need to find that module in the
+ // target
+
+ ModuleSP old_module_sp (target->GetImages().FindModule (symfile_module_sp->GetUUID()));
+ if (old_module_sp)
+ {
+ const bool can_create = false;
+ if (old_module_sp->GetSymbolVendor (can_create))
+ {
+ // The current module already has a symbol file, so we need
+ // need to unload the existing references to this module,
+ // and reload with the new one.
+
+ ModuleSP target_exe_module_sp (target->GetExecutableModule());
+ const bool adding_symbols_to_executable = target_exe_module_sp.get() == old_module_sp.get();
+ FileSpec target_module_file (old_module_sp->GetFileSpec());
+ ArchSpec target_module_arch (old_module_sp->GetArchitecture());
+
+ // Unload the old module
+ ModuleList module_list;
+ module_list.Append (old_module_sp);
+ target->ModulesDidUnload (module_list);
+
+ // Remove the module from the shared list
+ ModuleList::RemoveSharedModule (old_module_sp);
+
+ // Now create the new module and load it
+ module_list.Clear();
+ //ModuleSP new_module_sp (new Module (target_module_file, target_module_arch));
+ ModuleSP new_module_sp (target->GetSharedModule(target_module_file, target_module_arch));
+ if (new_module_sp)
+ {
+ new_module_sp->SetSymbolFileFileSpec (symfile_module_sp->GetFileSpec());
+
+ if (adding_symbols_to_executable)
+ {
+ bool get_dependent_files = true;
+ target->SetExecutableModule(new_module_sp, get_dependent_files);
+ }
+ else
+ {
+ module_list.Append (new_module_sp);
+ target->ModulesDidLoad(module_list);
+ }
+ }
+ }
+ else
+ {
+ // The module has not yet created its symbol vendor, we can just
+ // give the existing target module the symfile path to use for
+ // when it decides to create it!
+ old_module_sp->SetSymbolFileFileSpec (symfile_module_sp->GetFileSpec());
+ }
+ }
+ }
+ else
+ {
+ result.AppendError ("one or more executable image paths must be specified");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ char resolved_symfile_path[PATH_MAX];
+ result.SetStatus (eReturnStatusFailed);
+ if (symfile_spec.GetPath (resolved_symfile_path, sizeof(resolved_symfile_path)))
+ {
+ if (strcmp (resolved_symfile_path, symfile_path) != 0)
+ {
+ result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", symfile_path, resolved_symfile_path);
+ break;
+ }
+ }
+ result.AppendErrorWithFormat ("invalid module path '%s'\n", symfile_path);
+ break;
+ }
+ }
+ }
+ }
+ }
+ return result.Succeeded();
+ }
+
+ int
+ HandleArgumentCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ OptionElementVector &opt_element_vector,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+ {
+ std::string completion_str (input.GetArgumentAtIndex(cursor_index));
+ completion_str.erase (cursor_char_position);
+
+ CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
+ CommandCompletions::eDiskFileCompletion,
+ completion_str.c_str(),
+ match_start_point,
+ max_return_elements,
+ NULL,
+ word_complete,
+ matches);
+ return matches.GetSize();
+ }
+
+};
+
+
+#pragma mark CommandObjectTargetSymbols
+
+//-------------------------------------------------------------------------
+// CommandObjectTargetSymbols
+//-------------------------------------------------------------------------
+
+class CommandObjectTargetSymbols : public CommandObjectMultiword
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectTargetSymbols(CommandInterpreter &interpreter) :
+ CommandObjectMultiword (interpreter,
+ "target symbols",
+ "A set of commands for adding and managing debug symbol files.",
+ "target symbols <sub-command> ...")
+ {
+ LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetSymbolsAdd (interpreter)));
+
+ }
+ virtual
+ ~CommandObjectTargetSymbols()
+ {
+ }
+
+private:
+ //------------------------------------------------------------------
+ // For CommandObjectTargetModules only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (CommandObjectTargetSymbols);
+};
+
+
#pragma mark CommandObjectTargetStopHookAdd
//-------------------------------------------------------------------------
@@ -4187,6 +4383,7 @@
LoadSubCommand ("select", CommandObjectSP (new CommandObjectTargetSelect (interpreter)));
LoadSubCommand ("stop-hook", CommandObjectSP (new CommandObjectMultiwordTargetStopHooks (interpreter)));
LoadSubCommand ("modules", CommandObjectSP (new CommandObjectTargetModules (interpreter)));
+ LoadSubCommand ("symbols", CommandObjectSP (new CommandObjectTargetSymbols (interpreter)));
LoadSubCommand ("variable", CommandObjectSP (new CommandObjectTargetVariable (interpreter)));
}