summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Expression/DWARFExpression.cpp76
-rw-r--r--lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp50
-rw-r--r--lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h23
-rw-r--r--lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp91
-rw-r--r--lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h15
-rw-r--r--lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp91
-rw-r--r--lldb/source/Plugins/Process/Linux/ProcessMonitor.h4
-rw-r--r--lldb/source/Plugins/Process/POSIX/POSIXThread.cpp11
-rw-r--r--lldb/source/Plugins/Process/POSIX/POSIXThread.h3
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp3
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp6
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp16
-rw-r--r--lldb/source/Target/Thread.cpp18
13 files changed, 381 insertions, 26 deletions
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 50879f58388..ad396d499f5 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -38,10 +38,12 @@
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackID.h"
+#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
+// TODO- why is this also defined (in a better way) in DWARFDefines.cpp?
const char *
DW_OP_value_to_name (uint32_t val)
{
@@ -220,6 +222,7 @@ DW_OP_value_to_name (uint32_t val)
// DWARFExpression constructor
//----------------------------------------------------------------------
DWARFExpression::DWARFExpression() :
+ m_module_wp(),
m_data(),
m_reg_kind (eRegisterKindDWARF),
m_loclist_slide (LLDB_INVALID_ADDRESS)
@@ -227,6 +230,7 @@ DWARFExpression::DWARFExpression() :
}
DWARFExpression::DWARFExpression(const DWARFExpression& rhs) :
+ m_module_wp(rhs.m_module_wp),
m_data(rhs.m_data),
m_reg_kind (rhs.m_reg_kind),
m_loclist_slide(rhs.m_loclist_slide)
@@ -234,11 +238,14 @@ DWARFExpression::DWARFExpression(const DWARFExpression& rhs) :
}
-DWARFExpression::DWARFExpression(const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length) :
+DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length) :
+ m_module_wp(),
m_data(data, data_offset, data_length),
m_reg_kind (eRegisterKindDWARF),
m_loclist_slide(LLDB_INVALID_ADDRESS)
{
+ if (module_sp)
+ m_module_wp = module_sp;
}
//----------------------------------------------------------------------
@@ -262,11 +269,12 @@ DWARFExpression::SetOpcodeData (const DataExtractor& data)
}
void
-DWARFExpression::CopyOpcodeData (const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length)
+DWARFExpression::CopyOpcodeData (lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length)
{
const uint8_t *bytes = data.PeekData(data_offset, data_length);
if (bytes)
{
+ m_module_wp = module_sp;
m_data.SetData(DataBufferSP(new DataBufferHeap(bytes, data_length)));
m_data.SetByteOrder(data.GetByteOrder());
m_data.SetAddressByteSize(data.GetAddressByteSize());
@@ -274,8 +282,9 @@ DWARFExpression::CopyOpcodeData (const DataExtractor& data, lldb::offset_t data_
}
void
-DWARFExpression::SetOpcodeData (const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length)
+DWARFExpression::SetOpcodeData (lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length)
{
+ m_module_wp = module_sp;
m_data.SetData(data, data_offset, data_length);
}
@@ -588,6 +597,9 @@ DWARFExpression::DumpLocation (Stream *s, lldb::offset_t offset, lldb::offset_t
// case DW_OP_APPLE_array_ref:
// s->PutCString("DW_OP_APPLE_array_ref");
// break;
+ case DW_OP_GNU_push_tls_address:
+ s->PutCString("DW_OP_GNU_push_tls_address"); // 0xe0
+ break;
case DW_OP_APPLE_uninit:
s->PutCString("DW_OP_APPLE_uninit"); // 0xF0
break;
@@ -919,7 +931,8 @@ GetOpcodeDataSize (const DataExtractor &data, const lldb::offset_t data_offset,
case DW_OP_form_tls_address: // 0x9b DWARF3
case DW_OP_call_frame_cfa: // 0x9c DWARF3
case DW_OP_stack_value: // 0x9f DWARF4
- return 0;
+ case DW_OP_GNU_push_tls_address: // 0xe0 GNU extension
+ return 0;
// Opcodes with a single 1 byte arguments
case DW_OP_const1u: // 0x08 1 1-byte constant
@@ -1221,6 +1234,8 @@ DWARFExpression::Evaluate
Error *error_ptr
) const
{
+ ModuleSP module_sp = m_module_wp.lock();
+
if (IsLocationList())
{
lldb::offset_t offset = 0;
@@ -1268,7 +1283,7 @@ DWARFExpression::Evaluate
if (length > 0 && lo_pc <= pc && pc < hi_pc)
{
- return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, m_data, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
+ return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
}
offset += length;
}
@@ -1280,7 +1295,7 @@ DWARFExpression::Evaluate
}
// Not a location list, just a single expression.
- return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, m_data, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
+ return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
}
@@ -1292,6 +1307,7 @@ DWARFExpression::Evaluate
ClangExpressionVariableList *expr_locals,
ClangExpressionDeclMap *decl_map,
RegisterContext *reg_ctx,
+ lldb::ModuleSP opcode_ctx,
const DataExtractor& opcodes,
const lldb::offset_t opcodes_offset,
const lldb::offset_t opcodes_length,
@@ -2659,6 +2675,54 @@ DWARFExpression::Evaluate
return false;
}
break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_GNU_push_tls_address
+ // OPERANDS: none
+ // DESCRIPTION: Pops a TLS offset from the stack, converts it to
+ // an absolute value, and pushes it back on.
+ //----------------------------------------------------------------------
+ case DW_OP_GNU_push_tls_address:
+ {
+ if (stack.size() < 1)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString("DW_OP_GNU_push_tls_address needs an argument.");
+ return false;
+ }
+
+ if (!exe_ctx || !opcode_ctx)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString("No context to evaluate TLS within.");
+ return false;
+ }
+
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (!thread)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString("No thread to evaluate TLS within.");
+ return false;
+ }
+
+ // Lookup the TLS block address for this thread and module.
+ addr_t tls_addr = thread->GetThreadLocalData (opcode_ctx);
+
+ if (tls_addr == LLDB_INVALID_ADDRESS)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString ("No TLS data currently exists for this thread.");
+ return false;
+ }
+
+ // Convert the TLS offset into the absolute address.
+ Scalar tmp = stack.back().ResolveValue(exe_ctx);
+ stack.back() = tmp + tls_addr;
+ stack.back().SetValueType (Value::eValueTypeLoadAddress);
+ }
+ break;
+
default:
if (log)
log->Printf("Unhandled opcode %s in DWARFExpression.", DW_OP_value_to_name(op));
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 556df606248..3c5dcc5222a 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -55,6 +56,8 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
m_added_soentries(),
m_removed_soentries()
{
+ m_thread_info.valid = false;
+
// Cache a copy of the executable path
if (m_process)
{
@@ -284,6 +287,8 @@ bool
DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
{
entry.clear();
+
+ entry.link_addr = addr;
if (!(addr = ReadPointer(addr, &entry.base_addr)))
return false;
@@ -320,6 +325,51 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
return true;
}
+
+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;
+}
+
void
DYLDRendezvous::DumpToLog(Log *log) const
{
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index 5f8b013dd4a..ca008931799 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -48,6 +48,16 @@ class DYLDRendezvous {
};
public:
+ // Various metadata supplied by the inferior's threading library to describe
+ // the per-thread state.
+ struct ThreadInfo {
+ bool valid; // whether we read valid metadata
+ uint32_t dtv_offset; // offset of DTV pointer within pthread
+ uint32_t dtv_slot_size; // size of one DTV slot
+ uint32_t modid_offset; // offset of module ID within link_map
+ uint32_t tls_offset; // offset of TLS pointer within DTV slot
+ };
+
DYLDRendezvous(lldb_private::Process *process);
/// Update the internal snapshot of runtime linker rendezvous and recompute
@@ -100,6 +110,10 @@ public:
lldb::addr_t
GetLDBase() const { return m_current.ldbase; }
+ /// @returns the thread layout metadata from the inferiors thread library.
+ const ThreadInfo&
+ GetThreadInfo();
+
/// @returns true if modules have been loaded into the inferior since the
/// last call to Resolve().
bool
@@ -128,6 +142,7 @@ public:
/// This object is a rough analogue to the struct link_map object which
/// actually lives in the inferiors memory.
struct SOEntry {
+ lldb::addr_t link_addr; ///< Address of this link_map.
lldb::addr_t base_addr; ///< Base address of the loaded object.
lldb::addr_t path_addr; ///< String naming the shared object.
lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
@@ -142,6 +157,7 @@ public:
}
void clear() {
+ link_addr = 0;
base_addr = 0;
path_addr = 0;
dyn_addr = 0;
@@ -194,6 +210,9 @@ protected:
/// Resolve().
SOEntryList m_removed_soentries;
+ /// Threading metadata read from the inferior.
+ ThreadInfo m_thread_info;
+
/// Reads an unsigned integer of @p size bytes from the inferior's address
/// space starting at @p addr.
///
@@ -232,6 +251,10 @@ protected:
/// supplied by the runtime linker.
bool
TakeSnapshot(SOEntryList &entry_list);
+
+ enum PThreadField { eSize, eNElem, eOffset };
+
+ bool FindMetadata(const char *name, PThreadField field, uint32_t& value);
};
#endif
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 8a0b194446c..cb7adc4f3ec 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -123,7 +123,7 @@ DynamicLoaderPOSIXDYLD::DidAttach()
{
ModuleList module_list;
module_list.Append(executable);
- UpdateLoadedSections(executable, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
LoadAllCurrentModules();
m_process->GetTarget().ModulesDidLoad(module_list);
}
@@ -144,7 +144,7 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
{
ModuleList module_list;
module_list.Append(executable);
- UpdateLoadedSections(executable, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
ProbeEntry();
m_process->GetTarget().ModulesDidLoad(module_list);
}
@@ -209,13 +209,15 @@ DynamicLoaderPOSIXDYLD::CanLoadImage()
}
void
-DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
+DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
{
SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
const SectionList *sections = GetSectionListFromModule(module);
assert(sections && "SectionList missing from loaded module.");
+ m_loaded_modules[module] = link_map_addr;
+
const size_t num_sections = sections->GetSize();
for (unsigned i = 0; i < num_sections; ++i)
@@ -243,6 +245,8 @@ DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module)
assert(sections && "SectionList missing from unloaded module.");
+ m_loaded_modules.erase(module);
+
const size_t num_sections = sections->GetSize();
for (size_t i = 0; i < num_sections; ++i)
{
@@ -337,7 +341,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
for (I = m_rendezvous.loaded_begin(); I != E; ++I)
{
FileSpec file(I->path.c_str(), true);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
if (module_sp.get())
{
loaded_modules.AppendIfNeeded(module_sp);
@@ -439,11 +443,17 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
return;
}
+ // The rendezvous class doesn't enumerate the main module, so track
+ // that ourselves here.
+ ModuleSP executable = GetTargetExecutable();
+ m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
+
+
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
{
const char *module_path = I->path.c_str();
FileSpec file(module_path, false);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
if (module_sp.get())
{
module_list.Append(module_sp);
@@ -461,7 +471,7 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
}
ModuleSP
-DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)
+DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr)
{
Target &target = m_process->GetTarget();
ModuleList &modules = target.GetImages();
@@ -470,11 +480,11 @@ DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_ad
ModuleSpec module_spec (file, target.GetArchitecture());
if ((module_sp = modules.FindFirstModule (module_spec)))
{
- UpdateLoadedSections(module_sp, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr);
}
else if ((module_sp = target.GetSharedModule(module_spec)))
{
- UpdateLoadedSections(module_sp, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr);
}
return module_sp;
@@ -537,3 +547,68 @@ DynamicLoaderPOSIXDYLD::GetSectionListFromModule(const ModuleSP module) const
}
return sections;
}
+
+static int ReadInt(Process *process, addr_t addr)
+{
+ Error error;
+ int value = (int)process->ReadUnsignedIntegerFromMemory(addr, sizeof(uint32_t), 0, error);
+ if (error.Fail())
+ return -1;
+ else
+ return value;
+}
+
+static addr_t ReadPointer(Process *process, addr_t addr)
+{
+ Error error;
+ addr_t value = process->ReadPointerFromMemory(addr, error);
+ if (error.Fail())
+ return LLDB_INVALID_ADDRESS;
+ else
+ return value;
+}
+
+lldb::addr_t
+DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread)
+{
+ std::map<ModuleWP, addr_t>::const_iterator it = m_loaded_modules.find (module);
+ if (it == m_loaded_modules.end())
+ return LLDB_INVALID_ADDRESS;
+
+ addr_t link_map = it->second;
+ if (link_map == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ const DYLDRendezvous::ThreadInfo &metadata = m_rendezvous.GetThreadInfo();
+ if (!metadata.valid)
+ return LLDB_INVALID_ADDRESS;
+
+ // Get the thread pointer.
+ addr_t tp = thread->GetThreadPointer ();
+ if (tp == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ // Find the module's modid.
+ int modid = ReadInt (m_process, link_map + metadata.modid_offset);
+ if (modid == -1)
+ return LLDB_INVALID_ADDRESS;
+
+ // Lookup the DTV stucture for this thread.
+ addr_t dtv_ptr = tp + metadata.dtv_offset;
+ addr_t dtv = ReadPointer (m_process, dtv_ptr);
+ if (dtv == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ // Find the TLS block for this module.
+ addr_t dtv_slot = dtv + metadata.dtv_slot_size*modid;
+ addr_t tls_block = ReadPointer (m_process, dtv_slot + metadata.tls_offset);
+
+ Module *mod = module.get();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: "
+ "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%i, tls_block=0x%" PRIx64 "\n",
+ mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block);
+
+ return tls_block;
+}
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 414f12098cf..7997b34195a 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -61,6 +61,9 @@ public:
virtual lldb_private::Error
CanLoadImage();
+ virtual lldb::addr_t
+ GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread);
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -95,6 +98,9 @@ protected:
/// Rendezvous breakpoint.
lldb::break_id_t m_dyld_bid;
+ /// Loaded module list. (link map for each module)
+ std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> m_loaded_modules;
+
/// Enables a breakpoint on a function called by the runtime
/// linker each time a module is loaded or unloaded.
void
@@ -117,10 +123,13 @@ protected:
///
/// @param module The module to traverse.
///
+ /// @param link_map_addr The virtual address of the link map for the @p module.
+ ///
/// @param base_addr The virtual base address @p module is loaded at.
void
- UpdateLoadedSections(lldb::ModuleSP module,
- lldb::addr_t base_addr = 0);
+ UpdateLoadedSections(lldb::ModuleSP module,
+ lldb::addr_t link_map_addr,
+ lldb::addr_t base_addr);
/// Removes the loaded sections from the target in @p module.
///
@@ -131,7 +140,7 @@ protected:
/// Locates or creates a module given by @p file and updates/loads the
/// resulting module at the virtual base address @p base_addr.
lldb::ModuleSP
- LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr);
+ LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr);
/// Resolves the entry point for the current inferior process and sets a
/// breakpoint at that address.
diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
index a0cda3485c6..bda0cb33097 100644
--- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
+++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
@@ -19,6 +19,7 @@
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
+#include <sys/user.h>
#include <sys/wait.h>
// C++ Includes
@@ -46,6 +47,19 @@
#ifndef PTRACE_SETREGSET
#define PTRACE_SETREGSET 0x4205
#endif
+#ifndef PTRACE_GET_THREAD_AREA
+ #define PTRACE_GET_THREAD_AREA 25
+#endif
+#ifndef PTRACE_ARCH_PRCTL
+ #define PTRACE_ARCH_PRCTL 30
+#endif
+#ifndef ARCH_GET_FS
+ #define ARCH_SET_GS 0x1001
+ #define ARCH_SET_FS 0x1002
+ #define ARCH_GET_FS 0x1003
+ #define ARCH_GET_GS 0x1004
+#endif
+
// Support hardware breakpoints in case it has not been defined
#ifndef TRAP_HWBKPT
@@ -703,6 +717,74 @@ WriteRegisterSetOperation::Execute(ProcessMonitor *monitor)
}
//------------------------------------------------------------------------------
+/// @class ReadThreadPointerOperation
+/// @brief Implements ProcessMonitor::ReadThreadPointer.
+class ReadThreadPointerOperation : public Operation
+{
+public:
+ ReadThreadPointerOperation(lldb::tid_t tid, lldb::addr_t *addr, bool &result)
+ : m_tid(tid), m_addr(addr), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ lldb::addr_t *m_addr;
+ bool &m_result;
+};
+
+void
+ReadThreadPointerOperation::Execute(ProcessMonitor *monitor)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+ if (log)
+ log->Printf ("ProcessMonitor::%s()", __FUNCTION__);
+
+ // The process for getting the thread area on Linux is
+ // somewhat... obscure. There's several different ways depending on
+ // what arch you're on, and what kernel version you have.
+
+ const ArchSpec& arch = monitor->GetProcess().GetTarget().GetArchitecture();
+ switch(arch.GetMachine())
+ {
+ case llvm::Triple::x86:
+ {
+ // Find the GS register location for our host architecture.
+ size_t gs_user_offset = offsetof(struct user, regs);
+#ifdef __x86_64__
+ gs_user_offset += offsetof(struct user_regs_struct, gs);
+#endif
+#ifdef __i386__
+ gs_user_offset += offsetof(struct user_regs_struct, xgs);
+#endif
+
+ // Read the GS register value to get the selector.
+ errno = 0;
+ long gs = PTRACE(PTRACE_PEEKUSER, m_tid, (void*)gs_user_offset, NULL, 0);
+ if (errno)
+ {
+ m_result = false;
+ break;
+ }
+
+ // Read the LDT base for that selector.
+ uint32_t tmp[4];
+ m_result = (PTRACE(PTRACE_GET_THREAD_AREA, m_tid, (void *)(gs >> 3), &tmp, 0) == 0);
+ *m_addr = tmp[1];
+ break;
+ }
+ case llvm::Triple::x86_64:
+ // Read the FS register base.
+ m_result = (PTRACE(PTRACE_ARCH_PRCTL, m_tid, m_addr, (void *)ARCH_GET_FS, 0) == 0);
+ break;
+ default:
+ m_result = false;
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
/// @class ResumeOperation
/// @brief Implements ProcessMonitor::Resume.
class ResumeOperation : public Operation
@@ -2106,6 +2188,15 @@ ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, un
}
bool
+ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value)
+{
+ bool result;
+ ReadThreadPointerOperation op(tid, &value, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)
{
bool result;
diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.h b/lldb/source/Plugins/Process/Linux/ProcessMonitor.h
index 3729e257feb..a087140f407 100644
--- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.h
+++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.h
@@ -147,6 +147,10 @@ public:
bool
WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
+ /// Reads the value of the thread-specific pointer for a given thread ID.
+ bool
+ ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value);
+
/// Writes a siginfo_t structure corresponding to the given thread ID to the
/// memory region pointed to by @p siginfo.
bool
diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp
index db68875723c..16399748c54 100644
--- a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp
+++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp
@@ -230,6 +230,17 @@ POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
return reg_ctx_sp;
}
+lldb::addr_t
+POSIXThread::GetThreadPointer ()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ addr_t addr;
+ if (monitor.ReadThreadPointer (GetID(), addr))
+ return addr;
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
bool
POSIXThread::CalculateStopInfo()
{
diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.h b/lldb/source/Plugins/Process/POSIX/POSIXThread.h
index 5490f1f1ea5..51d6645f209 100644
--- a/lldb/source/Plugins/Process/POSIX/POSIXThread.h
+++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.h
@@ -59,6 +59,9 @@ public:
virtual lldb::RegisterContextSP
CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ virtual lldb::addr_t
+ GetThreadPointer ();
+
//--------------------------------------------------------------------------
// These functions provide a mapping from the register offset
// back to the register index or name for use in debugging or log
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 2a01d6a92d9..c19aec3a02c 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -1196,7 +1196,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
unwindplan_regloc.GetDWARFExpressionLength(),
process->GetByteOrder(), process->GetAddressByteSize());
- DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
+ ModuleSP opcode_ctx;
+ DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (unwindplan_registerkind);
Value result;
Error error;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 7351f1d9509..5dd81b7bb96 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -763,6 +763,8 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
lldb::offset_t offset;
const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
+ lldb::ModuleSP module = dwarf2Data->GetObjectFile()->GetModule();
+
if (abbrevDecl)
{
const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
@@ -874,7 +876,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
{
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- frame_base->SetOpcodeData(debug_info_data, block_offset, block_length);
+ frame_base->SetOpcodeData(module, debug_info_data, block_offset, block_length);
}
else
{
@@ -884,7 +886,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
if (loc_list_length > 0)
{
- frame_base->SetOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length);
+ frame_base->SetOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length);
if (lo_pc != LLDB_INVALID_ADDRESS)
{
assert (lo_pc >= cu->GetBaseAddress());
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 2579fe07591..c703ce5ed8a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1706,6 +1706,7 @@ SymbolFileDWARF::ParseChildMembers
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
uint32_t member_idx = 0;
BitfieldInfo last_field_info;
+ ModuleSP module = GetObjectFile()->GetModule();
for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
{
@@ -1769,6 +1770,7 @@ SymbolFileDWARF::ParseChildMembers
NULL, // ClangExpressionVariableList *
NULL, // ClangExpressionDeclMap *
NULL, // RegisterContext *
+ module,
debug_info_data,
block_offset,
block_length,
@@ -2160,6 +2162,7 @@ SymbolFileDWARF::ParseChildMembers
NULL,
NULL,
NULL,
+ module,
debug_info_data,
block_offset,
block_length,
@@ -7267,6 +7270,7 @@ SymbolFileDWARF::ParseVariableDIE
return var_sp; // Already been parsed!
const dw_tag_t tag = die->Tag();
+ ModuleSP module = GetObjectFile()->GetModule();
if ((tag == DW_TAG_variable) ||
(tag == DW_TAG_constant) ||
@@ -7316,7 +7320,7 @@ SymbolFileDWARF::ParseVariableDIE
// Retrieve the value as a block expression.
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- location.CopyOpcodeData(debug_info_data, block_offset, block_length);
+ location.CopyOpcodeData(module, debug_info_data, block_offset, block_length);
}
else if (DWARFFormValue::IsDataForm(form_value.Form()))
{
@@ -7324,7 +7328,7 @@ SymbolFileDWARF::ParseVariableDIE
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
uint32_t data_length = fixed_form_sizes[form_value.Form()];
- location.CopyOpcodeData(debug_info_data, data_offset, data_length);
+ location.CopyOpcodeData(module, debug_info_data, data_offset, data_length);
}
else
{
@@ -7334,14 +7338,14 @@ SymbolFileDWARF::ParseVariableDIE
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
uint32_t data_length = fixed_form_sizes[form_value.Form()];
- location.CopyOpcodeData(debug_info_data, data_offset, data_length);
+ location.CopyOpcodeData(module, debug_info_data, data_offset, data_length);
}
else
{
const char *str = form_value.AsCString(&debug_info_data);
uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart();
uint32_t string_length = strlen(str) + 1;
- location.CopyOpcodeData(debug_info_data, string_offset, string_length);
+ location.CopyOpcodeData(module, debug_info_data, string_offset, string_length);
}
}
}
@@ -7356,7 +7360,7 @@ SymbolFileDWARF::ParseVariableDIE
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- location.CopyOpcodeData(get_debug_info_data(), block_offset, block_length);
+ location.CopyOpcodeData(module, get_debug_info_data(), block_offset, block_length);
}
else
{
@@ -7366,7 +7370,7 @@ SymbolFileDWARF::ParseVariableDIE
size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
if (loc_list_length > 0)
{
- location.CopyOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length);
+ location.CopyOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length);
assert (func_low_pc != LLDB_INVALID_ADDRESS);
location.SetLocationListSlide (func_low_pc - dwarf_cu->GetBaseAddress());
}
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 0ef91e8a650..1e33565a4c5 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -1857,6 +1857,24 @@ Thread::SettingsTerminate ()
{
}
+lldb::addr_t
+Thread::GetThreadPointer ()
+{
+ return LLDB_INVALID_ADDRESS;
+}
+
+addr_t
+Thread::GetThreadLocalData (const ModuleSP module)
+{
+ // The default implementation is to ask the dynamic loader for it.
+ // This can be overridden for specific platforms.
+ DynamicLoader *loader = GetProcess()->GetDynamicLoader();
+ if (loader)
+ return loader->GetThreadLocalData (module, shared_from_this());
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
lldb::StackFrameSP
Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
{
OpenPOWER on IntegriCloud