[Lldb-commits] [lldb] [lldb] Improved formatting of 'register read' command. (PR #188049)

via lldb-commits lldb-commits at lists.llvm.org
Thu Apr 2 07:09:01 PDT 2026


https://github.com/Rifet-c updated https://github.com/llvm/llvm-project/pull/188049

>From 084a35eae5114f631b1850269d8f769f4205987c Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Mon, 23 Mar 2026 16:10:26 +0100
Subject: [PATCH 01/11] [lldb] Improved formatting of 'register read' command
 of lldb. Now it is dynamic in register name lengths and left-aligned.

---
 .../source/Commands/CommandObjectRegister.cpp | 37 +++++++++++++++++--
 lldb/source/Core/DumpRegisterValue.cpp        |  6 +--
 2 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index fbb92e5c63877..404c800047d49 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -75,7 +75,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
 
   bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm,
                     RegisterContext &reg_ctx, const RegisterInfo &reg_info,
-                    bool print_flags) {
+                    bool print_flags, uint32_t reg_name_align_at = 0) {
     RegisterValue reg_value;
     if (!reg_ctx.ReadRegister(&reg_info, reg_value))
       return false;
@@ -85,7 +85,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
     bool prefix_with_altname = (bool)m_command_options.alternate_name;
     bool prefix_with_name = !prefix_with_altname;
     DumpRegisterValue(reg_value, strm, reg_info, prefix_with_name,
-                      prefix_with_altname, m_format_options.GetFormat(), 8,
+                      prefix_with_altname, m_format_options.GetFormat(), reg_name_align_at,
                       exe_ctx.GetBestExecutionContextScope(), print_flags,
                       exe_ctx.GetTargetSP());
     if ((reg_info.encoding == eEncodingUint) ||
@@ -123,6 +123,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
       strm.Printf("%s:\n", (reg_set->name ? reg_set->name : "unknown"));
       strm.IndentMore();
       const size_t num_registers = reg_set->num_registers;
+      uint32_t reg_name_align_at = ComputeMatchingAlignment(reg_ctx, reg_set, primitive_only);
       for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
         const uint32_t reg = reg_set->registers[reg_idx];
         const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
@@ -131,7 +132,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
           continue;
 
         if (reg_info && DumpRegister(exe_ctx, strm, *reg_ctx, *reg_info,
-                                     /*print_flags=*/false))
+                                     /*print_flags=*/false, reg_name_align_at))
           ++available_count;
         else
           ++unavailable_count;
@@ -147,6 +148,36 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
   }
 
 protected:
+  uint32_t ComputeMatchingAlignment(RegisterContext *reg_ctx, const RegisterSet *const reg_set, bool primitive_only) {
+    bool use_primary_name = !static_cast<bool>(m_command_options.alternate_name);
+    const size_t num_registers = reg_set->num_registers;
+    uint32_t reg_name_align_at = 0;
+
+    auto getNameSize = [&](auto reg_info){ 
+      auto raw = use_primary_name ? reg_info->name : reg_info->alt_name;
+      auto str = raw ? std::string(raw) : std::string();
+      return static_cast<uint32_t>(str.size());
+    };
+
+    // Loop through all the registers to find the longest register name for the 
+    // matching alignment
+    for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
+      const uint32_t reg = reg_set->registers[reg_idx];
+      const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
+
+      // Derived registers are skipped if primitive_only is true.
+      if (primitive_only && reg_info && reg_info->value_regs)
+        continue;
+
+      if (!reg_info)
+        continue;
+
+      reg_name_align_at = std::max(reg_name_align_at, getNameSize(reg_info));
+    }
+
+    return reg_name_align_at;
+  }
+
   void DoExecute(Args &command, CommandReturnObject &result) override {
     Stream &strm = result.GetOutputStream();
     RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
diff --git a/lldb/source/Core/DumpRegisterValue.cpp b/lldb/source/Core/DumpRegisterValue.cpp
index aff4d2c621d7e..29b95ba41b085 100644
--- a/lldb/source/Core/DumpRegisterValue.cpp
+++ b/lldb/source/Core/DumpRegisterValue.cpp
@@ -62,7 +62,7 @@ void lldb_private::DumpRegisterValue(const RegisterValue &reg_val, Stream &s,
                                      const RegisterInfo &reg_info,
                                      bool prefix_with_name,
                                      bool prefix_with_alt_name, Format format,
-                                     uint32_t reg_name_right_align_at,
+                                     uint32_t reg_name_left_align_at,
                                      ExecutionContextScope *exe_scope,
                                      bool print_flags, TargetSP target_sp) {
   DataExtractor data;
@@ -76,8 +76,8 @@ void lldb_private::DumpRegisterValue(const RegisterValue &reg_val, Stream &s,
   //     prefix_with_name^prefix_with_alt_name is true
   //
   StreamString format_string;
-  if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name))
-    format_string.Printf("%%%us", reg_name_right_align_at);
+  if (reg_name_left_align_at && (prefix_with_name ^ prefix_with_alt_name))
+    format_string.Printf("%%-%us", reg_name_left_align_at);
   else
     format_string.Printf("%%s");
   std::string fmt = std::string(format_string.GetString());

>From 4386afc2d36f6be9d136aceb76fef156a7623a17 Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Mon, 23 Mar 2026 16:33:09 +0100
Subject: [PATCH 02/11] Fixed formatting

---
 .../source/Commands/CommandObjectRegister.cpp | 20 +++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index 404c800047d49..7f1f473795617 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -85,9 +85,9 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
     bool prefix_with_altname = (bool)m_command_options.alternate_name;
     bool prefix_with_name = !prefix_with_altname;
     DumpRegisterValue(reg_value, strm, reg_info, prefix_with_name,
-                      prefix_with_altname, m_format_options.GetFormat(), reg_name_align_at,
-                      exe_ctx.GetBestExecutionContextScope(), print_flags,
-                      exe_ctx.GetTargetSP());
+                      prefix_with_altname, m_format_options.GetFormat(),
+                      reg_name_align_at, exe_ctx.GetBestExecutionContextScope(),
+                      print_flags, exe_ctx.GetTargetSP());
     if ((reg_info.encoding == eEncodingUint) ||
         (reg_info.encoding == eEncodingSint)) {
       Process *process = exe_ctx.GetProcessPtr();
@@ -123,7 +123,8 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
       strm.Printf("%s:\n", (reg_set->name ? reg_set->name : "unknown"));
       strm.IndentMore();
       const size_t num_registers = reg_set->num_registers;
-      uint32_t reg_name_align_at = ComputeMatchingAlignment(reg_ctx, reg_set, primitive_only);
+      uint32_t reg_name_align_at =
+          ComputeMatchingAlignment(reg_ctx, reg_set, primitive_only);
       for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
         const uint32_t reg = reg_set->registers[reg_idx];
         const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
@@ -148,18 +149,21 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
   }
 
 protected:
