[Lldb-commits] [lldb] bcfe5a5 - [lldb] Add register field tables to the "register info" command
David Spickett via lldb-commits
lldb-commits at lists.llvm.org
Wed Jun 21 03:50:37 PDT 2023
Author: David Spickett
Date: 2023-06-21T10:50:31Z
New Revision: bcfe5a52a39dee6d50d5e2410863fc555d2f50a8
URL: https://github.com/llvm/llvm-project/commit/bcfe5a52a39dee6d50d5e2410863fc555d2f50a8
DIFF: https://github.com/llvm/llvm-project/commit/bcfe5a52a39dee6d50d5e2410863fc555d2f50a8.diff
LOG: [lldb] Add register field tables to the "register info" command
This teaches DumpRegisterInfo to generate a table from the register
flags type. It just calls a method on RegisterFlags.
As such, the extra tests are minimal and only show that the intergration
works. Exhaustive formatting tests are done with RegisterFlags itself.
Example:
```
(lldb) register info cpsr
Name: cpsr
Size: 4 bytes (32 bits)
In sets: general (index 0)
| 31 | 30 | 29 | 28 | 27-26 | 25 | 24 | 23 | 22 | 21 | 20 | 19-13 | 12 | 11-10 | 9 | 8 | 7 | 6 | 5 | 4 | 3-2 | 1 | 0 |
|----|----|----|----|-------|-----|-----|-----|-----|----|----|-------|------|-------|---|---|---|---|---|-----|-----|---|----|
| N | Z | C | V | | TCO | DIT | UAO | PAN | SS | IL | | SSBS | | D | A | I | F | | nRW | EL | | SP |
```
LLDB limits the max terminal width to 80 chars by default.
So to get that full width output you will need to change the "term-width"
setting to something higher.
Reviewed By: jasonmolenda
Differential Revision: https://reviews.llvm.org/D152918
Added:
Modified:
lldb/include/lldb/Core/DumpRegisterInfo.h
lldb/source/Commands/CommandObjectRegister.cpp
lldb/source/Core/DumpRegisterInfo.cpp
lldb/test/API/commands/register/register/register_command/TestRegisters.py
lldb/test/API/functionalities/gdb_remote_client/TestXMLRegisterFlags.py
lldb/unittests/Core/DumpRegisterInfoTest.cpp
Removed:
################################################################################
diff --git a/lldb/include/lldb/Core/DumpRegisterInfo.h b/lldb/include/lldb/Core/DumpRegisterInfo.h
index e257581864b5a..bceabcacd836e 100644
--- a/lldb/include/lldb/Core/DumpRegisterInfo.h
+++ b/lldb/include/lldb/Core/DumpRegisterInfo.h
@@ -18,16 +18,18 @@ namespace lldb_private {
class Stream;
class RegisterContext;
struct RegisterInfo;
+class RegisterFlags;
void DumpRegisterInfo(Stream &strm, RegisterContext &ctx,
- const RegisterInfo &info);
+ const RegisterInfo &info, uint32_t terminal_width);
// For testing only. Use DumpRegisterInfo instead.
void DoDumpRegisterInfo(
Stream &strm, const char *name, const char *alt_name, uint32_t byte_size,
const std::vector<const char *> &invalidates,
const std::vector<const char *> &read_from,
- const std::vector<std::pair<const char *, uint32_t>> &in_sets);
+ const std::vector<std::pair<const char *, uint32_t>> &in_sets,
+ const RegisterFlags *flags_type, uint32_t terminal_width);
} // namespace lldb_private
diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index 814219d186186..a0e88f6ab4ba2 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -11,6 +11,7 @@
#include "lldb/Core/DumpRegisterInfo.h"
#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Host/OptionParser.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
@@ -418,6 +419,8 @@ Read from (*) The registers that the value of this register is constructed
read from the wider register.
In sets (*) The register sets that contain this register. For example the
PC will be in the "General Purpose Register" set.
+Fields (*) A table of the names and bit positions of the values contained
+ in this register.
Fields marked with (*) may not always be present. Some information may be
diff erent for the same register when connected to
diff erent debug servers.)");
@@ -453,7 +456,9 @@
diff erent for the same register when connected to
diff erent debug servers.)");
RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
if (reg_info) {
- DumpRegisterInfo(result.GetOutputStream(), *reg_ctx, *reg_info);
+ DumpRegisterInfo(
+ result.GetOutputStream(), *reg_ctx, *reg_info,
+ GetCommandInterpreter().GetDebugger().GetTerminalWidth());
result.SetStatus(eReturnStatusSuccessFinishResult);
} else
result.AppendErrorWithFormat("No register found with name '%s'.\n",
diff --git a/lldb/source/Core/DumpRegisterInfo.cpp b/lldb/source/Core/DumpRegisterInfo.cpp
index e7083e5938f52..8334795416902 100644
--- a/lldb/source/Core/DumpRegisterInfo.cpp
+++ b/lldb/source/Core/DumpRegisterInfo.cpp
@@ -8,6 +8,7 @@
#include "lldb/Core/DumpRegisterInfo.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/RegisterFlags.h"
#include "lldb/Utility/Stream.h"
using namespace lldb;
@@ -16,7 +17,8 @@ using namespace lldb_private;
using SetInfo = std::pair<const char *, uint32_t>;
void lldb_private::DumpRegisterInfo(Stream &strm, RegisterContext &ctx,
- const RegisterInfo &info) {
+ const RegisterInfo &info,
+ uint32_t terminal_width) {
std::vector<const char *> invalidates;
if (info.invalidate_regs) {
for (uint32_t *inv_regs = info.invalidate_regs;
@@ -60,7 +62,8 @@ void lldb_private::DumpRegisterInfo(Stream &strm, RegisterContext &ctx,
}
DoDumpRegisterInfo(strm, info.name, info.alt_name, info.byte_size,
- invalidates, read_from, in_sets);
+ invalidates, read_from, in_sets, info.flags_type,
+ terminal_width);
}
template <typename ElementType>
@@ -85,7 +88,8 @@ void lldb_private::DoDumpRegisterInfo(
Stream &strm, const char *name, const char *alt_name, uint32_t byte_size,
const std::vector<const char *> &invalidates,
const std::vector<const char *> &read_from,
- const std::vector<SetInfo> &in_sets) {
+ const std::vector<SetInfo> &in_sets, const RegisterFlags *flags_type,
+ uint32_t terminal_width) {
strm << " Name: " << name;
if (alt_name)
strm << " (" << alt_name << ")";
@@ -106,4 +110,7 @@ void lldb_private::DoDumpRegisterInfo(
strm.Printf("%s (index %d)", info.first, info.second);
};
DumpList(strm, " In sets: ", in_sets, emit_set);
+
+ if (flags_type)
+ strm.Printf("\n\n%s", flags_type->AsTable(terminal_width).c_str());
}
diff --git a/lldb/test/API/commands/register/register/register_command/TestRegisters.py b/lldb/test/API/commands/register/register/register_command/TestRegisters.py
index dfb71438dc23b..9dfbd0dd84083 100644
--- a/lldb/test/API/commands/register/register/register_command/TestRegisters.py
+++ b/lldb/test/API/commands/register/register/register_command/TestRegisters.py
@@ -587,7 +587,8 @@ def test_info_many_registers(self):
def test_info_register(self):
# The behaviour of this command is generic but the specific registers
# are not, so this is written for AArch64 only.
- # Text alignment and ordering are checked in the DumpRegisterInfo unit tests.
+ # Text alignment and ordering are checked in the DumpRegisterInfo and
+ # RegisterFlags unit tests.
self.build()
self.common_setup()
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestXMLRegisterFlags.py b/lldb/test/API/functionalities/gdb_remote_client/TestXMLRegisterFlags.py
index 3a4e34374e600..97d7cf5e9780f 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestXMLRegisterFlags.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestXMLRegisterFlags.py
@@ -605,3 +605,31 @@ def test_xml_includes_flags_redefined(self):
self.expect("register read x0", substrs=["(correct = 1)"])
self.expect("register read x1", substrs=["(correct = 1)"])
+
+ @skipIfXmlSupportMissing
+ @skipIfRemote
+ def test_flags_in_register_info(self):
+ # See RegisterFlags for comprehensive formatting tests.
+ self.setup_flags_test(
+ '<field name="D" start="0" end="7"/>'
+ '<field name="C" start="8" end="15"/>'
+ '<field name="B" start="16" end="23"/>'
+ '<field name="A" start="24" end="31"/>'
+ )
+
+ # The table should split according to terminal width.
+ self.runCmd("settings set term-width 17")
+
+ self.expect("register info cpsr",
+ substrs=[
+ " Name: cpsr\n"
+ " Size: 4 bytes (32 bits)\n"
+ " In sets: general (index 0)\n"
+ "\n"
+ "| 31-24 | 23-16 |\n"
+ "|-------|-------|\n"
+ "| A | B |\n"
+ "\n"
+ "| 15-8 | 7-0 |\n"
+ "|------|-----|\n"
+ "| C | D |"])
\ No newline at end of file
diff --git a/lldb/unittests/Core/DumpRegisterInfoTest.cpp b/lldb/unittests/Core/DumpRegisterInfoTest.cpp
index 4e9cb53cb637c..0d3ff8f542595 100644
--- a/lldb/unittests/Core/DumpRegisterInfoTest.cpp
+++ b/lldb/unittests/Core/DumpRegisterInfoTest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/DumpRegisterInfo.h"
+#include "lldb/Target/RegisterFlags.h"
#include "lldb/Utility/StreamString.h"
#include "gtest/gtest.h"
@@ -14,27 +15,28 @@ using namespace lldb_private;
TEST(DoDumpRegisterInfoTest, MinimumInfo) {
StreamString strm;
- DoDumpRegisterInfo(strm, "foo", nullptr, 4, {}, {}, {});
+ DoDumpRegisterInfo(strm, "foo", nullptr, 4, {}, {}, {}, nullptr, 0);
ASSERT_EQ(strm.GetString(), " Name: foo\n"
" Size: 4 bytes (32 bits)");
}
TEST(DoDumpRegisterInfoTest, AltName) {
StreamString strm;
- DoDumpRegisterInfo(strm, "foo", "bar", 4, {}, {}, {});
+ DoDumpRegisterInfo(strm, "foo", "bar", 4, {}, {}, {}, nullptr, 0);
ASSERT_EQ(strm.GetString(), " Name: foo (bar)\n"
" Size: 4 bytes (32 bits)");
}
TEST(DoDumpRegisterInfoTest, Invalidates) {
StreamString strm;
- DoDumpRegisterInfo(strm, "foo", nullptr, 4, {"foo2"}, {}, {});
+ DoDumpRegisterInfo(strm, "foo", nullptr, 4, {"foo2"}, {}, {}, nullptr, 0);
ASSERT_EQ(strm.GetString(), " Name: foo\n"
" Size: 4 bytes (32 bits)\n"
"Invalidates: foo2");
strm.Clear();
- DoDumpRegisterInfo(strm, "foo", nullptr, 4, {"foo2", "foo3", "foo4"}, {}, {});
+ DoDumpRegisterInfo(strm, "foo", nullptr, 4, {"foo2", "foo3", "foo4"}, {}, {},
+ nullptr, 0);
ASSERT_EQ(strm.GetString(), " Name: foo\n"
" Size: 4 bytes (32 bits)\n"
"Invalidates: foo2, foo3, foo4");
@@ -42,13 +44,14 @@ TEST(DoDumpRegisterInfoTest, Invalidates) {
TEST(DoDumpRegisterInfoTest, ReadFrom) {
StreamString strm;
- DoDumpRegisterInfo(strm, "foo", nullptr, 4, {}, {"foo1"}, {});
+ DoDumpRegisterInfo(strm, "foo", nullptr, 4, {}, {"foo1"}, {}, nullptr, 0);
ASSERT_EQ(strm.GetString(), " Name: foo\n"
" Size: 4 bytes (32 bits)\n"
" Read from: foo1");
strm.Clear();
- DoDumpRegisterInfo(strm, "foo", nullptr, 4, {}, {"foo1", "foo2", "foo3"}, {});
+ DoDumpRegisterInfo(strm, "foo", nullptr, 4, {}, {"foo1", "foo2", "foo3"}, {},
+ nullptr, 0);
ASSERT_EQ(strm.GetString(), " Name: foo\n"
" Size: 4 bytes (32 bits)\n"
" Read from: foo1, foo2, foo3");
@@ -56,14 +59,15 @@ TEST(DoDumpRegisterInfoTest, ReadFrom) {
TEST(DoDumpRegisterInfoTest, InSets) {
StreamString strm;
- DoDumpRegisterInfo(strm, "foo", nullptr, 4, {}, {}, {{"set1", 101}});
+ DoDumpRegisterInfo(strm, "foo", nullptr, 4, {}, {}, {{"set1", 101}}, nullptr,
+ 0);
ASSERT_EQ(strm.GetString(), " Name: foo\n"
" Size: 4 bytes (32 bits)\n"
" In sets: set1 (index 101)");
strm.Clear();
DoDumpRegisterInfo(strm, "foo", nullptr, 4, {}, {},
- {{"set1", 0}, {"set2", 1}, {"set3", 2}});
+ {{"set1", 0}, {"set2", 1}, {"set3", 2}}, nullptr, 0);
ASSERT_EQ(strm.GetString(),
" Name: foo\n"
" Size: 4 bytes (32 bits)\n"
@@ -73,10 +77,28 @@ TEST(DoDumpRegisterInfoTest, InSets) {
TEST(DoDumpRegisterInfoTest, MaxInfo) {
StreamString strm;
DoDumpRegisterInfo(strm, "foo", nullptr, 4, {"foo2", "foo3"},
- {"foo3", "foo4"}, {{"set1", 1}, {"set2", 2}});
+ {"foo3", "foo4"}, {{"set1", 1}, {"set2", 2}}, nullptr, 0);
ASSERT_EQ(strm.GetString(), " Name: foo\n"
" Size: 4 bytes (32 bits)\n"
"Invalidates: foo2, foo3\n"
" Read from: foo3, foo4\n"
" In sets: set1 (index 1), set2 (index 2)");
}
+
+TEST(DoDumpRegisterInfoTest, FieldsTable) {
+ // This is thoroughly tested in RegisterFlags itself, only checking the
+ // integration here.
+ StreamString strm;
+ RegisterFlags flags(
+ "", 4,
+ {RegisterFlags::Field("A", 24, 31), RegisterFlags::Field("B", 16, 23),
+ RegisterFlags::Field("C", 8, 15), RegisterFlags::Field("D", 0, 7)});
+
+ DoDumpRegisterInfo(strm, "foo", nullptr, 4, {}, {}, {}, &flags, 100);
+ ASSERT_EQ(strm.GetString(), " Name: foo\n"
+ " Size: 4 bytes (32 bits)\n"
+ "\n"
+ "| 31-24 | 23-16 | 15-8 | 7-0 |\n"
+ "|-------|-------|------|-----|\n"
+ "| A | B | C | D |");
+}
More information about the lldb-commits
mailing list