mgorny updated this revision to Diff 372261.
mgorny added a comment.

Rename the file to `_x86.cpp` to future-proof it. Replace`assert()s` with 
explicit skipping, we don't really want to crash on unexpected data in 
`target.xml`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108831/new/

https://reviews.llvm.org/D108831

Files:
  lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext_x86.cpp
  lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py

Index: lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
===================================================================
--- lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
+++ lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
@@ -151,6 +151,26 @@
         self.match("register read flags",
                    ["eflags = 0x94939291"])
 
+        # test pseudo-registers
+        self.match("register read ecx",
+                   ["ecx = 0x04030201"])
+        self.match("register read cx",
+                   ["cx = 0x0201"])
+        self.match("register read ch",
+                   ["ch = 0x02"])
+        self.match("register read cl",
+                   ["cl = 0x01"])
+        self.match("register read r8d",
+                   ["r8d = 0x64636261"])
+        self.match("register read r8w",
+                   ["r8w = 0x6261"])
+        self.match("register read r8l",
+                   ["r8l = 0x61"])
+        self.match("register read mm0",
+                   ["mm0 = 0x0807060504030201"])
+        self.match("register read mm1",
+                   ["mm1 = 0x1817161514131211"])
+
         # both stX and xmmX should be displayed as vectors
         self.match("register read st0",
                    ["st0 = {0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a}"])
@@ -162,3 +182,44 @@
         self.match("register read xmm1",
                    ["xmm1 = {0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 "
                     "0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0}"])
