This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rL366493: Fall back to dyld's _dyld_start when no LC_MAIN 
/ main() func can be found (authored by jmolenda, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D64897?vs=210461&id=210664#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64897/new/

https://reviews.llvm.org/D64897

Files:
  lldb/trunk/include/lldb/Target/Target.h
  lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
  lldb/trunk/source/Target/Target.cpp
  lldb/trunk/source/Target/ThreadPlanCallFunction.cpp

Index: lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
===================================================================
--- lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
+++ lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
@@ -65,38 +65,17 @@
     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());
Index: lldb/trunk/source/Target/Target.cpp
===================================================================
--- lldb/trunk/source/Target/Target.cpp
+++ lldb/trunk/source/Target/Target.cpp
@@ -2448,6 +2448,44 @@
   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();
Index: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
===================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -1144,6 +1144,10 @@
   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 @@
   // 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 @@
       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:
Index: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
===================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -73,6 +73,8 @@
 
   bool IsExecutable() const override;
 
+  bool IsDynamicLoader() const;
+
   uint32_t GetAddressByteSize() const override;
 
   lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
Index: lldb/trunk/include/lldb/Target/Target.h
===================================================================
--- lldb/trunk/include/lldb/Target/Target.h
+++ lldb/trunk/include/lldb/Target/Target.h
@@ -1116,6 +1116,24 @@
 
   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:
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to