2012-01-06 05:48:15 +08:00
|
|
|
//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
// C Includes
|
|
|
|
// C++ Includes
|
|
|
|
// Other libraries and framework includes
|
|
|
|
#include "lldb/Core/ArchSpec.h"
|
|
|
|
#include "lldb/Core/Error.h"
|
|
|
|
#include "lldb/Core/Log.h"
|
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-30 05:13:06 +08:00
|
|
|
#include "lldb/Core/Module.h"
|
2014-07-01 05:05:18 +08:00
|
|
|
#include "lldb/Symbol/ObjectFile.h"
|
Added support for reading thread-local storage variables, as defined using the __thread modifier.
To make this work this patch extends LLDB to:
- Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list.
- Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines.
- Make DWARF expressions track which module they originated from.
- Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here.
- Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here:
1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target.
2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out.
3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized.
However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used.
Test case included.
llvm-svn: 192922
2013-10-18 05:14:00 +08:00
|
|
|
#include "lldb/Symbol/Symbol.h"
|
2015-03-04 03:23:09 +08:00
|
|
|
#include "lldb/Symbol/SymbolContext.h"
|
2012-01-06 05:48:15 +08:00
|
|
|
#include "lldb/Target/Process.h"
|
|
|
|
#include "lldb/Target/Target.h"
|
|
|
|
|
Use basename of main executable in POSIX-DYLD on Android.
Summary:
The Android dynamic linker reports only the basename of each SO entry, so for
the above check to be successful, we need to compare it to the basename of the
main executable.
This also has a nasty side-effect when working with older version of
Android (verified on platform version 16), and debugging PIE
executables: the dynamic linker has a bug and reports the load address
of the main executable (which is a shared object, because PIE) to be 0.
We then try to update the list of loaded sections for all shared
objects, including the main executable, and set the load address to 0,
which breaks everything that relies on resolving addresses in the main
executable (breakpoints, stepping, etc). This commit also fixes that broken
behavior when debugging on older Androids. This bug doesn't happen on newer
Android versions (verified for Android L).
Test Plan: Run test suite on linux.
Reviewers: clayborg, tfiala, richard.mitton
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D7188
llvm-svn: 228057
2015-02-04 06:48:34 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
|
|
|
|
2012-01-06 05:48:15 +08:00
|
|
|
#include "DYLDRendezvous.h"
|
|
|
|
|
|
|
|
using namespace lldb;
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
|
|
/// Locates the address of the rendezvous structure. Returns the address on
|
|
|
|
/// success and LLDB_INVALID_ADDRESS on failure.
|
|
|
|
static addr_t
|
|
|
|
ResolveRendezvousAddress(Process *process)
|
|
|
|
{
|
2014-07-01 05:05:18 +08:00
|
|
|
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
|
2012-01-06 05:48:15 +08:00
|
|
|
addr_t info_location;
|
|
|
|
addr_t info_addr;
|
|
|
|
Error error;
|
|
|
|
|
2014-09-06 06:28:40 +08:00
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf ("%s null process provided", __FUNCTION__);
|
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
2014-07-01 05:05:18 +08:00
|
|
|
// Try to get it from our process. This might be a remote process and might
|
|
|
|
// grab it via some remote-specific mechanism.
|
2012-01-06 05:48:15 +08:00
|
|
|
info_location = process->GetImageInfoAddress();
|
2014-07-01 05:05:18 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location);
|
2012-01-06 05:48:15 +08:00
|
|
|
|
2014-07-01 05:05:18 +08:00
|
|
|
// If the process fails to return an address, fall back to seeing if the local object file can help us find it.
|
2012-01-06 05:48:15 +08:00
|
|
|
if (info_location == LLDB_INVALID_ADDRESS)
|
2014-07-01 05:05:18 +08:00
|
|
|
{
|
2014-09-06 06:28:40 +08:00
|
|
|
Target *target = &process->GetTarget();
|
2014-07-01 05:05:18 +08:00
|
|
|
if (target)
|
|
|
|
{
|
|
|
|
ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
|
|
|
|
Address addr = obj_file->GetImageInfoAddress(target);
|
|
|
|
|
|
|
|
if (addr.IsValid())
|
|
|
|
{
|
|
|
|
info_location = addr.GetLoadAddress(target);
|
|
|
|
if (log)
|
|
|
|
log->Printf ("%s resolved via direct object file approach to 0x%" PRIx64, __FUNCTION__, info_location);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf ("%s FAILED - direct object file approach did not yield a valid address", __FUNCTION__);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info_location == LLDB_INVALID_ADDRESS)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf ("%s FAILED - invalid info address", __FUNCTION__);
|
2012-01-06 05:48:15 +08:00
|
|
|
return LLDB_INVALID_ADDRESS;
|
2014-07-01 05:05:18 +08:00
|
|
|
}
|
2012-01-06 05:48:15 +08:00
|
|
|
|
2014-09-06 06:28:40 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, __FUNCTION__, process->GetAddressByteSize(), info_location);
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
info_addr = process->ReadPointerFromMemory(info_location, error);
|
|
|
|
if (error.Fail())
|
2014-07-01 05:05:18 +08:00
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf ("%s FAILED - could not read from the info location: %s", __FUNCTION__, error.AsCString ());
|
2012-01-06 05:48:15 +08:00
|
|
|
return LLDB_INVALID_ADDRESS;
|
2014-07-01 05:05:18 +08:00
|
|
|
}
|
2012-01-06 05:48:15 +08:00
|
|
|
|
|
|
|
if (info_addr == 0)
|
2014-07-01 05:05:18 +08:00
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf ("%s FAILED - the rendezvous address contained at 0x%" PRIx64 " returned a null value", __FUNCTION__, info_location);
|
2012-01-06 05:48:15 +08:00
|
|
|
return LLDB_INVALID_ADDRESS;
|
2014-07-01 05:05:18 +08:00
|
|
|
}
|
2012-01-06 05:48:15 +08:00
|
|
|
|
|
|
|
return info_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
DYLDRendezvous::DYLDRendezvous(Process *process)
|
|
|
|
: m_process(process),
|
|
|
|
m_rendezvous_addr(LLDB_INVALID_ADDRESS),
|
|
|
|
m_current(),
|
|
|
|
m_previous(),
|
|
|
|
m_soentries(),
|
|
|
|
m_added_soentries(),
|
|
|
|
m_removed_soentries()
|
|
|
|
{
|
2014-07-01 05:05:18 +08:00
|
|
|
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
|
|
|
|
|
Added support for reading thread-local storage variables, as defined using the __thread modifier.
To make this work this patch extends LLDB to:
- Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list.
- Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines.
- Make DWARF expressions track which module they originated from.
- Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here.
- Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here:
1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target.
2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out.
3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized.
However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used.
Test case included.
llvm-svn: 192922
2013-10-18 05:14:00 +08:00
|
|
|
m_thread_info.valid = false;
|
|
|
|
|
2012-01-06 05:48:15 +08:00
|
|
|
// Cache a copy of the executable path
|
2013-05-08 06:46:38 +08:00
|
|
|
if (m_process)
|
|
|
|
{
|
|
|
|
Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
|
|
|
|
if (exe_mod)
|
2014-07-01 05:05:18 +08:00
|
|
|
{
|
2015-06-06 06:03:19 +08:00
|
|
|
m_exe_file_spec = exe_mod->GetPlatformFileSpec();
|
2014-07-01 05:05:18 +08:00
|
|
|
if (log)
|
2015-06-06 06:03:19 +08:00
|
|
|
log->Printf ("DYLDRendezvous::%s exe module executable path set: '%s'",
|
|
|
|
__FUNCTION__, m_exe_file_spec.GetCString());
|
2014-07-01 05:05:18 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf ("DYLDRendezvous::%s cannot cache exe module path: null executable module pointer", __FUNCTION__);
|
|
|
|
}
|
2013-05-08 06:46:38 +08:00
|
|
|
}
|
2012-01-06 05:48:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
DYLDRendezvous::Resolve()
|
|
|
|
{
|
2014-07-01 05:05:18 +08:00
|
|
|
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
|
|
|
|
|
2012-01-06 05:48:15 +08:00
|
|
|
const size_t word_size = 4;
|
|
|
|
Rendezvous info;
|
|
|
|
size_t address_size;
|
|
|
|
size_t padding;
|
|
|
|
addr_t info_addr;
|
|
|
|
addr_t cursor;
|
|
|
|
|
|
|
|
address_size = m_process->GetAddressByteSize();
|
|
|
|
padding = address_size - word_size;
|
2014-07-01 05:05:18 +08:00
|
|
|
if (log)
|
2015-04-23 21:57:30 +08:00
|
|
|
log->Printf ("DYLDRendezvous::%s address size: %" PRIu64 ", padding %" PRIu64, __FUNCTION__, uint64_t(address_size), uint64_t(padding));
|
2012-01-06 05:48:15 +08:00
|
|
|
|
|
|
|
if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
|
|
|
|
cursor = info_addr = ResolveRendezvousAddress(m_process);
|
|
|
|
else
|
|
|
|
cursor = info_addr = m_rendezvous_addr;
|
2014-07-01 05:05:18 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf ("DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, cursor);
|
|
|
|
|
2012-01-06 05:48:15 +08:00
|
|
|
if (cursor == LLDB_INVALID_ADDRESS)
|
|
|
|
return false;
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
if (!(cursor = ReadWord(cursor, &info.version, word_size)))
|
2012-01-06 05:48:15 +08:00
|
|
|
return false;
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
|
2012-01-06 05:48:15 +08:00
|
|
|
return false;
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
if (!(cursor = ReadPointer(cursor, &info.brk)))
|
2012-01-06 05:48:15 +08:00
|
|
|
return false;
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
if (!(cursor = ReadWord(cursor, &info.state, word_size)))
|
2012-01-06 05:48:15 +08:00
|
|
|
return false;
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
|
2012-01-06 05:48:15 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// The rendezvous was successfully read. Update our internal state.
|
|
|
|
m_rendezvous_addr = info_addr;
|
|
|
|
m_previous = m_current;
|
|
|
|
m_current = info;
|
|
|
|
|
|
|
|
return UpdateSOEntries();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
DYLDRendezvous::IsValid()
|
|
|
|
{
|
|
|
|
return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
DYLDRendezvous::UpdateSOEntries()
|
|
|
|
{
|
|
|
|
SOEntry entry;
|
|
|
|
|
|
|
|
if (m_current.map_addr == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// When the previous and current states are consistent this is the first
|
|
|
|
// time we have been asked to update. Just take a snapshot of the currently
|
|
|
|
// loaded modules.
|
|
|
|
if (m_previous.state == eConsistent && m_current.state == eConsistent)
|
|
|
|
return TakeSnapshot(m_soentries);
|
|
|
|
|
|
|
|
// If we are about to add or remove a shared object clear out the current
|
|
|
|
// state and take a snapshot of the currently loaded images.
|
|
|
|
if (m_current.state == eAdd || m_current.state == eDelete)
|
|
|
|
{
|
2015-03-24 01:05:41 +08:00
|
|
|
// Some versions of the android dynamic linker might send two
|
|
|
|
// notifications with state == eAdd back to back. Ignore them
|
|
|
|
// until we get an eConsistent notification.
|
|
|
|
if (!(m_previous.state == eConsistent || (m_previous.state == eAdd && m_current.state == eDelete)))
|
|
|
|
return false;
|
|
|
|
|
2012-01-06 05:48:15 +08:00
|
|
|
m_soentries.clear();
|
|
|
|
m_added_soentries.clear();
|
|
|
|
m_removed_soentries.clear();
|
|
|
|
return TakeSnapshot(m_soentries);
|
|
|
|
}
|
|
|
|
assert(m_current.state == eConsistent);
|
|
|
|
|
|
|
|
// Otherwise check the previous state to determine what to expect and update
|
|
|
|
// accordingly.
|
|
|
|
if (m_previous.state == eAdd)
|
|
|
|
return UpdateSOEntriesForAddition();
|
|
|
|
else if (m_previous.state == eDelete)
|
|
|
|
return UpdateSOEntriesForDeletion();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
DYLDRendezvous::UpdateSOEntriesForAddition()
|
|
|
|
{
|
|
|
|
SOEntry entry;
|
|
|
|
iterator pos;
|
|
|
|
|
|
|
|
assert(m_previous.state == eAdd);
|
|
|
|
|
|
|
|
if (m_current.map_addr == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
|
|
|
|
{
|
|
|
|
if (!ReadSOEntryFromMemory(cursor, entry))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Only add shared libraries and not the executable.
|
Use basename of main executable in POSIX-DYLD on Android.
Summary:
The Android dynamic linker reports only the basename of each SO entry, so for
the above check to be successful, we need to compare it to the basename of the
main executable.
This also has a nasty side-effect when working with older version of
Android (verified on platform version 16), and debugging PIE
executables: the dynamic linker has a bug and reports the load address
of the main executable (which is a shared object, because PIE) to be 0.
We then try to update the list of loaded sections for all shared
objects, including the main executable, and set the load address to 0,
which breaks everything that relies on resolving addresses in the main
executable (breakpoints, stepping, etc). This commit also fixes that broken
behavior when debugging on older Androids. This bug doesn't happen on newer
Android versions (verified for Android L).
Test Plan: Run test suite on linux.
Reviewers: clayborg, tfiala, richard.mitton
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D7188
llvm-svn: 228057
2015-02-04 06:48:34 +08:00
|
|
|
if (SOEntryIsMainExecutable(entry))
|
2012-01-06 05:48:15 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
|
|
|
|
if (pos == m_soentries.end())
|
|
|
|
{
|
|
|
|
m_soentries.push_back(entry);
|
|
|
|
m_added_soentries.push_back(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
DYLDRendezvous::UpdateSOEntriesForDeletion()
|
|
|
|
{
|
|
|
|
SOEntryList entry_list;
|
|
|
|
iterator pos;
|
|
|
|
|
|
|
|
assert(m_previous.state == eDelete);
|
|
|
|
|
|
|
|
if (!TakeSnapshot(entry_list))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (iterator I = begin(); I != end(); ++I)
|
|
|
|
{
|
|
|
|
pos = std::find(entry_list.begin(), entry_list.end(), *I);
|
|
|
|
if (pos == entry_list.end())
|
|
|
|
m_removed_soentries.push_back(*I);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_soentries = entry_list;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Use basename of main executable in POSIX-DYLD on Android.
Summary:
The Android dynamic linker reports only the basename of each SO entry, so for
the above check to be successful, we need to compare it to the basename of the
main executable.
This also has a nasty side-effect when working with older version of
Android (verified on platform version 16), and debugging PIE
executables: the dynamic linker has a bug and reports the load address
of the main executable (which is a shared object, because PIE) to be 0.
We then try to update the list of loaded sections for all shared
objects, including the main executable, and set the load address to 0,
which breaks everything that relies on resolving addresses in the main
executable (breakpoints, stepping, etc). This commit also fixes that broken
behavior when debugging on older Androids. This bug doesn't happen on newer
Android versions (verified for Android L).
Test Plan: Run test suite on linux.
Reviewers: clayborg, tfiala, richard.mitton
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D7188
llvm-svn: 228057
2015-02-04 06:48:34 +08:00
|
|
|
bool
|
|
|
|
DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry)
|
|
|
|
{
|
|
|
|
// On Linux the executable is indicated by an empty path in the entry. On
|
2015-03-13 19:16:14 +08:00
|
|
|
// FreeBSD and on Android it is the full path to the executable.
|
Use basename of main executable in POSIX-DYLD on Android.
Summary:
The Android dynamic linker reports only the basename of each SO entry, so for
the above check to be successful, we need to compare it to the basename of the
main executable.
This also has a nasty side-effect when working with older version of
Android (verified on platform version 16), and debugging PIE
executables: the dynamic linker has a bug and reports the load address
of the main executable (which is a shared object, because PIE) to be 0.
We then try to update the list of loaded sections for all shared
objects, including the main executable, and set the load address to 0,
which breaks everything that relies on resolving addresses in the main
executable (breakpoints, stepping, etc). This commit also fixes that broken
behavior when debugging on older Androids. This bug doesn't happen on newer
Android versions (verified for Android L).
Test Plan: Run test suite on linux.
Reviewers: clayborg, tfiala, richard.mitton
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D7188
llvm-svn: 228057
2015-02-04 06:48:34 +08:00
|
|
|
|
|
|
|
auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
|
|
|
|
auto os_type = triple.getOS();
|
|
|
|
auto env_type = triple.getEnvironment();
|
|
|
|
|
|
|
|
switch (os_type) {
|
|
|
|
case llvm::Triple::FreeBSD:
|
2015-06-06 06:03:19 +08:00
|
|
|
return entry.file_spec == m_exe_file_spec;
|
Use basename of main executable in POSIX-DYLD on Android.
Summary:
The Android dynamic linker reports only the basename of each SO entry, so for
the above check to be successful, we need to compare it to the basename of the
main executable.
This also has a nasty side-effect when working with older version of
Android (verified on platform version 16), and debugging PIE
executables: the dynamic linker has a bug and reports the load address
of the main executable (which is a shared object, because PIE) to be 0.
We then try to update the list of loaded sections for all shared
objects, including the main executable, and set the load address to 0,
which breaks everything that relies on resolving addresses in the main
executable (breakpoints, stepping, etc). This commit also fixes that broken
behavior when debugging on older Androids. This bug doesn't happen on newer
Android versions (verified for Android L).
Test Plan: Run test suite on linux.
Reviewers: clayborg, tfiala, richard.mitton
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D7188
llvm-svn: 228057
2015-02-04 06:48:34 +08:00
|
|
|
case llvm::Triple::Linux:
|
2015-03-13 19:16:14 +08:00
|
|
|
switch (env_type) {
|
|
|
|
case llvm::Triple::Android:
|
2015-06-06 06:03:19 +08:00
|
|
|
return entry.file_spec == m_exe_file_spec;
|
2015-03-13 19:16:14 +08:00
|
|
|
default:
|
2015-06-06 06:03:19 +08:00
|
|
|
return !entry.file_spec;
|
2015-03-13 19:16:14 +08:00
|
|
|
}
|
Use basename of main executable in POSIX-DYLD on Android.
Summary:
The Android dynamic linker reports only the basename of each SO entry, so for
the above check to be successful, we need to compare it to the basename of the
main executable.
This also has a nasty side-effect when working with older version of
Android (verified on platform version 16), and debugging PIE
executables: the dynamic linker has a bug and reports the load address
of the main executable (which is a shared object, because PIE) to be 0.
We then try to update the list of loaded sections for all shared
objects, including the main executable, and set the load address to 0,
which breaks everything that relies on resolving addresses in the main
executable (breakpoints, stepping, etc). This commit also fixes that broken
behavior when debugging on older Androids. This bug doesn't happen on newer
Android versions (verified for Android L).
Test Plan: Run test suite on linux.
Reviewers: clayborg, tfiala, richard.mitton
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D7188
llvm-svn: 228057
2015-02-04 06:48:34 +08:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-06 05:48:15 +08:00
|
|
|
bool
|
|
|
|
DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
|
|
|
|
{
|
|
|
|
SOEntry entry;
|
|
|
|
|
|
|
|
if (m_current.map_addr == 0)
|
|
|
|
return false;
|
|
|
|
|
2015-06-18 18:25:54 +08:00
|
|
|
// Clear previous entries since we are about to obtain an up to date list.
|
|
|
|
entry_list.clear();
|
|
|
|
|
2012-01-06 05:48:15 +08:00
|
|
|
for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
|
|
|
|
{
|
|
|
|
if (!ReadSOEntryFromMemory(cursor, entry))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Only add shared libraries and not the executable.
|
Use basename of main executable in POSIX-DYLD on Android.
Summary:
The Android dynamic linker reports only the basename of each SO entry, so for
the above check to be successful, we need to compare it to the basename of the
main executable.
This also has a nasty side-effect when working with older version of
Android (verified on platform version 16), and debugging PIE
executables: the dynamic linker has a bug and reports the load address
of the main executable (which is a shared object, because PIE) to be 0.
We then try to update the list of loaded sections for all shared
objects, including the main executable, and set the load address to 0,
which breaks everything that relies on resolving addresses in the main
executable (breakpoints, stepping, etc). This commit also fixes that broken
behavior when debugging on older Androids. This bug doesn't happen on newer
Android versions (verified for Android L).
Test Plan: Run test suite on linux.
Reviewers: clayborg, tfiala, richard.mitton
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D7188
llvm-svn: 228057
2015-02-04 06:48:34 +08:00
|
|
|
if (SOEntryIsMainExecutable(entry))
|
2012-01-06 05:48:15 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
entry_list.push_back(entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr_t
|
2013-10-02 22:14:05 +08:00
|
|
|
DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size)
|
2012-01-06 05:48:15 +08:00
|
|
|
{
|
|
|
|
Error error;
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
*dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
|
|
|
|
if (error.Fail())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return addr + size;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr_t
|
|
|
|
DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst)
|
|
|
|
{
|
|
|
|
Error error;
|
|
|
|
|
|
|
|
*dst = m_process->ReadPointerFromMemory(addr, error);
|
|
|
|
if (error.Fail())
|
2012-01-06 05:48:15 +08:00
|
|
|
return 0;
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
return addr + m_process->GetAddressByteSize();
|
2012-01-06 05:48:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string
|
|
|
|
DYLDRendezvous::ReadStringFromMemory(addr_t addr)
|
|
|
|
{
|
|
|
|
std::string str;
|
|
|
|
Error error;
|
|
|
|
|
|
|
|
if (addr == LLDB_INVALID_ADDRESS)
|
|
|
|
return std::string();
|
|
|
|
|
2014-09-04 22:16:19 +08:00
|
|
|
m_process->ReadCStringFromMemory(addr, str, error);
|
2012-01-06 05:48:15 +08:00
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
|
|
|
|
{
|
|
|
|
entry.clear();
|
Added support for reading thread-local storage variables, as defined using the __thread modifier.
To make this work this patch extends LLDB to:
- Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list.
- Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines.
- Make DWARF expressions track which module they originated from.
- Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here.
- Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here:
1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target.
2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out.
3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized.
However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used.
Test case included.
llvm-svn: 192922
2013-10-18 05:14:00 +08:00
|
|
|
|
|
|
|
entry.link_addr = addr;
|
2012-01-06 05:48:15 +08:00
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
if (!(addr = ReadPointer(addr, &entry.base_addr)))
|
2012-01-06 05:48:15 +08:00
|
|
|
return false;
|
2013-10-11 00:09:31 +08:00
|
|
|
|
|
|
|
// mips adds an extra load offset field to the link map struct on
|
|
|
|
// FreeBSD and NetBSD (need to validate other OSes).
|
|
|
|
// http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57
|
|
|
|
const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
|
2015-04-23 14:36:20 +08:00
|
|
|
if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD
|
|
|
|
|| arch.GetTriple().getOS() == llvm::Triple::NetBSD) &&
|
|
|
|
(arch.GetMachine() == llvm::Triple::mips || arch.GetMachine() == llvm::Triple::mipsel
|
|
|
|
|| arch.GetMachine() == llvm::Triple::mips64 || arch.GetMachine() == llvm::Triple::mips64el))
|
2013-10-11 00:09:31 +08:00
|
|
|
{
|
|
|
|
addr_t mips_l_offs;
|
|
|
|
if (!(addr = ReadPointer(addr, &mips_l_offs)))
|
|
|
|
return false;
|
|
|
|
if (mips_l_offs != 0 && mips_l_offs != entry.base_addr)
|
|
|
|
return false;
|
|
|
|
}
|
2012-01-06 05:48:15 +08:00
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
if (!(addr = ReadPointer(addr, &entry.path_addr)))
|
2012-01-06 05:48:15 +08:00
|
|
|
return false;
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
|
2012-01-06 05:48:15 +08:00
|
|
|
return false;
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
if (!(addr = ReadPointer(addr, &entry.next)))
|
2012-01-06 05:48:15 +08:00
|
|
|
return false;
|
|
|
|
|
2013-10-02 22:14:05 +08:00
|
|
|
if (!(addr = ReadPointer(addr, &entry.prev)))
|
2012-01-06 05:48:15 +08:00
|
|
|
return false;
|
2015-06-06 06:03:19 +08:00
|
|
|
|
|
|
|
entry.file_spec.SetFile(ReadStringFromMemory(entry.path_addr), false);
|
|
|
|
|
2015-06-19 04:43:56 +08:00
|
|
|
// The base_addr is not filled in for some case.
|
|
|
|
// Try to figure it out based on the load address of the object file.
|
|
|
|
if (entry.base_addr == 0)
|
|
|
|
{
|
|
|
|
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
|
|
|
|
bool is_loaded = false;
|
|
|
|
Error error = m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
|
|
|
|
if (error.Success() && is_loaded)
|
|
|
|
entry.base_addr = load_addr;
|
|
|
|
}
|
|
|
|
|
2012-01-06 05:48:15 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Added support for reading thread-local storage variables, as defined using the __thread modifier.
To make this work this patch extends LLDB to:
- Explicitly track the link_map address for each module. This is effectively the module handle, not sure why it wasn't already being stored off anywhere. As an extension later, it would be nice if someone were to add support for printing this as part of the modules list.
- Allow reading the per-thread data pointer via ptrace. I have added support for Linux here. I'll be happy to add support for FreeBSD once this is reviewed. OS X does not appear to have __thread variables, so maybe we don't need it there. Windows support should eventually be workable along the same lines.
- Make DWARF expressions track which module they originated from.
- Add support for the DW_OP_GNU_push_tls_address DWARF opcode, as generated by gcc and recent versions of clang. Earlier versions of clang (such as 3.2, which is default on Ubuntu right now) do not generate TLS debug info correctly so can not be supported here.
- Understand the format of the pthread DTV block. This is where it gets tricky. We have three basic options here:
1) Call "dlinfo" or "__tls_get_addr" on the inferior and ask it directly. However this won't work on core dumps, and generally speaking it's not a good idea for the debugger to call functions itself, as it has the potential to not work depending on the state of the target.
2) Use libthread_db. This is what GDB does. However this option requires having a version of libthread_db on the host cross-compiled for each potential target. This places a large burden on the user, and would make it very hard to cross-debug from Windows to Linux, for example. Trying to build a library intended exclusively for one OS on a different one is not pleasant. GDB sidesteps the problem and asks the user to figure it out.
3) Parse the DTV structure ourselves. On initial inspection this seems to be a bad option, as the DTV structure (the format used by the runtime to manage TLS data) is not in fact a kernel data structure, it is implemented entirely in useerland in libc. Therefore the layout of it's fields are version and OS dependent, and are not standardized.
However, it turns out not to be such a problem. All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only question therefore is the exact field layouts required. Happily, the implementors of libpthread expose the structure of the DTV via metadata exported as symbols from the .so itself, designed exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring third-party libraries, while still being independent of the version of libpthread being used.
Test case included.
llvm-svn: 192922
2013-10-18 05:14:00 +08:00
|
|
|
|
|
|
|
bool
|
|
|
|
DYLDRendezvous::FindMetadata(const char *name, PThreadField field, uint32_t& value)
|
|
|
|
{
|
|
|
|
Target& target = m_process->GetTarget();
|
|
|
|
|
|
|
|
SymbolContextList list;
|
|
|
|
if (!target.GetImages().FindSymbolsWithNameAndType (ConstString(name), eSymbolTypeAny, list))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Address address = list[0].symbol->GetAddress();
|
|
|
|
addr_t addr = address.GetLoadAddress (&target);
|
|
|
|
if (addr == LLDB_INVALID_ADDRESS)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Error error;
|
|
|
|
value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(addr + field*sizeof(uint32_t), sizeof(uint32_t), 0, error);
|
|
|
|
if (error.Fail())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (field == eSize)
|
|
|
|
value /= 8; // convert bits to bytes
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const DYLDRendezvous::ThreadInfo&
|
|
|
|
DYLDRendezvous::GetThreadInfo()
|
|
|
|
{
|
|
|
|
if (!m_thread_info.valid)
|
|
|
|
{
|
|
|
|
bool ok = true;
|
|
|
|
|
|
|
|
ok &= FindMetadata ("_thread_db_pthread_dtvp", eOffset, m_thread_info.dtv_offset);
|
|
|
|
ok &= FindMetadata ("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
|
|
|
|
ok &= FindMetadata ("_thread_db_link_map_l_tls_modid", eOffset, m_thread_info.modid_offset);
|
|
|
|
ok &= FindMetadata ("_thread_db_dtv_t_pointer_val", eOffset, m_thread_info.tls_offset);
|
|
|
|
|
|
|
|
if (ok)
|
|
|
|
m_thread_info.valid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_thread_info;
|
|
|
|
}
|
|
|
|
|
2012-01-06 05:48:15 +08:00
|
|
|
void
|
2013-03-28 07:08:40 +08:00
|
|
|
DYLDRendezvous::DumpToLog(Log *log) const
|
2012-01-06 05:48:15 +08:00
|
|
|
{
|
|
|
|
int state = GetState();
|
|
|
|
|
|
|
|
if (!log)
|
|
|
|
return;
|
|
|
|
|
|
|
|
log->PutCString("DYLDRendezvous:");
|
2012-11-30 05:49:15 +08:00
|
|
|
log->Printf(" Address: %" PRIx64, GetRendezvousAddress());
|
2013-01-26 02:06:21 +08:00
|
|
|
log->Printf(" Version: %" PRIu64, GetVersion());
|
2012-11-30 05:49:15 +08:00
|
|
|
log->Printf(" Link : %" PRIx64, GetLinkMapAddress());
|
|
|
|
log->Printf(" Break : %" PRIx64, GetBreakAddress());
|
|
|
|
log->Printf(" LDBase : %" PRIx64, GetLDBase());
|
2012-01-06 05:48:15 +08:00
|
|
|
log->Printf(" State : %s",
|
|
|
|
(state == eConsistent) ? "consistent" :
|
|
|
|
(state == eAdd) ? "add" :
|
|
|
|
(state == eDelete) ? "delete" : "unknown");
|
|
|
|
|
|
|
|
iterator I = begin();
|
|
|
|
iterator E = end();
|
|
|
|
|
|
|
|
if (I != E)
|
|
|
|
log->PutCString("DYLDRendezvous SOEntries:");
|
|
|
|
|
|
|
|
for (int i = 1; I != E; ++I, ++i)
|
|
|
|
{
|
2015-06-06 06:03:19 +08:00
|
|
|
log->Printf("\n SOEntry [%d] %s", i, I->file_spec.GetCString());
|
2012-11-30 05:49:15 +08:00
|
|
|
log->Printf(" Base : %" PRIx64, I->base_addr);
|
|
|
|
log->Printf(" Path : %" PRIx64, I->path_addr);
|
|
|
|
log->Printf(" Dyn : %" PRIx64, I->dyn_addr);
|
|
|
|
log->Printf(" Next : %" PRIx64, I->next);
|
|
|
|
log->Printf(" Prev : %" PRIx64, I->prev);
|
2012-01-06 05:48:15 +08:00
|
|
|
}
|
|
|
|
}
|