Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class DynamicLoaderHexagonDYLD : public lldb_private::DynamicLoader
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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...
Expand All @@ -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;
}


Expand Down Expand Up @@ -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()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

// C Includes
// C++ Includes
#include <map>
#include <mutex>
#include <vector>

Expand Down Expand Up @@ -76,6 +77,9 @@ class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader
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
//------------------------------------------------------------------
Expand Down Expand Up @@ -296,6 +300,8 @@ class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader
}
};

typedef std::map<uint64_t, lldb::addr_t> PthreadKeyToTLSMap;
typedef std::map<lldb::user_id_t, PthreadKeyToTLSMap> ThreadIDToTLSMap;
void
RegisterNotificationCallbacks();

Expand Down Expand Up @@ -365,11 +371,19 @@ class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader
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
Expand Down
19 changes: 16 additions & 3 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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,
Expand Down Expand Up @@ -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;
}
}
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Symbol/SymbolContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
8 changes: 7 additions & 1 deletion lldb/source/Symbol/Variable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 << ')';
}
}
Expand Down Expand Up @@ -344,6 +349,7 @@ Variable::IsInScope (StackFrame *frame)
case eValueTypeConstResult:
case eValueTypeVariableGlobal:
case eValueTypeVariableStatic:
case eValueTypeVariableThreadLocal:
return true;

case eValueTypeVariableArgument:
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Target/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down