Skip to content

Skip failing test cases and threadlocalstorage fix #8020

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 94 additions & 64 deletions lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,74 +1076,104 @@ DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp,

std::lock_guard<std::recursive_mutex> guard(m_mutex);

lldb_private::Address tls_addr;
if (!module_sp->ResolveFileAddress(tls_file_addr, tls_addr))
return LLDB_INVALID_ADDRESS;

Target &target = m_process->GetTarget();
TypeSystemClangSP scratch_ts_sp =
ScratchTypeSystemClang::GetForTarget(target);
if (!scratch_ts_sp)
return LLDB_INVALID_ADDRESS;

CompilerType clang_void_ptr_type =
scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();

auto evaluate_tls_address = [this, &thread_sp, &clang_void_ptr_type](
Address func_ptr,
llvm::ArrayRef<addr_t> args) -> addr_t {
EvaluateExpressionOptions options;

lldb::ThreadPlanSP thread_plan_sp(new ThreadPlanCallFunction(
*thread_sp, func_ptr, clang_void_ptr_type, args, 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) {
if (lldb::ValueObjectSP result_valobj_sp =
thread_plan_sp->GetReturnValueObject()) {
return result_valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
}
}
return LLDB_INVALID_ADDRESS;
};

// On modern apple platforms, there is a small data structure that looks
// approximately like this:
// struct TLS_Thunk {
// void *(*get_addr)(struct TLS_Thunk *);
// size_t key;
// size_t offset;
// }
//
// The strategy is to take get_addr, call it with the address of the
// containing TLS_Thunk structure, and add the offset to the resulting
// pointer to get the data block.
//
// On older apple platforms, the key is treated as a pthread_key_t and passed
// to pthread_getspecific. The pointer returned from that call is added to
// offset to get the relevant data block.

const uint32_t addr_size = m_process->GetAddressByteSize();
uint8_t buf[sizeof(lldb::addr_t) * 3];
uint8_t buf[sizeof(addr_t) * 3];
Status error;
const size_t tls_data_size = addr_size * 3;
const size_t bytes_read = target.ReadMemory(
tls_addr, buf, tls_data_size, error, /*force_live_memory = */ true);
if (bytes_read != tls_data_size || error.Fail())
return LLDB_INVALID_ADDRESS;

lldb_private::Address tls_addr;
if (module_sp->ResolveFileAddress(tls_file_addr, tls_addr)) {
Status error;
const size_t tsl_data_size = addr_size * 3;
Target &target = m_process->GetTarget();
if (target.ReadMemory(tls_addr, buf, tsl_data_size, error, true) ==
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) {
TypeSystemClangSP scratch_ts_sp =
ScratchTypeSystemClang::GetForTarget(target);

if (!scratch_ts_sp)
return LLDB_INVALID_ADDRESS;

CompilerType clang_void_ptr_type =
scratch_ts_sp->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;
}
}
}
}
}
DataExtractor data(buf, sizeof(buf), m_process->GetByteOrder(), addr_size);
lldb::offset_t offset = 0;
const addr_t tls_thunk = data.GetAddress(&offset);
const addr_t key = data.GetAddress(&offset);
const addr_t tls_offset = data.GetAddress(&offset);

if (tls_thunk != 0) {
const addr_t fixed_tls_thunk = m_process->FixCodeAddress(tls_thunk);
Address thunk_load_addr;
if (target.ResolveLoadAddress(fixed_tls_thunk, thunk_load_addr)) {
const addr_t tls_load_addr = tls_addr.GetLoadAddress(&target);
const addr_t tls_data = evaluate_tls_address(
thunk_load_addr, llvm::ArrayRef<addr_t>(tls_load_addr));
if (tls_data != LLDB_INVALID_ADDRESS)
return tls_data + tls_offset;
}
}

if (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(key);
if (tls_pos != tid_pos->second.end()) {
return tls_pos->second + tls_offset;
}
}
Address pthread_getspecific_addr = GetPthreadSetSpecificAddress();
if (pthread_getspecific_addr.IsValid()) {
const addr_t tls_data = evaluate_tls_address(pthread_getspecific_addr,
llvm::ArrayRef<addr_t>(key));
if (tls_data != LLDB_INVALID_ADDRESS)
return tls_data + tls_offset;
}
}
return LLDB_INVALID_ADDRESS;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def setUp(self):
self.script_file = self.script_module + ".py"

@skipUnlessDarwin
@skipIfDarwin
def test_passthrough_launch(self):
"""Test a simple pass-through process launch"""
self.passthrough_launch()
Expand All @@ -43,6 +44,7 @@ def test_passthrough_launch(self):
self.assertState(lldb.SBProcess.GetStateFromEvent(event), lldb.eStateStopped)

@skipUnlessDarwin
@skipIfDarwin
def test_multiplexed_launch(self):
"""Test a multiple interactive scripted process debugging"""
self.passthrough_launch()
Expand Down
1 change: 1 addition & 0 deletions lldb/test/API/lang/c/tls_globals/TestTlsGlobals.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def setUp(self):
bugnumber="llvm.org/pr28392",
oslist=no_match(lldbplatformutil.getDarwinOSTriples()),
)
@expectedFailureDarwin("rdar://120676969")
def test(self):
"""Test thread-local storage."""
self.build()
Expand Down
1 change: 1 addition & 0 deletions lldb/test/API/lang/cpp/thread_local/TestThreadLocal.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

class PlatformProcessCrashInfoTestCase(TestBase):
@expectedFailureAll(oslist=["windows", "linux", "freebsd", "netbsd"])
@skipIfDarwin # rdar://120795095
def test_thread_local(self):
# Set a breakpoint on the first instruction of the main function,
# before the TLS initialization has run.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def setUp(self):

@skipUnlessDarwin
@add_test_categories(["pyapi"])
@expectedFailureDarwin("rdar://120796553")
def test_with_python_api(self):
"""Test stepping and setting breakpoints in indirect and re-exported symbols."""
self.build()
Expand Down
2 changes: 2 additions & 0 deletions lldb/test/Shell/Unwind/eh-frame-dwarf-unwind.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

# UNSUPPORTED: system-windows
# REQUIRES: target-x86_64, native
# XFAIL: system-darwin
# See: rdar://120797300

# RUN: %clang_host %p/Inputs/call-asm.c %p/Inputs/eh-frame-dwarf-unwind.s -o %t
# RUN: %lldb %t -s %s -o exit | FileCheck %s
Expand Down
2 changes: 2 additions & 0 deletions lldb/test/Shell/Unwind/thread-step-out-ret-addr-check.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

# REQUIRES: target-x86_64
# UNSUPPORTED: system-windows
# XFAIL: system-darwin
# See: rdar://120797300

# RUN: %clang_host %p/Inputs/call-asm.c -x assembler-with-cpp %p/Inputs/thread-step-out-ret-addr-check.s -o %t
# RUN: not %lldb %t -s %s -b 2>&1 | FileCheck %s
Expand Down