Index: lldb/include/lldb/Target/ABI.h =================================================================== --- lldb/include/lldb/Target/ABI.h +++ lldb/include/lldb/Target/ABI.h @@ -11,6 +11,7 @@ #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/DynamicRegisterInfo.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-private.h" @@ -128,6 +129,9 @@ llvm::MCRegisterInfo &GetMCRegisterInfo() { return *m_mc_register_info_up; } virtual void AugmentRegisterInfo(RegisterInfo &info) = 0; + // Routine called before DynamicRegisterInfo::Finalize(). + virtual void + PreFinalizeDynamicRegisterInfo(lldb_private::DynamicRegisterInfo &info) {} virtual bool GetPointerReturnRegister(const char *&name) { return false; } Index: lldb/source/Plugins/ABI/AArch64/ABIAArch64.h =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABIAArch64.h +++ lldb/source/Plugins/ABI/AArch64/ABIAArch64.h @@ -32,6 +32,8 @@ uint32_t GetGenericNum(llvm::StringRef name) override; void AugmentRegisterInfo(lldb_private::RegisterInfo &info) override; + void PreFinalizeDynamicRegisterInfo( + lldb_private::DynamicRegisterInfo &info) override; using lldb_private::MCBasedABI::MCBasedABI; }; Index: lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp +++ lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp @@ -78,3 +78,60 @@ if (!strcmp(info.name, "sp") && !info.alt_name) info.alt_name = "x31"; } + +static void AddPartialRegister(lldb_private::DynamicRegisterInfo &info, + const lldb_private::RegisterInfo *full_reg, + uint32_t full_reg_size, + const std::string &partial_reg_name, + uint32_t partial_reg_size, + lldb::Encoding encoding, lldb::Format format, + uint32_t &next_regnum_lldb) { + if (!full_reg || full_reg->byte_size != full_reg_size) + return; + if (info.GetRegisterInfo(partial_reg_name)) + return; + + lldb_private::ConstString group{"partial registers"}; + + lldb_private::ConstString partial_reg_name_const{partial_reg_name}; + uint32_t value_regs[] = { + full_reg->kinds[lldb::eRegisterKindProcessPlugin], + LLDB_INVALID_REGNUM, + }; + + struct lldb_private::RegisterInfo partial_reg { + partial_reg_name_const.AsCString(), + nullptr, partial_reg_size, LLDB_INVALID_INDEX32, encoding, format, + { + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, next_regnum_lldb++, + }, + value_regs, nullptr, nullptr, 0 + }; + + info.AddSupplementaryRegister(partial_reg, group); +} + +void ABIAArch64::PreFinalizeDynamicRegisterInfo( + lldb_private::DynamicRegisterInfo &info) { + uint32_t next_regnum_lldb = info.GetNumRegisters(); + + // Create aliases for partial registers: wN for xN, and sN/dN for vN. + for (int i = 0; i < 32; i++) + AddPartialRegister(info, + info.GetRegisterInfo(llvm::formatv("x{0}", i).str()), 8, + llvm::formatv("w{0}", i), 4, lldb::eEncodingUint, + lldb::eFormatHex, next_regnum_lldb); + + for (int i = 0; i < 32; i++) + AddPartialRegister(info, + info.GetRegisterInfo(llvm::formatv("v{0}", i).str()), 16, + llvm::formatv("s{0}", i), 4, lldb::eEncodingIEEE754, + lldb::eFormatFloat, next_regnum_lldb); + + for (int i = 0; i < 32; i++) + AddPartialRegister(info, + info.GetRegisterInfo(llvm::formatv("v{0}", i).str()), 16, + llvm::formatv("d{0}", i), 8, lldb::eEncodingIEEE754, + lldb::eFormatFloat, next_regnum_lldb); +} Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -445,6 +445,10 @@ if (GetGDBServerRegisterInfo(arch_to_use)) return; + // We have to make a temporary ABI here, and not use the GetABI because + // this code gets called in DidAttach, when the target architecture + // (and consequently the ABI we'll get from the process) may be wrong. + ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use); char packet[128]; std::vector registers; uint32_t reg_num = 0; @@ -557,6 +561,8 @@ } // At this point, we can finalize our register info. + if (abi_sp) + abi_sp->PreFinalizeDynamicRegisterInfo(*m_register_info_sp); m_register_info_sp->Finalize(GetTarget().GetArchitecture()); } @@ -4545,6 +4551,8 @@ m_register_info_sp->AddRegister(reg_info, remote_reg_info.set_name); }; + if (abi_sp) + abi_sp->PreFinalizeDynamicRegisterInfo(*m_register_info_sp); m_register_info_sp->Finalize(arch_to_use); } Index: lldb/source/Target/DynamicRegisterInfo.cpp =================================================================== --- lldb/source/Target/DynamicRegisterInfo.cpp +++ lldb/source/Target/DynamicRegisterInfo.cpp @@ -833,7 +833,8 @@ const lldb_private::RegisterInfo * DynamicRegisterInfo::GetRegisterInfo(llvm::StringRef reg_name) const { for (auto ®_info : m_regs) - if (reg_info.name == reg_name) + if (reg_info.name == reg_name || + (reg_info.alt_name && reg_info.alt_name == reg_name)) return ®_info; return nullptr; } 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 @@ -380,6 +380,7 @@ return "".join(reg_data) def writeRegisters(self, reg_hex): + reg_data[:] = [reg_hex] return "OK" def haltReason(self): @@ -429,3 +430,43 @@ ["v0 = {0x81 0x82 0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90}"]) self.match("register read v31", ["v31 = {0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae 0xaf 0xb0}"]) + + # test partial registers + self.match("register read w0", + ["w0 = 0x04030201"]) + self.runCmd("register write w0 0xfffefdfc") + self.match("register read x0", + ["x0 = 0x08070605fffefdfc"]) + + self.match("register read w1", + ["w1 = 0x14131211"]) + self.runCmd("register write w1 0xefeeedec") + self.match("register read x1", + ["x1 = 0x18171615efeeedec"]) + + self.match("register read w30", + ["w30 = 0x44434241"]) + self.runCmd("register write w30 0xdfdedddc") + self.match("register read x30", + ["x30 = 0x48474645dfdedddc"]) + + self.match("register read w31", + ["w31 = 0x54535251"]) + self.runCmd("register write w31 0xcfcecdcc") + self.match("register read x31", + ["sp = 0x58575655cfcecdcc"]) + + # test FPU registers (overlapping with vector registers) + self.runCmd("register write d0 16") + self.match("register read v0", + ["v0 = {0x00 0x00 0x00 0x00 0x00 0x00 0x30 0x40 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90}"]) + self.runCmd("register write v31 '{0x00 0x00 0x00 0x00 0x00 0x00 0x50 0x40 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff}'") + self.match("register read d31", + ["d31 = 64"]) + + self.runCmd("register write s0 32") + self.match("register read v0", + ["v0 = {0x00 0x00 0x00 0x42 0x00 0x00 0x30 0x40 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90}"]) + self.runCmd("register write v31 '{0x00 0x00 0x00 0x43 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff}'") + self.match("register read s31", + ["s31 = 128"])