File: | tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp |
Location: | line 3161, column 86 |
Description: | Dereference of null pointer |
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 "NativeProcessLinux.h" | |||
11 | ||||
12 | // C Includes | |||
13 | #include <errno(*__errno_location ()).h> | |||
14 | #include <string.h> | |||
15 | #include <stdint.h> | |||
16 | #include <unistd.h> | |||
17 | ||||
18 | // C++ Includes | |||
19 | #include <fstream> | |||
20 | #include <mutex> | |||
21 | #include <sstream> | |||
22 | #include <string> | |||
23 | #include <unordered_map> | |||
24 | ||||
25 | // Other libraries and framework includes | |||
26 | #include "lldb/Core/EmulateInstruction.h" | |||
27 | #include "lldb/Core/Error.h" | |||
28 | #include "lldb/Core/Module.h" | |||
29 | #include "lldb/Core/ModuleSpec.h" | |||
30 | #include "lldb/Core/RegisterValue.h" | |||
31 | #include "lldb/Core/State.h" | |||
32 | #include "lldb/Host/common/NativeBreakpoint.h" | |||
33 | #include "lldb/Host/common/NativeRegisterContext.h" | |||
34 | #include "lldb/Host/Host.h" | |||
35 | #include "lldb/Host/ThreadLauncher.h" | |||
36 | #include "lldb/Target/Platform.h" | |||
37 | #include "lldb/Target/Process.h" | |||
38 | #include "lldb/Target/ProcessLaunchInfo.h" | |||
39 | #include "lldb/Target/Target.h" | |||
40 | #include "lldb/Utility/LLDBAssert.h" | |||
41 | #include "lldb/Utility/PseudoTerminal.h" | |||
42 | #include "lldb/Utility/StringExtractor.h" | |||
43 | ||||
44 | #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" | |||
45 | #include "NativeThreadLinux.h" | |||
46 | #include "ProcFileReader.h" | |||
47 | #include "Procfs.h" | |||
48 | ||||
49 | // System includes - They have to be included after framework includes because they define some | |||
50 | // macros which collide with variable names in other modules | |||
51 | #include <linux/unistd.h> | |||
52 | #include <sys/socket.h> | |||
53 | ||||
54 | #include <sys/syscall.h> | |||
55 | #include <sys/types.h> | |||
56 | #include <sys/user.h> | |||
57 | #include <sys/wait.h> | |||
58 | ||||
59 | #include "lldb/Host/linux/Personality.h" | |||
60 | #include "lldb/Host/linux/Ptrace.h" | |||
61 | #include "lldb/Host/linux/Signalfd.h" | |||
62 | #include "lldb/Host/linux/Uio.h" | |||
63 | #include "lldb/Host/android/Android.h" | |||
64 | ||||
65 | #define LLDB_PERSONALITY_GET_CURRENT_SETTINGS0xffffffff 0xffffffff | |||
66 | ||||
67 | // Support hardware breakpoints in case it has not been defined | |||
68 | #ifndef TRAP_HWBKPT4 | |||
69 | #define TRAP_HWBKPT4 4 | |||
70 | #endif | |||
71 | ||||
72 | using namespace lldb; | |||
73 | using namespace lldb_private; | |||
74 | using namespace lldb_private::process_linux; | |||
75 | using namespace llvm; | |||
76 | ||||
77 | // Private bits we only need internally. | |||
78 | ||||
79 | static bool ProcessVmReadvSupported() | |||
80 | { | |||
81 | static bool is_supported; | |||
82 | static std::once_flag flag; | |||
83 | ||||
84 | std::call_once(flag, [] { | |||
85 | Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
86 | ||||
87 | uint32_t source = 0x47424742; | |||
88 | uint32_t dest = 0; | |||
89 | ||||
90 | struct iovec local, remote; | |||
91 | remote.iov_base = &source; | |||
92 | local.iov_base = &dest; | |||
93 | remote.iov_len = local.iov_len = sizeof source; | |||
94 | ||||
95 | // We shall try if cross-process-memory reads work by attempting to read a value from our own process. | |||
96 | ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); | |||
97 | is_supported = (res == sizeof(source) && source == dest); | |||
98 | if (log) | |||
99 | { | |||
100 | if (is_supported) | |||
101 | log->Printf("%s: Detected kernel support for process_vm_readv syscall. Fast memory reads enabled.", | |||
102 | __FUNCTION__); | |||
103 | else | |||
104 | log->Printf("%s: syscall process_vm_readv failed (error: %s). Fast memory reads disabled.", | |||
105 | __FUNCTION__, strerror(errno(*__errno_location ()))); | |||
106 | } | |||
107 | }); | |||
108 | ||||
109 | return is_supported; | |||
110 | } | |||
111 | ||||
112 | namespace | |||
113 | { | |||
114 | Error | |||
115 | ResolveProcessArchitecture (lldb::pid_t pid, Platform &platform, ArchSpec &arch) | |||
116 | { | |||
117 | // Grab process info for the running process. | |||
118 | ProcessInstanceInfo process_info; | |||
119 | if (!platform.GetProcessInfo (pid, process_info)) | |||
120 | return Error("failed to get process info"); | |||
121 | ||||
122 | // Resolve the executable module. | |||
123 | ModuleSP exe_module_sp; | |||
124 | ModuleSpec exe_module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture()); | |||
125 | FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths ()); | |||
126 | Error error = platform.ResolveExecutable( | |||
127 | exe_module_spec, | |||
128 | exe_module_sp, | |||
129 | executable_search_paths.GetSize () ? &executable_search_paths : NULL__null); | |||
130 | ||||
131 | if (!error.Success ()) | |||
132 | return error; | |||
133 | ||||
134 | // Check if we've got our architecture from the exe_module. | |||
135 | arch = exe_module_sp->GetArchitecture (); | |||
136 | if (arch.IsValid ()) | |||
137 | return Error(); | |||
138 | else | |||
139 | return Error("failed to retrieve a valid architecture from the exe module"); | |||
140 | } | |||
141 | ||||
142 | void | |||
143 | DisplayBytes (StreamString &s, void *bytes, uint32_t count) | |||
144 | { | |||
145 | uint8_t *ptr = (uint8_t *)bytes; | |||
146 | const uint32_t loop_count = std::min<uint32_t>(DEBUG_PTRACE_MAXBYTES20, count); | |||
147 | for(uint32_t i=0; i<loop_count; i++) | |||
148 | { | |||
149 | s.Printf ("[%x]", *ptr); | |||
150 | ptr++; | |||
151 | } | |||
152 | } | |||
153 | ||||
154 | void | |||
155 | PtraceDisplayBytes(int &req, void *data, size_t data_size) | |||
156 | { | |||
157 | StreamString buf; | |||
158 | Log *verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet ( | |||
159 | POSIX_LOG_PTRACE(1u << 12) | POSIX_LOG_VERBOSE(1u << 0))); | |||
160 | ||||
161 | if (verbose_log) | |||
162 | { | |||
163 | switch(req) | |||
164 | { | |||
165 | case PTRACE_POKETEXT: | |||
166 | { | |||
167 | DisplayBytes(buf, &data, 8); | |||
168 | verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData()); | |||
169 | break; | |||
170 | } | |||
171 | case PTRACE_POKEDATA: | |||
172 | { | |||
173 | DisplayBytes(buf, &data, 8); | |||
174 | verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData()); | |||
175 | break; | |||
176 | } | |||
177 | case PTRACE_POKEUSER: | |||
178 | { | |||
179 | DisplayBytes(buf, &data, 8); | |||
180 | verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData()); | |||
181 | break; | |||
182 | } | |||
183 | case PTRACE_SETREGS: | |||
184 | { | |||
185 | DisplayBytes(buf, data, data_size); | |||
186 | verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData()); | |||
187 | break; | |||
188 | } | |||
189 | case PTRACE_SETFPREGS: | |||
190 | { | |||
191 | DisplayBytes(buf, data, data_size); | |||
192 | verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData()); | |||
193 | break; | |||
194 | } | |||
195 | case PTRACE_SETSIGINFO: | |||
196 | { | |||
197 | DisplayBytes(buf, data, sizeof(siginfo_t)); | |||
198 | verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData()); | |||
199 | break; | |||
200 | } | |||
201 | case PTRACE_SETREGSETPTRACE_SETREGSET: | |||
202 | { | |||
203 | // Extract iov_base from data, which is a pointer to the struct IOVEC | |||
204 | DisplayBytes(buf, *(void **)data, data_size); | |||
205 | verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData()); | |||
206 | break; | |||
207 | } | |||
208 | default: | |||
209 | { | |||
210 | } | |||
211 | } | |||
212 | } | |||
213 | } | |||
214 | ||||
215 | static constexpr unsigned k_ptrace_word_size = sizeof(void*); | |||
216 | static_assert(sizeof(long) >= k_ptrace_word_size, "Size of long must be larger than ptrace word size"); | |||
217 | } // end of anonymous namespace | |||
218 | ||||
219 | // Simple helper function to ensure flags are enabled on the given file | |||
220 | // descriptor. | |||
221 | static Error | |||
222 | EnsureFDFlags(int fd, int flags) | |||
223 | { | |||
224 | Error error; | |||
225 | ||||
226 | int status = fcntl(fd, F_GETFL3); | |||
227 | if (status == -1) | |||
228 | { | |||
229 | error.SetErrorToErrno(); | |||
230 | return error; | |||
231 | } | |||
232 | ||||
233 | if (fcntl(fd, F_SETFL4, status | flags) == -1) | |||
234 | { | |||
235 | error.SetErrorToErrno(); | |||
236 | return error; | |||
237 | } | |||
238 | ||||
239 | return error; | |||
240 | } | |||
241 | ||||
242 | NativeProcessLinux::LaunchArgs::LaunchArgs(Module *module, | |||
243 | char const **argv, | |||
244 | char const **envp, | |||
245 | const FileSpec &stdin_file_spec, | |||
246 | const FileSpec &stdout_file_spec, | |||
247 | const FileSpec &stderr_file_spec, | |||
248 | const FileSpec &working_dir, | |||
249 | const ProcessLaunchInfo &launch_info) | |||
250 | : m_module(module), | |||
251 | m_argv(argv), | |||
252 | m_envp(envp), | |||
253 | m_stdin_file_spec(stdin_file_spec), | |||
254 | m_stdout_file_spec(stdout_file_spec), | |||
255 | m_stderr_file_spec(stderr_file_spec), | |||
256 | m_working_dir(working_dir), | |||
257 | m_launch_info(launch_info) | |||
258 | { | |||
259 | } | |||
260 | ||||
261 | NativeProcessLinux::LaunchArgs::~LaunchArgs() | |||
262 | { } | |||
263 | ||||
264 | // ----------------------------------------------------------------------------- | |||
265 | // Public Static Methods | |||
266 | // ----------------------------------------------------------------------------- | |||
267 | ||||
268 | Error | |||
269 | NativeProcessProtocol::Launch ( | |||
270 | ProcessLaunchInfo &launch_info, | |||
271 | NativeProcessProtocol::NativeDelegate &native_delegate, | |||
272 | MainLoop &mainloop, | |||
273 | NativeProcessProtocolSP &native_process_sp) | |||
274 | { | |||
275 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
276 | ||||
277 | lldb::ModuleSP exe_module_sp; | |||
278 | PlatformSP platform_sp (Platform::GetHostPlatform ()); | |||
279 | Error error = platform_sp->ResolveExecutable( | |||
280 | ModuleSpec(launch_info.GetExecutableFile(), launch_info.GetArchitecture()), | |||
281 | exe_module_sp, | |||
282 | nullptr); | |||
283 | ||||
284 | if (! error.Success()) | |||
285 | return error; | |||
286 | ||||
287 | // Verify the working directory is valid if one was specified. | |||
288 | FileSpec working_dir{launch_info.GetWorkingDirectory()}; | |||
289 | if (working_dir && | |||
290 | (!working_dir.ResolvePath() || | |||
291 | working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) | |||
292 | { | |||
293 | error.SetErrorStringWithFormat ("No such file or directory: %s", | |||
294 | working_dir.GetCString()); | |||
295 | return error; | |||
296 | } | |||
297 | ||||
298 | const FileAction *file_action; | |||
299 | ||||
300 | // Default of empty will mean to use existing open file descriptors. | |||
301 | FileSpec stdin_file_spec{}; | |||
302 | FileSpec stdout_file_spec{}; | |||
303 | FileSpec stderr_file_spec{}; | |||
304 | ||||
305 | file_action = launch_info.GetFileActionForFD (STDIN_FILENO0); | |||
306 | if (file_action) | |||
307 | stdin_file_spec = file_action->GetFileSpec(); | |||
308 | ||||
309 | file_action = launch_info.GetFileActionForFD (STDOUT_FILENO1); | |||
310 | if (file_action) | |||
311 | stdout_file_spec = file_action->GetFileSpec(); | |||
312 | ||||
313 | file_action = launch_info.GetFileActionForFD (STDERR_FILENO2); | |||
314 | if (file_action) | |||
315 | stderr_file_spec = file_action->GetFileSpec(); | |||
316 | ||||
317 | if (log) | |||
318 | { | |||
319 | if (stdin_file_spec) | |||
320 | log->Printf ("NativeProcessLinux::%s setting STDIN to '%s'", | |||
321 | __FUNCTION__, stdin_file_spec.GetCString()); | |||
322 | else | |||
323 | log->Printf ("NativeProcessLinux::%s leaving STDIN as is", __FUNCTION__); | |||
324 | ||||
325 | if (stdout_file_spec) | |||
326 | log->Printf ("NativeProcessLinux::%s setting STDOUT to '%s'", | |||
327 | __FUNCTION__, stdout_file_spec.GetCString()); | |||
328 | else | |||
329 | log->Printf ("NativeProcessLinux::%s leaving STDOUT as is", __FUNCTION__); | |||
330 | ||||
331 | if (stderr_file_spec) | |||
332 | log->Printf ("NativeProcessLinux::%s setting STDERR to '%s'", | |||
333 | __FUNCTION__, stderr_file_spec.GetCString()); | |||
334 | else | |||
335 | log->Printf ("NativeProcessLinux::%s leaving STDERR as is", __FUNCTION__); | |||
336 | } | |||
337 | ||||
338 | // Create the NativeProcessLinux in launch mode. | |||
339 | native_process_sp.reset (new NativeProcessLinux ()); | |||
340 | ||||
341 | if (log) | |||
342 | { | |||
343 | int i = 0; | |||
344 | for (const char **args = launch_info.GetArguments ().GetConstArgumentVector (); *args; ++args, ++i) | |||
345 | { | |||
346 | log->Printf ("NativeProcessLinux::%s arg %d: \"%s\"", __FUNCTION__, i, *args ? *args : "nullptr"); | |||
347 | ++i; | |||
348 | } | |||
349 | } | |||
350 | ||||
351 | if (!native_process_sp->RegisterNativeDelegate (native_delegate)) | |||
352 | { | |||
353 | native_process_sp.reset (); | |||
354 | error.SetErrorStringWithFormat ("failed to register the native delegate"); | |||
355 | return error; | |||
356 | } | |||
357 | ||||
358 | std::static_pointer_cast<NativeProcessLinux> (native_process_sp)->LaunchInferior ( | |||
359 | mainloop, | |||
360 | exe_module_sp.get(), | |||
361 | launch_info.GetArguments ().GetConstArgumentVector (), | |||
362 | launch_info.GetEnvironmentEntries ().GetConstArgumentVector (), | |||
363 | stdin_file_spec, | |||
364 | stdout_file_spec, | |||
365 | stderr_file_spec, | |||
366 | working_dir, | |||
367 | launch_info, | |||
368 | error); | |||
369 | ||||
370 | if (error.Fail ()) | |||
371 | { | |||
372 | native_process_sp.reset (); | |||
373 | if (log) | |||
374 | log->Printf ("NativeProcessLinux::%s failed to launch process: %s", __FUNCTION__, error.AsCString ()); | |||
375 | return error; | |||
376 | } | |||
377 | ||||
378 | launch_info.SetProcessID (native_process_sp->GetID ()); | |||
379 | ||||
380 | return error; | |||
381 | } | |||
382 | ||||
383 | Error | |||
384 | NativeProcessProtocol::Attach ( | |||
385 | lldb::pid_t pid, | |||
386 | NativeProcessProtocol::NativeDelegate &native_delegate, | |||
387 | MainLoop &mainloop, | |||
388 | NativeProcessProtocolSP &native_process_sp) | |||
389 | { | |||
390 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
391 | if (log && log->GetMask ().Test (POSIX_LOG_VERBOSE(1u << 0))) | |||
392 | log->Printf ("NativeProcessLinux::%s(pid = %" PRIi64"l" "i" ")", __FUNCTION__, pid); | |||
393 | ||||
394 | // Grab the current platform architecture. This should be Linux, | |||
395 | // since this code is only intended to run on a Linux host. | |||
396 | PlatformSP platform_sp (Platform::GetHostPlatform ()); | |||
397 | if (!platform_sp) | |||
398 | return Error("failed to get a valid default platform"); | |||
399 | ||||
400 | // Retrieve the architecture for the running process. | |||
401 | ArchSpec process_arch; | |||
402 | Error error = ResolveProcessArchitecture (pid, *platform_sp.get (), process_arch); | |||
403 | if (!error.Success ()) | |||
404 | return error; | |||
405 | ||||
406 | std::shared_ptr<NativeProcessLinux> native_process_linux_sp (new NativeProcessLinux ()); | |||
407 | ||||
408 | if (!native_process_linux_sp->RegisterNativeDelegate (native_delegate)) | |||
409 | { | |||
410 | error.SetErrorStringWithFormat ("failed to register the native delegate"); | |||
411 | return error; | |||
412 | } | |||
413 | ||||
414 | native_process_linux_sp->AttachToInferior (mainloop, pid, error); | |||
415 | if (!error.Success ()) | |||
416 | return error; | |||
417 | ||||
418 | native_process_sp = native_process_linux_sp; | |||
419 | return error; | |||
420 | } | |||
421 | ||||
422 | // ----------------------------------------------------------------------------- | |||
423 | // Public Instance Methods | |||
424 | // ----------------------------------------------------------------------------- | |||
425 | ||||
426 | NativeProcessLinux::NativeProcessLinux () : | |||
427 | NativeProcessProtocol (LLDB_INVALID_PROCESS_ID0), | |||
428 | m_arch (), | |||
429 | m_supports_mem_region (eLazyBoolCalculate), | |||
430 | m_mem_region_cache (), | |||
431 | m_mem_region_cache_mutex(), | |||
432 | m_pending_notification_tid(LLDB_INVALID_THREAD_ID0) | |||
433 | { | |||
434 | } | |||
435 | ||||
436 | void | |||
437 | NativeProcessLinux::LaunchInferior ( | |||
438 | MainLoop &mainloop, | |||
439 | Module *module, | |||
440 | const char *argv[], | |||
441 | const char *envp[], | |||
442 | const FileSpec &stdin_file_spec, | |||
443 | const FileSpec &stdout_file_spec, | |||
444 | const FileSpec &stderr_file_spec, | |||
445 | const FileSpec &working_dir, | |||
446 | const ProcessLaunchInfo &launch_info, | |||
447 | Error &error) | |||
448 | { | |||
449 | m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD17, | |||
450 | [this] (MainLoopBase &) { SigchldHandler(); }, error); | |||
451 | if (! m_sigchld_handle) | |||
452 | return; | |||
453 | ||||
454 | if (module) | |||
455 | m_arch = module->GetArchitecture (); | |||
456 | ||||
457 | SetState (eStateLaunching); | |||
458 | ||||
459 | std::unique_ptr<LaunchArgs> args( | |||
460 | new LaunchArgs(module, argv, envp, | |||
461 | stdin_file_spec, | |||
462 | stdout_file_spec, | |||
463 | stderr_file_spec, | |||
464 | working_dir, | |||
465 | launch_info)); | |||
466 | ||||
467 | Launch(args.get(), error); | |||
468 | } | |||
469 | ||||
470 | void | |||
471 | NativeProcessLinux::AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error) | |||
472 | { | |||
473 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
474 | if (log) | |||
475 | log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64"l" "i" ")", __FUNCTION__, pid); | |||
476 | ||||
477 | m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD17, | |||
478 | [this] (MainLoopBase &) { SigchldHandler(); }, error); | |||
479 | if (! m_sigchld_handle) | |||
480 | return; | |||
481 | ||||
482 | // We can use the Host for everything except the ResolveExecutable portion. | |||
483 | PlatformSP platform_sp = Platform::GetHostPlatform (); | |||
484 | if (!platform_sp) | |||
485 | { | |||
486 | if (log) | |||
487 | log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64"l" "i" "): no default platform set", __FUNCTION__, pid); | |||
488 | error.SetErrorString ("no default platform available"); | |||
489 | return; | |||
490 | } | |||
491 | ||||
492 | // Gather info about the process. | |||
493 | ProcessInstanceInfo process_info; | |||
494 | if (!platform_sp->GetProcessInfo (pid, process_info)) | |||
495 | { | |||
496 | if (log) | |||
497 | log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64"l" "i" "): failed to get process info", __FUNCTION__, pid); | |||
498 | error.SetErrorString ("failed to get process info"); | |||
499 | return; | |||
500 | } | |||
501 | ||||
502 | // Resolve the executable module | |||
503 | ModuleSP exe_module_sp; | |||
504 | FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); | |||
505 | ModuleSpec exe_module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture()); | |||
506 | error = platform_sp->ResolveExecutable(exe_module_spec, exe_module_sp, | |||
507 | executable_search_paths.GetSize() ? &executable_search_paths : NULL__null); | |||
508 | if (!error.Success()) | |||
509 | return; | |||
510 | ||||
511 | // Set the architecture to the exe architecture. | |||
512 | m_arch = exe_module_sp->GetArchitecture(); | |||
513 | if (log) | |||
514 | log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64"l" "i" ") detected architecture %s", __FUNCTION__, pid, m_arch.GetArchitectureName ()); | |||
515 | ||||
516 | m_pid = pid; | |||
517 | SetState(eStateAttaching); | |||
518 | ||||
519 | Attach(pid, error); | |||
520 | } | |||
521 | ||||
522 | ::pid_t | |||
523 | NativeProcessLinux::Launch(LaunchArgs *args, Error &error) | |||
524 | { | |||
525 | assert (args && "null args")((args && "null args") ? static_cast<void> (0) : __assert_fail ("args && \"null args\"", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 525, __PRETTY_FUNCTION__)); | |||
526 | ||||
527 | const char **argv = args->m_argv; | |||
528 | const char **envp = args->m_envp; | |||
529 | const FileSpec working_dir = args->m_working_dir; | |||
530 | ||||
531 | lldb_utility::PseudoTerminal terminal; | |||
532 | const size_t err_len = 1024; | |||
533 | char err_str[err_len]; | |||
534 | lldb::pid_t pid; | |||
535 | ||||
536 | // Propagate the environment if one is not supplied. | |||
537 | if (envp == NULL__null || envp[0] == NULL__null) | |||
538 | envp = const_cast<const char **>(environ); | |||
539 | ||||
540 | if ((pid = terminal.Fork(err_str, err_len)) == static_cast<lldb::pid_t> (-1)) | |||
541 | { | |||
542 | error.SetErrorToGenericError(); | |||
543 | error.SetErrorStringWithFormat("Process fork failed: %s", err_str); | |||
544 | return -1; | |||
545 | } | |||
546 | ||||
547 | // Recognized child exit status codes. | |||
548 | enum { | |||
549 | ePtraceFailed = 1, | |||
550 | eDupStdinFailed, | |||
551 | eDupStdoutFailed, | |||
552 | eDupStderrFailed, | |||
553 | eChdirFailed, | |||
554 | eExecFailed, | |||
555 | eSetGidFailed, | |||
556 | eSetSigMaskFailed | |||
557 | }; | |||
558 | ||||
559 | // Child process. | |||
560 | if (pid == 0) | |||
561 | { | |||
562 | // First, make sure we disable all logging. If we are logging to stdout, our logs can be | |||
563 | // mistaken for inferior output. | |||
564 | Log::DisableAllLogChannels(nullptr); | |||
565 | // FIXME consider opening a pipe between parent/child and have this forked child | |||
566 | // send log info to parent re: launch status. | |||
567 | ||||
568 | // Start tracing this child that is about to exec. | |||
569 | error = PtraceWrapper(PTRACE_TRACEME, 0); | |||
570 | if (error.Fail()) | |||
571 | exit(ePtraceFailed); | |||
572 | ||||
573 | // terminal has already dupped the tty descriptors to stdin/out/err. | |||
574 | // This closes original fd from which they were copied (and avoids | |||
575 | // leaking descriptors to the debugged process. | |||
576 | terminal.CloseSlaveFileDescriptor(); | |||
577 | ||||
578 | // Do not inherit setgid powers. | |||
579 | if (setgid(getgid()) != 0) | |||
580 | exit(eSetGidFailed); | |||
581 | ||||
582 | // Attempt to have our own process group. | |||
583 | if (setpgid(0, 0) != 0) | |||
584 | { | |||
585 | // FIXME log that this failed. This is common. | |||
586 | // Don't allow this to prevent an inferior exec. | |||
587 | } | |||
588 | ||||
589 | // Dup file descriptors if needed. | |||
590 | if (args->m_stdin_file_spec) | |||
591 | if (!DupDescriptor(args->m_stdin_file_spec, STDIN_FILENO0, O_RDONLY00)) | |||
592 | exit(eDupStdinFailed); | |||
593 | ||||
594 | if (args->m_stdout_file_spec) | |||
595 | if (!DupDescriptor(args->m_stdout_file_spec, STDOUT_FILENO1, O_WRONLY01 | O_CREAT0100 | O_TRUNC01000)) | |||
596 | exit(eDupStdoutFailed); | |||
597 | ||||
598 | if (args->m_stderr_file_spec) | |||
599 | if (!DupDescriptor(args->m_stderr_file_spec, STDERR_FILENO2, O_WRONLY01 | O_CREAT0100 | O_TRUNC01000)) | |||
600 | exit(eDupStderrFailed); | |||
601 | ||||
602 | // Close everything besides stdin, stdout, and stderr that has no file | |||
603 | // action to avoid leaking | |||
604 | for (int fd = 3; fd < sysconf(_SC_OPEN_MAX_SC_OPEN_MAX); ++fd) | |||
605 | if (!args->m_launch_info.GetFileActionForFD(fd)) | |||
606 | close(fd); | |||
607 | ||||
608 | // Change working directory | |||
609 | if (working_dir && 0 != ::chdir(working_dir.GetCString())) | |||
610 | exit(eChdirFailed); | |||
611 | ||||
612 | // Disable ASLR if requested. | |||
613 | if (args->m_launch_info.GetFlags ().Test (lldb::eLaunchFlagDisableASLR)) | |||
614 | { | |||
615 | const int old_personality = personality (LLDB_PERSONALITY_GET_CURRENT_SETTINGS0xffffffff); | |||
616 | if (old_personality == -1) | |||
617 | { | |||
618 | // Can't retrieve Linux personality. Cannot disable ASLR. | |||
619 | } | |||
620 | else | |||
621 | { | |||
622 | const int new_personality = personality (ADDR_NO_RANDOMIZE | old_personality); | |||
623 | if (new_personality == -1) | |||
624 | { | |||
625 | // Disabling ASLR failed. | |||
626 | } | |||
627 | else | |||
628 | { | |||
629 | // Disabling ASLR succeeded. | |||
630 | } | |||
631 | } | |||
632 | } | |||
633 | ||||
634 | // Clear the signal mask to prevent the child from being affected by | |||
635 | // any masking done by the parent. | |||
636 | sigset_t set; | |||
637 | if (sigemptyset(&set) != 0 || pthread_sigmask(SIG_SETMASK2, &set, nullptr) != 0) | |||
638 | exit(eSetSigMaskFailed); | |||
639 | ||||
640 | // Execute. We should never return... | |||
641 | execve(argv[0], | |||
642 | const_cast<char *const *>(argv), | |||
643 | const_cast<char *const *>(envp)); | |||
644 | ||||
645 | // ...unless exec fails. In which case we definitely need to end the child here. | |||
646 | exit(eExecFailed); | |||
647 | } | |||
648 | ||||
649 | // | |||
650 | // This is the parent code here. | |||
651 | // | |||
652 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
653 | ||||
654 | // Wait for the child process to trap on its call to execve. | |||
655 | ::pid_t wpid; | |||
656 | int status; | |||
657 | if ((wpid = waitpid(pid, &status, 0)) < 0) | |||
658 | { | |||
659 | error.SetErrorToErrno(); | |||
660 | if (log) | |||
661 | log->Printf ("NativeProcessLinux::%s waitpid for inferior failed with %s", | |||
662 | __FUNCTION__, error.AsCString ()); | |||
663 | ||||
664 | // Mark the inferior as invalid. | |||
665 | // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. | |||
666 | SetState (StateType::eStateInvalid); | |||
667 | ||||
668 | return -1; | |||
669 | } | |||
670 | else if (WIFEXITED(status)((((*(int *) &(status))) & 0x7f) == 0)) | |||
671 | { | |||
672 | // open, dup or execve likely failed for some reason. | |||
673 | error.SetErrorToGenericError(); | |||
674 | switch (WEXITSTATUS(status)((((*(int *) &(status))) & 0xff00) >> 8)) | |||
675 | { | |||
676 | case ePtraceFailed: | |||
677 | error.SetErrorString("Child ptrace failed."); | |||
678 | break; | |||
679 | case eDupStdinFailed: | |||
680 | error.SetErrorString("Child open stdin failed."); | |||
681 | break; | |||
682 | case eDupStdoutFailed: | |||
683 | error.SetErrorString("Child open stdout failed."); | |||
684 | break; | |||
685 | case eDupStderrFailed: | |||
686 | error.SetErrorString("Child open stderr failed."); | |||
687 | break; | |||
688 | case eChdirFailed: | |||
689 | error.SetErrorString("Child failed to set working directory."); | |||
690 | break; | |||
691 | case eExecFailed: | |||
692 | error.SetErrorString("Child exec failed."); | |||
693 | break; | |||
694 | case eSetGidFailed: | |||
695 | error.SetErrorString("Child setgid failed."); | |||
696 | break; | |||
697 | case eSetSigMaskFailed: | |||
698 | error.SetErrorString("Child failed to set signal mask."); | |||
699 | break; | |||
700 | default: | |||
701 | error.SetErrorString("Child returned unknown exit status."); | |||
702 | break; | |||
703 | } | |||
704 | ||||
705 | if (log) | |||
706 | { | |||
707 | log->Printf ("NativeProcessLinux::%s inferior exited with status %d before issuing a STOP", | |||
708 | __FUNCTION__, | |||
709 | WEXITSTATUS(status)((((*(int *) &(status))) & 0xff00) >> 8)); | |||
710 | } | |||
711 | ||||
712 | // Mark the inferior as invalid. | |||
713 | // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. | |||
714 | SetState (StateType::eStateInvalid); | |||
715 | ||||
716 | return -1; | |||
717 | } | |||
718 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 719, __PRETTY_FUNCTION__)) | |||
719 | "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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 719, __PRETTY_FUNCTION__)); | |||
720 | ||||
721 | if (log) | |||
722 | log->Printf ("NativeProcessLinux::%s inferior started, now in stopped state", __FUNCTION__); | |||
723 | ||||
724 | error = SetDefaultPtraceOpts(pid); | |||
725 | if (error.Fail()) | |||
726 | { | |||
727 | if (log) | |||
728 | log->Printf ("NativeProcessLinux::%s inferior failed to set default ptrace options: %s", | |||
729 | __FUNCTION__, error.AsCString ()); | |||
730 | ||||
731 | // Mark the inferior as invalid. | |||
732 | // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. | |||
733 | SetState (StateType::eStateInvalid); | |||
734 | ||||
735 | return -1; | |||
736 | } | |||
737 | ||||
738 | // Release the master terminal descriptor and pass it off to the | |||
739 | // NativeProcessLinux instance. Similarly stash the inferior pid. | |||
740 | m_terminal_fd = terminal.ReleaseMasterFileDescriptor(); | |||
741 | m_pid = pid; | |||
742 | ||||
743 | // Set the terminal fd to be in non blocking mode (it simplifies the | |||
744 | // implementation of ProcessLinux::GetSTDOUT to have a non-blocking | |||
745 | // descriptor to read from). | |||
746 | error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK04000); | |||
747 | if (error.Fail()) | |||
748 | { | |||
749 | if (log) | |||
750 | log->Printf ("NativeProcessLinux::%s inferior EnsureFDFlags failed for ensuring terminal O_NONBLOCK setting: %s", | |||
751 | __FUNCTION__, error.AsCString ()); | |||
752 | ||||
753 | // Mark the inferior as invalid. | |||
754 | // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. | |||
755 | SetState (StateType::eStateInvalid); | |||
756 | ||||
757 | return -1; | |||
758 | } | |||
759 | ||||
760 | if (log) | |||
761 | log->Printf ("NativeProcessLinux::%s() adding pid = %" PRIu64"l" "u", __FUNCTION__, pid); | |||
762 | ||||
763 | NativeThreadLinuxSP thread_sp = AddThread(pid); | |||
764 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 764, __PRETTY_FUNCTION__)); | |||
765 | thread_sp->SetStoppedBySignal(SIGSTOP19); | |||
766 | ThreadWasCreated(*thread_sp); | |||
767 | ||||
768 | // Let our process instance know the thread has stopped. | |||
769 | SetCurrentThreadID (thread_sp->GetID ()); | |||
770 | SetState (StateType::eStateStopped); | |||
771 | ||||
772 | if (log) | |||
773 | { | |||
774 | if (error.Success ()) | |||
775 | { | |||
776 | log->Printf ("NativeProcessLinux::%s inferior launching succeeded", __FUNCTION__); | |||
777 | } | |||
778 | else | |||
779 | { | |||
780 | log->Printf ("NativeProcessLinux::%s inferior launching failed: %s", | |||
781 | __FUNCTION__, error.AsCString ()); | |||
782 | return -1; | |||
783 | } | |||
784 | } | |||
785 | return pid; | |||
786 | } | |||
787 | ||||
788 | ::pid_t | |||
789 | NativeProcessLinux::Attach(lldb::pid_t pid, Error &error) | |||
790 | { | |||
791 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
792 | ||||
793 | // Use a map to keep track of the threads which we have attached/need to attach. | |||
794 | Host::TidMap tids_to_attach; | |||
795 | if (pid <= 1) | |||
796 | { | |||
797 | error.SetErrorToGenericError(); | |||
798 | error.SetErrorString("Attaching to process 1 is not allowed."); | |||
799 | return -1; | |||
800 | } | |||
801 | ||||
802 | while (Host::FindProcessThreads(pid, tids_to_attach)) | |||
803 | { | |||
804 | for (Host::TidMap::iterator it = tids_to_attach.begin(); | |||
805 | it != tids_to_attach.end();) | |||
806 | { | |||
807 | if (it->second == false) | |||
808 | { | |||
809 | lldb::tid_t tid = it->first; | |||
810 | ||||
811 | // Attach to the requested process. | |||
812 | // An attach will cause the thread to stop with a SIGSTOP. | |||
813 | error = PtraceWrapper(PTRACE_ATTACH, tid); | |||
814 | if (error.Fail()) | |||
815 | { | |||
816 | // No such thread. The thread may have exited. | |||
817 | // More error handling may be needed. | |||
818 | if (error.GetError() == ESRCH3) | |||
819 | { | |||
820 | it = tids_to_attach.erase(it); | |||
821 | continue; | |||
822 | } | |||
823 | else | |||
824 | return -1; | |||
825 | } | |||
826 | ||||
827 | int status; | |||
828 | // Need to use __WALL otherwise we receive an error with errno=ECHLD | |||
829 | // At this point we should have a thread stopped if waitpid succeeds. | |||
830 | if ((status = waitpid(tid, NULL__null, __WALL0x40000000)) < 0) | |||
831 | { | |||
832 | // No such thread. The thread may have exited. | |||
833 | // More error handling may be needed. | |||
834 | if (errno(*__errno_location ()) == ESRCH3) | |||
835 | { | |||
836 | it = tids_to_attach.erase(it); | |||
837 | continue; | |||
838 | } | |||
839 | else | |||
840 | { | |||
841 | error.SetErrorToErrno(); | |||
842 | return -1; | |||
843 | } | |||
844 | } | |||
845 | ||||
846 | error = SetDefaultPtraceOpts(tid); | |||
847 | if (error.Fail()) | |||
848 | return -1; | |||
849 | ||||
850 | if (log) | |||
851 | log->Printf ("NativeProcessLinux::%s() adding tid = %" PRIu64"l" "u", __FUNCTION__, tid); | |||
852 | ||||
853 | it->second = true; | |||
854 | ||||
855 | // Create the thread, mark it as stopped. | |||
856 | NativeThreadLinuxSP thread_sp (AddThread(static_cast<lldb::tid_t>(tid))); | |||
857 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 857, __PRETTY_FUNCTION__)); | |||
858 | ||||
859 | // This will notify this is a new thread and tell the system it is stopped. | |||
860 | thread_sp->SetStoppedBySignal(SIGSTOP19); | |||
861 | ThreadWasCreated(*thread_sp); | |||
862 | SetCurrentThreadID (thread_sp->GetID ()); | |||
863 | } | |||
864 | ||||
865 | // move the loop forward | |||
866 | ++it; | |||
867 | } | |||
868 | } | |||
869 | ||||
870 | if (tids_to_attach.size() > 0) | |||
871 | { | |||
872 | m_pid = pid; | |||
873 | // Let our process instance know the thread has stopped. | |||
874 | SetState (StateType::eStateStopped); | |||
875 | } | |||
876 | else | |||
877 | { | |||
878 | error.SetErrorToGenericError(); | |||
879 | error.SetErrorString("No such process."); | |||
880 | return -1; | |||
881 | } | |||
882 | ||||
883 | return pid; | |||
884 | } | |||
885 | ||||
886 | Error | |||
887 | NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) | |||
888 | { | |||
889 | long ptrace_opts = 0; | |||
890 | ||||
891 | // Have the child raise an event on exit. This is used to keep the child in | |||
892 | // limbo until it is destroyed. | |||
893 | ptrace_opts |= PTRACE_O_TRACEEXIT; | |||
894 | ||||
895 | // Have the tracer trace threads which spawn in the inferior process. | |||
896 | // TODO: if we want to support tracing the inferiors' child, add the | |||
897 | // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK) | |||
898 | ptrace_opts |= PTRACE_O_TRACECLONE; | |||
899 | ||||
900 | // Have the tracer notify us before execve returns | |||
901 | // (needed to disable legacy SIGTRAP generation) | |||
902 | ptrace_opts |= PTRACE_O_TRACEEXEC; | |||
903 | ||||
904 | return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void*)ptrace_opts); | |||
905 | } | |||
906 | ||||
907 | static ExitType convert_pid_status_to_exit_type (int status) | |||
908 | { | |||
909 | if (WIFEXITED (status)((((*(int *) &(status))) & 0x7f) == 0)) | |||
910 | return ExitType::eExitTypeExit; | |||
911 | else if (WIFSIGNALED (status)(((signed char) ((((*(int *) &(status))) & 0x7f) + 1) >> 1) > 0)) | |||
912 | return ExitType::eExitTypeSignal; | |||
913 | else if (WIFSTOPPED (status)((((*(int *) &(status))) & 0xff) == 0x7f)) | |||
914 | return ExitType::eExitTypeStop; | |||
915 | else | |||
916 | { | |||
917 | // We don't know what this is. | |||
918 | return ExitType::eExitTypeInvalid; | |||
919 | } | |||
920 | } | |||
921 | ||||
922 | static int convert_pid_status_to_return_code (int status) | |||
923 | { | |||
924 | if (WIFEXITED (status)((((*(int *) &(status))) & 0x7f) == 0)) | |||
925 | return WEXITSTATUS (status)((((*(int *) &(status))) & 0xff00) >> 8); | |||
926 | else if (WIFSIGNALED (status)(((signed char) ((((*(int *) &(status))) & 0x7f) + 1) >> 1) > 0)) | |||
927 | return WTERMSIG (status)(((*(int *) &(status))) & 0x7f); | |||
928 | else if (WIFSTOPPED (status)((((*(int *) &(status))) & 0xff) == 0x7f)) | |||
929 | return WSTOPSIG (status)((((*(int *) &(status))) & 0xff00) >> 8); | |||
930 | else | |||
931 | { | |||
932 | // We don't know what this is. | |||
933 | return ExitType::eExitTypeInvalid; | |||
934 | } | |||
935 | } | |||
936 | ||||
937 | // Handles all waitpid events from the inferior process. | |||
938 | void | |||
939 | NativeProcessLinux::MonitorCallback(lldb::pid_t pid, | |||
940 | bool exited, | |||
941 | int signal, | |||
942 | int status) | |||
943 | { | |||
944 | Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
945 | ||||
946 | // Certain activities differ based on whether the pid is the tid of the main thread. | |||
947 | const bool is_main_thread = (pid == GetID ()); | |||
948 | ||||
949 | // Handle when the thread exits. | |||
950 | if (exited) | |||
| ||||
951 | { | |||
952 | if (log) | |||
953 | log->Printf ("NativeProcessLinux::%s() got exit signal(%d) , tid = %" PRIu64"l" "u" " (%s main thread)", __FUNCTION__, signal, pid, is_main_thread ? "is" : "is not"); | |||
954 | ||||
955 | // This is a thread that exited. Ensure we're not tracking it anymore. | |||
956 | const bool thread_found = StopTrackingThread (pid); | |||
957 | ||||
958 | if (is_main_thread) | |||
959 | { | |||
960 | // We only set the exit status and notify the delegate if we haven't already set the process | |||
961 | // state to an exited state. We normally should have received a SIGTRAP | (PTRACE_EVENT_EXIT << 8) | |||
962 | // for the main thread. | |||
963 | const bool already_notified = (GetState() == StateType::eStateExited) || (GetState () == StateType::eStateCrashed); | |||
964 | if (!already_notified) | |||
965 | { | |||
966 | if (log) | |||
967 | 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 (GetState ())); | |||
968 | // The main thread exited. We're done monitoring. Report to delegate. | |||
969 | SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true); | |||
970 | ||||
971 | // Notify delegate that our process has exited. | |||
972 | SetState (StateType::eStateExited, true); | |||
973 | } | |||
974 | else | |||
975 | { | |||
976 | if (log) | |||
977 | 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"); | |||
978 | } | |||
979 | } | |||
980 | else | |||
981 | { | |||
982 | // Do we want to report to the delegate in this case? I think not. If this was an orderly | |||
983 | // thread exit, we would already have received the SIGTRAP | (PTRACE_EVENT_EXIT << 8) signal, | |||
984 | // and we would have done an all-stop then. | |||
985 | if (log) | |||
986 | 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"); | |||
987 | } | |||
988 | return; | |||
989 | } | |||
990 | ||||
991 | siginfo_t info; | |||
992 | const auto info_err = GetSignalInfo(pid, &info); | |||
993 | auto thread_sp = GetThreadByID(pid); | |||
994 | ||||
995 | if (! thread_sp) | |||
996 | { | |||
997 | // Normally, the only situation when we cannot find the thread is if we have just | |||
998 | // received a new thread notification. This is indicated by GetSignalInfo() returning | |||
999 | // si_code == SI_USER and si_pid == 0 | |||
1000 | if (log) | |||
1001 | log->Printf("NativeProcessLinux::%s received notification about an unknown tid %" PRIu64"l" "u" ".", __FUNCTION__, pid); | |||
1002 | ||||
1003 | if (info_err.Fail()) | |||
1004 | { | |||
1005 | if (log) | |||
1006 | log->Printf("NativeProcessLinux::%s (tid %" PRIu64"l" "u" ") GetSignalInfo failed (%s). Ingoring this notification.", __FUNCTION__, pid, info_err.AsCString()); | |||
1007 | return; | |||
1008 | } | |||
1009 | ||||
1010 | if (log && (info.si_code != SI_USERSI_USER || info.si_pid_sifields._kill.si_pid != 0)) | |||
1011 | log->Printf("NativeProcessLinux::%s (tid %" PRIu64"l" "u" ") unexpected signal info (si_code: %d, si_pid: %d). Treating as a new thread notification anyway.", __FUNCTION__, pid, info.si_code, info.si_pid_sifields._kill.si_pid); | |||
1012 | ||||
1013 | auto thread_sp = AddThread(pid); | |||
1014 | // Resume the newly created thread. | |||
1015 | ResumeThread(*thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
1016 | ThreadWasCreated(*thread_sp); | |||
1017 | return; | |||
1018 | } | |||
1019 | ||||
1020 | // Get details on the signal raised. | |||
1021 | if (info_err.Success()) | |||
1022 | { | |||
1023 | // We have retrieved the signal info. Dispatch appropriately. | |||
1024 | if (info.si_signo == SIGTRAP5) | |||
1025 | MonitorSIGTRAP(info, *thread_sp); | |||
1026 | else | |||
1027 | MonitorSignal(info, *thread_sp, exited); | |||
1028 | } | |||
1029 | else | |||
1030 | { | |||
1031 | if (info_err.GetError() == EINVAL22) | |||
1032 | { | |||
1033 | // This is a group stop reception for this tid. | |||
1034 | // We can reach here if we reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU into the | |||
1035 | // tracee, triggering the group-stop mechanism. Normally receiving these would stop | |||
1036 | // the process, pending a SIGCONT. Simulating this state in a debugger is hard and is | |||
1037 | // generally not needed (one use case is debugging background task being managed by a | |||
1038 | // shell). For general use, it is sufficient to stop the process in a signal-delivery | |||
1039 | // stop which happens before the group stop. This done by MonitorSignal and works | |||
1040 | // correctly for all signals. | |||
1041 | if (log) | |||
1042 | log->Printf("NativeProcessLinux::%s received a group stop for pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ". Transparent handling of group stops not supported, resuming the thread.", __FUNCTION__, GetID (), pid); | |||
1043 | ResumeThread(*thread_sp, thread_sp->GetState(), LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
1044 | } | |||
1045 | else | |||
1046 | { | |||
1047 | // ptrace(GETSIGINFO) failed (but not due to group-stop). | |||
1048 | ||||
1049 | // A return value of ESRCH means the thread/process is no longer on the system, | |||
1050 | // so it was killed somehow outside of our control. Either way, we can't do anything | |||
1051 | // with it anymore. | |||
1052 | ||||
1053 | // Stop tracking the metadata for the thread since it's entirely off the system now. | |||
1054 | const bool thread_found = StopTrackingThread (pid); | |||
1055 | ||||
1056 | if (log) | |||
1057 | log->Printf ("NativeProcessLinux::%s GetSignalInfo failed: %s, tid = %" PRIu64"l" "u" ", signal = %d, status = %d (%s, %s, %s)", | |||
1058 | __FUNCTION__, info_err.AsCString(), pid, signal, status, info_err.GetError() == 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"); | |||
1059 | ||||
1060 | if (is_main_thread) | |||
1061 | { | |||
1062 | // Notify the delegate - our process is not available but appears to have been killed outside | |||
1063 | // our control. Is eStateExited the right exit state in this case? | |||
1064 | SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true); | |||
1065 | SetState (StateType::eStateExited, true); | |||
1066 | } | |||
1067 | else | |||
1068 | { | |||
1069 | // This thread was pulled out from underneath us. Anything to do here? Do we want to do an all stop? | |||
1070 | if (log) | |||
1071 | 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__, GetID (), pid); | |||
1072 | } | |||
1073 | } | |||
1074 | } | |||
1075 | } | |||
1076 | ||||
1077 | void | |||
1078 | NativeProcessLinux::WaitForNewThread(::pid_t tid) | |||
1079 | { | |||
1080 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1081 | ||||
1082 | NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid); | |||
1083 | ||||
1084 | if (new_thread_sp) | |||
1085 | { | |||
1086 | // We are already tracking the thread - we got the event on the new thread (see | |||
1087 | // MonitorSignal) before this one. We are done. | |||
1088 | return; | |||
1089 | } | |||
1090 | ||||
1091 | // The thread is not tracked yet, let's wait for it to appear. | |||
1092 | int status = -1; | |||
1093 | ::pid_t wait_pid; | |||
1094 | do | |||
1095 | { | |||
1096 | if (log) | |||
1097 | log->Printf ("NativeProcessLinux::%s() received thread creation event for tid %" PRIu32"u" ". tid not tracked yet, waiting for thread to appear...", __FUNCTION__, tid); | |||
1098 | wait_pid = waitpid(tid, &status, __WALL0x40000000); | |||
1099 | } | |||
1100 | while (wait_pid == -1 && errno(*__errno_location ()) == EINTR4); | |||
1101 | // Since we are waiting on a specific tid, this must be the creation event. But let's do | |||
1102 | // some checks just in case. | |||
1103 | if (wait_pid != tid) { | |||
1104 | if (log) | |||
1105 | log->Printf ("NativeProcessLinux::%s() waiting for tid %" PRIu32"u" " failed. Assuming the thread has disappeared in the meantime", __FUNCTION__, tid); | |||
1106 | // The only way I know of this could happen is if the whole process was | |||
1107 | // SIGKILLed in the mean time. In any case, we can't do anything about that now. | |||
1108 | return; | |||
1109 | } | |||
1110 | if (WIFEXITED(status)((((*(int *) &(status))) & 0x7f) == 0)) | |||
1111 | { | |||
1112 | if (log) | |||
1113 | log->Printf ("NativeProcessLinux::%s() waiting for tid %" PRIu32"u" " returned an 'exited' event. Not tracking the thread.", __FUNCTION__, tid); | |||
1114 | // Also a very improbable event. | |||
1115 | return; | |||
1116 | } | |||
1117 | ||||
1118 | siginfo_t info; | |||
1119 | Error error = GetSignalInfo(tid, &info); | |||
1120 | if (error.Fail()) | |||
1121 | { | |||
1122 | if (log) | |||
1123 | log->Printf ("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32"u" " failed. Assuming the thread has disappeared in the meantime.", __FUNCTION__, tid); | |||
1124 | return; | |||
1125 | } | |||
1126 | ||||
1127 | if (((info.si_pid_sifields._kill.si_pid != 0) || (info.si_code != SI_USERSI_USER)) && log) | |||
1128 | { | |||
1129 | // We should be getting a thread creation signal here, but we received something | |||
1130 | // else. There isn't much we can do about it now, so we will just log that. Since the | |||
1131 | // thread is alive and we are receiving events from it, we shall pretend that it was | |||
1132 | // created properly. | |||
1133 | log->Printf ("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32"u" " received unexpected signal with code %d from pid %d.", __FUNCTION__, tid, info.si_code, info.si_pid_sifields._kill.si_pid); | |||
1134 | } | |||
1135 | ||||
1136 | if (log) | |||
1137 | log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64"l" "u" ": tracking new thread tid %" PRIu32"u", | |||
1138 | __FUNCTION__, GetID (), tid); | |||
1139 | ||||
1140 | new_thread_sp = AddThread(tid); | |||
1141 | ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
1142 | ThreadWasCreated(*new_thread_sp); | |||
1143 | } | |||
1144 | ||||
1145 | void | |||
1146 | NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread) | |||
1147 | { | |||
1148 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1149 | const bool is_main_thread = (thread.GetID() == GetID ()); | |||
1150 | ||||
1151 | assert(info.si_signo == SIGTRAP && "Unexpected child signal!")((info.si_signo == 5 && "Unexpected child signal!") ? static_cast<void> (0) : __assert_fail ("info.si_signo == 5 && \"Unexpected child signal!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1151, __PRETTY_FUNCTION__)); | |||
1152 | ||||
1153 | Mutex::Locker locker (m_threads_mutex); | |||
1154 | ||||
1155 | switch (info.si_code) | |||
1156 | { | |||
1157 | // TODO: these two cases are required if we want to support tracing of the inferiors' children. We'd need this to debug a monitor. | |||
1158 | // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)): | |||
1159 | // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)): | |||
1160 | ||||
1161 | case (SIGTRAP5 | (PTRACE_EVENT_CLONE << 8)): | |||
1162 | { | |||
1163 | // This is the notification on the parent thread which informs us of new thread | |||
1164 | // creation. | |||
1165 | // We don't want to do anything with the parent thread so we just resume it. In case we | |||
1166 | // want to implement "break on thread creation" functionality, we would need to stop | |||
1167 | // here. | |||
1168 | ||||
1169 | unsigned long event_message = 0; | |||
1170 | if (GetEventMessage(thread.GetID(), &event_message).Fail()) | |||
1171 | { | |||
1172 | if (log) | |||
1173 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" " received thread creation event but GetEventMessage failed so we don't know the new tid", __FUNCTION__, thread.GetID()); | |||
1174 | } else | |||
1175 | WaitForNewThread(event_message); | |||
1176 | ||||
1177 | ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
1178 | break; | |||
1179 | } | |||
1180 | ||||
1181 | case (SIGTRAP5 | (PTRACE_EVENT_EXEC << 8)): | |||
1182 | { | |||
1183 | NativeThreadLinuxSP main_thread_sp; | |||
1184 | if (log) | |||
1185 | log->Printf ("NativeProcessLinux::%s() received exec event, code = %d", __FUNCTION__, info.si_code ^ SIGTRAP5); | |||
1186 | ||||
1187 | // Exec clears any pending notifications. | |||
1188 | m_pending_notification_tid = LLDB_INVALID_THREAD_ID0; | |||
1189 | ||||
1190 | // Remove all but the main thread here. Linux fork creates a new process which only copies the main thread. Mutexes are in undefined state. | |||
1191 | if (log) | |||
1192 | log->Printf ("NativeProcessLinux::%s exec received, stop tracking all but main thread", __FUNCTION__); | |||
1193 | ||||
1194 | for (auto thread_sp : m_threads) | |||
1195 | { | |||
1196 | const bool is_main_thread = thread_sp && thread_sp->GetID () == GetID (); | |||
1197 | if (is_main_thread) | |||
1198 | { | |||
1199 | main_thread_sp = std::static_pointer_cast<NativeThreadLinux>(thread_sp); | |||
1200 | if (log) | |||
1201 | log->Printf ("NativeProcessLinux::%s found main thread with tid %" PRIu64"l" "u" ", keeping", __FUNCTION__, main_thread_sp->GetID ()); | |||
1202 | } | |||
1203 | else | |||
1204 | { | |||
1205 | if (log) | |||
1206 | log->Printf ("NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64"l" "u" " due to exec", __FUNCTION__, thread_sp->GetID ()); | |||
1207 | } | |||
1208 | } | |||
1209 | ||||
1210 | m_threads.clear (); | |||
1211 | ||||
1212 | if (main_thread_sp) | |||
1213 | { | |||
1214 | m_threads.push_back (main_thread_sp); | |||
1215 | SetCurrentThreadID (main_thread_sp->GetID ()); | |||
1216 | main_thread_sp->SetStoppedByExec(); | |||
1217 | } | |||
1218 | else | |||
1219 | { | |||
1220 | SetCurrentThreadID (LLDB_INVALID_THREAD_ID0); | |||
1221 | if (log) | |||
1222 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" "no main thread found, discarded all threads, we're in a no-thread state!", __FUNCTION__, GetID ()); | |||
1223 | } | |||
1224 | ||||
1225 | // Tell coordinator about about the "new" (since exec) stopped main thread. | |||
1226 | ThreadWasCreated(*main_thread_sp); | |||
1227 | ||||
1228 | // Let our delegate know we have just exec'd. | |||
1229 | NotifyDidExec (); | |||
1230 | ||||
1231 | // If we have a main thread, indicate we are stopped. | |||
1232 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1232, __PRETTY_FUNCTION__)); | |||
1233 | ||||
1234 | // Let the process know we're stopped. | |||
1235 | StopRunningThreads(main_thread_sp->GetID()); | |||
1236 | ||||
1237 | break; | |||
1238 | } | |||
1239 | ||||
1240 | case (SIGTRAP5 | (PTRACE_EVENT_EXIT << 8)): | |||
1241 | { | |||
1242 | // The inferior process or one of its threads is about to exit. | |||
1243 | // We don't want to do anything with the thread so we just resume it. In case we | |||
1244 | // want to implement "break on thread exit" functionality, we would need to stop | |||
1245 | // here. | |||
1246 | ||||
1247 | unsigned long data = 0; | |||
1248 | if (GetEventMessage(thread.GetID(), &data).Fail()) | |||
1249 | data = -1; | |||
1250 | ||||
1251 | if (log) | |||
1252 | { | |||
1253 | log->Printf ("NativeProcessLinux::%s() received PTRACE_EVENT_EXIT, data = %lx (WIFEXITED=%s,WIFSIGNALED=%s), pid = %" PRIu64"l" "u" " (%s)", | |||
1254 | __FUNCTION__, | |||
1255 | data, WIFEXITED (data)((((*(int *) &(data))) & 0x7f) == 0) ? "true" : "false", WIFSIGNALED (data)(((signed char) ((((*(int *) &(data))) & 0x7f) + 1) >> 1) > 0) ? "true" : "false", | |||
1256 | thread.GetID(), | |||
1257 | is_main_thread ? "is main thread" : "not main thread"); | |||
1258 | } | |||
1259 | ||||
1260 | if (is_main_thread) | |||
1261 | { | |||
1262 | SetExitStatus (convert_pid_status_to_exit_type (data), convert_pid_status_to_return_code (data), nullptr, true); | |||
1263 | } | |||
1264 | ||||
1265 | StateType state = thread.GetState(); | |||
1266 | if (! StateIsRunningState(state)) | |||
1267 | { | |||
1268 | // Due to a kernel bug, we may sometimes get this stop after the inferior gets a | |||
1269 | // SIGKILL. This confuses our state tracking logic in ResumeThread(), since normally, | |||
1270 | // we should not be receiving any ptrace events while the inferior is stopped. This | |||
1271 | // makes sure that the inferior is resumed and exits normally. | |||
1272 | state = eStateRunning; | |||
1273 | } | |||
1274 | ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
1275 | ||||
1276 | break; | |||
1277 | } | |||
1278 | ||||
1279 | case 0: | |||
1280 | case TRAP_TRACETRAP_TRACE: // We receive this on single stepping. | |||
1281 | case TRAP_HWBKPT4: // We receive this on watchpoint hit | |||
1282 | { | |||
1283 | // If a watchpoint was hit, report it | |||
1284 | uint32_t wp_index; | |||
1285 | Error error = thread.GetRegisterContext()->GetWatchpointHitIndex(wp_index, (uintptr_t)info.si_addr_sifields._sigfault.si_addr); | |||
1286 | if (error.Fail() && log) | |||
1287 | log->Printf("NativeProcessLinux::%s() " | |||
1288 | "received error while checking for watchpoint hits, " | |||
1289 | "pid = %" PRIu64"l" "u" " error = %s", | |||
1290 | __FUNCTION__, thread.GetID(), error.AsCString()); | |||
1291 | if (wp_index != LLDB_INVALID_INDEX32(4294967295U)) | |||
1292 | { | |||
1293 | MonitorWatchpoint(thread, wp_index); | |||
1294 | break; | |||
1295 | } | |||
1296 | ||||
1297 | // Otherwise, report step over | |||
1298 | MonitorTrace(thread); | |||
1299 | break; | |||
1300 | } | |||
1301 | ||||
1302 | case SI_KERNELSI_KERNEL: | |||
1303 | #if defined __mips__ | |||
1304 | // For mips there is no special signal for watchpoint | |||
1305 | // So we check for watchpoint in kernel trap | |||
1306 | { | |||
1307 | // If a watchpoint was hit, report it | |||
1308 | uint32_t wp_index; | |||
1309 | Error error = thread.GetRegisterContext()->GetWatchpointHitIndex(wp_index, LLDB_INVALID_ADDRESS(18446744073709551615UL)); | |||
1310 | if (error.Fail() && log) | |||
1311 | log->Printf("NativeProcessLinux::%s() " | |||
1312 | "received error while checking for watchpoint hits, " | |||
1313 | "pid = %" PRIu64"l" "u" " error = %s", | |||
1314 | __FUNCTION__, thread.GetID(), error.AsCString()); | |||
1315 | if (wp_index != LLDB_INVALID_INDEX32(4294967295U)) | |||
1316 | { | |||
1317 | MonitorWatchpoint(thread, wp_index); | |||
1318 | break; | |||
1319 | } | |||
1320 | } | |||
1321 | // NO BREAK | |||
1322 | #endif | |||
1323 | case TRAP_BRKPTTRAP_BRKPT: | |||
1324 | MonitorBreakpoint(thread); | |||
1325 | break; | |||
1326 | ||||
1327 | case SIGTRAP5: | |||
1328 | case (SIGTRAP5 | 0x80): | |||
1329 | if (log) | |||
1330 | log->Printf ("NativeProcessLinux::%s() received unknown SIGTRAP system call stop event, pid %" PRIu64"l" "u" "tid %" PRIu64"l" "u" ", resuming", __FUNCTION__, GetID (), thread.GetID()); | |||
1331 | ||||
1332 | // Ignore these signals until we know more about them. | |||
1333 | ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER(2147483647)); | |||
1334 | break; | |||
1335 | ||||
1336 | default: | |||
1337 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1337, __PRETTY_FUNCTION__)); | |||
1338 | if (log) | |||
1339 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" "tid %" PRIu64"l" "u" " received unhandled SIGTRAP code: 0x%d", | |||
1340 | __FUNCTION__, GetID(), thread.GetID(), info.si_code); | |||
1341 | break; | |||
1342 | ||||
1343 | } | |||
1344 | } | |||
1345 | ||||
1346 | void | |||
1347 | NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) | |||
1348 | { | |||
1349 | Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1350 | if (log) | |||
1351 | log->Printf("NativeProcessLinux::%s() received trace event, pid = %" PRIu64"l" "u" " (single stepping)", | |||
1352 | __FUNCTION__, thread.GetID()); | |||
1353 | ||||
1354 | // This thread is currently stopped. | |||
1355 | thread.SetStoppedByTrace(); | |||
1356 | ||||
1357 | StopRunningThreads(thread.GetID()); | |||
1358 | } | |||
1359 | ||||
1360 | void | |||
1361 | NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) | |||
1362 | { | |||
1363 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_BREAKPOINTS(1u << 5))); | |||
1364 | if (log) | |||
1365 | log->Printf("NativeProcessLinux::%s() received breakpoint event, pid = %" PRIu64"l" "u", | |||
1366 | __FUNCTION__, thread.GetID()); | |||
1367 | ||||
1368 | // Mark the thread as stopped at breakpoint. | |||
1369 | thread.SetStoppedByBreakpoint(); | |||
1370 | Error error = FixupBreakpointPCAsNeeded(thread); | |||
1371 | if (error.Fail()) | |||
1372 | if (log) | |||
1373 | log->Printf("NativeProcessLinux::%s() pid = %" PRIu64"l" "u" " fixup: %s", | |||
1374 | __FUNCTION__, thread.GetID(), error.AsCString()); | |||
1375 | ||||
1376 | if (m_threads_stepping_with_breakpoint.find(thread.GetID()) != m_threads_stepping_with_breakpoint.end()) | |||
1377 | thread.SetStoppedByTrace(); | |||
1378 | ||||
1379 | StopRunningThreads(thread.GetID()); | |||
1380 | } | |||
1381 | ||||
1382 | void | |||
1383 | NativeProcessLinux::MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index) | |||
1384 | { | |||
1385 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_WATCHPOINTS(1u << 6))); | |||
1386 | if (log) | |||
1387 | log->Printf("NativeProcessLinux::%s() received watchpoint event, " | |||
1388 | "pid = %" PRIu64"l" "u" ", wp_index = %" PRIu32"u", | |||
1389 | __FUNCTION__, thread.GetID(), wp_index); | |||
1390 | ||||
1391 | // Mark the thread as stopped at watchpoint. | |||
1392 | // The address is at (lldb::addr_t)info->si_addr if we need it. | |||
1393 | thread.SetStoppedByWatchpoint(wp_index); | |||
1394 | ||||
1395 | // We need to tell all other running threads before we notify the delegate about this stop. | |||
1396 | StopRunningThreads(thread.GetID()); | |||
1397 | } | |||
1398 | ||||
1399 | void | |||
1400 | NativeProcessLinux::MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, bool exited) | |||
1401 | { | |||
1402 | const int signo = info.si_signo; | |||
1403 | const bool is_from_llgs = info.si_pid_sifields._kill.si_pid == getpid (); | |||
1404 | ||||
1405 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1406 | ||||
1407 | // POSIX says that process behaviour is undefined after it ignores a SIGFPE, | |||
1408 | // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a | |||
1409 | // kill(2) or raise(3). Similarly for tgkill(2) on Linux. | |||
1410 | // | |||
1411 | // IOW, user generated signals never generate what we consider to be a | |||
1412 | // "crash". | |||
1413 | // | |||
1414 | // Similarly, ACK signals generated by this monitor. | |||
1415 | ||||
1416 | Mutex::Locker locker (m_threads_mutex); | |||
1417 | ||||
1418 | // Handle the signal. | |||
1419 | if (info.si_code == SI_TKILLSI_TKILL || info.si_code == SI_USERSI_USER) | |||
1420 | { | |||
1421 | if (log) | |||
1422 | log->Printf ("NativeProcessLinux::%s() received signal %s (%d) with code %s, (siginfo pid = %d (%s), waitpid pid = %" PRIu64"l" "u" ")", | |||
1423 | __FUNCTION__, | |||
1424 | Host::GetSignalAsCString(signo), | |||
1425 | signo, | |||
1426 | (info.si_code == SI_TKILLSI_TKILL ? "SI_TKILL" : "SI_USER"), | |||
1427 | info.si_pid_sifields._kill.si_pid, | |||
1428 | is_from_llgs ? "from llgs" : "not from llgs", | |||
1429 | thread.GetID()); | |||
1430 | } | |||
1431 | ||||
1432 | // Check for thread stop notification. | |||
1433 | if (is_from_llgs && (info.si_code == SI_TKILLSI_TKILL) && (signo == SIGSTOP19)) | |||
1434 | { | |||
1435 | // This is a tgkill()-based stop. | |||
1436 | if (log) | |||
1437 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ", thread stopped", | |||
1438 | __FUNCTION__, | |||
1439 | GetID (), | |||
1440 | thread.GetID()); | |||
1441 | ||||
1442 | // Check that we're not already marked with a stop reason. | |||
1443 | // Note this thread really shouldn't already be marked as stopped - if we were, that would imply that | |||
1444 | // the kernel signaled us with the thread stopping which we handled and marked as stopped, | |||
1445 | // and that, without an intervening resume, we received another stop. It is more likely | |||
1446 | // that we are missing the marking of a run state somewhere if we find that the thread was | |||
1447 | // marked as stopped. | |||
1448 | const StateType thread_state = thread.GetState(); | |||
1449 | if (!StateIsStoppedState (thread_state, false)) | |||
1450 | { | |||
1451 | // An inferior thread has stopped because of a SIGSTOP we have sent it. | |||
1452 | // Generally, these are not important stops and we don't want to report them as | |||
1453 | // they are just used to stop other threads when one thread (the one with the | |||
1454 | // *real* stop reason) hits a breakpoint (watchpoint, etc...). However, in the | |||
1455 | // case of an asynchronous Interrupt(), this *is* the real stop reason, so we | |||
1456 | // leave the signal intact if this is the thread that was chosen as the | |||
1457 | // triggering thread. | |||
1458 | if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID0) | |||
1459 | { | |||
1460 | if (m_pending_notification_tid == thread.GetID()) | |||
1461 | thread.SetStoppedBySignal(SIGSTOP19, &info); | |||
1462 | else | |||
1463 | thread.SetStoppedWithNoReason(); | |||
1464 | ||||
1465 | SetCurrentThreadID (thread.GetID ()); | |||
1466 | SignalIfAllThreadsStopped(); | |||
1467 | } | |||
1468 | else | |||
1469 | { | |||
1470 | // We can end up here if stop was initiated by LLGS but by this time a | |||
1471 | // thread stop has occurred - maybe initiated by another event. | |||
1472 | Error error = ResumeThread(thread, thread.GetState(), 0); | |||
1473 | if (error.Fail() && log) | |||
1474 | { | |||
1475 | log->Printf("NativeProcessLinux::%s failed to resume thread tid %" PRIu64"l" "u" ": %s", | |||
1476 | __FUNCTION__, thread.GetID(), error.AsCString()); | |||
1477 | } | |||
1478 | } | |||
1479 | } | |||
1480 | else | |||
1481 | { | |||
1482 | if (log) | |||
1483 | { | |||
1484 | // Retrieve the signal name if the thread was stopped by a signal. | |||
1485 | int stop_signo = 0; | |||
1486 | const bool stopped_by_signal = thread.IsStopped(&stop_signo); | |||
1487 | const char *signal_name = stopped_by_signal ? Host::GetSignalAsCString(stop_signo) : "<not stopped by signal>"; | |||
1488 | if (!signal_name) | |||
1489 | signal_name = "<no-signal-name>"; | |||
1490 | ||||
1491 | log->Printf ("NativeProcessLinux::%s() pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ", thread was already marked as a stopped state (state=%s, signal=%d (%s)), leaving stop signal as is", | |||
1492 | __FUNCTION__, | |||
1493 | GetID (), | |||
1494 | thread.GetID(), | |||
1495 | StateAsCString (thread_state), | |||
1496 | stop_signo, | |||
1497 | signal_name); | |||
1498 | } | |||
1499 | SignalIfAllThreadsStopped(); | |||
1500 | } | |||
1501 | ||||
1502 | // Done handling. | |||
1503 | return; | |||
1504 | } | |||
1505 | ||||
1506 | if (log) | |||
1507 | log->Printf ("NativeProcessLinux::%s() received signal %s", __FUNCTION__, Host::GetSignalAsCString(signo)); | |||
1508 | ||||
1509 | // This thread is stopped. | |||
1510 | thread.SetStoppedBySignal(signo, &info); | |||
1511 | ||||
1512 | // Send a stop to the debugger after we get all other threads to stop. | |||
1513 | StopRunningThreads(thread.GetID()); | |||
1514 | } | |||
1515 | ||||
1516 | namespace { | |||
1517 | ||||
1518 | struct EmulatorBaton | |||
1519 | { | |||
1520 | NativeProcessLinux* m_process; | |||
1521 | NativeRegisterContext* m_reg_context; | |||
1522 | ||||
1523 | // eRegisterKindDWARF -> RegsiterValue | |||
1524 | std::unordered_map<uint32_t, RegisterValue> m_register_values; | |||
1525 | ||||
1526 | EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) : | |||
1527 | m_process(process), m_reg_context(reg_context) {} | |||
1528 | }; | |||
1529 | ||||
1530 | } // anonymous namespace | |||
1531 | ||||
1532 | static size_t | |||
1533 | ReadMemoryCallback (EmulateInstruction *instruction, | |||
1534 | void *baton, | |||
1535 | const EmulateInstruction::Context &context, | |||
1536 | lldb::addr_t addr, | |||
1537 | void *dst, | |||
1538 | size_t length) | |||
1539 | { | |||
1540 | EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); | |||
1541 | ||||
1542 | size_t bytes_read; | |||
1543 | emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); | |||
1544 | return bytes_read; | |||
1545 | } | |||
1546 | ||||
1547 | static bool | |||
1548 | ReadRegisterCallback (EmulateInstruction *instruction, | |||
1549 | void *baton, | |||
1550 | const RegisterInfo *reg_info, | |||
1551 | RegisterValue ®_value) | |||
1552 | { | |||
1553 | EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); | |||
1554 | ||||
1555 | auto it = emulator_baton->m_register_values.find(reg_info->kinds[eRegisterKindDWARF]); | |||
1556 | if (it != emulator_baton->m_register_values.end()) | |||
1557 | { | |||
1558 | reg_value = it->second; | |||
1559 | return true; | |||
1560 | } | |||
1561 | ||||
1562 | // The emulator only fill in the dwarf regsiter numbers (and in some case | |||
1563 | // the generic register numbers). Get the full register info from the | |||
1564 | // register context based on the dwarf register numbers. | |||
1565 | const RegisterInfo* full_reg_info = emulator_baton->m_reg_context->GetRegisterInfo( | |||
1566 | eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); | |||
1567 | ||||
1568 | Error error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); | |||
1569 | if (error.Success()) | |||
1570 | return true; | |||
1571 | ||||
1572 | return false; | |||
1573 | } | |||
1574 | ||||
1575 | static bool | |||
1576 | WriteRegisterCallback (EmulateInstruction *instruction, | |||
1577 | void *baton, | |||
1578 | const EmulateInstruction::Context &context, | |||
1579 | const RegisterInfo *reg_info, | |||
1580 | const RegisterValue ®_value) | |||
1581 | { | |||
1582 | EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); | |||
1583 | emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = reg_value; | |||
1584 | return true; | |||
1585 | } | |||
1586 | ||||
1587 | static size_t | |||
1588 | WriteMemoryCallback (EmulateInstruction *instruction, | |||
1589 | void *baton, | |||
1590 | const EmulateInstruction::Context &context, | |||
1591 | lldb::addr_t addr, | |||
1592 | const void *dst, | |||
1593 | size_t length) | |||
1594 | { | |||
1595 | return length; | |||
1596 | } | |||
1597 | ||||
1598 | static lldb::addr_t | |||
1599 | ReadFlags (NativeRegisterContext* regsiter_context) | |||
1600 | { | |||
1601 | const RegisterInfo* flags_info = regsiter_context->GetRegisterInfo( | |||
1602 | eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS4); | |||
1603 | return regsiter_context->ReadRegisterAsUnsigned(flags_info, LLDB_INVALID_ADDRESS(18446744073709551615UL)); | |||
1604 | } | |||
1605 | ||||
1606 | Error | |||
1607 | NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) | |||
1608 | { | |||
1609 | Error error; | |||
1610 | NativeRegisterContextSP register_context_sp = thread.GetRegisterContext(); | |||
1611 | ||||
1612 | std::unique_ptr<EmulateInstruction> emulator_ap( | |||
1613 | EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, nullptr)); | |||
1614 | ||||
1615 | if (emulator_ap == nullptr) | |||
1616 | return Error("Instruction emulator not found!"); | |||
1617 | ||||
1618 | EmulatorBaton baton(this, register_context_sp.get()); | |||
1619 | emulator_ap->SetBaton(&baton); | |||
1620 | emulator_ap->SetReadMemCallback(&ReadMemoryCallback); | |||
1621 | emulator_ap->SetReadRegCallback(&ReadRegisterCallback); | |||
1622 | emulator_ap->SetWriteMemCallback(&WriteMemoryCallback); | |||
1623 | emulator_ap->SetWriteRegCallback(&WriteRegisterCallback); | |||
1624 | ||||
1625 | if (!emulator_ap->ReadInstruction()) | |||
1626 | return Error("Read instruction failed!"); | |||
1627 | ||||
1628 | bool emulation_result = emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); | |||
1629 | ||||
1630 | const RegisterInfo* reg_info_pc = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC0); | |||
1631 | const RegisterInfo* reg_info_flags = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS4); | |||
1632 | ||||
1633 | auto pc_it = baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]); | |||
1634 | auto flags_it = baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]); | |||
1635 | ||||
1636 | lldb::addr_t next_pc; | |||
1637 | lldb::addr_t next_flags; | |||
1638 | if (emulation_result) | |||
1639 | { | |||
1640 | assert(pc_it != baton.m_register_values.end() && "Emulation was successfull but PC wasn't updated")((pc_it != baton.m_register_values.end() && "Emulation was successfull but PC wasn't updated" ) ? static_cast<void> (0) : __assert_fail ("pc_it != baton.m_register_values.end() && \"Emulation was successfull but PC wasn't updated\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1640, __PRETTY_FUNCTION__)); | |||
1641 | next_pc = pc_it->second.GetAsUInt64(); | |||
1642 | ||||
1643 | if (flags_it != baton.m_register_values.end()) | |||
1644 | next_flags = flags_it->second.GetAsUInt64(); | |||
1645 | else | |||
1646 | next_flags = ReadFlags (register_context_sp.get()); | |||
1647 | } | |||
1648 | else if (pc_it == baton.m_register_values.end()) | |||
1649 | { | |||
1650 | // Emulate instruction failed and it haven't changed PC. Advance PC | |||
1651 | // with the size of the current opcode because the emulation of all | |||
1652 | // PC modifying instruction should be successful. The failure most | |||
1653 | // likely caused by a not supported instruction which don't modify PC. | |||
1654 | next_pc = register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize(); | |||
1655 | next_flags = ReadFlags (register_context_sp.get()); | |||
1656 | } | |||
1657 | else | |||
1658 | { | |||
1659 | // The instruction emulation failed after it modified the PC. It is an | |||
1660 | // unknown error where we can't continue because the next instruction is | |||
1661 | // modifying the PC but we don't know how. | |||
1662 | return Error ("Instruction emulation failed unexpectedly."); | |||
1663 | } | |||
1664 | ||||
1665 | if (m_arch.GetMachine() == llvm::Triple::arm) | |||
1666 | { | |||
1667 | if (next_flags & 0x20) | |||
1668 | { | |||
1669 | // Thumb mode | |||
1670 | error = SetSoftwareBreakpoint(next_pc, 2); | |||
1671 | } | |||
1672 | else | |||
1673 | { | |||
1674 | // Arm mode | |||
1675 | error = SetSoftwareBreakpoint(next_pc, 4); | |||
1676 | } | |||
1677 | } | |||
1678 | else if (m_arch.GetMachine() == llvm::Triple::mips64 | |||
1679 | || m_arch.GetMachine() == llvm::Triple::mips64el | |||
1680 | || m_arch.GetMachine() == llvm::Triple::mips | |||
1681 | || m_arch.GetMachine() == llvm::Triple::mipsel) | |||
1682 | error = SetSoftwareBreakpoint(next_pc, 4); | |||
1683 | else | |||
1684 | { | |||
1685 | // No size hint is given for the next breakpoint | |||
1686 | error = SetSoftwareBreakpoint(next_pc, 0); | |||
1687 | } | |||
1688 | ||||
1689 | if (error.Fail()) | |||
1690 | return error; | |||
1691 | ||||
1692 | m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc}); | |||
1693 | ||||
1694 | return Error(); | |||
1695 | } | |||
1696 | ||||
1697 | bool | |||
1698 | NativeProcessLinux::SupportHardwareSingleStepping() const | |||
1699 | { | |||
1700 | if (m_arch.GetMachine() == llvm::Triple::arm | |||
1701 | || m_arch.GetMachine() == llvm::Triple::mips64 || m_arch.GetMachine() == llvm::Triple::mips64el | |||
1702 | || m_arch.GetMachine() == llvm::Triple::mips || m_arch.GetMachine() == llvm::Triple::mipsel) | |||
1703 | return false; | |||
1704 | return true; | |||
1705 | } | |||
1706 | ||||
1707 | Error | |||
1708 | NativeProcessLinux::Resume (const ResumeActionList &resume_actions) | |||
1709 | { | |||
1710 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_THREAD(1u << 2))); | |||
1711 | if (log) | |||
1712 | log->Printf ("NativeProcessLinux::%s called: pid %" PRIu64"l" "u", __FUNCTION__, GetID ()); | |||
1713 | ||||
1714 | bool software_single_step = !SupportHardwareSingleStepping(); | |||
1715 | ||||
1716 | Mutex::Locker locker (m_threads_mutex); | |||
1717 | ||||
1718 | if (software_single_step) | |||
1719 | { | |||
1720 | for (auto thread_sp : m_threads) | |||
1721 | { | |||
1722 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1722, __PRETTY_FUNCTION__)); | |||
1723 | ||||
1724 | const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true); | |||
1725 | if (action == nullptr) | |||
1726 | continue; | |||
1727 | ||||
1728 | if (action->state == eStateStepping) | |||
1729 | { | |||
1730 | Error error = SetupSoftwareSingleStepping(static_cast<NativeThreadLinux &>(*thread_sp)); | |||
1731 | if (error.Fail()) | |||
1732 | return error; | |||
1733 | } | |||
1734 | } | |||
1735 | } | |||
1736 | ||||
1737 | for (auto thread_sp : m_threads) | |||
1738 | { | |||
1739 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1739, __PRETTY_FUNCTION__)); | |||
1740 | ||||
1741 | const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true); | |||
1742 | ||||
1743 | if (action == nullptr) | |||
1744 | { | |||
1745 | if (log) | |||
1746 | log->Printf ("NativeProcessLinux::%s no action specified for pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u", | |||
1747 | __FUNCTION__, GetID (), thread_sp->GetID ()); | |||
1748 | continue; | |||
1749 | } | |||
1750 | ||||
1751 | if (log) | |||
1752 | { | |||
1753 | log->Printf ("NativeProcessLinux::%s processing resume action state %s for pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u", | |||
1754 | __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ()); | |||
1755 | } | |||
1756 | ||||
1757 | switch (action->state) | |||
1758 | { | |||
1759 | case eStateRunning: | |||
1760 | case eStateStepping: | |||
1761 | { | |||
1762 | // Run the thread, possibly feeding it the signal. | |||
1763 | const int signo = action->signal; | |||
1764 | ResumeThread(static_cast<NativeThreadLinux &>(*thread_sp), action->state, signo); | |||
1765 | break; | |||
1766 | } | |||
1767 | ||||
1768 | case eStateSuspended: | |||
1769 | case eStateStopped: | |||
1770 | lldbassert(0 && "Unexpected state")lldb_private::lldb_assert(0 && "Unexpected state", "0 && \"Unexpected state\"" , __FUNCTION__, "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1770); | |||
1771 | ||||
1772 | default: | |||
1773 | return Error ("NativeProcessLinux::%s (): unexpected state %s specified for pid %" PRIu64"l" "u" ", tid %" PRIu64"l" "u", | |||
1774 | __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ()); | |||
1775 | } | |||
1776 | } | |||
1777 | ||||
1778 | return Error(); | |||
1779 | } | |||
1780 | ||||
1781 | Error | |||
1782 | NativeProcessLinux::Halt () | |||
1783 | { | |||
1784 | Error error; | |||
1785 | ||||
1786 | if (kill (GetID (), SIGSTOP19) != 0) | |||
1787 | error.SetErrorToErrno (); | |||
1788 | ||||
1789 | return error; | |||
1790 | } | |||
1791 | ||||
1792 | Error | |||
1793 | NativeProcessLinux::Detach () | |||
1794 | { | |||
1795 | Error error; | |||
1796 | ||||
1797 | // Stop monitoring the inferior. | |||
1798 | m_sigchld_handle.reset(); | |||
1799 | ||||
1800 | // Tell ptrace to detach from the process. | |||
1801 | if (GetID () == LLDB_INVALID_PROCESS_ID0) | |||
1802 | return error; | |||
1803 | ||||
1804 | for (auto thread_sp : m_threads) | |||
1805 | { | |||
1806 | Error e = Detach(thread_sp->GetID()); | |||
1807 | if (e.Fail()) | |||
1808 | error = e; // Save the error, but still attempt to detach from other threads. | |||
1809 | } | |||
1810 | ||||
1811 | return error; | |||
1812 | } | |||
1813 | ||||
1814 | Error | |||
1815 | NativeProcessLinux::Signal (int signo) | |||
1816 | { | |||
1817 | Error error; | |||
1818 | ||||
1819 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1820 | if (log) | |||
1821 | log->Printf ("NativeProcessLinux::%s: sending signal %d (%s) to pid %" PRIu64"l" "u", | |||
1822 | __FUNCTION__, signo, Host::GetSignalAsCString(signo), GetID()); | |||
1823 | ||||
1824 | if (kill(GetID(), signo)) | |||
1825 | error.SetErrorToErrno(); | |||
1826 | ||||
1827 | return error; | |||
1828 | } | |||
1829 | ||||
1830 | Error | |||
1831 | NativeProcessLinux::Interrupt () | |||
1832 | { | |||
1833 | // Pick a running thread (or if none, a not-dead stopped thread) as | |||
1834 | // the chosen thread that will be the stop-reason thread. | |||
1835 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1836 | ||||
1837 | NativeThreadProtocolSP running_thread_sp; | |||
1838 | NativeThreadProtocolSP stopped_thread_sp; | |||
1839 | ||||
1840 | if (log) | |||
1841 | log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__); | |||
1842 | ||||
1843 | Mutex::Locker locker (m_threads_mutex); | |||
1844 | ||||
1845 | for (auto thread_sp : m_threads) | |||
1846 | { | |||
1847 | // The thread shouldn't be null but lets just cover that here. | |||
1848 | if (!thread_sp) | |||
1849 | continue; | |||
1850 | ||||
1851 | // If we have a running or stepping thread, we'll call that the | |||
1852 | // target of the interrupt. | |||
1853 | const auto thread_state = thread_sp->GetState (); | |||
1854 | if (thread_state == eStateRunning || | |||
1855 | thread_state == eStateStepping) | |||
1856 | { | |||
1857 | running_thread_sp = thread_sp; | |||
1858 | break; | |||
1859 | } | |||
1860 | else if (!stopped_thread_sp && StateIsStoppedState (thread_state, true)) | |||
1861 | { | |||
1862 | // Remember the first non-dead stopped thread. We'll use that as a backup if there are no running threads. | |||
1863 | stopped_thread_sp = thread_sp; | |||
1864 | } | |||
1865 | } | |||
1866 | ||||
1867 | if (!running_thread_sp && !stopped_thread_sp) | |||
1868 | { | |||
1869 | Error error("found no running/stepping or live stopped threads as target for interrupt"); | |||
1870 | if (log) | |||
1871 | log->Printf ("NativeProcessLinux::%s skipping due to error: %s", __FUNCTION__, error.AsCString ()); | |||
1872 | ||||
1873 | return error; | |||
1874 | } | |||
1875 | ||||
1876 | NativeThreadProtocolSP deferred_signal_thread_sp = running_thread_sp ? running_thread_sp : stopped_thread_sp; | |||
1877 | ||||
1878 | if (log) | |||
1879 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " %s tid %" PRIu64"l" "u" " chosen for interrupt target", | |||
1880 | __FUNCTION__, | |||
1881 | GetID (), | |||
1882 | running_thread_sp ? "running" : "stopped", | |||
1883 | deferred_signal_thread_sp->GetID ()); | |||
1884 | ||||
1885 | StopRunningThreads(deferred_signal_thread_sp->GetID()); | |||
1886 | ||||
1887 | return Error(); | |||
1888 | } | |||
1889 | ||||
1890 | Error | |||
1891 | NativeProcessLinux::Kill () | |||
1892 | { | |||
1893 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1894 | if (log) | |||
1895 | log->Printf ("NativeProcessLinux::%s called for PID %" PRIu64"l" "u", __FUNCTION__, GetID ()); | |||
1896 | ||||
1897 | Error error; | |||
1898 | ||||
1899 | switch (m_state) | |||
1900 | { | |||
1901 | case StateType::eStateInvalid: | |||
1902 | case StateType::eStateExited: | |||
1903 | case StateType::eStateCrashed: | |||
1904 | case StateType::eStateDetached: | |||
1905 | case StateType::eStateUnloaded: | |||
1906 | // Nothing to do - the process is already dead. | |||
1907 | if (log) | |||
1908 | log->Printf ("NativeProcessLinux::%s ignored for PID %" PRIu64"l" "u" " due to current state: %s", __FUNCTION__, GetID (), StateAsCString (m_state)); | |||
1909 | return error; | |||
1910 | ||||
1911 | case StateType::eStateConnected: | |||
1912 | case StateType::eStateAttaching: | |||
1913 | case StateType::eStateLaunching: | |||
1914 | case StateType::eStateStopped: | |||
1915 | case StateType::eStateRunning: | |||
1916 | case StateType::eStateStepping: | |||
1917 | case StateType::eStateSuspended: | |||
1918 | // We can try to kill a process in these states. | |||
1919 | break; | |||
1920 | } | |||
1921 | ||||
1922 | if (kill (GetID (), SIGKILL9) != 0) | |||
1923 | { | |||
1924 | error.SetErrorToErrno (); | |||
1925 | return error; | |||
1926 | } | |||
1927 | ||||
1928 | return error; | |||
1929 | } | |||
1930 | ||||
1931 | static Error | |||
1932 | ParseMemoryRegionInfoFromProcMapsLine (const std::string &maps_line, MemoryRegionInfo &memory_region_info) | |||
1933 | { | |||
1934 | memory_region_info.Clear(); | |||
1935 | ||||
1936 | StringExtractor line_extractor (maps_line.c_str ()); | |||
1937 | ||||
1938 | // Format: {address_start_hex}-{address_end_hex} perms offset dev inode pathname | |||
1939 | // perms: rwxp (letter is present if set, '-' if not, final character is p=private, s=shared). | |||
1940 | ||||
1941 | // Parse out the starting address | |||
1942 | lldb::addr_t start_address = line_extractor.GetHexMaxU64 (false, 0); | |||
1943 | ||||
1944 | // Parse out hyphen separating start and end address from range. | |||
1945 | if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != '-')) | |||
1946 | return Error ("malformed /proc/{pid}/maps entry, missing dash between address range"); | |||
1947 | ||||
1948 | // Parse out the ending address | |||
1949 | lldb::addr_t end_address = line_extractor.GetHexMaxU64 (false, start_address); | |||
1950 | ||||
1951 | // Parse out the space after the address. | |||
1952 | if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != ' ')) | |||
1953 | return Error ("malformed /proc/{pid}/maps entry, missing space after range"); | |||
1954 | ||||
1955 | // Save the range. | |||
1956 | memory_region_info.GetRange ().SetRangeBase (start_address); | |||
1957 | memory_region_info.GetRange ().SetRangeEnd (end_address); | |||
1958 | ||||
1959 | // Parse out each permission entry. | |||
1960 | if (line_extractor.GetBytesLeft () < 4) | |||
1961 | return Error ("malformed /proc/{pid}/maps entry, missing some portion of permissions"); | |||
1962 | ||||
1963 | // Handle read permission. | |||
1964 | const char read_perm_char = line_extractor.GetChar (); | |||
1965 | if (read_perm_char == 'r') | |||
1966 | memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eYes); | |||
1967 | else | |||
1968 | { | |||
1969 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1969, __PRETTY_FUNCTION__)); | |||
1970 | memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); | |||
1971 | } | |||
1972 | ||||
1973 | // Handle write permission. | |||
1974 | const char write_perm_char = line_extractor.GetChar (); | |||
1975 | if (write_perm_char == 'w') | |||
1976 | memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eYes); | |||
1977 | else | |||
1978 | { | |||
1979 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1979, __PRETTY_FUNCTION__)); | |||
1980 | memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); | |||
1981 | } | |||
1982 | ||||
1983 | // Handle execute permission. | |||
1984 | const char exec_perm_char = line_extractor.GetChar (); | |||
1985 | if (exec_perm_char == 'x') | |||
1986 | memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eYes); | |||
1987 | else | |||
1988 | { | |||
1989 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 1989, __PRETTY_FUNCTION__)); | |||
1990 | memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); | |||
1991 | } | |||
1992 | ||||
1993 | return Error (); | |||
1994 | } | |||
1995 | ||||
1996 | Error | |||
1997 | NativeProcessLinux::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) | |||
1998 | { | |||
1999 | // FIXME review that the final memory region returned extends to the end of the virtual address space, | |||
2000 | // with no perms if it is not mapped. | |||
2001 | ||||
2002 | // Use an approach that reads memory regions from /proc/{pid}/maps. | |||
2003 | // Assume proc maps entries are in ascending order. | |||
2004 | // FIXME assert if we find differently. | |||
2005 | Mutex::Locker locker (m_mem_region_cache_mutex); | |||
2006 | ||||
2007 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2008 | Error error; | |||
2009 | ||||
2010 | if (m_supports_mem_region == LazyBool::eLazyBoolNo) | |||
2011 | { | |||
2012 | // We're done. | |||
2013 | error.SetErrorString ("unsupported"); | |||
2014 | return error; | |||
2015 | } | |||
2016 | ||||
2017 | // If our cache is empty, pull the latest. There should always be at least one memory region | |||
2018 | // if memory region handling is supported. | |||
2019 | if (m_mem_region_cache.empty ()) | |||
2020 | { | |||
2021 | error = ProcFileReader::ProcessLineByLine (GetID (), "maps", | |||
2022 | [&] (const std::string &line) -> bool | |||
2023 | { | |||
2024 | MemoryRegionInfo info; | |||
2025 | const Error parse_error = ParseMemoryRegionInfoFromProcMapsLine (line, info); | |||
2026 | if (parse_error.Success ()) | |||
2027 | { | |||
2028 | m_mem_region_cache.push_back (info); | |||
2029 | return true; | |||
2030 | } | |||
2031 | else | |||
2032 | { | |||
2033 | if (log) | |||
2034 | log->Printf ("NativeProcessLinux::%s failed to parse proc maps line '%s': %s", __FUNCTION__, line.c_str (), error.AsCString ()); | |||
2035 | return false; | |||
2036 | } | |||
2037 | }); | |||
2038 | ||||
2039 | // If we had an error, we'll mark unsupported. | |||
2040 | if (error.Fail ()) | |||
2041 | { | |||
2042 | m_supports_mem_region = LazyBool::eLazyBoolNo; | |||
2043 | return error; | |||
2044 | } | |||
2045 | else if (m_mem_region_cache.empty ()) | |||
2046 | { | |||
2047 | // No entries after attempting to read them. This shouldn't happen if /proc/{pid}/maps | |||
2048 | // is supported. Assume we don't support map entries via procfs. | |||
2049 | if (log) | |||
2050 | log->Printf ("NativeProcessLinux::%s failed to find any procfs maps entries, assuming no support for memory region metadata retrieval", __FUNCTION__); | |||
2051 | m_supports_mem_region = LazyBool::eLazyBoolNo; | |||
2052 | error.SetErrorString ("not supported"); | |||
2053 | return error; | |||
2054 | } | |||
2055 | ||||
2056 | if (log) | |||
2057 | 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 ()); | |||
2058 | ||||
2059 | // We support memory retrieval, remember that. | |||
2060 | m_supports_mem_region = LazyBool::eLazyBoolYes; | |||
2061 | } | |||
2062 | else | |||
2063 | { | |||
2064 | if (log) | |||
2065 | log->Printf ("NativeProcessLinux::%s reusing %" PRIu64"l" "u" " cached memory region entries", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ())); | |||
2066 | } | |||
2067 | ||||
2068 | lldb::addr_t prev_base_address = 0; | |||
2069 | ||||
2070 | // FIXME start by finding the last region that is <= target address using binary search. Data is sorted. | |||
2071 | // There can be a ton of regions on pthreads apps with lots of threads. | |||
2072 | for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end (); ++it) | |||
2073 | { | |||
2074 | MemoryRegionInfo &proc_entry_info = *it; | |||
2075 | ||||
2076 | // Sanity check assumption that /proc/{pid}/maps entries are ascending. | |||
2077 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2077, __PRETTY_FUNCTION__)); | |||
2078 | prev_base_address = proc_entry_info.GetRange ().GetRangeBase (); | |||
2079 | ||||
2080 | // If the target address comes before this entry, indicate distance to next region. | |||
2081 | if (load_addr < proc_entry_info.GetRange ().GetRangeBase ()) | |||
2082 | { | |||
2083 | range_info.GetRange ().SetRangeBase (load_addr); | |||
2084 | range_info.GetRange ().SetByteSize (proc_entry_info.GetRange ().GetRangeBase () - load_addr); | |||
2085 | range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); | |||
2086 | range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); | |||
2087 | range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); | |||
2088 | ||||
2089 | return error; | |||
2090 | } | |||
2091 | else if (proc_entry_info.GetRange ().Contains (load_addr)) | |||
2092 | { | |||
2093 | // The target address is within the memory region we're processing here. | |||
2094 | range_info = proc_entry_info; | |||
2095 | return error; | |||
2096 | } | |||
2097 | ||||
2098 | // The target memory address comes somewhere after the region we just parsed. | |||
2099 | } | |||
2100 | ||||
2101 | // If we made it here, we didn't find an entry that contained the given address. Return the | |||
2102 | // load_addr as start and the amount of bytes betwwen load address and the end of the memory as | |||
2103 | // size. | |||
2104 | range_info.GetRange ().SetRangeBase (load_addr); | |||
2105 | switch (m_arch.GetAddressByteSize()) | |||
2106 | { | |||
2107 | case 4: | |||
2108 | range_info.GetRange ().SetByteSize (0x100000000ull - load_addr); | |||
2109 | break; | |||
2110 | case 8: | |||
2111 | range_info.GetRange ().SetByteSize (0ull - load_addr); | |||
2112 | break; | |||
2113 | default: | |||
2114 | assert(false && "Unrecognized data byte size")((false && "Unrecognized data byte size") ? static_cast <void> (0) : __assert_fail ("false && \"Unrecognized data byte size\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2114, __PRETTY_FUNCTION__)); | |||
2115 | break; | |||
2116 | } | |||
2117 | range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); | |||
2118 | range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); | |||
2119 | range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); | |||
2120 | return error; | |||
2121 | } | |||
2122 | ||||
2123 | void | |||
2124 | NativeProcessLinux::DoStopIDBumped (uint32_t newBumpId) | |||
2125 | { | |||
2126 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2127 | if (log) | |||
2128 | log->Printf ("NativeProcessLinux::%s(newBumpId=%" PRIu32"u" ") called", __FUNCTION__, newBumpId); | |||
2129 | ||||
2130 | { | |||
2131 | Mutex::Locker locker (m_mem_region_cache_mutex); | |||
2132 | if (log) | |||
2133 | log->Printf ("NativeProcessLinux::%s clearing %" PRIu64"l" "u" " entries from the cache", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ())); | |||
2134 | m_mem_region_cache.clear (); | |||
2135 | } | |||
2136 | } | |||
2137 | ||||
2138 | Error | |||
2139 | NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) | |||
2140 | { | |||
2141 | // FIXME implementing this requires the equivalent of | |||
2142 | // InferiorCallPOSIX::InferiorCallMmap, which depends on | |||
2143 | // functional ThreadPlans working with Native*Protocol. | |||
2144 | #if 1 | |||
2145 | return Error ("not implemented yet"); | |||
2146 | #else | |||
2147 | addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
2148 | ||||
2149 | unsigned prot = 0; | |||
2150 | if (permissions & lldb::ePermissionsReadable) | |||
2151 | prot |= eMmapProtRead; | |||
2152 | if (permissions & lldb::ePermissionsWritable) | |||
2153 | prot |= eMmapProtWrite; | |||
2154 | if (permissions & lldb::ePermissionsExecutable) | |||
2155 | prot |= eMmapProtExec; | |||
2156 | ||||
2157 | // TODO implement this directly in NativeProcessLinux | |||
2158 | // (and lift to NativeProcessPOSIX if/when that class is | |||
2159 | // refactored out). | |||
2160 | if (InferiorCallMmap(this, addr, 0, size, prot, | |||
2161 | eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { | |||
2162 | m_addr_to_mmap_size[addr] = size; | |||
2163 | return Error (); | |||
2164 | } else { | |||
2165 | addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
2166 | return Error("unable to allocate %" PRIu64"l" "u" " bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); | |||
2167 | } | |||
2168 | #endif | |||
2169 | } | |||
2170 | ||||
2171 | Error | |||
2172 | NativeProcessLinux::DeallocateMemory (lldb::addr_t addr) | |||
2173 | { | |||
2174 | // FIXME see comments in AllocateMemory - required lower-level | |||
2175 | // bits not in place yet (ThreadPlans) | |||
2176 | return Error ("not implemented"); | |||
2177 | } | |||
2178 | ||||
2179 | lldb::addr_t | |||
2180 | NativeProcessLinux::GetSharedLibraryInfoAddress () | |||
2181 | { | |||
2182 | #if 1 | |||
2183 | // punt on this for now | |||
2184 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
2185 | #else | |||
2186 | // Return the image info address for the exe module | |||
2187 | #if 1 | |||
2188 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2189 | ||||
2190 | ModuleSP module_sp; | |||
2191 | Error error = GetExeModuleSP (module_sp); | |||
2192 | if (error.Fail ()) | |||
2193 | { | |||
2194 | if (log) | |||
2195 | log->Warning ("NativeProcessLinux::%s failed to retrieve exe module: %s", __FUNCTION__, error.AsCString ()); | |||
2196 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
2197 | } | |||
2198 | ||||
2199 | if (module_sp == nullptr) | |||
2200 | { | |||
2201 | if (log) | |||
2202 | log->Warning ("NativeProcessLinux::%s exe module returned was NULL", __FUNCTION__); | |||
2203 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
2204 | } | |||
2205 | ||||
2206 | ObjectFileSP object_file_sp = module_sp->GetObjectFile (); | |||
2207 | if (object_file_sp == nullptr) | |||
2208 | { | |||
2209 | if (log) | |||
2210 | log->Warning ("NativeProcessLinux::%s exe module returned a NULL object file", __FUNCTION__); | |||
2211 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
2212 | } | |||
2213 | ||||
2214 | return obj_file_sp->GetImageInfoAddress(); | |||
2215 | #else | |||
2216 | Target *target = &GetTarget(); | |||
2217 | ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); | |||
2218 | Address addr = obj_file->GetImageInfoAddress(target); | |||
2219 | ||||
2220 | if (addr.IsValid()) | |||
2221 | return addr.GetLoadAddress(target); | |||
2222 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
2223 | #endif | |||
2224 | #endif // punt on this for now | |||
2225 | } | |||
2226 | ||||
2227 | size_t | |||
2228 | NativeProcessLinux::UpdateThreads () | |||
2229 | { | |||
2230 | // The NativeProcessLinux monitoring threads are always up to date | |||
2231 | // with respect to thread state and they keep the thread list | |||
2232 | // populated properly. All this method needs to do is return the | |||
2233 | // thread count. | |||
2234 | Mutex::Locker locker (m_threads_mutex); | |||
2235 | return m_threads.size (); | |||
2236 | } | |||
2237 | ||||
2238 | bool | |||
2239 | NativeProcessLinux::GetArchitecture (ArchSpec &arch) const | |||
2240 | { | |||
2241 | arch = m_arch; | |||
2242 | return true; | |||
2243 | } | |||
2244 | ||||
2245 | Error | |||
2246 | NativeProcessLinux::GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size) | |||
2247 | { | |||
2248 | // FIXME put this behind a breakpoint protocol class that can be | |||
2249 | // set per architecture. Need ARM, MIPS support here. | |||
2250 | static const uint8_t g_i386_opcode [] = { 0xCC }; | |||
2251 | ||||
2252 | switch (m_arch.GetMachine ()) | |||
2253 | { | |||
2254 | case llvm::Triple::x86: | |||
2255 | case llvm::Triple::x86_64: | |||
2256 | actual_opcode_size = static_cast<uint32_t> (sizeof(g_i386_opcode)); | |||
2257 | return Error (); | |||
2258 | ||||
2259 | case llvm::Triple::arm: | |||
2260 | case llvm::Triple::aarch64: | |||
2261 | case llvm::Triple::mips64: | |||
2262 | case llvm::Triple::mips64el: | |||
2263 | case llvm::Triple::mips: | |||
2264 | case llvm::Triple::mipsel: | |||
2265 | // On these architectures the PC don't get updated for breakpoint hits | |||
2266 | actual_opcode_size = 0; | |||
2267 | return Error (); | |||
2268 | ||||
2269 | default: | |||
2270 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2270, __PRETTY_FUNCTION__)); | |||
2271 | return Error ("CPU type not supported"); | |||
2272 | } | |||
2273 | } | |||
2274 | ||||
2275 | Error | |||
2276 | NativeProcessLinux::SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) | |||
2277 | { | |||
2278 | if (hardware) | |||
2279 | return Error ("NativeProcessLinux does not support hardware breakpoints"); | |||
2280 | else | |||
2281 | return SetSoftwareBreakpoint (addr, size); | |||
2282 | } | |||
2283 | ||||
2284 | Error | |||
2285 | NativeProcessLinux::GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, | |||
2286 | size_t &actual_opcode_size, | |||
2287 | const uint8_t *&trap_opcode_bytes) | |||
2288 | { | |||
2289 | // FIXME put this behind a breakpoint protocol class that can be set per | |||
2290 | // architecture. Need MIPS support here. | |||
2291 | static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 }; | |||
2292 | // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the | |||
2293 | // linux kernel does otherwise. | |||
2294 | static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 }; | |||
2295 | static const uint8_t g_i386_opcode [] = { 0xCC }; | |||
2296 | static const uint8_t g_mips64_opcode[] = { 0x00, 0x00, 0x00, 0x0d }; | |||
2297 | static const uint8_t g_mips64el_opcode[] = { 0x0d, 0x00, 0x00, 0x00 }; | |||
2298 | static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde }; | |||
2299 | ||||
2300 | switch (m_arch.GetMachine ()) | |||
2301 | { | |||
2302 | case llvm::Triple::aarch64: | |||
2303 | trap_opcode_bytes = g_aarch64_opcode; | |||
2304 | actual_opcode_size = sizeof(g_aarch64_opcode); | |||
2305 | return Error (); | |||
2306 | ||||
2307 | case llvm::Triple::arm: | |||
2308 | switch (trap_opcode_size_hint) | |||
2309 | { | |||
2310 | case 2: | |||
2311 | trap_opcode_bytes = g_thumb_breakpoint_opcode; | |||
2312 | actual_opcode_size = sizeof(g_thumb_breakpoint_opcode); | |||
2313 | return Error (); | |||
2314 | case 4: | |||
2315 | trap_opcode_bytes = g_arm_breakpoint_opcode; | |||
2316 | actual_opcode_size = sizeof(g_arm_breakpoint_opcode); | |||
2317 | return Error (); | |||
2318 | default: | |||
2319 | assert(false && "Unrecognised trap opcode size hint!")((false && "Unrecognised trap opcode size hint!") ? static_cast <void> (0) : __assert_fail ("false && \"Unrecognised trap opcode size hint!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2319, __PRETTY_FUNCTION__)); | |||
2320 | return Error ("Unrecognised trap opcode size hint!"); | |||
2321 | } | |||
2322 | ||||
2323 | case llvm::Triple::x86: | |||
2324 | case llvm::Triple::x86_64: | |||
2325 | trap_opcode_bytes = g_i386_opcode; | |||
2326 | actual_opcode_size = sizeof(g_i386_opcode); | |||
2327 | return Error (); | |||
2328 | ||||
2329 | case llvm::Triple::mips: | |||
2330 | case llvm::Triple::mips64: | |||
2331 | trap_opcode_bytes = g_mips64_opcode; | |||
2332 | actual_opcode_size = sizeof(g_mips64_opcode); | |||
2333 | return Error (); | |||
2334 | ||||
2335 | case llvm::Triple::mipsel: | |||
2336 | case llvm::Triple::mips64el: | |||
2337 | trap_opcode_bytes = g_mips64el_opcode; | |||
2338 | actual_opcode_size = sizeof(g_mips64el_opcode); | |||
2339 | return Error (); | |||
2340 | ||||
2341 | default: | |||
2342 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2342, __PRETTY_FUNCTION__)); | |||
2343 | return Error ("CPU type not supported"); | |||
2344 | } | |||
2345 | } | |||
2346 | ||||
2347 | #if 0 | |||
2348 | ProcessMessage::CrashReason | |||
2349 | NativeProcessLinux::GetCrashReasonForSIGSEGV(const siginfo_t *info) | |||
2350 | { | |||
2351 | ProcessMessage::CrashReason reason; | |||
2352 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2352, __PRETTY_FUNCTION__)); | |||
2353 | ||||
2354 | reason = ProcessMessage::eInvalidCrashReason; | |||
2355 | ||||
2356 | switch (info->si_code) | |||
2357 | { | |||
2358 | default: | |||
2359 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2359, __PRETTY_FUNCTION__)); | |||
2360 | break; | |||
2361 | case SI_KERNELSI_KERNEL: | |||
2362 | // Linux will occasionally send spurious SI_KERNEL codes. | |||
2363 | // (this is poorly documented in sigaction) | |||
2364 | // One way to get this is via unaligned SIMD loads. | |||
2365 | reason = ProcessMessage::eInvalidAddress; // for lack of anything better | |||
2366 | break; | |||
2367 | case SEGV_MAPERRSEGV_MAPERR: | |||
2368 | reason = ProcessMessage::eInvalidAddress; | |||
2369 | break; | |||
2370 | case SEGV_ACCERRSEGV_ACCERR: | |||
2371 | reason = ProcessMessage::ePrivilegedAddress; | |||
2372 | break; | |||
2373 | } | |||
2374 | ||||
2375 | return reason; | |||
2376 | } | |||
2377 | #endif | |||
2378 | ||||
2379 | ||||
2380 | #if 0 | |||
2381 | ProcessMessage::CrashReason | |||
2382 | NativeProcessLinux::GetCrashReasonForSIGILL(const siginfo_t *info) | |||
2383 | { | |||
2384 | ProcessMessage::CrashReason reason; | |||
2385 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2385, __PRETTY_FUNCTION__)); | |||
2386 | ||||
2387 | reason = ProcessMessage::eInvalidCrashReason; | |||
2388 | ||||
2389 | switch (info->si_code) | |||
2390 | { | |||
2391 | default: | |||
2392 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2392, __PRETTY_FUNCTION__)); | |||
2393 | break; | |||
2394 | case ILL_ILLOPCILL_ILLOPC: | |||
2395 | reason = ProcessMessage::eIllegalOpcode; | |||
2396 | break; | |||
2397 | case ILL_ILLOPNILL_ILLOPN: | |||
2398 | reason = ProcessMessage::eIllegalOperand; | |||
2399 | break; | |||
2400 | case ILL_ILLADRILL_ILLADR: | |||
2401 | reason = ProcessMessage::eIllegalAddressingMode; | |||
2402 | break; | |||
2403 | case ILL_ILLTRPILL_ILLTRP: | |||
2404 | reason = ProcessMessage::eIllegalTrap; | |||
2405 | break; | |||
2406 | case ILL_PRVOPCILL_PRVOPC: | |||
2407 | reason = ProcessMessage::ePrivilegedOpcode; | |||
2408 | break; | |||
2409 | case ILL_PRVREGILL_PRVREG: | |||
2410 | reason = ProcessMessage::ePrivilegedRegister; | |||
2411 | break; | |||
2412 | case ILL_COPROCILL_COPROC: | |||
2413 | reason = ProcessMessage::eCoprocessorError; | |||
2414 | break; | |||
2415 | case ILL_BADSTKILL_BADSTK: | |||
2416 | reason = ProcessMessage::eInternalStackError; | |||
2417 | break; | |||
2418 | } | |||
2419 | ||||
2420 | return reason; | |||
2421 | } | |||
2422 | #endif | |||
2423 | ||||
2424 | #if 0 | |||
2425 | ProcessMessage::CrashReason | |||
2426 | NativeProcessLinux::GetCrashReasonForSIGFPE(const siginfo_t *info) | |||
2427 | { | |||
2428 | ProcessMessage::CrashReason reason; | |||
2429 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2429, __PRETTY_FUNCTION__)); | |||
2430 | ||||
2431 | reason = ProcessMessage::eInvalidCrashReason; | |||
2432 | ||||
2433 | switch (info->si_code) | |||
2434 | { | |||
2435 | default: | |||
2436 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2436, __PRETTY_FUNCTION__)); | |||
2437 | break; | |||
2438 | case FPE_INTDIVFPE_INTDIV: | |||
2439 | reason = ProcessMessage::eIntegerDivideByZero; | |||
2440 | break; | |||
2441 | case FPE_INTOVFFPE_INTOVF: | |||
2442 | reason = ProcessMessage::eIntegerOverflow; | |||
2443 | break; | |||
2444 | case FPE_FLTDIVFPE_FLTDIV: | |||
2445 | reason = ProcessMessage::eFloatDivideByZero; | |||
2446 | break; | |||
2447 | case FPE_FLTOVFFPE_FLTOVF: | |||
2448 | reason = ProcessMessage::eFloatOverflow; | |||
2449 | break; | |||
2450 | case FPE_FLTUNDFPE_FLTUND: | |||
2451 | reason = ProcessMessage::eFloatUnderflow; | |||
2452 | break; | |||
2453 | case FPE_FLTRESFPE_FLTRES: | |||
2454 | reason = ProcessMessage::eFloatInexactResult; | |||
2455 | break; | |||
2456 | case FPE_FLTINVFPE_FLTINV: | |||
2457 | reason = ProcessMessage::eFloatInvalidOperation; | |||
2458 | break; | |||
2459 | case FPE_FLTSUBFPE_FLTSUB: | |||
2460 | reason = ProcessMessage::eFloatSubscriptRange; | |||
2461 | break; | |||
2462 | } | |||
2463 | ||||
2464 | return reason; | |||
2465 | } | |||
2466 | #endif | |||
2467 | ||||
2468 | #if 0 | |||
2469 | ProcessMessage::CrashReason | |||
2470 | NativeProcessLinux::GetCrashReasonForSIGBUS(const siginfo_t *info) | |||
2471 | { | |||
2472 | ProcessMessage::CrashReason reason; | |||
2473 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2473, __PRETTY_FUNCTION__)); | |||
2474 | ||||
2475 | reason = ProcessMessage::eInvalidCrashReason; | |||
2476 | ||||
2477 | switch (info->si_code) | |||
2478 | { | |||
2479 | default: | |||
2480 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2480, __PRETTY_FUNCTION__)); | |||
2481 | break; | |||
2482 | case BUS_ADRALNBUS_ADRALN: | |||
2483 | reason = ProcessMessage::eIllegalAlignment; | |||
2484 | break; | |||
2485 | case BUS_ADRERRBUS_ADRERR: | |||
2486 | reason = ProcessMessage::eIllegalAddress; | |||
2487 | break; | |||
2488 | case BUS_OBJERRBUS_OBJERR: | |||
2489 | reason = ProcessMessage::eHardwareError; | |||
2490 | break; | |||
2491 | } | |||
2492 | ||||
2493 | return reason; | |||
2494 | } | |||
2495 | #endif | |||
2496 | ||||
2497 | Error | |||
2498 | NativeProcessLinux::ReadMemory (lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) | |||
2499 | { | |||
2500 | if (ProcessVmReadvSupported()) { | |||
2501 | // The process_vm_readv path is about 50 times faster than ptrace api. We want to use | |||
2502 | // this syscall if it is supported. | |||
2503 | ||||
2504 | const ::pid_t pid = GetID(); | |||
2505 | ||||
2506 | struct iovec local_iov, remote_iov; | |||
2507 | local_iov.iov_base = buf; | |||
2508 | local_iov.iov_len = size; | |||
2509 | remote_iov.iov_base = reinterpret_cast<void *>(addr); | |||
2510 | remote_iov.iov_len = size; | |||
2511 | ||||
2512 | bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0); | |||
2513 | const bool success = bytes_read == size; | |||
2514 | ||||
2515 | Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2516 | if (log) | |||
2517 | log->Printf ("NativeProcessLinux::%s using process_vm_readv to read %zd bytes from inferior address 0x%" PRIx64"l" "x"": %s", | |||
2518 | __FUNCTION__, size, addr, success ? "Success" : strerror(errno(*__errno_location ()))); | |||
2519 | ||||
2520 | if (success) | |||
2521 | return Error(); | |||
2522 | // else | |||
2523 | // the call failed for some reason, let's retry the read using ptrace api. | |||
2524 | } | |||
2525 | ||||
2526 | unsigned char *dst = static_cast<unsigned char*>(buf); | |||
2527 | size_t remainder; | |||
2528 | long data; | |||
2529 | ||||
2530 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL((4294967295U)))); | |||
2531 | if (log) | |||
2532 | ProcessPOSIXLog::IncNestLevel(); | |||
2533 | if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY(1u << 4))) | |||
2534 | log->Printf ("NativeProcessLinux::%s(%p, %p, %zd, _)", __FUNCTION__, (void*)addr, buf, size); | |||
2535 | ||||
2536 | for (bytes_read = 0; bytes_read < size; bytes_read += remainder) | |||
2537 | { | |||
2538 | Error error = NativeProcessLinux::PtraceWrapper(PTRACE_PEEKDATA, GetID(), (void*)addr, nullptr, 0, &data); | |||
2539 | if (error.Fail()) | |||
2540 | { | |||
2541 | if (log) | |||
2542 | ProcessPOSIXLog::DecNestLevel(); | |||
2543 | return error; | |||
2544 | } | |||
2545 | ||||
2546 | remainder = size - bytes_read; | |||
2547 | remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; | |||
2548 | ||||
2549 | // Copy the data into our buffer | |||
2550 | for (unsigned i = 0; i < remainder; ++i) | |||
2551 | dst[i] = ((data >> i*8) & 0xFF); | |||
2552 | ||||
2553 | if (log && ProcessPOSIXLog::AtTopNestLevel() && | |||
2554 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG(1u << 6)) || | |||
2555 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT(1u << 5)) && | |||
2556 | size <= POSIX_LOG_MEMORY_SHORT_BYTES(4 * sizeof(ptrdiff_t))))) | |||
2557 | { | |||
2558 | uintptr_t print_dst = 0; | |||
2559 | // Format bytes from data by moving into print_dst for log output | |||
2560 | for (unsigned i = 0; i < remainder; ++i) | |||
2561 | print_dst |= (((data >> i*8) & 0xFF) << i*8); | |||
2562 | log->Printf ("NativeProcessLinux::%s() [0x%" PRIx64"l" "x" "]:0x%" PRIx64"l" "x" " (0x%" PRIx64"l" "x" ")", | |||
2563 | __FUNCTION__, addr, uint64_t(print_dst), uint64_t(data)); | |||
2564 | } | |||
2565 | addr += k_ptrace_word_size; | |||
2566 | dst += k_ptrace_word_size; | |||
2567 | } | |||
2568 | ||||
2569 | if (log) | |||
2570 | ProcessPOSIXLog::DecNestLevel(); | |||
2571 | return Error(); | |||
2572 | } | |||
2573 | ||||
2574 | Error | |||
2575 | NativeProcessLinux::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) | |||
2576 | { | |||
2577 | Error error = ReadMemory(addr, buf, size, bytes_read); | |||
2578 | if (error.Fail()) return error; | |||
2579 | return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size); | |||
2580 | } | |||
2581 | ||||
2582 | Error | |||
2583 | NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) | |||
2584 | { | |||
2585 | const unsigned char *src = static_cast<const unsigned char*>(buf); | |||
2586 | size_t remainder; | |||
2587 | Error error; | |||
2588 | ||||
2589 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL((4294967295U)))); | |||
2590 | if (log) | |||
2591 | ProcessPOSIXLog::IncNestLevel(); | |||
2592 | if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY(1u << 4))) | |||
2593 | log->Printf ("NativeProcessLinux::%s(0x%" PRIx64"l" "x" ", %p, %zu)", __FUNCTION__, addr, buf, size); | |||
2594 | ||||
2595 | for (bytes_written = 0; bytes_written < size; bytes_written += remainder) | |||
2596 | { | |||
2597 | remainder = size - bytes_written; | |||
2598 | remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; | |||
2599 | ||||
2600 | if (remainder == k_ptrace_word_size) | |||
2601 | { | |||
2602 | unsigned long data = 0; | |||
2603 | for (unsigned i = 0; i < k_ptrace_word_size; ++i) | |||
2604 | data |= (unsigned long)src[i] << i*8; | |||
2605 | ||||
2606 | if (log && ProcessPOSIXLog::AtTopNestLevel() && | |||
2607 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG(1u << 6)) || | |||
2608 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT(1u << 5)) && | |||
2609 | size <= POSIX_LOG_MEMORY_SHORT_BYTES(4 * sizeof(ptrdiff_t))))) | |||
2610 | log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, | |||
2611 | (void*)addr, *(const unsigned long*)src, data); | |||
2612 | ||||
2613 | error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(), (void*)addr, (void*)data); | |||
2614 | if (error.Fail()) | |||
2615 | { | |||
2616 | if (log) | |||
2617 | ProcessPOSIXLog::DecNestLevel(); | |||
2618 | return error; | |||
2619 | } | |||
2620 | } | |||
2621 | else | |||
2622 | { | |||
2623 | unsigned char buff[8]; | |||
2624 | size_t bytes_read; | |||
2625 | error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read); | |||
2626 | if (error.Fail()) | |||
2627 | { | |||
2628 | if (log) | |||
2629 | ProcessPOSIXLog::DecNestLevel(); | |||
2630 | return error; | |||
2631 | } | |||
2632 | ||||
2633 | memcpy(buff, src, remainder); | |||
2634 | ||||
2635 | size_t bytes_written_rec; | |||
2636 | error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec); | |||
2637 | if (error.Fail()) | |||
2638 | { | |||
2639 | if (log) | |||
2640 | ProcessPOSIXLog::DecNestLevel(); | |||
2641 | return error; | |||
2642 | } | |||
2643 | ||||
2644 | if (log && ProcessPOSIXLog::AtTopNestLevel() && | |||
2645 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG(1u << 6)) || | |||
2646 | (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT(1u << 5)) && | |||
2647 | size <= POSIX_LOG_MEMORY_SHORT_BYTES(4 * sizeof(ptrdiff_t))))) | |||
2648 | log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, | |||
2649 | (void*)addr, *(const unsigned long*)src, *(unsigned long*)buff); | |||
2650 | } | |||
2651 | ||||
2652 | addr += k_ptrace_word_size; | |||
2653 | src += k_ptrace_word_size; | |||
2654 | } | |||
2655 | if (log) | |||
2656 | ProcessPOSIXLog::DecNestLevel(); | |||
2657 | return error; | |||
2658 | } | |||
2659 | ||||
2660 | Error | |||
2661 | NativeProcessLinux::Resume (lldb::tid_t tid, uint32_t signo) | |||
2662 | { | |||
2663 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2664 | ||||
2665 | if (log) | |||
2666 | log->Printf ("NativeProcessLinux::%s() resuming thread = %" PRIu64"l" "u" " with signal %s", __FUNCTION__, tid, | |||
2667 | Host::GetSignalAsCString(signo)); | |||
2668 | ||||
2669 | ||||
2670 | ||||
2671 | intptr_t data = 0; | |||
2672 | ||||
2673 | if (signo != LLDB_INVALID_SIGNAL_NUMBER(2147483647)) | |||
2674 | data = signo; | |||
2675 | ||||
2676 | Error error = PtraceWrapper(PTRACE_CONT, tid, nullptr, (void*)data); | |||
2677 | ||||
2678 | if (log) | |||
2679 | log->Printf ("NativeProcessLinux::%s() resuming thread = %" PRIu64"l" "u" " result = %s", __FUNCTION__, tid, error.Success() ? "true" : "false"); | |||
2680 | return error; | |||
2681 | } | |||
2682 | ||||
2683 | Error | |||
2684 | NativeProcessLinux::SingleStep(lldb::tid_t tid, uint32_t signo) | |||
2685 | { | |||
2686 | intptr_t data = 0; | |||
2687 | ||||
2688 | if (signo != LLDB_INVALID_SIGNAL_NUMBER(2147483647)) | |||
2689 | data = signo; | |||
2690 | ||||
2691 | // If hardware single-stepping is not supported, we just do a continue. The breakpoint on the | |||
2692 | // next instruction has been setup in NativeProcessLinux::Resume. | |||
2693 | return PtraceWrapper(SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP : PTRACE_CONT, | |||
2694 | tid, nullptr, (void*)data); | |||
2695 | } | |||
2696 | ||||
2697 | Error | |||
2698 | NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo) | |||
2699 | { | |||
2700 | return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo); | |||
2701 | } | |||
2702 | ||||
2703 | Error | |||
2704 | NativeProcessLinux::GetEventMessage(lldb::tid_t tid, unsigned long *message) | |||
2705 | { | |||
2706 | return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message); | |||
2707 | } | |||
2708 | ||||
2709 | Error | |||
2710 | NativeProcessLinux::Detach(lldb::tid_t tid) | |||
2711 | { | |||
2712 | if (tid == LLDB_INVALID_THREAD_ID0) | |||
2713 | return Error(); | |||
2714 | ||||
2715 | return PtraceWrapper(PTRACE_DETACH, tid); | |||
2716 | } | |||
2717 | ||||
2718 | bool | |||
2719 | NativeProcessLinux::DupDescriptor(const FileSpec &file_spec, int fd, int flags) | |||
2720 | { | |||
2721 | int target_fd = open(file_spec.GetCString(), flags, 0666); | |||
2722 | ||||
2723 | if (target_fd == -1) | |||
2724 | return false; | |||
2725 | ||||
2726 | if (dup2(target_fd, fd) == -1) | |||
2727 | return false; | |||
2728 | ||||
2729 | return (close(target_fd) == -1) ? false : true; | |||
2730 | } | |||
2731 | ||||
2732 | bool | |||
2733 | NativeProcessLinux::HasThreadNoLock (lldb::tid_t thread_id) | |||
2734 | { | |||
2735 | for (auto thread_sp : m_threads) | |||
2736 | { | |||
2737 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2737, __PRETTY_FUNCTION__)); | |||
2738 | if (thread_sp->GetID () == thread_id) | |||
2739 | { | |||
2740 | // We have this thread. | |||
2741 | return true; | |||
2742 | } | |||
2743 | } | |||
2744 | ||||
2745 | // We don't have this thread. | |||
2746 | return false; | |||
2747 | } | |||
2748 | ||||
2749 | bool | |||
2750 | NativeProcessLinux::StopTrackingThread (lldb::tid_t thread_id) | |||
2751 | { | |||
2752 | Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD(1u << 2)); | |||
2753 | ||||
2754 | if (log) | |||
2755 | log->Printf("NativeProcessLinux::%s (tid: %" PRIu64"l" "u" ")", __FUNCTION__, thread_id); | |||
2756 | ||||
2757 | bool found = false; | |||
2758 | ||||
2759 | Mutex::Locker locker (m_threads_mutex); | |||
2760 | for (auto it = m_threads.begin (); it != m_threads.end (); ++it) | |||
2761 | { | |||
2762 | if (*it && ((*it)->GetID () == thread_id)) | |||
2763 | { | |||
2764 | m_threads.erase (it); | |||
2765 | found = true; | |||
2766 | break; | |||
2767 | } | |||
2768 | } | |||
2769 | ||||
2770 | SignalIfAllThreadsStopped(); | |||
2771 | ||||
2772 | return found; | |||
2773 | } | |||
2774 | ||||
2775 | NativeThreadLinuxSP | |||
2776 | NativeProcessLinux::AddThread (lldb::tid_t thread_id) | |||
2777 | { | |||
2778 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD(1u << 2))); | |||
2779 | ||||
2780 | Mutex::Locker locker (m_threads_mutex); | |||
2781 | ||||
2782 | if (log) | |||
2783 | { | |||
2784 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " adding thread with tid %" PRIu64"l" "u", | |||
2785 | __FUNCTION__, | |||
2786 | GetID (), | |||
2787 | thread_id); | |||
2788 | } | |||
2789 | ||||
2790 | 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.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 2790, __PRETTY_FUNCTION__)); | |||
2791 | ||||
2792 | // If this is the first thread, save it as the current thread | |||
2793 | if (m_threads.empty ()) | |||
2794 | SetCurrentThreadID (thread_id); | |||
2795 | ||||
2796 | auto thread_sp = std::make_shared<NativeThreadLinux>(this, thread_id); | |||
2797 | m_threads.push_back (thread_sp); | |||
2798 | return thread_sp; | |||
2799 | } | |||
2800 | ||||
2801 | Error | |||
2802 | NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) | |||
2803 | { | |||
2804 | Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS(1u << 5))); | |||
2805 | ||||
2806 | Error error; | |||
2807 | ||||
2808 | // Find out the size of a breakpoint (might depend on where we are in the code). | |||
2809 | NativeRegisterContextSP context_sp = thread.GetRegisterContext(); | |||
2810 | if (!context_sp) | |||
2811 | { | |||
2812 | error.SetErrorString ("cannot get a NativeRegisterContext for the thread"); | |||
2813 | if (log) | |||
2814 | log->Printf ("NativeProcessLinux::%s failed: %s", __FUNCTION__, error.AsCString ()); | |||
2815 | return error; | |||
2816 | } | |||
2817 | ||||
2818 | uint32_t breakpoint_size = 0; | |||
2819 | error = GetSoftwareBreakpointPCOffset(breakpoint_size); | |||
2820 | if (error.Fail ()) | |||
2821 | { | |||
2822 | if (log) | |||
2823 | log->Printf ("NativeProcessLinux::%s GetBreakpointSize() failed: %s", __FUNCTION__, error.AsCString ()); | |||
2824 | return error; | |||
2825 | } | |||
2826 | else | |||
2827 | { | |||
2828 | if (log) | |||
2829 | log->Printf ("NativeProcessLinux::%s breakpoint size: %" PRIu32"u", __FUNCTION__, breakpoint_size); | |||
2830 | } | |||
2831 | ||||
2832 | // First try probing for a breakpoint at a software breakpoint location: PC - breakpoint size. | |||
2833 | const lldb::addr_t initial_pc_addr = context_sp->GetPCfromBreakpointLocation (); | |||
2834 | lldb::addr_t breakpoint_addr = initial_pc_addr; | |||
2835 | if (breakpoint_size > 0) | |||
2836 | { | |||
2837 | // Do not allow breakpoint probe to wrap around. | |||
2838 | if (breakpoint_addr >= breakpoint_size) | |||
2839 | breakpoint_addr -= breakpoint_size; | |||
2840 | } | |||
2841 | ||||
2842 | // Check if we stopped because of a breakpoint. | |||
2843 | NativeBreakpointSP breakpoint_sp; | |||
2844 | error = m_breakpoint_list.GetBreakpoint (breakpoint_addr, breakpoint_sp); | |||
2845 | if (!error.Success () || !breakpoint_sp) | |||
2846 | { | |||
2847 | // We didn't find one at a software probe location. Nothing to do. | |||
2848 | if (log) | |||
2849 | 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); | |||
2850 | return Error (); | |||
2851 | } | |||
2852 | ||||
2853 | // If the breakpoint is not a software breakpoint, nothing to do. | |||
2854 | if (!breakpoint_sp->IsSoftwareBreakpoint ()) | |||
2855 | { | |||
2856 | if (log) | |||
2857 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " breakpoint found at 0x%" PRIx64"l" "x" ", not software, nothing to adjust", __FUNCTION__, GetID (), breakpoint_addr); | |||
2858 | return Error (); | |||
2859 | } | |||
2860 | ||||
2861 | // | |||
2862 | // We have a software breakpoint and need to adjust the PC. | |||
2863 | // | |||
2864 | ||||
2865 | // Sanity check. | |||
2866 | if (breakpoint_size == 0) | |||
2867 | { | |||
2868 | // Nothing to do! How did we get here? | |||
2869 | if (log) | |||
2870 | 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); | |||
2871 | return Error (); | |||
2872 | } | |||
2873 | ||||
2874 | // Change the program counter. | |||
2875 | if (log) | |||
2876 | 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(), thread.GetID(), initial_pc_addr, breakpoint_addr); | |||
2877 | ||||
2878 | error = context_sp->SetPC (breakpoint_addr); | |||
2879 | if (error.Fail ()) | |||
2880 | { | |||
2881 | if (log) | |||
2882 | log->Printf ("NativeProcessLinux::%s pid %" PRIu64"l" "u" " tid %" PRIu64"l" "u" ": failed to set PC: %s", __FUNCTION__, GetID(), thread.GetID(), error.AsCString ()); | |||
2883 | return error; | |||
2884 | } | |||
2885 | ||||
2886 | return error; | |||
2887 | } | |||
2888 | ||||
2889 | Error | |||
2890 | NativeProcessLinux::GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) | |||
2891 | { | |||
2892 | FileSpec module_file_spec(module_path, true); | |||
2893 | ||||
2894 | bool found = false; | |||
2895 | file_spec.Clear(); | |||
2896 | ProcFileReader::ProcessLineByLine(GetID(), "maps", | |||
2897 | [&] (const std::string &line) | |||
2898 | { | |||
2899 | SmallVector<StringRef, 16> columns; | |||
2900 | StringRef(line).split(columns, " ", -1, false); | |||
2901 | if (columns.size() < 6) | |||
2902 | return true; // continue searching | |||
2903 | ||||
2904 | FileSpec this_file_spec(columns[5].str().c_str(), false); | |||
2905 | if (this_file_spec.GetFilename() != module_file_spec.GetFilename()) | |||
2906 | return true; // continue searching | |||
2907 | ||||
2908 | file_spec = this_file_spec; | |||
2909 | found = true; | |||
2910 | return false; // we are done | |||
2911 | }); | |||
2912 | ||||
2913 | if (! found) | |||
2914 | return Error("Module file (%s) not found in /proc/%" PRIu64"l" "u" "/maps file!", | |||
2915 | module_file_spec.GetFilename().AsCString(), GetID()); | |||
2916 | ||||
2917 | return Error(); | |||
2918 | } | |||
2919 | ||||
2920 | Error | |||
2921 | NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr) | |||
2922 | { | |||
2923 | load_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
2924 | Error error = ProcFileReader::ProcessLineByLine (GetID (), "maps", | |||
2925 | [&] (const std::string &line) -> bool | |||
2926 | { | |||
2927 | StringRef maps_row(line); | |||
2928 | ||||
2929 | SmallVector<StringRef, 16> maps_columns; | |||
2930 | maps_row.split(maps_columns, StringRef(" "), -1, false); | |||
2931 | ||||
2932 | if (maps_columns.size() < 6) | |||
2933 | { | |||
2934 | // Return true to continue reading the proc file | |||
2935 | return true; | |||
2936 | } | |||
2937 | ||||
2938 | if (maps_columns[5] == file_name) | |||
2939 | { | |||
2940 | StringExtractor addr_extractor(maps_columns[0].str().c_str()); | |||
2941 | load_addr = addr_extractor.GetHexMaxU64(false, LLDB_INVALID_ADDRESS(18446744073709551615UL)); | |||
2942 | ||||
2943 | // Return false to stop reading the proc file further | |||
2944 | return false; | |||
2945 | } | |||
2946 | ||||
2947 | // Return true to continue reading the proc file | |||
2948 | return true; | |||
2949 | }); | |||
2950 | return error; | |||
2951 | } | |||
2952 | ||||
2953 | NativeThreadLinuxSP | |||
2954 | NativeProcessLinux::GetThreadByID(lldb::tid_t tid) | |||
2955 | { | |||
2956 | return std::static_pointer_cast<NativeThreadLinux>(NativeProcessProtocol::GetThreadByID(tid)); | |||
2957 | } | |||
2958 | ||||
2959 | Error | |||
2960 | NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, lldb::StateType state, int signo) | |||
2961 | { | |||
2962 | Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD(1u << 2)); | |||
2963 | ||||
2964 | if (log) | |||
2965 | log->Printf("NativeProcessLinux::%s (tid: %" PRIu64"l" "u" ")", | |||
2966 | __FUNCTION__, thread.GetID()); | |||
2967 | ||||
2968 | // Before we do the resume below, first check if we have a pending | |||
2969 | // stop notification that is currently waiting for | |||
2970 | // all threads to stop. This is potentially a buggy situation since | |||
2971 | // we're ostensibly waiting for threads to stop before we send out the | |||
2972 | // pending notification, and here we are resuming one before we send | |||
2973 | // out the pending stop notification. | |||
2974 | if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID0 && log) | |||
2975 | { | |||
2976 | log->Printf("NativeProcessLinux::%s about to resume tid %" PRIu64"l" "u" " per explicit request but we have a pending stop notification (tid %" PRIu64"l" "u" ") that is actively waiting for this thread to stop. Valid sequence of events?", __FUNCTION__, thread.GetID(), m_pending_notification_tid); | |||
2977 | } | |||
2978 | ||||
2979 | // Request a resume. We expect this to be synchronous and the system | |||
2980 | // to reflect it is running after this completes. | |||
2981 | switch (state) | |||
2982 | { | |||
2983 | case eStateRunning: | |||
2984 | { | |||
2985 | thread.SetRunning(); | |||
2986 | const auto resume_result = Resume(thread.GetID(), signo); | |||
2987 | if (resume_result.Success()) | |||
2988 | SetState(eStateRunning, true); | |||
2989 | return resume_result; | |||
2990 | } | |||
2991 | case eStateStepping: | |||
2992 | { | |||
2993 | thread.SetStepping(); | |||
2994 | const auto step_result = SingleStep(thread.GetID(), signo); | |||
2995 | if (step_result.Success()) | |||
2996 | SetState(eStateRunning, true); | |||
2997 | return step_result; | |||
2998 | } | |||
2999 | default: | |||
3000 | if (log) | |||
3001 | log->Printf("NativeProcessLinux::%s Unhandled state %s.", | |||
3002 | __FUNCTION__, StateAsCString(state)); | |||
3003 | llvm_unreachable("Unhandled state for resume")::llvm::llvm_unreachable_internal("Unhandled state for resume" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn255820/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp" , 3003); | |||
3004 | } | |||
3005 | } | |||
3006 | ||||
3007 | //===----------------------------------------------------------------------===// | |||
3008 | ||||
3009 | void | |||
3010 | NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) | |||
3011 | { | |||
3012 | Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD(1u << 2)); | |||
3013 | ||||
3014 | if (log) | |||
3015 | { | |||
3016 | log->Printf("NativeProcessLinux::%s about to process event: (triggering_tid: %" PRIu64"l" "u" ")", | |||
3017 | __FUNCTION__, triggering_tid); | |||
3018 | } | |||
3019 | ||||
3020 | m_pending_notification_tid = triggering_tid; | |||
3021 | ||||
3022 | // Request a stop for all the thread stops that need to be stopped | |||
3023 | // and are not already known to be stopped. | |||
3024 | for (const auto &thread_sp: m_threads) | |||
3025 | { | |||
3026 | if (StateIsRunningState(thread_sp->GetState())) | |||
3027 | static_pointer_cast<NativeThreadLinux>(thread_sp)->RequestStop(); | |||
3028 | } | |||
3029 | ||||
3030 | SignalIfAllThreadsStopped(); | |||
3031 | ||||
3032 | if (log) | |||
3033 | { | |||
3034 | log->Printf("NativeProcessLinux::%s event processing done", __FUNCTION__); | |||
3035 | } | |||
3036 | } | |||
3037 | ||||
3038 | void | |||
3039 | NativeProcessLinux::SignalIfAllThreadsStopped() | |||
3040 | { | |||
3041 | if (m_pending_notification_tid == LLDB_INVALID_THREAD_ID0) | |||
3042 | return; // No pending notification. Nothing to do. | |||
3043 | ||||
3044 | for (const auto &thread_sp: m_threads) | |||
3045 | { | |||
3046 | if (StateIsRunningState(thread_sp->GetState())) | |||
3047 | return; // Some threads are still running. Don't signal yet. | |||
3048 | } | |||
3049 | ||||
3050 | // We have a pending notification and all threads have stopped. | |||
3051 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_BREAKPOINTS(1u << 5))); | |||
3052 | ||||
3053 | // Clear any temporary breakpoints we used to implement software single stepping. | |||
3054 | for (const auto &thread_info: m_threads_stepping_with_breakpoint) | |||
3055 | { | |||
3056 | Error error = RemoveBreakpoint (thread_info.second); | |||
3057 | if (error.Fail()) | |||
3058 | if (log) | |||
3059 | log->Printf("NativeProcessLinux::%s() pid = %" PRIu64"l" "u" " remove stepping breakpoint: %s", | |||
3060 | __FUNCTION__, thread_info.first, error.AsCString()); | |||
3061 | } | |||
3062 | m_threads_stepping_with_breakpoint.clear(); | |||
3063 | ||||
3064 | // Notify the delegate about the stop | |||
3065 | SetCurrentThreadID(m_pending_notification_tid); | |||
3066 | SetState(StateType::eStateStopped, true); | |||
3067 | m_pending_notification_tid = LLDB_INVALID_THREAD_ID0; | |||
3068 | } | |||
3069 | ||||
3070 | void | |||
3071 | NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) | |||
3072 | { | |||
3073 | Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD(1u << 2)); | |||
3074 | ||||
3075 | if (log) | |||
3076 | log->Printf("NativeProcessLinux::%s (tid: %" PRIu64"l" "u" ")", __FUNCTION__, thread.GetID()); | |||
3077 | ||||
3078 | if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID0 && StateIsRunningState(thread.GetState())) | |||
3079 | { | |||
3080 | // We will need to wait for this new thread to stop as well before firing the | |||
3081 | // notification. | |||
3082 | thread.RequestStop(); | |||
3083 | } | |||
3084 | } | |||
3085 | ||||
3086 | void | |||
3087 | NativeProcessLinux::SigchldHandler() | |||
3088 | { | |||
3089 | Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
3090 | // Process all pending waitpid notifications. | |||
3091 | while (true) | |||
3092 | { | |||
3093 | int status = -1; | |||
3094 | ::pid_t wait_pid = waitpid(-1, &status, __WALL0x40000000 | __WNOTHREAD0x20000000 | WNOHANG1); | |||
3095 | ||||
3096 | if (wait_pid == 0) | |||
3097 | break; // We are done. | |||
3098 | ||||
3099 | if (wait_pid == -1) | |||
3100 | { | |||
3101 | if (errno(*__errno_location ()) == EINTR4) | |||
3102 | continue; | |||
3103 | ||||
3104 | Error error(errno(*__errno_location ()), eErrorTypePOSIX); | |||
3105 | if (log) | |||
3106 | log->Printf("NativeProcessLinux::%s waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG) failed: %s", | |||
3107 | __FUNCTION__, error.AsCString()); | |||
3108 | break; | |||
3109 | } | |||
3110 | ||||
3111 | bool exited = false; | |||
3112 | int signal = 0; | |||
3113 | int exit_status = 0; | |||
3114 | const char *status_cstr = nullptr; | |||
3115 | if (WIFSTOPPED(status)((((*(int *) &(status))) & 0xff) == 0x7f)) | |||
3116 | { | |||
3117 | signal = WSTOPSIG(status)((((*(int *) &(status))) & 0xff00) >> 8); | |||
3118 | status_cstr = "STOPPED"; | |||
3119 | } | |||
3120 | else if (WIFEXITED(status)((((*(int *) &(status))) & 0x7f) == 0)) | |||
3121 | { | |||
3122 | exit_status = WEXITSTATUS(status)((((*(int *) &(status))) & 0xff00) >> 8); | |||
3123 | status_cstr = "EXITED"; | |||
3124 | exited = true; | |||
3125 | } | |||
3126 | else if (WIFSIGNALED(status)(((signed char) ((((*(int *) &(status))) & 0x7f) + 1) >> 1) > 0)) | |||
3127 | { | |||
3128 | signal = WTERMSIG(status)(((*(int *) &(status))) & 0x7f); | |||
3129 | status_cstr = "SIGNALED"; | |||
3130 | if (wait_pid == static_cast< ::pid_t>(GetID())) { | |||
3131 | exited = true; | |||
3132 | exit_status = -1; | |||
3133 | } | |||
3134 | } | |||
3135 | else | |||
3136 | status_cstr = "(\?\?\?)"; | |||
3137 | ||||
3138 | if (log) | |||
3139 | log->Printf("NativeProcessLinux::%s: waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG)" | |||
3140 | "=> pid = %" PRIi32"i" ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", | |||
3141 | __FUNCTION__, wait_pid, status, status_cstr, signal, exit_status); | |||
3142 | ||||
3143 | MonitorCallback (wait_pid, exited, signal, exit_status); | |||
3144 | } | |||
3145 | } | |||
3146 | ||||
3147 | // Wrapper for ptrace to catch errors and log calls. | |||
3148 | // Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) | |||
3149 | Error | |||
3150 | NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, long *result) | |||
3151 | { | |||
3152 | Error error; | |||
3153 | long int ret; | |||
3154 | ||||
3155 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE(1u << 12))); | |||
3156 | ||||
3157 | PtraceDisplayBytes(req, data, data_size); | |||
3158 | ||||
3159 | errno(*__errno_location ()) = 0; | |||
3160 | if (req == PTRACE_GETREGSETPTRACE_GETREGSET || req == PTRACE_SETREGSETPTRACE_SETREGSET) | |||
3161 | ret = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); | |||
| ||||
3162 | else | |||
3163 | ret = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); | |||
3164 | ||||
3165 | if (ret == -1) | |||
3166 | error.SetErrorToErrno(); | |||
3167 | ||||
3168 | if (result) | |||
3169 | *result = ret; | |||
3170 | ||||
3171 | if (log) | |||
3172 | log->Printf("ptrace(%d, %" PRIu64"l" "u" ", %p, %p, %zu)=%lX", req, pid, addr, data, data_size, ret); | |||
3173 | ||||
3174 | PtraceDisplayBytes(req, data, data_size); | |||
3175 | ||||
3176 | if (log && error.GetError() != 0) | |||
3177 | { | |||
3178 | const char* str; | |||
3179 | switch (error.GetError()) | |||
3180 | { | |||
3181 | case ESRCH3: str = "ESRCH"; break; | |||
3182 | case EINVAL22: str = "EINVAL"; break; | |||
3183 | case EBUSY16: str = "EBUSY"; break; | |||
3184 | case EPERM1: str = "EPERM"; break; | |||
3185 | default: str = error.AsCString(); | |||
3186 | } | |||
3187 | log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str); | |||
3188 | } | |||
3189 | ||||
3190 | return error; | |||
3191 | } |