-  uint32_t ComputeMatchingAlignment(RegisterContext *reg_ctx, const RegisterSet *const reg_set, bool primitive_only) {
-    bool use_primary_name = !static_cast<bool>(m_command_options.alternate_name);
+  uint32_t ComputeMatchingAlignment(RegisterContext *reg_ctx,
+                                    const RegisterSet *const reg_set,
+                                    bool primitive_only) {
+    bool use_primary_name =
+        !static_cast<bool>(m_command_options.alternate_name);
     const size_t num_registers = reg_set->num_registers;
     uint32_t reg_name_align_at = 0;
 
-    auto getNameSize = [&](auto reg_info){ 
+    auto getNameSize = [&](auto reg_info) {
       auto raw = use_primary_name ? reg_info->name : reg_info->alt_name;
       auto str = raw ? std::string(raw) : std::string();
       return static_cast<uint32_t>(str.size());
     };
 
-    // Loop through all the registers to find the longest register name for the 
+    // Loop through all the registers to find the longest register name for the
     // matching alignment
     for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
       const uint32_t reg = reg_set->registers[reg_idx];

>From ba74a7960ac4d9749981045eb74578c46c14cb79 Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Tue, 24 Mar 2026 10:40:44 +0100
Subject: [PATCH 03/11] Returned right alignment

---
 lldb/source/Core/DumpRegisterValue.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/source/Core/DumpRegisterValue.cpp b/lldb/source/Core/DumpRegisterValue.cpp
index 29b95ba41b085..f5650f44d3fb3 100644
--- a/lldb/source/Core/DumpRegisterValue.cpp
+++ b/lldb/source/Core/DumpRegisterValue.cpp
@@ -77,7 +77,7 @@ void lldb_private::DumpRegisterValue(const RegisterValue &reg_val, Stream &s,
   //
   StreamString format_string;
   if (reg_name_left_align_at && (prefix_with_name ^ prefix_with_alt_name))
-    format_string.Printf("%%-%us", reg_name_left_align_at);
+    format_string.Printf("%%%us", reg_name_left_align_at);
   else
     format_string.Printf("%%s");
   std::string fmt = std::string(format_string.GetString());

>From d89ae1e5e45bc76e014c3cba2bc07810281469f7 Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Tue, 24 Mar 2026 13:58:01 +0100
Subject: [PATCH 04/11] Reversed renaming

---
 lldb/source/Core/DumpRegisterValue.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lldb/source/Core/DumpRegisterValue.cpp b/lldb/source/Core/DumpRegisterValue.cpp
index f5650f44d3fb3..aff4d2c621d7e 100644
--- a/lldb/source/Core/DumpRegisterValue.cpp
+++ b/lldb/source/Core/DumpRegisterValue.cpp
@@ -62,7 +62,7 @@ void lldb_private::DumpRegisterValue(const RegisterValue &reg_val, Stream &s,
                                      const RegisterInfo &reg_info,
                                      bool prefix_with_name,
                                      bool prefix_with_alt_name, Format format,
-                                     uint32_t reg_name_left_align_at,
+                                     uint32_t reg_name_right_align_at,
                                      ExecutionContextScope *exe_scope,
                                      bool print_flags, TargetSP target_sp) {
   DataExtractor data;
@@ -76,8 +76,8 @@ void lldb_private::DumpRegisterValue(const RegisterValue &reg_val, Stream &s,
   //     prefix_with_name^prefix_with_alt_name is true
   //
   StreamString format_string;
-  if (reg_name_left_align_at && (prefix_with_name ^ prefix_with_alt_name))
-    format_string.Printf("%%%us", reg_name_left_align_at);
+  if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name))
+    format_string.Printf("%%%us", reg_name_right_align_at);
   else
     format_string.Printf("%%s");
   std::string fmt = std::string(format_string.GetString());

>From e7404cd60488c2a6e2a8e51eea10bc9f5992a86c Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Tue, 31 Mar 2026 14:48:35 +0200
Subject: [PATCH 05/11] Separate registers printing is now well-aligned as well

---
 .../source/Commands/CommandObjectRegister.cpp | 52 ++++++++++++++-----
 1 file changed, 38 insertions(+), 14 deletions(-)

diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index 7f1f473795617..fb03d738bde84 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -149,6 +149,12 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
   }
 
 protected:
+  uint32_t GetNameSize(const RegisterInfo * reg_info, bool use_primary_name) {
+      const char *raw = use_primary_name ? reg_info->name : reg_info->alt_name;
+      std::string str = raw ? std::string(raw) : std::string();
+      return static_cast<uint32_t>(str.size());
+  }
+
   uint32_t ComputeMatchingAlignment(RegisterContext *reg_ctx,
                                     const RegisterSet *const reg_set,
                                     bool primitive_only) {
@@ -157,26 +163,43 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
     const size_t num_registers = reg_set->num_registers;
     uint32_t reg_name_align_at = 0;
 
-    auto getNameSize = [&](auto reg_info) {
-      auto raw = use_primary_name ? reg_info->name : reg_info->alt_name;
-      auto str = raw ? std::string(raw) : std::string();
-      return static_cast<uint32_t>(str.size());
-    };
-
     // Loop through all the registers to find the longest register name for the
     // matching alignment
     for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
       const uint32_t reg = reg_set->registers[reg_idx];
-      const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
+      if (const RegisterInfo *reg_info = 
+              reg_ctx->GetRegisterInfoAtIndex(reg)) {
+        // Derived registers are skipped if primitive_only is true.
+        if (primitive_only && reg_info->value_regs)
+          continue;
+
+        reg_name_align_at = std::max(reg_name_align_at, GetNameSize(reg_info, use_primary_name));
+      }
+    }
 
-      // Derived registers are skipped if primitive_only is true.
-      if (primitive_only && reg_info && reg_info->value_regs)
-        continue;
+    return reg_name_align_at;
+  }
 
-      if (!reg_info)
-        continue;
+  // Here, command is basically a list of registers to be printed by DumpRegister() method
+  uint32_t ComputeMatchingAlignment(Args &command, RegisterContext *reg_ctx, bool primitive_only) {
+    bool use_primary_name =
+        !static_cast<bool>(m_command_options.alternate_name);
+    uint32_t reg_name_align_at = 0;
 
-      reg_name_align_at = std::max(reg_name_align_at, getNameSize(reg_info));
+    // Loop through all the arguments to find the longest register name for the
+    // matching alignment
+    for (auto &entry : command) {
+      auto arg_str = entry.ref();
+      arg_str.consume_front("$");
+    
+      if (const RegisterInfo *reg_info =
+              reg_ctx->GetRegisterInfoByName(arg_str)) {
+        // Derived registers are skipped if primitive_only is true.
+        if (primitive_only && reg_info->value_regs)
+          continue;
+
+        reg_name_align_at = std::max(reg_name_align_at, GetNameSize(reg_info, use_primary_name));
+      }
     }
 
     return reg_name_align_at;
@@ -230,6 +253,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
         result.AppendError("the --set <set> option can't be used when "
                            "registers names are supplied as arguments\n");
       } else {
+        int alignment = ComputeMatchingAlignment(command, reg_ctx, !m_command_options.dump_all_sets.GetCurrentValue());
         for (auto &entry : command) {
           // in most LLDB commands we accept $rbx as the name for register RBX
           // - and here we would reject it and non-existant. we should be more
@@ -246,7 +270,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
             bool print_flags =
                 !m_format_options.GetFormatValue().OptionWasSet();
             if (!DumpRegister(m_exe_ctx, strm, *reg_ctx, *reg_info,
-                              print_flags))
+                              print_flags, alignment))
               strm.Printf("%-12s = error: unavailable\n", reg_info->name);
           } else {
             result.AppendErrorWithFormat("Invalid register name '%s'.\n",

>From 2eaa55c7bb67e35861c47daeec069c3687d1cb31 Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Wed, 1 Apr 2026 17:09:21 +0200
Subject: [PATCH 06/11] Added two tests: one for register set dumping, other
 for custom register bundles dumping

---
 .../source/Commands/CommandObjectRegister.cpp |  1 +
 ...d-register-read-alignment-custom-regs.test | 13 +++++++
 ...mmand-register-read-alignment-reg-set.test | 36 +++++++++++++++++++
 3 files changed, 50 insertions(+)
 create mode 100644 lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test
 create mode 100644 lldb/test/Shell/Commands/command-register-read-alignment-reg-set.test

diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index fb03d738bde84..4027928329bd4 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -254,6 +254,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
                            "registers names are supplied as arguments\n");
       } else {
         int alignment = ComputeMatchingAlignment(command, reg_ctx, !m_command_options.dump_all_sets.GetCurrentValue());
+        alignment += 2; // Extra ident to be consistent with register sets dumping
         for (auto &entry : command) {
           // in most LLDB commands we accept $rbx as the name for register RBX
           // - and here we would reject it and non-existant. we should be more
diff --git a/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test b/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test
new file mode 100644
index 0000000000000..67be61e094aa7
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test
@@ -0,0 +1,13 @@
+# REQUIRES: x86
+
+# RUN: %clang_host -g -O0 %S/Inputs/main.c -o %t.out
+# RUN: %lldb -b -o "breakpoint set --name main" \
+# RUN:        -o run \
+# RUN:        -o "register read pc ymm7 ymm12 fs_base" \
+# RUN:        %t.out | FileCheck --strict-whitespace %s
+
+# CHECK: (lldb) register read pc ymm7 ymm12 fs_base
+# CHECK: {{^      rip = }}
+# CHECK: {{^     ymm7 = }}
+# CHECK: {{^    ymm12 = }}
+# CHECK: {{^  fs_base = }}
\ No newline at end of file
diff --git a/lldb/test/Shell/Commands/command-register-read-alignment-reg-set.test b/lldb/test/Shell/Commands/command-register-read-alignment-reg-set.test
new file mode 100644
index 0000000000000..d40ea0c35c499
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-register-read-alignment-reg-set.test
@@ -0,0 +1,36 @@
+# REQUIRES: x86
+
+# RUN: %clang_host -g -O0 %S/Inputs/main.c -o %t.out
+# RUN: %lldb -b -o "breakpoint set --name main" \
+# RUN:        -o run \
+# RUN:        -o "register read" \
+# RUN:        %t.out | FileCheck --strict-whitespace %s
+
+# CHECK: (lldb) register read
+# CHECK: General Purpose Registers:
+# CHECK: {{      rax = }}
+# CHECK: {{      rbx = }}
+# CHECK: {{      rcx = }}
+# CHECK: {{      rdx = }}
+# CHECK: {{      rdi = }}
+# CHECK: {{      rsi = }}
+# CHECK: {{      rbp = }}
+# CHECK: {{      rsp = }}
+# CHECK: {{       r8 = }}
+# CHECK: {{       r9 = }}
+# CHECK: {{      r10 = }}
+# CHECK: {{      r11 = }}
+# CHECK: {{      r12 = }}
+# CHECK: {{      r13 = }}
+# CHECK: {{      r14 = }}
+# CHECK: {{      r15 = }}
+# CHECK: {{      rip = }}
+# CHECK: {{   rflags = }}
+# CHECK: {{       cs = }}
+# CHECK: {{       fs = }}
+# CHECK: {{       gs = }}
+# CHECK: {{       ss = }}
+# CHECK: {{  fs_base = }}
+# CHECK: {{  gs_base = }}
+# CHECK: {{       ds = }}
+# CHECK: {{       es = }}
\ No newline at end of file

>From ebb2751f73eb81c0071d6fe2eb996b7e46cb4094 Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Thu, 2 Apr 2026 13:44:59 +0200
Subject: [PATCH 07/11] Removed registers that are not guaranteed by x86
 architecture

---
 .../command-register-read-alignment-custom-regs.test     | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test b/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test
index 67be61e094aa7..9871734d3835b 100644
--- a/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test
+++ b/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test
@@ -6,8 +6,7 @@
 # RUN:        -o "register read pc ymm7 ymm12 fs_base" \
 # RUN:        %t.out | FileCheck --strict-whitespace %s
 
-# CHECK: (lldb) register read pc ymm7 ymm12 fs_base
-# CHECK: {{^      rip = }}
-# CHECK: {{^     ymm7 = }}
-# CHECK: {{^    ymm12 = }}
-# CHECK: {{^  fs_base = }}
\ No newline at end of file
+# CHECK: (lldb) register read pc rax r10d
+# CHECK: {{^    pc = }}
+# CHECK: {{^   rax = }}
+# CHECK: {{^  r10d = }}
\ No newline at end of file

>From 9397ee9f4f6180e26533e743c00ce01b6253c992 Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Thu, 2 Apr 2026 14:37:01 +0200
Subject: [PATCH 08/11] Renaming

---
 .../source/Commands/CommandObjectRegister.cpp | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index 4027928329bd4..e3481f8f28868 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -75,7 +75,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
 
   bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm,
                     RegisterContext &reg_ctx, const RegisterInfo &reg_info,
-                    bool print_flags, uint32_t reg_name_align_at = 0) {
+                    bool print_flags, uint32_t name_right_align_at = 0) {
     RegisterValue reg_value;
     if (!reg_ctx.ReadRegister(&reg_info, reg_value))
       return false;
@@ -86,7 +86,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
     bool prefix_with_name = !prefix_with_altname;
     DumpRegisterValue(reg_value, strm, reg_info, prefix_with_name,
                       prefix_with_altname, m_format_options.GetFormat(),
-                      reg_name_align_at, exe_ctx.GetBestExecutionContextScope(),
+                      name_right_align_at, exe_ctx.GetBestExecutionContextScope(),
                       print_flags, exe_ctx.GetTargetSP());
     if ((reg_info.encoding == eEncodingUint) ||
         (reg_info.encoding == eEncodingSint)) {
@@ -123,7 +123,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
       strm.Printf("%s:\n", (reg_set->name ? reg_set->name : "unknown"));
       strm.IndentMore();
       const size_t num_registers = reg_set->num_registers;
-      uint32_t reg_name_align_at =
+      uint32_t name_right_align_at =
           ComputeMatchingAlignment(reg_ctx, reg_set, primitive_only);
       for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
         const uint32_t reg = reg_set->registers[reg_idx];
@@ -133,7 +133,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
           continue;
 
         if (reg_info && DumpRegister(exe_ctx, strm, *reg_ctx, *reg_info,
-                                     /*print_flags=*/false, reg_name_align_at))
+                                     /*print_flags=*/false, name_right_align_at))
           ++available_count;
         else
           ++unavailable_count;
@@ -161,7 +161,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
     bool use_primary_name =
         !static_cast<bool>(m_command_options.alternate_name);
     const size_t num_registers = reg_set->num_registers;
-    uint32_t reg_name_align_at = 0;
+    uint32_t name_right_align_at = 0;
 
     // Loop through all the registers to find the longest register name for the
     // matching alignment
@@ -173,18 +173,18 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
         if (primitive_only && reg_info->value_regs)
           continue;
 
-        reg_name_align_at = std::max(reg_name_align_at, GetNameSize(reg_info, use_primary_name));
+        name_right_align_at = std::max(name_right_align_at, GetNameSize(reg_info, use_primary_name));
       }
     }
 
