[Lldb-commits] [lldb] r127194 - in /lldb/trunk: include/lldb/Symbol/ObjectFile.h source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp source/Plugins/ObjectFile/ELF/ObjectFileELF.h source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h source/Target/ThreadPlanCallFunction.cpp
Jim Ingham
jingham at apple.com
Mon Mar 7 15:44:08 PST 2011
Author: jingham
Date: Mon Mar 7 17:44:08 2011
New Revision: 127194
URL: http://llvm.org/viewvc/llvm-project?rev=127194&view=rev
Log:
Add a method "GetEntryPoint" to the ObjectFile class, and implement it on MachO & ELF - though the ELF implementation is probably a little weak. Then use this method in place of directly looking for "start" in the ThreadPlanCallFunction constructor to find the stopping point for our function evaluation.
Modified:
lldb/trunk/include/lldb/Symbol/ObjectFile.h
lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
Modified: lldb/trunk/include/lldb/Symbol/ObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ObjectFile.h?rev=127194&r1=127193&r2=127194&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ObjectFile.h (original)
+++ lldb/trunk/include/lldb/Symbol/ObjectFile.h Mon Mar 7 17:44:08 2011
@@ -338,6 +338,17 @@
/// object file format does not support or contain such information.
virtual lldb_private::Address
GetImageInfoAddress () { return Address(); }
+
+ //------------------------------------------------------------------
+ /// Returns the address of the Entry Point in this object file - if
+ /// the object file doesn't have an entry point (because it is not an
+ /// executable file) then an invalid address is returned.
+ ///
+ /// @return
+ /// Returns the entry address for this module.
+ //------------------------------------------------------------------
+ virtual lldb_private::Address
+ GetEntryPointAddress () { return Address();}
protected:
//------------------------------------------------------------------
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=127194&r1=127193&r2=127194&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Mon Mar 7 17:44:08 2011
@@ -16,9 +16,11 @@
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Host/Host.h"
#define CASE_AND_STREAM(s, def, width) \
@@ -276,6 +278,32 @@
return Address();
}
+lldb_private::Address
+ObjectFileELF::GetEntryPointAddress ()
+{
+ // If the object file is not an executable it can't hold the entry point. m_entry_point_address
+ // is initialized to an invalid address, so we can just 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())
+ return m_entry_point_address;
+
+ // FIXME: This is just looking for the "start" symbol, but that will fail if "start" is stripped.
+ // There's probably a better way in ELF to find the start address of an executable module.
+
+ SymbolContextList contexts;
+ SymbolContext context;
+ if (!m_module->FindSymbolsWithNameAndType(ConstString ("start"), lldb::eSymbolTypeCode, contexts))
+ return m_entry_point_address;
+
+ contexts.GetContextAtIndex(0, context);
+
+ m_entry_point_address = context.symbol->GetValue();
+
+ return m_entry_point_address;
+
+}
+
//----------------------------------------------------------------------
// ParseDependentModules
//----------------------------------------------------------------------
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=127194&r1=127193&r2=127194&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Mon Mar 7 17:44:08 2011
@@ -115,6 +115,9 @@
virtual lldb_private::Address
GetImageInfoAddress();
+
+ virtual lldb_private::Address
+ GetEntryPointAddress ();
private:
ObjectFileELF(lldb_private::Module* module,
@@ -156,6 +159,9 @@
/// Data extractor holding the string table used to resolve section names.
lldb_private::DataExtractor m_shstr_data;
+ /// Cached value of the entry point for this module.
+ lldb_private::Address m_entry_point_address;
+
/// Returns a 1 based index of the given section header.
unsigned
SectionIndex(const SectionHeaderCollIter &I);
Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=127194&r1=127193&r2=127194&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Mon Mar 7 17:44:08 2011
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/Support/MachO.h"
+
#include "ObjectFileMachO.h"
#include "lldb/Core/ArchSpec.h"
@@ -105,7 +107,8 @@
m_mutex (Mutex::eMutexTypeRecursive),
m_header(),
m_sections_ap(),
- m_symtab_ap()
+ m_symtab_ap(),
+ m_entry_point_address ()
{
::memset (&m_header, 0, sizeof(m_header));
::memset (&m_dysymtab, 0, sizeof(m_dysymtab));
@@ -1435,6 +1438,136 @@
return count;
}
+lldb_private::Address
+ObjectFileMachO::GetEntryPointAddress ()
+{
+ // If the object file is not an executable it can't hold the entry point. m_entry_point_address
+ // is initialized to an invalid address, so we can just 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())
+ 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:
+ //
+ // uint32_t flavor - this is the flavor argument you would pass to thread_get_state
+ // uint32_t count - this is the count of longs in the thread state data
+ // struct XXX_thread_state state - this is the structure from <machine/thread_status.h> corresponding to the flavor.
+ // <repeat this trio>
+ //
+ // So we just keep reading the various register flavors till we find the GPR one, then read the PC out of there.
+ // FIXME: We will need to have a "RegisterContext data provider" class at some point that can get all the registers
+ // out of data in this form & attach them to a given thread. That should underlie the MacOS X User process plugin,
+ // and we'll also need it for the MacOS X Core File process plugin. When we have that we can also use it here.
+ //
+ // For now we hard-code the offsets and flavors we need:
+ //
+ //
+
+ lldb_private::Mutex::Locker locker(m_mutex);
+ struct load_command load_cmd;
+ uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ uint32_t i;
+ lldb::addr_t start_address = LLDB_INVALID_ADDRESS;
+ bool done = false;
+
+ for (i=0; i<m_header.ncmds; ++i)
+ {
+ const uint32_t cmd_offset = offset;
+ if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
+ break;
+
+ switch (load_cmd.cmd)
+ {
+ case LoadCommandUnixThread:
+ case LoadCommandThread:
+ {
+ while (offset < cmd_offset + load_cmd.cmdsize)
+ {
+ uint32_t flavor = m_data.GetU32(&offset);
+ uint32_t count = m_data.GetU32(&offset);
+ if (count == 0)
+ {
+ // We've gotten off somehow, log and exit;
+ return m_entry_point_address;
+ }
+
+ switch (m_header.cputype)
+ {
+ case llvm::MachO::CPUTypeARM:
+ if (flavor == 1) // ARM_THREAD_STATE from mach/arm/thread_status.h
+ {
+ offset += 60; // This is the offset of pc in the GPR thread state data structure.
+ start_address = m_data.GetU32(&offset);
+ done = true;
+ }
+ break;
+ case llvm::MachO::CPUTypeI386:
+ if (flavor == 1) // x86_THREAD_STATE32 from mach/i386/thread_status.h
+ {
+ offset += 40; // This is the offset of eip in the GPR thread state data structure.
+ start_address = m_data.GetU32(&offset);
+ done = true;
+ }
+ break;
+ case llvm::MachO::CPUTypeX86_64:
+ if (flavor == 4) // x86_THREAD_STATE64 from mach/i386/thread_status.h
+ {
+ offset += 16 * 8; // This is the offset of rip in the GPR thread state data structure.
+ start_address = m_data.GetU64(&offset);
+ done = true;
+ }
+ break;
+ default:
+ return m_entry_point_address;
+ }
+ // Haven't found the GPR flavor yet, skip over the data for this flavor:
+ if (done)
+ break;
+ offset += count * 4;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ if (done)
+ break;
+
+ // Go to the next load command:
+ offset = cmd_offset + load_cmd.cmdsize;
+ }
+
+ 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:
+ if (!m_entry_point_address.ResolveAddressUsingFileSections (start_address, GetSectionList()))
+ {
+ m_entry_point_address.Clear();
+ }
+ }
+ else
+ {
+ // We couldn't read the UnixThread load command - maybe it wasn't there. As a fallback look for the
+ // "start" symbol in the main executable.
+
+ SymbolContextList contexts;
+ SymbolContext context;
+ if (!m_module->FindSymbolsWithNameAndType(ConstString ("start"), lldb::eSymbolTypeCode, contexts))
+ return m_entry_point_address;
+
+ contexts.GetContextAtIndex(0, context);
+
+ m_entry_point_address = context.symbol->GetValue();
+ }
+
+ return m_entry_point_address;
+
+}
+
bool
ObjectFileMachO::GetArchitecture (ArchSpec &arch)
{
Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h?rev=127194&r1=127193&r2=127194&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h Mon Mar 7 17:44:08 2011
@@ -12,6 +12,7 @@
#include "llvm/Support/MachO.h"
+#include "lldb/Core/Address.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -112,7 +113,8 @@
virtual lldb_private::Log *
EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
-
+ virtual lldb_private::Address
+ GetEntryPointAddress ();
protected:
mutable lldb_private::Mutex m_mutex;
@@ -123,6 +125,7 @@
llvm::MachO::dysymtab_command m_dysymtab;
std::vector<llvm::MachO::segment_command_64> m_mach_segments;
std::vector<llvm::MachO::section_64> m_mach_sections;
+ lldb_private::Address m_entry_point_address;
size_t
ParseSections ();
Modified: lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanCallFunction.cpp?rev=127194&r1=127193&r2=127194&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanCallFunction.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanCallFunction.cpp Mon Mar 7 17:44:08 2011
@@ -66,19 +66,33 @@
lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
- SymbolContextList contexts;
- SymbolContext context;
ModuleSP executableModuleSP (target.GetExecutableModule());
- if (!executableModuleSP ||
- !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
+ if (!executableModuleSP)
+ {
+ log->Printf ("Can't execute code without an executable module.");
return;
+ }
+ else
+ {
+ ObjectFile *objectFile = executableModuleSP->GetObjectFile();
+ if (!objectFile)
+ {
+ log->Printf ("Could not find object file for module \"%s\".",
+ executableModuleSP->GetFileSpec().GetFilename().AsCString());
+ return;
+ }
+ m_start_addr = objectFile->GetEntryPointAddress();
+ if (!m_start_addr.IsValid())
+ {
+ log->Printf ("Could not find entry point address for executable module \"%s\".",
+ executableModuleSP->GetFileSpec().GetFilename().AsCString());
+ return;
+ }
+ }
- contexts.GetContextAtIndex(0, context);
-
- m_start_addr = context.symbol->GetValue();
lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
-
+
// Checkpoint the thread state so we can restore it later.
if (log && log->GetVerbose())
ReportRegisterState ("About to checkpoint thread before function call. Original register state was:");
More information about the lldb-commits
mailing list