Skip to content

Conversation

@DavidSpickett
Copy link
Collaborator

@DavidSpickett DavidSpickett commented Dec 3, 2025

In https://discourse.llvm.org/t/does-lldb-qemu-support-dumping-x64-control-registers-such-as-cr3/89031 a user was not seeing certain registers when connected to QEMU. Turns out their LLDB build did not have libxml2 enabled.

While logging is not the first thing most users will think of, it is something an expert can ask for to confirm whether they have XML support enabled.

So in this PR I've shuffled the logic GetGDBServerRegisterInfo to better report problems in the log.

The key one is when lldb does not have libxml2 but the server did say it supports qxfer:features. In this case we would have used it if we could, and the debug session will likely be degraded because we are not able to.

https://sourceware.org/gdb/current/onlinedocs/gdb.html/General-Query-Packets.html#qXfer-target-description-read

…rget XML

In https://discourse.llvm.org/t/does-lldb-qemu-support-dumping-x64-control-registers-such-as-cr3/89031
a user was not seeing certain registers when connected to QEMU.
Turns out their LLDB build did not have libxml2 enabled.

While logging is not the first thing most users will think of,
it is something an expert can ask for to confirm whether they
have XML support enabled.

So in this PR I've shuffled the logic GetGDBServerRegisterInfo
to better report problems in the log.

The key one is when lldb does not have libxml2 but the server did
say it supports qxfer:features. In this case we would have used it
if we could, and the debug session will likely be degraded because
we are not able to.
@llvmbot
Copy link
Member

llvmbot commented Dec 3, 2025

@llvm/pr-subscribers-lldb

Author: David Spickett (DavidSpickett)

Changes

In https://discourse.llvm.org/t/does-lldb-qemu-support-dumping-x64-control-registers-such-as-cr3/89031 a user was not seeing certain registers when connected to QEMU. Turns out their LLDB build did not have libxml2 enabled.

While logging is not the first thing most users will think of, it is something an expert can ask for to confirm whether they have XML support enabled.

So in this PR I've shuffled the logic GetGDBServerRegisterInfo to better report problems in the log.

The key one is when lldb does not have libxml2 but the server did say it supports qxfer:features. In this case we would have used it if we could, and the debug session will likely be degraded because we are not able to.


Full diff: https://github.com/llvm/llvm-project/pull/170478.diff

2 Files Affected:

  • (modified) lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (+26-9)
  • (modified) lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (+1-1)
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 3c4d9a1f1ad37..6f45095c28977 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -441,8 +441,16 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
   if (!arch_to_use.IsValid())
     arch_to_use = target_arch;
 
-  if (GetGDBServerRegisterInfo(arch_to_use))
+  llvm::Error register_info_err = GetGDBServerRegisterInfo(arch_to_use);
+  if (!register_info_err) {
+    // We got the registers from target XML.
     return;
+  }
+
+  Log *log = GetLog(GDBRLog::Process);
+  LLDB_LOG_ERROR(log, std::move(register_info_err),
+                 "Failed to read register information from target XML: {0}");
+  LLDB_LOG(log, "Now trying to use qRegisterInfo instead.");
 
   char packet[128];
   std::vector<DynamicRegisterInfo::Register> registers;
@@ -5137,14 +5145,19 @@ void ProcessGDBRemote::AddRemoteRegisters(
 
 // query the target of gdb-remote for extended target information returns
 // true on success (got register definitions), false on failure (did not).
-bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
-  // Make sure LLDB has an XML parser it can use first
-  if (!XMLDocument::XMLEnabled())
-    return false;
-
-  // check that we have extended feature read support
+llvm::Error ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
+  // If the remote does not offer XML, does not matter if we would have been
+  // able to parse it.
   if (!m_gdb_comm.GetQXferFeaturesReadSupported())
-    return false;
+    return llvm::createStringError(
+        llvm::inconvertibleErrorCode(),
+        "The debug server does not support \"qXfer:features:read\"");
+
+  if (!XMLDocument::XMLEnabled())
+    return llvm::createStringError(
+        llvm::inconvertibleErrorCode(),
+        "The debug server supports \"qXfer:features:read\", but LLDB does not "
+        "have XML enabled (check LLLDB_ENABLE_LIBXML2)");
 
   // These hold register type information for the whole of target.xml.
   // target.xml may include further documents that
@@ -5161,7 +5174,11 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
       !registers.empty())
     AddRemoteRegisters(registers, arch_to_use);
 