-    return reg_name_align_at;
+    return name_right_align_at;
   }
 
   // Here, command is basically a list of registers to be printed by DumpRegister() method
   uint32_t ComputeMatchingAlignment(Args &command, RegisterContext *reg_ctx, bool primitive_only) {
     bool use_primary_name =
         !static_cast<bool>(m_command_options.alternate_name);
-    uint32_t reg_name_align_at = 0;
+    uint32_t name_right_align_at = 0;
 
     // Loop through all the arguments to find the longest register name for the
     // matching alignment
@@ -198,11 +198,11 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
         if (primitive_only && reg_info->value_regs)
           continue;
 
-        reg_name_align_at = std::max(reg_name_align_at, GetNameSize(reg_info, use_primary_name));
+        name_right_align_at = std::max(name_right_align_at, GetNameSize(reg_info, use_primary_name));
       }
     }
 
-    return reg_name_align_at;
+    return name_right_align_at;
   }
 
   void DoExecute(Args &command, CommandReturnObject &result) override {

>From e86d228105086132f2d6890a94d1fdb5c722e1d1 Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Thu, 2 Apr 2026 15:42:21 +0200
Subject: [PATCH 09/11] A bit of bug fixing (if a register is specified, it
 must be printed, so it must be counted into alignment)

---
 lldb/source/Commands/CommandObjectRegister.cpp         | 10 ++++------
 .../command-register-read-alignment-custom-regs.test   |  6 +++---
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index e3481f8f28868..6b6f66b61ee9d 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -181,7 +181,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
   }
 
   // Here, command is basically a list of registers to be printed by DumpRegister() method