+
+        # test writing into pseudo-registers
+        self.runCmd("register write ecx 0xfffefdfc")
+        reg_data[0] = "fcfdfeff05060708"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read rcx",
+                   ["rcx = 0x08070605fffefdfc"])
+
+        self.runCmd("register write cx 0xfbfa")
+        reg_data[0] = "fafbfeff05060708"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read ecx",
+                   ["ecx = 0xfffefbfa"])
+        self.match("register read rcx",
+                   ["rcx = 0x08070605fffefbfa"])
+
+        self.runCmd("register write ch 0xf9")
+        reg_data[0] = "faf9feff05060708"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read cx",
+                   ["cx = 0xf9fa"])
+        self.match("register read ecx",
+                   ["ecx = 0xfffef9fa"])
+        self.match("register read rcx",
+                   ["rcx = 0x08070605fffef9fa"])
+
+        self.runCmd("register write cl 0xf8")
+        reg_data[0] = "f8f9feff05060708"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read cx",
+                   ["cx = 0xf9f8"])
+        self.match("register read ecx",
+                   ["ecx = 0xfffef9f8"])
+        self.match("register read rcx",
+                   ["rcx = 0x08070605fffef9f8"])
+
+        self.runCmd("register write mm0 0xfffefdfcfbfaf9f8")
+        reg_data[10] = "f8f9fafbfcfdfeff090a"
+        self.assertPacketLogContains(["G" + "".join(reg_data)])
+        self.match("register read st0",
+                   ["st0 = {0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff 0x09 0x0a}"])
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext_x86.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext_x86.cpp
@@ -0,0 +1,189 @@
+//===-- GDBRemoteRegisterContext_x86.cpp ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "GDBRemoteRegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_gdb_remote;
+
+enum PartialGPRRegKind {
+  eRegKind32,
+  eRegKind16,
+  eRegKind8h,
+  eRegKind8l,
+
+  eRegKindCount
+};
+
+struct PartialGPRReg {
+  const char *name;
+
+  // extra storage used for pointers
+  uint32_t value_regs[2];
+  uint32_t invalidate_regs[eRegKindCount];
+};
+
+struct PartialGPRRegSet {
+  const char *reg64;
+  PartialGPRReg r[eRegKindCount];
+};
+
+static std::array<PartialGPRRegSet, 16> partial_gpr_regs = {{
+    {"rax", {{"eax"}, {"ax"}, {"ah"}, {"al"}}},
+    {"rbx", {{"ebx"}, {"bx"}, {"bh"}, {"bl"}}},
+    {"rcx", {{"ecx"}, {"cx"}, {"ch"}, {"cl"}}},
+    {"rdx", {{"edx"}, {"dx"}, {"dh"}, {"dl"}}},
+    {"rdi", {{"edi"}, {"di"}, {nullptr}, {"dil"}}},
+    {"rsi", {{"esi"}, {"si"}, {nullptr}, {"sil"}}},
+    {"rbp", {{"ebp"}, {"bp"}, {nullptr}, {"bpl"}}},
+    {"rsp", {{"esp"}, {"sp"}, {nullptr}, {"spl"}}},
+    {"r8", {{"r8d"}, {"r8w"}, {nullptr}, {"r8l"}}},
+    {"r9", {{"r9d"}, {"r9w"}, {nullptr}, {"r9l"}}},
+    {"r10", {{"r10d"}, {"r10w"}, {nullptr}, {"r10l"}}},
+    {"r11", {{"r11d"}, {"r11w"}, {nullptr}, {"r11l"}}},
+    {"r12", {{"r12d"}, {"r12w"}, {nullptr}, {"r12l"}}},
+    {"r13", {{"r13d"}, {"r13w"}, {nullptr}, {"r13l"}}},
+    {"r14", {{"r14d"}, {"r14w"}, {nullptr}, {"r14l"}}},
+    {"r15", {{"r15d"}, {"r15w"}, {nullptr}, {"r15l"}}},
+}};
+
+static uint32_t partial_gpr_sizes[eRegKindCount] = {4, 2, 1, 1};
+
+struct MMReg {
+  const char *streg;
+  const char *name;
+
+  // extra storage used for pointers
+  uint32_t value_regs[2];
+};
+
+static std::array<MMReg, 16> mm_regs = {{
+    {"st0", "mm0"},
+    {"st1", "mm1"},
+    {"st2", "mm2"},
+    {"st3", "mm3"},
+    {"st4", "mm4"},
+    {"st5", "mm5"},
+    {"st6", "mm6"},
+    {"st7", "mm7"},
+}};
+
+void GDBRemoteDynamicRegisterInfo::PreFinalize_x86_64() {
+  uint32_t max_regnum = 0;
+  uint32_t next_regindex = m_regs.size();
+  for (const RegisterInfo &reg : m_regs)
+    max_regnum = std::max(max_regnum, reg.kinds[eRegisterKindProcessPlugin]);
+
+  ConstString group;
+  group.SetCString("partial registers");
+
+  for (PartialGPRRegSet &partial_regset : partial_gpr_regs) {
+    const RegisterInfo *reg64 = GetRegisterInfo(partial_regset.reg64);
+    if (!reg64 || reg64->byte_size != 8)
+      continue;
+
+    const RegisterInfo *reginfo[eRegKindCount];
+    uint32_t regno[eRegKindCount];
+
+    for (int i = 0; i < eRegKindCount; i++) {
+      if (!partial_regset.r[i].name)
+        continue;
+
+      reginfo[i] = GetRegisterInfo(partial_regset.r[i].name);
+      if (reginfo[i])
+        regno[i] = reginfo[i]->kinds[eRegisterKindProcessPlugin];
+      else
+        regno[i] = ++max_regnum;
+    }
+
+    for (int i = 0; i < eRegKindCount; i++) {
+      if (!partial_regset.r[i].name)
+        continue;
+
+      partial_regset.r[i].value_regs[0] =
+          reg64->kinds[eRegisterKindProcessPlugin];
+      partial_regset.r[i].value_regs[1] = LLDB_INVALID_REGNUM;
+
+      int k = 0;
+      for (int j = 0; j < eRegKindCount; j++) {
+        if (i != j && partial_regset.r[j].name)
+          partial_regset.r[i].invalidate_regs[k++] = regno[j];
+      }
+      partial_regset.r[i].invalidate_regs[k] = LLDB_INVALID_REGNUM;
+
+      struct RegisterInfo new_reg {
+        partial_regset.r[i].name, nullptr, partial_gpr_sizes[i],
+            LLDB_INVALID_INDEX32, reg64->encoding, reg64->format,
+            {
+                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+                LLDB_INVALID_REGNUM, regno[i],
+                next_regindex++,
+            },
+            partial_regset.r[i].value_regs, partial_regset.r[i].invalidate_regs,
+            nullptr, 0
+      };
+
+      ConstString name;
+      ConstString alt_name;
+      name.SetCString(new_reg.name);
+      AddRegister(new_reg, name, alt_name, group);
+    }
+  }
+
+  for (MMReg &mmreg : mm_regs) {
+    const RegisterInfo *streg = GetRegisterInfo(mmreg.streg);
+    if (!streg || streg->byte_size != 10)
+      continue;
+
+    if (GetRegisterInfo(mmreg.name))
+      continue;
+
+    mmreg.value_regs[0] = streg->kinds[eRegisterKindProcessPlugin];
+    mmreg.value_regs[1] = LLDB_INVALID_REGNUM;
+
+    struct RegisterInfo new_reg {
+      mmreg.name, nullptr, 8, LLDB_INVALID_INDEX32, eEncodingUint, eFormatHex,
+          {
+              LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+              ++max_regnum,        next_regindex++,
+          },
+          mmreg.value_regs, nullptr, nullptr, 0
+    };
+
+    ConstString name;
+    ConstString alt_name;
+    name.SetCString(new_reg.name);
+    AddRegister(new_reg, name, alt_name, group);
+  }
+}
+
+void GDBRemoteDynamicRegisterInfo::PostFinalize_x86_64() {
+  for (PartialGPRRegSet &partial_regset : partial_gpr_regs) {
+    if (!partial_regset.r[eRegKind8h].name)
+      continue;
+
+    llvm::StringRef reg8h_name = partial_regset.r[eRegKind8h].name;
+    const RegisterInfo *reg8h = GetRegisterInfo(reg8h_name);
+    const RegisterInfo *reg8l =
+        GetRegisterInfo(partial_regset.r[eRegKind8l].name);
+    if (!reg8h || !reg8l || reg8h->byte_size != 1 || reg8l->byte_size != 1)
+      continue;
+
+    // we currently have no way of indicating offset via value_regs, so we
+    // instead increment it after Finalize() assigns byte offsets
+    if (reg8h->byte_offset == reg8l->byte_offset) {
+      for (auto &reg_info : m_regs) {
+        if (reg_info.name == reg8h_name) {
+          reg_info.byte_offset++;
+          break;
+        }
+      }
+    }
+  }
+}
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -40,6 +40,10 @@
 
   void HardcodeARMRegisters(bool from_scratch);
   bool UpdateARM64SVERegistersInfos(uint64_t vg);
