summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/API/SBBlock.cpp2
-rw-r--r--lldb/source/API/SBFrame.cpp51
-rw-r--r--lldb/source/API/SBValue.cpp4
-rw-r--r--lldb/source/Commands/CommandObjectFrame.cpp4
-rw-r--r--lldb/source/Commands/CommandObjectTarget.cpp5
-rw-r--r--lldb/source/Expression/DWARFExpression.cpp132
-rw-r--r--lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp5
-rw-r--r--lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h2
-rw-r--r--lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp178
-rw-r--r--lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h14
-rw-r--r--lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp5
-rw-r--r--lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp19
-rw-r--r--lldb/source/Symbol/SymbolContext.cpp4
-rw-r--r--lldb/source/Symbol/Variable.cpp8
-rw-r--r--lldb/source/Target/Thread.cpp4
16 files changed, 377 insertions, 62 deletions
diff --git a/lldb/source/API/SBBlock.cpp b/lldb/source/API/SBBlock.cpp
index f6231297277..03ee7343c9f 100644
--- a/lldb/source/API/SBBlock.cpp
+++ b/lldb/source/API/SBBlock.cpp
@@ -294,6 +294,7 @@ SBBlock::GetVariables (lldb::SBFrame& frame,
{
case eValueTypeVariableGlobal:
case eValueTypeVariableStatic:
+ case eValueTypeVariableThreadLocal:
add_variable = statics;
break;
@@ -356,6 +357,7 @@ SBBlock::GetVariables (lldb::SBTarget& target,
{
case eValueTypeVariableGlobal:
case eValueTypeVariableStatic:
+ case eValueTypeVariableThreadLocal:
add_variable = statics;
break;
diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp
index dc618d2c65c..38bbfb8675f 100644
--- a/lldb/source/API/SBFrame.cpp
+++ b/lldb/source/API/SBFrame.cpp
@@ -901,33 +901,31 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy
case eValueTypeVariableStatic: // static variable
case eValueTypeVariableArgument: // function argument variables
case eValueTypeVariableLocal: // function local variables
+ case eValueTypeVariableThreadLocal: // thread local variables
+ {
+ SymbolContext sc(frame->GetSymbolContext(eSymbolContextBlock));
+
+ const bool can_create = true;
+ const bool get_parent_variables = true;
+ const bool stop_if_block_is_inlined_function = true;
+
+ if (sc.block)
+ sc.block->AppendVariables(can_create, get_parent_variables, stop_if_block_is_inlined_function,
+ [frame](Variable *v) { return v->IsInScope(frame); }, &variable_list);
+ if (value_type == eValueTypeVariableGlobal)
{
- SymbolContext sc(frame->GetSymbolContext(eSymbolContextBlock));
-
- const bool can_create = true;
- const bool get_parent_variables = true;
- const bool stop_if_block_is_inlined_function = true;
-
- if (sc.block)
- sc.block->AppendVariables(can_create,
- get_parent_variables,
- stop_if_block_is_inlined_function,
- [frame](Variable* v) { return v->IsInScope(frame); },
- &variable_list);
- if (value_type == eValueTypeVariableGlobal)
- {
- const bool get_file_globals = true;
- VariableList *frame_vars = frame->GetVariableList(get_file_globals);
- if (frame_vars)
- frame_vars->AppendVariablesIfUnique(variable_list);
- }
- ConstString const_name(name);
- VariableSP variable_sp(variable_list.FindVariable(const_name, value_type));
- if (variable_sp)
- {
- value_sp = frame->GetValueObjectForFrameVariable(variable_sp, eNoDynamicValues);
- sb_value.SetSP(value_sp, use_dynamic);
- }
+ const bool get_file_globals = true;
+ VariableList *frame_vars = frame->GetVariableList(get_file_globals);
+ if (frame_vars)
+ frame_vars->AppendVariablesIfUnique(variable_list);
+ }
+ ConstString const_name(name);
+ VariableSP variable_sp(variable_list.FindVariable(const_name, value_type));
+ if (variable_sp)
+ {
+ value_sp = frame->GetValueObjectForFrameVariable(variable_sp, eNoDynamicValues);
+ sb_value.SetSP(value_sp, use_dynamic);
+ }
}
break;
@@ -1201,6 +1199,7 @@ SBFrame::GetVariables (const lldb::SBVariablesOptions& options)
{
case eValueTypeVariableGlobal:
case eValueTypeVariableStatic:
+ case eValueTypeVariableThreadLocal:
add_variable = statics;
break;
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp
index a93cd8d5546..d08073306cc 100644
--- a/lldb/source/API/SBValue.cpp
+++ b/lldb/source/API/SBValue.cpp
@@ -528,6 +528,10 @@ SBValue::GetValueType ()
log->Printf ("SBValue(%p)::GetValueType () => eValueTypeConstResult",
static_cast<void*>(value_sp.get()));
break;
+ case eValueTypeVariableThreadLocal:
+ log->Printf("SBValue(%p)::GetValueType () => eValueTypeVariableThreadLocal",
+ static_cast<void *>(value_sp.get()));
+ break;
}
}
return result;
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index a5810085519..cc70cf23ad7 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -539,6 +539,10 @@ protected:
scope_string = " LOCAL: ";
break;
+ case eValueTypeVariableThreadLocal:
+ if (dump_variable && m_option_variable.show_scope)
+ scope_string = "THREAD: ";
+ break;
default:
break;
}
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 45d372cba02..f70100c324e 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -795,6 +795,11 @@ public:
s.PutCString(" LOCAL: ");
break;
+ case eValueTypeVariableThreadLocal:
+ if (m_option_variable.show_scope)
+ s.PutCString("THREAD: ");
+ break;
+
default:
break;
}
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 610c8cf3a5f..b81d60e9b06 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1003,7 +1003,128 @@ DWARFExpression::Update_DW_OP_addr (lldb::addr_t file_addr)
}
bool
-DWARFExpression::LocationListContainsAddress (lldb::addr_t loclist_base_addr, lldb::addr_t addr) const
+DWARFExpression::ContainsThreadLocalStorage() const
+{
+ // We are assuming for now that any thread local variable will not
+ // have a location list. This has been true for all thread local
+ // variables we have seen so far produced by any compiler.
+ if (IsLocationList())
+ return false;
+ lldb::offset_t offset = 0;
+ while (m_data.ValidOffset(offset))
+ {
+ const uint8_t op = m_data.GetU8(&offset);
+
+ if (op == DW_OP_form_tls_address || op == DW_OP_GNU_push_tls_address)
+ return true;
+ const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
+ if (op_arg_size == LLDB_INVALID_OFFSET)
+ return false;
+ else
+ offset += op_arg_size;
+ }
+ return false;
+}
+bool
+DWARFExpression::LinkThreadLocalStorage(
+ lldb::ModuleSP new_module_sp, std::function<lldb::addr_t(lldb::addr_t file_addr)> const &link_address_callback)
+{
+ // We are assuming for now that any thread local variable will not
+ // have a location list. This has been true for all thread local
+ // variables we have seen so far produced by any compiler.
+ if (IsLocationList())
+ return false;
+
+ const uint32_t addr_byte_size = m_data.GetAddressByteSize();
+ // We have to make a copy of the data as we don't know if this
+ // data is from a read only memory mapped buffer, so we duplicate
+ // all of the data first, then modify it, and if all goes well,
+ // we then replace the data for this expression
+
+ // So first we copy the data into a heap buffer
+ std::shared_ptr<DataBufferHeap> heap_data_sp(new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize()));
+
+ // Make en encoder so we can write the address into the buffer using
+ // the correct byte order (endianness)
+ DataEncoder encoder(heap_data_sp->GetBytes(), heap_data_sp->GetByteSize(), m_data.GetByteOrder(), addr_byte_size);
+
+ lldb::offset_t offset = 0;
+ lldb::offset_t const_offset = 0;
+ lldb::addr_t const_value = 0;
+ size_t const_byte_size = 0;
+ while (m_data.ValidOffset(offset))
+ {
+ const uint8_t op = m_data.GetU8(&offset);
+
+ bool decoded_data = false;
+ switch (op)
+ {
+ case DW_OP_const4u:
+ // Remember the const offset in case we later have a DW_OP_form_tls_address
+ // or DW_OP_GNU_push_tls_address
+ const_offset = offset;
+ const_value = m_data.GetU32(&offset);
+ decoded_data = true;
+ const_byte_size = 4;
+ break;
+
+ case DW_OP_const8u:
+ // Remember the const offset in case we later have a DW_OP_form_tls_address
+ // or DW_OP_GNU_push_tls_address
+ const_offset = offset;
+ const_value = m_data.GetU64(&offset);
+ decoded_data = true;
+ const_byte_size = 8;
+ break;
+
+ case DW_OP_form_tls_address:
+ case DW_OP_GNU_push_tls_address:
+ // DW_OP_form_tls_address and DW_OP_GNU_push_tls_address must be preceded by
+ // a file address on the stack. We assume that DW_OP_const4u or DW_OP_const8u
+ // is used for these values, and we check that the last opcode we got before
+ // either of these was DW_OP_const4u or DW_OP_const8u. If so, then we can link
+ // the value accodingly. For Darwin, the value in the DW_OP_const4u or
+ // DW_OP_const8u is the file address of a structure that contains a function
+ // pointer, the pthread key and the offset into the data pointed to by the
+ // pthread key. So we must link this address and also set the module of this
+ // expression to the new_module_sp so we can resolve the file address correctly
+ if (const_byte_size > 0)
+ {
+ lldb::addr_t linked_file_addr = link_address_callback(const_value);
+ if (linked_file_addr == LLDB_INVALID_ADDRESS)
+ return false;
+ // Replace the address in the new buffer
+ if (encoder.PutMaxU64(const_offset, const_byte_size, linked_file_addr) == UINT32_MAX)
+ return false;
+ }
+ break;
+
+ default:
+ const_offset = 0;
+ const_value = 0;
+ const_byte_size = 0;
+ break;
+ }
+
+ if (!decoded_data)
+ {
+ const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
+ if (op_arg_size == LLDB_INVALID_OFFSET)
+ return false;
+ else
+ offset += op_arg_size;
+ }
+ }
+
+ // If we linked the TLS address correctly, update the module so that when the expression
+ // is evaluated it can resolve the file address to a load address and read the TLS data
+ m_module_wp = new_module_sp;
+ m_data.SetData(heap_data_sp);
+ return true;
+}
+
+bool
+DWARFExpression::LocationListContainsAddress(lldb::addr_t loclist_base_addr, lldb::addr_t addr) const
{
if (addr == LLDB_INVALID_ADDRESS)
return false;
@@ -2845,18 +2966,17 @@ DWARFExpression::Evaluate
}
// Lookup the TLS block address for this thread and module.
- addr_t tls_addr = thread->GetThreadLocalData (module_sp);
+ const addr_t tls_file_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+ const addr_t tls_load_addr = thread->GetThreadLocalData(module_sp, tls_file_addr);
- if (tls_addr == LLDB_INVALID_ADDRESS)
+ if (tls_load_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().GetScalar() = tls_load_addr;
stack.back().SetValueType (Value::eValueTypeLoadAddress);
}
break;
diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
index da14d9b10ae..0f7c6486886 100644
--- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -646,7 +646,8 @@ static int ReadInt(Process *process, addr_t addr)
}
lldb::addr_t
-DynamicLoaderHexagonDYLD::GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread)
+DynamicLoaderHexagonDYLD::GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread,
+ lldb::addr_t tls_file_addr)
{
auto it = m_loaded_modules.find (module);
if (it == m_loaded_modules.end())
@@ -687,5 +688,5 @@ DynamicLoaderHexagonDYLD::GetThreadLocalData (const lldb::ModuleSP module, const
"module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%i, tls_block=0x%" PRIx64,
mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block);
- return tls_block;
+ return tls_block + tls_file_addr;
}
diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
index 1cc1e29a4a3..67c32887d09 100644
--- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
+++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
@@ -59,7 +59,7 @@ public:
CanLoadImage() override;
lldb::addr_t
- GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override;
+ GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread, lldb::addr_t tls_file_addr) override;
//------------------------------------------------------------------
// PluginInterface protocol
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
index 33f428bb020..9cca56fc3a2 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
@@ -17,16 +17,18 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
+#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/ABI.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
-#include "lldb/Target/StackFrame.h"
#include "DynamicLoaderMacOSXDYLD.h"
@@ -142,8 +144,11 @@ DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD(Process *process)
: DynamicLoader(process),
m_dyld(),
m_dyld_module_wp(),
+ m_libpthread_module_wp(),
+ m_pthread_getspecific_addr(),
m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
m_dyld_all_image_infos(),
+ m_tid_to_tls_map(),
m_dyld_all_image_infos_stop_id(UINT32_MAX),
m_break_id(LLDB_INVALID_BREAK_ID),
m_dyld_image_infos(),
@@ -192,6 +197,7 @@ DynamicLoaderMacOSXDYLD::DidLaunch ()
bool
DynamicLoaderMacOSXDYLD::ProcessDidExec ()
{
+ bool did_exec = false;
if (m_process)
{
// If we are stopped after an exec, we will have only one thread...
@@ -205,35 +211,42 @@ DynamicLoaderMacOSXDYLD::ProcessDidExec ()
{
// The image info address from the process is the 'dyld_all_image_infos'
// address and it has changed.
- return true;
+ did_exec = true;
}
-
- if (m_process_image_addr_is_all_images_infos == false && shlib_addr == m_dyld.address)
+ else if (m_process_image_addr_is_all_images_infos == false && shlib_addr == m_dyld.address)
{
// The image info address from the process is the mach_header
// address for dyld and it has changed.
- return true;
+ did_exec = true;
}
-
- // ASLR might be disabled and dyld could have ended up in the same
- // location. We should try and detect if we are stopped at '_dyld_start'
- ThreadSP thread_sp (m_process->GetThreadList().GetThreadAtIndex(0));
- if (thread_sp)
+ else
{
- lldb::StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex(0));
- if (frame_sp)
+ // ASLR might be disabled and dyld could have ended up in the same
+ // location. We should try and detect if we are stopped at '_dyld_start'
+ ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0));
+ if (thread_sp)
{
- const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
- if (symbol)
+ lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
+ if (frame_sp)
{
- if (symbol->GetName() == ConstString("_dyld_start"))
- return true;
+ const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
+ if (symbol)
+ {
+ if (symbol->GetName() == ConstString("_dyld_start"))
+ did_exec = true;
+ }
}
}
}
+
+ if (did_exec)
+ {
+ m_libpthread_module_wp.reset();
+ m_pthread_getspecific_addr.Clear();
+ }
}
}
- return false;
+ return did_exec;
}
@@ -1982,6 +1995,135 @@ DynamicLoaderMacOSXDYLD::CanLoadImage ()
return error;
}
+lldb::ModuleSP
+DynamicLoaderMacOSXDYLD::GetPThreadLibraryModule()
+{
+ ModuleSP module_sp = m_libpthread_module_wp.lock();
+ if (!module_sp)
+ {
+ SymbolContextList sc_list;
+ ModuleSpec module_spec;
+ module_spec.GetFileSpec().GetFilename().SetCString("libsystem_pthread.dylib");
+ ModuleList module_list;
+ if (m_process->GetTarget().GetImages().FindModules(module_spec, module_list))
+ {
+ if (module_list.GetSize() == 1)
+ {
+ module_sp = module_list.GetModuleAtIndex(0);
+ if (module_sp)
+ m_libpthread_module_wp = module_sp;
+ }
+ }
+ }
+ return module_sp;
+}
+
+Address
+DynamicLoaderMacOSXDYLD::GetPthreadSetSpecificAddress()
+{
+ if (!m_pthread_getspecific_addr.IsValid())
+ {
+ ModuleSP module_sp = GetPThreadLibraryModule();
+ if (module_sp)
+ {
+ lldb_private::SymbolContextList sc_list;
+ module_sp->FindSymbolsWithNameAndType(ConstString("pthread_getspecific"), eSymbolTypeCode, sc_list);
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(0, sc))
+ {
+ if (sc.symbol)
+ m_pthread_getspecific_addr = sc.symbol->GetAddress();
+ }
+ }
+ }
+ return m_pthread_getspecific_addr;
+}
+
+lldb::addr_t
+DynamicLoaderMacOSXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp, const lldb::ThreadSP thread_sp,
+ lldb::addr_t tls_file_addr)
+{
+ if (!thread_sp || !module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+
+ const uint32_t addr_size = m_process->GetAddressByteSize();
+ uint8_t buf[sizeof(lldb::addr_t) * 3];
+
+ lldb_private::Address tls_addr;
+ if (module_sp->ResolveFileAddress(tls_file_addr, tls_addr))
+ {
+ Error error;
+ const size_t tsl_data_size = addr_size * 3;
+ Target &target = m_process->GetTarget();
+ if (target.ReadMemory(tls_addr, false, buf, tsl_data_size, error) == tsl_data_size)
+ {
+ const ByteOrder byte_order = m_process->GetByteOrder();
+ DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
+ lldb::offset_t offset = addr_size; // Skip the first pointer
+ const lldb::addr_t pthread_key = data.GetAddress(&offset);
+ const lldb::addr_t tls_offset = data.GetAddress(&offset);
+ if (pthread_key != 0)
+ {
+ // First check to see if we have already figured out the location
+ // of TLS data for the pthread_key on a specific thread yet. If we
+ // have we can re-use it since its location will not change unless
+ // the process execs.
+ const tid_t tid = thread_sp->GetID();
+ auto tid_pos = m_tid_to_tls_map.find(tid);
+ if (tid_pos != m_tid_to_tls_map.end())
+ {
+ auto tls_pos = tid_pos->second.find(pthread_key);
+ if (tls_pos != tid_pos->second.end())
+ {
+ return tls_pos->second + tls_offset;
+ }
+ }
+ StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(0);
+ if (frame_sp)
+ {
+ ClangASTContext *clang_ast_context = target.GetScratchClangASTContext();
+
+ if (!clang_ast_context)
+ return LLDB_INVALID_ADDRESS;
+
+ CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ Address pthread_getspecific_addr = GetPthreadSetSpecificAddress();
+ if (pthread_getspecific_addr.IsValid())
+ {
+ EvaluateExpressionOptions options;
+
+ lldb::ThreadPlanSP thread_plan_sp(
+ new ThreadPlanCallFunction(*thread_sp, pthread_getspecific_addr, clang_void_ptr_type,
+ llvm::ArrayRef<lldb::addr_t>(pthread_key), options));
+
+ DiagnosticManager execution_errors;
+ ExecutionContext exe_ctx(thread_sp);
+ lldb::ExpressionResults results =
+ m_process->RunThreadPlan(exe_ctx, thread_plan_sp, options, execution_errors);
+
+ if (results == lldb::eExpressionCompleted)
+ {
+ lldb::ValueObjectSP result_valobj_sp = thread_plan_sp->GetReturnValueObject();
+ if (result_valobj_sp)
+ {
+ const lldb::addr_t pthread_key_data = result_valobj_sp->GetValueAsUnsigned(0);
+ if (pthread_key_data)
+ {
+ m_tid_to_tls_map[tid].insert(std::make_pair(pthread_key, pthread_key_data));
+ return pthread_key_data + tls_offset;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return LLDB_INVALID_ADDRESS;
+}
+
void
DynamicLoaderMacOSXDYLD::Initialize()
{
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
index a5bb85fbf66..ff709bdb147 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
@@ -12,6 +12,7 @@
// C Includes
// C++ Includes
+#include <map>
#include <mutex>
#include <vector>
@@ -76,6 +77,9 @@ public:
lldb_private::Error
CanLoadImage() override;
+ lldb::addr_t
+ GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread, lldb::addr_t tls_file_addr) override;
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -296,6 +300,8 @@ protected:
}
};
+ typedef std::map<uint64_t, lldb::addr_t> PthreadKeyToTLSMap;
+ typedef std::map<lldb::user_id_t, PthreadKeyToTLSMap> ThreadIDToTLSMap;
void
RegisterNotificationCallbacks();
@@ -365,11 +371,19 @@ protected:
uint32_t image_infos_count,
DYLDImageInfo::collection &image_infos);
+ lldb::ModuleSP
+ GetPThreadLibraryModule();
+
+ lldb_private::Address
+ GetPthreadSetSpecificAddress();
DYLDImageInfo m_dyld; // Info about the current dyld being used
lldb::ModuleWP m_dyld_module_wp;
+ lldb::ModuleWP m_libpthread_module_wp;
+ lldb_private::Address m_pthread_getspecific_addr;
lldb::addr_t m_dyld_all_image_infos_addr;
DYLDAllImageInfos m_dyld_all_image_infos;
+ ThreadIDToTLSMap m_tid_to_tls_map;
uint32_t m_dyld_all_image_infos_stop_id;
lldb::user_id_t m_break_id;
DYLDImageInfo::collection m_dyld_image_infos; // Current shared libraries information
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 90638f5452b..d6c347309fe 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -599,7 +599,8 @@ DynamicLoaderPOSIXDYLD::GetEntryPoint()
}
lldb::addr_t
-DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread)
+DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread,
+ lldb::addr_t tls_file_addr)
{
auto it = m_loaded_modules.find (module);
if (it == m_loaded_modules.end())
@@ -641,7 +642,7 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const l
"module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n",
mod->GetObjectName().AsCString(""), link_map, tp, (int64_t)modid, tls_block);
- return tls_block;
+ return tls_block + tls_file_addr;
}
void
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index cb97bbf43ba..890808c5179 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -61,7 +61,7 @@ public:
CanLoadImage() override;
lldb::addr_t
- GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override;
+ GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread, lldb::addr_t tls_file_addr) override;
//------------------------------------------------------------------
// PluginInterface protocol
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 07ce8c843dc..e0a5973f854 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -4414,6 +4414,7 @@ SymbolFileDWARF::ParseVariableDIE
GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetString().c_str());
}
}
+ SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (location_DW_OP_addr != LLDB_INVALID_ADDRESS)
{
@@ -4422,9 +4423,6 @@ SymbolFileDWARF::ParseVariableDIE
else
scope = eValueTypeVariableStatic;
-
- SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
-
if (debug_map_symfile)
{
// When leaving the DWARF in the .o files on darwin,
@@ -4502,7 +4500,22 @@ SymbolFileDWARF::ParseVariableDIE
if (location_is_const_value_data)
scope = eValueTypeVariableStatic;
else
+ {
scope = eValueTypeVariableLocal;
+ if (debug_map_symfile)
+ {
+ // We need to check for TLS addresses that we need to fixup
+ if (location.ContainsThreadLocalStorage())
+ {
+ location.LinkThreadLocalStorage(
+ debug_map_symfile->GetObjectFile()->GetModule(),
+ [this, debug_map_symfile](lldb::addr_t unlinked_file_addr) -> lldb::addr_t {
+ return debug_map_symfile->LinkOSOFileAddress(this, unlinked_file_addr);
+ });
+ scope = eValueTypeVariableThreadLocal;
+ }
+ }
+ }
}
}
diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp
index 4a0947571eb..1e55ce652e0 100644
--- a/lldb/source/Symbol/SymbolContext.cpp
+++ b/lldb/source/Symbol/SymbolContext.cpp
@@ -365,6 +365,10 @@ SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *t
s->PutCString("kind = local, ");
break;
+ case eValueTypeVariableThreadLocal:
+ s->PutCString("kind = thread local, ");
+ break;
+
default:
break;
}
diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp
index 7bac02d89f9..dd27b1b5d80 100644
--- a/lldb/source/Symbol/Variable.cpp
+++ b/lldb/source/Symbol/Variable.cpp
@@ -157,8 +157,13 @@ Variable::Dump(Stream *s, bool show_context) const
switch (m_scope)
{
case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break;
- case eValueTypeVariableArgument: s->PutCString("parameter"); break;
+ case eValueTypeVariableArgument:
+ s->PutCString("parameter");
+ break;
case eValueTypeVariableLocal: s->PutCString("local"); break;
+ case eValueTypeVariableThreadLocal:
+ s->PutCString("thread local");
+ break;
default: *s << "??? (" << m_scope << ')';
}
}
@@ -344,6 +349,7 @@ Variable::IsInScope (StackFrame *frame)
case eValueTypeConstResult:
case eValueTypeVariableGlobal:
case eValueTypeVariableStatic:
+ case eValueTypeVariableThreadLocal:
return true;
case eValueTypeVariableArgument:
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index a2905016842..40c137c4d52 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -2090,13 +2090,13 @@ Thread::GetThreadPointer ()
}
addr_t
-Thread::GetThreadLocalData (const ModuleSP module)
+Thread::GetThreadLocalData(const ModuleSP module, lldb::addr_t tls_file_addr)
{
// 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());
+ return loader->GetThreadLocalData(module, shared_from_this(), tls_file_addr);
else
return LLDB_INVALID_ADDRESS;
}
OpenPOWER on IntegriCloud