-  uint32_t ComputeMatchingAlignment(Args &command, RegisterContext *reg_ctx, bool primitive_only) {
+  uint32_t ComputeMatchingAlignment(Args &command, RegisterContext *reg_ctx) {
     bool use_primary_name =
         !static_cast<bool>(m_command_options.alternate_name);
     uint32_t name_right_align_at = 0;
@@ -194,9 +194,6 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
     
       if (const RegisterInfo *reg_info =
               reg_ctx->GetRegisterInfoByName(arg_str)) {
-        // Derived registers are skipped if primitive_only is true.
-        if (primitive_only && reg_info->value_regs)
-          continue;
 
         name_right_align_at = std::max(name_right_align_at, GetNameSize(reg_info, use_primary_name));
       }
@@ -253,8 +250,8 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
         result.AppendError("the --set <set> option can't be used when "
                            "registers names are supplied as arguments\n");
       } else {
-        int alignment = ComputeMatchingAlignment(command, reg_ctx, !m_command_options.dump_all_sets.GetCurrentValue());
-        alignment += 2; // Extra ident to be consistent with register sets dumping
+        int alignment = ComputeMatchingAlignment(command, reg_ctx);
+        strm.IndentMore(); // Extra ident to be consistent with register sets dumping
         for (auto &entry : command) {
           // in most LLDB commands we accept $rbx as the name for register RBX
           // - and here we would reject it and non-existant. we should be more
@@ -278,6 +275,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
                                          arg_str.str().c_str());
           }
         }
