summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Target/Target.h18
-rw-r--r--lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp19
-rw-r--r--lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h2
-rw-r--r--lldb/source/Target/Target.cpp38
-rw-r--r--lldb/source/Target/ThreadPlanCallFunction.cpp37
5 files changed, 84 insertions, 30 deletions
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 4ed11afc31b..b1de1932708 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -1116,6 +1116,24 @@ public:
lldb::addr_t GetPersistentSymbol(ConstString name);
+ /// This method will return the address of the starting function for
+ /// this binary, e.g. main() or its equivalent. This can be used as
+ /// an address of a function that is not called once a binary has
+ /// started running - e.g. as a return address for inferior function
+ /// calls that are unambiguous completion of the function call, not
+ /// called during the course of the inferior function code running.
+ ///
+ /// If no entry point can be found, an invalid address is returned.
+ ///
+ /// \param [out] err
+ /// This object will be set to failure if no entry address could
+ /// be found, and may contain a helpful error message.
+ //
+ /// \return
+ /// Returns the entry address for this program, LLDB_INVALID_ADDRESS
+ /// if none can be found.
+ lldb_private::Address GetEntryPointAddress(Status &err);
+
// Target Stop Hooks
class StopHook : public UserID {
public:
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index ce928cf375d..050cb78577b 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -1144,6 +1144,10 @@ bool ObjectFileMachO::IsExecutable() const {
return m_header.filetype == MH_EXECUTE;
}
+bool ObjectFileMachO::IsDynamicLoader() const {
+ return m_header.filetype == MH_DYLINKER;
+}
+
uint32_t ObjectFileMachO::GetAddressByteSize() const {
return m_data.GetAddressByteSize();
}
@@ -5177,8 +5181,10 @@ lldb_private::Address ObjectFileMachO::GetEntryPointAddress() {
// return that. If m_entry_point_address is valid it means we've found it
// already, so return the cached value.
- if (!IsExecutable() || m_entry_point_address.IsValid())
+ if ((!IsExecutable() && !IsDynamicLoader()) ||
+ m_entry_point_address.IsValid()) {
return m_entry_point_address;
+ }
// Otherwise, look for the UnixThread or Thread command. The data for the
// Thread command is given in /usr/include/mach-o.h, but it is basically:
@@ -5300,6 +5306,17 @@ lldb_private::Address ObjectFileMachO::GetEntryPointAddress() {
offset = cmd_offset + load_cmd.cmdsize;
}
+ if (start_address == LLDB_INVALID_ADDRESS && IsDynamicLoader()) {
+ if (GetSymtab()) {
+ Symbol *dyld_start_sym = GetSymtab()->FindFirstSymbolWithNameAndType(
+ ConstString("_dyld_start"), SymbolType::eSymbolTypeCode,
+ Symtab::eDebugAny, Symtab::eVisibilityAny);
+ if (dyld_start_sym && dyld_start_sym->GetAddress().IsValid()) {
+ start_address = dyld_start_sym->GetAddress().GetFileAddress();
+ }
+ }
+ }
+
if (start_address != LLDB_INVALID_ADDRESS) {
// We got the start address from the load commands, so now resolve that
// address in the sections of this ObjectFile:
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index df6b914fa73..2326873ed41 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -73,6 +73,8 @@ public:
bool IsExecutable() const override;
+ bool IsDynamicLoader() const;
+
uint32_t GetAddressByteSize() const override;
lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 4941cb585c5..290094efc4b 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -2448,6 +2448,44 @@ lldb::addr_t Target::GetPersistentSymbol(ConstString name) {
return address;
}
+lldb_private::Address Target::GetEntryPointAddress(Status &err) {
+ err.Clear();
+ Address entry_addr;
+ Module *exe_module = GetExecutableModulePointer();
+
+ if (!exe_module || !exe_module->GetObjectFile()) {
+ err.SetErrorStringWithFormat("No primary executable found");
+ } else {
+ entry_addr = exe_module->GetObjectFile()->GetEntryPointAddress();
+ if (!entry_addr.IsValid()) {
+ err.SetErrorStringWithFormat(
+ "Could not find entry point address for executable module \"%s\".",
+ exe_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+
+ if (!entry_addr.IsValid()) {
+ 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));
+ if (module_sp && module_sp->GetObjectFile()) {
+ entry_addr = module_sp->GetObjectFile()->GetEntryPointAddress();
+ if (entry_addr.IsValid()) {
+ // Clear out any old error messages from the original
+ // main-executable-binary search; one of the other modules
+ // was able to provide an address.
+ err.Clear();
+ break;
+ }
+ }
+ }
+ }
+
+ return entry_addr;
+}
+
+
lldb::addr_t Target::GetCallableLoadAddress(lldb::addr_t load_addr,
AddressClass addr_class) const {
auto arch_plugin = GetArchitecturePlugin();
diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp
index 68d771c3794..57f4ef5874c 100644
--- a/lldb/source/Target/ThreadPlanCallFunction.cpp
+++ b/lldb/source/Target/ThreadPlanCallFunction.cpp
@@ -65,38 +65,17 @@ bool ThreadPlanCallFunction::ConstructorSetup(
return false;
}
- Module *exe_module = GetTarget().GetExecutableModulePointer();
+ m_start_addr = GetTarget().GetEntryPointAddress(error);
- if (exe_module == nullptr) {
- m_constructor_errors.Printf(
- "Can't execute code without an executable module.");
- if (log)
- log->Printf("ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),
- m_constructor_errors.GetData());
+ if (log && error.Fail()) {
+ m_constructor_errors.Printf("%s", error.AsCString());
+ log->Printf("ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this),
+ m_constructor_errors.GetData());
return false;
- } else {
- ObjectFile *objectFile = exe_module->GetObjectFile();
- if (!objectFile) {
- m_constructor_errors.Printf(
- "Could not find object file for module \"%s\".",
- exe_module->GetFileSpec().GetFilename().AsCString());
-
- if (log)
- log->Printf("ThreadPlanCallFunction(%p): %s.",
- static_cast<void *>(this), m_constructor_errors.GetData());
- return false;
- }
+ }
- m_start_addr = objectFile->GetEntryPointAddress();
- if (!m_start_addr.IsValid()) {
- m_constructor_errors.Printf(
- "Could not find entry point address for executable module \"%s\".",
- exe_module->GetFileSpec().GetFilename().AsCString());
- if (log)
- log->Printf("ThreadPlanCallFunction(%p): %s.",
- static_cast<void *>(this), m_constructor_errors.GetData());
- return false;
- }
+ if (!m_start_addr.IsValid()) {
+ return false;
}
start_load_addr = m_start_addr.GetLoadAddress(&GetTarget());
OpenPOWER on IntegriCloud