mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-26 13:26:22 +00:00
[lldb] [test/Register] Add read/write tests for multithreaded process
Add a test to verify that 'register read' and 'register write' commands work correctly in a multithreaded program, in particular that they read or write registers for the correct thread. The tests use locking to ensure that events are serialized and the test can execute reliably. Differential Revision: https://reviews.llvm.org/D89248
This commit is contained in:
parent
d95d3d2a42
commit
caedbc317a
61
lldb/test/Shell/Register/Inputs/x86-multithread-read.cpp
Normal file
61
lldb/test/Shell/Register/Inputs/x86-multithread-read.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
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<std::mutex> 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<std::mutex> m1_lock(t1_mutex);
|
||||
std::unique_lock<std::mutex> 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;
|
||||
}
|
66
lldb/test/Shell/Register/Inputs/x86-multithread-write.cpp
Normal file
66
lldb/test/Shell/Register/Inputs/x86-multithread-write.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
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<std::mutex> 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<std::mutex> m1_lock(t1_mutex);
|
||||
std::unique_lock<std::mutex> 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;
|
||||
}
|
23
lldb/test/Shell/Register/x86-multithread-read.test
Normal file
23
lldb/test/Shell/Register/x86-multithread-read.test
Normal file
@ -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
|
31
lldb/test/Shell/Register/x86-multithread-write.test
Normal file
31
lldb/test/Shell/Register/x86-multithread-write.test
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user