labath updated this revision to Diff 60256.
labath added a comment.
This revision is now accepted and ready to land.

Use an auxv-based approach for detecting the architecture in case of mips.


http://reviews.llvm.org/D20368

Files:
  source/Plugins/Process/Linux/NativeProcessLinux.cpp
  source/Plugins/Process/Linux/NativeProcessLinux.h
  source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
  source/Plugins/Process/Linux/NativeRegisterContextLinux.h
  source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
  source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
  source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
  source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
  source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
  source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h
  source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
  source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h
  source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
  source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
  source/Plugins/Process/Linux/NativeThreadLinux.cpp

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;
 }
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 <sys/user.h>
+
 #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/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_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,23 +401,76 @@
 
 } // 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))
 
 // ----------------------------------------------------------------------------
 // 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<const Auxv *>(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_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,34 +141,32 @@
     { "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__,
                             target_arch.GetTriple().getArchName().str().c_str());
             return nullptr;
     }
 }
 
-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_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.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 <elf.h>
+
 #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<char[]> 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, &regset, &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/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<NativeProcessLinux> (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<NativeProcessLinux> 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<LaunchArgs> 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<NativeRegisterContextLinux>(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<NativeRegisterContextLinux>(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
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to