Index: source/Plugins/Process/Linux/NativeProcessLinux.h =================================================================== --- source/Plugins/Process/Linux/NativeProcessLinux.h +++ source/Plugins/Process/Linux/NativeProcessLinux.h @@ -156,18 +156,12 @@ /// launching a child process. struct LaunchArgs { - LaunchArgs(Module *module, - char const **argv, - char const **envp, - const FileSpec &stdin_file_spec, - const FileSpec &stdout_file_spec, - const FileSpec &stderr_file_spec, - const FileSpec &working_dir, - const ProcessLaunchInfo &launch_info); + LaunchArgs(char const **argv, char const **envp, const FileSpec &stdin_file_spec, + const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec, const FileSpec &working_dir, + const ProcessLaunchInfo &launch_info); ~LaunchArgs(); - Module *m_module; // The executable image to launch. char const **m_argv; // Process arguments. char const **m_envp; // Process environment. const FileSpec m_stdin_file_spec; // Redirect stdin if not empty. @@ -189,7 +183,6 @@ void LaunchInferior ( MainLoop &mainloop, - Module *module, char const *argv[], char const *envp[], const FileSpec &stdin_file_spec, Index: source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -25,24 +25,20 @@ // Other libraries and framework includes #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Error.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/State.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/Host.h" #include "lldb/Host/common/NativeBreakpoint.h" #include "lldb/Host/common/NativeRegisterContext.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/ThreadLauncher.h" -#include "lldb/Target/Platform.h" -#include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Target/Target.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/PseudoTerminal.h" #include "lldb/Utility/StringExtractor.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "NativeRegisterContextLinux.h" #include "NativeThreadLinux.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "ProcFileReader.h" #include "Procfs.h" @@ -110,34 +106,6 @@ namespace { - Error - ResolveProcessArchitecture (lldb::pid_t pid, Platform &platform, ArchSpec &arch) - { - // Grab process info for the running process. - ProcessInstanceInfo process_info; - if (!platform.GetProcessInfo (pid, process_info)) - return Error("failed to get process info"); - - // Resolve the executable module. - ModuleSP exe_module_sp; - ModuleSpec exe_module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture()); - FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths ()); - Error error = platform.ResolveExecutable( - exe_module_spec, - exe_module_sp, - executable_search_paths.GetSize () ? &executable_search_paths : NULL); - - if (!error.Success ()) - return error; - - // Check if we've got our architecture from the exe_module. - arch = exe_module_sp->GetArchitecture (); - if (arch.IsValid ()) - return Error(); - else - return Error("failed to retrieve a valid architecture from the exe module"); - } - void DisplayBytes (StreamString &s, void *bytes, uint32_t count) { @@ -238,16 +206,10 @@ return error; } -NativeProcessLinux::LaunchArgs::LaunchArgs(Module *module, - char const **argv, - char const **envp, - const FileSpec &stdin_file_spec, - const FileSpec &stdout_file_spec, - const FileSpec &stderr_file_spec, - const FileSpec &working_dir, - const ProcessLaunchInfo &launch_info) - : m_module(module), - m_argv(argv), +NativeProcessLinux::LaunchArgs::LaunchArgs(char const **argv, char const **envp, const FileSpec &stdin_file_spec, + const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec, + const FileSpec &working_dir, const ProcessLaunchInfo &launch_info) + : m_argv(argv), m_envp(envp), m_stdin_file_spec(stdin_file_spec), m_stdout_file_spec(stdout_file_spec), @@ -272,16 +234,7 @@ NativeProcessProtocolSP &native_process_sp) { Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - lldb::ModuleSP exe_module_sp; - PlatformSP platform_sp (Platform::GetHostPlatform ()); - Error error = platform_sp->ResolveExecutable( - ModuleSpec(launch_info.GetExecutableFile(), launch_info.GetArchitecture()), - exe_module_sp, - nullptr); - - if (! error.Success()) - return error; + Error error; // Verify the working directory is valid if one was specified. FileSpec working_dir{launch_info.GetWorkingDirectory()}; @@ -356,7 +309,6 @@ std::static_pointer_cast (native_process_sp)->LaunchInferior ( mainloop, - exe_module_sp.get(), launch_info.GetArguments ().GetConstArgumentVector (), launch_info.GetEnvironmentEntries ().GetConstArgumentVector (), stdin_file_spec, @@ -390,26 +342,12 @@ if (log && log->GetMask ().Test (POSIX_LOG_VERBOSE)) log->Printf ("NativeProcessLinux::%s(pid = %" PRIi64 ")", __FUNCTION__, pid); - // Grab the current platform architecture. This should be Linux, - // since this code is only intended to run on a Linux host. - PlatformSP platform_sp (Platform::GetHostPlatform ()); - if (!platform_sp) - return Error("failed to get a valid default platform"); - - // Retrieve the architecture for the running process. - ArchSpec process_arch; - Error error = ResolveProcessArchitecture (pid, *platform_sp.get (), process_arch); - if (!error.Success ()) - return error; - std::shared_ptr native_process_linux_sp (new NativeProcessLinux ()); if (!native_process_linux_sp->RegisterNativeDelegate (native_delegate)) - { - error.SetErrorStringWithFormat ("failed to register the native delegate"); - return error; - } + return Error("Failed to register the native delegate"); + Error error; native_process_linux_sp->AttachToInferior (mainloop, pid, error); if (!error.Success ()) return error; @@ -434,7 +372,6 @@ void NativeProcessLinux::LaunchInferior ( MainLoop &mainloop, - Module *module, const char *argv[], const char *envp[], const FileSpec &stdin_file_spec, @@ -449,18 +386,10 @@ if (! m_sigchld_handle) return; - if (module) - m_arch = module->GetArchitecture (); - SetState (eStateLaunching); std::unique_ptr args( - new LaunchArgs(module, argv, envp, - stdin_file_spec, - stdout_file_spec, - stderr_file_spec, - working_dir, - launch_info)); + new LaunchArgs(argv, envp, stdin_file_spec, stdout_file_spec, stderr_file_spec, working_dir, launch_info)); Launch(args.get(), error); } @@ -477,44 +406,18 @@ if (! m_sigchld_handle) return; - // We can use the Host for everything except the ResolveExecutable portion. - PlatformSP platform_sp = Platform::GetHostPlatform (); - if (!platform_sp) - { - if (log) - log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 "): no default platform set", __FUNCTION__, pid); - error.SetErrorString ("no default platform available"); - return; - } - - // Gather info about the process. - ProcessInstanceInfo process_info; - if (!platform_sp->GetProcessInfo (pid, process_info)) - { - if (log) - log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 "): failed to get process info", __FUNCTION__, pid); - error.SetErrorString ("failed to get process info"); - return; - } - - // Resolve the executable module - ModuleSP exe_module_sp; - FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); - ModuleSpec exe_module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture()); - error = platform_sp->ResolveExecutable(exe_module_spec, exe_module_sp, - executable_search_paths.GetSize() ? &executable_search_paths : NULL); - if (!error.Success()) - return; - - // Set the architecture to the exe architecture. - m_arch = exe_module_sp->GetArchitecture(); - if (log) - log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ") detected architecture %s", __FUNCTION__, pid, m_arch.GetArchitectureName ()); m_pid = pid; SetState(eStateAttaching); Attach(pid, error); + m_arch = static_pointer_cast(GetThreadByID(pid)->GetRegisterContext()) + ->GetRegisterInfoInterface() + .GetTargetArchitecture(); + + if (log) + log->Printf("NativeProcessLinux::%s (pid = %" PRIi64 ") detected architecture %s", __FUNCTION__, pid, + m_arch.GetArchitectureName()); } ::pid_t @@ -763,6 +666,10 @@ thread_sp->SetStoppedBySignal(SIGSTOP); ThreadWasCreated(*thread_sp); + m_arch = static_pointer_cast(thread_sp->GetRegisterContext()) + ->GetRegisterInfoInterface() + .GetTargetArchitecture(); + // Let our process instance know the thread has stopped. SetCurrentThreadID (thread_sp->GetID ()); SetState (StateType::eStateStopped); @@ -2165,49 +2072,8 @@ lldb::addr_t NativeProcessLinux::GetSharedLibraryInfoAddress () { -#if 1 // punt on this for now return LLDB_INVALID_ADDRESS; -#else - // Return the image info address for the exe module -#if 1 - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - ModuleSP module_sp; - Error error = GetExeModuleSP (module_sp); - if (error.Fail ()) - { - if (log) - log->Warning ("NativeProcessLinux::%s failed to retrieve exe module: %s", __FUNCTION__, error.AsCString ()); - return LLDB_INVALID_ADDRESS; - } - - if (module_sp == nullptr) - { - if (log) - log->Warning ("NativeProcessLinux::%s exe module returned was NULL", __FUNCTION__); - return LLDB_INVALID_ADDRESS; - } - - ObjectFileSP object_file_sp = module_sp->GetObjectFile (); - if (object_file_sp == nullptr) - { - if (log) - log->Warning ("NativeProcessLinux::%s exe module returned a NULL object file", __FUNCTION__); - return LLDB_INVALID_ADDRESS; - } - - return obj_file_sp->GetImageInfoAddress(); -#else - Target *target = &GetTarget(); - ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(target); - - if (addr.IsValid()) - return addr.GetLoadAddress(target); - return LLDB_INVALID_ADDRESS; -#endif -#endif // punt on this for now } size_t Index: source/Plugins/Process/Linux/NativeRegisterContextLinux.h =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux.h +++ source/Plugins/Process/Linux/NativeRegisterContextLinux.h @@ -10,6 +10,7 @@ #ifndef lldb_NativeRegisterContextLinux_h #define lldb_NativeRegisterContextLinux_h +#include "lldb/Host/HostInfo.h" #include "lldb/Host/common/NativeRegisterContextRegisterInfo.h" #include "lldb/Host/common/NativeThreadProtocol.h" @@ -29,12 +30,13 @@ // instance of the host specific NativeRegisterContextLinux. The implementations can't collide // as only one NativeRegisterContextLinux_* variant should be compiled into the final // executable. - static NativeRegisterContextLinux* - CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + static NativeRegisterContextLinux * + CreateHostNativeRegisterContextLinux(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx); protected: + static ArchSpec + GetThreadArchitecture(lldb::tid_t tid, size_t sizeof_native_regs_struct); + lldb::ByteOrder GetByteOrder() const; Index: source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp @@ -9,16 +9,47 @@ #include "NativeRegisterContextLinux.h" +#include + #include "lldb/Core/RegisterValue.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeThreadProtocol.h" #include "lldb/Host/linux/Ptrace.h" +#include "lldb/Host/linux/Uio.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" using namespace lldb_private; using namespace lldb_private::process_linux; +ArchSpec +NativeRegisterContextLinux::GetThreadArchitecture(lldb::tid_t tid, size_t sizeof_native_regs_struct) +{ + // This relies on the fact that the size of the set that PTRACE_GETREGSET will return depends + // on the bitness of the target process. If the target process has the same bitness as us, we + // will get the expected number of bytes. If it returns less, we it means we are debugging a + // 32-bit process with a 64-bit server (the opposite is not possible). + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS)); + + std::unique_ptr regs(new char[sizeof_native_regs_struct]); + struct iovec ioVec; + ioVec.iov_base = regs.get(); + ioVec.iov_len = sizeof_native_regs_struct; + int regset = NT_PRSTATUS; + Error error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, sizeof_native_regs_struct); + HostInfo::ArchitectureKind kind = HostInfo::eArchKindDefault; // same bitness this process + // The ptrace call should only fail if the process has gone away (via SIGKILL). In that + // case, it doesn't matter which architecture it was. + if (error.Success() && ioVec.iov_len < sizeof_native_regs_struct) + kind = HostInfo::eArchKind32; // 32-bit process on a 64-bit server + if (log) + log->Printf("NativeRegisterContextLinux::%s(tid: %" PRIu64 + ", sizeof_native_regs_struct: %zd) iov_len = %zd => %s", + __FUNCTION__, tid, sizeof_native_regs_struct, ioVec.iov_len, + HostInfo::GetArchitecture(kind).GetArchitectureName()); + return HostInfo::GetArchitecture(kind); +} + NativeRegisterContextLinux::NativeRegisterContextLinux(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p) : Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h @@ -23,9 +23,7 @@ class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux { public: - NativeRegisterContextLinux_arm (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeRegisterContextLinux_arm(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx); uint32_t GetRegisterSetCount () const override; Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp @@ -15,6 +15,7 @@ #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" +#include "lldb/Host/HostInfo.h" #include "Plugins/Process/Linux/Procfs.h" #include "Plugins/Process/Utility/RegisterContextLinux_arm.h" @@ -175,24 +176,20 @@ #if defined(__arm__) -NativeRegisterContextLinux* -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, +NativeRegisterContextLinux * +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx); + return new NativeRegisterContextLinux_arm(native_thread, concrete_frame_idx); } #endif // defined(__arm__) -NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) : - NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm(target_arch)) +NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm(NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + new RegisterContextLinux_arm(HostInfo::GetArchitecture(HostInfo::eArchKind32))) { - switch (target_arch.GetMachine()) - { - case llvm::Triple::arm: m_reg_info.num_registers = k_num_registers_arm; m_reg_info.num_gpr_registers = k_num_gpr_registers_arm; m_reg_info.num_fpr_registers = k_num_fpr_registers_arm; @@ -202,11 +199,6 @@ m_reg_info.first_fpr_v = fpu_s0_arm; m_reg_info.last_fpr_v = fpu_s31_arm; m_reg_info.gpr_flags = gpr_cpsr_arm; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } ::memset(&m_fpr, 0, sizeof (m_fpr)); ::memset(&m_gpr_arm, 0, sizeof (m_gpr_arm)); Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -23,9 +23,7 @@ class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux { public: - NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeRegisterContextLinux_arm64(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx); uint32_t GetRegisterSetCount () const override; Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -141,18 +141,19 @@ { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } }; -NativeRegisterContextLinux* -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, +NativeRegisterContextLinux * +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) { Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS); + ArchSpec target_arch = GetThreadArchitecture(native_thread.GetID(), sizeof(struct user_regs_struct)); + switch (target_arch.GetMachine()) { case llvm::Triple::arm: - return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx); + return new NativeRegisterContextLinux_arm(native_thread, concrete_frame_idx); case llvm::Triple::aarch64: - return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx); + return new NativeRegisterContextLinux_arm64(native_thread, concrete_frame_idx); default: if (log) log->Printf("NativeRegisterContextLinux::%s() have no register context for architecture: %s\n", __FUNCTION__, @@ -161,14 +162,11 @@ } } -NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) : - NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm64(target_arch)) +NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + new RegisterContextLinux_arm64(HostInfo::GetArchitecture(HostInfo::eArchKind64))) { - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: m_reg_info.num_registers = k_num_registers_arm64; m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; @@ -178,11 +176,6 @@ m_reg_info.first_fpr_v = fpu_v0_arm64; m_reg_info.last_fpr_v = fpu_v31_arm64; m_reg_info.gpr_flags = gpr_cpsr_arm64; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } ::memset(&m_fpr, 0, sizeof (m_fpr)); ::memset(&m_gpr_arm64, 0, sizeof (m_gpr_arm64)); Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h @@ -26,9 +26,7 @@ class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux { public: - NativeRegisterContextLinux_mips64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeRegisterContextLinux_mips64(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx); uint32_t GetRegisterSetCount () const override; @@ -131,6 +129,9 @@ size_t GetFPRSize() override { return sizeof(FPR_linux_mips); } + static ArchSpec + GetThreadArchitecture(lldb::tid_t tid); + private: // Info about register ranges. struct RegInfo @@ -157,6 +158,9 @@ lldb::addr_t hw_addr_map[MAX_NUM_WP]; IOVEC_mips m_iovec; + + static RegisterInfoInterface * + CreateRegisterInfoInterface(NativeThreadProtocol &native_thread); }; } // namespace process_linux Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -15,19 +15,23 @@ // C++ Includes // Other libraries and framework includes +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Error.h" -#include "lldb/Core/RegisterValue.h" #include "lldb/Core/Log.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Host/HostInfo.h" +#include "lldb/Core/RegisterValue.h" #include "lldb/Host/Host.h" -#include "lldb/Core/EmulateInstruction.h" +#include "lldb/Host/HostInfo.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-private-enumerations.h" + #include "Plugins/Process/Linux/NativeProcessLinux.h" #include "Plugins/Process/Linux/Procfs.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "Plugins/Process/Utility/RegisterContextLinux_mips.h" +#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" + #define NT_MIPS_MSA 0x600 #define CONFIG5_FRE (1 << 8) #define SR_FR (1 << 26) @@ -397,12 +401,11 @@ } // end of anonymous namespace -NativeRegisterContextLinux* -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, +NativeRegisterContextLinux * +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_mips64(target_arch, native_thread, concrete_frame_idx); + return new NativeRegisterContextLinux_mips64(native_thread, concrete_frame_idx); } #define REG_CONTEXT_SIZE (GetRegisterInfoInterface ().GetGPRSize () + sizeof(FPR_linux_mips) + sizeof(MSA_linux_mips)) @@ -411,9 +414,63 @@ // NativeRegisterContextLinux_mips64 members. // ---------------------------------------------------------------------------- -static RegisterInfoInterface* -CreateRegisterInfoInterface(const ArchSpec& target_arch) +// This is a specialization of the GetThreadArchitecture function in NativeRegisterContextLinux. +// It is necessary because the required syscall (ptrace(GETREGSET, NT_PRSTATUS)) was not +// available until linux 3.13. It can be removed in favour of the generic version once linux +// kernels below 3.13 become obsolete. +ArchSpec +NativeRegisterContextLinux_mips64::GetThreadArchitecture(lldb::tid_t tid) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS)); + + ArchSpec arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); + lldb::DataBufferSP auxv_sp = Host::GetAuxvData(tid); + if (!auxv_sp) + { + if (log) + log->Printf("NativeRegisterContextLinux_mips64::%s(tid: %" PRIu64 + ") unable to read auxv. Has the process died?", + __FUNCTION__, tid); + return arch; + } + + // The auxiliary vector consists of a sequence of key-value pairs, where key and value are of + // the pointer size for the architecture that the process is running on. We can use this to + // detect the process architecture. We will try reading the vector as if it were a 64-bit + // process. If it really is a 64-bit process everything will be fine. Now, if it really is a + // 32-bit process, the "value" of the auxv entry will show up in the upper 32 bits of our + // "key" field. We can detect this because normally all key values are small integers (as + // they have to fit in the 32-bit key field). If we find at least one entry with the upper 32 + // key bits set, we can be sure we are dealing with a 32-bit process. All it takes is for the + // process to have one auxv entry with a non-zero value (which it should always have). + struct Auxv + { + uint32_t key_lower; + uint32_t key_upper; + uint64_t value; + }; + static_assert(sizeof(Auxv) == 16, "Unexpected structure size"); + DataExtractor extractor(auxv_sp, arch.GetByteOrder(), 8); + lldb::offset_t offset = 0; + while (const Auxv *entry = reinterpret_cast(extractor.GetData(&offset, sizeof(Auxv)))) + { + if (entry->key_upper) + { + arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); + break; + } + } + if (log) + log->Printf("NativeRegisterContextLinux::%s(tid: %" PRIu64 ") => %s", __FUNCTION__, tid, + arch.GetArchitectureName()); + return arch; +} + +RegisterInfoInterface * +NativeRegisterContextLinux_mips64::CreateRegisterInfoInterface(NativeThreadProtocol &native_thread) +{ + ArchSpec target_arch = GetThreadArchitecture(native_thread.GetID()); + if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) { // 32-bit hosts run with a RegisterContextLinux_mips context. @@ -428,12 +485,11 @@ } } -NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) : - NativeRegisterContextLinux (native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)) +NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64(NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(native_thread)) { - switch (target_arch.GetMachine ()) + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { case llvm::Triple::mips: case llvm::Triple::mipsel: Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h @@ -26,8 +26,7 @@ class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux { public: - NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeRegisterContextLinux_s390x(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx); uint32_t GetRegisterSetCount() const override; Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp @@ -135,45 +135,27 @@ #define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ NativeRegisterContextLinux * -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_s390x(target_arch, native_thread, concrete_frame_idx); + return new NativeRegisterContextLinux_s390x(native_thread, concrete_frame_idx); } // ---------------------------------------------------------------------------- // NativeRegisterContextLinux_s390x members. // ---------------------------------------------------------------------------- -static RegisterInfoInterface * -CreateRegisterInfoInterface(const ArchSpec &target_arch) -{ - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && - "Register setting path assumes this is a 64-bit host"); - return new RegisterContextLinux_s390x(target_arch); -} - -NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, +NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + new RegisterContextLinux_s390x(HostInfo::GetArchitecture(HostInfo::eArchKindDefault))) { - // Set up data about ranges of valid registers. - switch (target_arch.GetMachine()) - { - case llvm::Triple::systemz: m_reg_info.num_registers = k_num_registers_s390x; m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; m_reg_info.last_gpr = k_last_gpr_s390x; m_reg_info.first_fpr = k_first_fpr_s390x; m_reg_info.last_fpr = k_last_fpr_s390x; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } // Clear out the watchpoint state. m_watchpoint_addr = LLDB_INVALID_ADDRESS; Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h @@ -24,9 +24,7 @@ class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux { public: - NativeRegisterContextLinux_x86_64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeRegisterContextLinux_x86_64(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx); uint32_t GetRegisterSetCount () const override; @@ -138,6 +136,9 @@ uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; uint32_t m_fctrl_offset_in_userarea; + static RegisterInfoInterface * + CreateRegisterInfoInterface(NativeThreadProtocol &native_thread); + // Private member methods. bool IsRegisterSetAvailable (uint32_t set_index) const; Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -11,11 +11,12 @@ #include "NativeRegisterContextLinux_x86_64.h" +#include + #include "lldb/Core/Log.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" -#include "lldb/Host/HostInfo.h" #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" @@ -331,21 +332,22 @@ #define NT_PRXFPREG 0x46e62b7f #endif -NativeRegisterContextLinux* -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, +NativeRegisterContextLinux * +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_x86_64(target_arch, native_thread, concrete_frame_idx); + return new NativeRegisterContextLinux_x86_64(native_thread, concrete_frame_idx); } // ---------------------------------------------------------------------------- // NativeRegisterContextLinux_x86_64 members. // ---------------------------------------------------------------------------- -static RegisterInfoInterface* -CreateRegisterInfoInterface(const ArchSpec& target_arch) +RegisterInfoInterface * +NativeRegisterContextLinux_x86_64::CreateRegisterInfoInterface(NativeThreadProtocol &native_thread) { + ArchSpec target_arch = GetThreadArchitecture(native_thread.GetID(), sizeof(struct user_regs_struct)); + if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) { // 32-bit hosts run with a RegisterContextLinux_i386 context. @@ -360,19 +362,18 @@ } } -NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (const ArchSpec& target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) : - NativeRegisterContextLinux (native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)), - m_fpr_type (eFPRTypeNotValid), - m_fpr (), - m_iovec (), - m_ymm_set (), - m_reg_info (), - m_gpr_x86_64 () +NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(native_thread)), + m_fpr_type(eFPRTypeNotValid), + m_fpr(), + m_iovec(), + m_ymm_set(), + m_reg_info(), + m_gpr_x86_64() { // Set up data about ranges of valid registers. - switch (target_arch.GetMachine ()) + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86: m_reg_info.num_registers = k_num_registers_i386; Index: source/Plugins/Process/Linux/NativeThreadLinux.cpp =================================================================== --- source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -158,14 +158,8 @@ if (!m_process_sp) return NativeRegisterContextSP (); - ArchSpec target_arch; - if (!m_process_sp->GetArchitecture (target_arch)) - return NativeRegisterContextSP (); - const uint32_t concrete_frame_idx = 0; - m_reg_context_sp.reset (NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(target_arch, - *this, - concrete_frame_idx)); + m_reg_context_sp.reset(NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(*this, concrete_frame_idx)); return m_reg_context_sp; }