+        strm.IndentLess();
       }
     }
   }
diff --git a/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test b/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test
index 9871734d3835b..10def3699635d 100644
--- a/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test
+++ b/lldb/test/Shell/Commands/command-register-read-alignment-custom-regs.test
@@ -3,10 +3,10 @@
 # RUN: %clang_host -g -O0 %S/Inputs/main.c -o %t.out
 # RUN: %lldb -b -o "breakpoint set --name main" \
 # RUN:        -o run \
-# RUN:        -o "register read pc ymm7 ymm12 fs_base" \
+# RUN:        -o "register read rip rax r10d" \
 # RUN:        %t.out | FileCheck --strict-whitespace %s
 
-# CHECK: (lldb) register read pc rax r10d
-# CHECK: {{^    pc = }}
+# CHECK: (lldb) register read rip rax r10d
+# CHECK: {{^   rip = }}
 # CHECK: {{^   rax = }}
 # CHECK: {{^  r10d = }}
\ No newline at end of file

>From 6c76293bbc23d5258beed5d6b008fafc51b03b34 Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Thu, 2 Apr 2026 15:46:20 +0200
Subject: [PATCH 10/11] Function renaming [ ComputeMatchingAlignment ->
 ComputeLongestRegisterName ]

---
 lldb/source/Commands/CommandObjectRegister.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index 6b6f66b61ee9d..5410f8295e144 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -124,7 +124,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
       strm.IndentMore();
       const size_t num_registers = reg_set->num_registers;
       uint32_t name_right_align_at =
