|
53 | 53 | #include "lldb/Target/ABI.h"
|
54 | 54 | #include "lldb/Target/DynamicLoader.h"
|
55 | 55 | #include "lldb/Target/MemoryRegionInfo.h"
|
| 56 | +#include "lldb/Target/RegisterFlags.h" |
56 | 57 | #include "lldb/Target/SystemRuntime.h"
|
57 | 58 | #include "lldb/Target/Target.h"
|
58 | 59 | #include "lldb/Target/TargetList.h"
|
|
84 | 85 | #include "lldb/Utility/StringExtractorGDBRemote.h"
|
85 | 86 |
|
86 | 87 | #include "llvm/ADT/ScopeExit.h"
|
| 88 | +#include "llvm/ADT/StringMap.h" |
87 | 89 | #include "llvm/ADT/StringSwitch.h"
|
88 | 90 | #include "llvm/Support/FormatAdapters.h"
|
89 | 91 | #include "llvm/Support/Threading.h"
|
@@ -4059,15 +4061,213 @@ struct GdbServerTargetInfo {
|
4059 | 4061 | RegisterSetMap reg_set_map;
|
4060 | 4062 | };
|
4061 | 4063 |
|
4062 |
| -bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, |
4063 |
| - std::vector<DynamicRegisterInfo::Register> ®isters) { |
| 4064 | +static std::vector<RegisterFlags::Field> ParseFlagsFields(XMLNode flags_node, |
| 4065 | + unsigned size) { |
| 4066 | + Log *log(GetLog(GDBRLog::Process)); |
| 4067 | + const unsigned max_start_bit = size * 8 - 1; |
| 4068 | + |
| 4069 | + // Process the fields of this set of flags. |
| 4070 | + std::vector<RegisterFlags::Field> fields; |
| 4071 | + flags_node.ForEachChildElementWithName("field", [&fields, max_start_bit, |
| 4072 | + &log](const XMLNode |
| 4073 | + &field_node) { |
| 4074 | + std::optional<llvm::StringRef> name; |
| 4075 | + std::optional<unsigned> start; |
| 4076 | + std::optional<unsigned> end; |
| 4077 | + |
| 4078 | + field_node.ForEachAttribute([&name, &start, &end, max_start_bit, |
| 4079 | + &log](const llvm::StringRef &attr_name, |
| 4080 | + const llvm::StringRef &attr_value) { |
| 4081 | + // Note that XML in general requires that each of these attributes only |
| 4082 | + // appears once, so we don't have to handle that here. |
| 4083 | + if (attr_name == "name") { |
| 4084 | + LLDB_LOG(log, |
| 4085 | + "ProcessGDBRemote::ParseFlags Found field node name \"{0}\"", |
| 4086 | + attr_value.data()); |
| 4087 | + name = attr_value; |
| 4088 | + } else if (attr_name == "start") { |
| 4089 | + unsigned parsed_start = 0; |
| 4090 | + if (llvm::to_integer(attr_value, parsed_start)) { |
| 4091 | + if (parsed_start > max_start_bit) { |
| 4092 | + LLDB_LOG( |
| 4093 | + log, |
| 4094 | + "ProcessGDBRemote::ParseFlags Invalid start {0} in field node, " |
| 4095 | + "cannot be > {1}", |
| 4096 | + parsed_start, max_start_bit); |
| 4097 | + } else |
| 4098 | + start = parsed_start; |
| 4099 | + } else { |
| 4100 | + LLDB_LOG(log, |
| 4101 | + "ProcessGDBRemote::ParseFlags Invalid start \"{0}\" in " |
| 4102 | + "field node", |
| 4103 | + attr_value.data()); |
| 4104 | + } |
| 4105 | + } else if (attr_name == "end") { |
| 4106 | + unsigned parsed_end = 0; |
| 4107 | + if (llvm::to_integer(attr_value, parsed_end)) |
| 4108 | + if (parsed_end > max_start_bit) { |
| 4109 | + LLDB_LOG( |
| 4110 | + log, |
| 4111 | + "ProcessGDBRemote::ParseFlags Invalid end {0} in field node, " |
| 4112 | + "cannot be > {1}", |
| 4113 | + parsed_end, max_start_bit); |
| 4114 | + } else |
| 4115 | + end = parsed_end; |
| 4116 | + else { |
| 4117 | + LLDB_LOG( |
| 4118 | + log, |
| 4119 | + "ProcessGDBRemote::ParseFlags Invalid end \"{0}\" in field node", |
| 4120 | + attr_value.data()); |
| 4121 | + } |
| 4122 | + } else if (attr_name == "type") { |
| 4123 | + // Type is a known attribute but we do not currently use it and it is |
| 4124 | + // not required. |
| 4125 | + } else { |
| 4126 | + LLDB_LOG(log, |
| 4127 | + "ProcessGDBRemote::ParseFlags Ignoring unknown attribute " |
| 4128 | + "\"{0}\" in field node", |
| 4129 | + attr_name.data()); |
| 4130 | + } |
| 4131 | + |
| 4132 | + return true; // Walk all attributes of the field. |
| 4133 | + }); |
| 4134 | + |
| 4135 | + if (name && start && end) { |
| 4136 | + if (*start > *end) { |
| 4137 | + LLDB_LOG(log, |
| 4138 | + "ProcessGDBRemote::ParseFlags Start {0} > end {1} in field " |
| 4139 | + "\"{2}\", ignoring", |
| 4140 | + *start, *end, name->data()); |
| 4141 | + } else { |
| 4142 | + fields.push_back(RegisterFlags::Field(name->str(), *start, *end)); |
| 4143 | + } |
| 4144 | + } |
| 4145 | + |
| 4146 | + return true; // Iterate all "field" nodes. |
| 4147 | + }); |
| 4148 | + return fields; |
| 4149 | +} |
| 4150 | + |
| 4151 | +void ParseFlags( |
| 4152 | + XMLNode feature_node, |
| 4153 | + llvm::StringMap<std::unique_ptr<RegisterFlags>> ®isters_flags_types) { |
| 4154 | + Log *log(GetLog(GDBRLog::Process)); |
| 4155 | + |
| 4156 | + feature_node.ForEachChildElementWithName( |
| 4157 | + "flags", |
| 4158 | + [&log, ®isters_flags_types](const XMLNode &flags_node) -> bool { |
| 4159 | + LLDB_LOG(log, "ProcessGDBRemote::ParseFlags Found flags node \"{0}\"", |
| 4160 | + flags_node.GetAttributeValue("id").c_str()); |
| 4161 | + |
| 4162 | + std::optional<llvm::StringRef> id; |
| 4163 | + std::optional<unsigned> size; |
| 4164 | + flags_node.ForEachAttribute( |
| 4165 | + [&id, &size, &log](const llvm::StringRef &name, |
| 4166 | + const llvm::StringRef &value) { |
| 4167 | + if (name == "id") { |
| 4168 | + id = value; |
| 4169 | + } else if (name == "size") { |
| 4170 | + unsigned parsed_size = 0; |
| 4171 | + if (llvm::to_integer(value, parsed_size)) |
| 4172 | + size = parsed_size; |
| 4173 | + else { |
| 4174 | + LLDB_LOG(log, |
| 4175 | + "ProcessGDBRemote::ParseFlags Invalid size \"{0}\" " |
| 4176 | + "in flags node", |
| 4177 | + value.data()); |
| 4178 | + } |
| 4179 | + } else { |
| 4180 | + LLDB_LOG(log, |
| 4181 | + "ProcessGDBRemote::ParseFlags Ignoring unknown " |
| 4182 | + "attribute \"{0}\" in flags node", |
| 4183 | + name.data()); |
| 4184 | + } |
| 4185 | + return true; // Walk all attributes. |
| 4186 | + }); |
| 4187 | + |
| 4188 | + if (id && size) { |
| 4189 | + // Process the fields of this set of flags. |
| 4190 | + std::vector<RegisterFlags::Field> fields = |
| 4191 | + ParseFlagsFields(flags_node, *size); |
| 4192 | + if (fields.size()) { |
| 4193 | + // Sort so that the fields with the MSBs are first. |
| 4194 | + std::sort(fields.rbegin(), fields.rend()); |
| 4195 | + std::vector<RegisterFlags::Field>::const_iterator overlap = |
| 4196 | + std::adjacent_find(fields.begin(), fields.end(), |
| 4197 | + [](const RegisterFlags::Field &lhs, |
| 4198 | + const RegisterFlags::Field &rhs) { |
| 4199 | + return lhs.Overlaps(rhs); |
| 4200 | + }); |
| 4201 | + |
| 4202 | + // If no fields overlap, use them. |
| 4203 | + if (overlap == fields.end()) { |
| 4204 | + if (registers_flags_types.find(*id) != |
| 4205 | + registers_flags_types.end()) { |
| 4206 | + // In theory you could define some flag set, use it with a |
| 4207 | + // register then redefine it. We do not know if anyone does |
| 4208 | + // that, or what they would expect to happen in that case. |
| 4209 | + // |
| 4210 | + // LLDB chooses to take the first definition and ignore the rest |
| 4211 | + // as waiting until everything has been processed is more |
| 4212 | + // expensive and difficult. This means that pointers to flag |
| 4213 | + // sets in the register info remain valid if later the flag set |
| 4214 | + // is redefined. If we allowed redefinitions, LLDB would crash |
| 4215 | + // when you tried to print a register that used the original |
| 4216 | + // definition. |
| 4217 | + LLDB_LOG( |
| 4218 | + log, |
| 4219 | + "ProcessGDBRemote::ParseFlags Definition of flags " |
| 4220 | + "\"{0}\" shadows " |
| 4221 | + "previous definition, using original definition instead.", |
| 4222 | + id->data()); |
| 4223 | + } else { |
| 4224 | + registers_flags_types.insert_or_assign( |
| 4225 | + *id, std::make_unique<RegisterFlags>(id->str(), *size, |
| 4226 | + std::move(fields))); |
| 4227 | + } |
| 4228 | + } else { |
| 4229 | + // If any fields overlap, ignore the whole set of flags. |
| 4230 | + std::vector<RegisterFlags::Field>::const_iterator next = |
| 4231 | + std::next(overlap); |
| 4232 | + LLDB_LOG( |
| 4233 | + log, |
| 4234 | + "ProcessGDBRemote::ParseFlags Ignoring flags because fields " |
| 4235 | + "{0} (start: {1} end: {2}) and {3} (start: {4} end: {5}) " |
| 4236 | + "overlap.", |
| 4237 | + overlap->GetName().c_str(), overlap->GetStart(), |
| 4238 | + overlap->GetEnd(), next->GetName().c_str(), next->GetStart(), |
| 4239 | + next->GetEnd()); |
| 4240 | + } |
| 4241 | + } else { |
| 4242 | + LLDB_LOG( |
| 4243 | + log, |
| 4244 | + "ProcessGDBRemote::ParseFlags Ignoring definition of flags " |
| 4245 | + "\"{0}\" because it contains no fields.", |
| 4246 | + id->data()); |
| 4247 | + } |
| 4248 | + } |
| 4249 | + |
| 4250 | + return true; // Keep iterating through all "flags" elements. |
| 4251 | + }); |
| 4252 | +} |
| 4253 | + |
| 4254 | +bool ParseRegisters( |
| 4255 | + XMLNode feature_node, GdbServerTargetInfo &target_info, |
| 4256 | + std::vector<DynamicRegisterInfo::Register> ®isters, |
| 4257 | + llvm::StringMap<std::unique_ptr<RegisterFlags>> ®isters_flags_types) { |
4064 | 4258 | if (!feature_node)
|
4065 | 4259 | return false;
|
4066 | 4260 |
|
4067 | 4261 | Log *log(GetLog(GDBRLog::Process));
|
4068 | 4262 |
|
| 4263 | + ParseFlags(feature_node, registers_flags_types); |
| 4264 | + for (const auto &flags : registers_flags_types) |
| 4265 | + flags.second->log(log); |
| 4266 | + |
4069 | 4267 | feature_node.ForEachChildElementWithName(
|
4070 |
| - "reg", [&target_info, ®isters, log](const XMLNode ®_node) -> bool { |
| 4268 | + "reg", |
| 4269 | + [&target_info, ®isters, ®isters_flags_types, |
| 4270 | + log](const XMLNode ®_node) -> bool { |
4071 | 4271 | std::string gdb_group;
|
4072 | 4272 | std::string gdb_type;
|
4073 | 4273 | DynamicRegisterInfo::Register reg_info;
|
@@ -4143,29 +4343,40 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
|
4143 | 4343 | return true; // Keep iterating through all attributes
|
4144 | 4344 | });
|
4145 | 4345 |
|
4146 |
| - if (!gdb_type.empty() && !(encoding_set || format_set)) { |
4147 |
| - if (llvm::StringRef(gdb_type).startswith("int")) { |
4148 |
| - reg_info.format = eFormatHex; |
4149 |
| - reg_info.encoding = eEncodingUint; |
4150 |
| - } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") { |
4151 |
| - reg_info.format = eFormatAddressInfo; |
4152 |
| - reg_info.encoding = eEncodingUint; |
4153 |
| - } else if (gdb_type == "float") { |
4154 |
| - reg_info.format = eFormatFloat; |
4155 |
| - reg_info.encoding = eEncodingIEEE754; |
4156 |
| - } else if (gdb_type == "aarch64v" || |
4157 |
| - llvm::StringRef(gdb_type).startswith("vec") || |
4158 |
| - gdb_type == "i387_ext" || gdb_type == "uint128") { |
4159 |
| - // lldb doesn't handle 128-bit uints correctly (for ymm*h), so treat |
4160 |
| - // them as vector (similarly to xmm/ymm) |
4161 |
| - reg_info.format = eFormatVectorOfUInt8; |
4162 |
| - reg_info.encoding = eEncodingVector; |
4163 |
| - } else { |
4164 |
| - LLDB_LOGF( |
4165 |
| - log, |
4166 |
| - "ProcessGDBRemote::ParseRegisters Could not determine lldb" |
4167 |
| - "format and encoding for gdb type %s", |
4168 |
| - gdb_type.c_str()); |
| 4346 | + if (!gdb_type.empty()) { |
| 4347 | + // gdb_type could reference some flags type defined in XML. |
| 4348 | + llvm::StringMap<std::unique_ptr<RegisterFlags>>::iterator it = |
| 4349 | + registers_flags_types.find(gdb_type); |
| 4350 | + if (it != registers_flags_types.end()) |
| 4351 | + reg_info.flags_type = it->second.get(); |
| 4352 | + |
| 4353 | + // There's a slim chance that the gdb_type name is both a flags type |
| 4354 | + // and a simple type. Just in case, look for that too (setting both |
| 4355 | + // does no harm). |
| 4356 | + if (!gdb_type.empty() && !(encoding_set || format_set)) { |
| 4357 | + if (llvm::StringRef(gdb_type).startswith("int")) { |
| 4358 | + reg_info.format = eFormatHex; |
| 4359 | + reg_info.encoding = eEncodingUint; |
| 4360 | + } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") { |
| 4361 | + reg_info.format = eFormatAddressInfo; |
| 4362 | + reg_info.encoding = eEncodingUint; |
| 4363 | + } else if (gdb_type == "float") { |
| 4364 | + reg_info.format = eFormatFloat; |
| 4365 | + reg_info.encoding = eEncodingIEEE754; |
| 4366 | + } else if (gdb_type == "aarch64v" || |
| 4367 | + llvm::StringRef(gdb_type).startswith("vec") || |
| 4368 | + gdb_type == "i387_ext" || gdb_type == "uint128") { |
| 4369 | + // lldb doesn't handle 128-bit uints correctly (for ymm*h), so |
| 4370 | + // treat them as vector (similarly to xmm/ymm) |
| 4371 | + reg_info.format = eFormatVectorOfUInt8; |
| 4372 | + reg_info.encoding = eEncodingVector; |
| 4373 | + } else { |
| 4374 | + LLDB_LOGF( |
| 4375 | + log, |
| 4376 | + "ProcessGDBRemote::ParseRegisters Could not determine lldb" |
| 4377 | + "format and encoding for gdb type %s", |
| 4378 | + gdb_type.c_str()); |
| 4379 | + } |
4169 | 4380 | }
|
4170 | 4381 | }
|
4171 | 4382 |
|
@@ -4297,8 +4508,8 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess(
|
4297 | 4508 |
|
4298 | 4509 | if (arch_to_use.IsValid()) {
|
4299 | 4510 | for (auto &feature_node : feature_nodes) {
|
4300 |
| - ParseRegisters(feature_node, target_info, |
4301 |
| - registers); |
| 4511 | + ParseRegisters(feature_node, target_info, registers, |
| 4512 | + m_registers_flags_types); |
4302 | 4513 | }
|
4303 | 4514 |
|
4304 | 4515 | for (const auto &include : target_info.includes) {
|
@@ -4363,6 +4574,13 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
|
4363 | 4574 | if (!m_gdb_comm.GetQXferFeaturesReadSupported())
|
4364 | 4575 | return false;
|
4365 | 4576 |
|
| 4577 | + // This holds register flags information for the whole of target.xml. |
| 4578 | + // target.xml may include further documents that |
| 4579 | + // GetGDBServerRegisterInfoXMLAndProcess will recurse to fetch and process. |
| 4580 | + // That's why we clear the cache here, and not in |
| 4581 | + // GetGDBServerRegisterInfoXMLAndProcess. To prevent it being cleared on every |
| 4582 | + // include read. |
| 4583 | + m_registers_flags_types.clear(); |
4366 | 4584 | std::vector<DynamicRegisterInfo::Register> registers;
|
4367 | 4585 | if (GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, "target.xml",
|
4368 | 4586 | registers))
|
|
0 commit comments