diff --git a/lldb/test/Shell/Register/Inputs/x86-multithread-read.cpp b/lldb/test/Shell/Register/Inputs/x86-multithread-read.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Register/Inputs/x86-multithread-read.cpp @@ -0,0 +1,61 @@ +#include +#include +#include + +std::mutex t1_mutex, t2_mutex; + +struct test_data { + uint32_t eax; + uint32_t ebx; + + struct alignas(16) { + uint64_t mantissa; + uint16_t sign_exp; + } st0; +}; + +void t_func(std::mutex &t_mutex, const test_data &t_data) { + std::lock_guard t_lock(t_mutex); + + asm volatile( + "finit\t\n" + "fldt %2\t\n" + "int3\n\t" + : + : "a"(t_data.eax), "b"(t_data.ebx), "m"(t_data.st0) + : "st" + ); +} + +int main() { + test_data t1_data = { + .eax = 0x05060708, + .ebx = 0x15161718, + .st0 = {0x8070605040302010, 0x4000}, + }; + test_data t2_data = { + .eax = 0x25262728, + .ebx = 0x35363738, + .st0 = {0x8171615141312111, 0xc000}, + }; + + // block both threads from proceeding + std::unique_lock m1_lock(t1_mutex); + std::unique_lock m2_lock(t2_mutex); + + // start both threads + std::thread t1(t_func, std::ref(t1_mutex), std::ref(t1_data)); + std::thread t2(t_func, std::ref(t2_mutex), std::ref(t2_data)); + + // release lock on thread 1 to make it interrupt the program + m1_lock.unlock(); + // wait for thread 1 to finish + t1.join(); + + // release lock on thread 2 + m2_lock.unlock(); + // wait for thread 2 to finish + t2.join(); + + return 0; +} diff --git a/lldb/test/Shell/Register/Inputs/x86-multithread-write.cpp b/lldb/test/Shell/Register/Inputs/x86-multithread-write.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Register/Inputs/x86-multithread-write.cpp @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include + +std::mutex t1_mutex, t2_mutex; + +struct test_data { + uint32_t eax; + uint32_t ebx; + + struct alignas(16) { + uint8_t data[10]; + } st0; +}; + +constexpr test_data filler = { + .eax = 0xffffffff, + .ebx = 0xffffffff, + .st0 = {{0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, 0x8f, 0x80, 0x40}}, +}; + +void t_func(std::mutex &t_mutex) { + std::lock_guard t_lock(t_mutex); + test_data out = filler; + + asm volatile( + "finit\t\n" + "fldt %2\t\n" + "int3\n\t" + "fstpt %2\t\n" + : "+a"(out.eax), "+b"(out.ebx) + : "m"(out.st0) + : "memory", "st" + ); + + printf("eax = 0x%08" PRIx32 "\n", out.eax); + printf("ebx = 0x%08" PRIx32 "\n", out.ebx); + printf("st0 = { "); + for (int i = 0; i < sizeof(out.st0.data); ++i) + printf("0x%02" PRIx8 " ", out.st0.data[i]); + printf("}\n"); +} + +int main() { + // block both threads from proceeding + std::unique_lock m1_lock(t1_mutex); + std::unique_lock m2_lock(t2_mutex); + + // start both threads + std::thread t1(t_func, std::ref(t1_mutex)); + std::thread t2(t_func, std::ref(t2_mutex)); + + // release lock on thread 1 to make it interrupt the program + m1_lock.unlock(); + // wait for thread 1 to finish + t1.join(); + + // release lock on thread 2 + m2_lock.unlock(); + // wait for thread 2 to finish + t2.join(); + + return 0; +} diff --git a/lldb/test/Shell/Register/x86-multithread-read.test b/lldb/test/Shell/Register/x86-multithread-read.test new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Register/x86-multithread-read.test @@ -0,0 +1,23 @@ +# XFAIL: system-windows +# REQUIRES: native && (target-x86 || target-x86_64) +# RUN: %clangxx_host %p/Inputs/x86-multithread-read.cpp -o %t -pthread +# RUN: %lldb -b -s %s %t | FileCheck %s + +process launch +# CHECK: Process {{[0-9]+}} stopped + +register read --all +# CHECK-DAG: eax = 0x05060708 +# CHECK-DAG: ebx = 0x15161718 +# CHECK-DAG: st{{(mm)?}}0 = {0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x00 0x40} + +process continue +# CHECK: Process {{[0-9]+}} stopped + +register read --all +# CHECK-DAG: eax = 0x25262728 +# CHECK-DAG: ebx = 0x35363738 +# CHECK-DAG: st{{(mm)?}}0 = {0x11 0x21 0x31 0x41 0x51 0x61 0x71 0x81 0x00 0xc0} + +process continue +# CHECK: Process {{[0-9]+}} exited with status = 0 diff --git a/lldb/test/Shell/Register/x86-multithread-write.test b/lldb/test/Shell/Register/x86-multithread-write.test new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Register/x86-multithread-write.test @@ -0,0 +1,31 @@ +# XFAIL: system-windows +# XFAIL: system-darwin +# REQUIRES: native && (target-x86 || target-x86_64) +# RUN: %clangxx_host %p/Inputs/x86-multithread-write.cpp -o %t -pthread +# RUN: %lldb -b -s %s %t | FileCheck %s + +process launch +# CHECK: Process {{[0-9]+}} stopped + +register write eax 0x05060708 +register write ebx 0x15161718 +# TODO: the need to call 'read' is probably a bug in the Linux plugin +register read st0 +register write st0 "{0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x00 0x40}" + +process continue +# CHECK-DAG: eax = 0x05060708 +# CHECK-DAG: ebx = 0x15161718 +# CHECK-DAG: st0 = { 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x00 0x40 } +# CHECK: Process {{[0-9]+}} stopped + +register write eax 0x25262728 +register write ebx 0x35363738 +register read st0 +register write st0 "{0x11 0x21 0x31 0x41 0x51 0x61 0x71 0x81 0x00 0xc0}" + +process continue +# CHECK-DAG: eax = 0x25262728 +# CHECK-DAG: ebx = 0x35363738 +# CHECK-DAG: st0 = { 0x11 0x21 0x31 0x41 0x51 0x61 0x71 0x81 0x00 0xc0 } +# CHECK: Process {{[0-9]+}} exited with status = 0