+  void Finalize(const lldb_private::ArchSpec &arch);
+
+  void PreFinalize_x86_64();
+  void PostFinalize_x86_64();
 };
 
 class GDBRemoteRegisterContext : public RegisterContext {
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -1064,3 +1064,28 @@
     }
   }
 }
+
+void GDBRemoteDynamicRegisterInfo::Finalize(const ArchSpec &arch) {
+  if (m_finalized)
+    return;
+
+  switch (arch.GetMachine()) {
+  case llvm::Triple::x86_64:
+    PreFinalize_x86_64();
+    break;
+
+  default:
+    break;
+  }
+
+  DynamicRegisterInfo::Finalize(arch);
+
+  switch (arch.GetMachine()) {
+  case llvm::Triple::x86_64:
+    PostFinalize_x86_64();
+    break;
+
+  default:
+    break;
+  }
+}
Index: lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt
+++ lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt
@@ -26,6 +26,7 @@
   GDBRemoteCommunicationServerLLGS.cpp
   GDBRemoteCommunicationServerPlatform.cpp
   GDBRemoteRegisterContext.cpp
+  GDBRemoteRegisterContext_x86.cpp
   ProcessGDBRemote.cpp
   ProcessGDBRemoteLog.cpp
   ThreadGDBRemote.cpp
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to