1af245d11STodd Fiala //===-- NativeProcessLinux.cpp -------------------------------- -*- C++ -*-===// 2af245d11STodd Fiala // 3af245d11STodd Fiala // The LLVM Compiler Infrastructure 4af245d11STodd Fiala // 5af245d11STodd Fiala // This file is distributed under the University of Illinois Open Source 6af245d11STodd Fiala // License. See LICENSE.TXT for details. 7af245d11STodd Fiala // 8af245d11STodd Fiala //===----------------------------------------------------------------------===// 9af245d11STodd Fiala 10af245d11STodd Fiala #include "NativeProcessLinux.h" 11af245d11STodd Fiala 12af245d11STodd Fiala // C Includes 13af245d11STodd Fiala #include <errno.h> 14af245d11STodd Fiala #include <string.h> 15af245d11STodd Fiala #include <stdint.h> 16af245d11STodd Fiala #include <unistd.h> 17af245d11STodd Fiala 18af245d11STodd Fiala // C++ Includes 19af245d11STodd Fiala #include <fstream> 20df7c6995SPavel Labath #include <mutex> 21c076559aSPavel Labath #include <sstream> 22af245d11STodd Fiala #include <string> 235b981ab9SPavel Labath #include <unordered_map> 24af245d11STodd Fiala 25af245d11STodd Fiala // Other libraries and framework includes 26d8c338d4STamas Berghammer #include "lldb/Core/EmulateInstruction.h" 27af245d11STodd Fiala #include "lldb/Core/Error.h" 286edef204SOleksiy Vyalov #include "lldb/Core/ModuleSpec.h" 29af245d11STodd Fiala #include "lldb/Core/RegisterValue.h" 30af245d11STodd Fiala #include "lldb/Core/State.h" 31af245d11STodd Fiala #include "lldb/Host/Host.h" 3239de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h" 332a86b555SPavel Labath #include "lldb/Host/common/NativeBreakpoint.h" 342a86b555SPavel Labath #include "lldb/Host/common/NativeRegisterContext.h" 352a86b555SPavel Labath #include "lldb/Symbol/ObjectFile.h" 3690aff47cSZachary Turner #include "lldb/Target/Process.h" 37af245d11STodd Fiala #include "lldb/Target/ProcessLaunchInfo.h" 385b981ab9SPavel Labath #include "lldb/Target/Target.h" 39c16f5dcaSChaoren Lin #include "lldb/Utility/LLDBAssert.h" 40af245d11STodd Fiala #include "lldb/Utility/PseudoTerminal.h" 41f805e190SPavel Labath #include "lldb/Utility/StringExtractor.h" 42af245d11STodd Fiala 431e209fccSTamas Berghammer #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 44af245d11STodd Fiala #include "NativeThreadLinux.h" 45af245d11STodd Fiala #include "ProcFileReader.h" 461e209fccSTamas Berghammer #include "Procfs.h" 47cacde7dfSTodd Fiala 48d858487eSTamas Berghammer // System includes - They have to be included after framework includes because they define some 49d858487eSTamas Berghammer // macros which collide with variable names in other modules 50d858487eSTamas Berghammer #include <linux/unistd.h> 51d858487eSTamas Berghammer #include <sys/socket.h> 528b335671SVince Harron 53df7c6995SPavel Labath #include <sys/syscall.h> 54d858487eSTamas Berghammer #include <sys/types.h> 55d858487eSTamas Berghammer #include <sys/user.h> 56d858487eSTamas Berghammer #include <sys/wait.h> 57d858487eSTamas Berghammer 588b335671SVince Harron #include "lldb/Host/linux/Personality.h" 598b335671SVince Harron #include "lldb/Host/linux/Ptrace.h" 60df7c6995SPavel Labath #include "lldb/Host/linux/Uio.h" 618b335671SVince Harron #include "lldb/Host/android/Android.h" 62af245d11STodd Fiala 630bce1b67STodd Fiala #define LLDB_PERSONALITY_GET_CURRENT_SETTINGS 0xffffffff 64af245d11STodd Fiala 65af245d11STodd Fiala // Support hardware breakpoints in case it has not been defined 66af245d11STodd Fiala #ifndef TRAP_HWBKPT 67af245d11STodd Fiala #define TRAP_HWBKPT 4 68af245d11STodd Fiala #endif 69af245d11STodd Fiala 707cb18bf5STamas Berghammer using namespace lldb; 717cb18bf5STamas Berghammer using namespace lldb_private; 72db264a6dSTamas Berghammer using namespace lldb_private::process_linux; 737cb18bf5STamas Berghammer using namespace llvm; 747cb18bf5STamas Berghammer 75af245d11STodd Fiala // Private bits we only need internally. 76df7c6995SPavel Labath 77df7c6995SPavel Labath static bool ProcessVmReadvSupported() 78df7c6995SPavel Labath { 79df7c6995SPavel Labath static bool is_supported; 80df7c6995SPavel Labath static std::once_flag flag; 81df7c6995SPavel Labath 82df7c6995SPavel Labath std::call_once(flag, [] { 83df7c6995SPavel Labath Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 84df7c6995SPavel Labath 85df7c6995SPavel Labath uint32_t source = 0x47424742; 86df7c6995SPavel Labath uint32_t dest = 0; 87df7c6995SPavel Labath 88df7c6995SPavel Labath struct iovec local, remote; 89df7c6995SPavel Labath remote.iov_base = &source; 90df7c6995SPavel Labath local.iov_base = &dest; 91df7c6995SPavel Labath remote.iov_len = local.iov_len = sizeof source; 92df7c6995SPavel Labath 93df7c6995SPavel Labath // We shall try if cross-process-memory reads work by attempting to read a value from our own process. 94df7c6995SPavel Labath ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); 95df7c6995SPavel Labath is_supported = (res == sizeof(source) && source == dest); 96df7c6995SPavel Labath if (log) 97df7c6995SPavel Labath { 98df7c6995SPavel Labath if (is_supported) 99df7c6995SPavel Labath log->Printf("%s: Detected kernel support for process_vm_readv syscall. Fast memory reads enabled.", 100df7c6995SPavel Labath __FUNCTION__); 101df7c6995SPavel Labath else 102df7c6995SPavel Labath log->Printf("%s: syscall process_vm_readv failed (error: %s). Fast memory reads disabled.", 103df7c6995SPavel Labath __FUNCTION__, strerror(errno)); 104df7c6995SPavel Labath } 105df7c6995SPavel Labath }); 106df7c6995SPavel Labath 107df7c6995SPavel Labath return is_supported; 108df7c6995SPavel Labath } 109df7c6995SPavel Labath 110af245d11STodd Fiala namespace 111af245d11STodd Fiala { 112af245d11STodd Fiala Error 1132a86b555SPavel Labath ResolveProcessArchitecture(lldb::pid_t pid, ArchSpec &arch) 114af245d11STodd Fiala { 115af245d11STodd Fiala // Grab process info for the running process. 116af245d11STodd Fiala ProcessInstanceInfo process_info; 1172a86b555SPavel Labath if (!Host::GetProcessInfo(pid, process_info)) 118db264a6dSTamas Berghammer return Error("failed to get process info"); 119af245d11STodd Fiala 120af245d11STodd Fiala // Resolve the executable module. 1212a86b555SPavel Labath ModuleSpecList module_specs; 1222a86b555SPavel Labath if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), 0, 0, module_specs)) 1232a86b555SPavel Labath return Error("failed to get module specifications"); 1242a86b555SPavel Labath assert(module_specs.GetSize() == 1); 125af245d11STodd Fiala 1262a86b555SPavel Labath arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture(); 127af245d11STodd Fiala if (arch.IsValid()) 128af245d11STodd Fiala return Error(); 129af245d11STodd Fiala else 130af245d11STodd Fiala return Error("failed to retrieve a valid architecture from the exe module"); 131af245d11STodd Fiala } 132af245d11STodd Fiala 1330c4f01d4SPavel Labath // Used to notify the parent about which part of the launch sequence failed. 1340c4f01d4SPavel Labath enum LaunchCallSpecifier 1350c4f01d4SPavel Labath { 1360c4f01d4SPavel Labath ePtraceFailed, 1370c4f01d4SPavel Labath eDupStdinFailed, 1380c4f01d4SPavel Labath eDupStdoutFailed, 1390c4f01d4SPavel Labath eDupStderrFailed, 1400c4f01d4SPavel Labath eChdirFailed, 1410c4f01d4SPavel Labath eExecFailed, 1420c4f01d4SPavel Labath eSetGidFailed, 1430c4f01d4SPavel Labath eSetSigMaskFailed, 1440c4f01d4SPavel Labath eLaunchCallMax = eSetSigMaskFailed 1450c4f01d4SPavel Labath }; 1460c4f01d4SPavel Labath 1470c4f01d4SPavel Labath static uint8_t LLVM_ATTRIBUTE_NORETURN 1480c4f01d4SPavel Labath ExitChildAbnormally(LaunchCallSpecifier spec) 1490c4f01d4SPavel Labath { 1500c4f01d4SPavel Labath static_assert(eLaunchCallMax < 0x8, "Have more launch calls than we are able to represent"); 1510c4f01d4SPavel Labath // This may truncate the topmost bits of the errno because the exit code is only 8 bits wide. 1520c4f01d4SPavel Labath // However, it should still give us a pretty good indication of what went wrong. (And the 1530c4f01d4SPavel Labath // most common errors have small numbers anyway). 1540c4f01d4SPavel Labath _exit(unsigned(spec) | (errno << 3)); 1550c4f01d4SPavel Labath } 1560c4f01d4SPavel Labath 1570c4f01d4SPavel Labath // The second member is the errno (or its 5 lowermost bits anyway). 1580c4f01d4SPavel Labath inline std::pair<LaunchCallSpecifier, uint8_t> 1590c4f01d4SPavel Labath DecodeChildExitCode(int exit_code) 1600c4f01d4SPavel Labath { 1610c4f01d4SPavel Labath return std::make_pair(LaunchCallSpecifier(exit_code & 0x7), exit_code >> 3); 1620c4f01d4SPavel Labath } 1630c4f01d4SPavel Labath 164af245d11STodd Fiala void 165*4abe5d69SPavel Labath MaybeLogLaunchInfo(const ProcessLaunchInfo &info) 166*4abe5d69SPavel Labath { 167*4abe5d69SPavel Labath Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 168*4abe5d69SPavel Labath if (!log) 169*4abe5d69SPavel Labath return; 170*4abe5d69SPavel Labath 171*4abe5d69SPavel Labath if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO)) 172*4abe5d69SPavel Labath log->Printf("%s: setting STDIN to '%s'", __FUNCTION__, action->GetFileSpec().GetCString()); 173*4abe5d69SPavel Labath else 174*4abe5d69SPavel Labath log->Printf("%s leaving STDIN as is", __FUNCTION__); 175*4abe5d69SPavel Labath 176*4abe5d69SPavel Labath if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO)) 177*4abe5d69SPavel Labath log->Printf("%s setting STDOUT to '%s'", __FUNCTION__, action->GetFileSpec().GetCString()); 178*4abe5d69SPavel Labath else 179*4abe5d69SPavel Labath log->Printf("%s leaving STDOUT as is", __FUNCTION__); 180*4abe5d69SPavel Labath 181*4abe5d69SPavel Labath if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO)) 182*4abe5d69SPavel Labath log->Printf("%s setting STDERR to '%s'", __FUNCTION__, action->GetFileSpec().GetCString()); 183*4abe5d69SPavel Labath else 184*4abe5d69SPavel Labath log->Printf("%s leaving STDERR as is", __FUNCTION__); 185*4abe5d69SPavel Labath 186*4abe5d69SPavel Labath int i = 0; 187*4abe5d69SPavel Labath for (const char **args = info.GetArguments().GetConstArgumentVector(); *args; ++args, ++i) 188*4abe5d69SPavel Labath log->Printf("%s arg %d: \"%s\"", __FUNCTION__, i, *args ? *args : "nullptr"); 189*4abe5d69SPavel Labath } 190*4abe5d69SPavel Labath 191*4abe5d69SPavel Labath void 192db264a6dSTamas Berghammer DisplayBytes(StreamString &s, void *bytes, uint32_t count) 193af245d11STodd Fiala { 194af245d11STodd Fiala uint8_t *ptr = (uint8_t *)bytes; 195af245d11STodd Fiala const uint32_t loop_count = std::min<uint32_t>(DEBUG_PTRACE_MAXBYTES, count); 196af245d11STodd Fiala for (uint32_t i = 0; i < loop_count; i++) 197af245d11STodd Fiala { 198af245d11STodd Fiala s.Printf("[%x]", *ptr); 199af245d11STodd Fiala ptr++; 200af245d11STodd Fiala } 201af245d11STodd Fiala } 202af245d11STodd Fiala 203af245d11STodd Fiala void 204af245d11STodd Fiala PtraceDisplayBytes(int &req, void *data, size_t data_size) 205af245d11STodd Fiala { 206af245d11STodd Fiala StreamString buf; 207af245d11STodd Fiala Log *verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet ( 208af245d11STodd Fiala POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE)); 209af245d11STodd Fiala 210af245d11STodd Fiala if (verbose_log) 211af245d11STodd Fiala { 212af245d11STodd Fiala switch(req) 213af245d11STodd Fiala { 214af245d11STodd Fiala case PTRACE_POKETEXT: 215af245d11STodd Fiala { 216af245d11STodd Fiala DisplayBytes(buf, &data, 8); 217af245d11STodd Fiala verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData()); 218af245d11STodd Fiala break; 219af245d11STodd Fiala } 220af245d11STodd Fiala case PTRACE_POKEDATA: 221af245d11STodd Fiala { 222af245d11STodd Fiala DisplayBytes(buf, &data, 8); 223af245d11STodd Fiala verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData()); 224af245d11STodd Fiala break; 225af245d11STodd Fiala } 226af245d11STodd Fiala case PTRACE_POKEUSER: 227af245d11STodd Fiala { 228af245d11STodd Fiala DisplayBytes(buf, &data, 8); 229af245d11STodd Fiala verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData()); 230af245d11STodd Fiala break; 231af245d11STodd Fiala } 232af245d11STodd Fiala case PTRACE_SETREGS: 233af245d11STodd Fiala { 234af245d11STodd Fiala DisplayBytes(buf, data, data_size); 235af245d11STodd Fiala verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData()); 236af245d11STodd Fiala break; 237af245d11STodd Fiala } 238af245d11STodd Fiala case PTRACE_SETFPREGS: 239af245d11STodd Fiala { 240af245d11STodd Fiala DisplayBytes(buf, data, data_size); 241af245d11STodd Fiala verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData()); 242af245d11STodd Fiala break; 243af245d11STodd Fiala } 244af245d11STodd Fiala case PTRACE_SETSIGINFO: 245af245d11STodd Fiala { 246af245d11STodd Fiala DisplayBytes(buf, data, sizeof(siginfo_t)); 247af245d11STodd Fiala verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData()); 248af245d11STodd Fiala break; 249af245d11STodd Fiala } 250af245d11STodd Fiala case PTRACE_SETREGSET: 251af245d11STodd Fiala { 252af245d11STodd Fiala // Extract iov_base from data, which is a pointer to the struct IOVEC 253af245d11STodd Fiala DisplayBytes(buf, *(void **)data, data_size); 254af245d11STodd Fiala verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData()); 255af245d11STodd Fiala break; 256af245d11STodd Fiala } 257af245d11STodd Fiala default: 258af245d11STodd Fiala { 259af245d11STodd Fiala } 260af245d11STodd Fiala } 261af245d11STodd Fiala } 262af245d11STodd Fiala } 263af245d11STodd Fiala 26419cbe96aSPavel Labath static constexpr unsigned k_ptrace_word_size = sizeof(void*); 26519cbe96aSPavel Labath static_assert(sizeof(long) >= k_ptrace_word_size, "Size of long must be larger than ptrace word size"); 2661107b5a5SPavel Labath } // end of anonymous namespace 2671107b5a5SPavel Labath 268bd7cbc5aSPavel Labath // Simple helper function to ensure flags are enabled on the given file 269bd7cbc5aSPavel Labath // descriptor. 270bd7cbc5aSPavel Labath static Error 271bd7cbc5aSPavel Labath EnsureFDFlags(int fd, int flags) 272bd7cbc5aSPavel Labath { 273bd7cbc5aSPavel Labath Error error; 274bd7cbc5aSPavel Labath 275bd7cbc5aSPavel Labath int status = fcntl(fd, F_GETFL); 276bd7cbc5aSPavel Labath if (status == -1) 277bd7cbc5aSPavel Labath { 278bd7cbc5aSPavel Labath error.SetErrorToErrno(); 279bd7cbc5aSPavel Labath return error; 280bd7cbc5aSPavel Labath } 281bd7cbc5aSPavel Labath 282bd7cbc5aSPavel Labath if (fcntl(fd, F_SETFL, status | flags) == -1) 283bd7cbc5aSPavel Labath { 284bd7cbc5aSPavel Labath error.SetErrorToErrno(); 285bd7cbc5aSPavel Labath return error; 286bd7cbc5aSPavel Labath } 287bd7cbc5aSPavel Labath 288bd7cbc5aSPavel Labath return error; 289bd7cbc5aSPavel Labath } 290bd7cbc5aSPavel Labath 291af245d11STodd Fiala // ----------------------------------------------------------------------------- 292af245d11STodd Fiala // Public Static Methods 293af245d11STodd Fiala // ----------------------------------------------------------------------------- 294af245d11STodd Fiala 295db264a6dSTamas Berghammer Error 296d5b310f2SPavel Labath NativeProcessProtocol::Launch ( 297db264a6dSTamas Berghammer ProcessLaunchInfo &launch_info, 298db264a6dSTamas Berghammer NativeProcessProtocol::NativeDelegate &native_delegate, 29919cbe96aSPavel Labath MainLoop &mainloop, 300af245d11STodd Fiala NativeProcessProtocolSP &native_process_sp) 301af245d11STodd Fiala { 302af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 303af245d11STodd Fiala 3042a86b555SPavel Labath Error error; 305af245d11STodd Fiala 306af245d11STodd Fiala // Verify the working directory is valid if one was specified. 307d3173f34SChaoren Lin FileSpec working_dir{launch_info.GetWorkingDirectory()}; 308d3173f34SChaoren Lin if (working_dir && 309d3173f34SChaoren Lin (!working_dir.ResolvePath() || 310d3173f34SChaoren Lin working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) 311af245d11STodd Fiala { 312d3173f34SChaoren Lin error.SetErrorStringWithFormat ("No such file or directory: %s", 313d3173f34SChaoren Lin working_dir.GetCString()); 314af245d11STodd Fiala return error; 315af245d11STodd Fiala } 316af245d11STodd Fiala 317af245d11STodd Fiala // Create the NativeProcessLinux in launch mode. 318af245d11STodd Fiala native_process_sp.reset (new NativeProcessLinux ()); 319af245d11STodd Fiala 320af245d11STodd Fiala if (!native_process_sp->RegisterNativeDelegate (native_delegate)) 321af245d11STodd Fiala { 322af245d11STodd Fiala native_process_sp.reset (); 323af245d11STodd Fiala error.SetErrorStringWithFormat ("failed to register the native delegate"); 324af245d11STodd Fiala return error; 325af245d11STodd Fiala } 326af245d11STodd Fiala 327*4abe5d69SPavel Labath error = std::static_pointer_cast<NativeProcessLinux>(native_process_sp)->LaunchInferior(mainloop, launch_info); 328af245d11STodd Fiala 329af245d11STodd Fiala if (error.Fail ()) 330af245d11STodd Fiala { 331af245d11STodd Fiala native_process_sp.reset (); 332af245d11STodd Fiala if (log) 333af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s failed to launch process: %s", __FUNCTION__, error.AsCString ()); 334af245d11STodd Fiala return error; 335af245d11STodd Fiala } 336af245d11STodd Fiala 337af245d11STodd Fiala launch_info.SetProcessID (native_process_sp->GetID ()); 338af245d11STodd Fiala 339af245d11STodd Fiala return error; 340af245d11STodd Fiala } 341af245d11STodd Fiala 342db264a6dSTamas Berghammer Error 343d5b310f2SPavel Labath NativeProcessProtocol::Attach ( 344af245d11STodd Fiala lldb::pid_t pid, 345db264a6dSTamas Berghammer NativeProcessProtocol::NativeDelegate &native_delegate, 34619cbe96aSPavel Labath MainLoop &mainloop, 347af245d11STodd Fiala NativeProcessProtocolSP &native_process_sp) 348af245d11STodd Fiala { 349af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 350af245d11STodd Fiala if (log && log->GetMask ().Test (POSIX_LOG_VERBOSE)) 351af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s(pid = %" PRIi64 ")", __FUNCTION__, pid); 352af245d11STodd Fiala 353af245d11STodd Fiala // Retrieve the architecture for the running process. 354af245d11STodd Fiala ArchSpec process_arch; 3552a86b555SPavel Labath Error error = ResolveProcessArchitecture(pid, process_arch); 356af245d11STodd Fiala if (!error.Success ()) 357af245d11STodd Fiala return error; 358af245d11STodd Fiala 3591339b5e8SOleksiy Vyalov std::shared_ptr<NativeProcessLinux> native_process_linux_sp (new NativeProcessLinux ()); 360af245d11STodd Fiala 3611339b5e8SOleksiy Vyalov if (!native_process_linux_sp->RegisterNativeDelegate (native_delegate)) 362af245d11STodd Fiala { 363af245d11STodd Fiala error.SetErrorStringWithFormat ("failed to register the native delegate"); 364af245d11STodd Fiala return error; 365af245d11STodd Fiala } 366af245d11STodd Fiala 36719cbe96aSPavel Labath native_process_linux_sp->AttachToInferior (mainloop, pid, error); 368af245d11STodd Fiala if (!error.Success ()) 369af245d11STodd Fiala return error; 370af245d11STodd Fiala 3711339b5e8SOleksiy Vyalov native_process_sp = native_process_linux_sp; 372af245d11STodd Fiala return error; 373af245d11STodd Fiala } 374af245d11STodd Fiala 375af245d11STodd Fiala // ----------------------------------------------------------------------------- 376af245d11STodd Fiala // Public Instance Methods 377af245d11STodd Fiala // ----------------------------------------------------------------------------- 378af245d11STodd Fiala 379af245d11STodd Fiala NativeProcessLinux::NativeProcessLinux () : 380af245d11STodd Fiala NativeProcessProtocol (LLDB_INVALID_PROCESS_ID), 381af245d11STodd Fiala m_arch (), 382af245d11STodd Fiala m_supports_mem_region (eLazyBoolCalculate), 383af245d11STodd Fiala m_mem_region_cache (), 3840e1d729bSPavel Labath m_pending_notification_tid(LLDB_INVALID_THREAD_ID) 385af245d11STodd Fiala { 386af245d11STodd Fiala } 387af245d11STodd Fiala 388af245d11STodd Fiala void 38919cbe96aSPavel Labath NativeProcessLinux::AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error) 390af245d11STodd Fiala { 391af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 392af245d11STodd Fiala if (log) 393af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ")", __FUNCTION__, pid); 394af245d11STodd Fiala 39519cbe96aSPavel Labath m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD, 39619cbe96aSPavel Labath [this] (MainLoopBase &) { SigchldHandler(); }, error); 39719cbe96aSPavel Labath if (! m_sigchld_handle) 39819cbe96aSPavel Labath return; 39919cbe96aSPavel Labath 4002a86b555SPavel Labath error = ResolveProcessArchitecture(pid, m_arch); 401af245d11STodd Fiala if (!error.Success()) 402af245d11STodd Fiala return; 403af245d11STodd Fiala 404af245d11STodd Fiala // Set the architecture to the exe architecture. 405af245d11STodd Fiala if (log) 406af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ") detected architecture %s", __FUNCTION__, pid, m_arch.GetArchitectureName ()); 407af245d11STodd Fiala 408af245d11STodd Fiala m_pid = pid; 409af245d11STodd Fiala SetState(eStateAttaching); 410af245d11STodd Fiala 41119cbe96aSPavel Labath Attach(pid, error); 412af245d11STodd Fiala } 413af245d11STodd Fiala 4140c4f01d4SPavel Labath void 415*4abe5d69SPavel Labath NativeProcessLinux::ChildFunc(const ProcessLaunchInfo &info) 416af245d11STodd Fiala { 41775f47c3aSTodd Fiala // Start tracing this child that is about to exec. 4180c4f01d4SPavel Labath if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1) 4190c4f01d4SPavel Labath ExitChildAbnormally(ePtraceFailed); 420493c3a12SPavel Labath 421af245d11STodd Fiala // Do not inherit setgid powers. 422af245d11STodd Fiala if (setgid(getgid()) != 0) 4230c4f01d4SPavel Labath ExitChildAbnormally(eSetGidFailed); 424af245d11STodd Fiala 425af245d11STodd Fiala // Attempt to have our own process group. 426af245d11STodd Fiala if (setpgid(0, 0) != 0) 427af245d11STodd Fiala { 42875f47c3aSTodd Fiala // FIXME log that this failed. This is common. 429af245d11STodd Fiala // Don't allow this to prevent an inferior exec. 430af245d11STodd Fiala } 431af245d11STodd Fiala 432af245d11STodd Fiala // Dup file descriptors if needed. 433*4abe5d69SPavel Labath if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO)) 434*4abe5d69SPavel Labath if (!DupDescriptor(action->GetFileSpec(), STDIN_FILENO, O_RDONLY)) 4350c4f01d4SPavel Labath ExitChildAbnormally(eDupStdinFailed); 436af245d11STodd Fiala 437*4abe5d69SPavel Labath if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO)) 438*4abe5d69SPavel Labath if (!DupDescriptor(action->GetFileSpec(), STDOUT_FILENO, O_WRONLY | O_CREAT | O_TRUNC)) 4390c4f01d4SPavel Labath ExitChildAbnormally(eDupStdoutFailed); 440af245d11STodd Fiala 441*4abe5d69SPavel Labath if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO)) 442*4abe5d69SPavel Labath if (!DupDescriptor(action->GetFileSpec(), STDERR_FILENO, O_WRONLY | O_CREAT | O_TRUNC)) 4430c4f01d4SPavel Labath ExitChildAbnormally(eDupStderrFailed); 444af245d11STodd Fiala 4459cf4f2c2SChaoren Lin // Close everything besides stdin, stdout, and stderr that has no file 4469cf4f2c2SChaoren Lin // action to avoid leaking 4479cf4f2c2SChaoren Lin for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd) 448*4abe5d69SPavel Labath if (!info.GetFileActionForFD(fd)) 4499cf4f2c2SChaoren Lin close(fd); 4509cf4f2c2SChaoren Lin 451af245d11STodd Fiala // Change working directory 452*4abe5d69SPavel Labath if (info.GetWorkingDirectory() && 0 != ::chdir(info.GetWorkingDirectory().GetCString())) 4530c4f01d4SPavel Labath ExitChildAbnormally(eChdirFailed); 454af245d11STodd Fiala 4550bce1b67STodd Fiala // Disable ASLR if requested. 456*4abe5d69SPavel Labath if (info.GetFlags().Test(lldb::eLaunchFlagDisableASLR)) 4570bce1b67STodd Fiala { 4580bce1b67STodd Fiala const int old_personality = personality(LLDB_PERSONALITY_GET_CURRENT_SETTINGS); 4590bce1b67STodd Fiala if (old_personality == -1) 4600bce1b67STodd Fiala { 46175f47c3aSTodd Fiala // Can't retrieve Linux personality. Cannot disable ASLR. 4620bce1b67STodd Fiala } 4630bce1b67STodd Fiala else 4640bce1b67STodd Fiala { 4650bce1b67STodd Fiala const int new_personality = personality(ADDR_NO_RANDOMIZE | old_personality); 4660bce1b67STodd Fiala if (new_personality == -1) 4670bce1b67STodd Fiala { 46875f47c3aSTodd Fiala // Disabling ASLR failed. 4690bce1b67STodd Fiala } 4700bce1b67STodd Fiala else 4710bce1b67STodd Fiala { 47275f47c3aSTodd Fiala // Disabling ASLR succeeded. 4730bce1b67STodd Fiala } 4740bce1b67STodd Fiala } 4750bce1b67STodd Fiala } 4760bce1b67STodd Fiala 47778856474SPavel Labath // Clear the signal mask to prevent the child from being affected by 47878856474SPavel Labath // any masking done by the parent. 47978856474SPavel Labath sigset_t set; 48078856474SPavel Labath if (sigemptyset(&set) != 0 || pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0) 4810c4f01d4SPavel Labath ExitChildAbnormally(eSetSigMaskFailed); 4820c4f01d4SPavel Labath 483*4abe5d69SPavel Labath const char **argv = info.GetArguments().GetConstArgumentVector(); 484*4abe5d69SPavel Labath 4850c4f01d4SPavel Labath // Propagate the environment if one is not supplied. 486*4abe5d69SPavel Labath const char **envp = info.GetEnvironmentEntries().GetConstArgumentVector(); 4870c4f01d4SPavel Labath if (envp == NULL || envp[0] == NULL) 4880c4f01d4SPavel Labath envp = const_cast<const char **>(environ); 48978856474SPavel Labath 49075f47c3aSTodd Fiala // Execute. We should never return... 491*4abe5d69SPavel Labath execve(argv[0], const_cast<char *const *>(argv), const_cast<char *const *>(envp)); 49275f47c3aSTodd Fiala 493ca92aed5SPavel Labath if (errno == ETXTBSY) 494ca92aed5SPavel Labath { 495ca92aed5SPavel Labath // On android M and earlier we can get this error because the adb deamon can hold a write 496ca92aed5SPavel Labath // handle on the executable even after it has finished uploading it. This state lasts 497ca92aed5SPavel Labath // only a short time and happens only when there are many concurrent adb commands being 498ca92aed5SPavel Labath // issued, such as when running the test suite. (The file remains open when someone does 499ca92aed5SPavel Labath // an "adb shell" command in the fork() child before it has had a chance to exec.) Since 500ca92aed5SPavel Labath // this state should clear up quickly, wait a while and then give it one more go. 5013be0a3a1SPavel Labath usleep(50000); 502*4abe5d69SPavel Labath execve(argv[0], const_cast<char *const *>(argv), const_cast<char *const *>(envp)); 503ca92aed5SPavel Labath } 504ca92aed5SPavel Labath 50575f47c3aSTodd Fiala // ...unless exec fails. In which case we definitely need to end the child here. 5060c4f01d4SPavel Labath ExitChildAbnormally(eExecFailed); 507af245d11STodd Fiala } 508af245d11STodd Fiala 509*4abe5d69SPavel Labath Error 510*4abe5d69SPavel Labath NativeProcessLinux::LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info) 5110c4f01d4SPavel Labath { 512*4abe5d69SPavel Labath Error error; 513*4abe5d69SPavel Labath m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); 514*4abe5d69SPavel Labath if (!m_sigchld_handle) 515*4abe5d69SPavel Labath return error; 516*4abe5d69SPavel Labath 517*4abe5d69SPavel Labath SetState(eStateLaunching); 5180c4f01d4SPavel Labath 5190c4f01d4SPavel Labath lldb_utility::PseudoTerminal terminal; 5200c4f01d4SPavel Labath const size_t err_len = 1024; 5210c4f01d4SPavel Labath char err_str[err_len]; 5220c4f01d4SPavel Labath lldb::pid_t pid; 5230c4f01d4SPavel Labath 524*4abe5d69SPavel Labath MaybeLogLaunchInfo(launch_info); 525*4abe5d69SPavel Labath 5260c4f01d4SPavel Labath if ((pid = terminal.Fork(err_str, err_len)) == static_cast<lldb::pid_t> (-1)) 5270c4f01d4SPavel Labath { 5280c4f01d4SPavel Labath error.SetErrorToGenericError(); 5290c4f01d4SPavel Labath error.SetErrorStringWithFormat("Process fork failed: %s", err_str); 530*4abe5d69SPavel Labath return error; 5310c4f01d4SPavel Labath } 5320c4f01d4SPavel Labath 5330c4f01d4SPavel Labath // Child process. 5340c4f01d4SPavel Labath if (pid == 0) 5350c4f01d4SPavel Labath { 5360c4f01d4SPavel Labath // First, make sure we disable all logging. If we are logging to stdout, our logs can be 5370c4f01d4SPavel Labath // mistaken for inferior output. 5380c4f01d4SPavel Labath Log::DisableAllLogChannels(nullptr); 5390c4f01d4SPavel Labath 5400c4f01d4SPavel Labath // terminal has already dupped the tty descriptors to stdin/out/err. 5410c4f01d4SPavel Labath // This closes original fd from which they were copied (and avoids 5420c4f01d4SPavel Labath // leaking descriptors to the debugged process. 5430c4f01d4SPavel Labath terminal.CloseSlaveFileDescriptor(); 5440c4f01d4SPavel Labath 545*4abe5d69SPavel Labath ChildFunc(launch_info); 5460c4f01d4SPavel Labath } 5470c4f01d4SPavel Labath 54875f47c3aSTodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 54975f47c3aSTodd Fiala 550af245d11STodd Fiala // Wait for the child process to trap on its call to execve. 551af245d11STodd Fiala ::pid_t wpid; 552af245d11STodd Fiala int status; 553af245d11STodd Fiala if ((wpid = waitpid(pid, &status, 0)) < 0) 554af245d11STodd Fiala { 555bd7cbc5aSPavel Labath error.SetErrorToErrno(); 556af245d11STodd Fiala if (log) 557bd7cbc5aSPavel Labath log->Printf ("NativeProcessLinux::%s waitpid for inferior failed with %s", 558bd7cbc5aSPavel Labath __FUNCTION__, error.AsCString ()); 559af245d11STodd Fiala 560af245d11STodd Fiala // Mark the inferior as invalid. 561af245d11STodd Fiala // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. 562bd7cbc5aSPavel Labath SetState (StateType::eStateInvalid); 563af245d11STodd Fiala 564*4abe5d69SPavel Labath return error; 565af245d11STodd Fiala } 566af245d11STodd Fiala else if (WIFEXITED(status)) 567af245d11STodd Fiala { 5680c4f01d4SPavel Labath auto p = DecodeChildExitCode(WEXITSTATUS(status)); 5690c4f01d4SPavel Labath Error child_error(p.second, eErrorTypePOSIX); 5700c4f01d4SPavel Labath const char *failure_reason; 5710c4f01d4SPavel Labath switch (p.first) 572af245d11STodd Fiala { 573af245d11STodd Fiala case ePtraceFailed: 5740c4f01d4SPavel Labath failure_reason = "Child ptrace failed"; 575af245d11STodd Fiala break; 576af245d11STodd Fiala case eDupStdinFailed: 5770c4f01d4SPavel Labath failure_reason = "Child open stdin failed"; 578af245d11STodd Fiala break; 579af245d11STodd Fiala case eDupStdoutFailed: 5800c4f01d4SPavel Labath failure_reason = "Child open stdout failed"; 581af245d11STodd Fiala break; 582af245d11STodd Fiala case eDupStderrFailed: 5830c4f01d4SPavel Labath failure_reason = "Child open stderr failed"; 584af245d11STodd Fiala break; 585af245d11STodd Fiala case eChdirFailed: 5860c4f01d4SPavel Labath failure_reason = "Child failed to set working directory"; 587af245d11STodd Fiala break; 588af245d11STodd Fiala case eExecFailed: 5890c4f01d4SPavel Labath failure_reason = "Child exec failed"; 590af245d11STodd Fiala break; 591af245d11STodd Fiala case eSetGidFailed: 5920c4f01d4SPavel Labath failure_reason = "Child setgid failed"; 593af245d11STodd Fiala break; 59478856474SPavel Labath case eSetSigMaskFailed: 5950c4f01d4SPavel Labath failure_reason = "Child failed to set signal mask"; 596af245d11STodd Fiala break; 597af245d11STodd Fiala } 5980c4f01d4SPavel Labath error.SetErrorStringWithFormat("%s: %d - %s (error code truncated)", failure_reason, child_error.GetError(), child_error.AsCString()); 599af245d11STodd Fiala 600af245d11STodd Fiala if (log) 601af245d11STodd Fiala { 602af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s inferior exited with status %d before issuing a STOP", 603af245d11STodd Fiala __FUNCTION__, 604af245d11STodd Fiala WEXITSTATUS(status)); 605af245d11STodd Fiala } 606af245d11STodd Fiala 607af245d11STodd Fiala // Mark the inferior as invalid. 608af245d11STodd Fiala // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. 609bd7cbc5aSPavel Labath SetState (StateType::eStateInvalid); 610af245d11STodd Fiala 611*4abe5d69SPavel Labath return error; 612af245d11STodd Fiala } 613af245d11STodd Fiala assert(WIFSTOPPED(status) && (wpid == static_cast< ::pid_t> (pid)) && 614af245d11STodd Fiala "Could not sync with inferior process."); 615af245d11STodd Fiala 616af245d11STodd Fiala if (log) 617af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s inferior started, now in stopped state", __FUNCTION__); 618af245d11STodd Fiala 619bd7cbc5aSPavel Labath error = SetDefaultPtraceOpts(pid); 620bd7cbc5aSPavel Labath if (error.Fail()) 621af245d11STodd Fiala { 622af245d11STodd Fiala if (log) 623af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s inferior failed to set default ptrace options: %s", 624bd7cbc5aSPavel Labath __FUNCTION__, error.AsCString ()); 625af245d11STodd Fiala 626af245d11STodd Fiala // Mark the inferior as invalid. 627af245d11STodd Fiala // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. 628bd7cbc5aSPavel Labath SetState (StateType::eStateInvalid); 629af245d11STodd Fiala 630*4abe5d69SPavel Labath return error; 631af245d11STodd Fiala } 632af245d11STodd Fiala 633af245d11STodd Fiala // Release the master terminal descriptor and pass it off to the 634af245d11STodd Fiala // NativeProcessLinux instance. Similarly stash the inferior pid. 635bd7cbc5aSPavel Labath m_terminal_fd = terminal.ReleaseMasterFileDescriptor(); 636bd7cbc5aSPavel Labath m_pid = pid; 637*4abe5d69SPavel Labath launch_info.SetProcessID(pid); 638af245d11STodd Fiala 639af245d11STodd Fiala // Set the terminal fd to be in non blocking mode (it simplifies the 640af245d11STodd Fiala // implementation of ProcessLinux::GetSTDOUT to have a non-blocking 641af245d11STodd Fiala // descriptor to read from). 642bd7cbc5aSPavel Labath error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); 643bd7cbc5aSPavel Labath if (error.Fail()) 644af245d11STodd Fiala { 645af245d11STodd Fiala if (log) 646af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s inferior EnsureFDFlags failed for ensuring terminal O_NONBLOCK setting: %s", 647bd7cbc5aSPavel Labath __FUNCTION__, error.AsCString ()); 648af245d11STodd Fiala 649af245d11STodd Fiala // Mark the inferior as invalid. 650af245d11STodd Fiala // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. 651bd7cbc5aSPavel Labath SetState (StateType::eStateInvalid); 652af245d11STodd Fiala 653*4abe5d69SPavel Labath return error; 654af245d11STodd Fiala } 655af245d11STodd Fiala 656af245d11STodd Fiala if (log) 657af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s() adding pid = %" PRIu64, __FUNCTION__, pid); 658af245d11STodd Fiala 6592a86b555SPavel Labath ResolveProcessArchitecture(m_pid, m_arch); 660f9077782SPavel Labath NativeThreadLinuxSP thread_sp = AddThread(pid); 661af245d11STodd Fiala assert (thread_sp && "AddThread() returned a nullptr thread"); 662f9077782SPavel Labath thread_sp->SetStoppedBySignal(SIGSTOP); 663f9077782SPavel Labath ThreadWasCreated(*thread_sp); 664af245d11STodd Fiala 665af245d11STodd Fiala // Let our process instance know the thread has stopped. 666bd7cbc5aSPavel Labath SetCurrentThreadID (thread_sp->GetID ()); 667bd7cbc5aSPavel Labath SetState (StateType::eStateStopped); 668af245d11STodd Fiala 669af245d11STodd Fiala if (log) 670af245d11STodd Fiala { 671bd7cbc5aSPavel Labath if (error.Success ()) 672af245d11STodd Fiala log->Printf("NativeProcessLinux::%s inferior launching succeeded", __FUNCTION__); 673af245d11STodd Fiala else 674*4abe5d69SPavel Labath log->Printf("NativeProcessLinux::%s inferior launching failed: %s", __FUNCTION__, error.AsCString()); 675af245d11STodd Fiala } 676*4abe5d69SPavel Labath return error; 677af245d11STodd Fiala } 678af245d11STodd Fiala 679bd7cbc5aSPavel Labath ::pid_t 680bd7cbc5aSPavel Labath NativeProcessLinux::Attach(lldb::pid_t pid, Error &error) 681af245d11STodd Fiala { 682af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 683af245d11STodd Fiala 684af245d11STodd Fiala // Use a map to keep track of the threads which we have attached/need to attach. 685af245d11STodd Fiala Host::TidMap tids_to_attach; 686af245d11STodd Fiala if (pid <= 1) 687af245d11STodd Fiala { 688bd7cbc5aSPavel Labath error.SetErrorToGenericError(); 689bd7cbc5aSPavel Labath error.SetErrorString("Attaching to process 1 is not allowed."); 690bd7cbc5aSPavel Labath return -1; 691af245d11STodd Fiala } 692af245d11STodd Fiala 693af245d11STodd Fiala while (Host::FindProcessThreads(pid, tids_to_attach)) 694af245d11STodd Fiala { 695af245d11STodd Fiala for (Host::TidMap::iterator it = tids_to_attach.begin(); 696af245d11STodd Fiala it != tids_to_attach.end();) 697af245d11STodd Fiala { 698af245d11STodd Fiala if (it->second == false) 699af245d11STodd Fiala { 700af245d11STodd Fiala lldb::tid_t tid = it->first; 701af245d11STodd Fiala 702af245d11STodd Fiala // Attach to the requested process. 703af245d11STodd Fiala // An attach will cause the thread to stop with a SIGSTOP. 7044a9babb2SPavel Labath error = PtraceWrapper(PTRACE_ATTACH, tid); 705bd7cbc5aSPavel Labath if (error.Fail()) 706af245d11STodd Fiala { 707af245d11STodd Fiala // No such thread. The thread may have exited. 708af245d11STodd Fiala // More error handling may be needed. 709bd7cbc5aSPavel Labath if (error.GetError() == ESRCH) 710af245d11STodd Fiala { 711af245d11STodd Fiala it = tids_to_attach.erase(it); 712af245d11STodd Fiala continue; 713af245d11STodd Fiala } 714af245d11STodd Fiala else 715bd7cbc5aSPavel Labath return -1; 716af245d11STodd Fiala } 717af245d11STodd Fiala 718af245d11STodd Fiala int status; 719af245d11STodd Fiala // Need to use __WALL otherwise we receive an error with errno=ECHLD 720af245d11STodd Fiala // At this point we should have a thread stopped if waitpid succeeds. 721af245d11STodd Fiala if ((status = waitpid(tid, NULL, __WALL)) < 0) 722af245d11STodd Fiala { 723af245d11STodd Fiala // No such thread. The thread may have exited. 724af245d11STodd Fiala // More error handling may be needed. 725af245d11STodd Fiala if (errno == ESRCH) 726af245d11STodd Fiala { 727af245d11STodd Fiala it = tids_to_attach.erase(it); 728af245d11STodd Fiala continue; 729af245d11STodd Fiala } 730af245d11STodd Fiala else 731af245d11STodd Fiala { 732bd7cbc5aSPavel Labath error.SetErrorToErrno(); 733bd7cbc5aSPavel Labath return -1; 734af245d11STodd Fiala } 735af245d11STodd Fiala } 736af245d11STodd Fiala 737bd7cbc5aSPavel Labath error = SetDefaultPtraceOpts(tid); 738bd7cbc5aSPavel Labath if (error.Fail()) 739bd7cbc5aSPavel Labath return -1; 740af245d11STodd Fiala 741af245d11STodd Fiala if (log) 742af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s() adding tid = %" PRIu64, __FUNCTION__, tid); 743af245d11STodd Fiala 744af245d11STodd Fiala it->second = true; 745af245d11STodd Fiala 746af245d11STodd Fiala // Create the thread, mark it as stopped. 747f9077782SPavel Labath NativeThreadLinuxSP thread_sp (AddThread(static_cast<lldb::tid_t>(tid))); 748af245d11STodd Fiala assert (thread_sp && "AddThread() returned a nullptr"); 749fa03ad2eSChaoren Lin 750fa03ad2eSChaoren Lin // This will notify this is a new thread and tell the system it is stopped. 751f9077782SPavel Labath thread_sp->SetStoppedBySignal(SIGSTOP); 752f9077782SPavel Labath ThreadWasCreated(*thread_sp); 753bd7cbc5aSPavel Labath SetCurrentThreadID (thread_sp->GetID ()); 754af245d11STodd Fiala } 755af245d11STodd Fiala 756af245d11STodd Fiala // move the loop forward 757af245d11STodd Fiala ++it; 758af245d11STodd Fiala } 759af245d11STodd Fiala } 760af245d11STodd Fiala 761af245d11STodd Fiala if (tids_to_attach.size() > 0) 762af245d11STodd Fiala { 763bd7cbc5aSPavel Labath m_pid = pid; 764af245d11STodd Fiala // Let our process instance know the thread has stopped. 765bd7cbc5aSPavel Labath SetState (StateType::eStateStopped); 766af245d11STodd Fiala } 767af245d11STodd Fiala else 768af245d11STodd Fiala { 769bd7cbc5aSPavel Labath error.SetErrorToGenericError(); 770bd7cbc5aSPavel Labath error.SetErrorString("No such process."); 771bd7cbc5aSPavel Labath return -1; 772af245d11STodd Fiala } 773af245d11STodd Fiala 774bd7cbc5aSPavel Labath return pid; 775af245d11STodd Fiala } 776af245d11STodd Fiala 77797ccc294SChaoren Lin Error 778af245d11STodd Fiala NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) 779af245d11STodd Fiala { 780af245d11STodd Fiala long ptrace_opts = 0; 781af245d11STodd Fiala 782af245d11STodd Fiala // Have the child raise an event on exit. This is used to keep the child in 783af245d11STodd Fiala // limbo until it is destroyed. 784af245d11STodd Fiala ptrace_opts |= PTRACE_O_TRACEEXIT; 785af245d11STodd Fiala 786af245d11STodd Fiala // Have the tracer trace threads which spawn in the inferior process. 787af245d11STodd Fiala // TODO: if we want to support tracing the inferiors' child, add the 788af245d11STodd Fiala // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK) 789af245d11STodd Fiala ptrace_opts |= PTRACE_O_TRACECLONE; 790af245d11STodd Fiala 791af245d11STodd Fiala // Have the tracer notify us before execve returns 792af245d11STodd Fiala // (needed to disable legacy SIGTRAP generation) 793af245d11STodd Fiala ptrace_opts |= PTRACE_O_TRACEEXEC; 794af245d11STodd Fiala 7954a9babb2SPavel Labath return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void*)ptrace_opts); 796af245d11STodd Fiala } 797af245d11STodd Fiala 798af245d11STodd Fiala static ExitType convert_pid_status_to_exit_type (int status) 799af245d11STodd Fiala { 800af245d11STodd Fiala if (WIFEXITED (status)) 801af245d11STodd Fiala return ExitType::eExitTypeExit; 802af245d11STodd Fiala else if (WIFSIGNALED (status)) 803af245d11STodd Fiala return ExitType::eExitTypeSignal; 804af245d11STodd Fiala else if (WIFSTOPPED (status)) 805af245d11STodd Fiala return ExitType::eExitTypeStop; 806af245d11STodd Fiala else 807af245d11STodd Fiala { 808af245d11STodd Fiala // We don't know what this is. 809af245d11STodd Fiala return ExitType::eExitTypeInvalid; 810af245d11STodd Fiala } 811af245d11STodd Fiala } 812af245d11STodd Fiala 813af245d11STodd Fiala static int convert_pid_status_to_return_code (int status) 814af245d11STodd Fiala { 815af245d11STodd Fiala if (WIFEXITED (status)) 816af245d11STodd Fiala return WEXITSTATUS (status); 817af245d11STodd Fiala else if (WIFSIGNALED (status)) 818af245d11STodd Fiala return WTERMSIG (status); 819af245d11STodd Fiala else if (WIFSTOPPED (status)) 820af245d11STodd Fiala return WSTOPSIG (status); 821af245d11STodd Fiala else 822af245d11STodd Fiala { 823af245d11STodd Fiala // We don't know what this is. 824af245d11STodd Fiala return ExitType::eExitTypeInvalid; 825af245d11STodd Fiala } 826af245d11STodd Fiala } 827af245d11STodd Fiala 8281107b5a5SPavel Labath // Handles all waitpid events from the inferior process. 8291107b5a5SPavel Labath void 8301107b5a5SPavel Labath NativeProcessLinux::MonitorCallback(lldb::pid_t pid, 831af245d11STodd Fiala bool exited, 832af245d11STodd Fiala int signal, 833af245d11STodd Fiala int status) 834af245d11STodd Fiala { 835af245d11STodd Fiala Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS)); 836af245d11STodd Fiala 837af245d11STodd Fiala // Certain activities differ based on whether the pid is the tid of the main thread. 8381107b5a5SPavel Labath const bool is_main_thread = (pid == GetID ()); 839af245d11STodd Fiala 840af245d11STodd Fiala // Handle when the thread exits. 841af245d11STodd Fiala if (exited) 842af245d11STodd Fiala { 843af245d11STodd Fiala if (log) 84486fd8e45SChaoren Lin log->Printf ("NativeProcessLinux::%s() got exit signal(%d) , tid = %" PRIu64 " (%s main thread)", __FUNCTION__, signal, pid, is_main_thread ? "is" : "is not"); 845af245d11STodd Fiala 846af245d11STodd Fiala // This is a thread that exited. Ensure we're not tracking it anymore. 8471107b5a5SPavel Labath const bool thread_found = StopTrackingThread (pid); 848af245d11STodd Fiala 849af245d11STodd Fiala if (is_main_thread) 850af245d11STodd Fiala { 851af245d11STodd Fiala // We only set the exit status and notify the delegate if we haven't already set the process 852af245d11STodd Fiala // state to an exited state. We normally should have received a SIGTRAP | (PTRACE_EVENT_EXIT << 8) 853af245d11STodd Fiala // for the main thread. 8541107b5a5SPavel Labath const bool already_notified = (GetState() == StateType::eStateExited) || (GetState () == StateType::eStateCrashed); 855af245d11STodd Fiala if (!already_notified) 856af245d11STodd Fiala { 857af245d11STodd Fiala if (log) 8581107b5a5SPavel Labath log->Printf ("NativeProcessLinux::%s() tid = %" PRIu64 " 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 ())); 859af245d11STodd Fiala // The main thread exited. We're done monitoring. Report to delegate. 8601107b5a5SPavel Labath SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true); 861af245d11STodd Fiala 862af245d11STodd Fiala // Notify delegate that our process has exited. 8631107b5a5SPavel Labath SetState (StateType::eStateExited, true); 864af245d11STodd Fiala } 865af245d11STodd Fiala else 866af245d11STodd Fiala { 867af245d11STodd Fiala if (log) 868af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s() tid = %" PRIu64 " main thread now exited (%s)", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found"); 869af245d11STodd Fiala } 870af245d11STodd Fiala } 871af245d11STodd Fiala else 872af245d11STodd Fiala { 873af245d11STodd Fiala // Do we want to report to the delegate in this case? I think not. If this was an orderly 874af245d11STodd Fiala // thread exit, we would already have received the SIGTRAP | (PTRACE_EVENT_EXIT << 8) signal, 875af245d11STodd Fiala // and we would have done an all-stop then. 876af245d11STodd Fiala if (log) 877af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s() tid = %" PRIu64 " handling non-main thread exit (%s)", __FUNCTION__, pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found"); 878af245d11STodd Fiala } 8791107b5a5SPavel Labath return; 880af245d11STodd Fiala } 881af245d11STodd Fiala 882af245d11STodd Fiala siginfo_t info; 883b9cc0c75SPavel Labath const auto info_err = GetSignalInfo(pid, &info); 884b9cc0c75SPavel Labath auto thread_sp = GetThreadByID(pid); 885b9cc0c75SPavel Labath 886b9cc0c75SPavel Labath if (! thread_sp) 887b9cc0c75SPavel Labath { 888b9cc0c75SPavel Labath // Normally, the only situation when we cannot find the thread is if we have just 889b9cc0c75SPavel Labath // received a new thread notification. This is indicated by GetSignalInfo() returning 890b9cc0c75SPavel Labath // si_code == SI_USER and si_pid == 0 891b9cc0c75SPavel Labath if (log) 892b9cc0c75SPavel Labath log->Printf("NativeProcessLinux::%s received notification about an unknown tid %" PRIu64 ".", __FUNCTION__, pid); 893b9cc0c75SPavel Labath 894b9cc0c75SPavel Labath if (info_err.Fail()) 895b9cc0c75SPavel Labath { 896b9cc0c75SPavel Labath if (log) 897b9cc0c75SPavel Labath log->Printf("NativeProcessLinux::%s (tid %" PRIu64 ") GetSignalInfo failed (%s). Ingoring this notification.", __FUNCTION__, pid, info_err.AsCString()); 898b9cc0c75SPavel Labath return; 899b9cc0c75SPavel Labath } 900b9cc0c75SPavel Labath 901b9cc0c75SPavel Labath if (log && (info.si_code != SI_USER || info.si_pid != 0)) 902b9cc0c75SPavel Labath log->Printf("NativeProcessLinux::%s (tid %" PRIu64 ") unexpected signal info (si_code: %d, si_pid: %d). Treating as a new thread notification anyway.", __FUNCTION__, pid, info.si_code, info.si_pid); 903b9cc0c75SPavel Labath 904b9cc0c75SPavel Labath auto thread_sp = AddThread(pid); 905b9cc0c75SPavel Labath // Resume the newly created thread. 906b9cc0c75SPavel Labath ResumeThread(*thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); 907b9cc0c75SPavel Labath ThreadWasCreated(*thread_sp); 908b9cc0c75SPavel Labath return; 909b9cc0c75SPavel Labath } 910b9cc0c75SPavel Labath 911b9cc0c75SPavel Labath // Get details on the signal raised. 912b9cc0c75SPavel Labath if (info_err.Success()) 913fa03ad2eSChaoren Lin { 914fa03ad2eSChaoren Lin // We have retrieved the signal info. Dispatch appropriately. 915fa03ad2eSChaoren Lin if (info.si_signo == SIGTRAP) 916b9cc0c75SPavel Labath MonitorSIGTRAP(info, *thread_sp); 917fa03ad2eSChaoren Lin else 918b9cc0c75SPavel Labath MonitorSignal(info, *thread_sp, exited); 919fa03ad2eSChaoren Lin } 920fa03ad2eSChaoren Lin else 921af245d11STodd Fiala { 922b9cc0c75SPavel Labath if (info_err.GetError() == EINVAL) 923af245d11STodd Fiala { 924fa03ad2eSChaoren Lin // This is a group stop reception for this tid. 92539036ac3SPavel Labath // We can reach here if we reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU into the 92639036ac3SPavel Labath // tracee, triggering the group-stop mechanism. Normally receiving these would stop 92739036ac3SPavel Labath // the process, pending a SIGCONT. Simulating this state in a debugger is hard and is 92839036ac3SPavel Labath // generally not needed (one use case is debugging background task being managed by a 92939036ac3SPavel Labath // shell). For general use, it is sufficient to stop the process in a signal-delivery 93039036ac3SPavel Labath // stop which happens before the group stop. This done by MonitorSignal and works 93139036ac3SPavel Labath // correctly for all signals. 932fa03ad2eSChaoren Lin if (log) 93339036ac3SPavel Labath log->Printf("NativeProcessLinux::%s received a group stop for pid %" PRIu64 " tid %" PRIu64 ". Transparent handling of group stops not supported, resuming the thread.", __FUNCTION__, GetID (), pid); 934b9cc0c75SPavel Labath ResumeThread(*thread_sp, thread_sp->GetState(), LLDB_INVALID_SIGNAL_NUMBER); 935a9882ceeSTodd Fiala } 936a9882ceeSTodd Fiala else 937a9882ceeSTodd Fiala { 938af245d11STodd Fiala // ptrace(GETSIGINFO) failed (but not due to group-stop). 939af245d11STodd Fiala 940af245d11STodd Fiala // A return value of ESRCH means the thread/process is no longer on the system, 941af245d11STodd Fiala // so it was killed somehow outside of our control. Either way, we can't do anything 942af245d11STodd Fiala // with it anymore. 943af245d11STodd Fiala 944af245d11STodd Fiala // Stop tracking the metadata for the thread since it's entirely off the system now. 9451107b5a5SPavel Labath const bool thread_found = StopTrackingThread (pid); 946af245d11STodd Fiala 947af245d11STodd Fiala if (log) 948af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s GetSignalInfo failed: %s, tid = %" PRIu64 ", signal = %d, status = %d (%s, %s, %s)", 949b9cc0c75SPavel Labath __FUNCTION__, info_err.AsCString(), pid, signal, status, info_err.GetError() == ESRCH ? "thread/process killed" : "unknown reason", is_main_thread ? "is main thread" : "is not main thread", thread_found ? "thread metadata removed" : "thread metadata not found"); 950af245d11STodd Fiala 951af245d11STodd Fiala if (is_main_thread) 952af245d11STodd Fiala { 953af245d11STodd Fiala // Notify the delegate - our process is not available but appears to have been killed outside 954af245d11STodd Fiala // our control. Is eStateExited the right exit state in this case? 9551107b5a5SPavel Labath SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true); 9561107b5a5SPavel Labath SetState (StateType::eStateExited, true); 957af245d11STodd Fiala } 958af245d11STodd Fiala else 959af245d11STodd Fiala { 960af245d11STodd Fiala // This thread was pulled out from underneath us. Anything to do here? Do we want to do an all stop? 961af245d11STodd Fiala if (log) 9621107b5a5SPavel Labath log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 " non-main thread exit occurred, didn't tell delegate anything since thread disappeared out from underneath us", __FUNCTION__, GetID (), pid); 963af245d11STodd Fiala } 964af245d11STodd Fiala } 965af245d11STodd Fiala } 966af245d11STodd Fiala } 967af245d11STodd Fiala 968af245d11STodd Fiala void 969426bdf88SPavel Labath NativeProcessLinux::WaitForNewThread(::pid_t tid) 970426bdf88SPavel Labath { 971426bdf88SPavel Labath Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 972426bdf88SPavel Labath 973f9077782SPavel Labath NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid); 974426bdf88SPavel Labath 975426bdf88SPavel Labath if (new_thread_sp) 976426bdf88SPavel Labath { 977426bdf88SPavel Labath // We are already tracking the thread - we got the event on the new thread (see 978426bdf88SPavel Labath // MonitorSignal) before this one. We are done. 979426bdf88SPavel Labath return; 980426bdf88SPavel Labath } 981426bdf88SPavel Labath 982426bdf88SPavel Labath // The thread is not tracked yet, let's wait for it to appear. 983426bdf88SPavel Labath int status = -1; 984426bdf88SPavel Labath ::pid_t wait_pid; 985426bdf88SPavel Labath do 986426bdf88SPavel Labath { 987426bdf88SPavel Labath if (log) 988426bdf88SPavel Labath log->Printf ("NativeProcessLinux::%s() received thread creation event for tid %" PRIu32 ". tid not tracked yet, waiting for thread to appear...", __FUNCTION__, tid); 989426bdf88SPavel Labath wait_pid = waitpid(tid, &status, __WALL); 990426bdf88SPavel Labath } 991426bdf88SPavel Labath while (wait_pid == -1 && errno == EINTR); 992426bdf88SPavel Labath // Since we are waiting on a specific tid, this must be the creation event. But let's do 993426bdf88SPavel Labath // some checks just in case. 994426bdf88SPavel Labath if (wait_pid != tid) { 995426bdf88SPavel Labath if (log) 996426bdf88SPavel Labath log->Printf ("NativeProcessLinux::%s() waiting for tid %" PRIu32 " failed. Assuming the thread has disappeared in the meantime", __FUNCTION__, tid); 997426bdf88SPavel Labath // The only way I know of this could happen is if the whole process was 998426bdf88SPavel Labath // SIGKILLed in the mean time. In any case, we can't do anything about that now. 999426bdf88SPavel Labath return; 1000426bdf88SPavel Labath } 1001426bdf88SPavel Labath if (WIFEXITED(status)) 1002426bdf88SPavel Labath { 1003426bdf88SPavel Labath if (log) 1004426bdf88SPavel Labath log->Printf ("NativeProcessLinux::%s() waiting for tid %" PRIu32 " returned an 'exited' event. Not tracking the thread.", __FUNCTION__, tid); 1005426bdf88SPavel Labath // Also a very improbable event. 1006426bdf88SPavel Labath return; 1007426bdf88SPavel Labath } 1008426bdf88SPavel Labath 1009426bdf88SPavel Labath siginfo_t info; 1010426bdf88SPavel Labath Error error = GetSignalInfo(tid, &info); 1011426bdf88SPavel Labath if (error.Fail()) 1012426bdf88SPavel Labath { 1013426bdf88SPavel Labath if (log) 1014426bdf88SPavel Labath log->Printf ("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32 " failed. Assuming the thread has disappeared in the meantime.", __FUNCTION__, tid); 1015426bdf88SPavel Labath return; 1016426bdf88SPavel Labath } 1017426bdf88SPavel Labath 1018426bdf88SPavel Labath if (((info.si_pid != 0) || (info.si_code != SI_USER)) && log) 1019426bdf88SPavel Labath { 1020426bdf88SPavel Labath // We should be getting a thread creation signal here, but we received something 1021426bdf88SPavel Labath // else. There isn't much we can do about it now, so we will just log that. Since the 1022426bdf88SPavel Labath // thread is alive and we are receiving events from it, we shall pretend that it was 1023426bdf88SPavel Labath // created properly. 1024426bdf88SPavel Labath log->Printf ("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32 " received unexpected signal with code %d from pid %d.", __FUNCTION__, tid, info.si_code, info.si_pid); 1025426bdf88SPavel Labath } 1026426bdf88SPavel Labath 1027426bdf88SPavel Labath if (log) 1028426bdf88SPavel Labath log->Printf ("NativeProcessLinux::%s() pid = %" PRIu64 ": tracking new thread tid %" PRIu32, 1029426bdf88SPavel Labath __FUNCTION__, GetID (), tid); 1030426bdf88SPavel Labath 1031f9077782SPavel Labath new_thread_sp = AddThread(tid); 1032b9cc0c75SPavel Labath ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); 1033f9077782SPavel Labath ThreadWasCreated(*new_thread_sp); 1034426bdf88SPavel Labath } 1035426bdf88SPavel Labath 1036426bdf88SPavel Labath void 1037b9cc0c75SPavel Labath NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread) 1038af245d11STodd Fiala { 1039af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 1040b9cc0c75SPavel Labath const bool is_main_thread = (thread.GetID() == GetID ()); 1041af245d11STodd Fiala 1042b9cc0c75SPavel Labath assert(info.si_signo == SIGTRAP && "Unexpected child signal!"); 1043af245d11STodd Fiala 1044b9cc0c75SPavel Labath switch (info.si_code) 1045af245d11STodd Fiala { 1046af245d11STodd Fiala // TODO: these two cases are required if we want to support tracing of the inferiors' children. We'd need this to debug a monitor. 1047af245d11STodd Fiala // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)): 1048af245d11STodd Fiala // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)): 1049af245d11STodd Fiala 1050af245d11STodd Fiala case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): 1051af245d11STodd Fiala { 10525fd24c67SPavel Labath // This is the notification on the parent thread which informs us of new thread 1053426bdf88SPavel Labath // creation. 1054426bdf88SPavel Labath // We don't want to do anything with the parent thread so we just resume it. In case we 1055426bdf88SPavel Labath // want to implement "break on thread creation" functionality, we would need to stop 1056426bdf88SPavel Labath // here. 1057af245d11STodd Fiala 1058af245d11STodd Fiala unsigned long event_message = 0; 1059b9cc0c75SPavel Labath if (GetEventMessage(thread.GetID(), &event_message).Fail()) 1060fa03ad2eSChaoren Lin { 1061426bdf88SPavel Labath if (log) 1062b9cc0c75SPavel Labath log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " received thread creation event but GetEventMessage failed so we don't know the new tid", __FUNCTION__, thread.GetID()); 1063426bdf88SPavel Labath } else 1064426bdf88SPavel Labath WaitForNewThread(event_message); 1065af245d11STodd Fiala 1066b9cc0c75SPavel Labath ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); 1067af245d11STodd Fiala break; 1068af245d11STodd Fiala } 1069af245d11STodd Fiala 1070af245d11STodd Fiala case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): 1071a9882ceeSTodd Fiala { 1072f9077782SPavel Labath NativeThreadLinuxSP main_thread_sp; 1073af245d11STodd Fiala if (log) 1074b9cc0c75SPavel Labath log->Printf ("NativeProcessLinux::%s() received exec event, code = %d", __FUNCTION__, info.si_code ^ SIGTRAP); 1075a9882ceeSTodd Fiala 10761dbc6c9cSPavel Labath // Exec clears any pending notifications. 10770e1d729bSPavel Labath m_pending_notification_tid = LLDB_INVALID_THREAD_ID; 1078fa03ad2eSChaoren Lin 107957a77118SPavel Labath // Remove all but the main thread here. Linux fork creates a new process which only copies the main thread. 1080a9882ceeSTodd Fiala if (log) 1081a9882ceeSTodd Fiala log->Printf ("NativeProcessLinux::%s exec received, stop tracking all but main thread", __FUNCTION__); 1082a9882ceeSTodd Fiala 1083a9882ceeSTodd Fiala for (auto thread_sp : m_threads) 1084a9882ceeSTodd Fiala { 1085a9882ceeSTodd Fiala const bool is_main_thread = thread_sp && thread_sp->GetID () == GetID (); 1086a9882ceeSTodd Fiala if (is_main_thread) 1087a9882ceeSTodd Fiala { 1088f9077782SPavel Labath main_thread_sp = std::static_pointer_cast<NativeThreadLinux>(thread_sp); 1089a9882ceeSTodd Fiala if (log) 1090a9882ceeSTodd Fiala log->Printf ("NativeProcessLinux::%s found main thread with tid %" PRIu64 ", keeping", __FUNCTION__, main_thread_sp->GetID ()); 1091a9882ceeSTodd Fiala } 1092a9882ceeSTodd Fiala else 1093a9882ceeSTodd Fiala { 1094a9882ceeSTodd Fiala if (log) 1095a9882ceeSTodd Fiala log->Printf ("NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64 " due to exec", __FUNCTION__, thread_sp->GetID ()); 1096a9882ceeSTodd Fiala } 1097a9882ceeSTodd Fiala } 1098a9882ceeSTodd Fiala 1099a9882ceeSTodd Fiala m_threads.clear (); 1100a9882ceeSTodd Fiala 1101a9882ceeSTodd Fiala if (main_thread_sp) 1102a9882ceeSTodd Fiala { 1103a9882ceeSTodd Fiala m_threads.push_back (main_thread_sp); 1104a9882ceeSTodd Fiala SetCurrentThreadID (main_thread_sp->GetID ()); 1105f9077782SPavel Labath main_thread_sp->SetStoppedByExec(); 1106a9882ceeSTodd Fiala } 1107a9882ceeSTodd Fiala else 1108a9882ceeSTodd Fiala { 1109a9882ceeSTodd Fiala SetCurrentThreadID (LLDB_INVALID_THREAD_ID); 1110a9882ceeSTodd Fiala if (log) 1111a9882ceeSTodd Fiala log->Printf ("NativeProcessLinux::%s pid %" PRIu64 "no main thread found, discarded all threads, we're in a no-thread state!", __FUNCTION__, GetID ()); 1112a9882ceeSTodd Fiala } 1113a9882ceeSTodd Fiala 1114fa03ad2eSChaoren Lin // Tell coordinator about about the "new" (since exec) stopped main thread. 1115f9077782SPavel Labath ThreadWasCreated(*main_thread_sp); 1116fa03ad2eSChaoren Lin 1117a9882ceeSTodd Fiala // Let our delegate know we have just exec'd. 1118a9882ceeSTodd Fiala NotifyDidExec (); 1119a9882ceeSTodd Fiala 1120a9882ceeSTodd Fiala // If we have a main thread, indicate we are stopped. 1121a9882ceeSTodd Fiala assert (main_thread_sp && "exec called during ptraced process but no main thread metadata tracked"); 1122fa03ad2eSChaoren Lin 1123fa03ad2eSChaoren Lin // Let the process know we're stopped. 1124b9cc0c75SPavel Labath StopRunningThreads(main_thread_sp->GetID()); 1125a9882ceeSTodd Fiala 1126af245d11STodd Fiala break; 1127a9882ceeSTodd Fiala } 1128af245d11STodd Fiala 1129af245d11STodd Fiala case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): 1130af245d11STodd Fiala { 1131af245d11STodd Fiala // The inferior process or one of its threads is about to exit. 11326e35163cSPavel Labath // We don't want to do anything with the thread so we just resume it. In case we 11336e35163cSPavel Labath // want to implement "break on thread exit" functionality, we would need to stop 11346e35163cSPavel Labath // here. 1135fa03ad2eSChaoren Lin 1136af245d11STodd Fiala unsigned long data = 0; 1137b9cc0c75SPavel Labath if (GetEventMessage(thread.GetID(), &data).Fail()) 1138af245d11STodd Fiala data = -1; 1139af245d11STodd Fiala 1140af245d11STodd Fiala if (log) 1141af245d11STodd Fiala { 1142af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s() received PTRACE_EVENT_EXIT, data = %lx (WIFEXITED=%s,WIFSIGNALED=%s), pid = %" PRIu64 " (%s)", 1143af245d11STodd Fiala __FUNCTION__, 1144af245d11STodd Fiala data, WIFEXITED (data) ? "true" : "false", WIFSIGNALED (data) ? "true" : "false", 1145b9cc0c75SPavel Labath thread.GetID(), 1146af245d11STodd Fiala is_main_thread ? "is main thread" : "not main thread"); 1147af245d11STodd Fiala } 1148af245d11STodd Fiala 1149af245d11STodd Fiala if (is_main_thread) 1150af245d11STodd Fiala { 1151af245d11STodd Fiala SetExitStatus (convert_pid_status_to_exit_type (data), convert_pid_status_to_return_code (data), nullptr, true); 115275f47c3aSTodd Fiala } 115375f47c3aSTodd Fiala 115486852d36SPavel Labath StateType state = thread.GetState(); 115586852d36SPavel Labath if (! StateIsRunningState(state)) 115686852d36SPavel Labath { 115786852d36SPavel Labath // Due to a kernel bug, we may sometimes get this stop after the inferior gets a 115886852d36SPavel Labath // SIGKILL. This confuses our state tracking logic in ResumeThread(), since normally, 115986852d36SPavel Labath // we should not be receiving any ptrace events while the inferior is stopped. This 116086852d36SPavel Labath // makes sure that the inferior is resumed and exits normally. 116186852d36SPavel Labath state = eStateRunning; 116286852d36SPavel Labath } 116386852d36SPavel Labath ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER); 1164af245d11STodd Fiala 1165af245d11STodd Fiala break; 1166af245d11STodd Fiala } 1167af245d11STodd Fiala 1168af245d11STodd Fiala case 0: 1169c16f5dcaSChaoren Lin case TRAP_TRACE: // We receive this on single stepping. 1170c16f5dcaSChaoren Lin case TRAP_HWBKPT: // We receive this on watchpoint hit 117186fd8e45SChaoren Lin { 1172c16f5dcaSChaoren Lin // If a watchpoint was hit, report it 1173c16f5dcaSChaoren Lin uint32_t wp_index; 11741fa5c4b9STamas Berghammer Error error = thread.GetRegisterContext()->GetWatchpointHitIndex(wp_index, (uintptr_t)info.si_addr); 1175c16f5dcaSChaoren Lin if (error.Fail() && log) 1176c16f5dcaSChaoren Lin log->Printf("NativeProcessLinux::%s() " 1177c16f5dcaSChaoren Lin "received error while checking for watchpoint hits, " 1178c16f5dcaSChaoren Lin "pid = %" PRIu64 " error = %s", 1179b9cc0c75SPavel Labath __FUNCTION__, thread.GetID(), error.AsCString()); 1180c16f5dcaSChaoren Lin if (wp_index != LLDB_INVALID_INDEX32) 11815830aa75STamas Berghammer { 1182b9cc0c75SPavel Labath MonitorWatchpoint(thread, wp_index); 1183c16f5dcaSChaoren Lin break; 1184c16f5dcaSChaoren Lin } 1185b9cc0c75SPavel Labath 1186be379e15STamas Berghammer // Otherwise, report step over 1187be379e15STamas Berghammer MonitorTrace(thread); 1188af245d11STodd Fiala break; 1189b9cc0c75SPavel Labath } 1190af245d11STodd Fiala 1191af245d11STodd Fiala case SI_KERNEL: 119235799963SMohit K. Bhakkad #if defined __mips__ 119335799963SMohit K. Bhakkad // For mips there is no special signal for watchpoint 119435799963SMohit K. Bhakkad // So we check for watchpoint in kernel trap 119535799963SMohit K. Bhakkad { 119635799963SMohit K. Bhakkad // If a watchpoint was hit, report it 119735799963SMohit K. Bhakkad uint32_t wp_index; 1198b9cc0c75SPavel Labath Error error = thread.GetRegisterContext()->GetWatchpointHitIndex(wp_index, LLDB_INVALID_ADDRESS); 119935799963SMohit K. Bhakkad if (error.Fail() && log) 120035799963SMohit K. Bhakkad log->Printf("NativeProcessLinux::%s() " 120135799963SMohit K. Bhakkad "received error while checking for watchpoint hits, " 120235799963SMohit K. Bhakkad "pid = %" PRIu64 " error = %s", 120316ad0321SMohit K. Bhakkad __FUNCTION__, thread.GetID(), error.AsCString()); 120435799963SMohit K. Bhakkad if (wp_index != LLDB_INVALID_INDEX32) 120535799963SMohit K. Bhakkad { 1206b9cc0c75SPavel Labath MonitorWatchpoint(thread, wp_index); 120735799963SMohit K. Bhakkad break; 120835799963SMohit K. Bhakkad } 120935799963SMohit K. Bhakkad } 121035799963SMohit K. Bhakkad // NO BREAK 121135799963SMohit K. Bhakkad #endif 1212af245d11STodd Fiala case TRAP_BRKPT: 1213b9cc0c75SPavel Labath MonitorBreakpoint(thread); 1214af245d11STodd Fiala break; 1215af245d11STodd Fiala 1216af245d11STodd Fiala case SIGTRAP: 1217af245d11STodd Fiala case (SIGTRAP | 0x80): 1218af245d11STodd Fiala if (log) 1219b9cc0c75SPavel Labath log->Printf ("NativeProcessLinux::%s() received unknown SIGTRAP system call stop event, pid %" PRIu64 "tid %" PRIu64 ", resuming", __FUNCTION__, GetID (), thread.GetID()); 1220fa03ad2eSChaoren Lin 1221af245d11STodd Fiala // Ignore these signals until we know more about them. 1222b9cc0c75SPavel Labath ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); 1223af245d11STodd Fiala break; 1224af245d11STodd Fiala 1225af245d11STodd Fiala default: 1226af245d11STodd Fiala assert(false && "Unexpected SIGTRAP code!"); 1227af245d11STodd Fiala if (log) 12286e35163cSPavel Labath log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 "tid %" PRIu64 " received unhandled SIGTRAP code: 0x%d", 1229b9cc0c75SPavel Labath __FUNCTION__, GetID(), thread.GetID(), info.si_code); 1230af245d11STodd Fiala break; 1231af245d11STodd Fiala 1232af245d11STodd Fiala } 1233af245d11STodd Fiala } 1234af245d11STodd Fiala 1235af245d11STodd Fiala void 1236b9cc0c75SPavel Labath NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) 1237c16f5dcaSChaoren Lin { 1238c16f5dcaSChaoren Lin Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 1239c16f5dcaSChaoren Lin if (log) 1240c16f5dcaSChaoren Lin log->Printf("NativeProcessLinux::%s() received trace event, pid = %" PRIu64 " (single stepping)", 1241b9cc0c75SPavel Labath __FUNCTION__, thread.GetID()); 1242c16f5dcaSChaoren Lin 12430e1d729bSPavel Labath // This thread is currently stopped. 1244b9cc0c75SPavel Labath thread.SetStoppedByTrace(); 1245c16f5dcaSChaoren Lin 1246b9cc0c75SPavel Labath StopRunningThreads(thread.GetID()); 1247c16f5dcaSChaoren Lin } 1248c16f5dcaSChaoren Lin 1249c16f5dcaSChaoren Lin void 1250b9cc0c75SPavel Labath NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) 1251c16f5dcaSChaoren Lin { 1252c16f5dcaSChaoren Lin Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); 1253c16f5dcaSChaoren Lin if (log) 1254c16f5dcaSChaoren Lin log->Printf("NativeProcessLinux::%s() received breakpoint event, pid = %" PRIu64, 1255b9cc0c75SPavel Labath __FUNCTION__, thread.GetID()); 1256c16f5dcaSChaoren Lin 1257c16f5dcaSChaoren Lin // Mark the thread as stopped at breakpoint. 1258b9cc0c75SPavel Labath thread.SetStoppedByBreakpoint(); 1259b9cc0c75SPavel Labath Error error = FixupBreakpointPCAsNeeded(thread); 1260c16f5dcaSChaoren Lin if (error.Fail()) 1261c16f5dcaSChaoren Lin if (log) 1262c16f5dcaSChaoren Lin log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " fixup: %s", 1263b9cc0c75SPavel Labath __FUNCTION__, thread.GetID(), error.AsCString()); 1264d8c338d4STamas Berghammer 1265b9cc0c75SPavel Labath if (m_threads_stepping_with_breakpoint.find(thread.GetID()) != m_threads_stepping_with_breakpoint.end()) 1266b9cc0c75SPavel Labath thread.SetStoppedByTrace(); 1267c16f5dcaSChaoren Lin 1268b9cc0c75SPavel Labath StopRunningThreads(thread.GetID()); 1269c16f5dcaSChaoren Lin } 1270c16f5dcaSChaoren Lin 1271c16f5dcaSChaoren Lin void 1272f9077782SPavel Labath NativeProcessLinux::MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index) 1273c16f5dcaSChaoren Lin { 1274c16f5dcaSChaoren Lin Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_WATCHPOINTS)); 1275c16f5dcaSChaoren Lin if (log) 1276c16f5dcaSChaoren Lin log->Printf("NativeProcessLinux::%s() received watchpoint event, " 1277c16f5dcaSChaoren Lin "pid = %" PRIu64 ", wp_index = %" PRIu32, 1278f9077782SPavel Labath __FUNCTION__, thread.GetID(), wp_index); 1279c16f5dcaSChaoren Lin 1280c16f5dcaSChaoren Lin // Mark the thread as stopped at watchpoint. 1281c16f5dcaSChaoren Lin // The address is at (lldb::addr_t)info->si_addr if we need it. 1282f9077782SPavel Labath thread.SetStoppedByWatchpoint(wp_index); 1283c16f5dcaSChaoren Lin 1284c16f5dcaSChaoren Lin // We need to tell all other running threads before we notify the delegate about this stop. 1285f9077782SPavel Labath StopRunningThreads(thread.GetID()); 1286c16f5dcaSChaoren Lin } 1287c16f5dcaSChaoren Lin 1288c16f5dcaSChaoren Lin void 1289b9cc0c75SPavel Labath NativeProcessLinux::MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, bool exited) 1290af245d11STodd Fiala { 1291b9cc0c75SPavel Labath const int signo = info.si_signo; 1292b9cc0c75SPavel Labath const bool is_from_llgs = info.si_pid == getpid (); 1293af245d11STodd Fiala 1294af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 1295af245d11STodd Fiala 1296af245d11STodd Fiala // POSIX says that process behaviour is undefined after it ignores a SIGFPE, 1297af245d11STodd Fiala // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a 1298af245d11STodd Fiala // kill(2) or raise(3). Similarly for tgkill(2) on Linux. 1299af245d11STodd Fiala // 1300af245d11STodd Fiala // IOW, user generated signals never generate what we consider to be a 1301af245d11STodd Fiala // "crash". 1302af245d11STodd Fiala // 1303af245d11STodd Fiala // Similarly, ACK signals generated by this monitor. 1304af245d11STodd Fiala 1305af245d11STodd Fiala // Handle the signal. 1306b9cc0c75SPavel Labath if (info.si_code == SI_TKILL || info.si_code == SI_USER) 1307af245d11STodd Fiala { 1308af245d11STodd Fiala if (log) 1309af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s() received signal %s (%d) with code %s, (siginfo pid = %d (%s), waitpid pid = %" PRIu64 ")", 1310af245d11STodd Fiala __FUNCTION__, 131198d0a4b3SChaoren Lin Host::GetSignalAsCString(signo), 1312af245d11STodd Fiala signo, 1313b9cc0c75SPavel Labath (info.si_code == SI_TKILL ? "SI_TKILL" : "SI_USER"), 1314b9cc0c75SPavel Labath info.si_pid, 1315511e5cdcSTodd Fiala is_from_llgs ? "from llgs" : "not from llgs", 1316b9cc0c75SPavel Labath thread.GetID()); 1317af245d11STodd Fiala } 131858a2f669STodd Fiala 131958a2f669STodd Fiala // Check for thread stop notification. 1320b9cc0c75SPavel Labath if (is_from_llgs && (info.si_code == SI_TKILL) && (signo == SIGSTOP)) 1321af245d11STodd Fiala { 1322af245d11STodd Fiala // This is a tgkill()-based stop. 1323fa03ad2eSChaoren Lin if (log) 1324fa03ad2eSChaoren Lin log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 ", thread stopped", 1325fa03ad2eSChaoren Lin __FUNCTION__, 1326fa03ad2eSChaoren Lin GetID (), 1327b9cc0c75SPavel Labath thread.GetID()); 1328fa03ad2eSChaoren Lin 1329aab58633SChaoren Lin // Check that we're not already marked with a stop reason. 1330aab58633SChaoren Lin // Note this thread really shouldn't already be marked as stopped - if we were, that would imply that 1331aab58633SChaoren Lin // the kernel signaled us with the thread stopping which we handled and marked as stopped, 1332aab58633SChaoren Lin // and that, without an intervening resume, we received another stop. It is more likely 1333aab58633SChaoren Lin // that we are missing the marking of a run state somewhere if we find that the thread was 1334aab58633SChaoren Lin // marked as stopped. 1335b9cc0c75SPavel Labath const StateType thread_state = thread.GetState(); 1336aab58633SChaoren Lin if (!StateIsStoppedState (thread_state, false)) 1337aab58633SChaoren Lin { 1338ed89c7feSPavel Labath // An inferior thread has stopped because of a SIGSTOP we have sent it. 1339ed89c7feSPavel Labath // Generally, these are not important stops and we don't want to report them as 1340ed89c7feSPavel Labath // they are just used to stop other threads when one thread (the one with the 1341ed89c7feSPavel Labath // *real* stop reason) hits a breakpoint (watchpoint, etc...). However, in the 1342ed89c7feSPavel Labath // case of an asynchronous Interrupt(), this *is* the real stop reason, so we 1343ed89c7feSPavel Labath // leave the signal intact if this is the thread that was chosen as the 1344ed89c7feSPavel Labath // triggering thread. 13450e1d729bSPavel Labath if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) 13460e1d729bSPavel Labath { 1347b9cc0c75SPavel Labath if (m_pending_notification_tid == thread.GetID()) 1348b9cc0c75SPavel Labath thread.SetStoppedBySignal(SIGSTOP, &info); 1349ed89c7feSPavel Labath else 1350b9cc0c75SPavel Labath thread.SetStoppedWithNoReason(); 1351ed89c7feSPavel Labath 1352b9cc0c75SPavel Labath SetCurrentThreadID (thread.GetID ()); 13530e1d729bSPavel Labath SignalIfAllThreadsStopped(); 13540e1d729bSPavel Labath } 13550e1d729bSPavel Labath else 13560e1d729bSPavel Labath { 13570e1d729bSPavel Labath // We can end up here if stop was initiated by LLGS but by this time a 13580e1d729bSPavel Labath // thread stop has occurred - maybe initiated by another event. 1359b9cc0c75SPavel Labath Error error = ResumeThread(thread, thread.GetState(), 0); 13600e1d729bSPavel Labath if (error.Fail() && log) 13610e1d729bSPavel Labath { 13620e1d729bSPavel Labath log->Printf("NativeProcessLinux::%s failed to resume thread tid %" PRIu64 ": %s", 1363b9cc0c75SPavel Labath __FUNCTION__, thread.GetID(), error.AsCString()); 13640e1d729bSPavel Labath } 13650e1d729bSPavel Labath } 1366aab58633SChaoren Lin } 1367aab58633SChaoren Lin else 1368aab58633SChaoren Lin { 1369aab58633SChaoren Lin if (log) 1370aab58633SChaoren Lin { 1371aab58633SChaoren Lin // Retrieve the signal name if the thread was stopped by a signal. 1372aab58633SChaoren Lin int stop_signo = 0; 1373b9cc0c75SPavel Labath const bool stopped_by_signal = thread.IsStopped(&stop_signo); 137498d0a4b3SChaoren Lin const char *signal_name = stopped_by_signal ? Host::GetSignalAsCString(stop_signo) : "<not stopped by signal>"; 1375aab58633SChaoren Lin if (!signal_name) 1376aab58633SChaoren Lin signal_name = "<no-signal-name>"; 1377aab58633SChaoren Lin 1378aab58633SChaoren Lin log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 ", thread was already marked as a stopped state (state=%s, signal=%d (%s)), leaving stop signal as is", 1379aab58633SChaoren Lin __FUNCTION__, 1380aab58633SChaoren Lin GetID (), 1381b9cc0c75SPavel Labath thread.GetID(), 1382aab58633SChaoren Lin StateAsCString (thread_state), 1383aab58633SChaoren Lin stop_signo, 1384aab58633SChaoren Lin signal_name); 1385aab58633SChaoren Lin } 13860e1d729bSPavel Labath SignalIfAllThreadsStopped(); 1387af245d11STodd Fiala } 1388af245d11STodd Fiala 138958a2f669STodd Fiala // Done handling. 1390af245d11STodd Fiala return; 1391af245d11STodd Fiala } 1392af245d11STodd Fiala 1393af245d11STodd Fiala if (log) 139498d0a4b3SChaoren Lin log->Printf ("NativeProcessLinux::%s() received signal %s", __FUNCTION__, Host::GetSignalAsCString(signo)); 1395af245d11STodd Fiala 139686fd8e45SChaoren Lin // This thread is stopped. 1397b9cc0c75SPavel Labath thread.SetStoppedBySignal(signo, &info); 139886fd8e45SChaoren Lin 139986fd8e45SChaoren Lin // Send a stop to the debugger after we get all other threads to stop. 1400b9cc0c75SPavel Labath StopRunningThreads(thread.GetID()); 1401511e5cdcSTodd Fiala } 1402af245d11STodd Fiala 1403e7708688STamas Berghammer namespace { 1404e7708688STamas Berghammer 1405e7708688STamas Berghammer struct EmulatorBaton 1406e7708688STamas Berghammer { 1407e7708688STamas Berghammer NativeProcessLinux* m_process; 1408e7708688STamas Berghammer NativeRegisterContext* m_reg_context; 14096648fcc3SPavel Labath 14106648fcc3SPavel Labath // eRegisterKindDWARF -> RegsiterValue 14116648fcc3SPavel Labath std::unordered_map<uint32_t, RegisterValue> m_register_values; 1412e7708688STamas Berghammer 1413e7708688STamas Berghammer EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) : 1414e7708688STamas Berghammer m_process(process), m_reg_context(reg_context) {} 1415e7708688STamas Berghammer }; 1416e7708688STamas Berghammer 1417e7708688STamas Berghammer } // anonymous namespace 1418e7708688STamas Berghammer 1419e7708688STamas Berghammer static size_t 1420e7708688STamas Berghammer ReadMemoryCallback (EmulateInstruction *instruction, 1421e7708688STamas Berghammer void *baton, 1422e7708688STamas Berghammer const EmulateInstruction::Context &context, 1423e7708688STamas Berghammer lldb::addr_t addr, 1424e7708688STamas Berghammer void *dst, 1425e7708688STamas Berghammer size_t length) 1426e7708688STamas Berghammer { 1427e7708688STamas Berghammer EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); 1428e7708688STamas Berghammer 14293eb4b458SChaoren Lin size_t bytes_read; 1430e7708688STamas Berghammer emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); 1431e7708688STamas Berghammer return bytes_read; 1432e7708688STamas Berghammer } 1433e7708688STamas Berghammer 1434e7708688STamas Berghammer static bool 1435e7708688STamas Berghammer ReadRegisterCallback (EmulateInstruction *instruction, 1436e7708688STamas Berghammer void *baton, 1437e7708688STamas Berghammer const RegisterInfo *reg_info, 1438e7708688STamas Berghammer RegisterValue ®_value) 1439e7708688STamas Berghammer { 1440e7708688STamas Berghammer EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); 1441e7708688STamas Berghammer 14426648fcc3SPavel Labath auto it = emulator_baton->m_register_values.find(reg_info->kinds[eRegisterKindDWARF]); 14436648fcc3SPavel Labath if (it != emulator_baton->m_register_values.end()) 14446648fcc3SPavel Labath { 14456648fcc3SPavel Labath reg_value = it->second; 14466648fcc3SPavel Labath return true; 14476648fcc3SPavel Labath } 14486648fcc3SPavel Labath 1449e7708688STamas Berghammer // The emulator only fill in the dwarf regsiter numbers (and in some case 1450e7708688STamas Berghammer // the generic register numbers). Get the full register info from the 1451e7708688STamas Berghammer // register context based on the dwarf register numbers. 1452e7708688STamas Berghammer const RegisterInfo* full_reg_info = emulator_baton->m_reg_context->GetRegisterInfo( 1453e7708688STamas Berghammer eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); 1454e7708688STamas Berghammer 1455e7708688STamas Berghammer Error error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); 14566648fcc3SPavel Labath if (error.Success()) 14576648fcc3SPavel Labath return true; 1458cdc22a88SMohit K. Bhakkad 14596648fcc3SPavel Labath return false; 1460e7708688STamas Berghammer } 1461e7708688STamas Berghammer 1462e7708688STamas Berghammer static bool 1463e7708688STamas Berghammer WriteRegisterCallback (EmulateInstruction *instruction, 1464e7708688STamas Berghammer void *baton, 1465e7708688STamas Berghammer const EmulateInstruction::Context &context, 1466e7708688STamas Berghammer const RegisterInfo *reg_info, 1467e7708688STamas Berghammer const RegisterValue ®_value) 1468e7708688STamas Berghammer { 1469e7708688STamas Berghammer EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton); 14706648fcc3SPavel Labath emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = reg_value; 1471e7708688STamas Berghammer return true; 1472e7708688STamas Berghammer } 1473e7708688STamas Berghammer 1474e7708688STamas Berghammer static size_t 1475e7708688STamas Berghammer WriteMemoryCallback (EmulateInstruction *instruction, 1476e7708688STamas Berghammer void *baton, 1477e7708688STamas Berghammer const EmulateInstruction::Context &context, 1478e7708688STamas Berghammer lldb::addr_t addr, 1479e7708688STamas Berghammer const void *dst, 1480e7708688STamas Berghammer size_t length) 1481e7708688STamas Berghammer { 1482e7708688STamas Berghammer return length; 1483e7708688STamas Berghammer } 1484e7708688STamas Berghammer 1485e7708688STamas Berghammer static lldb::addr_t 1486e7708688STamas Berghammer ReadFlags (NativeRegisterContext* regsiter_context) 1487e7708688STamas Berghammer { 1488e7708688STamas Berghammer const RegisterInfo* flags_info = regsiter_context->GetRegisterInfo( 1489e7708688STamas Berghammer eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 1490e7708688STamas Berghammer return regsiter_context->ReadRegisterAsUnsigned(flags_info, LLDB_INVALID_ADDRESS); 1491e7708688STamas Berghammer } 1492e7708688STamas Berghammer 1493e7708688STamas Berghammer Error 1494b9cc0c75SPavel Labath NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) 1495e7708688STamas Berghammer { 1496e7708688STamas Berghammer Error error; 1497b9cc0c75SPavel Labath NativeRegisterContextSP register_context_sp = thread.GetRegisterContext(); 1498e7708688STamas Berghammer 1499e7708688STamas Berghammer std::unique_ptr<EmulateInstruction> emulator_ap( 1500e7708688STamas Berghammer EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, nullptr)); 1501e7708688STamas Berghammer 1502e7708688STamas Berghammer if (emulator_ap == nullptr) 1503e7708688STamas Berghammer return Error("Instruction emulator not found!"); 1504e7708688STamas Berghammer 1505e7708688STamas Berghammer EmulatorBaton baton(this, register_context_sp.get()); 1506e7708688STamas Berghammer emulator_ap->SetBaton(&baton); 1507e7708688STamas Berghammer emulator_ap->SetReadMemCallback(&ReadMemoryCallback); 1508e7708688STamas Berghammer emulator_ap->SetReadRegCallback(&ReadRegisterCallback); 1509e7708688STamas Berghammer emulator_ap->SetWriteMemCallback(&WriteMemoryCallback); 1510e7708688STamas Berghammer emulator_ap->SetWriteRegCallback(&WriteRegisterCallback); 1511e7708688STamas Berghammer 1512e7708688STamas Berghammer if (!emulator_ap->ReadInstruction()) 1513e7708688STamas Berghammer return Error("Read instruction failed!"); 1514e7708688STamas Berghammer 15156648fcc3SPavel Labath bool emulation_result = emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); 15166648fcc3SPavel Labath 15176648fcc3SPavel Labath const RegisterInfo* reg_info_pc = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 15186648fcc3SPavel Labath const RegisterInfo* reg_info_flags = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 15196648fcc3SPavel Labath 15206648fcc3SPavel Labath auto pc_it = baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]); 15216648fcc3SPavel Labath auto flags_it = baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]); 15226648fcc3SPavel Labath 1523e7708688STamas Berghammer lldb::addr_t next_pc; 1524e7708688STamas Berghammer lldb::addr_t next_flags; 15256648fcc3SPavel Labath if (emulation_result) 1526e7708688STamas Berghammer { 15276648fcc3SPavel Labath assert(pc_it != baton.m_register_values.end() && "Emulation was successfull but PC wasn't updated"); 15286648fcc3SPavel Labath next_pc = pc_it->second.GetAsUInt64(); 15296648fcc3SPavel Labath 15306648fcc3SPavel Labath if (flags_it != baton.m_register_values.end()) 15316648fcc3SPavel Labath next_flags = flags_it->second.GetAsUInt64(); 1532e7708688STamas Berghammer else 1533e7708688STamas Berghammer next_flags = ReadFlags (register_context_sp.get()); 1534e7708688STamas Berghammer } 15356648fcc3SPavel Labath else if (pc_it == baton.m_register_values.end()) 1536e7708688STamas Berghammer { 1537e7708688STamas Berghammer // Emulate instruction failed and it haven't changed PC. Advance PC 1538e7708688STamas Berghammer // with the size of the current opcode because the emulation of all 1539e7708688STamas Berghammer // PC modifying instruction should be successful. The failure most 1540e7708688STamas Berghammer // likely caused by a not supported instruction which don't modify PC. 1541e7708688STamas Berghammer next_pc = register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize(); 1542e7708688STamas Berghammer next_flags = ReadFlags (register_context_sp.get()); 1543e7708688STamas Berghammer } 1544e7708688STamas Berghammer else 1545e7708688STamas Berghammer { 1546e7708688STamas Berghammer // The instruction emulation failed after it modified the PC. It is an 1547e7708688STamas Berghammer // unknown error where we can't continue because the next instruction is 1548e7708688STamas Berghammer // modifying the PC but we don't know how. 1549e7708688STamas Berghammer return Error ("Instruction emulation failed unexpectedly."); 1550e7708688STamas Berghammer } 1551e7708688STamas Berghammer 1552e7708688STamas Berghammer if (m_arch.GetMachine() == llvm::Triple::arm) 1553e7708688STamas Berghammer { 1554e7708688STamas Berghammer if (next_flags & 0x20) 1555e7708688STamas Berghammer { 1556e7708688STamas Berghammer // Thumb mode 1557e7708688STamas Berghammer error = SetSoftwareBreakpoint(next_pc, 2); 1558e7708688STamas Berghammer } 1559e7708688STamas Berghammer else 1560e7708688STamas Berghammer { 1561e7708688STamas Berghammer // Arm mode 1562e7708688STamas Berghammer error = SetSoftwareBreakpoint(next_pc, 4); 1563e7708688STamas Berghammer } 1564e7708688STamas Berghammer } 1565cdc22a88SMohit K. Bhakkad else if (m_arch.GetMachine() == llvm::Triple::mips64 1566c60c9452SJaydeep Patil || m_arch.GetMachine() == llvm::Triple::mips64el 1567c60c9452SJaydeep Patil || m_arch.GetMachine() == llvm::Triple::mips 1568c60c9452SJaydeep Patil || m_arch.GetMachine() == llvm::Triple::mipsel) 1569cdc22a88SMohit K. Bhakkad error = SetSoftwareBreakpoint(next_pc, 4); 1570e7708688STamas Berghammer else 1571e7708688STamas Berghammer { 1572e7708688STamas Berghammer // No size hint is given for the next breakpoint 1573e7708688STamas Berghammer error = SetSoftwareBreakpoint(next_pc, 0); 1574e7708688STamas Berghammer } 1575e7708688STamas Berghammer 1576e7708688STamas Berghammer if (error.Fail()) 1577e7708688STamas Berghammer return error; 1578e7708688STamas Berghammer 1579b9cc0c75SPavel Labath m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc}); 1580e7708688STamas Berghammer 1581e7708688STamas Berghammer return Error(); 1582e7708688STamas Berghammer } 1583e7708688STamas Berghammer 1584e7708688STamas Berghammer bool 1585e7708688STamas Berghammer NativeProcessLinux::SupportHardwareSingleStepping() const 1586e7708688STamas Berghammer { 1587cdc22a88SMohit K. Bhakkad if (m_arch.GetMachine() == llvm::Triple::arm 1588c60c9452SJaydeep Patil || m_arch.GetMachine() == llvm::Triple::mips64 || m_arch.GetMachine() == llvm::Triple::mips64el 1589c60c9452SJaydeep Patil || m_arch.GetMachine() == llvm::Triple::mips || m_arch.GetMachine() == llvm::Triple::mipsel) 1590cdc22a88SMohit K. Bhakkad return false; 1591cdc22a88SMohit K. Bhakkad return true; 1592e7708688STamas Berghammer } 1593e7708688STamas Berghammer 1594af245d11STodd Fiala Error 1595af245d11STodd Fiala NativeProcessLinux::Resume (const ResumeActionList &resume_actions) 1596af245d11STodd Fiala { 1597af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); 1598af245d11STodd Fiala if (log) 1599af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s called: pid %" PRIu64, __FUNCTION__, GetID ()); 1600af245d11STodd Fiala 1601e7708688STamas Berghammer bool software_single_step = !SupportHardwareSingleStepping(); 1602af245d11STodd Fiala 1603e7708688STamas Berghammer if (software_single_step) 1604e7708688STamas Berghammer { 1605e7708688STamas Berghammer for (auto thread_sp : m_threads) 1606e7708688STamas Berghammer { 1607e7708688STamas Berghammer assert (thread_sp && "thread list should not contain NULL threads"); 1608e7708688STamas Berghammer 1609e7708688STamas Berghammer const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true); 1610e7708688STamas Berghammer if (action == nullptr) 1611e7708688STamas Berghammer continue; 1612e7708688STamas Berghammer 1613e7708688STamas Berghammer if (action->state == eStateStepping) 1614e7708688STamas Berghammer { 1615b9cc0c75SPavel Labath Error error = SetupSoftwareSingleStepping(static_cast<NativeThreadLinux &>(*thread_sp)); 1616e7708688STamas Berghammer if (error.Fail()) 1617e7708688STamas Berghammer return error; 1618e7708688STamas Berghammer } 1619e7708688STamas Berghammer } 1620e7708688STamas Berghammer } 1621e7708688STamas Berghammer 1622af245d11STodd Fiala for (auto thread_sp : m_threads) 1623af245d11STodd Fiala { 1624af245d11STodd Fiala assert (thread_sp && "thread list should not contain NULL threads"); 1625af245d11STodd Fiala 1626af245d11STodd Fiala const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true); 16276a196ce6SChaoren Lin 16286a196ce6SChaoren Lin if (action == nullptr) 16296a196ce6SChaoren Lin { 16306a196ce6SChaoren Lin if (log) 16316a196ce6SChaoren Lin log->Printf ("NativeProcessLinux::%s no action specified for pid %" PRIu64 " tid %" PRIu64, 16326a196ce6SChaoren Lin __FUNCTION__, GetID (), thread_sp->GetID ()); 16336a196ce6SChaoren Lin continue; 16346a196ce6SChaoren Lin } 1635af245d11STodd Fiala 1636af245d11STodd Fiala if (log) 1637af245d11STodd Fiala { 1638af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s processing resume action state %s for pid %" PRIu64 " tid %" PRIu64, 1639af245d11STodd Fiala __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ()); 1640af245d11STodd Fiala } 1641af245d11STodd Fiala 1642af245d11STodd Fiala switch (action->state) 1643af245d11STodd Fiala { 1644af245d11STodd Fiala case eStateRunning: 16450e1d729bSPavel Labath case eStateStepping: 1646fa03ad2eSChaoren Lin { 1647af245d11STodd Fiala // Run the thread, possibly feeding it the signal. 1648fa03ad2eSChaoren Lin const int signo = action->signal; 1649b9cc0c75SPavel Labath ResumeThread(static_cast<NativeThreadLinux &>(*thread_sp), action->state, signo); 1650af245d11STodd Fiala break; 1651ae29d395SChaoren Lin } 1652af245d11STodd Fiala 1653af245d11STodd Fiala case eStateSuspended: 1654af245d11STodd Fiala case eStateStopped: 1655108c325dSPavel Labath lldbassert(0 && "Unexpected state"); 1656af245d11STodd Fiala 1657af245d11STodd Fiala default: 1658af245d11STodd Fiala return Error ("NativeProcessLinux::%s (): unexpected state %s specified for pid %" PRIu64 ", tid %" PRIu64, 1659af245d11STodd Fiala __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ()); 1660af245d11STodd Fiala } 1661af245d11STodd Fiala } 1662af245d11STodd Fiala 16635830aa75STamas Berghammer return Error(); 1664af245d11STodd Fiala } 1665af245d11STodd Fiala 1666af245d11STodd Fiala Error 1667af245d11STodd Fiala NativeProcessLinux::Halt () 1668af245d11STodd Fiala { 1669af245d11STodd Fiala Error error; 1670af245d11STodd Fiala 1671af245d11STodd Fiala if (kill (GetID (), SIGSTOP) != 0) 1672af245d11STodd Fiala error.SetErrorToErrno (); 1673af245d11STodd Fiala 1674af245d11STodd Fiala return error; 1675af245d11STodd Fiala } 1676af245d11STodd Fiala 1677af245d11STodd Fiala Error 1678af245d11STodd Fiala NativeProcessLinux::Detach () 1679af245d11STodd Fiala { 1680af245d11STodd Fiala Error error; 1681af245d11STodd Fiala 1682af245d11STodd Fiala // Stop monitoring the inferior. 168319cbe96aSPavel Labath m_sigchld_handle.reset(); 1684af245d11STodd Fiala 16857a9495bcSPavel Labath // Tell ptrace to detach from the process. 16867a9495bcSPavel Labath if (GetID () == LLDB_INVALID_PROCESS_ID) 16877a9495bcSPavel Labath return error; 16887a9495bcSPavel Labath 16897a9495bcSPavel Labath for (auto thread_sp : m_threads) 16907a9495bcSPavel Labath { 16917a9495bcSPavel Labath Error e = Detach(thread_sp->GetID()); 16927a9495bcSPavel Labath if (e.Fail()) 16937a9495bcSPavel Labath error = e; // Save the error, but still attempt to detach from other threads. 16947a9495bcSPavel Labath } 16957a9495bcSPavel Labath 1696af245d11STodd Fiala return error; 1697af245d11STodd Fiala } 1698af245d11STodd Fiala 1699af245d11STodd Fiala Error 1700af245d11STodd Fiala NativeProcessLinux::Signal (int signo) 1701af245d11STodd Fiala { 1702af245d11STodd Fiala Error error; 1703af245d11STodd Fiala 1704af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 1705af245d11STodd Fiala if (log) 1706af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s: sending signal %d (%s) to pid %" PRIu64, 170798d0a4b3SChaoren Lin __FUNCTION__, signo, Host::GetSignalAsCString(signo), GetID()); 1708af245d11STodd Fiala 1709af245d11STodd Fiala if (kill(GetID(), signo)) 1710af245d11STodd Fiala error.SetErrorToErrno(); 1711af245d11STodd Fiala 1712af245d11STodd Fiala return error; 1713af245d11STodd Fiala } 1714af245d11STodd Fiala 1715af245d11STodd Fiala Error 1716e9547b80SChaoren Lin NativeProcessLinux::Interrupt () 1717e9547b80SChaoren Lin { 1718e9547b80SChaoren Lin // Pick a running thread (or if none, a not-dead stopped thread) as 1719e9547b80SChaoren Lin // the chosen thread that will be the stop-reason thread. 1720e9547b80SChaoren Lin Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 1721e9547b80SChaoren Lin 1722e9547b80SChaoren Lin NativeThreadProtocolSP running_thread_sp; 1723e9547b80SChaoren Lin NativeThreadProtocolSP stopped_thread_sp; 1724e9547b80SChaoren Lin 1725e9547b80SChaoren Lin if (log) 1726e9547b80SChaoren Lin log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__); 1727e9547b80SChaoren Lin 1728e9547b80SChaoren Lin for (auto thread_sp : m_threads) 1729e9547b80SChaoren Lin { 1730e9547b80SChaoren Lin // The thread shouldn't be null but lets just cover that here. 1731e9547b80SChaoren Lin if (!thread_sp) 1732e9547b80SChaoren Lin continue; 1733e9547b80SChaoren Lin 1734e9547b80SChaoren Lin // If we have a running or stepping thread, we'll call that the 1735e9547b80SChaoren Lin // target of the interrupt. 1736e9547b80SChaoren Lin const auto thread_state = thread_sp->GetState (); 1737e9547b80SChaoren Lin if (thread_state == eStateRunning || 1738e9547b80SChaoren Lin thread_state == eStateStepping) 1739e9547b80SChaoren Lin { 1740e9547b80SChaoren Lin running_thread_sp = thread_sp; 1741e9547b80SChaoren Lin break; 1742e9547b80SChaoren Lin } 1743e9547b80SChaoren Lin else if (!stopped_thread_sp && StateIsStoppedState (thread_state, true)) 1744e9547b80SChaoren Lin { 1745e9547b80SChaoren Lin // Remember the first non-dead stopped thread. We'll use that as a backup if there are no running threads. 1746e9547b80SChaoren Lin stopped_thread_sp = thread_sp; 1747e9547b80SChaoren Lin } 1748e9547b80SChaoren Lin } 1749e9547b80SChaoren Lin 1750e9547b80SChaoren Lin if (!running_thread_sp && !stopped_thread_sp) 1751e9547b80SChaoren Lin { 17525830aa75STamas Berghammer Error error("found no running/stepping or live stopped threads as target for interrupt"); 1753e9547b80SChaoren Lin if (log) 1754e9547b80SChaoren Lin log->Printf ("NativeProcessLinux::%s skipping due to error: %s", __FUNCTION__, error.AsCString ()); 17555830aa75STamas Berghammer 1756e9547b80SChaoren Lin return error; 1757e9547b80SChaoren Lin } 1758e9547b80SChaoren Lin 1759e9547b80SChaoren Lin NativeThreadProtocolSP deferred_signal_thread_sp = running_thread_sp ? running_thread_sp : stopped_thread_sp; 1760e9547b80SChaoren Lin 1761e9547b80SChaoren Lin if (log) 1762e9547b80SChaoren Lin log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " %s tid %" PRIu64 " chosen for interrupt target", 1763e9547b80SChaoren Lin __FUNCTION__, 1764e9547b80SChaoren Lin GetID (), 1765e9547b80SChaoren Lin running_thread_sp ? "running" : "stopped", 1766e9547b80SChaoren Lin deferred_signal_thread_sp->GetID ()); 1767e9547b80SChaoren Lin 1768ed89c7feSPavel Labath StopRunningThreads(deferred_signal_thread_sp->GetID()); 176945f5cb31SPavel Labath 17705830aa75STamas Berghammer return Error(); 1771e9547b80SChaoren Lin } 1772e9547b80SChaoren Lin 1773e9547b80SChaoren Lin Error 1774af245d11STodd Fiala NativeProcessLinux::Kill () 1775af245d11STodd Fiala { 1776af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 1777af245d11STodd Fiala if (log) 1778af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s called for PID %" PRIu64, __FUNCTION__, GetID ()); 1779af245d11STodd Fiala 1780af245d11STodd Fiala Error error; 1781af245d11STodd Fiala 1782af245d11STodd Fiala switch (m_state) 1783af245d11STodd Fiala { 1784af245d11STodd Fiala case StateType::eStateInvalid: 1785af245d11STodd Fiala case StateType::eStateExited: 1786af245d11STodd Fiala case StateType::eStateCrashed: 1787af245d11STodd Fiala case StateType::eStateDetached: 1788af245d11STodd Fiala case StateType::eStateUnloaded: 1789af245d11STodd Fiala // Nothing to do - the process is already dead. 1790af245d11STodd Fiala if (log) 1791af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s ignored for PID %" PRIu64 " due to current state: %s", __FUNCTION__, GetID (), StateAsCString (m_state)); 1792af245d11STodd Fiala return error; 1793af245d11STodd Fiala 1794af245d11STodd Fiala case StateType::eStateConnected: 1795af245d11STodd Fiala case StateType::eStateAttaching: 1796af245d11STodd Fiala case StateType::eStateLaunching: 1797af245d11STodd Fiala case StateType::eStateStopped: 1798af245d11STodd Fiala case StateType::eStateRunning: 1799af245d11STodd Fiala case StateType::eStateStepping: 1800af245d11STodd Fiala case StateType::eStateSuspended: 1801af245d11STodd Fiala // We can try to kill a process in these states. 1802af245d11STodd Fiala break; 1803af245d11STodd Fiala } 1804af245d11STodd Fiala 1805af245d11STodd Fiala if (kill (GetID (), SIGKILL) != 0) 1806af245d11STodd Fiala { 1807af245d11STodd Fiala error.SetErrorToErrno (); 1808af245d11STodd Fiala return error; 1809af245d11STodd Fiala } 1810af245d11STodd Fiala 1811af245d11STodd Fiala return error; 1812af245d11STodd Fiala } 1813af245d11STodd Fiala 1814af245d11STodd Fiala static Error 1815af245d11STodd Fiala ParseMemoryRegionInfoFromProcMapsLine (const std::string &maps_line, MemoryRegionInfo &memory_region_info) 1816af245d11STodd Fiala { 1817af245d11STodd Fiala memory_region_info.Clear(); 1818af245d11STodd Fiala 1819af245d11STodd Fiala StringExtractor line_extractor (maps_line.c_str ()); 1820af245d11STodd Fiala 1821af245d11STodd Fiala // Format: {address_start_hex}-{address_end_hex} perms offset dev inode pathname 1822af245d11STodd Fiala // perms: rwxp (letter is present if set, '-' if not, final character is p=private, s=shared). 1823af245d11STodd Fiala 1824af245d11STodd Fiala // Parse out the starting address 1825af245d11STodd Fiala lldb::addr_t start_address = line_extractor.GetHexMaxU64 (false, 0); 1826af245d11STodd Fiala 1827af245d11STodd Fiala // Parse out hyphen separating start and end address from range. 1828af245d11STodd Fiala if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != '-')) 1829af245d11STodd Fiala return Error ("malformed /proc/{pid}/maps entry, missing dash between address range"); 1830af245d11STodd Fiala 1831af245d11STodd Fiala // Parse out the ending address 1832af245d11STodd Fiala lldb::addr_t end_address = line_extractor.GetHexMaxU64 (false, start_address); 1833af245d11STodd Fiala 1834af245d11STodd Fiala // Parse out the space after the address. 1835af245d11STodd Fiala if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != ' ')) 1836af245d11STodd Fiala return Error ("malformed /proc/{pid}/maps entry, missing space after range"); 1837af245d11STodd Fiala 1838af245d11STodd Fiala // Save the range. 1839af245d11STodd Fiala memory_region_info.GetRange ().SetRangeBase (start_address); 1840af245d11STodd Fiala memory_region_info.GetRange ().SetRangeEnd (end_address); 1841af245d11STodd Fiala 1842ad007563SHoward Hellyer // Any memory region in /proc/{pid}/maps is by definition mapped into the process. 1843ad007563SHoward Hellyer memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes); 1844ad007563SHoward Hellyer 1845af245d11STodd Fiala // Parse out each permission entry. 1846af245d11STodd Fiala if (line_extractor.GetBytesLeft () < 4) 1847af245d11STodd Fiala return Error ("malformed /proc/{pid}/maps entry, missing some portion of permissions"); 1848af245d11STodd Fiala 1849af245d11STodd Fiala // Handle read permission. 1850af245d11STodd Fiala const char read_perm_char = line_extractor.GetChar (); 1851af245d11STodd Fiala if (read_perm_char == 'r') 1852af245d11STodd Fiala memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eYes); 1853c73301bbSTamas Berghammer else if (read_perm_char == '-') 1854af245d11STodd Fiala memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); 1855c73301bbSTamas Berghammer else 1856c73301bbSTamas Berghammer return Error ("unexpected /proc/{pid}/maps read permission char"); 1857af245d11STodd Fiala 1858af245d11STodd Fiala // Handle write permission. 1859af245d11STodd Fiala const char write_perm_char = line_extractor.GetChar (); 1860af245d11STodd Fiala if (write_perm_char == 'w') 1861af245d11STodd Fiala memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eYes); 1862c73301bbSTamas Berghammer else if (write_perm_char == '-') 1863af245d11STodd Fiala memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); 1864c73301bbSTamas Berghammer else 1865c73301bbSTamas Berghammer return Error ("unexpected /proc/{pid}/maps write permission char"); 1866af245d11STodd Fiala 1867af245d11STodd Fiala // Handle execute permission. 1868af245d11STodd Fiala const char exec_perm_char = line_extractor.GetChar (); 1869af245d11STodd Fiala if (exec_perm_char == 'x') 1870af245d11STodd Fiala memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eYes); 1871c73301bbSTamas Berghammer else if (exec_perm_char == '-') 1872af245d11STodd Fiala memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); 1873c73301bbSTamas Berghammer else 1874c73301bbSTamas Berghammer return Error ("unexpected /proc/{pid}/maps exec permission char"); 1875af245d11STodd Fiala 1876af245d11STodd Fiala return Error (); 1877af245d11STodd Fiala } 1878af245d11STodd Fiala 1879af245d11STodd Fiala Error 1880af245d11STodd Fiala NativeProcessLinux::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) 1881af245d11STodd Fiala { 1882af245d11STodd Fiala // FIXME review that the final memory region returned extends to the end of the virtual address space, 1883af245d11STodd Fiala // with no perms if it is not mapped. 1884af245d11STodd Fiala 1885af245d11STodd Fiala // Use an approach that reads memory regions from /proc/{pid}/maps. 1886af245d11STodd Fiala // Assume proc maps entries are in ascending order. 1887af245d11STodd Fiala // FIXME assert if we find differently. 1888af245d11STodd Fiala 1889af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 1890af245d11STodd Fiala Error error; 1891af245d11STodd Fiala 1892af245d11STodd Fiala if (m_supports_mem_region == LazyBool::eLazyBoolNo) 1893af245d11STodd Fiala { 1894af245d11STodd Fiala // We're done. 1895af245d11STodd Fiala error.SetErrorString ("unsupported"); 1896af245d11STodd Fiala return error; 1897af245d11STodd Fiala } 1898af245d11STodd Fiala 1899af245d11STodd Fiala // If our cache is empty, pull the latest. There should always be at least one memory region 1900af245d11STodd Fiala // if memory region handling is supported. 1901af245d11STodd Fiala if (m_mem_region_cache.empty ()) 1902af245d11STodd Fiala { 1903af245d11STodd Fiala error = ProcFileReader::ProcessLineByLine (GetID (), "maps", 1904af245d11STodd Fiala [&] (const std::string &line) -> bool 1905af245d11STodd Fiala { 1906af245d11STodd Fiala MemoryRegionInfo info; 1907af245d11STodd Fiala const Error parse_error = ParseMemoryRegionInfoFromProcMapsLine (line, info); 1908af245d11STodd Fiala if (parse_error.Success ()) 1909af245d11STodd Fiala { 1910af245d11STodd Fiala m_mem_region_cache.push_back (info); 1911af245d11STodd Fiala return true; 1912af245d11STodd Fiala } 1913af245d11STodd Fiala else 1914af245d11STodd Fiala { 1915af245d11STodd Fiala if (log) 1916af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s failed to parse proc maps line '%s': %s", __FUNCTION__, line.c_str (), error.AsCString ()); 1917af245d11STodd Fiala return false; 1918af245d11STodd Fiala } 1919af245d11STodd Fiala }); 1920af245d11STodd Fiala 1921af245d11STodd Fiala // If we had an error, we'll mark unsupported. 1922af245d11STodd Fiala if (error.Fail ()) 1923af245d11STodd Fiala { 1924af245d11STodd Fiala m_supports_mem_region = LazyBool::eLazyBoolNo; 1925af245d11STodd Fiala return error; 1926af245d11STodd Fiala } 1927af245d11STodd Fiala else if (m_mem_region_cache.empty ()) 1928af245d11STodd Fiala { 1929af245d11STodd Fiala // No entries after attempting to read them. This shouldn't happen if /proc/{pid}/maps 1930af245d11STodd Fiala // is supported. Assume we don't support map entries via procfs. 1931af245d11STodd Fiala if (log) 1932af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s failed to find any procfs maps entries, assuming no support for memory region metadata retrieval", __FUNCTION__); 1933af245d11STodd Fiala m_supports_mem_region = LazyBool::eLazyBoolNo; 1934af245d11STodd Fiala error.SetErrorString ("not supported"); 1935af245d11STodd Fiala return error; 1936af245d11STodd Fiala } 1937af245d11STodd Fiala 1938af245d11STodd Fiala if (log) 1939af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s read %" PRIu64 " memory region entries from /proc/%" PRIu64 "/maps", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ()), GetID ()); 1940af245d11STodd Fiala 1941af245d11STodd Fiala // We support memory retrieval, remember that. 1942af245d11STodd Fiala m_supports_mem_region = LazyBool::eLazyBoolYes; 1943af245d11STodd Fiala } 1944af245d11STodd Fiala else 1945af245d11STodd Fiala { 1946af245d11STodd Fiala if (log) 1947af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s reusing %" PRIu64 " cached memory region entries", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ())); 1948af245d11STodd Fiala } 1949af245d11STodd Fiala 1950af245d11STodd Fiala lldb::addr_t prev_base_address = 0; 1951af245d11STodd Fiala 1952af245d11STodd Fiala // FIXME start by finding the last region that is <= target address using binary search. Data is sorted. 1953af245d11STodd Fiala // There can be a ton of regions on pthreads apps with lots of threads. 1954af245d11STodd Fiala for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end (); ++it) 1955af245d11STodd Fiala { 1956af245d11STodd Fiala MemoryRegionInfo &proc_entry_info = *it; 1957af245d11STodd Fiala 1958af245d11STodd Fiala // Sanity check assumption that /proc/{pid}/maps entries are ascending. 1959af245d11STodd Fiala assert ((proc_entry_info.GetRange ().GetRangeBase () >= prev_base_address) && "descending /proc/pid/maps entries detected, unexpected"); 1960af245d11STodd Fiala prev_base_address = proc_entry_info.GetRange ().GetRangeBase (); 1961af245d11STodd Fiala 1962af245d11STodd Fiala // If the target address comes before this entry, indicate distance to next region. 1963af245d11STodd Fiala if (load_addr < proc_entry_info.GetRange ().GetRangeBase ()) 1964af245d11STodd Fiala { 1965af245d11STodd Fiala range_info.GetRange ().SetRangeBase (load_addr); 1966af245d11STodd Fiala range_info.GetRange ().SetByteSize (proc_entry_info.GetRange ().GetRangeBase () - load_addr); 1967af245d11STodd Fiala range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); 1968af245d11STodd Fiala range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); 1969af245d11STodd Fiala range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); 1970ad007563SHoward Hellyer range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); 1971af245d11STodd Fiala 1972af245d11STodd Fiala return error; 1973af245d11STodd Fiala } 1974af245d11STodd Fiala else if (proc_entry_info.GetRange ().Contains (load_addr)) 1975af245d11STodd Fiala { 1976af245d11STodd Fiala // The target address is within the memory region we're processing here. 1977af245d11STodd Fiala range_info = proc_entry_info; 1978af245d11STodd Fiala return error; 1979af245d11STodd Fiala } 1980af245d11STodd Fiala 1981af245d11STodd Fiala // The target memory address comes somewhere after the region we just parsed. 1982af245d11STodd Fiala } 1983af245d11STodd Fiala 198409839c33STamas Berghammer // If we made it here, we didn't find an entry that contained the given address. Return the 198509839c33STamas Berghammer // load_addr as start and the amount of bytes betwwen load address and the end of the memory as 198609839c33STamas Berghammer // size. 198709839c33STamas Berghammer range_info.GetRange ().SetRangeBase (load_addr); 1988ad007563SHoward Hellyer range_info.GetRange ().SetRangeEnd(LLDB_INVALID_ADDRESS); 198909839c33STamas Berghammer range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); 199009839c33STamas Berghammer range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); 199109839c33STamas Berghammer range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); 1992ad007563SHoward Hellyer range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); 1993af245d11STodd Fiala return error; 1994af245d11STodd Fiala } 1995af245d11STodd Fiala 1996af245d11STodd Fiala void 1997af245d11STodd Fiala NativeProcessLinux::DoStopIDBumped (uint32_t newBumpId) 1998af245d11STodd Fiala { 1999af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 2000af245d11STodd Fiala if (log) 2001af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s(newBumpId=%" PRIu32 ") called", __FUNCTION__, newBumpId); 2002af245d11STodd Fiala 2003af245d11STodd Fiala if (log) 2004af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s clearing %" PRIu64 " entries from the cache", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ())); 2005af245d11STodd Fiala m_mem_region_cache.clear (); 2006af245d11STodd Fiala } 2007af245d11STodd Fiala 2008af245d11STodd Fiala Error 20093eb4b458SChaoren Lin NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) 2010af245d11STodd Fiala { 2011af245d11STodd Fiala // FIXME implementing this requires the equivalent of 2012af245d11STodd Fiala // InferiorCallPOSIX::InferiorCallMmap, which depends on 2013af245d11STodd Fiala // functional ThreadPlans working with Native*Protocol. 2014af245d11STodd Fiala #if 1 2015af245d11STodd Fiala return Error ("not implemented yet"); 2016af245d11STodd Fiala #else 2017af245d11STodd Fiala addr = LLDB_INVALID_ADDRESS; 2018af245d11STodd Fiala 2019af245d11STodd Fiala unsigned prot = 0; 2020af245d11STodd Fiala if (permissions & lldb::ePermissionsReadable) 2021af245d11STodd Fiala prot |= eMmapProtRead; 2022af245d11STodd Fiala if (permissions & lldb::ePermissionsWritable) 2023af245d11STodd Fiala prot |= eMmapProtWrite; 2024af245d11STodd Fiala if (permissions & lldb::ePermissionsExecutable) 2025af245d11STodd Fiala prot |= eMmapProtExec; 2026af245d11STodd Fiala 2027af245d11STodd Fiala // TODO implement this directly in NativeProcessLinux 2028af245d11STodd Fiala // (and lift to NativeProcessPOSIX if/when that class is 2029af245d11STodd Fiala // refactored out). 2030af245d11STodd Fiala if (InferiorCallMmap(this, addr, 0, size, prot, 2031af245d11STodd Fiala eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { 2032af245d11STodd Fiala m_addr_to_mmap_size[addr] = size; 2033af245d11STodd Fiala return Error (); 2034af245d11STodd Fiala } else { 2035af245d11STodd Fiala addr = LLDB_INVALID_ADDRESS; 2036af245d11STodd Fiala return Error("unable to allocate %" PRIu64 " bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); 2037af245d11STodd Fiala } 2038af245d11STodd Fiala #endif 2039af245d11STodd Fiala } 2040af245d11STodd Fiala 2041af245d11STodd Fiala Error 2042af245d11STodd Fiala NativeProcessLinux::DeallocateMemory (lldb::addr_t addr) 2043af245d11STodd Fiala { 2044af245d11STodd Fiala // FIXME see comments in AllocateMemory - required lower-level 2045af245d11STodd Fiala // bits not in place yet (ThreadPlans) 2046af245d11STodd Fiala return Error ("not implemented"); 2047af245d11STodd Fiala } 2048af245d11STodd Fiala 2049af245d11STodd Fiala lldb::addr_t 2050af245d11STodd Fiala NativeProcessLinux::GetSharedLibraryInfoAddress () 2051af245d11STodd Fiala { 2052af245d11STodd Fiala // punt on this for now 2053af245d11STodd Fiala return LLDB_INVALID_ADDRESS; 2054af245d11STodd Fiala } 2055af245d11STodd Fiala 2056af245d11STodd Fiala size_t 2057af245d11STodd Fiala NativeProcessLinux::UpdateThreads () 2058af245d11STodd Fiala { 2059af245d11STodd Fiala // The NativeProcessLinux monitoring threads are always up to date 2060af245d11STodd Fiala // with respect to thread state and they keep the thread list 2061af245d11STodd Fiala // populated properly. All this method needs to do is return the 2062af245d11STodd Fiala // thread count. 2063af245d11STodd Fiala return m_threads.size (); 2064af245d11STodd Fiala } 2065af245d11STodd Fiala 2066af245d11STodd Fiala bool 2067af245d11STodd Fiala NativeProcessLinux::GetArchitecture (ArchSpec &arch) const 2068af245d11STodd Fiala { 2069af245d11STodd Fiala arch = m_arch; 2070af245d11STodd Fiala return true; 2071af245d11STodd Fiala } 2072af245d11STodd Fiala 2073af245d11STodd Fiala Error 2074b9cc0c75SPavel Labath NativeProcessLinux::GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size) 2075af245d11STodd Fiala { 2076af245d11STodd Fiala // FIXME put this behind a breakpoint protocol class that can be 2077af245d11STodd Fiala // set per architecture. Need ARM, MIPS support here. 2078af245d11STodd Fiala static const uint8_t g_i386_opcode [] = { 0xCC }; 2079bb00d0b6SUlrich Weigand static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 }; 2080af245d11STodd Fiala 2081af245d11STodd Fiala switch (m_arch.GetMachine ()) 2082af245d11STodd Fiala { 2083af245d11STodd Fiala case llvm::Triple::x86: 2084af245d11STodd Fiala case llvm::Triple::x86_64: 2085af245d11STodd Fiala actual_opcode_size = static_cast<uint32_t> (sizeof(g_i386_opcode)); 2086af245d11STodd Fiala return Error (); 2087af245d11STodd Fiala 2088bb00d0b6SUlrich Weigand case llvm::Triple::systemz: 2089bb00d0b6SUlrich Weigand actual_opcode_size = static_cast<uint32_t> (sizeof(g_s390x_opcode)); 2090bb00d0b6SUlrich Weigand return Error (); 2091bb00d0b6SUlrich Weigand 2092ff7fd900STamas Berghammer case llvm::Triple::arm: 2093ff7fd900STamas Berghammer case llvm::Triple::aarch64: 2094e8659b5dSMohit K. Bhakkad case llvm::Triple::mips64: 2095e8659b5dSMohit K. Bhakkad case llvm::Triple::mips64el: 2096ce815e45SSagar Thakur case llvm::Triple::mips: 2097ce815e45SSagar Thakur case llvm::Triple::mipsel: 2098ff7fd900STamas Berghammer // On these architectures the PC don't get updated for breakpoint hits 2099c60c9452SJaydeep Patil actual_opcode_size = 0; 2100e8659b5dSMohit K. Bhakkad return Error (); 2101e8659b5dSMohit K. Bhakkad 2102af245d11STodd Fiala default: 2103af245d11STodd Fiala assert(false && "CPU type not supported!"); 2104af245d11STodd Fiala return Error ("CPU type not supported"); 2105af245d11STodd Fiala } 2106af245d11STodd Fiala } 2107af245d11STodd Fiala 2108af245d11STodd Fiala Error 2109af245d11STodd Fiala NativeProcessLinux::SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) 2110af245d11STodd Fiala { 2111af245d11STodd Fiala if (hardware) 2112af245d11STodd Fiala return Error ("NativeProcessLinux does not support hardware breakpoints"); 2113af245d11STodd Fiala else 2114af245d11STodd Fiala return SetSoftwareBreakpoint (addr, size); 2115af245d11STodd Fiala } 2116af245d11STodd Fiala 2117af245d11STodd Fiala Error 211863c8be95STamas Berghammer NativeProcessLinux::GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, 211963c8be95STamas Berghammer size_t &actual_opcode_size, 212063c8be95STamas Berghammer const uint8_t *&trap_opcode_bytes) 2121af245d11STodd Fiala { 212263c8be95STamas Berghammer // FIXME put this behind a breakpoint protocol class that can be set per 212363c8be95STamas Berghammer // architecture. Need MIPS support here. 21242afc5966STodd Fiala static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 }; 2125be379e15STamas Berghammer // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the 2126be379e15STamas Berghammer // linux kernel does otherwise. 2127be379e15STamas Berghammer static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 }; 2128af245d11STodd Fiala static const uint8_t g_i386_opcode [] = { 0xCC }; 21293df471c3SMohit K. Bhakkad static const uint8_t g_mips64_opcode[] = { 0x00, 0x00, 0x00, 0x0d }; 21302c2acf96SMohit K. Bhakkad static const uint8_t g_mips64el_opcode[] = { 0x0d, 0x00, 0x00, 0x00 }; 2131bb00d0b6SUlrich Weigand static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 }; 2132be379e15STamas Berghammer static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde }; 2133af245d11STodd Fiala 2134af245d11STodd Fiala switch (m_arch.GetMachine ()) 2135af245d11STodd Fiala { 21362afc5966STodd Fiala case llvm::Triple::aarch64: 21372afc5966STodd Fiala trap_opcode_bytes = g_aarch64_opcode; 21382afc5966STodd Fiala actual_opcode_size = sizeof(g_aarch64_opcode); 21392afc5966STodd Fiala return Error (); 21402afc5966STodd Fiala 214163c8be95STamas Berghammer case llvm::Triple::arm: 214263c8be95STamas Berghammer switch (trap_opcode_size_hint) 214363c8be95STamas Berghammer { 214463c8be95STamas Berghammer case 2: 214563c8be95STamas Berghammer trap_opcode_bytes = g_thumb_breakpoint_opcode; 214663c8be95STamas Berghammer actual_opcode_size = sizeof(g_thumb_breakpoint_opcode); 214763c8be95STamas Berghammer return Error (); 214863c8be95STamas Berghammer case 4: 214963c8be95STamas Berghammer trap_opcode_bytes = g_arm_breakpoint_opcode; 215063c8be95STamas Berghammer actual_opcode_size = sizeof(g_arm_breakpoint_opcode); 215163c8be95STamas Berghammer return Error (); 215263c8be95STamas Berghammer default: 215363c8be95STamas Berghammer assert(false && "Unrecognised trap opcode size hint!"); 215463c8be95STamas Berghammer return Error ("Unrecognised trap opcode size hint!"); 215563c8be95STamas Berghammer } 215663c8be95STamas Berghammer 2157af245d11STodd Fiala case llvm::Triple::x86: 2158af245d11STodd Fiala case llvm::Triple::x86_64: 2159af245d11STodd Fiala trap_opcode_bytes = g_i386_opcode; 2160af245d11STodd Fiala actual_opcode_size = sizeof(g_i386_opcode); 2161af245d11STodd Fiala return Error (); 2162af245d11STodd Fiala 2163ce815e45SSagar Thakur case llvm::Triple::mips: 21643df471c3SMohit K. Bhakkad case llvm::Triple::mips64: 21653df471c3SMohit K. Bhakkad trap_opcode_bytes = g_mips64_opcode; 21663df471c3SMohit K. Bhakkad actual_opcode_size = sizeof(g_mips64_opcode); 21673df471c3SMohit K. Bhakkad return Error (); 21683df471c3SMohit K. Bhakkad 2169ce815e45SSagar Thakur case llvm::Triple::mipsel: 21702c2acf96SMohit K. Bhakkad case llvm::Triple::mips64el: 21712c2acf96SMohit K. Bhakkad trap_opcode_bytes = g_mips64el_opcode; 21722c2acf96SMohit K. Bhakkad actual_opcode_size = sizeof(g_mips64el_opcode); 21732c2acf96SMohit K. Bhakkad return Error (); 21742c2acf96SMohit K. Bhakkad 2175bb00d0b6SUlrich Weigand case llvm::Triple::systemz: 2176bb00d0b6SUlrich Weigand trap_opcode_bytes = g_s390x_opcode; 2177bb00d0b6SUlrich Weigand actual_opcode_size = sizeof(g_s390x_opcode); 2178bb00d0b6SUlrich Weigand return Error (); 2179bb00d0b6SUlrich Weigand 2180af245d11STodd Fiala default: 2181af245d11STodd Fiala assert(false && "CPU type not supported!"); 2182af245d11STodd Fiala return Error ("CPU type not supported"); 2183af245d11STodd Fiala } 2184af245d11STodd Fiala } 2185af245d11STodd Fiala 2186af245d11STodd Fiala #if 0 2187af245d11STodd Fiala ProcessMessage::CrashReason 2188af245d11STodd Fiala NativeProcessLinux::GetCrashReasonForSIGSEGV(const siginfo_t *info) 2189af245d11STodd Fiala { 2190af245d11STodd Fiala ProcessMessage::CrashReason reason; 2191af245d11STodd Fiala assert(info->si_signo == SIGSEGV); 2192af245d11STodd Fiala 2193af245d11STodd Fiala reason = ProcessMessage::eInvalidCrashReason; 2194af245d11STodd Fiala 2195af245d11STodd Fiala switch (info->si_code) 2196af245d11STodd Fiala { 2197af245d11STodd Fiala default: 2198af245d11STodd Fiala assert(false && "unexpected si_code for SIGSEGV"); 2199af245d11STodd Fiala break; 2200af245d11STodd Fiala case SI_KERNEL: 2201af245d11STodd Fiala // Linux will occasionally send spurious SI_KERNEL codes. 2202af245d11STodd Fiala // (this is poorly documented in sigaction) 2203af245d11STodd Fiala // One way to get this is via unaligned SIMD loads. 2204af245d11STodd Fiala reason = ProcessMessage::eInvalidAddress; // for lack of anything better 2205af245d11STodd Fiala break; 2206af245d11STodd Fiala case SEGV_MAPERR: 2207af245d11STodd Fiala reason = ProcessMessage::eInvalidAddress; 2208af245d11STodd Fiala break; 2209af245d11STodd Fiala case SEGV_ACCERR: 2210af245d11STodd Fiala reason = ProcessMessage::ePrivilegedAddress; 2211af245d11STodd Fiala break; 2212af245d11STodd Fiala } 2213af245d11STodd Fiala 2214af245d11STodd Fiala return reason; 2215af245d11STodd Fiala } 2216af245d11STodd Fiala #endif 2217af245d11STodd Fiala 2218af245d11STodd Fiala 2219af245d11STodd Fiala #if 0 2220af245d11STodd Fiala ProcessMessage::CrashReason 2221af245d11STodd Fiala NativeProcessLinux::GetCrashReasonForSIGILL(const siginfo_t *info) 2222af245d11STodd Fiala { 2223af245d11STodd Fiala ProcessMessage::CrashReason reason; 2224af245d11STodd Fiala assert(info->si_signo == SIGILL); 2225af245d11STodd Fiala 2226af245d11STodd Fiala reason = ProcessMessage::eInvalidCrashReason; 2227af245d11STodd Fiala 2228af245d11STodd Fiala switch (info->si_code) 2229af245d11STodd Fiala { 2230af245d11STodd Fiala default: 2231af245d11STodd Fiala assert(false && "unexpected si_code for SIGILL"); 2232af245d11STodd Fiala break; 2233af245d11STodd Fiala case ILL_ILLOPC: 2234af245d11STodd Fiala reason = ProcessMessage::eIllegalOpcode; 2235af245d11STodd Fiala break; 2236af245d11STodd Fiala case ILL_ILLOPN: 2237af245d11STodd Fiala reason = ProcessMessage::eIllegalOperand; 2238af245d11STodd Fiala break; 2239af245d11STodd Fiala case ILL_ILLADR: 2240af245d11STodd Fiala reason = ProcessMessage::eIllegalAddressingMode; 2241af245d11STodd Fiala break; 2242af245d11STodd Fiala case ILL_ILLTRP: 2243af245d11STodd Fiala reason = ProcessMessage::eIllegalTrap; 2244af245d11STodd Fiala break; 2245af245d11STodd Fiala case ILL_PRVOPC: 2246af245d11STodd Fiala reason = ProcessMessage::ePrivilegedOpcode; 2247af245d11STodd Fiala break; 2248af245d11STodd Fiala case ILL_PRVREG: 2249af245d11STodd Fiala reason = ProcessMessage::ePrivilegedRegister; 2250af245d11STodd Fiala break; 2251af245d11STodd Fiala case ILL_COPROC: 2252af245d11STodd Fiala reason = ProcessMessage::eCoprocessorError; 2253af245d11STodd Fiala break; 2254af245d11STodd Fiala case ILL_BADSTK: 2255af245d11STodd Fiala reason = ProcessMessage::eInternalStackError; 2256af245d11STodd Fiala break; 2257af245d11STodd Fiala } 2258af245d11STodd Fiala 2259af245d11STodd Fiala return reason; 2260af245d11STodd Fiala } 2261af245d11STodd Fiala #endif 2262af245d11STodd Fiala 2263af245d11STodd Fiala #if 0 2264af245d11STodd Fiala ProcessMessage::CrashReason 2265af245d11STodd Fiala NativeProcessLinux::GetCrashReasonForSIGFPE(const siginfo_t *info) 2266af245d11STodd Fiala { 2267af245d11STodd Fiala ProcessMessage::CrashReason reason; 2268af245d11STodd Fiala assert(info->si_signo == SIGFPE); 2269af245d11STodd Fiala 2270af245d11STodd Fiala reason = ProcessMessage::eInvalidCrashReason; 2271af245d11STodd Fiala 2272af245d11STodd Fiala switch (info->si_code) 2273af245d11STodd Fiala { 2274af245d11STodd Fiala default: 2275af245d11STodd Fiala assert(false && "unexpected si_code for SIGFPE"); 2276af245d11STodd Fiala break; 2277af245d11STodd Fiala case FPE_INTDIV: 2278af245d11STodd Fiala reason = ProcessMessage::eIntegerDivideByZero; 2279af245d11STodd Fiala break; 2280af245d11STodd Fiala case FPE_INTOVF: 2281af245d11STodd Fiala reason = ProcessMessage::eIntegerOverflow; 2282af245d11STodd Fiala break; 2283af245d11STodd Fiala case FPE_FLTDIV: 2284af245d11STodd Fiala reason = ProcessMessage::eFloatDivideByZero; 2285af245d11STodd Fiala break; 2286af245d11STodd Fiala case FPE_FLTOVF: 2287af245d11STodd Fiala reason = ProcessMessage::eFloatOverflow; 2288af245d11STodd Fiala break; 2289af245d11STodd Fiala case FPE_FLTUND: 2290af245d11STodd Fiala reason = ProcessMessage::eFloatUnderflow; 2291af245d11STodd Fiala break; 2292af245d11STodd Fiala case FPE_FLTRES: 2293af245d11STodd Fiala reason = ProcessMessage::eFloatInexactResult; 2294af245d11STodd Fiala break; 2295af245d11STodd Fiala case FPE_FLTINV: 2296af245d11STodd Fiala reason = ProcessMessage::eFloatInvalidOperation; 2297af245d11STodd Fiala break; 2298af245d11STodd Fiala case FPE_FLTSUB: 2299af245d11STodd Fiala reason = ProcessMessage::eFloatSubscriptRange; 2300af245d11STodd Fiala break; 2301af245d11STodd Fiala } 2302af245d11STodd Fiala 2303af245d11STodd Fiala return reason; 2304af245d11STodd Fiala } 2305af245d11STodd Fiala #endif 2306af245d11STodd Fiala 2307af245d11STodd Fiala #if 0 2308af245d11STodd Fiala ProcessMessage::CrashReason 2309af245d11STodd Fiala NativeProcessLinux::GetCrashReasonForSIGBUS(const siginfo_t *info) 2310af245d11STodd Fiala { 2311af245d11STodd Fiala ProcessMessage::CrashReason reason; 2312af245d11STodd Fiala assert(info->si_signo == SIGBUS); 2313af245d11STodd Fiala 2314af245d11STodd Fiala reason = ProcessMessage::eInvalidCrashReason; 2315af245d11STodd Fiala 2316af245d11STodd Fiala switch (info->si_code) 2317af245d11STodd Fiala { 2318af245d11STodd Fiala default: 2319af245d11STodd Fiala assert(false && "unexpected si_code for SIGBUS"); 2320af245d11STodd Fiala break; 2321af245d11STodd Fiala case BUS_ADRALN: 2322af245d11STodd Fiala reason = ProcessMessage::eIllegalAlignment; 2323af245d11STodd Fiala break; 2324af245d11STodd Fiala case BUS_ADRERR: 2325af245d11STodd Fiala reason = ProcessMessage::eIllegalAddress; 2326af245d11STodd Fiala break; 2327af245d11STodd Fiala case BUS_OBJERR: 2328af245d11STodd Fiala reason = ProcessMessage::eHardwareError; 2329af245d11STodd Fiala break; 2330af245d11STodd Fiala } 2331af245d11STodd Fiala 2332af245d11STodd Fiala return reason; 2333af245d11STodd Fiala } 2334af245d11STodd Fiala #endif 2335af245d11STodd Fiala 2336af245d11STodd Fiala Error 233726438d26SChaoren Lin NativeProcessLinux::ReadMemory (lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) 2338af245d11STodd Fiala { 2339df7c6995SPavel Labath if (ProcessVmReadvSupported()) { 2340df7c6995SPavel Labath // The process_vm_readv path is about 50 times faster than ptrace api. We want to use 2341df7c6995SPavel Labath // this syscall if it is supported. 2342df7c6995SPavel Labath 2343df7c6995SPavel Labath const ::pid_t pid = GetID(); 2344df7c6995SPavel Labath 2345df7c6995SPavel Labath struct iovec local_iov, remote_iov; 2346df7c6995SPavel Labath local_iov.iov_base = buf; 2347df7c6995SPavel Labath local_iov.iov_len = size; 2348df7c6995SPavel Labath remote_iov.iov_base = reinterpret_cast<void *>(addr); 2349df7c6995SPavel Labath remote_iov.iov_len = size; 2350df7c6995SPavel Labath 2351df7c6995SPavel Labath bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0); 2352df7c6995SPavel Labath const bool success = bytes_read == size; 2353df7c6995SPavel Labath 2354df7c6995SPavel Labath Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 2355df7c6995SPavel Labath if (log) 2356df7c6995SPavel Labath log->Printf ("NativeProcessLinux::%s using process_vm_readv to read %zd bytes from inferior address 0x%" PRIx64": %s", 2357df7c6995SPavel Labath __FUNCTION__, size, addr, success ? "Success" : strerror(errno)); 2358df7c6995SPavel Labath 2359df7c6995SPavel Labath if (success) 2360df7c6995SPavel Labath return Error(); 2361df7c6995SPavel Labath // else 2362df7c6995SPavel Labath // the call failed for some reason, let's retry the read using ptrace api. 2363df7c6995SPavel Labath } 2364df7c6995SPavel Labath 236519cbe96aSPavel Labath unsigned char *dst = static_cast<unsigned char*>(buf); 236619cbe96aSPavel Labath size_t remainder; 236719cbe96aSPavel Labath long data; 236819cbe96aSPavel Labath 236919cbe96aSPavel Labath Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); 237019cbe96aSPavel Labath if (log) 237119cbe96aSPavel Labath ProcessPOSIXLog::IncNestLevel(); 237219cbe96aSPavel Labath if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) 237319cbe96aSPavel Labath log->Printf ("NativeProcessLinux::%s(%p, %p, %zd, _)", __FUNCTION__, (void*)addr, buf, size); 237419cbe96aSPavel Labath 237519cbe96aSPavel Labath for (bytes_read = 0; bytes_read < size; bytes_read += remainder) 237619cbe96aSPavel Labath { 237719cbe96aSPavel Labath Error error = NativeProcessLinux::PtraceWrapper(PTRACE_PEEKDATA, GetID(), (void*)addr, nullptr, 0, &data); 237819cbe96aSPavel Labath if (error.Fail()) 237919cbe96aSPavel Labath { 238019cbe96aSPavel Labath if (log) 238119cbe96aSPavel Labath ProcessPOSIXLog::DecNestLevel(); 238219cbe96aSPavel Labath return error; 238319cbe96aSPavel Labath } 238419cbe96aSPavel Labath 238519cbe96aSPavel Labath remainder = size - bytes_read; 238619cbe96aSPavel Labath remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; 238719cbe96aSPavel Labath 238819cbe96aSPavel Labath // Copy the data into our buffer 2389f6ef187bSMohit K. Bhakkad memcpy(dst, &data, remainder); 239019cbe96aSPavel Labath 239119cbe96aSPavel Labath if (log && ProcessPOSIXLog::AtTopNestLevel() && 239219cbe96aSPavel Labath (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || 239319cbe96aSPavel Labath (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && 239419cbe96aSPavel Labath size <= POSIX_LOG_MEMORY_SHORT_BYTES))) 239519cbe96aSPavel Labath { 239619cbe96aSPavel Labath uintptr_t print_dst = 0; 239719cbe96aSPavel Labath // Format bytes from data by moving into print_dst for log output 239819cbe96aSPavel Labath for (unsigned i = 0; i < remainder; ++i) 239919cbe96aSPavel Labath print_dst |= (((data >> i*8) & 0xFF) << i*8); 240079203995SPavel Labath log->Printf ("NativeProcessLinux::%s() [0x%" PRIx64 "]:0x%" PRIx64 " (0x%" PRIx64 ")", 240179203995SPavel Labath __FUNCTION__, addr, uint64_t(print_dst), uint64_t(data)); 240219cbe96aSPavel Labath } 240319cbe96aSPavel Labath addr += k_ptrace_word_size; 240419cbe96aSPavel Labath dst += k_ptrace_word_size; 240519cbe96aSPavel Labath } 240619cbe96aSPavel Labath 240719cbe96aSPavel Labath if (log) 240819cbe96aSPavel Labath ProcessPOSIXLog::DecNestLevel(); 240919cbe96aSPavel Labath return Error(); 2410af245d11STodd Fiala } 2411af245d11STodd Fiala 2412af245d11STodd Fiala Error 24133eb4b458SChaoren Lin NativeProcessLinux::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) 24143eb4b458SChaoren Lin { 24153eb4b458SChaoren Lin Error error = ReadMemory(addr, buf, size, bytes_read); 24163eb4b458SChaoren Lin if (error.Fail()) return error; 24173eb4b458SChaoren Lin return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size); 24183eb4b458SChaoren Lin } 24193eb4b458SChaoren Lin 24203eb4b458SChaoren Lin Error 24213eb4b458SChaoren Lin NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) 2422af245d11STodd Fiala { 242319cbe96aSPavel Labath const unsigned char *src = static_cast<const unsigned char*>(buf); 242419cbe96aSPavel Labath size_t remainder; 242519cbe96aSPavel Labath Error error; 242619cbe96aSPavel Labath 242719cbe96aSPavel Labath Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); 242819cbe96aSPavel Labath if (log) 242919cbe96aSPavel Labath ProcessPOSIXLog::IncNestLevel(); 243019cbe96aSPavel Labath if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) 243179203995SPavel Labath log->Printf ("NativeProcessLinux::%s(0x%" PRIx64 ", %p, %zu)", __FUNCTION__, addr, buf, size); 243219cbe96aSPavel Labath 243319cbe96aSPavel Labath for (bytes_written = 0; bytes_written < size; bytes_written += remainder) 243419cbe96aSPavel Labath { 243519cbe96aSPavel Labath remainder = size - bytes_written; 243619cbe96aSPavel Labath remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; 243719cbe96aSPavel Labath 243819cbe96aSPavel Labath if (remainder == k_ptrace_word_size) 243919cbe96aSPavel Labath { 244019cbe96aSPavel Labath unsigned long data = 0; 2441f6ef187bSMohit K. Bhakkad memcpy(&data, src, k_ptrace_word_size); 244219cbe96aSPavel Labath 244319cbe96aSPavel Labath if (log && ProcessPOSIXLog::AtTopNestLevel() && 244419cbe96aSPavel Labath (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || 244519cbe96aSPavel Labath (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && 244619cbe96aSPavel Labath size <= POSIX_LOG_MEMORY_SHORT_BYTES))) 244719cbe96aSPavel Labath log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, 244819cbe96aSPavel Labath (void*)addr, *(const unsigned long*)src, data); 244919cbe96aSPavel Labath 245019cbe96aSPavel Labath error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(), (void*)addr, (void*)data); 245119cbe96aSPavel Labath if (error.Fail()) 245219cbe96aSPavel Labath { 245319cbe96aSPavel Labath if (log) 245419cbe96aSPavel Labath ProcessPOSIXLog::DecNestLevel(); 245519cbe96aSPavel Labath return error; 245619cbe96aSPavel Labath } 245719cbe96aSPavel Labath } 245819cbe96aSPavel Labath else 245919cbe96aSPavel Labath { 246019cbe96aSPavel Labath unsigned char buff[8]; 246119cbe96aSPavel Labath size_t bytes_read; 246219cbe96aSPavel Labath error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read); 246319cbe96aSPavel Labath if (error.Fail()) 246419cbe96aSPavel Labath { 246519cbe96aSPavel Labath if (log) 246619cbe96aSPavel Labath ProcessPOSIXLog::DecNestLevel(); 246719cbe96aSPavel Labath return error; 246819cbe96aSPavel Labath } 246919cbe96aSPavel Labath 247019cbe96aSPavel Labath memcpy(buff, src, remainder); 247119cbe96aSPavel Labath 247219cbe96aSPavel Labath size_t bytes_written_rec; 247319cbe96aSPavel Labath error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec); 247419cbe96aSPavel Labath if (error.Fail()) 247519cbe96aSPavel Labath { 247619cbe96aSPavel Labath if (log) 247719cbe96aSPavel Labath ProcessPOSIXLog::DecNestLevel(); 247819cbe96aSPavel Labath return error; 247919cbe96aSPavel Labath } 248019cbe96aSPavel Labath 248119cbe96aSPavel Labath if (log && ProcessPOSIXLog::AtTopNestLevel() && 248219cbe96aSPavel Labath (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || 248319cbe96aSPavel Labath (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && 248419cbe96aSPavel Labath size <= POSIX_LOG_MEMORY_SHORT_BYTES))) 248519cbe96aSPavel Labath log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, 248619cbe96aSPavel Labath (void*)addr, *(const unsigned long*)src, *(unsigned long*)buff); 248719cbe96aSPavel Labath } 248819cbe96aSPavel Labath 248919cbe96aSPavel Labath addr += k_ptrace_word_size; 249019cbe96aSPavel Labath src += k_ptrace_word_size; 249119cbe96aSPavel Labath } 249219cbe96aSPavel Labath if (log) 249319cbe96aSPavel Labath ProcessPOSIXLog::DecNestLevel(); 249419cbe96aSPavel Labath return error; 2495af245d11STodd Fiala } 2496af245d11STodd Fiala 249797ccc294SChaoren Lin Error 249897ccc294SChaoren Lin NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo) 2499af245d11STodd Fiala { 250019cbe96aSPavel Labath return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo); 2501af245d11STodd Fiala } 2502af245d11STodd Fiala 250397ccc294SChaoren Lin Error 2504af245d11STodd Fiala NativeProcessLinux::GetEventMessage(lldb::tid_t tid, unsigned long *message) 2505af245d11STodd Fiala { 250619cbe96aSPavel Labath return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message); 2507af245d11STodd Fiala } 2508af245d11STodd Fiala 2509db264a6dSTamas Berghammer Error 2510af245d11STodd Fiala NativeProcessLinux::Detach(lldb::tid_t tid) 2511af245d11STodd Fiala { 251297ccc294SChaoren Lin if (tid == LLDB_INVALID_THREAD_ID) 251397ccc294SChaoren Lin return Error(); 251497ccc294SChaoren Lin 251519cbe96aSPavel Labath return PtraceWrapper(PTRACE_DETACH, tid); 2516af245d11STodd Fiala } 2517af245d11STodd Fiala 2518af245d11STodd Fiala bool 2519d3173f34SChaoren Lin NativeProcessLinux::DupDescriptor(const FileSpec &file_spec, int fd, int flags) 2520af245d11STodd Fiala { 2521d3173f34SChaoren Lin int target_fd = open(file_spec.GetCString(), flags, 0666); 2522af245d11STodd Fiala 2523af245d11STodd Fiala if (target_fd == -1) 2524af245d11STodd Fiala return false; 2525af245d11STodd Fiala 2526493c3a12SPavel Labath if (dup2(target_fd, fd) == -1) 2527493c3a12SPavel Labath return false; 2528493c3a12SPavel Labath 2529493c3a12SPavel Labath return (close(target_fd) == -1) ? false : true; 2530af245d11STodd Fiala } 2531af245d11STodd Fiala 2532af245d11STodd Fiala bool 2533af245d11STodd Fiala NativeProcessLinux::HasThreadNoLock (lldb::tid_t thread_id) 2534af245d11STodd Fiala { 2535af245d11STodd Fiala for (auto thread_sp : m_threads) 2536af245d11STodd Fiala { 2537af245d11STodd Fiala assert (thread_sp && "thread list should not contain NULL threads"); 2538af245d11STodd Fiala if (thread_sp->GetID () == thread_id) 2539af245d11STodd Fiala { 2540af245d11STodd Fiala // We have this thread. 2541af245d11STodd Fiala return true; 2542af245d11STodd Fiala } 2543af245d11STodd Fiala } 2544af245d11STodd Fiala 2545af245d11STodd Fiala // We don't have this thread. 2546af245d11STodd Fiala return false; 2547af245d11STodd Fiala } 2548af245d11STodd Fiala 2549af245d11STodd Fiala bool 2550af245d11STodd Fiala NativeProcessLinux::StopTrackingThread (lldb::tid_t thread_id) 2551af245d11STodd Fiala { 25521dbc6c9cSPavel Labath Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD); 25531dbc6c9cSPavel Labath 25541dbc6c9cSPavel Labath if (log) 25551dbc6c9cSPavel Labath log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, thread_id); 25561dbc6c9cSPavel Labath 25571dbc6c9cSPavel Labath bool found = false; 25581dbc6c9cSPavel Labath 2559af245d11STodd Fiala for (auto it = m_threads.begin (); it != m_threads.end (); ++it) 2560af245d11STodd Fiala { 2561af245d11STodd Fiala if (*it && ((*it)->GetID () == thread_id)) 2562af245d11STodd Fiala { 2563af245d11STodd Fiala m_threads.erase (it); 25641dbc6c9cSPavel Labath found = true; 25651dbc6c9cSPavel Labath break; 2566af245d11STodd Fiala } 2567af245d11STodd Fiala } 2568af245d11STodd Fiala 25699eb1ecb9SPavel Labath SignalIfAllThreadsStopped(); 25701dbc6c9cSPavel Labath 25711dbc6c9cSPavel Labath return found; 2572af245d11STodd Fiala } 2573af245d11STodd Fiala 2574f9077782SPavel Labath NativeThreadLinuxSP 2575af245d11STodd Fiala NativeProcessLinux::AddThread (lldb::tid_t thread_id) 2576af245d11STodd Fiala { 2577af245d11STodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 2578af245d11STodd Fiala 2579af245d11STodd Fiala if (log) 2580af245d11STodd Fiala { 2581af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " adding thread with tid %" PRIu64, 2582af245d11STodd Fiala __FUNCTION__, 2583af245d11STodd Fiala GetID (), 2584af245d11STodd Fiala thread_id); 2585af245d11STodd Fiala } 2586af245d11STodd Fiala 2587af245d11STodd Fiala assert (!HasThreadNoLock (thread_id) && "attempted to add a thread by id that already exists"); 2588af245d11STodd Fiala 2589af245d11STodd Fiala // If this is the first thread, save it as the current thread 2590af245d11STodd Fiala if (m_threads.empty ()) 2591af245d11STodd Fiala SetCurrentThreadID (thread_id); 2592af245d11STodd Fiala 2593f9077782SPavel Labath auto thread_sp = std::make_shared<NativeThreadLinux>(this, thread_id); 2594af245d11STodd Fiala m_threads.push_back (thread_sp); 2595af245d11STodd Fiala return thread_sp; 2596af245d11STodd Fiala } 2597af245d11STodd Fiala 2598af245d11STodd Fiala Error 2599b9cc0c75SPavel Labath NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) 2600af245d11STodd Fiala { 260175f47c3aSTodd Fiala Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 2602af245d11STodd Fiala 2603af245d11STodd Fiala Error error; 2604af245d11STodd Fiala 2605af245d11STodd Fiala // Find out the size of a breakpoint (might depend on where we are in the code). 2606b9cc0c75SPavel Labath NativeRegisterContextSP context_sp = thread.GetRegisterContext(); 2607af245d11STodd Fiala if (!context_sp) 2608af245d11STodd Fiala { 2609af245d11STodd Fiala error.SetErrorString ("cannot get a NativeRegisterContext for the thread"); 2610af245d11STodd Fiala if (log) 2611af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s failed: %s", __FUNCTION__, error.AsCString ()); 2612af245d11STodd Fiala return error; 2613af245d11STodd Fiala } 2614af245d11STodd Fiala 2615af245d11STodd Fiala uint32_t breakpoint_size = 0; 2616b9cc0c75SPavel Labath error = GetSoftwareBreakpointPCOffset(breakpoint_size); 2617af245d11STodd Fiala if (error.Fail ()) 2618af245d11STodd Fiala { 2619af245d11STodd Fiala if (log) 2620af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s GetBreakpointSize() failed: %s", __FUNCTION__, error.AsCString ()); 2621af245d11STodd Fiala return error; 2622af245d11STodd Fiala } 2623af245d11STodd Fiala else 2624af245d11STodd Fiala { 2625af245d11STodd Fiala if (log) 2626af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s breakpoint size: %" PRIu32, __FUNCTION__, breakpoint_size); 2627af245d11STodd Fiala } 2628af245d11STodd Fiala 2629af245d11STodd Fiala // First try probing for a breakpoint at a software breakpoint location: PC - breakpoint size. 2630c60c9452SJaydeep Patil const lldb::addr_t initial_pc_addr = context_sp->GetPCfromBreakpointLocation (); 2631af245d11STodd Fiala lldb::addr_t breakpoint_addr = initial_pc_addr; 26323eb4b458SChaoren Lin if (breakpoint_size > 0) 2633af245d11STodd Fiala { 2634af245d11STodd Fiala // Do not allow breakpoint probe to wrap around. 26353eb4b458SChaoren Lin if (breakpoint_addr >= breakpoint_size) 26363eb4b458SChaoren Lin breakpoint_addr -= breakpoint_size; 2637af245d11STodd Fiala } 2638af245d11STodd Fiala 2639af245d11STodd Fiala // Check if we stopped because of a breakpoint. 2640af245d11STodd Fiala NativeBreakpointSP breakpoint_sp; 2641af245d11STodd Fiala error = m_breakpoint_list.GetBreakpoint (breakpoint_addr, breakpoint_sp); 2642af245d11STodd Fiala if (!error.Success () || !breakpoint_sp) 2643af245d11STodd Fiala { 2644af245d11STodd Fiala // We didn't find one at a software probe location. Nothing to do. 2645af245d11STodd Fiala if (log) 2646af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " no lldb breakpoint found at current pc with adjustment: 0x%" PRIx64, __FUNCTION__, GetID (), breakpoint_addr); 2647af245d11STodd Fiala return Error (); 2648af245d11STodd Fiala } 2649af245d11STodd Fiala 2650af245d11STodd Fiala // If the breakpoint is not a software breakpoint, nothing to do. 2651af245d11STodd Fiala if (!breakpoint_sp->IsSoftwareBreakpoint ()) 2652af245d11STodd Fiala { 2653af245d11STodd Fiala if (log) 2654af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " breakpoint found at 0x%" PRIx64 ", not software, nothing to adjust", __FUNCTION__, GetID (), breakpoint_addr); 2655af245d11STodd Fiala return Error (); 2656af245d11STodd Fiala } 2657af245d11STodd Fiala 2658af245d11STodd Fiala // 2659af245d11STodd Fiala // We have a software breakpoint and need to adjust the PC. 2660af245d11STodd Fiala // 2661af245d11STodd Fiala 2662af245d11STodd Fiala // Sanity check. 2663af245d11STodd Fiala if (breakpoint_size == 0) 2664af245d11STodd Fiala { 2665af245d11STodd Fiala // Nothing to do! How did we get here? 2666af245d11STodd Fiala if (log) 2667af245d11STodd Fiala log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " breakpoint found at 0x%" PRIx64 ", it is software, but the size is zero, nothing to do (unexpected)", __FUNCTION__, GetID (), breakpoint_addr); 2668af245d11STodd Fiala return Error (); 2669af245d11STodd Fiala } 2670af245d11STodd Fiala 2671af245d11STodd Fiala // Change the program counter. 2672af245d11STodd Fiala if (log) 2673b9cc0c75SPavel Labath log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 ": changing PC from 0x%" PRIx64 " to 0x%" PRIx64, __FUNCTION__, GetID(), thread.GetID(), initial_pc_addr, breakpoint_addr); 2674af245d11STodd Fiala 2675af245d11STodd Fiala error = context_sp->SetPC (breakpoint_addr); 2676af245d11STodd Fiala if (error.Fail ()) 2677af245d11STodd Fiala { 2678af245d11STodd Fiala if (log) 2679b9cc0c75SPavel Labath log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 ": failed to set PC: %s", __FUNCTION__, GetID(), thread.GetID(), error.AsCString ()); 2680af245d11STodd Fiala return error; 2681af245d11STodd Fiala } 2682af245d11STodd Fiala 2683af245d11STodd Fiala return error; 2684af245d11STodd Fiala } 2685fa03ad2eSChaoren Lin 26867cb18bf5STamas Berghammer Error 26877cb18bf5STamas Berghammer NativeProcessLinux::GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) 26887cb18bf5STamas Berghammer { 26897cb18bf5STamas Berghammer FileSpec module_file_spec(module_path, true); 26907cb18bf5STamas Berghammer 2691162fb8e8SPavel Labath bool found = false; 26927cb18bf5STamas Berghammer file_spec.Clear(); 2693162fb8e8SPavel Labath ProcFileReader::ProcessLineByLine(GetID(), "maps", 2694162fb8e8SPavel Labath [&] (const std::string &line) 2695162fb8e8SPavel Labath { 2696162fb8e8SPavel Labath SmallVector<StringRef, 16> columns; 2697162fb8e8SPavel Labath StringRef(line).split(columns, " ", -1, false); 2698162fb8e8SPavel Labath if (columns.size() < 6) 2699162fb8e8SPavel Labath return true; // continue searching 2700162fb8e8SPavel Labath 2701162fb8e8SPavel Labath FileSpec this_file_spec(columns[5].str().c_str(), false); 2702162fb8e8SPavel Labath if (this_file_spec.GetFilename() != module_file_spec.GetFilename()) 2703162fb8e8SPavel Labath return true; // continue searching 2704162fb8e8SPavel Labath 2705162fb8e8SPavel Labath file_spec = this_file_spec; 2706162fb8e8SPavel Labath found = true; 2707162fb8e8SPavel Labath return false; // we are done 2708162fb8e8SPavel Labath }); 2709162fb8e8SPavel Labath 2710162fb8e8SPavel Labath if (! found) 27117cb18bf5STamas Berghammer return Error("Module file (%s) not found in /proc/%" PRIu64 "/maps file!", 27127cb18bf5STamas Berghammer module_file_spec.GetFilename().AsCString(), GetID()); 2713162fb8e8SPavel Labath 2714162fb8e8SPavel Labath return Error(); 27157cb18bf5STamas Berghammer } 2716c076559aSPavel Labath 27175eb721edSPavel Labath Error 2718783bfc8cSTamas Berghammer NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr) 2719783bfc8cSTamas Berghammer { 2720783bfc8cSTamas Berghammer load_addr = LLDB_INVALID_ADDRESS; 2721783bfc8cSTamas Berghammer Error error = ProcFileReader::ProcessLineByLine (GetID (), "maps", 2722783bfc8cSTamas Berghammer [&] (const std::string &line) -> bool 2723783bfc8cSTamas Berghammer { 2724783bfc8cSTamas Berghammer StringRef maps_row(line); 2725783bfc8cSTamas Berghammer 2726783bfc8cSTamas Berghammer SmallVector<StringRef, 16> maps_columns; 2727783bfc8cSTamas Berghammer maps_row.split(maps_columns, StringRef(" "), -1, false); 2728783bfc8cSTamas Berghammer 2729783bfc8cSTamas Berghammer if (maps_columns.size() < 6) 2730783bfc8cSTamas Berghammer { 2731783bfc8cSTamas Berghammer // Return true to continue reading the proc file 2732783bfc8cSTamas Berghammer return true; 2733783bfc8cSTamas Berghammer } 2734783bfc8cSTamas Berghammer 2735783bfc8cSTamas Berghammer if (maps_columns[5] == file_name) 2736783bfc8cSTamas Berghammer { 2737783bfc8cSTamas Berghammer StringExtractor addr_extractor(maps_columns[0].str().c_str()); 2738783bfc8cSTamas Berghammer load_addr = addr_extractor.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); 2739783bfc8cSTamas Berghammer 2740783bfc8cSTamas Berghammer // Return false to stop reading the proc file further 2741783bfc8cSTamas Berghammer return false; 2742783bfc8cSTamas Berghammer } 2743783bfc8cSTamas Berghammer 2744783bfc8cSTamas Berghammer // Return true to continue reading the proc file 2745783bfc8cSTamas Berghammer return true; 2746783bfc8cSTamas Berghammer }); 2747783bfc8cSTamas Berghammer return error; 2748783bfc8cSTamas Berghammer } 2749783bfc8cSTamas Berghammer 2750f9077782SPavel Labath NativeThreadLinuxSP 2751f9077782SPavel Labath NativeProcessLinux::GetThreadByID(lldb::tid_t tid) 2752f9077782SPavel Labath { 2753f9077782SPavel Labath return std::static_pointer_cast<NativeThreadLinux>(NativeProcessProtocol::GetThreadByID(tid)); 2754f9077782SPavel Labath } 2755f9077782SPavel Labath 2756783bfc8cSTamas Berghammer Error 2757b9cc0c75SPavel Labath NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, lldb::StateType state, int signo) 2758c076559aSPavel Labath { 27595eb721edSPavel Labath Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD); 27605eb721edSPavel Labath 27611dbc6c9cSPavel Labath if (log) 27620e1d729bSPavel Labath log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", 2763b9cc0c75SPavel Labath __FUNCTION__, thread.GetID()); 2764c076559aSPavel Labath 2765c076559aSPavel Labath // Before we do the resume below, first check if we have a pending 2766108c325dSPavel Labath // stop notification that is currently waiting for 27670e1d729bSPavel Labath // all threads to stop. This is potentially a buggy situation since 2768c076559aSPavel Labath // we're ostensibly waiting for threads to stop before we send out the 2769c076559aSPavel Labath // pending notification, and here we are resuming one before we send 2770c076559aSPavel Labath // out the pending stop notification. 27710e1d729bSPavel Labath if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && log) 2772c076559aSPavel Labath { 2773b9cc0c75SPavel Labath log->Printf("NativeProcessLinux::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that is actively waiting for this thread to stop. Valid sequence of events?", __FUNCTION__, thread.GetID(), m_pending_notification_tid); 2774c076559aSPavel Labath } 2775c076559aSPavel Labath 2776c076559aSPavel Labath // Request a resume. We expect this to be synchronous and the system 2777c076559aSPavel Labath // to reflect it is running after this completes. 27780e1d729bSPavel Labath switch (state) 2779c076559aSPavel Labath { 27800e1d729bSPavel Labath case eStateRunning: 27810e1d729bSPavel Labath { 2782605b51b8SPavel Labath const auto resume_result = thread.Resume(signo); 27830e1d729bSPavel Labath if (resume_result.Success()) 27840e1d729bSPavel Labath SetState(eStateRunning, true); 27850e1d729bSPavel Labath return resume_result; 2786c076559aSPavel Labath } 27870e1d729bSPavel Labath case eStateStepping: 27880e1d729bSPavel Labath { 2789605b51b8SPavel Labath const auto step_result = thread.SingleStep(signo); 27900e1d729bSPavel Labath if (step_result.Success()) 27910e1d729bSPavel Labath SetState(eStateRunning, true); 27920e1d729bSPavel Labath return step_result; 27930e1d729bSPavel Labath } 27940e1d729bSPavel Labath default: 27950e1d729bSPavel Labath if (log) 27960e1d729bSPavel Labath log->Printf("NativeProcessLinux::%s Unhandled state %s.", 27970e1d729bSPavel Labath __FUNCTION__, StateAsCString(state)); 27980e1d729bSPavel Labath llvm_unreachable("Unhandled state for resume"); 27990e1d729bSPavel Labath } 2800c076559aSPavel Labath } 2801c076559aSPavel Labath 2802c076559aSPavel Labath //===----------------------------------------------------------------------===// 2803c076559aSPavel Labath 2804c076559aSPavel Labath void 2805337f3eb9SPavel Labath NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) 2806c076559aSPavel Labath { 28075eb721edSPavel Labath Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD); 2808c076559aSPavel Labath 28095eb721edSPavel Labath if (log) 2810c076559aSPavel Labath { 28115eb721edSPavel Labath log->Printf("NativeProcessLinux::%s about to process event: (triggering_tid: %" PRIu64 ")", 2812c076559aSPavel Labath __FUNCTION__, triggering_tid); 2813c076559aSPavel Labath } 2814c076559aSPavel Labath 28150e1d729bSPavel Labath m_pending_notification_tid = triggering_tid; 28160e1d729bSPavel Labath 28170e1d729bSPavel Labath // Request a stop for all the thread stops that need to be stopped 28180e1d729bSPavel Labath // and are not already known to be stopped. 28190e1d729bSPavel Labath for (const auto &thread_sp: m_threads) 28200e1d729bSPavel Labath { 28210e1d729bSPavel Labath if (StateIsRunningState(thread_sp->GetState())) 28220e1d729bSPavel Labath static_pointer_cast<NativeThreadLinux>(thread_sp)->RequestStop(); 28230e1d729bSPavel Labath } 28240e1d729bSPavel Labath 28250e1d729bSPavel Labath SignalIfAllThreadsStopped(); 2826c076559aSPavel Labath 28275eb721edSPavel Labath if (log) 2828c076559aSPavel Labath { 28295eb721edSPavel Labath log->Printf("NativeProcessLinux::%s event processing done", __FUNCTION__); 2830c076559aSPavel Labath } 2831c076559aSPavel Labath } 2832c076559aSPavel Labath 2833c076559aSPavel Labath void 28349eb1ecb9SPavel Labath NativeProcessLinux::SignalIfAllThreadsStopped() 2835c076559aSPavel Labath { 28360e1d729bSPavel Labath if (m_pending_notification_tid == LLDB_INVALID_THREAD_ID) 28370e1d729bSPavel Labath return; // No pending notification. Nothing to do. 28380e1d729bSPavel Labath 28390e1d729bSPavel Labath for (const auto &thread_sp: m_threads) 2840c076559aSPavel Labath { 28410e1d729bSPavel Labath if (StateIsRunningState(thread_sp->GetState())) 28420e1d729bSPavel Labath return; // Some threads are still running. Don't signal yet. 28430e1d729bSPavel Labath } 28440e1d729bSPavel Labath 28450e1d729bSPavel Labath // We have a pending notification and all threads have stopped. 28469eb1ecb9SPavel Labath Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); 28479eb1ecb9SPavel Labath 28489eb1ecb9SPavel Labath // Clear any temporary breakpoints we used to implement software single stepping. 28499eb1ecb9SPavel Labath for (const auto &thread_info: m_threads_stepping_with_breakpoint) 28509eb1ecb9SPavel Labath { 28519eb1ecb9SPavel Labath Error error = RemoveBreakpoint (thread_info.second); 28529eb1ecb9SPavel Labath if (error.Fail()) 28539eb1ecb9SPavel Labath if (log) 28549eb1ecb9SPavel Labath log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " remove stepping breakpoint: %s", 28559eb1ecb9SPavel Labath __FUNCTION__, thread_info.first, error.AsCString()); 28569eb1ecb9SPavel Labath } 28579eb1ecb9SPavel Labath m_threads_stepping_with_breakpoint.clear(); 28589eb1ecb9SPavel Labath 28599eb1ecb9SPavel Labath // Notify the delegate about the stop 28600e1d729bSPavel Labath SetCurrentThreadID(m_pending_notification_tid); 2861ed89c7feSPavel Labath SetState(StateType::eStateStopped, true); 28620e1d729bSPavel Labath m_pending_notification_tid = LLDB_INVALID_THREAD_ID; 2863c076559aSPavel Labath } 2864c076559aSPavel Labath 2865c076559aSPavel Labath void 2866f9077782SPavel Labath NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) 2867c076559aSPavel Labath { 28681dbc6c9cSPavel Labath Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD); 28691dbc6c9cSPavel Labath 28701dbc6c9cSPavel Labath if (log) 2871f9077782SPavel Labath log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, thread.GetID()); 28721dbc6c9cSPavel Labath 2873f9077782SPavel Labath if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && StateIsRunningState(thread.GetState())) 2874c076559aSPavel Labath { 2875c076559aSPavel Labath // We will need to wait for this new thread to stop as well before firing the 2876c076559aSPavel Labath // notification. 2877f9077782SPavel Labath thread.RequestStop(); 2878c076559aSPavel Labath } 2879c076559aSPavel Labath } 2880068f8a7eSTamas Berghammer 288119cbe96aSPavel Labath void 288219cbe96aSPavel Labath NativeProcessLinux::SigchldHandler() 2883068f8a7eSTamas Berghammer { 288419cbe96aSPavel Labath Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 288519cbe96aSPavel Labath // Process all pending waitpid notifications. 288619cbe96aSPavel Labath while (true) 288719cbe96aSPavel Labath { 288819cbe96aSPavel Labath int status = -1; 288919cbe96aSPavel Labath ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG); 289019cbe96aSPavel Labath 289119cbe96aSPavel Labath if (wait_pid == 0) 289219cbe96aSPavel Labath break; // We are done. 289319cbe96aSPavel Labath 289419cbe96aSPavel Labath if (wait_pid == -1) 289519cbe96aSPavel Labath { 289619cbe96aSPavel Labath if (errno == EINTR) 289719cbe96aSPavel Labath continue; 289819cbe96aSPavel Labath 289919cbe96aSPavel Labath Error error(errno, eErrorTypePOSIX); 290019cbe96aSPavel Labath if (log) 290119cbe96aSPavel Labath log->Printf("NativeProcessLinux::%s waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG) failed: %s", 290219cbe96aSPavel Labath __FUNCTION__, error.AsCString()); 290319cbe96aSPavel Labath break; 290419cbe96aSPavel Labath } 290519cbe96aSPavel Labath 290619cbe96aSPavel Labath bool exited = false; 290719cbe96aSPavel Labath int signal = 0; 290819cbe96aSPavel Labath int exit_status = 0; 290919cbe96aSPavel Labath const char *status_cstr = nullptr; 291019cbe96aSPavel Labath if (WIFSTOPPED(status)) 291119cbe96aSPavel Labath { 291219cbe96aSPavel Labath signal = WSTOPSIG(status); 291319cbe96aSPavel Labath status_cstr = "STOPPED"; 291419cbe96aSPavel Labath } 291519cbe96aSPavel Labath else if (WIFEXITED(status)) 291619cbe96aSPavel Labath { 291719cbe96aSPavel Labath exit_status = WEXITSTATUS(status); 291819cbe96aSPavel Labath status_cstr = "EXITED"; 291919cbe96aSPavel Labath exited = true; 292019cbe96aSPavel Labath } 292119cbe96aSPavel Labath else if (WIFSIGNALED(status)) 292219cbe96aSPavel Labath { 292319cbe96aSPavel Labath signal = WTERMSIG(status); 292419cbe96aSPavel Labath status_cstr = "SIGNALED"; 292519cbe96aSPavel Labath if (wait_pid == static_cast< ::pid_t>(GetID())) { 292619cbe96aSPavel Labath exited = true; 292719cbe96aSPavel Labath exit_status = -1; 292819cbe96aSPavel Labath } 292919cbe96aSPavel Labath } 293019cbe96aSPavel Labath else 293119cbe96aSPavel Labath status_cstr = "(\?\?\?)"; 293219cbe96aSPavel Labath 293319cbe96aSPavel Labath if (log) 293419cbe96aSPavel Labath log->Printf("NativeProcessLinux::%s: waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG)" 293519cbe96aSPavel Labath "=> pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", 293619cbe96aSPavel Labath __FUNCTION__, wait_pid, status, status_cstr, signal, exit_status); 293719cbe96aSPavel Labath 293819cbe96aSPavel Labath MonitorCallback (wait_pid, exited, signal, exit_status); 293919cbe96aSPavel Labath } 2940068f8a7eSTamas Berghammer } 2941068f8a7eSTamas Berghammer 2942068f8a7eSTamas Berghammer // Wrapper for ptrace to catch errors and log calls. 2943068f8a7eSTamas Berghammer // Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) 29444a9babb2SPavel Labath Error 29454a9babb2SPavel Labath NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, long *result) 2946068f8a7eSTamas Berghammer { 29474a9babb2SPavel Labath Error error; 29484a9babb2SPavel Labath long int ret; 2949068f8a7eSTamas Berghammer 2950068f8a7eSTamas Berghammer Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); 2951068f8a7eSTamas Berghammer 2952068f8a7eSTamas Berghammer PtraceDisplayBytes(req, data, data_size); 2953068f8a7eSTamas Berghammer 2954068f8a7eSTamas Berghammer errno = 0; 2955068f8a7eSTamas Berghammer if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) 29564a9babb2SPavel Labath ret = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); 2957068f8a7eSTamas Berghammer else 29584a9babb2SPavel Labath ret = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); 2959068f8a7eSTamas Berghammer 29604a9babb2SPavel Labath if (ret == -1) 2961068f8a7eSTamas Berghammer error.SetErrorToErrno(); 2962068f8a7eSTamas Berghammer 29634a9babb2SPavel Labath if (result) 29644a9babb2SPavel Labath *result = ret; 29654a9babb2SPavel Labath 2966068f8a7eSTamas Berghammer if (log) 29674a9babb2SPavel Labath log->Printf("ptrace(%d, %" PRIu64 ", %p, %p, %zu)=%lX", req, pid, addr, data, data_size, ret); 2968068f8a7eSTamas Berghammer 2969068f8a7eSTamas Berghammer PtraceDisplayBytes(req, data, data_size); 2970068f8a7eSTamas Berghammer 2971068f8a7eSTamas Berghammer if (log && error.GetError() != 0) 2972068f8a7eSTamas Berghammer { 2973068f8a7eSTamas Berghammer const char* str; 2974068f8a7eSTamas Berghammer switch (error.GetError()) 2975068f8a7eSTamas Berghammer { 2976068f8a7eSTamas Berghammer case ESRCH: str = "ESRCH"; break; 2977068f8a7eSTamas Berghammer case EINVAL: str = "EINVAL"; break; 2978068f8a7eSTamas Berghammer case EBUSY: str = "EBUSY"; break; 2979068f8a7eSTamas Berghammer case EPERM: str = "EPERM"; break; 2980068f8a7eSTamas Berghammer default: str = error.AsCString(); 2981068f8a7eSTamas Berghammer } 2982068f8a7eSTamas Berghammer log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str); 2983068f8a7eSTamas Berghammer } 2984068f8a7eSTamas Berghammer 29854a9babb2SPavel Labath return error; 2986068f8a7eSTamas Berghammer } 2987