25 #if defined(__APPLE__)
26 #include <TargetConditionals.h>
29 static const char *const PRINT_PID_COMMAND
= "print-pid";
31 static bool g_print_thread_ids
= false;
32 static std::mutex g_print_mutex
;
33 static bool g_threads_do_segfault
= false;
35 static std::mutex g_jump_buffer_mutex
;
36 static jmp_buf g_jump_buffer
;
37 static bool g_is_segfaulting
= false;
39 static char g_message
[256];
41 static volatile char g_c1
= '0';
42 static volatile char g_c2
= '1';
44 static void print_pid() {
46 fprintf(stderr
, "PID: %d\n", ::GetCurrentProcessId());
48 fprintf(stderr
, "PID: %d\n", getpid());
52 static void signal_handler(int signo
) {
54 // No signal support on Windows.
56 const char *signal_name
= nullptr;
59 signal_name
= "SIGUSR1";
62 signal_name
= "SIGSEGV";
65 signal_name
= nullptr;
68 // Print notice that we received the signal on a given thread.
71 snprintf(buf
, sizeof(buf
), "received %s on thread id: %" PRIx64
"\n", signal_name
, get_thread_id());
73 snprintf(buf
, sizeof(buf
), "received signo %d (%s) on thread id: %" PRIx64
"\n", signo
, strsignal(signo
), get_thread_id());
74 write(STDOUT_FILENO
, buf
, strlen(buf
));
76 // Reset the signal handler if we're one of the expected signal handlers.
79 if (g_is_segfaulting
) {
80 // Fix up the pointer we're writing to. This needs to happen if nothing
81 // intercepts the SIGSEGV (i.e. if somebody runs this from the command
83 longjmp(g_jump_buffer
, 1);
87 if (g_is_segfaulting
) {
88 // Fix up the pointer we're writing to. This is used to test gdb remote
89 // signal delivery. A SIGSEGV will be raised when the thread is created,
90 // switched out for a SIGUSR1, and then this code still needs to fix the
91 // seg fault. (i.e. if somebody runs this from the command line).
92 longjmp(g_jump_buffer
, 1);
97 // Reset the signal handler.
98 sig_t sig_result
= signal(signo
, signal_handler
);
99 if (sig_result
== SIG_ERR
) {
100 fprintf(stderr
, "failed to set signal handler: errno=%d\n", errno
);
106 static void swap_chars() {
107 #if defined(__x86_64__) || defined(__i386__)
108 asm volatile("movb %1, (%2)\n\t"
113 : "i"('0'), "i"('1'), "r"(&g_c1
), "r"(&g_c2
)
115 #elif defined(__aarch64__)
116 asm volatile("strb %w1, [%2]\n\t"
121 : "r"('0'), "r"('1'), "r"(&g_c1
), "r"(&g_c2
)
123 #elif defined(__arm__)
124 asm volatile("strb %1, [%2]\n\t"
129 : "r"('0'), "r"('1'), "r"(&g_c1
), "r"(&g_c2
)
132 #warning This may generate unpredictible assembly and cause the single-stepping test to fail.
133 #warning Please add appropriate assembly for your target.
143 #if defined(__x86_64__) || defined(__i386__)
144 asm volatile("int3");
145 #elif defined(__aarch64__)
146 asm volatile("brk #0xf000");
147 #elif defined(__arm__)
148 asm volatile("udf #254");
149 #elif defined(__powerpc__)
150 asm volatile("trap");
151 #elif __has_builtin(__builtin_debugtrap())
152 __builtin_debugtrap();
154 #warning Don't know how to generate a trap. Some tests may fail.
158 static void hello() {
159 std::lock_guard<std::mutex> lock(g_print_mutex);
160 printf("hello, world\n");
163 static void *thread_func(std::promise<void> ready) {
165 static std::atomic<int> s_thread_index(1);
166 const int this_thread_index = s_thread_index++;
167 if (g_print_thread_ids) {
168 std::lock_guard<std::mutex> lock(g_print_mutex);
169 printf("thread %d id: %" PRIx64 "\n", this_thread_index, get_thread_id());
172 if (g_threads_do_segfault) {
173 // Sleep for a number of seconds based on the thread index.
174 // TODO add ability to send commands to test exe so we can
175 // handle timing more precisely. This is clunky. All we're
176 // trying to do is add predictability as to the timing of
177 // signal generation by created threads.
178 int sleep_seconds
= 2 * (this_thread_index
- 1);
179 std::this_thread::sleep_for(std::chrono::seconds(sleep_seconds
));
181 // Test creating a SEGV.
183 std::lock_guard
<std::mutex
> lock(g_jump_buffer_mutex
);
184 g_is_segfaulting
= true;
185 int *bad_p
= nullptr;
186 if (setjmp(g_jump_buffer
) == 0) {
187 // Force a seg fault signal on this thread.
190 // Tell the system we're no longer seg faulting.
191 // Used by the SIGUSR1 signal handler that we inject
192 // in place of the SIGSEGV so it only tries to
193 // recover from the SIGSEGV if this seg fault code
195 g_is_segfaulting
= false;
200 std::lock_guard
<std::mutex
> lock(g_print_mutex
);
201 printf("thread %" PRIx64
": past SIGSEGV\n", get_thread_id());
205 int sleep_seconds_remaining
= 60;
206 std::this_thread::sleep_for(std::chrono::seconds(sleep_seconds_remaining
));
211 static bool consume_front(std::string
&str
, const std::string
&front
) {
212 if (str
.find(front
) != 0)
215 str
= str
.substr(front
.size());
219 int main(int argc
, char **argv
) {
220 lldb_enable_attach();
222 std::vector
<std::thread
> threads
;
223 std::unique_ptr
<uint8_t[]> heap_array_up
;
224 int return_value
= 0;
227 bool is_child
= false;
229 // Set the signal handler.
230 sig_t sig_result
= signal(SIGALRM
, signal_handler
);
231 if (sig_result
== SIG_ERR
) {
232 fprintf(stderr
, "failed to set SIGALRM signal handler: errno=%d\n", errno
);
236 sig_result
= signal(SIGUSR1
, signal_handler
);
237 if (sig_result
== SIG_ERR
) {
238 fprintf(stderr
, "failed to set SIGUSR1 handler: errno=%d\n", errno
);
242 sig_result
= signal(SIGSEGV
, signal_handler
);
243 if (sig_result
== SIG_ERR
) {
244 fprintf(stderr
, "failed to set SIGSEGV handler: errno=%d\n", errno
);
248 sig_result
= signal(SIGCHLD
, SIG_IGN
);
249 if (sig_result
== SIG_ERR
) {
250 fprintf(stderr
, "failed to set SIGCHLD handler: errno=%d\n", errno
);
255 // Process command line args.
256 for (int i
= 1; i
< argc
; ++i
) {
257 std::string arg
= argv
[i
];
258 if (consume_front(arg
, "stderr:")) {
259 // Treat remainder as text to go to stderr.
260 fprintf(stderr
, "%s\n", arg
.c_str());
261 } else if (consume_front(arg
, "retval:")) {
262 // Treat as the return value for the program.
263 return_value
= std::atoi(arg
.c_str());
264 } else if (consume_front(arg
, "sleep:")) {
265 // Treat as the amount of time to have this process sleep (in seconds).
266 int sleep_seconds_remaining
= std::atoi(arg
.c_str());
268 // Loop around, sleeping until all sleep time is used up. Note that
269 // signals will cause sleep to end early with the number of seconds
271 std::this_thread::sleep_for(
272 std::chrono::seconds(sleep_seconds_remaining
));
274 } else if (consume_front(arg
, "set-message:")) {
275 // Copy the contents after "set-message:" to the g_message buffer.
276 // Used for reading inferior memory and verifying contents match
278 strncpy(g_message
, arg
.c_str(), sizeof(g_message
));
280 // Ensure we're null terminated.
281 g_message
[sizeof(g_message
) - 1] = '\0';
283 } else if (consume_front(arg
, "print-message:")) {
284 std::lock_guard
<std::mutex
> lock(g_print_mutex
);
285 printf("message: %s\n", g_message
);
286 } else if (consume_front(arg
, "get-data-address-hex:")) {
287 volatile void *data_p
= nullptr;
289 if (arg
== "g_message")
290 data_p
= &g_message
[0];
291 else if (arg
== "g_c1")
293 else if (arg
== "g_c2")
296 std::lock_guard
<std::mutex
> lock(g_print_mutex
);
297 printf("data address: %p\n", data_p
);
298 } else if (consume_front(arg
, "get-heap-address-hex:")) {
299 // Create a byte array if not already present.
301 heap_array_up
.reset(new uint8_t[32]);
303 std::lock_guard
<std::mutex
> lock(g_print_mutex
);
304 printf("heap address: %p\n", heap_array_up
.get());
306 } else if (consume_front(arg
, "get-stack-address-hex:")) {
307 std::lock_guard
<std::mutex
> lock(g_print_mutex
);
308 printf("stack address: %p\n", &return_value
);
309 } else if (consume_front(arg
, "get-code-address-hex:")) {
310 void (*func_p
)() = nullptr;
314 else if (arg
== "swap_chars")
317 std::lock_guard
<std::mutex
> lock(g_print_mutex
);
318 printf("code address: %p\n", func_p
);
319 } else if (consume_front(arg
, "call-function:")) {
320 void (*func_p
)() = nullptr;
324 else if (arg
== "swap_chars")
327 #if !defined(_WIN32) && !defined(TARGET_OS_WATCH) && !defined(TARGET_OS_TV)
328 } else if (arg
== "fork") {
329 pid_t fork_pid
= fork();
330 assert(fork_pid
!= -1);
331 is_child
= fork_pid
== 0;
332 } else if (arg
== "vfork") {
335 } else if (consume_front(arg
, "process:sync:")) {
336 // this is only valid after fork
337 const char *filenames
[] = {"parent", "child"};
338 std::string my_file
= arg
+ "." + filenames
[is_child
];
339 std::string other_file
= arg
+ "." + filenames
[!is_child
];
341 // indicate that we're ready
342 FILE *f
= fopen(my_file
.c_str(), "w");
346 // wait for the other process to be ready
347 for (int i
= 0; i
< 5; ++i
) {
348 f
= fopen(other_file
.c_str(), "r");
351 std::this_thread::sleep_for(std::chrono::milliseconds(125 * (1<<i
)));
356 } else if (consume_front(arg
, "thread:new")) {
357 std::promise
<void> promise
;
358 std::future
<void> ready
= promise
.get_future();
359 threads
.push_back(std::thread(thread_func
, std::move(promise
)));
361 } else if (consume_front(arg
, "thread:print-ids")) {
362 // Turn on thread id announcing.
363 g_print_thread_ids
= true;
367 std::lock_guard
<std::mutex
> lock(g_print_mutex
);
368 printf("thread 0 id: %" PRIx64
"\n", get_thread_id());
370 } else if (consume_front(arg
, "thread:segfault")) {
371 g_threads_do_segfault
= true;
372 } else if (consume_front(arg
, "print-pid")) {
374 } else if (consume_front(arg
, "print-env:")) {
375 // Print the value of specified envvar to stdout.
376 const char *value
= getenv(arg
.c_str());
377 printf("%s\n", value
? value
: "__unset__");
378 } else if (consume_front(arg
, "trap")) {
381 } else if (arg
== "stop") {
385 // Treat the argument as text for stdout.
386 printf("%s\n", argv
[i
]);
390 // If we launched any threads, join them
391 for (std::vector
<std::thread
>::iterator it
= threads
.begin();
392 it
!= threads
.end(); ++it
)