-          ComputeMatchingAlignment(reg_ctx, reg_set, primitive_only);
+          ComputeLongestRegisterName(reg_ctx, reg_set, primitive_only);
       for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
         const uint32_t reg = reg_set->registers[reg_idx];
         const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
@@ -155,7 +155,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
       return static_cast<uint32_t>(str.size());
   }
 
-  uint32_t ComputeMatchingAlignment(RegisterContext *reg_ctx,
+  uint32_t ComputeLongestRegisterName(RegisterContext *reg_ctx,
                                     const RegisterSet *const reg_set,
                                     bool primitive_only) {
     bool use_primary_name =
@@ -181,7 +181,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
   }
 
   // Here, command is basically a list of registers to be printed by DumpRegister() method
-  uint32_t ComputeMatchingAlignment(Args &command, RegisterContext *reg_ctx) {
+  uint32_t ComputeLongestRegisterName(Args &command, RegisterContext *reg_ctx) {
     bool use_primary_name =
         !static_cast<bool>(m_command_options.alternate_name);
     uint32_t name_right_align_at = 0;
@@ -250,7 +250,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
         result.AppendError("the --set <set> option can't be used when "
                            "registers names are supplied as arguments\n");
       } else {
-        int alignment = ComputeMatchingAlignment(command, reg_ctx);
+        int alignment = ComputeLongestRegisterName(command, reg_ctx);
         strm.IndentMore(); // Extra ident to be consistent with register sets dumping
         for (auto &entry : command) {
           // in most LLDB commands we accept $rbx as the name for register RBX

>From d42c91dacc4ed43f43d4186c35b9cb831acea508 Mon Sep 17 00:00:00 2001
From: Aleksandr Levin <aleksandr.levin at codasip.com>
Date: Thu, 2 Apr 2026 16:08:45 +0200
Subject: [PATCH 11/11] Made some methods to be static functions (2x
 ComputeLongestRegisterName and 1x GetNameSize)

---
 .../source/Commands/CommandObjectRegister.cpp | 103 ++++++++----------
 1 file changed, 48 insertions(+), 55 deletions(-)

diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index 5410f8295e144..920f98bbdf9b2 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -36,6 +36,52 @@ using namespace lldb_private;
 #define LLDB_OPTIONS_register_read
 #include "CommandOptions.inc"
 
+static uint32_t GetNameSize(const RegisterInfo * reg_info, bool use_primary_name) {
+    const char *raw = use_primary_name ? reg_info->name : reg_info->alt_name;
+    std::string str = raw ? std::string(raw) : std::string();
+    return static_cast<uint32_t>(str.size());
+}
+
+static uint32_t ComputeLongestRegisterName(RegisterContext *reg_ctx,
+                                    const RegisterSet *const reg_set,
+                                    bool use_primary_name, bool primitive_only) {
+  const size_t num_registers = reg_set->num_registers;
+  uint32_t name_right_align_at = 0;
+
+  // Loop through all the registers to find the longest register name
+  for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
+    const uint32_t reg = reg_set->registers[reg_idx];
+    if (const RegisterInfo *reg_info = 
+            reg_ctx->GetRegisterInfoAtIndex(reg)) {
+      // Derived registers are skipped if primitive_only is true.
+      if (primitive_only && reg_info->value_regs)
+        continue;
+
+      name_right_align_at = std::max(name_right_align_at, GetNameSize(reg_info, use_primary_name));
+    }
+  }
+
+  return name_right_align_at;
+}
+
+// Here, [command] is basically a list of registers to be printed by DumpRegister() method
+static uint32_t ComputeLongestRegisterName(Args &command, RegisterContext *reg_ctx, bool use_primary_name) {
+  uint32_t name_right_align_at = 0;
+
+  // Loop through all the arguments to find the longest register name
+  for (auto &entry : command) {
+    auto arg_str = entry.ref();
+    arg_str.consume_front("$");
+
+    if (const RegisterInfo *reg_info =
+            reg_ctx->GetRegisterInfoByName(arg_str)) {
+      name_right_align_at = std::max(name_right_align_at, GetNameSize(reg_info, use_primary_name));
+    }
+  }
+
+  return name_right_align_at;
+}
+
 class CommandObjectRegisterRead : public CommandObjectParsed {
 public:
   CommandObjectRegisterRead(CommandInterpreter &interpreter)
@@ -124,7 +170,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
       strm.IndentMore();
       const size_t num_registers = reg_set->num_registers;
       uint32_t name_right_align_at =
-          ComputeLongestRegisterName(reg_ctx, reg_set, primitive_only);
+          ComputeLongestRegisterName(reg_ctx, reg_set, !static_cast<bool>(m_command_options.alternate_name), primitive_only);
       for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
         const uint32_t reg = reg_set->registers[reg_idx];
         const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
@@ -149,59 +195,6 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
   }
 
 protected:
-  uint32_t GetNameSize(const RegisterInfo * reg_info, bool use_primary_name) {
-      const char *raw = use_primary_name ? reg_info->name : reg_info->alt_name;
-      std::string str = raw ? std::string(raw) : std::string();
-      return static_cast<uint32_t>(str.size());
-  }
-
-  uint32_t ComputeLongestRegisterName(RegisterContext *reg_ctx,
-                                    const RegisterSet *const reg_set,
-                                    bool primitive_only) {
-    bool use_primary_name =
-        !static_cast<bool>(m_command_options.alternate_name);
-    const size_t num_registers = reg_set->num_registers;
-    uint32_t name_right_align_at = 0;
-
-    // Loop through all the registers to find the longest register name for the
-    // matching alignment
-    for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
-      const uint32_t reg = reg_set->registers[reg_idx];
-      if (const RegisterInfo *reg_info = 
-              reg_ctx->GetRegisterInfoAtIndex(reg)) {
-        // Derived registers are skipped if primitive_only is true.
-        if (primitive_only && reg_info->value_regs)
-          continue;
-
-        name_right_align_at = std::max(name_right_align_at, GetNameSize(reg_info, use_primary_name));
-      }
-    }
-
-    return name_right_align_at;
-  }
-
-  // Here, command is basically a list of registers to be printed by DumpRegister() method
-  uint32_t ComputeLongestRegisterName(Args &command, RegisterContext *reg_ctx) {
-    bool use_primary_name =
-        !static_cast<bool>(m_command_options.alternate_name);
-    uint32_t name_right_align_at = 0;
-
-    // Loop through all the arguments to find the longest register name for the
-    // matching alignment
-    for (auto &entry : command) {
-      auto arg_str = entry.ref();
-      arg_str.consume_front("$");
-    
-      if (const RegisterInfo *reg_info =
-              reg_ctx->GetRegisterInfoByName(arg_str)) {
-
-        name_right_align_at = std::max(name_right_align_at, GetNameSize(reg_info, use_primary_name));
-      }
-    }
-
-    return name_right_align_at;
-  }
-
   void DoExecute(Args &command, CommandReturnObject &result) override {
     Stream &strm = result.GetOutputStream();
     RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
@@ -250,7 +243,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed {
         result.AppendError("the --set <set> option can't be used when "
                            "registers names are supplied as arguments\n");
       } else {
-        int alignment = ComputeLongestRegisterName(command, reg_ctx);
+        int alignment = ComputeLongestRegisterName(command, reg_ctx, !static_cast<bool>(m_command_options.alternate_name));
         strm.IndentMore(); // Extra ident to be consistent with register sets dumping
         for (auto &entry : command) {
           // in most LLDB commands we accept $rbx as the name for register RBX



More information about the lldb-commits mailing list