File: | tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp |
Location: | line 2427, column 17 |
Description: | Called C++ object pointer is null |
1 | //===-- NativeProcessLinux.cpp -------------------------------- -*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | ||||
10 | #include "lldb/lldb-python.h" | |||
11 | ||||
12 | #include "NativeProcessLinux.h" | |||
13 | ||||
14 | // C Includes | |||
15 | #include <errno(*__errno_location ()).h> | |||
16 | #include <poll.h> | |||
17 | #include <string.h> | |||
18 | #include <stdint.h> | |||
19 | #include <unistd.h> | |||
20 | #include <linux/unistd.h> | |||
21 | #if defined(__ANDROID_NDK__) && defined (__arm__) | |||
22 | #include <linux/personality.h> | |||
23 | #include <linux/user.h> | |||
24 | #else | |||
25 | #include <sys/personality.h> | |||
26 | #include <sys/user.h> | |||
27 | #endif | |||
28 | #ifndef __ANDROID__ | |||
29 | #include <sys/procfs.h> | |||
30 | #endif | |||
31 | #include <sys/ptrace.h> | |||
32 | #include <sys/uio.h> | |||
33 | #include <sys/socket.h> | |||
34 | #include <sys/syscall.h> | |||
35 | #include <sys/types.h> | |||
36 | #include <sys/wait.h> | |||
37 | ||||
38 | #if defined (__arm64__) || defined (__aarch64__) | |||
39 | // NT_PRSTATUS and NT_FPREGSET definition | |||
40 | #include <elf.h> | |||
41 | #endif | |||
42 | ||||
43 | // C++ Includes | |||
44 | #include <fstream> | |||
45 | #include <string> | |||
46 | ||||
47 | // Other libraries and framework includes | |||
48 | #include "lldb/Core/Debugger.h" | |||
49 | #include "lldb/Core/Error.h" | |||
50 | #include "lldb/Core/Module.h" | |||
51 | #include "lldb/Core/ModuleSpec.h" | |||
52 | #include "lldb/Core/RegisterValue.h" | |||
53 | #include "lldb/Core/Scalar.h" | |||
54 | #include "lldb/Core/State.h" | |||
55 | #include "lldb/Host/Host.h" | |||
56 | #include "lldb/Host/HostInfo.h" | |||
57 | #include "lldb/Host/ThreadLauncher.h" | |||
58 | #include "lldb/Symbol/ObjectFile.h" | |||
59 | #include "lldb/Target/NativeRegisterContext.h" | |||
60 | #include "lldb/Target/ProcessLaunchInfo.h" | |||
61 | #include "lldb/Utility/PseudoTerminal.h" | |||
62 | ||||
63 | #include "Host/common/NativeBreakpoint.h" | |||
64 | #include "Utility/StringExtractor.h" | |||
65 | ||||
66 | #include "Plugins/Process/Utility/LinuxSignals.h" | |||
67 | #include "NativeThreadLinux.h" | |||
68 | #include "ProcFileReader.h" | |||
69 | #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" | |||
70 | ||||
71 | #ifdef __ANDROID__ | |||
72 | #define __ptrace_request int | |||
73 | #define PT_DETACHPTRACE_DETACH PTRACE_DETACH | |||
74 | #endif | |||
75 | ||||
76 | #define DEBUG_PTRACE_MAXBYTES20 20 | |||
77 | ||||
78 | // Support ptrace extensions even when compiled without required kernel support | |||
79 | #ifndef PT_GETREGSPTRACE_GETREGS | |||
80 | #ifndef PTRACE_GETREGS | |||
81 | #define PTRACE_GETREGS 12 | |||
82 | #endif | |||
83 | #endif | |||
84 | #ifndef PT_SETREGSPTRACE_SETREGS | |||
85 | #ifndef PTRACE_SETREGS | |||
86 | #define PTRACE_SETREGS 13 | |||
87 | #endif | |||
88 | #endif | |||
89 | #ifndef PT_GETFPREGSPTRACE_GETFPREGS | |||
90 | #ifndef PTRACE_GETFPREGS | |||
91 | #define PTRACE_GETFPREGS 14 | |||
92 | #endif | |||
93 | #endif | |||
94 | #ifndef PT_SETFPREGSPTRACE_SETFPREGS | |||
95 | #ifndef PTRACE_SETFPREGS | |||
96 | #define PTRACE_SETFPREGS 15 | |||
97 | #endif | |||
98 | #endif | |||
99 | #ifndef PTRACE_GETREGSETPTRACE_GETREGSET | |||
100 | #define PTRACE_GETREGSETPTRACE_GETREGSET 0x4204 | |||
101 | #endif | |||
102 | #ifndef PTRACE_SETREGSETPTRACE_SETREGSET | |||
103 | #define PTRACE_SETREGSETPTRACE_SETREGSET 0x4205 | |||
104 | #endif | |||
105 | #ifndef PTRACE_GET_THREAD_AREA25 | |||
106 | #define PTRACE_GET_THREAD_AREA25 25 | |||
107 | #endif | |||
108 | #ifndef PTRACE_ARCH_PRCTL30 | |||
109 | #define PTRACE_ARCH_PRCTL30 30 | |||
110 | #endif | |||
111 | #ifndef ARCH_GET_FS0x1003 | |||
112 | #define ARCH_SET_GS0x1001 0x1001 | |||
113 | #define ARCH_SET_FS0x1002 0x1002 | |||
114 | #define ARCH_GET_FS0x1003 0x1003 | |||
115 | #define ARCH_GET_GS0x1004 0x1004 | |||
116 | #endif | |||
117 | ||||
118 | #define LLDB_PERSONALITY_GET_CURRENT_SETTINGS0xffffffff 0xffffffff | |||
119 | ||||
120 | // Support hardware breakpoints in case it has not been defined | |||
121 | #ifndef TRAP_HWBKPT4 | |||
122 | #define TRAP_HWBKPT4 4 | |||
123 | #endif | |||
124 | ||||
125 | // Try to define a macro to encapsulate the tgkill syscall | |||
126 | // fall back on kill() if tgkill isn't available | |||
127 | #define tgkill(pid, tid, sig)syscall(234, pid, tid, sig) syscall(SYS_tgkill234, pid, tid, sig) | |||
128 | ||||
129 | // We disable the tracing of ptrace calls for integration builds to | |||
130 | // avoid the additional indirection and checks. | |||
131 | #ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION | |||
132 | #define PTRACE(req, pid, addr, data, data_size)PtraceWrapper((req), (pid), (addr), (data), (data_size), "req" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 132) \ | |||
133 | PtraceWrapper((req), (pid), (addr), (data), (data_size), #req, __FILE__"/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp", __LINE__133) | |||
134 | #else | |||
135 | #define PTRACE(req, pid, addr, data, data_size)PtraceWrapper((req), (pid), (addr), (data), (data_size), "req" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 135) \ | |||
136 | PtraceWrapper((req), (pid), (addr), (data), (data_size)) | |||
137 | #endif | |||
138 | ||||
139 | // Private bits we only need internally. | |||
140 | namespace | |||
141 | { | |||
142 | using namespace lldb; | |||
143 | using namespace lldb_private; | |||
144 | ||||
145 | const UnixSignals& | |||
146 | GetUnixSignals () | |||
147 | { | |||
148 | static process_linux::LinuxSignals signals; | |||
149 | return signals; | |||
150 | } | |||
151 | ||||
152 | Error | |||
153 | ResolveProcessArchitecture (lldb::pid_t pid, Platform &platform, ArchSpec &arch) | |||
154 | { | |||
155 | // Grab process info for the running process. | |||
156 | ProcessInstanceInfo process_info; | |||
157 | if (!platform.GetProcessInfo (pid, process_info)) | |||
158 | return lldb_private::Error("failed to get process info"); | |||
159 | ||||
160 | // Resolve the executable module. | |||
161 | ModuleSP exe_module_sp; | |||
162 | ModuleSpec exe_module_spec(process_info.GetExecutableFile(), platform.GetSystemArchitecture ()); | |||
163 | FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths ()); | |||
164 | Error error = platform.ResolveExecutable( | |||
165 | exe_module_spec, | |||
166 | exe_module_sp, | |||
167 | executable_search_paths.GetSize () ? &executable_search_paths : NULL__null); | |||
168 | ||||
169 | if (!error.Success ()) | |||
170 | return error; | |||
171 | ||||
172 | // Check if we've got our architecture from the exe_module. | |||
173 | arch = exe_module_sp->GetArchitecture (); | |||
174 | if (arch.IsValid ()) | |||
175 | return Error(); | |||
176 | else | |||
177 | return Error("failed to retrieve a valid architecture from the exe module"); | |||
178 | } | |||
179 | ||||
180 | void | |||
181 | DisplayBytes (lldb_private::StreamString &s, void *bytes, uint32_t count) | |||
182 | { | |||
183 | uint8_t *ptr = (uint8_t *)bytes; | |||
184 | const uint32_t loop_count = std::min<uint32_t>(DEBUG_PTRACE_MAXBYTES20, count); | |||
185 | for(uint32_t i=0; i<loop_count; i++) | |||
186 | { | |||
187 | s.Printf ("[%x]", *ptr); | |||
188 | ptr++; | |||
189 | } | |||
190 | } | |||
191 | ||||
192 | void | |||
193 | PtraceDisplayBytes(int &req, void *data, size_t data_size) | |||
194 | { | |||
195 | StreamString buf; | |||
196 | Log *verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet ( | |||
197 | POSIX_LOG_PTRACE(1u << 12) | POSIX_LOG_VERBOSE(1u << 0))); | |||
198 | ||||
199 | if (verbose_log) | |||
200 | { | |||
201 | switch(req) | |||
202 | { | |||
203 | case PTRACE_POKETEXT: | |||
204 | { | |||
205 | DisplayBytes(buf, &data, 8); | |||
206 | verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData()); | |||
207 | break; | |||
208 | } | |||
209 | case PTRACE_POKEDATA: | |||
210 | { | |||
211 | DisplayBytes(buf, &data, 8); | |||
212 | verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData()); | |||
213 | break; | |||
214 | } | |||
215 | case PTRACE_POKEUSER: | |||
216 | { | |||
217 | DisplayBytes(buf, &data, 8); | |||
218 | verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData()); | |||
219 | break; | |||
220 | } | |||
221 | case PTRACE_SETREGS: | |||
222 | { | |||
223 | DisplayBytes(buf, data, data_size); | |||
224 | verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData()); | |||
225 | break; | |||
226 | } | |||
227 | case PTRACE_SETFPREGS: | |||
228 | { | |||
229 | DisplayBytes(buf, data, data_size); | |||
230 | verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData()); | |||
231 | break; | |||
232 | } | |||
233 | case PTRACE_SETSIGINFO: | |||
234 | { | |||
235 | DisplayBytes(buf, data, sizeof(siginfo_t)); | |||
236 | verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData()); | |||
237 | break; | |||
238 | } | |||
239 | case PTRACE_SETREGSETPTRACE_SETREGSET: | |||
240 | { | |||
241 | // Extract iov_base from data, which is a pointer to the struct IOVEC | |||
242 | DisplayBytes(buf, *(void **)data, data_size); | |||
243 | verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData()); | |||
244 | break; | |||
245 | } | |||
246 | default: | |||
247 | { | |||
248 | } | |||
249 | } | |||
250 | } | |||
251 | } | |||
252 | ||||
253 | // Wrapper for ptrace to catch errors and log calls. | |||
254 | // Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) | |||
255 | long | |||
256 | PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, | |||
257 | const char* reqName, const char* file, int line) | |||
258 | { | |||
259 | long int result; | |||
260 | ||||
261 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE(1u << 12))); | |||
262 | ||||
263 | PtraceDisplayBytes(req, data, data_size); | |||
264 | ||||
265 | errno(*__errno_location ()) = 0; | |||
266 | if (req == PTRACE_GETREGSETPTRACE_GETREGSET || req == PTRACE_SETREGSETPTRACE_SETREGSET) | |||
267 | result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); | |||
268 | else | |||
269 | result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); | |||
270 | ||||
271 | if (log) | |||
272 | log->Printf("ptrace(%s, %" PRIu64"l" "u" ", %p, %p, %zu)=%lX called from file %s line %d", | |||
273 | reqName, pid, addr, data, data_size, result, file, line); | |||
274 | ||||
275 | PtraceDisplayBytes(req, data, data_size); | |||
276 | ||||
277 | if (log && errno(*__errno_location ()) != 0) | |||
278 | { | |||
279 | const char* str; | |||
280 | switch (errno(*__errno_location ())) | |||
281 | { | |||
282 | case ESRCH3: str = "ESRCH"; break; | |||
283 | case EINVAL22: str = "EINVAL"; break; | |||
284 | case EBUSY16: str = "EBUSY"; break; | |||
285 | case EPERM1: str = "EPERM"; break; | |||
286 | default: str = "<unknown>"; | |||
287 | } | |||
288 | log->Printf("ptrace() failed; errno=%d (%s)", errno(*__errno_location ()), str); | |||
289 | } | |||
290 | ||||
291 | return result; | |||
292 | } | |||
293 | ||||
294 | #ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION | |||
295 | // Wrapper for ptrace when logging is not required. | |||
296 | // Sets errno to 0 prior to calling ptrace. | |||
297 | long | |||
298 | PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size) | |||
299 | { | |||
300 | long result = 0; | |||
301 | errno(*__errno_location ()) = 0; | |||
302 | if (req == PTRACE_GETREGSETPTRACE_GETREGSET || req == PTRACE_SETREGSETPTRACE_SETREGSET) | |||
303 | result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); | |||
304 | else | |||
305 | result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); | |||
306 | return result; | |||
307 | } | |||
308 | #endif | |||
309 | ||||
310 | //------------------------------------------------------------------------------ | |||
311 | // Static implementations of NativeProcessLinux::ReadMemory and | |||
312 | // NativeProcessLinux::WriteMemory. This enables mutual recursion between these | |||
313 | // functions without needed to go thru the thread funnel. | |||
314 | ||||
315 | static lldb::addr_t | |||
316 | DoReadMemory ( | |||
317 | lldb::pid_t pid, | |||
318 | lldb::addr_t vm_addr, | |||
319 | void *buf, | |||
320 | lldb::addr_t size, | |||
321 | Error &error) | |||
322 | { | |||
323 | // ptrace word size is determined by the host, not the child | |||
324 | static const unsigned word_size = sizeof(void*); | |||
325 | unsigned char *dst = static_cast<unsigned char*>(buf); | |||
326 | lldb::addr_t bytes_read; | |||
327 | lldb::addr_t remainder; | |||
328 | long data; | |||
329 | ||||
330 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL((4294967295U)))); | |||
331 | if (log) | |||
332 | ProcessPOSIXLog::IncNestLevel(); | |||
333 | if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY(1u << 4))) | |||
334 | log->Printf ("NativeProcessLinux::%s(%" PRIu64"l" "u" ", %d, %p, %p, %zd, _)", __FUNCTION__, | |||
335 | pid, word_size, (void*)vm_addr, buf, size); | |||
336 | ||||
337 | assert(sizeof(data) >= word_size)((sizeof(data) >= word_size) ? static_cast<void> (0) : __assert_fail ("sizeof(data) >= word_size", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 337, __PRETTY_FUNCTION__)); | |||
338 | for (bytes_read = 0; bytes_read < size; bytes_read += remainder) | |||
339 | { | |||
340 | errno(*__errno_location ()) = 0; | |||
341 | data = PTRACE(PTRACE_PEEKDATA, pid, (void*)vm_addr, NULL, 0)PtraceWrapper((PTRACE_PEEKDATA), (pid), ((void*)vm_addr), (__null ), (0), "PTRACE_PEEKDATA", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 341); | |||
342 | if (errno(*__errno_location ())) | |||
343 | { | |||
344 | error.SetErrorToErrno(); | |||
345 | if (log) | |||
346 | ProcessPOSIXLog::DecNestLevel(); | |||
347 | return bytes_read; | |||
348 | } | |||
349 | ||||
350 | remainder = size - bytes_read; | |||
351 | remainder = remainder > word_size ? word_size : remainder; | |||
352 | ||||
353 | // Copy the data into our buffer | |||
354 | for (unsigned i = 0; i < remainder; ++i) | |||
355 | dst[i] = ((data >> i*8) & 0xFF); | |||
356 | ||||
357 | if (log && ProcessPOSIXLog::AtTopNestLevel() && | |||
358 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG(1u << 6)) || | |||
359 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT(1u << 5)) && | |||
360 | size <= POSIX_LOG_MEMORY_SHORT_BYTES(4 * sizeof(ptrdiff_t))))) | |||
361 | { | |||
362 | uintptr_t print_dst = 0; | |||
363 | // Format bytes from data by moving into print_dst for log output | |||
364 | for (unsigned i = 0; i < remainder; ++i) | |||
365 | print_dst |= (((data >> i*8) & 0xFF) << i*8); | |||
366 | log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, | |||
367 | (void*)vm_addr, print_dst, (unsigned long)data); | |||
368 | } | |||
369 | ||||
370 | vm_addr += word_size; | |||
371 | dst += word_size; | |||
372 | } | |||
373 | ||||
374 | if (log) | |||
375 | ProcessPOSIXLog::DecNestLevel(); | |||
376 | return bytes_read; | |||
377 | } | |||
378 | ||||
379 | static lldb::addr_t | |||
380 | DoWriteMemory( | |||
381 | lldb::pid_t pid, | |||
382 | lldb::addr_t vm_addr, | |||
383 | const void *buf, | |||
384 | lldb::addr_t size, | |||
385 | Error &error) | |||
386 | { | |||
387 | // ptrace word size is determined by the host, not the child | |||
388 | static const unsigned word_size = sizeof(void*); | |||
389 | const unsigned char *src = static_cast<const unsigned char*>(buf); | |||
390 | lldb::addr_t bytes_written = 0; | |||
391 | lldb::addr_t remainder; | |||
392 | ||||
393 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL((4294967295U)))); | |||
394 | if (log) | |||
395 | ProcessPOSIXLog::IncNestLevel(); | |||
396 | if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY(1u << 4))) | |||
397 | log->Printf ("NativeProcessLinux::%s(%" PRIu64"l" "u" ", %u, %p, %p, %" PRIu64"l" "u" ")", __FUNCTION__, | |||
398 | pid, word_size, (void*)vm_addr, buf, size); | |||
399 | ||||
400 | for (bytes_written = 0; bytes_written < size; bytes_written += remainder) | |||
401 | { | |||
402 | remainder = size - bytes_written; | |||
403 | remainder = remainder > word_size ? word_size : remainder; | |||
404 | ||||
405 | if (remainder == word_size) | |||
406 | { | |||
407 | unsigned long data = 0; | |||
408 | assert(sizeof(data) >= word_size)((sizeof(data) >= word_size) ? static_cast<void> (0) : __assert_fail ("sizeof(data) >= word_size", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 408, __PRETTY_FUNCTION__)); | |||
409 | for (unsigned i = 0; i < word_size; ++i) | |||
410 | data |= (unsigned long)src[i] << i*8; | |||
411 | ||||
412 | if (log && ProcessPOSIXLog::AtTopNestLevel() && | |||
413 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG(1u << 6)) || | |||
414 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT(1u << 5)) && | |||
415 | size <= POSIX_LOG_MEMORY_SHORT_BYTES(4 * sizeof(ptrdiff_t))))) | |||
416 | log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, | |||
417 | (void*)vm_addr, *(unsigned long*)src, data); | |||
418 | ||||
419 | if (PTRACE(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data, 0)PtraceWrapper((PTRACE_POKEDATA), (pid), ((void*)vm_addr), ((void *)data), (0), "PTRACE_POKEDATA", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 419)) | |||
420 | { | |||
421 | error.SetErrorToErrno(); | |||
422 | if (log) | |||
423 | ProcessPOSIXLog::DecNestLevel(); | |||
424 | return bytes_written; | |||
425 | } | |||
426 | } | |||
427 | else | |||
428 | { | |||
429 | unsigned char buff[8]; | |||
430 | if (DoReadMemory(pid, vm_addr, | |||
431 | buff, word_size, error) != word_size) | |||
432 | { | |||
433 | if (log) | |||
434 | ProcessPOSIXLog::DecNestLevel(); | |||
435 | return bytes_written; | |||
436 | } | |||
437 | ||||
438 | memcpy(buff, src, remainder); | |||
439 | ||||
440 | if (DoWriteMemory(pid, vm_addr, | |||
441 | buff, word_size, error) != word_size) | |||
442 | { | |||
443 | if (log) | |||
444 | ProcessPOSIXLog::DecNestLevel(); | |||
445 | return bytes_written; | |||
446 | } | |||
447 | ||||
448 | if (log && ProcessPOSIXLog::AtTopNestLevel() && | |||
449 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG(1u << 6)) || | |||
450 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT(1u << 5)) && | |||
451 | size <= POSIX_LOG_MEMORY_SHORT_BYTES(4 * sizeof(ptrdiff_t))))) | |||
452 | log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, | |||
453 | (void*)vm_addr, *(unsigned long*)src, *(unsigned long*)buff); | |||
454 | } | |||
455 | ||||
456 | vm_addr += word_size; | |||
457 | src += word_size; | |||
458 | } | |||
459 | if (log) | |||
460 | ProcessPOSIXLog::DecNestLevel(); | |||
461 | return bytes_written; | |||
462 | } | |||
463 | ||||
464 | //------------------------------------------------------------------------------ | |||
465 | /// @class Operation | |||
466 | /// @brief Represents a NativeProcessLinux operation. | |||
467 | /// | |||
468 | /// Under Linux, it is not possible to ptrace() from any other thread but the | |||
469 | /// one that spawned or attached to the process from the start. Therefore, when | |||
470 | /// a NativeProcessLinux is asked to deliver or change the state of an inferior | |||
471 | /// process the operation must be "funneled" to a specific thread to perform the | |||
472 | /// task. The Operation class provides an abstract base for all services the | |||
473 | /// NativeProcessLinux must perform via the single virtual function Execute, thus | |||
474 | /// encapsulating the code that needs to run in the privileged context. | |||
475 | class Operation | |||
476 | { | |||
477 | public: | |||
478 | Operation () : m_error() { } | |||
479 | ||||
480 | virtual | |||
481 | ~Operation() {} | |||
482 | ||||
483 | virtual void | |||
484 | Execute (NativeProcessLinux *process) = 0; | |||
485 | ||||
486 | const Error & | |||
487 | GetError () const { return m_error; } | |||
488 | ||||
489 | protected: | |||
490 | Error m_error; | |||
491 | }; | |||
492 | ||||
493 | //------------------------------------------------------------------------------ | |||
494 | /// @class ReadOperation | |||
495 | /// @brief Implements NativeProcessLinux::ReadMemory. | |||
496 | class ReadOperation : public Operation | |||
497 | { | |||
498 | public: | |||
499 | ReadOperation ( | |||
500 | lldb::addr_t addr, | |||
501 | void *buff, | |||
502 | lldb::addr_t size, | |||
503 | lldb::addr_t &result) : | |||
504 | Operation (), | |||
505 | m_addr (addr), | |||
506 | m_buff (buff), | |||
507 | m_size (size), | |||
508 | m_result (result) | |||
509 | { | |||
510 | } | |||
511 | ||||
512 | void Execute (NativeProcessLinux *process) override; | |||
513 | ||||
514 | private: | |||
515 | lldb::addr_t m_addr; | |||
516 | void *m_buff; | |||
517 | lldb::addr_t m_size; | |||
518 | lldb::addr_t &m_result; | |||
519 | }; | |||
520 | ||||
521 | void | |||
522 | ReadOperation::Execute (NativeProcessLinux *process) | |||
523 | { | |||
524 | m_result = DoReadMemory (process->GetID (), m_addr, m_buff, m_size, m_error); | |||
525 | } | |||
526 | ||||
527 | //------------------------------------------------------------------------------ | |||
528 | /// @class WriteOperation | |||
529 | /// @brief Implements NativeProcessLinux::WriteMemory. | |||
530 | class WriteOperation : public Operation | |||
531 | { | |||
532 | public: | |||
533 | WriteOperation ( | |||
534 | lldb::addr_t addr, | |||
535 | const void *buff, | |||
536 | lldb::addr_t size, | |||
537 | lldb::addr_t &result) : | |||
538 | Operation (), | |||
539 | m_addr (addr), | |||
540 | m_buff (buff), | |||
541 | m_size (size), | |||
542 | m_result (result) | |||
543 | { | |||
544 | } | |||
545 | ||||
546 | void Execute (NativeProcessLinux *process) override; | |||
547 | ||||
548 | private: | |||
549 | lldb::addr_t m_addr; | |||
550 | const void *m_buff; | |||
551 | lldb::addr_t m_size; | |||
552 | lldb::addr_t &m_result; | |||
553 | }; | |||
554 | ||||
555 | void | |||
556 | WriteOperation::Execute(NativeProcessLinux *process) | |||
557 | { | |||
558 | m_result = DoWriteMemory (process->GetID (), m_addr, m_buff, m_size, m_error); | |||
559 | } | |||
560 | ||||
561 | //------------------------------------------------------------------------------ | |||
562 | /// @class ReadRegOperation | |||
563 | /// @brief Implements NativeProcessLinux::ReadRegisterValue. | |||
564 | class ReadRegOperation : public Operation | |||
565 | { | |||
566 | public: | |||
567 | ReadRegOperation(lldb::tid_t tid, uint32_t offset, const char *reg_name, | |||
568 | RegisterValue &value, bool &result) | |||
569 | : m_tid(tid), m_offset(static_cast<uintptr_t> (offset)), m_reg_name(reg_name), | |||
570 | m_value(value), m_result(result) | |||
571 | { } | |||
572 | ||||
573 | void Execute(NativeProcessLinux *monitor); | |||
574 | ||||
575 | private: | |||
576 | lldb::tid_t m_tid; | |||
577 | uintptr_t m_offset; | |||
578 | const char *m_reg_name; | |||
579 | RegisterValue &m_value; | |||
580 | bool &m_result; | |||
581 | }; | |||
582 | ||||
583 | void | |||
584 | ReadRegOperation::Execute(NativeProcessLinux *monitor) | |||
585 | { | |||
586 | #if defined (__arm64__) || defined (__aarch64__) | |||
587 | if (m_offset > sizeof(struct user_pt_regs)) | |||
588 | { | |||
589 | uintptr_t offset = m_offset - sizeof(struct user_pt_regs); | |||
590 | if (offset > sizeof(struct user_fpsimd_state)) | |||
591 | { | |||
592 | m_result = false; | |||
593 | } | |||
594 | else | |||
595 | { | |||
596 | elf_fpregset_t regs; | |||
597 | int regset = NT_FPREGSET; | |||
598 | struct iovec ioVec; | |||
599 | ||||
600 | ioVec.iov_base = ®s; | |||
601 | ioVec.iov_len = sizeof regs; | |||
602 | if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs)PtraceWrapper((PTRACE_GETREGSET), (m_tid), (®set), (& ioVec), (sizeof regs), "PTRACE_GETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 602) < 0) | |||
603 | m_result = false; | |||
604 | else | |||
605 | { | |||
606 | lldb_private::ArchSpec arch; | |||
607 | if (monitor->GetArchitecture(arch)) | |||
608 | { | |||
609 | m_result = true; | |||
610 | m_value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, arch.GetByteOrder()); | |||
611 | } | |||
612 | else | |||
613 | m_result = false; | |||
614 | } | |||
615 | } | |||
616 | } | |||
617 | else | |||
618 | { | |||
619 | elf_gregset_t regs; | |||
620 | int regset = NT_PRSTATUS; | |||
621 | struct iovec ioVec; | |||
622 | ||||
623 | ioVec.iov_base = ®s; | |||
624 | ioVec.iov_len = sizeof regs; | |||
625 | if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs)PtraceWrapper((PTRACE_GETREGSET), (m_tid), (®set), (& ioVec), (sizeof regs), "PTRACE_GETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 625) < 0) | |||
626 | m_result = false; | |||
627 | else | |||
628 | { | |||
629 | lldb_private::ArchSpec arch; | |||
630 | if (monitor->GetArchitecture(arch)) | |||
631 | { | |||
632 | m_result = true; | |||
633 | m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder()); | |||
634 | } else | |||
635 | m_result = false; | |||
636 | } | |||
637 | } | |||
638 | #else | |||
639 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS(1u << 13))); | |||
640 | ||||
641 | // Set errno to zero so that we can detect a failed peek. | |||
642 | errno(*__errno_location ()) = 0; | |||
643 | lldb::addr_t data = PTRACE(PTRACE_PEEKUSER, m_tid, (void*)m_offset, NULL, 0)PtraceWrapper((PTRACE_PEEKUSER), (m_tid), ((void*)m_offset), ( __null), (0), "PTRACE_PEEKUSER", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 643); | |||
644 | if (errno(*__errno_location ())) | |||
645 | m_result = false; | |||
646 | else | |||
647 | { | |||
648 | m_value = data; | |||
649 | m_result = true; | |||
650 | } | |||
651 | if (log) | |||
652 | log->Printf ("NativeProcessLinux::%s() reg %s: 0x%" PRIx64"l" "x", __FUNCTION__, | |||
653 | m_reg_name, data); | |||
654 | #endif | |||
655 | } | |||
656 | ||||
657 | //------------------------------------------------------------------------------ | |||
658 | /// @class WriteRegOperation | |||
659 | /// @brief Implements NativeProcessLinux::WriteRegisterValue. | |||
660 | class WriteRegOperation : public Operation | |||
661 | { | |||
662 | public: | |||
663 | WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, | |||
664 | const RegisterValue &value, bool &result) | |||
665 | : m_tid(tid), m_offset(offset), m_reg_name(reg_name), | |||
666 | m_value(value), m_result(result) | |||
667 | { } | |||
668 | ||||
669 | void Execute(NativeProcessLinux *monitor); | |||
670 | ||||
671 | private: | |||
672 | lldb::tid_t m_tid; | |||
673 | uintptr_t m_offset; | |||
674 | const char *m_reg_name; | |||
675 | const RegisterValue &m_value; | |||
676 | bool &m_result; | |||
677 | }; | |||
678 | ||||
679 | void | |||
680 | WriteRegOperation::Execute(NativeProcessLinux *monitor) | |||
681 | { | |||
682 | #if defined (__arm64__) || defined (__aarch64__) | |||
683 | if (m_offset > sizeof(struct user_pt_regs)) | |||
684 | { | |||
685 | uintptr_t offset = m_offset - sizeof(struct user_pt_regs); | |||
686 | if (offset > sizeof(struct user_fpsimd_state)) | |||
687 | { | |||
688 | m_result = false; | |||
689 | } | |||
690 | else | |||
691 | { | |||
692 | elf_fpregset_t regs; | |||
693 | int regset = NT_FPREGSET; | |||
694 | struct iovec ioVec; | |||
695 | ||||
696 | ioVec.iov_base = ®s; | |||
697 | ioVec.iov_len = sizeof regs; | |||
698 | if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs)PtraceWrapper((PTRACE_GETREGSET), (m_tid), (®set), (& ioVec), (sizeof regs), "PTRACE_GETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 698) < 0) | |||
699 | m_result = false; | |||
700 | else | |||
701 | { | |||
702 | ::memcpy((void *)(((unsigned char *)(®s)) + offset), m_value.GetBytes(), 16); | |||
703 | if (PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs)PtraceWrapper((PTRACE_SETREGSET), (m_tid), (®set), (& ioVec), (sizeof regs), "PTRACE_SETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 703) < 0) | |||
704 | m_result = false; | |||
705 | else | |||
706 | m_result = true; | |||
707 | } | |||
708 | } | |||
709 | } | |||
710 | else | |||
711 | { | |||
712 | elf_gregset_t regs; | |||
713 | int regset = NT_PRSTATUS; | |||
714 | struct iovec ioVec; | |||
715 | ||||
716 | ioVec.iov_base = ®s; | |||
717 | ioVec.iov_len = sizeof regs; | |||
718 | if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs)PtraceWrapper((PTRACE_GETREGSET), (m_tid), (®set), (& ioVec), (sizeof regs), "PTRACE_GETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 718) < 0) | |||
719 | m_result = false; | |||
720 | else | |||
721 | { | |||
722 | ::memcpy((void *)(((unsigned char *)(®s)) + m_offset), m_value.GetBytes(), 8); | |||
723 | if (PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs)PtraceWrapper((PTRACE_SETREGSET), (m_tid), (®set), (& ioVec), (sizeof regs), "PTRACE_SETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 723) < 0) | |||
724 | m_result = false; | |||
725 | else | |||
726 | m_result = true; | |||
727 | } | |||
728 | } | |||
729 | #else | |||
730 | void* buf; | |||
731 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS(1u << 13))); | |||
732 | ||||
733 | buf = (void*) m_value.GetAsUInt64(); | |||
734 | ||||
735 | if (log) | |||
736 | log->Printf ("NativeProcessLinux::%s() reg %s: %p", __FUNCTION__, m_reg_name, buf); | |||
737 | if (PTRACE(PTRACE_POKEUSER, m_tid, (void*)m_offset, buf, 0)PtraceWrapper((PTRACE_POKEUSER), (m_tid), ((void*)m_offset), ( buf), (0), "PTRACE_POKEUSER", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 737)) | |||
738 | m_result = false; | |||
739 | else | |||
740 | m_result = true; | |||
741 | #endif | |||
742 | } | |||
743 | ||||
744 | //------------------------------------------------------------------------------ | |||
745 | /// @class ReadGPROperation | |||
746 | /// @brief Implements NativeProcessLinux::ReadGPR. | |||
747 | class ReadGPROperation : public Operation | |||
748 | { | |||
749 | public: | |||
750 | ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result) | |||
751 | : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result) | |||
752 | { } | |||
753 | ||||
754 | void Execute(NativeProcessLinux *monitor); | |||
755 | ||||
756 | private: | |||
757 | lldb::tid_t m_tid; | |||
758 | void *m_buf; | |||
759 | size_t m_buf_size; | |||
760 | bool &m_result; | |||
761 | }; | |||
762 | ||||
763 | void | |||
764 | ReadGPROperation::Execute(NativeProcessLinux *monitor) | |||
765 | { | |||
766 | #if defined (__arm64__) || defined (__aarch64__) | |||
767 | int regset = NT_PRSTATUS; | |||
768 | struct iovec ioVec; | |||
769 | ||||
770 | ioVec.iov_base = m_buf; | |||
771 | ioVec.iov_len = m_buf_size; | |||
772 | if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size)PtraceWrapper((PTRACE_GETREGSET), (m_tid), (®set), (& ioVec), (m_buf_size), "PTRACE_GETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 772) < 0) | |||
773 | m_result = false; | |||
774 | else | |||
775 | m_result = true; | |||
776 | #else | |||
777 | if (PTRACE(PTRACE_GETREGS, m_tid, NULL, m_buf, m_buf_size)PtraceWrapper((PTRACE_GETREGS), (m_tid), (__null), (m_buf), ( m_buf_size), "PTRACE_GETREGS", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 777) < 0) | |||
778 | m_result = false; | |||
779 | else | |||
780 | m_result = true; | |||
781 | #endif | |||
782 | } | |||
783 | ||||
784 | //------------------------------------------------------------------------------ | |||
785 | /// @class ReadFPROperation | |||
786 | /// @brief Implements NativeProcessLinux::ReadFPR. | |||
787 | class ReadFPROperation : public Operation | |||
788 | { | |||
789 | public: | |||
790 | ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result) | |||
791 | : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result) | |||
792 | { } | |||
793 | ||||
794 | void Execute(NativeProcessLinux *monitor); | |||
795 | ||||
796 | private: | |||
797 | lldb::tid_t m_tid; | |||
798 | void *m_buf; | |||
799 | size_t m_buf_size; | |||
800 | bool &m_result; | |||
801 | }; | |||
802 | ||||
803 | void | |||
804 | ReadFPROperation::Execute(NativeProcessLinux *monitor) | |||
805 | { | |||
806 | #if defined (__arm64__) || defined (__aarch64__) | |||
807 | int regset = NT_FPREGSET; | |||
808 | struct iovec ioVec; | |||
809 | ||||
810 | ioVec.iov_base = m_buf; | |||
811 | ioVec.iov_len = m_buf_size; | |||
812 | if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size)PtraceWrapper((PTRACE_GETREGSET), (m_tid), (®set), (& ioVec), (m_buf_size), "PTRACE_GETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 812) < 0) | |||
813 | m_result = false; | |||
814 | else | |||
815 | m_result = true; | |||
816 | #else | |||
817 | if (PTRACE(PTRACE_GETFPREGS, m_tid, NULL, m_buf, m_buf_size)PtraceWrapper((PTRACE_GETFPREGS), (m_tid), (__null), (m_buf), (m_buf_size), "PTRACE_GETFPREGS", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 817) < 0) | |||
818 | m_result = false; | |||
819 | else | |||
820 | m_result = true; | |||
821 | #endif | |||
822 | } | |||
823 | ||||
824 | //------------------------------------------------------------------------------ | |||
825 | /// @class ReadRegisterSetOperation | |||
826 | /// @brief Implements NativeProcessLinux::ReadRegisterSet. | |||
827 | class ReadRegisterSetOperation : public Operation | |||
828 | { | |||
829 | public: | |||
830 | ReadRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset, bool &result) | |||
831 | : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset), m_result(result) | |||
832 | { } | |||
833 | ||||
834 | void Execute(NativeProcessLinux *monitor); | |||
835 | ||||
836 | private: | |||
837 | lldb::tid_t m_tid; | |||
838 | void *m_buf; | |||
839 | size_t m_buf_size; | |||
840 | const unsigned int m_regset; | |||
841 | bool &m_result; | |||
842 | }; | |||
843 | ||||
844 | void | |||
845 | ReadRegisterSetOperation::Execute(NativeProcessLinux *monitor) | |||
846 | { | |||
847 | if (PTRACE(PTRACE_GETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size)PtraceWrapper((PTRACE_GETREGSET), (m_tid), ((void *)&m_regset ), (m_buf), (m_buf_size), "PTRACE_GETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 847) < 0) | |||
848 | m_result = false; | |||
849 | else | |||
850 | m_result = true; | |||
851 | } | |||
852 | ||||
853 | //------------------------------------------------------------------------------ | |||
854 | /// @class WriteGPROperation | |||
855 | /// @brief Implements NativeProcessLinux::WriteGPR. | |||
856 | class WriteGPROperation : public Operation | |||
857 | { | |||
858 | public: | |||
859 | WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result) | |||
860 | : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result) | |||
861 | { } | |||
862 | ||||
863 | void Execute(NativeProcessLinux *monitor); | |||
864 | ||||
865 | private: | |||
866 | lldb::tid_t m_tid; | |||
867 | void *m_buf; | |||
868 | size_t m_buf_size; | |||
869 | bool &m_result; | |||
870 | }; | |||
871 | ||||
872 | void | |||
873 | WriteGPROperation::Execute(NativeProcessLinux *monitor) | |||
874 | { | |||
875 | #if defined (__arm64__) || defined (__aarch64__) | |||
876 | int regset = NT_PRSTATUS; | |||
877 | struct iovec ioVec; | |||
878 | ||||
879 | ioVec.iov_base = m_buf; | |||
880 | ioVec.iov_len = m_buf_size; | |||
881 | if (PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size)PtraceWrapper((PTRACE_SETREGSET), (m_tid), (®set), (& ioVec), (m_buf_size), "PTRACE_SETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 881) < 0) | |||
882 | m_result = false; | |||
883 | else | |||
884 | m_result = true; | |||
885 | #else | |||
886 | if (PTRACE(PTRACE_SETREGS, m_tid, NULL, m_buf, m_buf_size)PtraceWrapper((PTRACE_SETREGS), (m_tid), (__null), (m_buf), ( m_buf_size), "PTRACE_SETREGS", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 886) < 0) | |||
887 | m_result = false; | |||
888 | else | |||
889 | m_result = true; | |||
890 | #endif | |||
891 | } | |||
892 | ||||
893 | //------------------------------------------------------------------------------ | |||
894 | /// @class WriteFPROperation | |||
895 | /// @brief Implements NativeProcessLinux::WriteFPR. | |||
896 | class WriteFPROperation : public Operation | |||
897 | { | |||
898 | public: | |||
899 | WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result) | |||
900 | : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result) | |||
901 | { } | |||
902 | ||||
903 | void Execute(NativeProcessLinux *monitor); | |||
904 | ||||
905 | private: | |||
906 | lldb::tid_t m_tid; | |||
907 | void *m_buf; | |||
908 | size_t m_buf_size; | |||
909 | bool &m_result; | |||
910 | }; | |||
911 | ||||
912 | void | |||
913 | WriteFPROperation::Execute(NativeProcessLinux *monitor) | |||
914 | { | |||
915 | #if defined (__arm64__) || defined (__aarch64__) | |||
916 | int regset = NT_FPREGSET; | |||
917 | struct iovec ioVec; | |||
918 | ||||
919 | ioVec.iov_base = m_buf; | |||
920 | ioVec.iov_len = m_buf_size; | |||
921 | if (PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size)PtraceWrapper((PTRACE_SETREGSET), (m_tid), (®set), (& ioVec), (m_buf_size), "PTRACE_SETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 921) < 0) | |||
922 | m_result = false; | |||
923 | else | |||
924 | m_result = true; | |||
925 | #else | |||
926 | if (PTRACE(PTRACE_SETFPREGS, m_tid, NULL, m_buf, m_buf_size)PtraceWrapper((PTRACE_SETFPREGS), (m_tid), (__null), (m_buf), (m_buf_size), "PTRACE_SETFPREGS", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 926) < 0) | |||
927 | m_result = false; | |||
928 | else | |||
929 | m_result = true; | |||
930 | #endif | |||
931 | } | |||
932 | ||||
933 | //------------------------------------------------------------------------------ | |||
934 | /// @class WriteRegisterSetOperation | |||
935 | /// @brief Implements NativeProcessLinux::WriteRegisterSet. | |||
936 | class WriteRegisterSetOperation : public Operation | |||
937 | { | |||
938 | public: | |||
939 | WriteRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset, bool &result) | |||
940 | : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset), m_result(result) | |||
941 | { } | |||
942 | ||||
943 | void Execute(NativeProcessLinux *monitor); | |||
944 | ||||
945 | private: | |||
946 | lldb::tid_t m_tid; | |||
947 | void *m_buf; | |||
948 | size_t m_buf_size; | |||
949 | const unsigned int m_regset; | |||
950 | bool &m_result; | |||
951 | }; | |||
952 | ||||
953 | void | |||
954 | WriteRegisterSetOperation::Execute(NativeProcessLinux *monitor) | |||
955 | { | |||
956 | if (PTRACE(PTRACE_SETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size)PtraceWrapper((PTRACE_SETREGSET), (m_tid), ((void *)&m_regset ), (m_buf), (m_buf_size), "PTRACE_SETREGSET", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 956) < 0) | |||
957 | m_result = false; | |||
958 | else | |||
959 | m_result = true; | |||
960 | } | |||
961 | ||||
962 | //------------------------------------------------------------------------------ | |||
963 | /// @class ResumeOperation | |||
964 | /// @brief Implements NativeProcessLinux::Resume. | |||
965 | class ResumeOperation : public Operation | |||
966 | { | |||
967 | public: | |||
968 | ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) : | |||
969 | m_tid(tid), m_signo(signo), m_result(result) { } | |||
970 | ||||
971 | void Execute(NativeProcessLinux *monitor); | |||
972 | ||||
973 | private: | |||
974 | lldb::tid_t m_tid; | |||
975 | uint32_t m_signo; | |||
976 | bool &m_result; | |||
977 | }; | |||
978 | ||||
979 | void | |||
980 | ResumeOperation::Execute(NativeProcessLinux *monitor) | |||
981 | { | |||
982 | intptr_t data = 0; | |||
983 | ||||
984 | if (m_signo != LLDB_INVALID_SIGNAL_NUMBER(2147483647)) | |||
985 | data = m_signo; | |||
986 | ||||
987 | if (PTRACE(PTRACE_CONT, m_tid, NULL, (void*)data, 0)PtraceWrapper((PTRACE_CONT), (m_tid), (__null), ((void*)data) , (0), "PTRACE_CONT", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 987)) | |||
988 | { | |||
989 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
990 | ||||
991 | if (log) | |||
992 | log->Printf ("ResumeOperation (%" PRIu64"l" "u" ") failed: %s", m_tid, strerror(errno(*__errno_location ()))); | |||
993 | m_result = false; | |||
994 | } | |||
995 | else | |||
996 | m_result = true; | |||
997 | } | |||
998 | ||||
999 | //------------------------------------------------------------------------------ | |||
1000 | /// @class SingleStepOperation | |||
1001 | /// @brief Implements NativeProcessLinux::SingleStep. | |||
1002 | class SingleStepOperation : public Operation | |||
1003 | { | |||
1004 | public: | |||
1005 | SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result) | |||
1006 | : m_tid(tid), m_signo(signo), m_result(result) { } | |||
1007 | ||||
1008 | void Execute(NativeProcessLinux *monitor); | |||
1009 | ||||
1010 | private: | |||
1011 | lldb::tid_t m_tid; | |||
1012 | uint32_t m_signo; | |||
1013 | bool &m_result; | |||
1014 | }; | |||
1015 | ||||
1016 | void | |||
1017 | SingleStepOperation::Execute(NativeProcessLinux *monitor) | |||
1018 | { | |||
1019 | intptr_t data = 0; | |||
1020 | ||||
1021 | if (m_signo != LLDB_INVALID_SIGNAL_NUMBER(2147483647)) | |||
1022 | data = m_signo; | |||
1023 | ||||
1024 | if (PTRACE(PTRACE_SINGLESTEP, m_tid, NULL, (void*)data, 0)PtraceWrapper((PTRACE_SINGLESTEP), (m_tid), (__null), ((void* )data), (0), "PTRACE_SINGLESTEP", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1024)) | |||
1025 | m_result = false; | |||
1026 | else | |||
1027 | m_result = true; | |||
1028 | } | |||
1029 | ||||
1030 | //------------------------------------------------------------------------------ | |||
1031 | /// @class SiginfoOperation | |||
1032 | /// @brief Implements NativeProcessLinux::GetSignalInfo. | |||
1033 | class SiginfoOperation : public Operation | |||
1034 | { | |||
1035 | public: | |||
1036 | SiginfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err) | |||
1037 | : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { } | |||
1038 | ||||
1039 | void Execute(NativeProcessLinux *monitor); | |||
1040 | ||||
1041 | private: | |||
1042 | lldb::tid_t m_tid; | |||
1043 | void *m_info; | |||
1044 | bool &m_result; | |||
1045 | int &m_err; | |||
1046 | }; | |||
1047 | ||||
1048 | void | |||
1049 | SiginfoOperation::Execute(NativeProcessLinux *monitor) | |||
1050 | { | |||
1051 | if (PTRACE(PTRACE_GETSIGINFO, m_tid, NULL, m_info, 0)PtraceWrapper((PTRACE_GETSIGINFO), (m_tid), (__null), (m_info ), (0), "PTRACE_GETSIGINFO", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1051)) { | |||
1052 | m_result = false; | |||
1053 | m_err = errno(*__errno_location ()); | |||
1054 | } | |||
1055 | else | |||
1056 | m_result = true; | |||
1057 | } | |||
1058 | ||||
1059 | //------------------------------------------------------------------------------ | |||
1060 | /// @class EventMessageOperation | |||
1061 | /// @brief Implements NativeProcessLinux::GetEventMessage. | |||
1062 | class EventMessageOperation : public Operation | |||
1063 | { | |||
1064 | public: | |||
1065 | EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result) | |||
1066 | : m_tid(tid), m_message(message), m_result(result) { } | |||
1067 | ||||
1068 | void Execute(NativeProcessLinux *monitor); | |||
1069 | ||||
1070 | private: | |||
1071 | lldb::tid_t m_tid; | |||
1072 | unsigned long *m_message; | |||
1073 | bool &m_result; | |||
1074 | }; | |||
1075 | ||||
1076 | void | |||
1077 | EventMessageOperation::Execute(NativeProcessLinux *monitor) | |||
1078 | { | |||
1079 | if (PTRACE(PTRACE_GETEVENTMSG, m_tid, NULL, m_message, 0)PtraceWrapper((PTRACE_GETEVENTMSG), (m_tid), (__null), (m_message ), (0), "PTRACE_GETEVENTMSG", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1079)) | |||
1080 | m_result = false; | |||
1081 | else | |||
1082 | m_result = true; | |||
1083 | } | |||
1084 | ||||
1085 | class DetachOperation : public Operation | |||
1086 | { | |||
1087 | public: | |||
1088 | DetachOperation(lldb::tid_t tid, Error &result) : m_tid(tid), m_error(result) { } | |||
1089 | ||||
1090 | void Execute(NativeProcessLinux *monitor); | |||
1091 | ||||
1092 | private: | |||
1093 | lldb::tid_t m_tid; | |||
1094 | Error &m_error; | |||
1095 | }; | |||
1096 | ||||
1097 | void | |||
1098 | DetachOperation::Execute(NativeProcessLinux *monitor) | |||
1099 | { | |||
1100 | if (ptrace(PT_DETACHPTRACE_DETACH, m_tid, NULL__null, 0) < 0) | |||
1101 | m_error.SetErrorToErrno(); | |||
1102 | } | |||
1103 | ||||
1104 | } | |||
1105 | ||||
1106 | using namespace lldb_private; | |||
1107 | ||||
1108 | // Simple helper function to ensure flags are enabled on the given file | |||
1109 | // descriptor. | |||
1110 | static bool | |||
1111 | EnsureFDFlags(int fd, int flags, Error &error) | |||
1112 | { | |||
1113 | int status; | |||
1114 | ||||
1115 | if ((status = fcntl(fd, F_GETFL3)) == -1) | |||
1116 | { | |||
1117 | error.SetErrorToErrno(); | |||
1118 | return false; | |||
1119 | } | |||
1120 | ||||
1121 | if (fcntl(fd, F_SETFL4, status | flags) == -1) | |||
1122 | { | |||
1123 | error.SetErrorToErrno(); | |||
1124 | return false; | |||
1125 | } | |||
1126 | ||||
1127 | return true; | |||
1128 | } | |||
1129 | ||||
1130 | NativeProcessLinux::OperationArgs::OperationArgs(NativeProcessLinux *monitor) | |||
1131 | : m_monitor(monitor) | |||
1132 | { | |||
1133 | sem_init(&m_semaphore, 0, 0); | |||
1134 | } | |||
1135 | ||||
1136 | NativeProcessLinux::OperationArgs::~OperationArgs() | |||
1137 | { | |||
1138 | sem_destroy(&m_semaphore); | |||
1139 | } | |||
1140 | ||||
1141 | NativeProcessLinux::LaunchArgs::LaunchArgs(NativeProcessLinux *monitor, | |||
1142 | lldb_private::Module *module, | |||
1143 | char const **argv, | |||
1144 | char const **envp, | |||
1145 | const std::string &stdin_path, | |||
1146 | const std::string &stdout_path, | |||
1147 | const std::string &stderr_path, | |||
1148 | const char *working_dir, | |||
1149 | const lldb_private::ProcessLaunchInfo &launch_info) | |||
1150 | : OperationArgs(monitor), | |||
1151 | m_module(module), | |||
1152 | m_argv(argv), | |||
1153 | m_envp(envp), | |||
1154 | m_stdin_path(stdin_path), | |||
1155 | m_stdout_path(stdout_path), | |||
1156 | m_stderr_path(stderr_path), | |||
1157 | m_working_dir(working_dir), | |||
1158 | m_launch_info(launch_info) | |||
1159 | { | |||
1160 | } | |||
1161 | ||||
1162 | NativeProcessLinux::LaunchArgs::~LaunchArgs() | |||
1163 | { } | |||
1164 | ||||
1165 | NativeProcessLinux::AttachArgs::AttachArgs(NativeProcessLinux *monitor, | |||
1166 | lldb::pid_t pid) | |||
1167 | : OperationArgs(monitor), m_pid(pid) { } | |||
1168 | ||||
1169 | NativeProcessLinux::AttachArgs::~AttachArgs() | |||
1170 | { } | |||
1171 | ||||
1172 | // ----------------------------------------------------------------------------- | |||
1173 | // Public Static Methods | |||
1174 | // ----------------------------------------------------------------------------- | |||
1175 | ||||
1176 | lldb_private::Error | |||
1177 | NativeProcessLinux::LaunchProcess ( | |||
1178 | lldb_private::Module *exe_module, | |||
1179 | lldb_private::ProcessLaunchInfo &launch_info, | |||
1180 | lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, | |||
1181 | NativeProcessProtocolSP &native_process_sp) | |||
1182 | { | |||
1183 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1184 | ||||
1185 | Error error; | |||
1186 | ||||
1187 | // Verify the working directory is valid if one was specified. | |||
1188 | const char* working_dir = launch_info.GetWorkingDirectory (); | |||
1189 | if (working_dir) | |||
1190 | { | |||
1191 | FileSpec working_dir_fs (working_dir, true); | |||
1192 | if (!working_dir_fs || working_dir_fs.GetFileType () != FileSpec::eFileTypeDirectory) | |||
1193 | { | |||
1194 | error.SetErrorStringWithFormat ("No such file or directory: %s", working_dir); | |||
1195 | return error; | |||
1196 | } | |||
1197 | } | |||
1198 | ||||
1199 | const lldb_private::FileAction *file_action; | |||
1200 | ||||
1201 | // Default of NULL will mean to use existing open file descriptors. | |||
1202 | std::string stdin_path; | |||
1203 | std::string stdout_path; | |||
1204 | std::string stderr_path; | |||
1205 | ||||
1206 | file_action = launch_info.GetFileActionForFD (STDIN_FILENO0); | |||
1207 | if (file_action) | |||
1208 | stdin_path = file_action->GetPath (); | |||
1209 | ||||
1210 | file_action = launch_info.GetFileActionForFD (STDOUT_FILENO1); | |||
1211 | if (file_action) | |||
1212 | stdout_path = file_action->GetPath (); | |||
1213 | ||||
1214 | file_action = launch_info.GetFileActionForFD (STDERR_FILENO2); | |||
1215 | if (file_action) | |||
1216 | stderr_path = file_action->GetPath (); | |||
1217 | ||||
1218 | if (log) | |||
1219 | { | |||
1220 | if (!stdin_path.empty ()) | |||
1221 | log->Printf ("NativeProcessLinux::%s setting STDIN to '%s'", __FUNCTION__, stdin_path.c_str ()); | |||
1222 | else | |||
1223 | log->Printf ("NativeProcessLinux::%s leaving STDIN as is", __FUNCTION__); | |||
1224 | ||||
1225 | if (!stdout_path.empty ()) | |||
1226 | log->Printf ("NativeProcessLinux::%s setting STDOUT to '%s'", __FUNCTION__, stdout_path.c_str ()); | |||
1227 | else | |||
1228 | log->Printf ("NativeProcessLinux::%s leaving STDOUT as is", __FUNCTION__); | |||
1229 | ||||
1230 | if (!stderr_path.empty ()) | |||
1231 | log->Printf ("NativeProcessLinux::%s setting STDERR to '%s'", __FUNCTION__, stderr_path.c_str ()); | |||
1232 | else | |||
1233 | log->Printf ("NativeProcessLinux::%s leaving STDERR as is", __FUNCTION__); | |||
1234 | } | |||
1235 | ||||
1236 | // Create the NativeProcessLinux in launch mode. | |||
1237 | native_process_sp.reset (new NativeProcessLinux ()); | |||
1238 | ||||
1239 | if (log) | |||
1240 | { | |||
1241 | int i = 0; | |||
1242 | for (const char **args = launch_info.GetArguments ().GetConstArgumentVector (); *args; ++args, ++i) | |||
1243 | { | |||
1244 | log->Printf ("NativeProcessLinux::%s arg %d: \"%s\"", __FUNCTION__, i, *args ? *args : "nullptr"); | |||
1245 | ++i; | |||
1246 | } | |||
1247 | } | |||
1248 | ||||
1249 | if (!native_process_sp->RegisterNativeDelegate (native_delegate)) | |||
1250 | { | |||
1251 | native_process_sp.reset (); | |||
1252 | error.SetErrorStringWithFormat ("failed to register the native delegate"); | |||
1253 | return error; | |||
1254 | } | |||
1255 | ||||
1256 | reinterpret_cast<NativeProcessLinux*> (native_process_sp.get ())->LaunchInferior ( | |||
1257 | exe_module, | |||
1258 | launch_info.GetArguments ().GetConstArgumentVector (), | |||
1259 | launch_info.GetEnvironmentEntries ().GetConstArgumentVector (), | |||
1260 | stdin_path, | |||
1261 | stdout_path, | |||
1262 | stderr_path, | |||
1263 | working_dir, | |||
1264 | launch_info, | |||
1265 | error); | |||
1266 | ||||
1267 | if (error.Fail ()) | |||
1268 | { | |||
1269 | native_process_sp.reset (); | |||
1270 | if (log) | |||
1271 | log->Printf ("NativeProcessLinux::%s failed to launch process: %s", __FUNCTION__, error.AsCString ()); | |||
1272 | return error; | |||
1273 | } | |||
1274 | ||||
1275 | launch_info.SetProcessID (native_process_sp->GetID ()); | |||
1276 | ||||
1277 | return error; | |||
1278 | } | |||
1279 | ||||
1280 | lldb_private::Error | |||
1281 | NativeProcessLinux::AttachToProcess ( | |||
1282 | lldb::pid_t pid, | |||
1283 | lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, | |||
1284 | NativeProcessProtocolSP &native_process_sp) | |||
1285 | { | |||
1286 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1287 | if (log && log->GetMask ().Test (POSIX_LOG_VERBOSE(1u << 0))) | |||
1288 | log->Printf ("NativeProcessLinux::%s(pid = %" PRIi64"l" "i" ")", __FUNCTION__, pid); | |||
1289 | ||||
1290 | // Grab the current platform architecture. This should be Linux, | |||
1291 | // since this code is only intended to run on a Linux host. | |||
1292 | PlatformSP platform_sp (Platform::GetHostPlatform ()); | |||
1293 | if (!platform_sp) | |||
1294 | return Error("failed to get a valid default platform"); | |||
1295 | ||||
1296 | // Retrieve the architecture for the running process. | |||
1297 | ArchSpec process_arch; | |||
1298 | Error error = ResolveProcessArchitecture (pid, *platform_sp.get (), process_arch); | |||
1299 | if (!error.Success ()) | |||
1300 | return error; | |||
1301 | ||||
1302 | std::shared_ptr<NativeProcessLinux> native_process_linux_sp (new NativeProcessLinux ()); | |||
1303 | ||||
1304 | if (!native_process_linux_sp->RegisterNativeDelegate (native_delegate)) | |||
1305 | { | |||
1306 | error.SetErrorStringWithFormat ("failed to register the native delegate"); | |||
1307 | return error; | |||
1308 | } | |||
1309 | ||||
1310 | native_process_linux_sp->AttachToInferior (pid, error); | |||
1311 | if (!error.Success ()) | |||
1312 | return error; | |||
1313 | ||||
1314 | native_process_sp = native_process_linux_sp; | |||
1315 | return error; | |||
1316 | } | |||
1317 | ||||
1318 | // ----------------------------------------------------------------------------- | |||
1319 | // Public Instance Methods | |||
1320 | // ----------------------------------------------------------------------------- | |||
1321 | ||||
1322 | NativeProcessLinux::NativeProcessLinux () : | |||
1323 | NativeProcessProtocol (LLDB_INVALID_PROCESS_ID0), | |||
1324 | m_arch (), | |||
1325 | m_operation (nullptr), | |||
1326 | m_operation_mutex (), | |||
1327 | m_operation_pending (), | |||
1328 | m_operation_done (), | |||
1329 | m_wait_for_stop_tids (), | |||
1330 | m_wait_for_stop_tids_mutex (), | |||
1331 | m_wait_for_group_stop_tids (), | |||
1332 | m_group_stop_signal_tid (LLDB_INVALID_THREAD_ID0), | |||
1333 | m_group_stop_signal (LLDB_INVALID_SIGNAL_NUMBER(2147483647)), | |||
1334 | m_wait_for_group_stop_tids_mutex (), | |||
1335 | m_supports_mem_region (eLazyBoolCalculate), | |||
1336 | m_mem_region_cache (), | |||
1337 | m_mem_region_cache_mutex () | |||
1338 | { | |||
1339 | } | |||
1340 | ||||
1341 | //------------------------------------------------------------------------------ | |||
1342 | /// The basic design of the NativeProcessLinux is built around two threads. | |||
1343 | /// | |||
1344 | /// One thread (@see SignalThread) simply blocks on a call to waitpid() looking | |||
1345 | /// for changes in the debugee state. When a change is detected a | |||
1346 | /// ProcessMessage is sent to the associated ProcessLinux instance. This thread | |||
1347 | /// "drives" state changes in the debugger. | |||
1348 | /// | |||
1349 | /// The second thread (@see OperationThread) is responsible for two things 1) | |||
1350 | /// launching or attaching to the inferior process, and then 2) servicing | |||
1351 | /// operations such as register reads/writes, stepping, etc. See the comments | |||
1352 | /// on the Operation class for more info as to why this is needed. | |||
1353 | void | |||
1354 | NativeProcessLinux::LaunchInferior ( | |||
1355 | Module *module, | |||
1356 | const char *argv[], | |||
1357 | const char *envp[], | |||
1358 | const std::string &stdin_path, | |||
1359 | const std::string &stdout_path, | |||
1360 | const std::string &stderr_path, | |||
1361 | const char *working_dir, | |||
1362 | const lldb_private::ProcessLaunchInfo &launch_info, | |||
1363 | lldb_private::Error &error) | |||
1364 | { | |||
1365 | if (module) | |||
1366 | m_arch = module->GetArchitecture (); | |||
1367 | ||||
1368 | SetState(eStateLaunching); | |||
1369 | ||||
1370 | std::unique_ptr<LaunchArgs> args( | |||
1371 | new LaunchArgs( | |||
1372 | this, module, argv, envp, | |||
1373 | stdin_path, stdout_path, stderr_path, | |||
1374 | working_dir, launch_info)); | |||
1375 | ||||
1376 | sem_init(&m_operation_pending, 0, 0); | |||
1377 | sem_init(&m_operation_done, 0, 0); | |||
1378 | ||||
1379 | StartLaunchOpThread(args.get(), error); | |||
1380 | if (!error.Success()) | |||
1381 | return; | |||
1382 | ||||
1383 | WAIT_AGAIN: | |||
1384 | // Wait for the operation thread to initialize. | |||
1385 | if (sem_wait(&args->m_semaphore)) | |||
1386 | { | |||
1387 | if (errno(*__errno_location ()) == EINTR4) | |||
1388 | goto WAIT_AGAIN; | |||
1389 | else | |||
1390 | { | |||
1391 | error.SetErrorToErrno(); | |||
1392 | return; | |||
1393 | } | |||
1394 | } | |||
1395 | ||||
1396 | // Check that the launch was a success. | |||
1397 | if (!args->m_error.Success()) | |||
1398 | { | |||
1399 | StopOpThread(); | |||
1400 | error = args->m_error; | |||
1401 | return; | |||
1402 | } | |||
1403 | ||||
1404 | // Finally, start monitoring the child process for change in state. | |||
1405 | m_monitor_thread = Host::StartMonitoringChildProcess( | |||
1406 | NativeProcessLinux::MonitorCallback, this, GetID(), true); | |||
1407 | if (!m_monitor_thread.IsJoinable()) | |||
1408 | { | |||
1409 | error.SetErrorToGenericError(); | |||
1410 | error.SetErrorString ("Process attach failed to create monitor thread for NativeProcessLinux::MonitorCallback."); | |||
1411 | return; | |||
1412 | } | |||
1413 | } | |||
1414 | ||||
1415 | void | |||
1416 | NativeProcessLinux::AttachToInferior (lldb::pid_t pid, lldb_private::Error &error) | |||
1417 | { | |||
1418 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1419 | if (log) | |||
1420 | log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64"l" "i" ")", __FUNCTION__, pid); | |||
1421 | ||||
1422 | // We can use the Host for everything except the ResolveExecutable portion. | |||
1423 | PlatformSP platform_sp = Platform::GetHostPlatform (); | |||
1424 | if (!platform_sp) | |||
1425 | { | |||
1426 | if (log) | |||
1427 | log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64"l" "i" "): no default platform set", __FUNCTION__, pid); | |||
1428 | error.SetErrorString ("no default platform available"); | |||
1429 | return; | |||
1430 | } | |||
1431 | ||||
1432 | // Gather info about the process. | |||
1433 | ProcessInstanceInfo process_info; | |||
1434 | if (!platform_sp->GetProcessInfo (pid, process_info)) | |||
1435 | { | |||
1436 | if (log) | |||
1437 | log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64"l" "i" "): failed to get process info", __FUNCTION__, pid); | |||
1438 | error.SetErrorString ("failed to get process info"); | |||
1439 | return; | |||
1440 | } | |||
1441 | ||||
1442 | // Resolve the executable module | |||
1443 | ModuleSP exe_module_sp; | |||
1444 | FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); | |||
1445 | ModuleSpec exe_module_spec(process_info.GetExecutableFile(), HostInfo::GetArchitecture()); | |||
1446 | error = platform_sp->ResolveExecutable(exe_module_spec, exe_module_sp, | |||
1447 | executable_search_paths.GetSize() ? &executable_search_paths : NULL__null); | |||
1448 | if (!error.Success()) | |||
1449 | return; | |||
1450 | ||||
1451 | // Set the architecture to the exe architecture. | |||
1452 | m_arch = exe_module_sp->GetArchitecture(); | |||
1453 | if (log) | |||
1454 | log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64"l" "i" ") detected architecture %s", __FUNCTION__, pid, m_arch.GetArchitectureName ()); | |||
1455 | ||||
1456 | m_pid = pid; | |||
1457 | SetState(eStateAttaching); | |||
1458 | ||||
1459 | sem_init (&m_operation_pending, 0, 0); | |||
1460 | sem_init (&m_operation_done, 0, 0); | |||
1461 | ||||
1462 | std::unique_ptr<AttachArgs> args (new AttachArgs (this, pid)); | |||
1463 | ||||
1464 | StartAttachOpThread(args.get (), error); | |||
1465 | if (!error.Success ()) | |||
1466 | return; | |||
1467 | ||||
1468 | WAIT_AGAIN: | |||
1469 | // Wait for the operation thread to initialize. | |||
1470 | if (sem_wait (&args->m_semaphore)) | |||
1471 | { | |||
1472 | if (errno(*__errno_location ()) == EINTR4) | |||
1473 | goto WAIT_AGAIN; | |||
1474 | else | |||
1475 | { | |||
1476 | error.SetErrorToErrno (); | |||
1477 | return; | |||
1478 | } | |||
1479 | } | |||
1480 | ||||
1481 | // Check that the attach was a success. | |||
1482 | if (!args->m_error.Success ()) | |||
1483 | { | |||
1484 | StopOpThread (); | |||
1485 | error = args->m_error; | |||
1486 | return; | |||
1487 | } | |||
1488 | ||||
1489 | // Finally, start monitoring the child process for change in state. | |||
1490 | m_monitor_thread = Host::StartMonitoringChildProcess ( | |||
1491 | NativeProcessLinux::MonitorCallback, this, GetID (), true); | |||
1492 | if (!m_monitor_thread.IsJoinable()) | |||
1493 | { | |||
1494 | error.SetErrorToGenericError (); | |||
1495 | error.SetErrorString ("Process attach failed to create monitor thread for NativeProcessLinux::MonitorCallback."); | |||
1496 | return; | |||
1497 | } | |||
1498 | } | |||
1499 | ||||
1500 | NativeProcessLinux::~NativeProcessLinux() | |||
1501 | { | |||
1502 | StopMonitor(); | |||
1503 | } | |||
1504 | ||||
1505 | //------------------------------------------------------------------------------ | |||
1506 | // Thread setup and tear down. | |||
1507 | ||||
1508 | void | |||
1509 | NativeProcessLinux::StartLaunchOpThread(LaunchArgs *args, Error &error) | |||
1510 | { | |||
1511 | static const char *g_thread_name = "lldb.process.nativelinux.operation"; | |||
1512 | ||||
1513 | if (m_operation_thread.IsJoinable()) | |||
1514 | return; | |||
1515 | ||||
1516 | m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args, &error); | |||
1517 | } | |||
1518 | ||||
1519 | void * | |||
1520 | NativeProcessLinux::LaunchOpThread(void *arg) | |||
1521 | { | |||
1522 | LaunchArgs *args = static_cast<LaunchArgs*>(arg); | |||
1523 | ||||
1524 | if (!Launch(args)) { | |||
1525 | sem_post(&args->m_semaphore); | |||
1526 | return NULL__null; | |||
1527 | } | |||
1528 | ||||
1529 | ServeOperation(args); | |||
1530 | return NULL__null; | |||
1531 | } | |||
1532 | ||||
1533 | bool | |||
1534 | NativeProcessLinux::Launch(LaunchArgs *args) | |||
1535 | { | |||
1536 | assert (args && "null args")((args && "null args") ? static_cast<void> (0) : __assert_fail ("args && \"null args\"", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1536, __PRETTY_FUNCTION__)); | |||
1537 | if (!args) | |||
1538 | return false; | |||
1539 | ||||
1540 | NativeProcessLinux *monitor = args->m_monitor; | |||
1541 | assert (monitor && "monitor is NULL")((monitor && "monitor is NULL") ? static_cast<void > (0) : __assert_fail ("monitor && \"monitor is NULL\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1541, __PRETTY_FUNCTION__)); | |||
1542 | if (!monitor) | |||
1543 | return false; | |||
1544 | ||||
1545 | const char **argv = args->m_argv; | |||
1546 | const char **envp = args->m_envp; | |||
1547 | const char *working_dir = args->m_working_dir; | |||
1548 | ||||
1549 | lldb_utility::PseudoTerminal terminal; | |||
1550 | const size_t err_len = 1024; | |||
1551 | char err_str[err_len]; | |||
1552 | lldb::pid_t pid; | |||
1553 | NativeThreadProtocolSP thread_sp; | |||
1554 | ||||
1555 | lldb::ThreadSP inferior; | |||
1556 | ||||
1557 | // Propagate the environment if one is not supplied. | |||
1558 | if (envp == NULL__null || envp[0] == NULL__null) | |||
1559 | envp = const_cast<const char **>(environ); | |||
1560 | ||||
1561 | if ((pid = terminal.Fork(err_str, err_len)) == static_cast<lldb::pid_t> (-1)) | |||
1562 | { | |||
1563 | args->m_error.SetErrorToGenericError(); | |||
1564 | args->m_error.SetErrorString("Process fork failed."); | |||
1565 | return false; | |||
1566 | } | |||
1567 | ||||
1568 | // Recognized child exit status codes. | |||
1569 | enum { | |||
1570 | ePtraceFailed = 1, | |||
1571 | eDupStdinFailed, | |||
1572 | eDupStdoutFailed, | |||
1573 | eDupStderrFailed, | |||
1574 | eChdirFailed, | |||
1575 | eExecFailed, | |||
1576 | eSetGidFailed | |||
1577 | }; | |||
1578 | ||||
1579 | // Child process. | |||
1580 | if (pid == 0) | |||
1581 | { | |||
1582 | // FIXME consider opening a pipe between parent/child and have this forked child | |||
1583 | // send log info to parent re: launch status, in place of the log lines removed here. | |||
1584 | ||||
1585 | // Start tracing this child that is about to exec. | |||
1586 | if (PTRACE(PTRACE_TRACEME, 0, NULL, NULL, 0)PtraceWrapper((PTRACE_TRACEME), (0), (__null), (__null), (0), "PTRACE_TRACEME", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1586) < 0) | |||
1587 | exit(ePtraceFailed); | |||
1588 | ||||
1589 | // Do not inherit setgid powers. | |||
1590 | if (setgid(getgid()) != 0) | |||
1591 | exit(eSetGidFailed); | |||
1592 | ||||
1593 | // Attempt to have our own process group. | |||
1594 | if (setpgid(0, 0) != 0) | |||
1595 | { | |||
1596 | // FIXME log that this failed. This is common. | |||
1597 | // Don't allow this to prevent an inferior exec. | |||
1598 | } | |||
1599 | ||||
1600 | // Dup file descriptors if needed. | |||
1601 | if (!args->m_stdin_path.empty ()) | |||
1602 | if (!DupDescriptor(args->m_stdin_path.c_str (), STDIN_FILENO0, O_RDONLY00)) | |||
1603 | exit(eDupStdinFailed); | |||
1604 | ||||
1605 | if (!args->m_stdout_path.empty ()) | |||
1606 | if (!DupDescriptor(args->m_stdout_path.c_str (), STDOUT_FILENO1, O_WRONLY01 | O_CREAT0100)) | |||
1607 | exit(eDupStdoutFailed); | |||
1608 | ||||
1609 | if (!args->m_stderr_path.empty ()) | |||
1610 | if (!DupDescriptor(args->m_stderr_path.c_str (), STDERR_FILENO2, O_WRONLY01 | O_CREAT0100)) | |||
1611 | exit(eDupStderrFailed); | |||
1612 | ||||
1613 | // Change working directory | |||
1614 | if (working_dir != NULL__null && working_dir[0]) | |||
1615 | if (0 != ::chdir(working_dir)) | |||
1616 | exit(eChdirFailed); | |||
1617 | ||||
1618 | // Disable ASLR if requested. | |||
1619 | if (args->m_launch_info.GetFlags ().Test (lldb::eLaunchFlagDisableASLR)) | |||
1620 | { | |||
1621 | const int old_personality = personality (LLDB_PERSONALITY_GET_CURRENT_SETTINGS0xffffffff); | |||
1622 | if (old_personality == -1) | |||
1623 | { | |||
1624 | // Can't retrieve Linux personality. Cannot disable ASLR. | |||
1625 | } | |||
1626 | else | |||
1627 | { | |||
1628 | const int new_personality = personality (ADDR_NO_RANDOMIZE | old_personality); | |||
1629 | if (new_personality == -1) | |||
1630 | { | |||
1631 | // Disabling ASLR failed. | |||
1632 | } | |||
1633 | else | |||
1634 | { | |||
1635 | // Disabling ASLR succeeded. | |||
1636 | } | |||
1637 | } | |||
1638 | } | |||
1639 | ||||
1640 | // Execute. We should never return... | |||
1641 | execve(argv[0], | |||
1642 | const_cast<char *const *>(argv), | |||
1643 | const_cast<char *const *>(envp)); | |||
1644 | ||||
1645 | // ...unless exec fails. In which case we definitely need to end the child here. | |||
1646 | exit(eExecFailed); | |||
1647 | } | |||
1648 | ||||
1649 | // | |||
1650 | // This is the parent code here. | |||
1651 | // | |||
1652 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1653 | ||||
1654 | // Wait for the child process to trap on its call to execve. | |||
1655 | ::pid_t wpid; | |||
1656 | int status; | |||
1657 | if ((wpid = waitpid(pid, &status, 0)) < 0) | |||
1658 | { | |||
1659 | args->m_error.SetErrorToErrno(); | |||
1660 | ||||
1661 | if (log) | |||
1662 | log->Printf ("NativeProcessLinux::%s waitpid for inferior failed with %s", __FUNCTION__, args->m_error.AsCString ()); | |||
1663 | ||||
1664 | // Mark the inferior as invalid. | |||
1665 | // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. | |||
1666 | monitor->SetState (StateType::eStateInvalid); | |||
1667 | ||||
1668 | return false; | |||
1669 | } | |||
1670 | else if (WIFEXITED(status)((((*(int *) &(status))) & 0x7f) == 0)) | |||
1671 | { | |||
1672 | // open, dup or execve likely failed for some reason. | |||
1673 | args->m_error.SetErrorToGenericError(); | |||
1674 | switch (WEXITSTATUS(status)((((*(int *) &(status))) & 0xff00) >> 8)) | |||
1675 | { | |||
1676 | case ePtraceFailed: | |||
1677 | args->m_error.SetErrorString("Child ptrace failed."); | |||
1678 | break; | |||
1679 | case eDupStdinFailed: | |||
1680 | args->m_error.SetErrorString("Child open stdin failed."); | |||
1681 | break; | |||
1682 | case eDupStdoutFailed: | |||
1683 | args->m_error.SetErrorString("Child open stdout failed."); | |||
1684 | break; | |||
1685 | case eDupStderrFailed: | |||
1686 | args->m_error.SetErrorString("Child open stderr failed."); | |||
1687 | break; | |||
1688 | case eChdirFailed: | |||
1689 | args->m_error.SetErrorString("Child failed to set working directory."); | |||
1690 | break; | |||
1691 | case eExecFailed: | |||
1692 | args->m_error.SetErrorString("Child exec failed."); | |||
1693 | break; | |||
1694 | case eSetGidFailed: | |||
1695 | args->m_error.SetErrorString("Child setgid failed."); | |||
1696 | break; | |||
1697 | default: | |||
1698 | args->m_error.SetErrorString("Child returned unknown exit status."); | |||
1699 | break; | |||
1700 | } | |||
1701 | ||||
1702 | if (log) | |||
1703 | { | |||
1704 | log->Printf ("NativeProcessLinux::%s inferior exited with status %d before issuing a STOP", | |||
1705 | __FUNCTION__, | |||
1706 | WEXITSTATUS(status)((((*(int *) &(status))) & 0xff00) >> 8)); | |||
1707 | } | |||
1708 | ||||
1709 | // Mark the inferior as invalid. | |||
1710 | // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. | |||
1711 | monitor->SetState (StateType::eStateInvalid); | |||
1712 | ||||
1713 | return false; | |||
1714 | } | |||
1715 | assert(WIFSTOPPED(status) && (wpid == static_cast< ::pid_t> (pid)) &&((((((*(int *) &(status))) & 0xff) == 0x7f) && (wpid == static_cast< ::pid_t> (pid)) && "Could not sync with inferior process." ) ? static_cast<void> (0) : __assert_fail ("((((*(int *) &(status))) & 0xff) == 0x7f) && (wpid == static_cast< ::pid_t> (pid)) && \"Could not sync with inferior process.\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1716, __PRETTY_FUNCTION__)) | |||
1716 | "Could not sync with inferior process.")((((((*(int *) &(status))) & 0xff) == 0x7f) && (wpid == static_cast< ::pid_t> (pid)) && "Could not sync with inferior process." ) ? static_cast<void> (0) : __assert_fail ("((((*(int *) &(status))) & 0xff) == 0x7f) && (wpid == static_cast< ::pid_t> (pid)) && \"Could not sync with inferior process.\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1716, __PRETTY_FUNCTION__)); | |||
1717 | ||||
1718 | if (log) | |||
1719 | log->Printf ("NativeProcessLinux::%s inferior started, now in stopped state", __FUNCTION__); | |||
1720 | ||||
1721 | if (!SetDefaultPtraceOpts(pid)) | |||
1722 | { | |||
1723 | args->m_error.SetErrorToErrno(); | |||
1724 | if (log) | |||
1725 | log->Printf ("NativeProcessLinux::%s inferior failed to set default ptrace options: %s", | |||
1726 | __FUNCTION__, | |||
1727 | args->m_error.AsCString ()); | |||
1728 | ||||
1729 | // Mark the inferior as invalid. | |||
1730 | // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. | |||
1731 | monitor->SetState (StateType::eStateInvalid); | |||
1732 | ||||
1733 | return false; | |||
1734 | } | |||
1735 | ||||
1736 | // Release the master terminal descriptor and pass it off to the | |||
1737 | // NativeProcessLinux instance. Similarly stash the inferior pid. | |||
1738 | monitor->m_terminal_fd = terminal.ReleaseMasterFileDescriptor(); | |||
1739 | monitor->m_pid = pid; | |||
1740 | ||||
1741 | // Set the terminal fd to be in non blocking mode (it simplifies the | |||
1742 | // implementation of ProcessLinux::GetSTDOUT to have a non-blocking | |||
1743 | // descriptor to read from). | |||
1744 | if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK04000, args->m_error)) | |||
1745 | { | |||
1746 | if (log) | |||
1747 | log->Printf ("NativeProcessLinux::%s inferior EnsureFDFlags failed for ensuring terminal O_NONBLOCK setting: %s", | |||
1748 | __FUNCTION__, | |||
1749 | args->m_error.AsCString ()); | |||
1750 | ||||
1751 | // Mark the inferior as invalid. | |||
1752 | // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. | |||
1753 | monitor->SetState (StateType::eStateInvalid); | |||
1754 | ||||
1755 | return false; | |||
1756 | } | |||
1757 | ||||
1758 | if (log) | |||
1759 | log->Printf ("NativeProcessLinux::%s() adding pid = %" PRIu64"l" "u", __FUNCTION__, pid); | |||
1760 | ||||
1761 | thread_sp = monitor->AddThread (static_cast<lldb::tid_t> (pid)); | |||
1762 | assert (thread_sp && "AddThread() returned a nullptr thread")((thread_sp && "AddThread() returned a nullptr thread" ) ? static_cast<void> (0) : __assert_fail ("thread_sp && \"AddThread() returned a nullptr thread\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1762, __PRETTY_FUNCTION__)); | |||
1763 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (SIGSTOP19); | |||
1764 | monitor->SetCurrentThreadID (thread_sp->GetID ()); | |||
1765 | ||||
1766 | // Let our process instance know the thread has stopped. | |||
1767 | monitor->SetState (StateType::eStateStopped); | |||
1768 | ||||
1769 | if (log) | |||
1770 | { | |||
1771 | if (args->m_error.Success ()) | |||
1772 | { | |||
1773 | log->Printf ("NativeProcessLinux::%s inferior launching succeeded", __FUNCTION__); | |||
1774 | } | |||
1775 | else | |||
1776 | { | |||
1777 | log->Printf ("NativeProcessLinux::%s inferior launching failed: %s", | |||
1778 | __FUNCTION__, | |||
1779 | args->m_error.AsCString ()); | |||
1780 | } | |||
1781 | } | |||
1782 | return args->m_error.Success(); | |||
1783 | } | |||
1784 | ||||
1785 | void | |||
1786 | NativeProcessLinux::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error) | |||
1787 | { | |||
1788 | static const char *g_thread_name = "lldb.process.linux.operation"; | |||
1789 | ||||
1790 | if (m_operation_thread.IsJoinable()) | |||
1791 | return; | |||
1792 | ||||
1793 | m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args, &error); | |||
1794 | } | |||
1795 | ||||
1796 | void * | |||
1797 | NativeProcessLinux::AttachOpThread(void *arg) | |||
1798 | { | |||
1799 | AttachArgs *args = static_cast<AttachArgs*>(arg); | |||
1800 | ||||
1801 | if (!Attach(args)) { | |||
1802 | sem_post(&args->m_semaphore); | |||
1803 | return NULL__null; | |||
1804 | } | |||
1805 | ||||
1806 | ServeOperation(args); | |||
1807 | return NULL__null; | |||
1808 | } | |||
1809 | ||||
1810 | bool | |||
1811 | NativeProcessLinux::Attach(AttachArgs *args) | |||
1812 | { | |||
1813 | lldb::pid_t pid = args->m_pid; | |||
1814 | ||||
1815 | NativeProcessLinux *monitor = args->m_monitor; | |||
1816 | lldb::ThreadSP inferior; | |||
1817 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1818 | ||||
1819 | // Use a map to keep track of the threads which we have attached/need to attach. | |||
1820 | Host::TidMap tids_to_attach; | |||
1821 | if (pid <= 1) | |||
1822 | { | |||
1823 | args->m_error.SetErrorToGenericError(); | |||
1824 | args->m_error.SetErrorString("Attaching to process 1 is not allowed."); | |||
1825 | goto FINISH; | |||
1826 | } | |||
1827 | ||||
1828 | while (Host::FindProcessThreads(pid, tids_to_attach)) | |||
1829 | { | |||
1830 | for (Host::TidMap::iterator it = tids_to_attach.begin(); | |||
1831 | it != tids_to_attach.end();) | |||
1832 | { | |||
1833 | if (it->second == false) | |||
1834 | { | |||
1835 | lldb::tid_t tid = it->first; | |||
1836 | ||||
1837 | // Attach to the requested process. | |||
1838 | // An attach will cause the thread to stop with a SIGSTOP. | |||
1839 | if (PTRACE(PTRACE_ATTACH, tid, NULL, NULL, 0)PtraceWrapper((PTRACE_ATTACH), (tid), (__null), (__null), (0) , "PTRACE_ATTACH", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1839) < 0) | |||
1840 | { | |||
1841 | // No such thread. The thread may have exited. | |||
1842 | // More error handling may be needed. | |||
1843 | if (errno(*__errno_location ()) == ESRCH3) | |||
1844 | { | |||
1845 | it = tids_to_attach.erase(it); | |||
1846 | continue; | |||
1847 | } | |||
1848 | else | |||
1849 | { | |||
1850 | args->m_error.SetErrorToErrno(); | |||
1851 | goto FINISH; | |||
1852 | } | |||
1853 | } | |||
1854 | ||||
1855 | int status; | |||
1856 | // Need to use __WALL otherwise we receive an error with errno=ECHLD | |||
1857 | // At this point we should have a thread stopped if waitpid succeeds. | |||
1858 | if ((status = waitpid(tid, NULL__null, __WALL0x40000000)) < 0) | |||
1859 | { | |||
1860 | // No such thread. The thread may have exited. | |||
1861 | // More error handling may be needed. | |||
1862 | if (errno(*__errno_location ()) == ESRCH3) | |||
1863 | { | |||
1864 | it = tids_to_attach.erase(it); | |||
1865 | continue; | |||
1866 | } | |||
1867 | else | |||
1868 | { | |||
1869 | args->m_error.SetErrorToErrno(); | |||
1870 | goto FINISH; | |||
1871 | } | |||
1872 | } | |||
1873 | ||||
1874 | if (!SetDefaultPtraceOpts(tid)) | |||
1875 | { | |||
1876 | args->m_error.SetErrorToErrno(); | |||
1877 | goto FINISH; | |||
1878 | } | |||
1879 | ||||
1880 | ||||
1881 | if (log) | |||
1882 | log->Printf ("NativeProcessLinux::%s() adding tid = %" PRIu64"l" "u", __FUNCTION__, tid); | |||
1883 | ||||
1884 | it->second = true; | |||
1885 | ||||
1886 | // Create the thread, mark it as stopped. | |||
1887 | NativeThreadProtocolSP thread_sp (monitor->AddThread (static_cast<lldb::tid_t> (tid))); | |||
1888 | assert (thread_sp && "AddThread() returned a nullptr")((thread_sp && "AddThread() returned a nullptr") ? static_cast <void> (0) : __assert_fail ("thread_sp && \"AddThread() returned a nullptr\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1888, __PRETTY_FUNCTION__)); | |||
1889 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (SIGSTOP19); | |||
1890 | monitor->SetCurrentThreadID (thread_sp->GetID ()); | |||
1891 | } | |||
1892 | ||||
1893 | // move the loop forward | |||
1894 | ++it; | |||
1895 | } | |||
1896 | } | |||
1897 | ||||
1898 | if (tids_to_attach.size() > 0) | |||
1899 | { | |||
1900 | monitor->m_pid = pid; | |||
1901 | // Let our process instance know the thread has stopped. | |||
1902 | monitor->SetState (StateType::eStateStopped); | |||
1903 | } | |||
1904 | else | |||
1905 | { | |||
1906 | args->m_error.SetErrorToGenericError(); | |||
1907 | args->m_error.SetErrorString("No such process."); | |||
1908 | } | |||
1909 | ||||
1910 | FINISH: | |||
1911 | return args->m_error.Success(); | |||
1912 | } | |||
1913 | ||||
1914 | bool | |||
1915 | NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) | |||
1916 | { | |||
1917 | long ptrace_opts = 0; | |||
1918 | ||||
1919 | // Have the child raise an event on exit. This is used to keep the child in | |||
1920 | // limbo until it is destroyed. | |||
1921 | ptrace_opts |= PTRACE_O_TRACEEXIT; | |||
1922 | ||||
1923 | // Have the tracer trace threads which spawn in the inferior process. | |||
1924 | // TODO: if we want to support tracing the inferiors' child, add the | |||
1925 | // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK) | |||
1926 | ptrace_opts |= PTRACE_O_TRACECLONE; | |||
1927 | ||||
1928 | // Have the tracer notify us before execve returns | |||
1929 | // (needed to disable legacy SIGTRAP generation) | |||
1930 | ptrace_opts |= PTRACE_O_TRACEEXEC; | |||
1931 | ||||
1932 | return PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)ptrace_opts, 0)PtraceWrapper((PTRACE_SETOPTIONS), (pid), (__null), ((void*)ptrace_opts ), (0), "PTRACE_SETOPTIONS", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1932) >= 0; | |||
1933 | } | |||
1934 | ||||
1935 | static ExitType convert_pid_status_to_exit_type (int status) | |||
1936 | { | |||
1937 | if (WIFEXITED (status)((((*(int *) &(status))) & 0x7f) == 0)) | |||
1938 | return ExitType::eExitTypeExit; | |||
1939 | else if (WIFSIGNALED (status)(((signed char) ((((*(int *) &(status))) & 0x7f) + 1) >> 1) > 0)) | |||
1940 | return ExitType::eExitTypeSignal; | |||
1941 | else if (WIFSTOPPED (status)((((*(int *) &(status))) & 0xff) == 0x7f)) | |||
1942 | return ExitType::eExitTypeStop; | |||
1943 | else | |||
1944 | { | |||
1945 | // We don't know what this is. | |||
1946 | return ExitType::eExitTypeInvalid; | |||
1947 | } | |||
1948 | } | |||
1949 | ||||
1950 | static int convert_pid_status_to_return_code (int status) | |||
1951 | { | |||
1952 | if (WIFEXITED (status)((((*(int *) &(status))) & 0x7f) == 0)) | |||
1953 | return WEXITSTATUS (status)((((*(int *) &(status))) & 0xff00) >> 8); | |||
1954 | else if (WIFSIGNALED (status)(((signed char) ((((*(int *) &(status))) & 0x7f) + 1) >> 1) > 0)) | |||
1955 | return WTERMSIG (status)(((*(int *) &(status))) & 0x7f); | |||
1956 | else if (WIFSTOPPED (status)((((*(int *) &(status))) & 0xff) == 0x7f)) | |||
1957 | return WSTOPSIG (status)((((*(int *) &(status))) & 0xff00) >> 8); | |||
1958 | else | |||
1959 | { | |||
1960 | // We don't know what this is. | |||
1961 | return ExitType::eExitTypeInvalid; | |||
1962 | } | |||
1963 | } | |||
1964 | ||||
1965 | // Main process monitoring waitpid-loop handler. | |||
1966 | bool | |||
1967 | NativeProcessLinux::MonitorCallback(void *callback_baton, | |||
1968 | lldb::pid_t pid, | |||
1969 | bool exited, | |||
1970 | int signal, | |||
1971 | int status) | |||
1972 | { | |||
1973 | Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1974 | ||||
1975 | NativeProcessLinux *const process = static_cast<NativeProcessLinux*>(callback_baton); | |||
1976 | assert (process && "process is null")((process && "process is null") ? static_cast<void > (0) : __assert_fail ("process && \"process is null\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1976, __PRETTY_FUNCTION__)); | |||
1977 | if (!process) | |||
1978 | { | |||
1979 | if (log) | |||
1980 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " callback_baton was null, can't determine process to use", __FUNCTION__, pid); | |||
1981 | return true; | |||
1982 | } | |||
1983 | ||||
1984 | // Certain activities differ based on whether the pid is the tid of the main thread. | |||
1985 | const bool is_main_thread = (pid == process->GetID ()); | |||
1986 | ||||
1987 | // Assume we keep monitoring by default. | |||
1988 | bool stop_monitoring = false; | |||
1989 | ||||
1990 | // Handle when the thread exits. | |||
1991 | if (exited) | |||
1992 | { | |||
1993 | if (log) | |||
1994 | log->Printf ("NativeProcessLinux::%s() got exit signal, tid = %" PRIu64"l" "u" " (%s main thread)", __FUNCTION__, pid, is_main_thread ? "is" : "is not"); | |||
1995 | ||||
1996 | // This is a thread that exited. Ensure we're not tracking it anymore. | |||
1997 | const bool thread_found = process->StopTrackingThread (pid); | |||
1998 | ||||
1999 | if (is_main_thread) | |||
2000 | { | |||
2001 | // We only set the exit status and notify the delegate if we haven't already set the process | |||
2002 | // state to an exited state. We normally should have received a SIGTRAP | (PTRACE_EVENT_EXIT << 8) | |||
2003 | // for the main thread. | |||
2004 | const bool already_notified = (process->GetState() == StateType::eStateExited) | (process->GetState () == StateType::eStateCrashed); | |||
2005 | if (!already_notified) | |||
2006 | { | |||
2007 | if (log) | |||
2008 | log->Printf ("NativeProcessLinux::%s() tid = %" PRIu64"l" "u" " handling main thread exit (%s), expected exit state already set but state was %s instead, setting exit state now", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found", StateAsCString (process->GetState ())); | |||
2009 | // The main thread exited. We're done monitoring. Report to delegate. | |||
2010 | process->SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true); | |||
2011 | ||||
2012 | // Notify delegate that our process has exited. | |||
2013 | process->SetState (StateType::eStateExited, true); | |||
2014 | } | |||
2015 | else | |||
2016 | { | |||
2017 | if (log) | |||
2018 | log->Printf ("NativeProcessLinux::%s() tid = %" PRIu64"l" "u" " main thread now exited (%s)", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found"); | |||
2019 | } | |||
2020 | return true; | |||
2021 | } | |||
2022 | else | |||
2023 | { | |||
2024 | // Do we want to report to the delegate in this case? I think not. If this was an orderly | |||
2025 | // thread exit, we would already have received the SIGTRAP | (PTRACE_EVENT_EXIT << 8) signal, | |||
2026 | // and we would have done an all-stop then. | |||
2027 | if (log) | |||
2028 | log->Printf ("NativeProcessLinux::%s() tid = %" PRIu64"l" "u" " handling non-main thread exit (%s)", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found"); | |||
2029 | ||||
2030 | // Not the main thread, we keep going. | |||
2031 | return false; | |||
2032 | } | |||
2033 | } | |||
2034 | ||||
2035 | // Get details on the signal raised. | |||
2036 | siginfo_t info; | |||
2037 | int ptrace_err = 0; | |||
2038 | ||||
2039 | if (!process->GetSignalInfo (pid, &info, ptrace_err)) | |||
2040 | { | |||
2041 | if (ptrace_err == EINVAL22) | |||
2042 | { | |||
2043 | process->OnGroupStop (pid); | |||
2044 | } | |||
2045 | else | |||
2046 | { | |||
2047 | // ptrace(GETSIGINFO) failed (but not due to group-stop). | |||
2048 | ||||
2049 | // A return value of ESRCH means the thread/process is no longer on the system, | |||
2050 | // so it was killed somehow outside of our control. Either way, we can't do anything | |||
2051 | // with it anymore. | |||
2052 | ||||
2053 | // We stop monitoring if it was the main thread. | |||
2054 | stop_monitoring = is_main_thread; | |||
2055 | ||||
2056 | // Stop tracking the metadata for the thread since it's entirely off the system now. | |||
2057 | const bool thread_found = process->StopTrackingThread (pid); | |||
2058 | ||||
2059 | if (log) | |||
2060 | log->Printf ("NativeProcessLinux::%s GetSignalInfo failed: %s, tid = %" PRIu64"l" "u" ", signal = %d, status = %d (%s, %s, %s)", | |||
2061 | __FUNCTION__, strerror(ptrace_err), pid, signal, status, ptrace_err == ESRCH3 ? "thread/process killed" : "unknown reason", is_main_thread ? "is main thread" : "is not main thread", thread_found ? "thread metadata removed" : "thread metadata not found"); | |||
2062 | ||||
2063 | if (is_main_thread) | |||
2064 | { | |||
2065 | // Notify the delegate - our process is not available but appears to have been killed outside | |||
2066 | // our control. Is eStateExited the right exit state in this case? | |||
2067 | process->SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true); | |||
2068 | process->SetState (StateType::eStateExited, true); | |||
2069 | } | |||
2070 | else | |||
2071 | { | |||
2072 | // This thread was pulled out from underneath us. Anything to do here? Do we want to do an all stop? | |||
2073 | if (log) | |||
2074 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " non-main thread exit occurred, didn't tell delegate anything since thread disappeared out from underneath us", __FUNCTION__, process->GetID (), pid); | |||
2075 | } | |||
2076 | } | |||
2077 | } | |||
2078 | else | |||
2079 | { | |||
2080 | // We have retrieved the signal info. Dispatch appropriately. | |||
2081 | if (info.si_signo == SIGTRAP5) | |||
2082 | process->MonitorSIGTRAP(&info, pid); | |||
2083 | else | |||
2084 | process->MonitorSignal(&info, pid, exited); | |||
2085 | ||||
2086 | stop_monitoring = false; | |||
2087 | } | |||
2088 | ||||
2089 | return stop_monitoring; | |||
2090 | } | |||
2091 | ||||
2092 | void | |||
2093 | NativeProcessLinux::MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid) | |||
2094 | { | |||
2095 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2096 | const bool is_main_thread = (pid == GetID ()); | |||
2097 | ||||
2098 | assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!")((info && info->si_signo == 5 && "Unexpected child signal!" ) ? static_cast<void> (0) : __assert_fail ("info && info->si_signo == 5 && \"Unexpected child signal!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2098, __PRETTY_FUNCTION__)); | |||
2099 | if (!info) | |||
2100 | return; | |||
2101 | ||||
2102 | // See if we can find a thread for this signal. | |||
2103 | NativeThreadProtocolSP thread_sp = GetThreadByID (pid); | |||
2104 | if (!thread_sp) | |||
2105 | { | |||
2106 | if (log) | |||
2107 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" " no thread found for tid %" PRIu64"l" "u", __FUNCTION__, GetID (), pid); | |||
2108 | } | |||
2109 | ||||
2110 | switch (info->si_code) | |||
2111 | { | |||
2112 | // TODO: these two cases are required if we want to support tracing of the inferiors' children. We'd need this to debug a monitor. | |||
2113 | // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)): | |||
2114 | // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)): | |||
2115 | ||||
2116 | case (SIGTRAP5 | (PTRACE_EVENT_CLONE << 8)): | |||
2117 | { | |||
2118 | lldb::tid_t tid = LLDB_INVALID_THREAD_ID0; | |||
2119 | ||||
2120 | unsigned long event_message = 0; | |||
2121 | if (GetEventMessage(pid, &event_message)) | |||
2122 | tid = static_cast<lldb::tid_t> (event_message); | |||
2123 | ||||
2124 | if (log) | |||
2125 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" " received thread creation event for tid %" PRIu64"l" "u", __FUNCTION__, pid, tid); | |||
2126 | ||||
2127 | // If we don't track the thread yet: create it, mark as stopped. | |||
2128 | // If we do track it, this is the wait we needed. Now resume the new thread. | |||
2129 | // In all cases, resume the current (i.e. main process) thread. | |||
2130 | bool created_now = false; | |||
2131 | thread_sp = GetOrCreateThread (tid, created_now); | |||
2132 | assert (thread_sp.get() && "failed to get or create the tracking data for newly created inferior thread")((thread_sp.get() && "failed to get or create the tracking data for newly created inferior thread" ) ? static_cast<void> (0) : __assert_fail ("thread_sp.get() && \"failed to get or create the tracking data for newly created inferior thread\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2132, __PRETTY_FUNCTION__)); | |||
2133 | ||||
2134 | // If the thread was already tracked, it means the created thread already received its SI_USER notification of creation. | |||
2135 | if (!created_now) | |||
2136 | { | |||
2137 | // FIXME loops like we want to stop all theads here. | |||
2138 | // StopAllThreads | |||
2139 | ||||
2140 | // We can now resume the newly created thread since it is fully created. | |||
2141 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning (); | |||
2142 | Resume (tid, LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
2143 | } | |||
2144 | else | |||
2145 | { | |||
2146 | // Mark the thread as currently launching. Need to wait for SIGTRAP clone on the main thread before | |||
2147 | // this thread is ready to go. | |||
2148 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetLaunching (); | |||
2149 | } | |||
2150 | ||||
2151 | // In all cases, we can resume the main thread here. | |||
2152 | Resume (pid, LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
2153 | break; | |||
2154 | } | |||
2155 | ||||
2156 | case (SIGTRAP5 | (PTRACE_EVENT_EXEC << 8)): | |||
2157 | { | |||
2158 | NativeThreadProtocolSP main_thread_sp; | |||
2159 | ||||
2160 | if (log) | |||
2161 | log->Printf ("NativeProcessLinux::%s() received exec event, code = %d", __FUNCTION__, info->si_code ^ SIGTRAP5); | |||
2162 | ||||
2163 | // Remove all but the main thread here. | |||
2164 | // FIXME check if we really need to do this - how does ptrace behave under exec when multiple threads were present | |||
2165 | // before the exec? If we get all the detach signals right, we don't need to do this. However, it makes it clearer | |||
2166 | // what we should really be tracking. | |||
2167 | { | |||
2168 | Mutex::Locker locker (m_threads_mutex); | |||
2169 | ||||
2170 | if (log) | |||
2171 | log->Printf ("NativeProcessLinux::%s exec received, stop tracking all but main thread", __FUNCTION__); | |||
2172 | ||||
2173 | for (auto thread_sp : m_threads) | |||
2174 | { | |||
2175 | const bool is_main_thread = thread_sp && thread_sp->GetID () == GetID (); | |||
2176 | if (is_main_thread) | |||
2177 | { | |||
2178 | main_thread_sp = thread_sp; | |||
2179 | if (log) | |||
2180 | log->Printf ("NativeProcessLinux::%s found main thread with tid %" PRIu64"l" "u" ", keeping", __FUNCTION__, main_thread_sp->GetID ()); | |||
2181 | } | |||
2182 | else | |||
2183 | { | |||
2184 | if (log) | |||
2185 | log->Printf ("NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64"l" "u" " due to exec", __FUNCTION__, thread_sp->GetID ()); | |||
2186 | } | |||
2187 | } | |||
2188 | ||||
2189 | m_threads.clear (); | |||
2190 | ||||
2191 | if (main_thread_sp) | |||
2192 | { | |||
2193 | m_threads.push_back (main_thread_sp); | |||
2194 | SetCurrentThreadID (main_thread_sp->GetID ()); | |||
2195 | reinterpret_cast<NativeThreadLinux*>(main_thread_sp.get())->SetStoppedByExec (); | |||
2196 | } | |||
2197 | else | |||
2198 | { | |||
2199 | SetCurrentThreadID (LLDB_INVALID_THREAD_ID0); | |||
2200 | if (log) | |||
2201 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" "no main thread found, discarded all threads, we're in a no-thread state!", __FUNCTION__, GetID ()); | |||
2202 | } | |||
2203 | } | |||
2204 | ||||
2205 | // Let our delegate know we have just exec'd. | |||
2206 | NotifyDidExec (); | |||
2207 | ||||
2208 | // If we have a main thread, indicate we are stopped. | |||
2209 | assert (main_thread_sp && "exec called during ptraced process but no main thread metadata tracked")((main_thread_sp && "exec called during ptraced process but no main thread metadata tracked" ) ? static_cast<void> (0) : __assert_fail ("main_thread_sp && \"exec called during ptraced process but no main thread metadata tracked\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2209, __PRETTY_FUNCTION__)); | |||
2210 | SetState (StateType::eStateStopped); | |||
2211 | ||||
2212 | break; | |||
2213 | } | |||
2214 | ||||
2215 | case (SIGTRAP5 | (PTRACE_EVENT_EXIT << 8)): | |||
2216 | { | |||
2217 | // The inferior process or one of its threads is about to exit. | |||
2218 | unsigned long data = 0; | |||
2219 | if (!GetEventMessage(pid, &data)) | |||
2220 | data = -1; | |||
2221 | ||||
2222 | if (log) | |||
2223 | { | |||
2224 | log->Printf ("NativeProcessLinux::%s() received PTRACE_EVENT_EXIT, data = %lx (WIFEXITED=%s,WIFSIGNALED=%s), pid = %" PRIu64"l" "u" " (%s)", | |||
2225 | __FUNCTION__, | |||
2226 | data, WIFEXITED (data)((((*(int *) &(data))) & 0x7f) == 0) ? "true" : "false", WIFSIGNALED (data)(((signed char) ((((*(int *) &(data))) & 0x7f) + 1) >> 1) > 0) ? "true" : "false", | |||
2227 | pid, | |||
2228 | is_main_thread ? "is main thread" : "not main thread"); | |||
2229 | } | |||
2230 | ||||
2231 | // Set the thread to exited. | |||
2232 | if (thread_sp) | |||
2233 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetExited (); | |||
2234 | else | |||
2235 | { | |||
2236 | if (log) | |||
2237 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" " failed to retrieve thread for tid %" PRIu64"l" "u"", cannot set thread state", __FUNCTION__, GetID (), pid); | |||
2238 | } | |||
2239 | ||||
2240 | if (is_main_thread) | |||
2241 | { | |||
2242 | SetExitStatus (convert_pid_status_to_exit_type (data), convert_pid_status_to_return_code (data), nullptr, true); | |||
2243 | } | |||
2244 | ||||
2245 | // Resume the thread so it completely exits. | |||
2246 | Resume (pid, LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
2247 | ||||
2248 | break; | |||
2249 | } | |||
2250 | ||||
2251 | case 0: | |||
2252 | case TRAP_TRACETRAP_TRACE: | |||
2253 | // We receive this on single stepping. | |||
2254 | if (log) | |||
2255 | log->Printf ("NativeProcessLinux::%s() received trace event, pid = %" PRIu64"l" "u" " (single stepping)", __FUNCTION__, pid); | |||
2256 | ||||
2257 | if (thread_sp) | |||
2258 | { | |||
2259 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (SIGTRAP5); | |||
2260 | SetCurrentThreadID (thread_sp->GetID ()); | |||
2261 | } | |||
2262 | else | |||
2263 | { | |||
2264 | if (log) | |||
2265 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " single stepping received trace but thread not found", __FUNCTION__, GetID (), pid); | |||
2266 | } | |||
2267 | ||||
2268 | // Tell the process we have a stop (from single stepping). | |||
2269 | SetState (StateType::eStateStopped, true); | |||
2270 | break; | |||
2271 | ||||
2272 | case SI_KERNELSI_KERNEL: | |||
2273 | case TRAP_BRKPTTRAP_BRKPT: | |||
2274 | if (log) | |||
2275 | log->Printf ("NativeProcessLinux::%s() received breakpoint event, pid = %" PRIu64"l" "u", __FUNCTION__, pid); | |||
2276 | ||||
2277 | // Mark the thread as stopped at breakpoint. | |||
2278 | if (thread_sp) | |||
2279 | { | |||
2280 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (SIGTRAP5); | |||
2281 | Error error = FixupBreakpointPCAsNeeded (thread_sp); | |||
2282 | if (error.Fail ()) | |||
2283 | { | |||
2284 | if (log) | |||
2285 | log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64"l" "u" " fixup: %s", __FUNCTION__, pid, error.AsCString ()); | |||
2286 | } | |||
2287 | } | |||
2288 | else | |||
2289 | { | |||
2290 | if (log) | |||
2291 | log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64"l" "u" ": warning, cannot process software breakpoint since no thread metadata", __FUNCTION__, pid); | |||
2292 | } | |||
2293 | ||||
2294 | ||||
2295 | // Tell the process we have a stop from this thread. | |||
2296 | SetCurrentThreadID (pid); | |||
2297 | SetState (StateType::eStateStopped, true); | |||
2298 | break; | |||
2299 | ||||
2300 | case TRAP_HWBKPT4: | |||
2301 | if (log) | |||
2302 | log->Printf ("NativeProcessLinux::%s() received watchpoint event, pid = %" PRIu64"l" "u", __FUNCTION__, pid); | |||
2303 | ||||
2304 | // Mark the thread as stopped at watchpoint. | |||
2305 | // The address is at (lldb::addr_t)info->si_addr if we need it. | |||
2306 | if (thread_sp) | |||
2307 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (SIGTRAP5); | |||
2308 | else | |||
2309 | { | |||
2310 | if (log) | |||
2311 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ": warning, cannot process hardware breakpoint since no thread metadata", __FUNCTION__, GetID (), pid); | |||
2312 | } | |||
2313 | ||||
2314 | // Tell the process we have a stop from this thread. | |||
2315 | SetCurrentThreadID (pid); | |||
2316 | SetState (StateType::eStateStopped, true); | |||
2317 | break; | |||
2318 | ||||
2319 | case SIGTRAP5: | |||
2320 | case (SIGTRAP5 | 0x80): | |||
2321 | if (log) | |||
2322 | log->Printf ("NativeProcessLinux::%s() received system call stop event, pid %" PRIu64"l" "u" "tid %" PRIu64"l" "u", __FUNCTION__, GetID (), pid); | |||
2323 | // Ignore these signals until we know more about them. | |||
2324 | Resume(pid, 0); | |||
2325 | break; | |||
2326 | ||||
2327 | default: | |||
2328 | assert(false && "Unexpected SIGTRAP code!")((false && "Unexpected SIGTRAP code!") ? static_cast< void> (0) : __assert_fail ("false && \"Unexpected SIGTRAP code!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2328, __PRETTY_FUNCTION__)); | |||
2329 | if (log) | |||
2330 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" "tid %" PRIu64"l" "u" " received unhandled SIGTRAP code: 0x%" PRIx64"l" "x", __FUNCTION__, GetID (), pid, static_cast<uint64_t> (SIGTRAP5 | (PTRACE_EVENT_CLONE << 8))); | |||
2331 | break; | |||
2332 | ||||
2333 | } | |||
2334 | } | |||
2335 | ||||
2336 | void | |||
2337 | NativeProcessLinux::MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool exited) | |||
2338 | { | |||
2339 | assert (info && "null info")((info && "null info") ? static_cast<void> (0) : __assert_fail ("info && \"null info\"", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2339, __PRETTY_FUNCTION__)); | |||
2340 | if (!info) | |||
| ||||
2341 | return; | |||
2342 | ||||
2343 | const int signo = info->si_signo; | |||
2344 | const bool is_from_llgs = info->si_pid_sifields._kill.si_pid == getpid (); | |||
2345 | ||||
2346 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2347 | ||||
2348 | // POSIX says that process behaviour is undefined after it ignores a SIGFPE, | |||
2349 | // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a | |||
2350 | // kill(2) or raise(3). Similarly for tgkill(2) on Linux. | |||
2351 | // | |||
2352 | // IOW, user generated signals never generate what we consider to be a | |||
2353 | // "crash". | |||
2354 | // | |||
2355 | // Similarly, ACK signals generated by this monitor. | |||
2356 | ||||
2357 | // See if we can find a thread for this signal. | |||
2358 | NativeThreadProtocolSP thread_sp = GetThreadByID (pid); | |||
2359 | if (!thread_sp) | |||
2360 | { | |||
2361 | if (log) | |||
2362 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" " no thread found for tid %" PRIu64"l" "u", __FUNCTION__, GetID (), pid); | |||
2363 | } | |||
2364 | ||||
2365 | // Handle the signal. | |||
2366 | if (info->si_code == SI_TKILLSI_TKILL || info->si_code == SI_USERSI_USER) | |||
2367 | { | |||
2368 | if (log) | |||
2369 | log->Printf ("NativeProcessLinux::%s() received signal %s (%d) with code %s, (siginfo pid = %d (%s), waitpid pid = %" PRIu64"l" "u" ")", | |||
2370 | __FUNCTION__, | |||
2371 | GetUnixSignals ().GetSignalAsCString (signo), | |||
2372 | signo, | |||
2373 | (info->si_code == SI_TKILLSI_TKILL ? "SI_TKILL" : "SI_USER"), | |||
2374 | info->si_pid_sifields._kill.si_pid, | |||
2375 | is_from_llgs ? "from llgs" : "not from llgs", | |||
2376 | pid); | |||
2377 | } | |||
2378 | ||||
2379 | // Check for new thread notification. | |||
2380 | if ((info->si_pid_sifields._kill.si_pid == 0) && (info->si_code == SI_USERSI_USER)) | |||
2381 | { | |||
2382 | // A new thread creation is being signaled. This is one of two parts that come in | |||
2383 | // a non-deterministic order. pid is the thread id. | |||
2384 | if (log) | |||
2385 | log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ": new thread notification", | |||
2386 | __FUNCTION__, GetID (), pid); | |||
2387 | ||||
2388 | // Did we already create the thread? | |||
2389 | bool created_now = false; | |||
2390 | thread_sp = GetOrCreateThread (pid, created_now); | |||
2391 | assert (thread_sp.get() && "failed to get or create the tracking data for newly created inferior thread")((thread_sp.get() && "failed to get or create the tracking data for newly created inferior thread" ) ? static_cast<void> (0) : __assert_fail ("thread_sp.get() && \"failed to get or create the tracking data for newly created inferior thread\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2391, __PRETTY_FUNCTION__)); | |||
2392 | ||||
2393 | // If the thread was already tracked, it means the main thread already received its SIGTRAP for the create. | |||
2394 | if (!created_now) | |||
2395 | { | |||
2396 | // We can now resume this thread up since it is fully created. | |||
2397 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning (); | |||
2398 | Resume (thread_sp->GetID (), LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
2399 | } | |||
2400 | else | |||
2401 | { | |||
2402 | // Mark the thread as currently launching. Need to wait for SIGTRAP clone on the main thread before | |||
2403 | // this thread is ready to go. | |||
2404 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetLaunching (); | |||
2405 | } | |||
2406 | ||||
2407 | // Done handling. | |||
2408 | return; | |||
2409 | } | |||
2410 | ||||
2411 | // Check for thread stop notification. | |||
2412 | if (is_from_llgs && (info->si_code == SI_TKILLSI_TKILL) && (signo == SIGSTOP19)) | |||
2413 | { | |||
2414 | // This is a tgkill()-based stop. | |||
2415 | if (thread_sp) | |||
2416 | { | |||
2417 | // An inferior thread just stopped. Mark it as such. | |||
2418 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (signo); | |||
2419 | SetCurrentThreadID (thread_sp->GetID ()); | |||
2420 | ||||
2421 | // Remove this tid from the wait-for-stop set. | |||
2422 | Mutex::Locker locker (m_wait_for_stop_tids_mutex); | |||
2423 | ||||
2424 | auto removed_count = m_wait_for_stop_tids.erase (thread_sp->GetID ()); | |||
2425 | if (removed_count < 1) | |||
2426 | { | |||
2427 | log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ": tgkill()-stopped thread not in m_wait_for_stop_tids", | |||
| ||||
2428 | __FUNCTION__, GetID (), thread_sp->GetID ()); | |||
2429 | ||||
2430 | } | |||
2431 | ||||
2432 | // If this is the last thread in the m_wait_for_stop_tids, we need to notify | |||
2433 | // the delegate that a stop has occurred now that every thread that was supposed | |||
2434 | // to stop has stopped. | |||
2435 | if (m_wait_for_stop_tids.empty ()) | |||
2436 | { | |||
2437 | if (log) | |||
2438 | { | |||
2439 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ", setting process state to stopped now that all tids marked for stop have completed", | |||
2440 | __FUNCTION__, | |||
2441 | GetID (), | |||
2442 | pid); | |||
2443 | } | |||
2444 | SetState (StateType::eStateStopped, true); | |||
2445 | } | |||
2446 | } | |||
2447 | ||||
2448 | // Done handling. | |||
2449 | return; | |||
2450 | } | |||
2451 | ||||
2452 | if (log) | |||
2453 | log->Printf ("NativeProcessLinux::%s() received signal %s", __FUNCTION__, GetUnixSignals ().GetSignalAsCString (signo)); | |||
2454 | ||||
2455 | switch (signo) | |||
2456 | { | |||
2457 | case SIGSEGV11: | |||
2458 | { | |||
2459 | lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr_sifields._sigfault.si_addr); | |||
2460 | ||||
2461 | // FIXME figure out how to propagate this properly. Seems like it | |||
2462 | // should go in ThreadStopInfo. | |||
2463 | // We can get more details on the exact nature of the crash here. | |||
2464 | // ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info); | |||
2465 | if (!exited) | |||
2466 | { | |||
2467 | // This is just a pre-signal-delivery notification of the incoming signal. | |||
2468 | // Send a stop to the debugger. | |||
2469 | if (thread_sp) | |||
2470 | { | |||
2471 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (signo); | |||
2472 | SetCurrentThreadID (thread_sp->GetID ()); | |||
2473 | } | |||
2474 | SetState (StateType::eStateStopped, true); | |||
2475 | } | |||
2476 | else | |||
2477 | { | |||
2478 | if (thread_sp) | |||
2479 | { | |||
2480 | // FIXME figure out what type this is. | |||
2481 | const uint64_t exception_type = static_cast<uint64_t> (SIGSEGV11); | |||
2482 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetCrashedWithException (exception_type, fault_addr); | |||
2483 | } | |||
2484 | SetState (StateType::eStateCrashed, true); | |||
2485 | } | |||
2486 | } | |||
2487 | break; | |||
2488 | ||||
2489 | case SIGABRT6: | |||
2490 | case SIGILL4: | |||
2491 | case SIGFPE8: | |||
2492 | case SIGBUS7: | |||
2493 | { | |||
2494 | // Break these out into separate cases once I have more data for each type of signal. | |||
2495 | lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr_sifields._sigfault.si_addr); | |||
2496 | if (!exited) | |||
2497 | { | |||
2498 | // This is just a pre-signal-delivery notification of the incoming signal. | |||
2499 | // Send a stop to the debugger. | |||
2500 | if (thread_sp) | |||
2501 | { | |||
2502 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (signo); | |||
2503 | SetCurrentThreadID (thread_sp->GetID ()); | |||
2504 | } | |||
2505 | SetState (StateType::eStateStopped, true); | |||
2506 | } | |||
2507 | else | |||
2508 | { | |||
2509 | if (thread_sp) | |||
2510 | { | |||
2511 | // FIXME figure out how to report exit by signal correctly. | |||
2512 | const uint64_t exception_type = static_cast<uint64_t> (SIGABRT6); | |||
2513 | reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetCrashedWithException (exception_type, fault_addr); | |||
2514 | } | |||
2515 | SetState (StateType::eStateCrashed, true); | |||
2516 | } | |||
2517 | } | |||
2518 | break; | |||
2519 | ||||
2520 | case SIGSTOP19: | |||
2521 | { | |||
2522 | if (log) | |||
2523 | { | |||
2524 | if (is_from_llgs) | |||
2525 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " received SIGSTOP from llgs, most likely an interrupt", __FUNCTION__, GetID (), pid); | |||
2526 | else | |||
2527 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " received SIGSTOP from outside of debugger", __FUNCTION__, GetID (), pid); | |||
2528 | } | |||
2529 | ||||
2530 | // Save group stop tids to wait for. | |||
2531 | SetGroupStopTids (pid, SIGSTOP19); | |||
2532 | // Fall through to deliver signal to thread. | |||
2533 | // This will trigger a group stop sequence, after which we'll notify the process that everything stopped. | |||
2534 | } | |||
2535 | ||||
2536 | default: | |||
2537 | { | |||
2538 | if (log) | |||
2539 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " resuming thread with signal %s (%d)", __FUNCTION__, GetID (), pid, GetUnixSignals().GetSignalAsCString (signo), signo); | |||
2540 | ||||
2541 | // Pass the signal on to the inferior. | |||
2542 | const bool resume_success = Resume (pid, signo); | |||
2543 | ||||
2544 | if (log) | |||
2545 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " resume %s", __FUNCTION__, GetID (), pid, resume_success ? "SUCCESS" : "FAILURE"); | |||
2546 | ||||
2547 | } | |||
2548 | break; | |||
2549 | } | |||
2550 | } | |||
2551 | ||||
2552 | void | |||
2553 | NativeProcessLinux::SetGroupStopTids (lldb::tid_t signaled_thread_tid, int signo) | |||
2554 | { | |||
2555 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD(1u << 2))); | |||
2556 | ||||
2557 | // Lock 1 - thread lock. | |||
2558 | { | |||
2559 | Mutex::Locker locker (m_threads_mutex); | |||
2560 | // Lock 2 - group stop tids | |||
2561 | { | |||
2562 | Mutex::Locker locker (m_wait_for_group_stop_tids_mutex); | |||
2563 | if (log) | |||
2564 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " loading up known threads in set%s", | |||
2565 | __FUNCTION__, | |||
2566 | GetID (), | |||
2567 | signaled_thread_tid, | |||
2568 | m_wait_for_group_stop_tids.empty () ? " (currently empty)" | |||
2569 | : "(group_stop_tids not empty?!?)"); | |||
2570 | ||||
2571 | // Add all known threads not already stopped into the wait for group-stop tids. | |||
2572 | for (auto thread_sp : m_threads) | |||
2573 | { | |||
2574 | int unused_signo = LLDB_INVALID_SIGNAL_NUMBER(2147483647); | |||
2575 | if (thread_sp && !((NativeThreadLinux*)thread_sp.get())->IsStopped (&unused_signo)) | |||
2576 | { | |||
2577 | // Wait on this thread for a group stop before we notify the delegate about the process state change. | |||
2578 | m_wait_for_group_stop_tids.insert (thread_sp->GetID ()); | |||
2579 | } | |||
2580 | } | |||
2581 | ||||
2582 | m_group_stop_signal_tid = signaled_thread_tid; | |||
2583 | m_group_stop_signal = signo; | |||
2584 | } | |||
2585 | } | |||
2586 | } | |||
2587 | ||||
2588 | void | |||
2589 | NativeProcessLinux::OnGroupStop (lldb::tid_t tid) | |||
2590 | { | |||
2591 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD(1u << 2))); | |||
2592 | bool should_tell_delegate = false; | |||
2593 | ||||
2594 | // Lock 1 - thread lock. | |||
2595 | { | |||
2596 | Mutex::Locker locker (m_threads_mutex); | |||
2597 | // Lock 2 - group stop tids | |||
2598 | { | |||
2599 | Mutex::Locker locker (m_wait_for_group_stop_tids_mutex); | |||
2600 | ||||
2601 | // Remove this thread from the set. | |||
2602 | auto remove_result = m_wait_for_group_stop_tids.erase (tid); | |||
2603 | if (log) | |||
2604 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " tried to remove tid from group-stop set: %s", | |||
2605 | __FUNCTION__, | |||
2606 | GetID (), | |||
2607 | tid, | |||
2608 | remove_result > 0 ? "SUCCESS" : "FAILURE"); | |||
2609 | ||||
2610 | // Grab the thread metadata for this thread. | |||
2611 | NativeThreadProtocolSP thread_sp = GetThreadByIDUnlocked (tid); | |||
2612 | if (thread_sp) | |||
2613 | { | |||
2614 | NativeThreadLinux *const linux_thread = static_cast<NativeThreadLinux*> (thread_sp.get ()); | |||
2615 | if (thread_sp->GetID () == m_group_stop_signal_tid) | |||
2616 | { | |||
2617 | linux_thread->SetStoppedBySignal (m_group_stop_signal); | |||
2618 | if (log) | |||
2619 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " set group stop tid to state 'stopped by signal %d'", | |||
2620 | __FUNCTION__, | |||
2621 | GetID (), | |||
2622 | tid, | |||
2623 | m_group_stop_signal); | |||
2624 | } | |||
2625 | else | |||
2626 | { | |||
2627 | int stopping_signal = LLDB_INVALID_SIGNAL_NUMBER(2147483647); | |||
2628 | if (linux_thread->IsStopped (&stopping_signal)) | |||
2629 | { | |||
2630 | if (log) | |||
2631 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " thread is already stopped with signal %d, not clearing", | |||
2632 | __FUNCTION__, | |||
2633 | GetID (), | |||
2634 | tid, | |||
2635 | stopping_signal); | |||
2636 | ||||
2637 | } | |||
2638 | else | |||
2639 | { | |||
2640 | linux_thread->SetStoppedBySignal (0); | |||
2641 | if (log) | |||
2642 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " set stopped by signal with signal 0 (i.e. debugger-initiated stop)", | |||
2643 | __FUNCTION__, | |||
2644 | GetID (), | |||
2645 | tid); | |||
2646 | ||||
2647 | } | |||
2648 | } | |||
2649 | } | |||
2650 | else | |||
2651 | { | |||
2652 | if (log) | |||
2653 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " WARNING failed to find thread metadata for tid", | |||
2654 | __FUNCTION__, | |||
2655 | GetID (), | |||
2656 | tid); | |||
2657 | ||||
2658 | } | |||
2659 | ||||
2660 | // If there are no more threads we're waiting on for group stop, signal the process. | |||
2661 | if (m_wait_for_group_stop_tids.empty ()) | |||
2662 | { | |||
2663 | if (log) | |||
2664 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " done waiting for group stop, will notify delegate of process state change", | |||
2665 | __FUNCTION__, | |||
2666 | GetID (), | |||
2667 | tid); | |||
2668 | ||||
2669 | SetCurrentThreadID (m_group_stop_signal_tid); | |||
2670 | ||||
2671 | // Tell the delegate about the stop event, after we release our mutexes. | |||
2672 | should_tell_delegate = true; | |||
2673 | } | |||
2674 | } | |||
2675 | } | |||
2676 | ||||
2677 | // If we're ready to broadcast the process event change, do it now that we're no longer | |||
2678 | // holding any locks. Note this does introduce a potential race, we should think about | |||
2679 | // adding a notification queue. | |||
2680 | if (should_tell_delegate) | |||
2681 | { | |||
2682 | if (log) | |||
2683 | log->Printf ("NativeProcessLinux::%s pid = %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " done waiting for group stop, notifying delegate of process state change", | |||
2684 | __FUNCTION__, | |||
2685 | GetID (), | |||
2686 | tid); | |||
2687 | SetState (StateType::eStateStopped, true); | |||
2688 | } | |||
2689 | } | |||
2690 | ||||
2691 | Error | |||
2692 | NativeProcessLinux::Resume (const ResumeActionList &resume_actions) | |||
2693 | { | |||
2694 | Error error; | |||
2695 | ||||
2696 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_THREAD(1u << 2))); | |||
2697 | if (log) | |||
2698 | log->Printf ("NativeProcessLinux::%s called: pid %" PRIu64"l" "u", __FUNCTION__, GetID ()); | |||
2699 | ||||
2700 | int run_thread_count = 0; | |||
2701 | int stop_thread_count = 0; | |||
2702 | int step_thread_count = 0; | |||
2703 | ||||
2704 | std::vector<NativeThreadProtocolSP> new_stop_threads; | |||
2705 | ||||
2706 | Mutex::Locker locker (m_threads_mutex); | |||
2707 | for (auto thread_sp : m_threads) | |||
2708 | { | |||
2709 | assert (thread_sp && "thread list should not contain NULL threads")((thread_sp && "thread list should not contain NULL threads" ) ? static_cast<void> (0) : __assert_fail ("thread_sp && \"thread list should not contain NULL threads\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2709, __PRETTY_FUNCTION__)); | |||
2710 | NativeThreadLinux *const linux_thread_p = reinterpret_cast<NativeThreadLinux*> (thread_sp.get ()); | |||
2711 | ||||
2712 | const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true); | |||
2713 | assert (action && "NULL ResumeAction returned for thread during Resume ()")((action && "NULL ResumeAction returned for thread during Resume ()" ) ? static_cast<void> (0) : __assert_fail ("action && \"NULL ResumeAction returned for thread during Resume ()\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2713, __PRETTY_FUNCTION__)); | |||
2714 | ||||
2715 | if (log) | |||
2716 | { | |||
2717 | log->Printf ("NativeProcessLinux::%s processing resume action state %s for pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u", | |||
2718 | __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ()); | |||
2719 | } | |||
2720 | ||||
2721 | switch (action->state) | |||
2722 | { | |||
2723 | case eStateRunning: | |||
2724 | // Run the thread, possibly feeding it the signal. | |||
2725 | linux_thread_p->SetRunning (); | |||
2726 | if (action->signal > 0) | |||
2727 | { | |||
2728 | // Resume the thread and deliver the given signal, | |||
2729 | // then mark as delivered. | |||
2730 | Resume (thread_sp->GetID (), action->signal); | |||
2731 | resume_actions.SetSignalHandledForThread (thread_sp->GetID ()); | |||
2732 | } | |||
2733 | else | |||
2734 | { | |||
2735 | // Just resume the thread with no signal. | |||
2736 | Resume (thread_sp->GetID (), LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
2737 | } | |||
2738 | ++run_thread_count; | |||
2739 | break; | |||
2740 | ||||
2741 | case eStateStepping: | |||
2742 | // Note: if we have multiple threads, we may need to stop | |||
2743 | // the other threads first, then step this one. | |||
2744 | linux_thread_p->SetStepping (); | |||
2745 | if (SingleStep (thread_sp->GetID (), 0)) | |||
2746 | { | |||
2747 | if (log) | |||
2748 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " single step succeeded", | |||
2749 | __FUNCTION__, GetID (), thread_sp->GetID ()); | |||
2750 | } | |||
2751 | else | |||
2752 | { | |||
2753 | if (log) | |||
2754 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " single step failed", | |||
2755 | __FUNCTION__, GetID (), thread_sp->GetID ()); | |||
2756 | } | |||
2757 | ++step_thread_count; | |||
2758 | break; | |||
2759 | ||||
2760 | case eStateSuspended: | |||
2761 | case eStateStopped: | |||
2762 | if (!StateIsStoppedState (linux_thread_p->GetState (), false)) | |||
2763 | new_stop_threads.push_back (thread_sp); | |||
2764 | else | |||
2765 | { | |||
2766 | if (log) | |||
2767 | log->Printf ("NativeProcessLinux::%s no need to stop pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ", thread state already %s", | |||
2768 | __FUNCTION__, GetID (), thread_sp->GetID (), StateAsCString (linux_thread_p->GetState ())); | |||
2769 | } | |||
2770 | ||||
2771 | ++stop_thread_count; | |||
2772 | break; | |||
2773 | ||||
2774 | default: | |||
2775 | return Error ("NativeProcessLinux::%s (): unexpected state %s specified for pid %" PRIu64"l" "u" ", tid %" PRIu64"l" "u", | |||
2776 | __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ()); | |||
2777 | } | |||
2778 | } | |||
2779 | ||||
2780 | // If any thread was set to run, notify the process state as running. | |||
2781 | if (run_thread_count > 0) | |||
2782 | SetState (StateType::eStateRunning, true); | |||
2783 | ||||
2784 | // Now do a tgkill SIGSTOP on each thread we want to stop. | |||
2785 | if (!new_stop_threads.empty ()) | |||
2786 | { | |||
2787 | // Lock the m_wait_for_stop_tids set so we can fill it with every thread we expect to have stopped. | |||
2788 | Mutex::Locker stop_thread_id_locker (m_wait_for_stop_tids_mutex); | |||
2789 | for (auto thread_sp : new_stop_threads) | |||
2790 | { | |||
2791 | // Send a stop signal to the thread. | |||
2792 | const int result = tgkill (GetID (), thread_sp->GetID (), SIGSTOP)syscall(234, GetID (), thread_sp->GetID (), 19); | |||
2793 | if (result != 0) | |||
2794 | { | |||
2795 | // tgkill failed. | |||
2796 | if (log) | |||
2797 | log->Printf ("NativeProcessLinux::%s error: tgkill SIGSTOP for pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" "failed, retval %d", | |||
2798 | __FUNCTION__, GetID (), thread_sp->GetID (), result); | |||
2799 | } | |||
2800 | else | |||
2801 | { | |||
2802 | // tgkill succeeded. Don't mark the thread state, though. Let the signal | |||
2803 | // handling mark it. | |||
2804 | if (log) | |||
2805 | log->Printf ("NativeProcessLinux::%s tgkill SIGSTOP for pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" " succeeded", | |||
2806 | __FUNCTION__, GetID (), thread_sp->GetID ()); | |||
2807 | ||||
2808 | // Add it to the set of threads we expect to signal a stop. | |||
2809 | // We won't tell the delegate about it until this list drains to empty. | |||
2810 | m_wait_for_stop_tids.insert (thread_sp->GetID ()); | |||
2811 | } | |||
2812 | } | |||
2813 | } | |||
2814 | ||||
2815 | return error; | |||
2816 | } | |||
2817 | ||||
2818 | Error | |||
2819 | NativeProcessLinux::Halt () | |||
2820 | { | |||
2821 | Error error; | |||
2822 | ||||
2823 | // FIXME check if we're already stopped | |||
2824 | const bool is_stopped = false; | |||
2825 | if (is_stopped) | |||
2826 | return error; | |||
2827 | ||||
2828 | if (kill (GetID (), SIGSTOP19) != 0) | |||
2829 | error.SetErrorToErrno (); | |||
2830 | ||||
2831 | return error; | |||
2832 | } | |||
2833 | ||||
2834 | Error | |||
2835 | NativeProcessLinux::Detach () | |||
2836 | { | |||
2837 | Error error; | |||
2838 | ||||
2839 | // Tell ptrace to detach from the process. | |||
2840 | if (GetID () != LLDB_INVALID_PROCESS_ID0) | |||
2841 | error = Detach (GetID ()); | |||
2842 | ||||
2843 | // Stop monitoring the inferior. | |||
2844 | StopMonitor (); | |||
2845 | ||||
2846 | // No error. | |||
2847 | return error; | |||
2848 | } | |||
2849 | ||||
2850 | Error | |||
2851 | NativeProcessLinux::Signal (int signo) | |||
2852 | { | |||
2853 | Error error; | |||
2854 | ||||
2855 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2856 | if (log) | |||
2857 | log->Printf ("NativeProcessLinux::%s: sending signal %d (%s) to pid %" PRIu64"l" "u", | |||
2858 | __FUNCTION__, signo, GetUnixSignals ().GetSignalAsCString (signo), GetID ()); | |||
2859 | ||||
2860 | if (kill(GetID(), signo)) | |||
2861 | error.SetErrorToErrno(); | |||
2862 | ||||
2863 | return error; | |||
2864 | } | |||
2865 | ||||
2866 | Error | |||
2867 | NativeProcessLinux::Kill () | |||
2868 | { | |||
2869 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2870 | if (log) | |||
2871 | log->Printf ("NativeProcessLinux::%s called for PID %" PRIu64"l" "u", __FUNCTION__, GetID ()); | |||
2872 | ||||
2873 | Error error; | |||
2874 | ||||
2875 | switch (m_state) | |||
2876 | { | |||
2877 | case StateType::eStateInvalid: | |||
2878 | case StateType::eStateExited: | |||
2879 | case StateType::eStateCrashed: | |||
2880 | case StateType::eStateDetached: | |||
2881 | case StateType::eStateUnloaded: | |||
2882 | // Nothing to do - the process is already dead. | |||
2883 | if (log) | |||
2884 | log->Printf ("NativeProcessLinux::%s ignored for PID %" PRIu64"l" "u" " due to current state: %s", __FUNCTION__, GetID (), StateAsCString (m_state)); | |||
2885 | return error; | |||
2886 | ||||
2887 | case StateType::eStateConnected: | |||
2888 | case StateType::eStateAttaching: | |||
2889 | case StateType::eStateLaunching: | |||
2890 | case StateType::eStateStopped: | |||
2891 | case StateType::eStateRunning: | |||
2892 | case StateType::eStateStepping: | |||
2893 | case StateType::eStateSuspended: | |||
2894 | // We can try to kill a process in these states. | |||
2895 | break; | |||
2896 | } | |||
2897 | ||||
2898 | if (kill (GetID (), SIGKILL9) != 0) | |||
2899 | { | |||
2900 | error.SetErrorToErrno (); | |||
2901 | return error; | |||
2902 | } | |||
2903 | ||||
2904 | return error; | |||
2905 | } | |||
2906 | ||||
2907 | static Error | |||
2908 | ParseMemoryRegionInfoFromProcMapsLine (const std::string &maps_line, MemoryRegionInfo &memory_region_info) | |||
2909 | { | |||
2910 | memory_region_info.Clear(); | |||
2911 | ||||
2912 | StringExtractor line_extractor (maps_line.c_str ()); | |||
2913 | ||||
2914 | // Format: {address_start_hex}-{address_end_hex} perms offset dev inode pathname | |||
2915 | // perms: rwxp (letter is present if set, '-' if not, final character is p=private, s=shared). | |||
2916 | ||||
2917 | // Parse out the starting address | |||
2918 | lldb::addr_t start_address = line_extractor.GetHexMaxU64 (false, 0); | |||
2919 | ||||
2920 | // Parse out hyphen separating start and end address from range. | |||
2921 | if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != '-')) | |||
2922 | return Error ("malformed /proc/{pid}/maps entry, missing dash between address range"); | |||
2923 | ||||
2924 | // Parse out the ending address | |||
2925 | lldb::addr_t end_address = line_extractor.GetHexMaxU64 (false, start_address); | |||
2926 | ||||
2927 | // Parse out the space after the address. | |||
2928 | if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != ' ')) | |||
2929 | return Error ("malformed /proc/{pid}/maps entry, missing space after range"); | |||
2930 | ||||
2931 | // Save the range. | |||
2932 | memory_region_info.GetRange ().SetRangeBase (start_address); | |||
2933 | memory_region_info.GetRange ().SetRangeEnd (end_address); | |||
2934 | ||||
2935 | // Parse out each permission entry. | |||
2936 | if (line_extractor.GetBytesLeft () < 4) | |||
2937 | return Error ("malformed /proc/{pid}/maps entry, missing some portion of permissions"); | |||
2938 | ||||
2939 | // Handle read permission. | |||
2940 | const char read_perm_char = line_extractor.GetChar (); | |||
2941 | if (read_perm_char == 'r') | |||
2942 | memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eYes); | |||
2943 | else | |||
2944 | { | |||
2945 | assert ( (read_perm_char == '-') && "unexpected /proc/{pid}/maps read permission char" )(((read_perm_char == '-') && "unexpected /proc/{pid}/maps read permission char" ) ? static_cast<void> (0) : __assert_fail ("(read_perm_char == '-') && \"unexpected /proc/{pid}/maps read permission char\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2945, __PRETTY_FUNCTION__)); | |||
2946 | memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); | |||
2947 | } | |||
2948 | ||||
2949 | // Handle write permission. | |||
2950 | const char write_perm_char = line_extractor.GetChar (); | |||
2951 | if (write_perm_char == 'w') | |||
2952 | memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eYes); | |||
2953 | else | |||
2954 | { | |||
2955 | assert ( (write_perm_char == '-') && "unexpected /proc/{pid}/maps write permission char" )(((write_perm_char == '-') && "unexpected /proc/{pid}/maps write permission char" ) ? static_cast<void> (0) : __assert_fail ("(write_perm_char == '-') && \"unexpected /proc/{pid}/maps write permission char\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2955, __PRETTY_FUNCTION__)); | |||
2956 | memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); | |||
2957 | } | |||
2958 | ||||
2959 | // Handle execute permission. | |||
2960 | const char exec_perm_char = line_extractor.GetChar (); | |||
2961 | if (exec_perm_char == 'x') | |||
2962 | memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eYes); | |||
2963 | else | |||
2964 | { | |||
2965 | assert ( (exec_perm_char == '-') && "unexpected /proc/{pid}/maps exec permission char" )(((exec_perm_char == '-') && "unexpected /proc/{pid}/maps exec permission char" ) ? static_cast<void> (0) : __assert_fail ("(exec_perm_char == '-') && \"unexpected /proc/{pid}/maps exec permission char\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2965, __PRETTY_FUNCTION__)); | |||
2966 | memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); | |||
2967 | } | |||
2968 | ||||
2969 | return Error (); | |||
2970 | } | |||
2971 | ||||
2972 | Error | |||
2973 | NativeProcessLinux::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) | |||
2974 | { | |||
2975 | // FIXME review that the final memory region returned extends to the end of the virtual address space, | |||
2976 | // with no perms if it is not mapped. | |||
2977 | ||||
2978 | // Use an approach that reads memory regions from /proc/{pid}/maps. | |||
2979 | // Assume proc maps entries are in ascending order. | |||
2980 | // FIXME assert if we find differently. | |||
2981 | Mutex::Locker locker (m_mem_region_cache_mutex); | |||
2982 | ||||
2983 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2984 | Error error; | |||
2985 | ||||
2986 | if (m_supports_mem_region == LazyBool::eLazyBoolNo) | |||
2987 | { | |||
2988 | // We're done. | |||
2989 | error.SetErrorString ("unsupported"); | |||
2990 | return error; | |||
2991 | } | |||
2992 | ||||
2993 | // If our cache is empty, pull the latest. There should always be at least one memory region | |||
2994 | // if memory region handling is supported. | |||
2995 | if (m_mem_region_cache.empty ()) | |||
2996 | { | |||
2997 | error = ProcFileReader::ProcessLineByLine (GetID (), "maps", | |||
2998 | [&] (const std::string &line) -> bool | |||
2999 | { | |||
3000 | MemoryRegionInfo info; | |||
3001 | const Error parse_error = ParseMemoryRegionInfoFromProcMapsLine (line, info); | |||
3002 | if (parse_error.Success ()) | |||
3003 | { | |||
3004 | m_mem_region_cache.push_back (info); | |||
3005 | return true; | |||
3006 | } | |||
3007 | else | |||
3008 | { | |||
3009 | if (log) | |||
3010 | log->Printf ("NativeProcessLinux::%s failed to parse proc maps line '%s': %s", __FUNCTION__, line.c_str (), error.AsCString ()); | |||
3011 | return false; | |||
3012 | } | |||
3013 | }); | |||
3014 | ||||
3015 | // If we had an error, we'll mark unsupported. | |||
3016 | if (error.Fail ()) | |||
3017 | { | |||
3018 | m_supports_mem_region = LazyBool::eLazyBoolNo; | |||
3019 | return error; | |||
3020 | } | |||
3021 | else if (m_mem_region_cache.empty ()) | |||
3022 | { | |||
3023 | // No entries after attempting to read them. This shouldn't happen if /proc/{pid}/maps | |||
3024 | // is supported. Assume we don't support map entries via procfs. | |||
3025 | if (log) | |||
3026 | log->Printf ("NativeProcessLinux::%s failed to find any procfs maps entries, assuming no support for memory region metadata retrieval", __FUNCTION__); | |||
3027 | m_supports_mem_region = LazyBool::eLazyBoolNo; | |||
3028 | error.SetErrorString ("not supported"); | |||
3029 | return error; | |||
3030 | } | |||
3031 | ||||
3032 | if (log) | |||
3033 | log->Printf ("NativeProcessLinux::%s read %" PRIu64"l" "u" " memory region entries from /proc/%" PRIu64"l" "u" "/maps", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ()), GetID ()); | |||
3034 | ||||
3035 | // We support memory retrieval, remember that. | |||
3036 | m_supports_mem_region = LazyBool::eLazyBoolYes; | |||
3037 | } | |||
3038 | else | |||
3039 | { | |||
3040 | if (log) | |||
3041 | log->Printf ("NativeProcessLinux::%s reusing %" PRIu64"l" "u" " cached memory region entries", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ())); | |||
3042 | } | |||
3043 | ||||
3044 | lldb::addr_t prev_base_address = 0; | |||
3045 | ||||
3046 | // FIXME start by finding the last region that is <= target address using binary search. Data is sorted. | |||
3047 | // There can be a ton of regions on pthreads apps with lots of threads. | |||
3048 | for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end (); ++it) | |||
3049 | { | |||
3050 | MemoryRegionInfo &proc_entry_info = *it; | |||
3051 | ||||
3052 | // Sanity check assumption that /proc/{pid}/maps entries are ascending. | |||
3053 | assert ((proc_entry_info.GetRange ().GetRangeBase () >= prev_base_address) && "descending /proc/pid/maps entries detected, unexpected")(((proc_entry_info.GetRange ().GetRangeBase () >= prev_base_address ) && "descending /proc/pid/maps entries detected, unexpected" ) ? static_cast<void> (0) : __assert_fail ("(proc_entry_info.GetRange ().GetRangeBase () >= prev_base_address) && \"descending /proc/pid/maps entries detected, unexpected\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3053, __PRETTY_FUNCTION__)); | |||
3054 | prev_base_address = proc_entry_info.GetRange ().GetRangeBase (); | |||
3055 | ||||
3056 | // If the target address comes before this entry, indicate distance to next region. | |||
3057 | if (load_addr < proc_entry_info.GetRange ().GetRangeBase ()) | |||
3058 | { | |||
3059 | range_info.GetRange ().SetRangeBase (load_addr); | |||
3060 | range_info.GetRange ().SetByteSize (proc_entry_info.GetRange ().GetRangeBase () - load_addr); | |||
3061 | range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); | |||
3062 | range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); | |||
3063 | range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); | |||
3064 | ||||
3065 | return error; | |||
3066 | } | |||
3067 | else if (proc_entry_info.GetRange ().Contains (load_addr)) | |||
3068 | { | |||
3069 | // The target address is within the memory region we're processing here. | |||
3070 | range_info = proc_entry_info; | |||
3071 | return error; | |||
3072 | } | |||
3073 | ||||
3074 | // The target memory address comes somewhere after the region we just parsed. | |||
3075 | } | |||
3076 | ||||
3077 | // If we made it here, we didn't find an entry that contained the given address. | |||
3078 | error.SetErrorString ("address comes after final region"); | |||
3079 | ||||
3080 | if (log) | |||
3081 | log->Printf ("NativeProcessLinux::%s failed to find map entry for address 0x%" PRIx64"l" "x" ": %s", __FUNCTION__, load_addr, error.AsCString ()); | |||
3082 | ||||
3083 | return error; | |||
3084 | } | |||
3085 | ||||
3086 | void | |||
3087 | NativeProcessLinux::DoStopIDBumped (uint32_t newBumpId) | |||
3088 | { | |||
3089 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
3090 | if (log) | |||
3091 | log->Printf ("NativeProcessLinux::%s(newBumpId=%" PRIu32"u" ") called", __FUNCTION__, newBumpId); | |||
3092 | ||||
3093 | { | |||
3094 | Mutex::Locker locker (m_mem_region_cache_mutex); | |||
3095 | if (log) | |||
3096 | log->Printf ("NativeProcessLinux::%s clearing %" PRIu64"l" "u" " entries from the cache", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ())); | |||
3097 | m_mem_region_cache.clear (); | |||
3098 | } | |||
3099 | } | |||
3100 | ||||
3101 | Error | |||
3102 | NativeProcessLinux::AllocateMemory ( | |||
3103 | lldb::addr_t size, | |||
3104 | uint32_t permissions, | |||
3105 | lldb::addr_t &addr) | |||
3106 | { | |||
3107 | // FIXME implementing this requires the equivalent of | |||
3108 | // InferiorCallPOSIX::InferiorCallMmap, which depends on | |||
3109 | // functional ThreadPlans working with Native*Protocol. | |||
3110 | #if 1 | |||
3111 | return Error ("not implemented yet"); | |||
3112 | #else | |||
3113 | addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3114 | ||||
3115 | unsigned prot = 0; | |||
3116 | if (permissions & lldb::ePermissionsReadable) | |||
3117 | prot |= eMmapProtRead; | |||
3118 | if (permissions & lldb::ePermissionsWritable) | |||
3119 | prot |= eMmapProtWrite; | |||
3120 | if (permissions & lldb::ePermissionsExecutable) | |||
3121 | prot |= eMmapProtExec; | |||
3122 | ||||
3123 | // TODO implement this directly in NativeProcessLinux | |||
3124 | // (and lift to NativeProcessPOSIX if/when that class is | |||
3125 | // refactored out). | |||
3126 | if (InferiorCallMmap(this, addr, 0, size, prot, | |||
3127 | eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { | |||
3128 | m_addr_to_mmap_size[addr] = size; | |||
3129 | return Error (); | |||
3130 | } else { | |||
3131 | addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3132 | return Error("unable to allocate %" PRIu64"l" "u" " bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); | |||
3133 | } | |||
3134 | #endif | |||
3135 | } | |||
3136 | ||||
3137 | Error | |||
3138 | NativeProcessLinux::DeallocateMemory (lldb::addr_t addr) | |||
3139 | { | |||
3140 | // FIXME see comments in AllocateMemory - required lower-level | |||
3141 | // bits not in place yet (ThreadPlans) | |||
3142 | return Error ("not implemented"); | |||
3143 | } | |||
3144 | ||||
3145 | lldb::addr_t | |||
3146 | NativeProcessLinux::GetSharedLibraryInfoAddress () | |||
3147 | { | |||
3148 | #if 1 | |||
3149 | // punt on this for now | |||
3150 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3151 | #else | |||
3152 | // Return the image info address for the exe module | |||
3153 | #if 1 | |||
3154 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
3155 | ||||
3156 | ModuleSP module_sp; | |||
3157 | Error error = GetExeModuleSP (module_sp); | |||
3158 | if (error.Fail ()) | |||
3159 | { | |||
3160 | if (log) | |||
3161 | log->Warning ("NativeProcessLinux::%s failed to retrieve exe module: %s", __FUNCTION__, error.AsCString ()); | |||
3162 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3163 | } | |||
3164 | ||||
3165 | if (module_sp == nullptr) | |||
3166 | { | |||
3167 | if (log) | |||
3168 | log->Warning ("NativeProcessLinux::%s exe module returned was NULL", __FUNCTION__); | |||
3169 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3170 | } | |||
3171 | ||||
3172 | ObjectFileSP object_file_sp = module_sp->GetObjectFile (); | |||
3173 | if (object_file_sp == nullptr) | |||
3174 | { | |||
3175 | if (log) | |||
3176 | log->Warning ("NativeProcessLinux::%s exe module returned a NULL object file", __FUNCTION__); | |||
3177 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3178 | } | |||
3179 | ||||
3180 | return obj_file_sp->GetImageInfoAddress(); | |||
3181 | #else | |||
3182 | Target *target = &GetTarget(); | |||
3183 | ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); | |||
3184 | Address addr = obj_file->GetImageInfoAddress(target); | |||
3185 | ||||
3186 | if (addr.IsValid()) | |||
3187 | return addr.GetLoadAddress(target); | |||
3188 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3189 | #endif | |||
3190 | #endif // punt on this for now | |||
3191 | } | |||
3192 | ||||
3193 | size_t | |||
3194 | NativeProcessLinux::UpdateThreads () | |||
3195 | { | |||
3196 | // The NativeProcessLinux monitoring threads are always up to date | |||
3197 | // with respect to thread state and they keep the thread list | |||
3198 | // populated properly. All this method needs to do is return the | |||
3199 | // thread count. | |||
3200 | Mutex::Locker locker (m_threads_mutex); | |||
3201 | return m_threads.size (); | |||
3202 | } | |||
3203 | ||||
3204 | bool | |||
3205 | NativeProcessLinux::GetArchitecture (ArchSpec &arch) const | |||
3206 | { | |||
3207 | arch = m_arch; | |||
3208 | return true; | |||
3209 | } | |||
3210 | ||||
3211 | Error | |||
3212 | NativeProcessLinux::GetSoftwareBreakpointSize (NativeRegisterContextSP context_sp, uint32_t &actual_opcode_size) | |||
3213 | { | |||
3214 | // FIXME put this behind a breakpoint protocol class that can be | |||
3215 | // set per architecture. Need ARM, MIPS support here. | |||
3216 | static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 }; | |||
3217 | static const uint8_t g_i386_opcode [] = { 0xCC }; | |||
3218 | ||||
3219 | switch (m_arch.GetMachine ()) | |||
3220 | { | |||
3221 | case llvm::Triple::aarch64: | |||
3222 | actual_opcode_size = static_cast<uint32_t> (sizeof(g_aarch64_opcode)); | |||
3223 | return Error (); | |||
3224 | ||||
3225 | case llvm::Triple::x86: | |||
3226 | case llvm::Triple::x86_64: | |||
3227 | actual_opcode_size = static_cast<uint32_t> (sizeof(g_i386_opcode)); | |||
3228 | return Error (); | |||
3229 | ||||
3230 | default: | |||
3231 | assert(false && "CPU type not supported!")((false && "CPU type not supported!") ? static_cast< void> (0) : __assert_fail ("false && \"CPU type not supported!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3231, __PRETTY_FUNCTION__)); | |||
3232 | return Error ("CPU type not supported"); | |||
3233 | } | |||
3234 | } | |||
3235 | ||||
3236 | Error | |||
3237 | NativeProcessLinux::SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) | |||
3238 | { | |||
3239 | if (hardware) | |||
3240 | return Error ("NativeProcessLinux does not support hardware breakpoints"); | |||
3241 | else | |||
3242 | return SetSoftwareBreakpoint (addr, size); | |||
3243 | } | |||
3244 | ||||
3245 | Error | |||
3246 | NativeProcessLinux::GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) | |||
3247 | { | |||
3248 | // FIXME put this behind a breakpoint protocol class that can be | |||
3249 | // set per architecture. Need ARM, MIPS support here. | |||
3250 | static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 }; | |||
3251 | static const uint8_t g_i386_opcode [] = { 0xCC }; | |||
3252 | ||||
3253 | switch (m_arch.GetMachine ()) | |||
3254 | { | |||
3255 | case llvm::Triple::aarch64: | |||
3256 | trap_opcode_bytes = g_aarch64_opcode; | |||
3257 | actual_opcode_size = sizeof(g_aarch64_opcode); | |||
3258 | return Error (); | |||
3259 | ||||
3260 | case llvm::Triple::x86: | |||
3261 | case llvm::Triple::x86_64: | |||
3262 | trap_opcode_bytes = g_i386_opcode; | |||
3263 | actual_opcode_size = sizeof(g_i386_opcode); | |||
3264 | return Error (); | |||
3265 | ||||
3266 | default: | |||
3267 | assert(false && "CPU type not supported!")((false && "CPU type not supported!") ? static_cast< void> (0) : __assert_fail ("false && \"CPU type not supported!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3267, __PRETTY_FUNCTION__)); | |||
3268 | return Error ("CPU type not supported"); | |||
3269 | } | |||
3270 | } | |||
3271 | ||||
3272 | #if 0 | |||
3273 | ProcessMessage::CrashReason | |||
3274 | NativeProcessLinux::GetCrashReasonForSIGSEGV(const siginfo_t *info) | |||
3275 | { | |||
3276 | ProcessMessage::CrashReason reason; | |||
3277 | assert(info->si_signo == SIGSEGV)((info->si_signo == 11) ? static_cast<void> (0) : __assert_fail ("info->si_signo == 11", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3277, __PRETTY_FUNCTION__)); | |||
3278 | ||||
3279 | reason = ProcessMessage::eInvalidCrashReason; | |||
3280 | ||||
3281 | switch (info->si_code) | |||
3282 | { | |||
3283 | default: | |||
3284 | assert(false && "unexpected si_code for SIGSEGV")((false && "unexpected si_code for SIGSEGV") ? static_cast <void> (0) : __assert_fail ("false && \"unexpected si_code for SIGSEGV\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3284, __PRETTY_FUNCTION__)); | |||
3285 | break; | |||
3286 | case SI_KERNELSI_KERNEL: | |||
3287 | // Linux will occasionally send spurious SI_KERNEL codes. | |||
3288 | // (this is poorly documented in sigaction) | |||
3289 | // One way to get this is via unaligned SIMD loads. | |||
3290 | reason = ProcessMessage::eInvalidAddress; // for lack of anything better | |||
3291 | break; | |||
3292 | case SEGV_MAPERRSEGV_MAPERR: | |||
3293 | reason = ProcessMessage::eInvalidAddress; | |||
3294 | break; | |||
3295 | case SEGV_ACCERRSEGV_ACCERR: | |||
3296 | reason = ProcessMessage::ePrivilegedAddress; | |||
3297 | break; | |||
3298 | } | |||
3299 | ||||
3300 | return reason; | |||
3301 | } | |||
3302 | #endif | |||
3303 | ||||
3304 | ||||
3305 | #if 0 | |||
3306 | ProcessMessage::CrashReason | |||
3307 | NativeProcessLinux::GetCrashReasonForSIGILL(const siginfo_t *info) | |||
3308 | { | |||
3309 | ProcessMessage::CrashReason reason; | |||
3310 | assert(info->si_signo == SIGILL)((info->si_signo == 4) ? static_cast<void> (0) : __assert_fail ("info->si_signo == 4", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3310, __PRETTY_FUNCTION__)); | |||
3311 | ||||
3312 | reason = ProcessMessage::eInvalidCrashReason; | |||
3313 | ||||
3314 | switch (info->si_code) | |||
3315 | { | |||
3316 | default: | |||
3317 | assert(false && "unexpected si_code for SIGILL")((false && "unexpected si_code for SIGILL") ? static_cast <void> (0) : __assert_fail ("false && \"unexpected si_code for SIGILL\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3317, __PRETTY_FUNCTION__)); | |||
3318 | break; | |||
3319 | case ILL_ILLOPCILL_ILLOPC: | |||
3320 | reason = ProcessMessage::eIllegalOpcode; | |||
3321 | break; | |||
3322 | case ILL_ILLOPNILL_ILLOPN: | |||
3323 | reason = ProcessMessage::eIllegalOperand; | |||
3324 | break; | |||
3325 | case ILL_ILLADRILL_ILLADR: | |||
3326 | reason = ProcessMessage::eIllegalAddressingMode; | |||
3327 | break; | |||
3328 | case ILL_ILLTRPILL_ILLTRP: | |||
3329 | reason = ProcessMessage::eIllegalTrap; | |||
3330 | break; | |||
3331 | case ILL_PRVOPCILL_PRVOPC: | |||
3332 | reason = ProcessMessage::ePrivilegedOpcode; | |||
3333 | break; | |||
3334 | case ILL_PRVREGILL_PRVREG: | |||
3335 | reason = ProcessMessage::ePrivilegedRegister; | |||
3336 | break; | |||
3337 | case ILL_COPROCILL_COPROC: | |||
3338 | reason = ProcessMessage::eCoprocessorError; | |||
3339 | break; | |||
3340 | case ILL_BADSTKILL_BADSTK: | |||
3341 | reason = ProcessMessage::eInternalStackError; | |||
3342 | break; | |||
3343 | } | |||
3344 | ||||
3345 | return reason; | |||
3346 | } | |||
3347 | #endif | |||
3348 | ||||
3349 | #if 0 | |||
3350 | ProcessMessage::CrashReason | |||
3351 | NativeProcessLinux::GetCrashReasonForSIGFPE(const siginfo_t *info) | |||
3352 | { | |||
3353 | ProcessMessage::CrashReason reason; | |||
3354 | assert(info->si_signo == SIGFPE)((info->si_signo == 8) ? static_cast<void> (0) : __assert_fail ("info->si_signo == 8", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3354, __PRETTY_FUNCTION__)); | |||
3355 | ||||
3356 | reason = ProcessMessage::eInvalidCrashReason; | |||
3357 | ||||
3358 | switch (info->si_code) | |||
3359 | { | |||
3360 | default: | |||
3361 | assert(false && "unexpected si_code for SIGFPE")((false && "unexpected si_code for SIGFPE") ? static_cast <void> (0) : __assert_fail ("false && \"unexpected si_code for SIGFPE\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3361, __PRETTY_FUNCTION__)); | |||
3362 | break; | |||
3363 | case FPE_INTDIVFPE_INTDIV: | |||
3364 | reason = ProcessMessage::eIntegerDivideByZero; | |||
3365 | break; | |||
3366 | case FPE_INTOVFFPE_INTOVF: | |||
3367 | reason = ProcessMessage::eIntegerOverflow; | |||
3368 | break; | |||
3369 | case FPE_FLTDIVFPE_FLTDIV: | |||
3370 | reason = ProcessMessage::eFloatDivideByZero; | |||
3371 | break; | |||
3372 | case FPE_FLTOVFFPE_FLTOVF: | |||
3373 | reason = ProcessMessage::eFloatOverflow; | |||
3374 | break; | |||
3375 | case FPE_FLTUNDFPE_FLTUND: | |||
3376 | reason = ProcessMessage::eFloatUnderflow; | |||
3377 | break; | |||
3378 | case FPE_FLTRESFPE_FLTRES: | |||
3379 | reason = ProcessMessage::eFloatInexactResult; | |||
3380 | break; | |||
3381 | case FPE_FLTINVFPE_FLTINV: | |||
3382 | reason = ProcessMessage::eFloatInvalidOperation; | |||
3383 | break; | |||
3384 | case FPE_FLTSUBFPE_FLTSUB: | |||
3385 | reason = ProcessMessage::eFloatSubscriptRange; | |||
3386 | break; | |||
3387 | } | |||
3388 | ||||
3389 | return reason; | |||
3390 | } | |||
3391 | #endif | |||
3392 | ||||
3393 | #if 0 | |||
3394 | ProcessMessage::CrashReason | |||
3395 | NativeProcessLinux::GetCrashReasonForSIGBUS(const siginfo_t *info) | |||
3396 | { | |||
3397 | ProcessMessage::CrashReason reason; | |||
3398 | assert(info->si_signo == SIGBUS)((info->si_signo == 7) ? static_cast<void> (0) : __assert_fail ("info->si_signo == 7", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3398, __PRETTY_FUNCTION__)); | |||
3399 | ||||
3400 | reason = ProcessMessage::eInvalidCrashReason; | |||
3401 | ||||
3402 | switch (info->si_code) | |||
3403 | { | |||
3404 | default: | |||
3405 | assert(false && "unexpected si_code for SIGBUS")((false && "unexpected si_code for SIGBUS") ? static_cast <void> (0) : __assert_fail ("false && \"unexpected si_code for SIGBUS\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3405, __PRETTY_FUNCTION__)); | |||
3406 | break; | |||
3407 | case BUS_ADRALNBUS_ADRALN: | |||
3408 | reason = ProcessMessage::eIllegalAlignment; | |||
3409 | break; | |||
3410 | case BUS_ADRERRBUS_ADRERR: | |||
3411 | reason = ProcessMessage::eIllegalAddress; | |||
3412 | break; | |||
3413 | case BUS_OBJERRBUS_OBJERR: | |||
3414 | reason = ProcessMessage::eHardwareError; | |||
3415 | break; | |||
3416 | } | |||
3417 | ||||
3418 | return reason; | |||
3419 | } | |||
3420 | #endif | |||
3421 | ||||
3422 | void | |||
3423 | NativeProcessLinux::ServeOperation(OperationArgs *args) | |||
3424 | { | |||
3425 | NativeProcessLinux *monitor = args->m_monitor; | |||
3426 | ||||
3427 | // We are finised with the arguments and are ready to go. Sync with the | |||
3428 | // parent thread and start serving operations on the inferior. | |||
3429 | sem_post(&args->m_semaphore); | |||
3430 | ||||
3431 | for(;;) | |||
3432 | { | |||
3433 | // wait for next pending operation | |||
3434 | if (sem_wait(&monitor->m_operation_pending)) | |||
3435 | { | |||
3436 | if (errno(*__errno_location ()) == EINTR4) | |||
3437 | continue; | |||
3438 | assert(false && "Unexpected errno from sem_wait")((false && "Unexpected errno from sem_wait") ? static_cast <void> (0) : __assert_fail ("false && \"Unexpected errno from sem_wait\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3438, __PRETTY_FUNCTION__)); | |||
3439 | } | |||
3440 | ||||
3441 | reinterpret_cast<Operation*>(monitor->m_operation)->Execute(monitor); | |||
3442 | ||||
3443 | // notify calling thread that operation is complete | |||
3444 | sem_post(&monitor->m_operation_done); | |||
3445 | } | |||
3446 | } | |||
3447 | ||||
3448 | void | |||
3449 | NativeProcessLinux::DoOperation(void *op) | |||
3450 | { | |||
3451 | Mutex::Locker lock(m_operation_mutex); | |||
3452 | ||||
3453 | m_operation = op; | |||
3454 | ||||
3455 | // notify operation thread that an operation is ready to be processed | |||
3456 | sem_post(&m_operation_pending); | |||
3457 | ||||
3458 | // wait for operation to complete | |||
3459 | while (sem_wait(&m_operation_done)) | |||
3460 | { | |||
3461 | if (errno(*__errno_location ()) == EINTR4) | |||
3462 | continue; | |||
3463 | assert(false && "Unexpected errno from sem_wait")((false && "Unexpected errno from sem_wait") ? static_cast <void> (0) : __assert_fail ("false && \"Unexpected errno from sem_wait\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3463, __PRETTY_FUNCTION__)); | |||
3464 | } | |||
3465 | } | |||
3466 | ||||
3467 | Error | |||
3468 | NativeProcessLinux::ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) | |||
3469 | { | |||
3470 | ReadOperation op(addr, buf, size, bytes_read); | |||
3471 | DoOperation(&op); | |||
3472 | return op.GetError (); | |||
3473 | } | |||
3474 | ||||
3475 | Error | |||
3476 | NativeProcessLinux::WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) | |||
3477 | { | |||
3478 | WriteOperation op(addr, buf, size, bytes_written); | |||
3479 | DoOperation(&op); | |||
3480 | return op.GetError (); | |||
3481 | } | |||
3482 | ||||
3483 | bool | |||
3484 | NativeProcessLinux::ReadRegisterValue(lldb::tid_t tid, uint32_t offset, const char* reg_name, | |||
3485 | uint32_t size, RegisterValue &value) | |||
3486 | { | |||
3487 | bool result; | |||
3488 | ReadRegOperation op(tid, offset, reg_name, value, result); | |||
3489 | DoOperation(&op); | |||
3490 | return result; | |||
3491 | } | |||
3492 | ||||
3493 | bool | |||
3494 | NativeProcessLinux::WriteRegisterValue(lldb::tid_t tid, unsigned offset, | |||
3495 | const char* reg_name, const RegisterValue &value) | |||
3496 | { | |||
3497 | bool result; | |||
3498 | WriteRegOperation op(tid, offset, reg_name, value, result); | |||
3499 | DoOperation(&op); | |||
3500 | return result; | |||
3501 | } | |||
3502 | ||||
3503 | bool | |||
3504 | NativeProcessLinux::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size) | |||
3505 | { | |||
3506 | bool result; | |||
3507 | ReadGPROperation op(tid, buf, buf_size, result); | |||
3508 | DoOperation(&op); | |||
3509 | return result; | |||
3510 | } | |||
3511 | ||||
3512 | bool | |||
3513 | NativeProcessLinux::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size) | |||
3514 | { | |||
3515 | bool result; | |||
3516 | ReadFPROperation op(tid, buf, buf_size, result); | |||
3517 | DoOperation(&op); | |||
3518 | return result; | |||
3519 | } | |||
3520 | ||||
3521 | bool | |||
3522 | NativeProcessLinux::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) | |||
3523 | { | |||
3524 | bool result; | |||
3525 | ReadRegisterSetOperation op(tid, buf, buf_size, regset, result); | |||
3526 | DoOperation(&op); | |||
3527 | return result; | |||
3528 | } | |||
3529 | ||||
3530 | bool | |||
3531 | NativeProcessLinux::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size) | |||
3532 | { | |||
3533 | bool result; | |||
3534 | WriteGPROperation op(tid, buf, buf_size, result); | |||
3535 | DoOperation(&op); | |||
3536 | return result; | |||
3537 | } | |||
3538 | ||||
3539 | bool | |||
3540 | NativeProcessLinux::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size) | |||
3541 | { | |||
3542 | bool result; | |||
3543 | WriteFPROperation op(tid, buf, buf_size, result); | |||
3544 | DoOperation(&op); | |||
3545 | return result; | |||
3546 | } | |||
3547 | ||||
3548 | bool | |||
3549 | NativeProcessLinux::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) | |||
3550 | { | |||
3551 | bool result; | |||
3552 | WriteRegisterSetOperation op(tid, buf, buf_size, regset, result); | |||
3553 | DoOperation(&op); | |||
3554 | return result; | |||
3555 | } | |||
3556 | ||||
3557 | bool | |||
3558 | NativeProcessLinux::Resume (lldb::tid_t tid, uint32_t signo) | |||
3559 | { | |||
3560 | bool result; | |||
3561 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
3562 | ||||
3563 | if (log) | |||
3564 | log->Printf ("NativeProcessLinux::%s() resuming thread = %" PRIu64"l" "u" " with signal %s", __FUNCTION__, tid, | |||
3565 | GetUnixSignals().GetSignalAsCString (signo)); | |||
3566 | ResumeOperation op (tid, signo, result); | |||
3567 | DoOperation (&op); | |||
3568 | if (log) | |||
3569 | log->Printf ("NativeProcessLinux::%s() resuming result = %s", __FUNCTION__, result ? "true" : "false"); | |||
3570 | return result; | |||
3571 | } | |||
3572 | ||||
3573 | bool | |||
3574 | NativeProcessLinux::SingleStep(lldb::tid_t tid, uint32_t signo) | |||
3575 | { | |||
3576 | bool result; | |||
3577 | SingleStepOperation op(tid, signo, result); | |||
3578 | DoOperation(&op); | |||
3579 | return result; | |||
3580 | } | |||
3581 | ||||
3582 | bool | |||
3583 | NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err) | |||
3584 | { | |||
3585 | bool result; | |||
3586 | SiginfoOperation op(tid, siginfo, result, ptrace_err); | |||
3587 | DoOperation(&op); | |||
3588 | return result; | |||
3589 | } | |||
3590 | ||||
3591 | bool | |||
3592 | NativeProcessLinux::GetEventMessage(lldb::tid_t tid, unsigned long *message) | |||
3593 | { | |||
3594 | bool result; | |||
3595 | EventMessageOperation op(tid, message, result); | |||
3596 | DoOperation(&op); | |||
3597 | return result; | |||
3598 | } | |||
3599 | ||||
3600 | lldb_private::Error | |||
3601 | NativeProcessLinux::Detach(lldb::tid_t tid) | |||
3602 | { | |||
3603 | lldb_private::Error error; | |||
3604 | if (tid != LLDB_INVALID_THREAD_ID0) | |||
3605 | { | |||
3606 | DetachOperation op(tid, error); | |||
3607 | DoOperation(&op); | |||
3608 | } | |||
3609 | return error; | |||
3610 | } | |||
3611 | ||||
3612 | bool | |||
3613 | NativeProcessLinux::DupDescriptor(const char *path, int fd, int flags) | |||
3614 | { | |||
3615 | int target_fd = open(path, flags, 0666); | |||
3616 | ||||
3617 | if (target_fd == -1) | |||
3618 | return false; | |||
3619 | ||||
3620 | return (dup2(target_fd, fd) == -1) ? false : true; | |||
3621 | } | |||
3622 | ||||
3623 | void | |||
3624 | NativeProcessLinux::StopMonitoringChildProcess() | |||
3625 | { | |||
3626 | if (m_monitor_thread.IsJoinable()) | |||
3627 | { | |||
3628 | m_monitor_thread.Cancel(); | |||
3629 | m_monitor_thread.Join(nullptr); | |||
3630 | } | |||
3631 | } | |||
3632 | ||||
3633 | void | |||
3634 | NativeProcessLinux::StopMonitor() | |||
3635 | { | |||
3636 | StopMonitoringChildProcess(); | |||
3637 | StopOpThread(); | |||
3638 | sem_destroy(&m_operation_pending); | |||
3639 | sem_destroy(&m_operation_done); | |||
3640 | ||||
3641 | // TODO: validate whether this still holds, fix up comment. | |||
3642 | // Note: ProcessPOSIX passes the m_terminal_fd file descriptor to | |||
3643 | // Process::SetSTDIOFileDescriptor, which in turn transfers ownership of | |||
3644 | // the descriptor to a ConnectionFileDescriptor object. Consequently | |||
3645 | // even though still has the file descriptor, we shouldn't close it here. | |||
3646 | } | |||
3647 | ||||
3648 | void | |||
3649 | NativeProcessLinux::StopOpThread() | |||
3650 | { | |||
3651 | if (!m_operation_thread.IsJoinable()) | |||
3652 | return; | |||
3653 | ||||
3654 | m_operation_thread.Cancel(); | |||
3655 | m_operation_thread.Join(nullptr); | |||
3656 | } | |||
3657 | ||||
3658 | bool | |||
3659 | NativeProcessLinux::HasThreadNoLock (lldb::tid_t thread_id) | |||
3660 | { | |||
3661 | for (auto thread_sp : m_threads) | |||
3662 | { | |||
3663 | assert (thread_sp && "thread list should not contain NULL threads")((thread_sp && "thread list should not contain NULL threads" ) ? static_cast<void> (0) : __assert_fail ("thread_sp && \"thread list should not contain NULL threads\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3663, __PRETTY_FUNCTION__)); | |||
3664 | if (thread_sp->GetID () == thread_id) | |||
3665 | { | |||
3666 | // We have this thread. | |||
3667 | return true; | |||
3668 | } | |||
3669 | } | |||
3670 | ||||
3671 | // We don't have this thread. | |||
3672 | return false; | |||
3673 | } | |||
3674 | ||||
3675 | NativeThreadProtocolSP | |||
3676 | NativeProcessLinux::MaybeGetThreadNoLock (lldb::tid_t thread_id) | |||
3677 | { | |||
3678 | // CONSIDER organize threads by map - we can do better than linear. | |||
3679 | for (auto thread_sp : m_threads) | |||
3680 | { | |||
3681 | if (thread_sp->GetID () == thread_id) | |||
3682 | return thread_sp; | |||
3683 | } | |||
3684 | ||||
3685 | // We don't have this thread. | |||
3686 | return NativeThreadProtocolSP (); | |||
3687 | } | |||
3688 | ||||
3689 | bool | |||
3690 | NativeProcessLinux::StopTrackingThread (lldb::tid_t thread_id) | |||
3691 | { | |||
3692 | Mutex::Locker locker (m_threads_mutex); | |||
3693 | for (auto it = m_threads.begin (); it != m_threads.end (); ++it) | |||
3694 | { | |||
3695 | if (*it && ((*it)->GetID () == thread_id)) | |||
3696 | { | |||
3697 | m_threads.erase (it); | |||
3698 | return true; | |||
3699 | } | |||
3700 | } | |||
3701 | ||||
3702 | // Didn't find it. | |||
3703 | return false; | |||
3704 | } | |||
3705 | ||||
3706 | NativeThreadProtocolSP | |||
3707 | NativeProcessLinux::AddThread (lldb::tid_t thread_id) | |||
3708 | { | |||
3709 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD(1u << 2))); | |||
3710 | ||||
3711 | Mutex::Locker locker (m_threads_mutex); | |||
3712 | ||||
3713 | if (log) | |||
3714 | { | |||
3715 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " adding thread with tid %" PRIu64"l" "u", | |||
3716 | __FUNCTION__, | |||
3717 | GetID (), | |||
3718 | thread_id); | |||
3719 | } | |||
3720 | ||||
3721 | assert (!HasThreadNoLock (thread_id) && "attempted to add a thread by id that already exists")((!HasThreadNoLock (thread_id) && "attempted to add a thread by id that already exists" ) ? static_cast<void> (0) : __assert_fail ("!HasThreadNoLock (thread_id) && \"attempted to add a thread by id that already exists\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3721, __PRETTY_FUNCTION__)); | |||
3722 | ||||
3723 | // If this is the first thread, save it as the current thread | |||
3724 | if (m_threads.empty ()) | |||
3725 | SetCurrentThreadID (thread_id); | |||
3726 | ||||
3727 | NativeThreadProtocolSP thread_sp (new NativeThreadLinux (this, thread_id)); | |||
3728 | m_threads.push_back (thread_sp); | |||
3729 | ||||
3730 | return thread_sp; | |||
3731 | } | |||
3732 | ||||
3733 | NativeThreadProtocolSP | |||
3734 | NativeProcessLinux::GetOrCreateThread (lldb::tid_t thread_id, bool &created) | |||
3735 | { | |||
3736 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD(1u << 2))); | |||
3737 | ||||
3738 | Mutex::Locker locker (m_threads_mutex); | |||
3739 | if (log) | |||
3740 | { | |||
3741 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " get/create thread with tid %" PRIu64"l" "u", | |||
3742 | __FUNCTION__, | |||
3743 | GetID (), | |||
3744 | thread_id); | |||
3745 | } | |||
3746 | ||||
3747 | // Retrieve the thread if it is already getting tracked. | |||
3748 | NativeThreadProtocolSP thread_sp = MaybeGetThreadNoLock (thread_id); | |||
3749 | if (thread_sp) | |||
3750 | { | |||
3751 | if (log) | |||
3752 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ": thread already tracked, returning", | |||
3753 | __FUNCTION__, | |||
3754 | GetID (), | |||
3755 | thread_id); | |||
3756 | created = false; | |||
3757 | return thread_sp; | |||
3758 | ||||
3759 | } | |||
3760 | ||||
3761 | // Create the thread metadata since it isn't being tracked. | |||
3762 | if (log) | |||
3763 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ": thread didn't exist, tracking now", | |||
3764 | __FUNCTION__, | |||
3765 | GetID (), | |||
3766 | thread_id); | |||
3767 | ||||
3768 | thread_sp.reset (new NativeThreadLinux (this, thread_id)); | |||
3769 | m_threads.push_back (thread_sp); | |||
3770 | created = true; | |||
3771 | ||||
3772 | return thread_sp; | |||
3773 | } | |||
3774 | ||||
3775 | Error | |||
3776 | NativeProcessLinux::FixupBreakpointPCAsNeeded (NativeThreadProtocolSP &thread_sp) | |||
3777 | { | |||
3778 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS(1u << 5))); | |||
3779 | ||||
3780 | Error error; | |||
3781 | ||||
3782 | // Get a linux thread pointer. | |||
3783 | if (!thread_sp) | |||
3784 | { | |||
3785 | error.SetErrorString ("null thread_sp"); | |||
3786 | if (log) | |||
3787 | log->Printf ("NativeProcessLinux::%s failed: %s", __FUNCTION__, error.AsCString ()); | |||
3788 | return error; | |||
3789 | } | |||
3790 | NativeThreadLinux *const linux_thread_p = reinterpret_cast<NativeThreadLinux*> (thread_sp.get()); | |||
3791 | ||||
3792 | // Find out the size of a breakpoint (might depend on where we are in the code). | |||
3793 | NativeRegisterContextSP context_sp = linux_thread_p->GetRegisterContext (); | |||
3794 | if (!context_sp) | |||
3795 | { | |||
3796 | error.SetErrorString ("cannot get a NativeRegisterContext for the thread"); | |||
3797 | if (log) | |||
3798 | log->Printf ("NativeProcessLinux::%s failed: %s", __FUNCTION__, error.AsCString ()); | |||
3799 | return error; | |||
3800 | } | |||
3801 | ||||
3802 | uint32_t breakpoint_size = 0; | |||
3803 | error = GetSoftwareBreakpointSize (context_sp, breakpoint_size); | |||
3804 | if (error.Fail ()) | |||
3805 | { | |||
3806 | if (log) | |||
3807 | log->Printf ("NativeProcessLinux::%s GetBreakpointSize() failed: %s", __FUNCTION__, error.AsCString ()); | |||
3808 | return error; | |||
3809 | } | |||
3810 | else | |||
3811 | { | |||
3812 | if (log) | |||
3813 | log->Printf ("NativeProcessLinux::%s breakpoint size: %" PRIu32"u", __FUNCTION__, breakpoint_size); | |||
3814 | } | |||
3815 | ||||
3816 | // First try probing for a breakpoint at a software breakpoint location: PC - breakpoint size. | |||
3817 | const lldb::addr_t initial_pc_addr = context_sp->GetPC (); | |||
3818 | lldb::addr_t breakpoint_addr = initial_pc_addr; | |||
3819 | if (breakpoint_size > static_cast<lldb::addr_t> (0)) | |||
3820 | { | |||
3821 | // Do not allow breakpoint probe to wrap around. | |||
3822 | if (breakpoint_addr >= static_cast<lldb::addr_t> (breakpoint_size)) | |||
3823 | breakpoint_addr -= static_cast<lldb::addr_t> (breakpoint_size); | |||
3824 | } | |||
3825 | ||||
3826 | // Check if we stopped because of a breakpoint. | |||
3827 | NativeBreakpointSP breakpoint_sp; | |||
3828 | error = m_breakpoint_list.GetBreakpoint (breakpoint_addr, breakpoint_sp); | |||
3829 | if (!error.Success () || !breakpoint_sp) | |||
3830 | { | |||
3831 | // We didn't find one at a software probe location. Nothing to do. | |||
3832 | if (log) | |||
3833 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " no lldb breakpoint found at current pc with adjustment: 0x%" PRIx64"l" "x", __FUNCTION__, GetID (), breakpoint_addr); | |||
3834 | return Error (); | |||
3835 | } | |||
3836 | ||||
3837 | // If the breakpoint is not a software breakpoint, nothing to do. | |||
3838 | if (!breakpoint_sp->IsSoftwareBreakpoint ()) | |||
3839 | { | |||
3840 | if (log) | |||
3841 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " breakpoint found at 0x%" PRIx64"l" "x" ", not software, nothing to adjust", __FUNCTION__, GetID (), breakpoint_addr); | |||
3842 | return Error (); | |||
3843 | } | |||
3844 | ||||
3845 | // | |||
3846 | // We have a software breakpoint and need to adjust the PC. | |||
3847 | // | |||
3848 | ||||
3849 | // Sanity check. | |||
3850 | if (breakpoint_size == 0) | |||
3851 | { | |||
3852 | // Nothing to do! How did we get here? | |||
3853 | if (log) | |||
3854 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " breakpoint found at 0x%" PRIx64"l" "x" ", it is software, but the size is zero, nothing to do (unexpected)", __FUNCTION__, GetID (), breakpoint_addr); | |||
3855 | return Error (); | |||
3856 | } | |||
3857 | ||||
3858 | // Change the program counter. | |||
3859 | if (log) | |||
3860 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ": changing PC from 0x%" PRIx64"l" "x" " to 0x%" PRIx64"l" "x", __FUNCTION__, GetID (), linux_thread_p->GetID (), initial_pc_addr, breakpoint_addr); | |||
3861 | ||||
3862 | error = context_sp->SetPC (breakpoint_addr); | |||
3863 | if (error.Fail ()) | |||
3864 | { | |||
3865 | if (log) | |||
3866 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ": failed to set PC: %s", __FUNCTION__, GetID (), linux_thread_p->GetID (), error.AsCString ()); | |||
3867 | return error; | |||
3868 | } | |||
3869 | ||||
3870 | return error; | |||
3871 | } |