diff options
Diffstat (limited to 'lldb/source')
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; } |