-  return m_register_info_sp->GetNumRegisters() > 0;
+  return m_register_info_sp->GetNumRegisters() > 0
+             ? llvm::ErrorSuccess()
+             : llvm::createStringError(
+                   llvm::inconvertibleErrorCode(),
+                   "Debug server did not describe any registers");
 }
 
 llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() {
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index eb33b52b57441..b7e8777c9e12e 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -416,7 +416,7 @@ class ProcessGDBRemote : public Process,
   void AddRemoteRegisters(std::vector<DynamicRegisterInfo::Register> &registers,
                           const ArchSpec &arch_to_use);
   // Query remote GDBServer for register information
-  bool GetGDBServerRegisterInfo(ArchSpec &arch);
+  llvm::Error GetGDBServerRegisterInfo(ArchSpec &arch);
 
   lldb::ModuleSP LoadModuleAtAddress(const FileSpec &file,
                                      lldb::addr_t link_map,

@DavidSpickett
Copy link
Collaborator Author

DavidSpickett commented Dec 3, 2025

Some things I'm not sure on:

  1. We can report this as a warning in the debugger using Debugger::ReportWarning. It would happen only once per connection, but it could become annoying if the warning isn't relevant to you and you can't avoid it (if you have your specific reasons for having lldb configured this way).
  2. Not sure if we should be mentioning cmake options in the log message. In a sense it's too late to check that, but I wanted a way to give some hint. Then again, you'd have to know to enable the log anyway, so I can remove that hint and assume a somewhat expert is reading the log and will know what to do.

@DavidSpickett
Copy link
Collaborator Author

Also it would be cool if there was some discoverable way to check for XML support. GCC has an option that prints what it was configured with, and if you had a packaged llvm release, maybe you could find it in the cmake files. Otherwise, I don't think we have one.

Other than finding a command that happens to ingest XML but I think they're all JSON or other niche formats.

@JDevlieghere
Copy link
Member

Also it would be cool if there was some discoverable way to check for XML support. GCC has an option that prints what it was configured with, and if you had a packaged llvm release, maybe you could find it in the cmake files. Otherwise, I don't think we have one.

We have SBDebugger::GetBuildConfiguration that could cover this. We could dump this with a command line option, but I think even better would be to make this accessible through a command. Maybe we can add it behind a verbose flag for version? Happy to file an issue to track that if you agree.

@JDevlieghere
Copy link
Member

Some things I'm not sure on:

  1. We can report this as a warning in the debugger using Debugger::ReportWarning. It would happen only once per connection, but it could become annoying if the warning isn't relevant to you and you can't avoid it (if you have your specific reasons for having lldb configured this way).

I would personally prefer this option. If we're worried about it being to spammy, we could also scope it to the debugger or have a static so it's printed only once per LLDB instance. Both are kinda hacky though. Another option is to make it configurable with a setting and including the setting in the warning. The "stepping through optimized code" is another very spammy one that I've been meaning to make configurable.

  1. Not sure if we should be mentioning cmake options in the log message. In a sense it's too late to check that, but I wanted a way to give some hint. Then again, you'd have to know to enable the log anyway, so I can remove that hint and assume a somewhat expert is reading the log and will know what to do.

Given that the log is primarily intended for us as LLDB developers, I don't have any concerns with mentioning the CMake option.

@JDevlieghere
Copy link
Member

I was wondering what exactly would happen (swiftlang/swift#85345) to thanks for figuring that out and making the status quo better!

@DavidSpickett
Copy link
Collaborator Author

We have SBDebugger::GetBuildConfiguration that could cover this. We could dump this with a command line option, but I think even better would be to make this accessible through a command. Maybe we can add it behind a verbose flag for version? Happy to file an issue to track that if you agree.

Yes that would be great. Being able to see curl/python/lua/etc. settings would be a big help too.

@DavidSpickett
Copy link
Collaborator Author

I was wondering what exactly would happen (swiftlang/swift#85345) to thanks for figuring that out and making the status quo better!

I know there was work done for FreeBSD server debugging so that LLDB correctly assumes the register offsets without needing XML information. Which their server stub, I presume, does not send.

In user space they'd be using lldb-server so qRegisterInfo should convey the same information the XML would have.

@DavidSpickett
Copy link
Collaborator Author

If we're worried about it being to spammy, we could also scope it to the debugger or have a static so it's printed only once per LLDB instance. Both are kinda hacky though.

I will do this for a follow up change. Once per session makes sense, if you're reconnecting over and over, you probably don't care about the warning enough to want to see it again.

@DavidSpickett
Copy link
Collaborator Author

We can report this as a warning in the debugger using Debugger::ReportWarning.

#170663

@JDevlieghere
Copy link
Member

JDevlieghere commented Dec 4, 2025

We have SBDebugger::GetBuildConfiguration that could cover this. We could dump this with a command line option, but I think even better would be to make this accessible through a command. Maybe we can add it behind a verbose flag for version? Happy to file an issue to track that if you agree.

Yes that would be great. Being able to see curl/python/lua/etc. settings would be a big help too.

I've filed #170727 and should have a PR for this shortly.

@DavidSpickett DavidSpickett merged commit 2317347 into llvm:main Dec 5, 2025
10 checks passed
@DavidSpickett DavidSpickett deleted the lldb-no-xml branch December 5, 2025 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants