[NFC][AArch64] Explicitly define undefined bits for instructions (#122129)
[llvm-project.git] / lldb / test / API / api / multiple-debuggers / multi-process-driver.cpp
blob64728fb7c29a1ede2002011a3793264eee6ae848
2 // This program creates NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS of pthreads,
3 // creates an lldb Debugger on each thread, creates targets, inserts two
4 // breakpoints, runs to the first breakpoint, backtraces, runs to the second
5 // breakpoint, backtraces, kills the inferior process, closes down the
6 // debugger.
8 // The main thread keeps track of which pthreads have completed and which
9 // pthreads have completed successfully, and exits when all pthreads have
10 // completed successfully, or our time limit has been exceeded.
12 // This test file helps to uncover race conditions and locking mistakes
13 // that are hit when lldb is being used to debug multiple processes
14 // simultaneously.
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <inttypes.h>
21 #include "lldb/API/LLDB.h"
22 #include "lldb/API/SBCommandInterpreter.h"
23 #include "lldb/API/SBCommandReturnObject.h"
24 #include "lldb/API/SBDebugger.h"
26 #include <chrono>
27 #include <csignal>
28 #include <thread>
30 #define NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS 10
32 #define DEBUG 0
34 #define STR1(x) #x
35 #define STR(x) STR1(x)
37 using namespace lldb;
39 bool *completed_threads_array = 0;
40 bool *successful_threads_array = 0;
42 const char *inferior_process_name = "testprog";
44 bool
45 wait_for_stop_event (SBProcess process, SBListener listener)
47 bool stopped = false;
48 while (!stopped)
50 SBEvent event;
51 bool waitfor_ret = listener.WaitForEvent (2, event);
52 if (event.GetType() == SBProcess::eBroadcastBitStateChanged)
54 if (process.GetState() == StateType::eStateStopped
55 || process.GetState() == StateType::eStateCrashed
56 || process.GetState() == StateType::eStateDetached
57 || process.GetState() == StateType::eStateExited)
59 stopped = true;
63 return stopped;
66 bool
67 walk_stack_to_main (SBThread thread)
69 if (thread.IsValid() == 0)
71 return false;
74 bool found_main = false;
75 uint32_t curr_frame = 0;
76 const uint32_t framecount = thread.GetNumFrames();
77 while (!found_main && curr_frame < framecount)
79 SBFrame frame = thread.GetFrameAtIndex (curr_frame);
80 if (strcmp (frame.GetFunctionName(), "main") == 0)
82 found_main = true;
83 break;
85 curr_frame += 1;
87 return found_main;
90 void *do_one_debugger (void *in)
92 uint64_t threadnum = (uint64_t) in;
94 #if defined (__APPLE__)
95 char *threadname;
96 asprintf (&threadname, "thread #%lld", threadnum);
97 pthread_setname_np (threadname);
98 free (threadname);
99 #endif
101 #if DEBUG == 1
102 printf ("#%lld: Starting debug session\n", threadnum);
103 #endif
105 SBDebugger debugger = lldb::SBDebugger::Create (false);
106 if (debugger.IsValid ())
108 debugger.SetAsync (true);
109 SBTarget target = debugger.CreateTargetWithFileAndArch(inferior_process_name,
110 STR(LLDB_HOST_ARCH));
111 SBCommandInterpreter command_interp = debugger.GetCommandInterpreter();
112 if (target.IsValid())
114 SBBreakpoint bar_br = target.BreakpointCreateByName ("bar", "testprog");
115 if (!bar_br.IsValid())
117 printf ("#%" PRIu64 ": failed to set breakpoint on bar, exiting.\n", threadnum);
118 exit (1);
120 SBBreakpoint foo_br = target.BreakpointCreateByName ("foo", "testprog");
121 if (!foo_br.IsValid())
123 printf ("#%" PRIu64 ": Failed to set breakpoint on foo()\n", threadnum);
126 SBLaunchInfo launch_info (NULL);
127 SBError error;
128 SBProcess process = target.Launch (launch_info, error);
129 if (process.IsValid())
131 SBListener listener = debugger.GetListener();
132 SBBroadcaster broadcaster = process.GetBroadcaster();
133 uint32_t rc = broadcaster.AddListener (listener, SBProcess::eBroadcastBitStateChanged);
134 if (rc == 0)
136 printf ("adding listener failed\n");
137 exit (1);
140 wait_for_stop_event (process, listener);
142 if (!walk_stack_to_main (process.GetThreadAtIndex(0)))
144 printf ("#%" PRIu64 ": backtrace while @ foo() failed\n", threadnum);
145 completed_threads_array[threadnum] = true;
146 return (void *) 1;
149 // On Linux the () are included.
150 const char* hit_fn = process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName();
151 if (strcmp (hit_fn, "foo") != 0 && strcmp (hit_fn, "foo()") != 0)
153 #if DEBUG == 1
154 printf ("#%" PRIu64 ": First breakpoint did not stop at foo(), instead stopped at '%s'\n", threadnum, process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName());
155 #endif
156 completed_threads_array[threadnum] = true;
157 return (void*) 1;
160 process.Continue();
162 wait_for_stop_event (process, listener);
164 if (process.GetState() == StateType::eStateExited)
166 printf ("#%" PRIu64 ": Process exited\n", threadnum);
167 completed_threads_array[threadnum] = true;
168 return (void *) 1;
172 if (!walk_stack_to_main (process.GetThreadAtIndex(0)))
174 printf ("#%" PRIu64 ": backtrace while @ bar() failed\n", threadnum);
175 completed_threads_array[threadnum] = true;
176 return (void *) 1;
179 hit_fn = process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName();
180 if (strcmp (hit_fn, "bar") != 0 && strcmp (hit_fn, "bar()") != 0)
182 printf ("#%" PRIu64 ": First breakpoint did not stop at bar()\n", threadnum);
183 completed_threads_array[threadnum] = true;
184 return (void*) 1;
187 process.Kill();
189 wait_for_stop_event (process, listener);
191 SBDebugger::Destroy(debugger);
193 #if DEBUG == 1
194 printf ("#%" PRIu64 ": All good!\n", threadnum);
195 #endif
196 successful_threads_array[threadnum] = true;
197 completed_threads_array[threadnum] = true;
198 return (void*) 0;
200 else
202 printf("#%" PRIu64 ": process failed to launch\n", threadnum);
203 successful_threads_array[threadnum] = false;
204 completed_threads_array[threadnum] = true;
205 return (void*) 0;
208 else
210 printf ("#%" PRIu64 ": did not get valid target\n", threadnum);
211 successful_threads_array[threadnum] = false;
212 completed_threads_array[threadnum] = true;
213 return (void*) 0;
216 else
218 printf ("#%" PRIu64 ": did not get debugger\n", threadnum);
219 successful_threads_array[threadnum] = false;
220 completed_threads_array[threadnum] = true;
221 return (void*) 0;
223 completed_threads_array[threadnum] = true;
224 return (void*) 1;
227 int count_completed_threads(int num_threads) {
228 int num_completed_threads = 0;
229 for (int i = 0; i < num_threads; i++)
230 if (completed_threads_array[i])
231 num_completed_threads++;
232 return num_completed_threads;
235 int count_successful_threads(int num_threads) {
236 int num_successful_threads = 0;
237 for (int i = 0; i < num_threads; i++)
238 if (successful_threads_array[i])
239 num_successful_threads++;
240 return num_successful_threads;
243 int main (int argc, char **argv)
245 #if !defined(_MSC_VER)
246 signal(SIGPIPE, SIG_IGN);
247 #endif
249 SBDebugger::Initialize();
251 completed_threads_array = (bool *) malloc (sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
252 memset (completed_threads_array, 0, sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
253 successful_threads_array = (bool *) malloc (sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
254 memset (successful_threads_array, 0, sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
256 if (argc > 1 && argv[1] != NULL)
258 inferior_process_name = argv[1];
261 std::thread threads[NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS];
262 for (uint64_t i = 0; i< NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS; i++)
264 threads[i] = std::move(std::thread(do_one_debugger, (void*)i));
268 int max_time_to_wait = 40; // 40 iterations, or 120 seconds
269 if (getenv("ASAN_OPTIONS"))
270 max_time_to_wait *= 4;
271 for (int iter = 0; iter < max_time_to_wait; iter++) {
272 std::this_thread::sleep_for(std::chrono::seconds(3));
273 int successful_threads = count_successful_threads(NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
274 int total_completed_threads = count_completed_threads(NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
276 if (total_completed_threads == NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS)
278 #if DEBUG == 1
279 printf ("All threads completed.\n");
280 printf ("%d threads completed successfully out of %d\n", successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
281 #endif
282 SBDebugger::Terminate();
283 exit(0);
285 else
287 #if DEBUG == 1
288 printf ("%d threads completed so far (%d successfully), out of %d\n", total_completed_threads, successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
289 #endif
291 if (iter == max_time_to_wait)
292 printf("reached maximum timeout but only %d threads have completed "
293 "so far "
294 "(%d successfully), out of %d. Exiting.\n",
295 total_completed_threads, successful_threads,
296 NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);
299 SBDebugger::Terminate();
300 exit (1);