When lldb gets the register definitions from the response of a

qXfer:features:read:target.xml packet, or via the
plugin.process.gdb-remote.target-definition-file setting, if the
register definition doesn't give us eh_frame or DWARF register
numbers for that register, try to get that information from the ABI
plugin.

The DWARF/eh_frame register numbers are defined in the ABI
standardization documents - so getting this from the ABI plugin is
reasonable.  There's little value in having the remote stub inform
us of this generic information, as long as we can all agree on the
names of the registers.

There's some additional information we could get from the ABI.  For
instance, on ABIs where function arguments are passed in registers,
lldb defines alternate names like "arg1", "arg2", "arg3" for these
registers so they can be referred to that way by the user.  We could
get this from the ABI if the remote stub doesn't provide that.  That
may be something worth doing in the future - but for now, I'm keeping
this a little more minimal.

Thinking about this, what we want/need from the remote stub at a
minimum are:

 1. The names of the register
 2. The number that the stub will use to refer to the register with
    the p/P packets and in the ? response packets (T/S) where 
    expedited register values are provided
 3. The size of the register in bytes
   
(nice to have, to remove any doubt)
 4. The offset of the register in the g/G packet if we're going to
    use that for reading/writing registers.

debugserver traditionally provides a lot more information in
addition to this via the qRegisterInfo packet, and debugserver 
augments its response to the qXfer:features:read:target.xml
query to include this information.  Including:

DWARF regnum, eh_frame regnum, stabs regnum, encoding (ieee754,
Uint, Vector, Sint), format (hex, unsigned, pointer, vectorof*,
float), registers that should be marked as invalid if this 
register is modified, and registers that contain this register.

We might want to get all of this from the ABI - I'm not convinced
that it makes sense for the remote stub to provide any of these 
details, as long as the ABI and remote stub can agree on register
names.

Anyway, start with eh_frame and DWARF coming from the ABI if 
they're not provided by the remote stub.  We can look at doing
more in the future.

<rdar://problem/22566585> 

llvm-svn: 247121
This commit is contained in:
Jason Molenda 2015-09-09 03:36:24 +00:00
parent 0ace3f5c73
commit 21586c8385
1 changed files with 37 additions and 4 deletions

View File

@ -56,6 +56,7 @@
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
@ -513,6 +514,35 @@ ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_
return false;
}
// If the remote stub didn't give us eh_frame or DWARF register numbers for a register,
// see if the ABI can provide them.
// DWARF and eh_frame register numbers are defined as a part of the ABI.
static void
AugmentRegisterInfoViaABI (RegisterInfo &reg_info, ConstString reg_name, ABISP abi_sp)
{
if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM
|| reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM)
{
if (abi_sp)
{
RegisterInfo abi_reg_info;
if (abi_sp->GetRegisterInfoByName (reg_name, abi_reg_info))
{
if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM
&& abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
{
reg_info.kinds[eRegisterKindEHFrame] = abi_reg_info.kinds[eRegisterKindEHFrame];
}
if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM
&& abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
{
reg_info.kinds[eRegisterKindDWARF] = abi_reg_info.kinds[eRegisterKindDWARF];
}
}
}
}
}
static size_t
SplitCommaSeparatedRegisterNumberString(const llvm::StringRef &comma_separated_regiter_numbers, std::vector<uint32_t> &regnums, int base)
{
@ -715,6 +745,8 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
reg_info.invalidate_regs = invalidate_regs.data();
}
AugmentRegisterInfoViaABI (reg_info, reg_name, GetABI ());
m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
}
else
@ -4273,7 +4305,7 @@ struct GdbServerTargetInfo
};
bool
ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info)
ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp)
{
if (!feature_node)
return false;
@ -4281,7 +4313,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
uint32_t prev_reg_num = 0;
uint32_t reg_offset = 0;
feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &prev_reg_num, &reg_offset](const XMLNode &reg_node) -> bool {
feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &prev_reg_num, &reg_offset, &abi_sp](const XMLNode &reg_node) -> bool {
std::string gdb_group;
std::string gdb_type;
ConstString reg_name;
@ -4444,6 +4476,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
}
++prev_reg_num;
AugmentRegisterInfoViaABI (reg_info, reg_name, abi_sp);
dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);
return true; // Keep iterating through all "reg" elements
@ -4539,7 +4572,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
if (feature_node)
{
ParseRegisters(feature_node, target_info, this->m_register_info);
ParseRegisters(feature_node, target_info, this->m_register_info, GetABI());
}
for (const auto &include : target_info.includes)
@ -4557,7 +4590,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
XMLNode include_feature_node = include_xml_document.GetRootElement("feature");
if (include_feature_node)
{
ParseRegisters(include_feature_node, target_info, this->m_register_info);
ParseRegisters(include_feature_node, target_info, this->m_register_info, GetABI());
}
}
this->m_register_info.Finalize(GetTarget().GetArchitecture());