Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[lldb][lldb-server] Enable sending RegisterFlags as XML #69951

Merged
merged 6 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions lldb/include/lldb/Target/RegisterFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLDB_TARGET_REGISTERFLAGS_H

#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
DavidSpickett marked this conversation as resolved.
Show resolved Hide resolved

namespace lldb_private {

Expand Down Expand Up @@ -51,6 +52,10 @@ class RegisterFlags {
/// covered by either field.
unsigned PaddingDistance(const Field &other) const;

/// Output XML that describes this field, to be inserted into a target XML
/// file.
void ToXML(StreamString &strm) const;

bool operator<(const Field &rhs) const {
return GetStart() < rhs.GetStart();
}
Expand Down Expand Up @@ -106,6 +111,9 @@ class RegisterFlags {
/// be split into many tables as needed.
std::string AsTable(uint32_t max_width) const;

// Output XML that describes this set of flags.
void ToXML(StreamString &strm) const;

private:
const std::string m_id;
/// Size in bytes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3094,6 +3094,12 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
continue;
}

if (reg_info->flags_type) {
response.IndentMore();
reg_info->flags_type->ToXML(response);
response.IndentLess();
}

response.Indent();
response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32
"\" regnum=\"%d\" ",
Expand All @@ -3113,6 +3119,10 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
if (!format.empty())
response << "format=\"" << format << "\" ";

if (reg_info->flags_type) {
response << "type=\"" << reg_info->flags_type->GetID() << "\" ";
}
DavidSpickett marked this conversation as resolved.
Show resolved Hide resolved

const char *const register_set_name =
reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index);
if (register_set_name)
Expand Down
32 changes: 32 additions & 0 deletions lldb/source/Target/RegisterFlags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,35 @@ std::string RegisterFlags::AsTable(uint32_t max_width) const {

return table;
}

void RegisterFlags::ToXML(StreamString &strm) const {
// Example XML:
// <flags id="cpsr_flags" size="4">
// <field name="incorrect" start="0" end="0"/>
// </flags>
strm.Indent();
strm << "<flags id=\"" << GetID() << "\" ";
strm.Printf("size=\"%d\"", GetSize());
strm << ">";
for (const Field &field : m_fields) {
// Skip padding fields.
if (field.GetName().empty())
continue;

strm << "\n";
strm.IndentMore();
field.ToXML(strm);
strm.IndentLess();
}
strm.PutChar('\n');
strm.Indent("</flags>\n");
}

void RegisterFlags::Field::ToXML(StreamString &strm) const {
// Example XML:
// <field name="correct" start="0" end="0"/>
strm.Indent();
strm << "<field name=\"" << GetName() << "\" ";
DavidSpickett marked this conversation as resolved.
Show resolved Hide resolved
strm.Printf("start=\"%d\" end=\"%d\"", GetStart(), GetEnd());
strm << "/>";
}
32 changes: 32 additions & 0 deletions lldb/unittests/Target/RegisterFlagsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,35 @@ TEST(RegisterFlagsTest, AsTable) {
"| really long name |",
max_many_columns.AsTable(23));
}

TEST(RegisterFieldsTest, ToXML) {
StreamString strm;

// RegisterFlags requires that some fields be given, so no testing of empty
// input.

// Unnamed fields are padding that are ignored. This applies to fields passed
// in, and those generated to fill the other bits (31-1 here).
RegisterFlags("Foo", 4, {RegisterFlags::Field("", 0, 0)}).ToXML(strm);
ASSERT_EQ(strm.GetString(), "<flags id=\"Foo\" size=\"4\">\n"
"</flags>\n");

strm.Clear();
RegisterFlags("Foo", 4, {RegisterFlags::Field("abc", 0, 0)}).ToXML(strm);
ASSERT_EQ(strm.GetString(), "<flags id=\"Foo\" size=\"4\">\n"
" <field name=\"abc\" start=\"0\" end=\"0\"/>\n"
"</flags>\n");

strm.Clear();
// Should use the current indentation level as a starting point.
strm.IndentMore();
RegisterFlags(
"Bar", 5,
{RegisterFlags::Field("f1", 25, 32), RegisterFlags::Field("f2", 10, 24)})
.ToXML(strm);
ASSERT_EQ(strm.GetString(),
" <flags id=\"Bar\" size=\"5\">\n"
" <field name=\"f1\" start=\"25\" end=\"32\"/>\n"
" <field name=\"f2\" start=\"10\" end=\"24\"/>\n"
" </flags>\n");
}