[Lldb-commits] [lldb] [lldb] Fix a typo in documentation (PR #146115)

2025-06-27 Thread Kazu Hirata via lldb-commits

https://github.com/kazutakahirata closed 
https://github.com/llvm/llvm-project/pull/146115
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] 9f5061d - [lldb] Fix a typo in documentation (#146115)

2025-06-27 Thread via lldb-commits

Author: Kazu Hirata
Date: 2025-06-27T14:26:32-07:00
New Revision: 9f5061d4f00456d882db9eb606f4a82b2c40e7a8

URL: 
https://github.com/llvm/llvm-project/commit/9f5061d4f00456d882db9eb606f4a82b2c40e7a8
DIFF: 
https://github.com/llvm/llvm-project/commit/9f5061d4f00456d882db9eb606f4a82b2c40e7a8.diff

LOG: [lldb] Fix a typo in documentation (#146115)

Added: 


Modified: 
lldb/docs/resources/contributing.rst

Removed: 




diff  --git a/lldb/docs/resources/contributing.rst 
b/lldb/docs/resources/contributing.rst
index e7d46c9061d53..7e84df41c3fbd 100644
--- a/lldb/docs/resources/contributing.rst
+++ b/lldb/docs/resources/contributing.rst
@@ -104,7 +104,7 @@ making sense for the particular pair of plugins). 
Unfortunately, due to historic
 reasons, not all plugin dependencies follow this rule, which is why we have
 another category called `LLDB_TOLERATED_PLUGIN_DEPENDENCIES`. New dependencies
 are forbidden (even though they are accepted by CMake) and existing ones should
-be removed whereever possible.
+be removed wherever possible.
 
 .. _Error handling:
 



___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Fix evaluating expressions without JIT in an object context (PR #145599)

2025-06-27 Thread Igor Kudrin via lldb-commits

https://github.com/igorkudrin closed 
https://github.com/llvm/llvm-project/pull/145599
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] 442f99d - [lldb] Fix evaluating expressions without JIT in an object context (#145599)

2025-06-27 Thread via lldb-commits

Author: Igor Kudrin
Date: 2025-06-27T14:30:24-07:00
New Revision: 442f99d7698a4ca87ebb16cb22df610c45d4698a

URL: 
https://github.com/llvm/llvm-project/commit/442f99d7698a4ca87ebb16cb22df610c45d4698a
DIFF: 
https://github.com/llvm/llvm-project/commit/442f99d7698a4ca87ebb16cb22df610c45d4698a.diff

LOG: [lldb] Fix evaluating expressions without JIT in an object context 
(#145599)

If a server does not support allocating memory in an inferior process or
when debugging a core file, evaluating an expression in the context of a
value object results in an error:

```
error: :43:1: use of undeclared identifier '$__lldb_class'
   43 | $__lldb_class::$__lldb_expr(void *$__lldb_arg)
  | ^
```

Such expressions require a live address to be stored in the value
object. However, `EntityResultVariable::Dematerialize()` only sets
`ret->m_live_sp` if JIT is available, even if the address points to the
process memory and no custom allocations were made. Similarly,
`EntityPersistentVariable::Dematerialize()` tries to deallocate memory
based on the same check, resulting in an error if the memory was not
previously allocated in `EntityPersistentVariable::Materialize()`.

As an unintended bonus, the patch also fixes a FIXME case in
`TestCxxChar8_t.py`.

Added: 
lldb/test/API/functionalities/postmortem/elf-core/expr/TestExpr.py
lldb/test/API/functionalities/postmortem/elf-core/expr/linux-x86_64.core
lldb/test/API/functionalities/postmortem/elf-core/expr/linux-x86_64.out
lldb/test/API/functionalities/postmortem/elf-core/expr/main.cpp

Modified: 
lldb/include/lldb/Expression/IRMemoryMap.h
lldb/source/Expression/IRMemoryMap.cpp
lldb/source/Expression/Materializer.cpp
lldb/test/API/lang/cpp/char8_t/TestCxxChar8_t.py

Removed: 




diff  --git a/lldb/include/lldb/Expression/IRMemoryMap.h 
b/lldb/include/lldb/Expression/IRMemoryMap.h
index acbffd1e40b94..58b95c56c1c36 100644
--- a/lldb/include/lldb/Expression/IRMemoryMap.h
+++ b/lldb/include/lldb/Expression/IRMemoryMap.h
@@ -51,10 +51,13 @@ class IRMemoryMap {
  ///only in the process.
   };
 
+  // If 'policy' is 'eAllocationPolicyMirror' but it is impossible to allocate
+  // memory in the process, 'eAllocationPolicyHostOnly' will be used instead.
+  // The actual policy is returned via 'used_policy'.
   llvm::Expected Malloc(size_t size, uint8_t alignment,
   uint32_t permissions,
-  AllocationPolicy policy,
-  bool zero_memory);
+  AllocationPolicy policy, bool 
zero_memory,
+  AllocationPolicy *used_policy = nullptr);
   void Leak(lldb::addr_t process_address, Status &error);
   void Free(lldb::addr_t process_address, Status &error);
 

diff  --git a/lldb/source/Expression/IRMemoryMap.cpp 
b/lldb/source/Expression/IRMemoryMap.cpp
index f500272cfb302..150699352a2e3 100644
--- a/lldb/source/Expression/IRMemoryMap.cpp
+++ b/lldb/source/Expression/IRMemoryMap.cpp
@@ -319,10 +319,10 @@ IRMemoryMap::Allocation::Allocation(lldb::addr_t 
process_alloc,
   }
 }
 
-llvm::Expected IRMemoryMap::Malloc(size_t size, uint8_t 
alignment,
- uint32_t permissions,
- AllocationPolicy policy,
- bool zero_memory) {
+llvm::Expected
+IRMemoryMap::Malloc(size_t size, uint8_t alignment, uint32_t permissions,
+AllocationPolicy policy, bool zero_memory,
+AllocationPolicy *used_policy) {
   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
 
   lldb::ProcessSP process_sp;
@@ -454,6 +454,9 @@ llvm::Expected IRMemoryMap::Malloc(size_t 
size, uint8_t alignment,
   (uint64_t)permissions, policy_string, aligned_address);
   }
 
+  if (used_policy)
+*used_policy = policy;
+
   return aligned_address;
 }
 

diff  --git a/lldb/source/Expression/Materializer.cpp 
b/lldb/source/Expression/Materializer.cpp
index 96add56f92180..17ea1596806d0 100644
--- a/lldb/source/Expression/Materializer.cpp
+++ b/lldb/source/Expression/Materializer.cpp
@@ -75,11 +75,12 @@ class EntityPersistentVariable : public 
Materializer::Entity {
 // contents.
 
 const bool zero_memory = false;
+IRMemoryMap::AllocationPolicy used_policy;
 auto address_or_error = map.Malloc(
 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
 .value_or(0),
 8, lldb::ePermissionsReadable | lldb::ePermissionsWritable,
-IRMemoryMap::eAllocationPolicyMirror, zero_memory);
+IRMemoryMap::eAllocationPolicyMirror, zero_memory, &used_policy);
 if (!address_or_error) {
   err = Status::FromErrorStringWithFormat(
   "couldn't allocate a memory area to store %

[Lldb-commits] [lldb] Add option to not loading all DWOs when dumping separate_debug-info (PR #146166)

2025-06-27 Thread via lldb-commits

llvmbot wrote:




@llvm/pr-subscribers-lldb

Author: None (qxy11)


Changes

### Summary
Currently `target modules dump separate separate-debug-info` automatically 
loads up all DWO files, even if deferred loading is enabled through 
debug_names. Then, as expected all DWO files (assuming there is no error 
loading it), get marked as "loaded".

This change adds the option `--defer-load-all-debug-info` or `--d` for short to 
dump this debug info without loading it up, if it hasn't been loaded yet, so 
that the correct DWO files will show up for each modules as "loaded" or not 
"loaded", which could be helpful in cases such as when DWO files are not 
getting loaded eagerly for correctly labeling files as loaded or not loaded.

### Testing
 Unit Tests
Added additional unit tests `test_dwos_defer_loaded_json_with_debug_names` and 
`test_dwos_loaded_symbols_on_demand_defer_load_all`.
```
bin/lldb-dotest -p TestDumpDwo 
~/llvm-project/lldb/test/API/commands/target/dump-separate-debug-info/dwo
```

 Manual Testing
Compiled a simple binary w/ `--gsplit-dwarf --gpubnames` and loaded it up:
```
(lldb) target create "./a.out"
Current executable set to '/home/qxy11/hello-world/a.out' (x86_64).
(lldb) help target modules dump separate-debug-info
List the separate debug info symbol files for one or more target modules.

Syntax: target modules dump separate-debug-info  
[ [ [...]]]

Command Options Usage:
  target modules dump separate-debug-info [-dej] [ 
[ [...]]]

   -d ( --defer-load-all-debug-info )
Defer loading all debug info files.

   -e ( --errors-only )
Filter to show only debug info files with errors.

   -j ( --json )
Output the details in JSON format.

 This command takes options and free-form arguments.  If your arguments 
resemble option specifiers (i.e., they start with a - or --), you must use ' -- 
' between the end of
 the command options and the beginning of the arguments.
(lldb) target modules dump separate-debug-info --j --d
[
  {
"separate-debug-info-files": [
  {  ...
"dwo_name": "main.dwo",
"loaded": false
  },
  {  ...
"dwo_name": "foo.dwo",
"loaded": false
  },
  { ...
"dwo_name": "bar.dwo",
"loaded": false
  }
],
  }
]
(lldb) b main
Breakpoint 1: where = a.out`main + 15 at main.cc:3:12, address = 
0x11ff
(lldb) target modules dump separate-debug-info --j --d
[
  {
"separate-debug-info-files": [
  { ...
"dwo_name": "main.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/main.dwo"
  },
  { ...
"dwo_name": "foo.dwo",
"loaded": false
  },
  { ...
"dwo_name": "bar.dwo",
"loaded": false
  }
],
  }
]
(lldb) b foo
Breakpoint 2: where = a.out`foo(int) + 11 at foo.cc:12:11, address = 
0x121b
(lldb) target modules dump separate-debug-info --j --d
[
  {
"separate-debug-info-files": [
  { ...
"dwo_name": "main.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/main.dwo"
  },
  { ...
"dwo_name": "foo.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/foo.dwo"
  },
  { ...
"dwo_name": "bar.dwo",
"loaded": false
  }
],
  }
]
(lldb) b bar
Breakpoint 3: where = a.out`bar(int) + 11 at bar.cc:10:9, address = 
0x126b
(lldb) target modules dump separate-debug-info --j --d
[
  {
"separate-debug-info-files": [
  { ...
"dwo_name": "main.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/main.dwo"
  },
  { ...
"dwo_name": "foo.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/foo.dwo"
  },
  { ...
"dwo_name": "bar.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/bar.dwo"
  }
],
  }
]
```


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


10 Files Affected:

- (modified) lldb/include/lldb/Symbol/SymbolFile.h (+4-1) 
- (modified) lldb/include/lldb/Symbol/SymbolFileOnDemand.h (+4-3) 
- (modified) lldb/source/Commands/CommandObjectTarget.cpp (+41-24) 
- (modified) lldb/source/Commands/Options.td (+3) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+3-2) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (+2-2) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp 
(+2-1) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h 
(+2-2) 
- (modified) 
lldb/test/API/commands/target/dump-separate-debug-info/dwo/Makefile (+1-1) 
- (modified) 
lldb/test/API/commands/target/dump-separate-debug-info/dwo/TestDumpDwo.py 
(+75-2) 


``diff
diff --git a/lldb/include/lldb/Symbol/SymbolFile.h 
b/lldb/incl

[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread John Harrison via lldb-commits

https://github.com/ashgti updated 
https://github.com/llvm/llvm-project/pull/145621

>From 79c10b6f6630b3ceaa85af45956aeafdf372b5be Mon Sep 17 00:00:00 2001
From: John Harrison 
Date: Wed, 25 Jun 2025 18:03:39 -0700
Subject: [PATCH 1/5] [lldb] Adding file and pipe support to
 lldb_private::MainLoopWindows.

This updates MainLoopWindows to support events for reading from a file and a 
socket type.

This unifies both handle types using WaitForMultipleEvents which can listen to 
both sockets and files for change events.

This should allow us to unify how we handle watching files/pipes/sockets on 
Windows and Posix systems.
---
 lldb/include/lldb/Host/File.h |   2 +
 lldb/include/lldb/Host/Socket.h   |   2 +
 .../lldb/Host/windows/MainLoopWindows.h   |   3 +-
 lldb/include/lldb/Utility/IOObject.h  |   8 +-
 lldb/source/Host/common/File.cpp  |  18 +++
 lldb/source/Host/common/Socket.cpp|  49 +++-
 .../posix/ConnectionFileDescriptorPosix.cpp   |  14 ++-
 lldb/source/Host/windows/MainLoopWindows.cpp  | 116 +-
 lldb/source/Utility/IOObject.cpp  |   9 ++
 lldb/unittests/Host/FileTest.cpp  |  16 ++-
 lldb/unittests/Host/MainLoopTest.cpp  |  26 
 11 files changed, 190 insertions(+), 73 deletions(-)

diff --git a/lldb/include/lldb/Host/File.h b/lldb/include/lldb/Host/File.h
index 9e2d0abe0b1af..36cb192281289 100644
--- a/lldb/include/lldb/Host/File.h
+++ b/lldb/include/lldb/Host/File.h
@@ -127,6 +127,7 @@ class File : public IOObject {
   /// \return
   /// a valid handle or IOObject::kInvalidHandleValue
   WaitableHandle GetWaitableHandle() override;
+  bool HasReadableData() override;
 
   /// Get the file specification for this file, if possible.
   ///
@@ -400,6 +401,7 @@ class NativeFile : public File {
   Status Write(const void *buf, size_t &num_bytes) override;
   Status Close() override;
   WaitableHandle GetWaitableHandle() override;
+  bool HasReadableData() override;
   Status GetFileSpec(FileSpec &file_spec) const override;
   int GetDescriptor() const override;
   FILE *GetStream() override;
diff --git a/lldb/include/lldb/Host/Socket.h b/lldb/include/lldb/Host/Socket.h
index 89953ee7fd5b6..6569e9e6ea818 100644
--- a/lldb/include/lldb/Host/Socket.h
+++ b/lldb/include/lldb/Host/Socket.h
@@ -158,6 +158,7 @@ class Socket : public IOObject {
 
   bool IsValid() const override { return m_socket != kInvalidSocketValue; }
   WaitableHandle GetWaitableHandle() override;
+  bool HasReadableData() override;
 
   static llvm::Expected
   DecodeHostAndPort(llvm::StringRef host_and_port);
@@ -185,6 +186,7 @@ class Socket : public IOObject {
 
   SocketProtocol m_protocol;
   NativeSocket m_socket;
+  WaitableHandle m_waitable_handle;
   bool m_should_close_fd;
 };
 
diff --git a/lldb/include/lldb/Host/windows/MainLoopWindows.h 
b/lldb/include/lldb/Host/windows/MainLoopWindows.h
index 3937a24645d95..43b7d13a0e445 100644
--- a/lldb/include/lldb/Host/windows/MainLoopWindows.h
+++ b/lldb/include/lldb/Host/windows/MainLoopWindows.h
@@ -37,11 +37,10 @@ class MainLoopWindows : public MainLoopBase {
   void Interrupt() override;
 
 private:
-  void ProcessReadObject(IOObject::WaitableHandle handle);
   llvm::Expected Poll();
 
   struct FdInfo {
-void *event;
+lldb::IOObjectSP object_sp;
 Callback callback;
   };
   llvm::DenseMap m_read_fds;
diff --git a/lldb/include/lldb/Utility/IOObject.h 
b/lldb/include/lldb/Utility/IOObject.h
index 8cf42992e7be5..48a8a2076581f 100644
--- a/lldb/include/lldb/Utility/IOObject.h
+++ b/lldb/include/lldb/Utility/IOObject.h
@@ -14,6 +14,7 @@
 #include 
 
 #include "lldb/lldb-private.h"
+#include "lldb/lldb-types.h"
 
 namespace lldb_private {
 
@@ -24,9 +25,9 @@ class IOObject {
 eFDTypeSocket, // Socket requiring send/recv
   };
 
-  // TODO: On Windows this should be a HANDLE, and wait should use
-  // WaitForMultipleObjects
-  typedef int WaitableHandle;
+  // A handle for integrating with the host event loop model.
+  using WaitableHandle = lldb::file_t;
+
   static const WaitableHandle kInvalidHandleValue;
 
   IOObject(FDType type) : m_fd_type(type) {}
@@ -40,6 +41,7 @@ class IOObject {
   FDType GetFdType() const { return m_fd_type; }
 
   virtual WaitableHandle GetWaitableHandle() = 0;
+  virtual bool HasReadableData() = 0;
 
 protected:
   FDType m_fd_type;
diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp
index 9aa95ffda44cb..2d33f9e2028c4 100644
--- a/lldb/source/Host/common/File.cpp
+++ b/lldb/source/Host/common/File.cpp
@@ -118,6 +118,8 @@ IOObject::WaitableHandle File::GetWaitableHandle() {
   return IOObject::kInvalidHandleValue;
 }
 
+bool File::HasReadableData() { return false; }
+
 Status File::GetFileSpec(FileSpec &file_spec) const {
   file_spec.Clear();
   return std::error_code(ENOTSUP, std::system_category());
@@ -274,7 +276,23 @@ int NativeFile::GetDescriptor() const {
 }
 
 IOObject::WaitableHandle N

[Lldb-commits] [lldb] Add option to not loading all DWOs when dumping separate_debug-info (PR #146166)

2025-06-27 Thread via lldb-commits

https://github.com/qxy11 created 
https://github.com/llvm/llvm-project/pull/146166

### Summary
Currently `target modules dump separate separate-debug-info` automatically 
loads up all DWO files, even if deferred loading is enabled through 
debug_names. Then, as expected all DWO files (assuming there is no error 
loading it), get marked as "loaded".

This change adds the option `--defer-load-all-debug-info` or `--d` for short to 
dump this debug info without loading it up, if it hasn't been loaded yet, so 
that the correct DWO files will show up for each modules as "loaded" or not 
"loaded", which could be helpful in cases such as when DWO files are not 
getting loaded eagerly for correctly labeling files as loaded or not loaded.

### Testing
 Unit Tests
Added additional unit tests `test_dwos_defer_loaded_json_with_debug_names` and 
`test_dwos_loaded_symbols_on_demand_defer_load_all`.
```
bin/lldb-dotest -p TestDumpDwo 
~/llvm-project/lldb/test/API/commands/target/dump-separate-debug-info/dwo
```

 Manual Testing
Compiled a simple binary w/ `--gsplit-dwarf --gpubnames` and loaded it up:
```
(lldb) target create "./a.out"
Current executable set to '/home/qxy11/hello-world/a.out' (x86_64).
(lldb) help target modules dump separate-debug-info
List the separate debug info symbol files for one or more target modules.

Syntax: target modules dump separate-debug-info  [ 
[ [...]]]

Command Options Usage:
  target modules dump separate-debug-info [-dej] [ [ [...]]]

   -d ( --defer-load-all-debug-info )
Defer loading all debug info files.

   -e ( --errors-only )
Filter to show only debug info files with errors.

   -j ( --json )
Output the details in JSON format.

 This command takes options and free-form arguments.  If your arguments 
resemble option specifiers (i.e., they start with a - or --), you must use ' -- 
' between the end of
 the command options and the beginning of the arguments.
(lldb) target modules dump separate-debug-info --j --d
[
  {
"separate-debug-info-files": [
  {  ...
"dwo_name": "main.dwo",
"loaded": false
  },
  {  ...
"dwo_name": "foo.dwo",
"loaded": false
  },
  { ...
"dwo_name": "bar.dwo",
"loaded": false
  }
],
  }
]
(lldb) b main
Breakpoint 1: where = a.out`main + 15 at main.cc:3:12, address = 
0x11ff
(lldb) target modules dump separate-debug-info --j --d
[
  {
"separate-debug-info-files": [
  { ...
"dwo_name": "main.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/main.dwo"
  },
  { ...
"dwo_name": "foo.dwo",
"loaded": false
  },
  { ...
"dwo_name": "bar.dwo",
"loaded": false
  }
],
  }
]
(lldb) b foo
Breakpoint 2: where = a.out`foo(int) + 11 at foo.cc:12:11, address = 
0x121b
(lldb) target modules dump separate-debug-info --j --d
[
  {
"separate-debug-info-files": [
  { ...
"dwo_name": "main.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/main.dwo"
  },
  { ...
"dwo_name": "foo.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/foo.dwo"
  },
  { ...
"dwo_name": "bar.dwo",
"loaded": false
  }
],
  }
]
(lldb) b bar
Breakpoint 3: where = a.out`bar(int) + 11 at bar.cc:10:9, address = 
0x126b
(lldb) target modules dump separate-debug-info --j --d
[
  {
"separate-debug-info-files": [
  { ...
"dwo_name": "main.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/main.dwo"
  },
  { ...
"dwo_name": "foo.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/foo.dwo"
  },
  { ...
"dwo_name": "bar.dwo",
"loaded": true,
"resolved_dwo_path": "/home/qxy11/hello-world/bar.dwo"
  }
],
  }
]
```


>From 65cdc870c365592f354663eabf1a009e4bdd3c52 Mon Sep 17 00:00:00 2001
From: Janet Yang 
Date: Wed, 18 Jun 2025 15:58:10 -0700
Subject: [PATCH] Add defer-load-all-debug-info option to dumping
 separate_debug-info

The target modules dump separate separate-debug-info option
automatically loads up all DWO files, even if deferred loading is
enabled through debug_names.

This adds the option to get the debug info without loading it up, if
it hasn't been loaded yet, so that the correct DWO files will show up
for each modules as "loaded" or not "loaded", which could be more
informational to the user.
---
 lldb/include/lldb/Symbol/SymbolFile.h |  5 +-
 lldb/include/lldb/Symbol/SymbolFileOnDemand.h |  7 +-
 lldb/source/Commands/CommandObjectTarget.cpp  | 65 ++--
 lldb/source/Commands/Options.td   |  3 +
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp  |  5 +-
 .../SymbolFile/DWARF/SymbolFileDWARF.h|  4 +-
 .../DWARF/SymbolFileDWARFDe

[Lldb-commits] [lldb] [lldb] Adding pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread John Harrison via lldb-commits

https://github.com/ashgti edited 
https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits

https://github.com/jasonmolenda updated 
https://github.com/llvm/llvm-project/pull/144627

>From 92348b28fb02901e9437b92c1ddf8cfed31c Mon Sep 17 00:00:00 2001
From: Jason Molenda 
Date: Tue, 17 Jun 2025 18:57:11 -0700
Subject: [PATCH 01/13] [lldb][Mach-O] Allow "process metadata" LC_NOTE to
 supply registers

The "process metadata" LC_NOTE allows for thread IDs to be specified
in a Mach-O corefile.  This extends the JSON recognzied in that
LC_NOTE to allow for additional registers to be supplied on a
per-thread basis.

The registers included in a Mach-O corefile LC_THREAD load command
can only be one of the register flavors that the kernel (xnu) defines
in  for arm64 -- the general purpose
registers, floating point registers, exception registers.

JTAG style corefile producers may have access to many additional
registers beyond these that EL0 programs typically use, for instance
TCR_EL1 on AArch64, and people developing low level code need access
to these registers.  This patch defines a format for including these
registers for any thread.

The JSON in "process metadata" is a dictionary that must have a
`threads` key.  The value is an array of entries, one per LC_THREAD
in the Mach-O corefile.  The number of entries must match the
LC_THREADs so they can be correctly associated.

Each thread's dictionary must have two keys, `sets`, and `registers`.
`sets` is an array of register set names.  If a register set name
matches one from the LC_THREAD core registers, any registers that
are defined will be added to that register set.  e.g. metadata can
add a register to the "General Purpose Registers" set that lldb
shows users.

`registers` is an array of dictionaries, one per register.  Each
register must have the keys `name`, `value`, `bitsize`, and `set`.
It may provide additional keys like `alt-name`, that
`DynamicRegisterInfo::SetRegisterInfo` recognizes.

This `sets` + `registers` formatting is the same that is used by
the `target.process.python-os-plugin-path` script interface uses,
both are parsed by `DynamicRegisterInfo`.  The one addition is that
in this LC_NOTE metadata, each register must also have a `value`
field, with the value provided in big-endian base 10, as usual with
JSON.

In RegisterContextUnifiedCore, I combine the register sets & registers
from the LC_THREAD for a specific thread, and the metadata sets &
registers for that thread from the LC_NOTE.  Even if no LC_NOTE
is present, this class ingests the LC_THREAD register contexts and
reformats it to its internal stores before returning itself as the
RegisterContex, instead of shortcutting and returning the core's
native RegisterContext.  I could have gone either way with that,
but in the end I decided if the code is correct, we should live on
it always.

I added a test where we process save-core to create a userland corefile,
then use a utility "add-lcnote" to strip the existing "process metadata"
LC_NOTE that lldb put in it, and adds a new one from a JSON string.

rdar://74358787
---
 lldb/include/lldb/Symbol/ObjectFile.h |  17 +-
 .../ObjectFile/Mach-O/ObjectFileMachO.cpp |  61 ++-
 .../ObjectFile/Mach-O/ObjectFileMachO.h   |   2 +
 .../Plugins/Process/mach-core/CMakeLists.txt  |   1 +
 .../mach-core/RegisterContextUnifiedCore.cpp  | 293 +
 .../mach-core/RegisterContextUnifiedCore.h|  57 +++
 .../Process/mach-core/ThreadMachCore.cpp  |  55 ++-
 .../lc-note/additional-registers/Makefile |  11 +
 .../TestMetadataRegisters.py  | 100 +
 .../additional-registers/add-lcnote.cpp   | 384 ++
 .../lc-note/additional-registers/main.c   |  11 +
 11 files changed, 957 insertions(+), 35 deletions(-)
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.cpp
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.h
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/Makefile
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/TestMetadataRegisters.py
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/add-lcnote.cpp
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/main.c

diff --git a/lldb/include/lldb/Symbol/ObjectFile.h 
b/lldb/include/lldb/Symbol/ObjectFile.h
index 43567592dd447..1b9ae1fb31a69 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -18,6 +18,7 @@
 #include "lldb/Utility/Endian.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/FileSpecList.h"
+#include "lldb/Utility/StructuredData.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-private.h"
 #include "llvm/Support/Threading.h"
@@ -544,9 +545,9 @@ class ObjectFile : public 
std::enable_shared_from_this,
 return false;
   }
 
-  /// Get metadata about threads from the corefile.
+  /// Get metadata about thread ids from the corefile.
   ///
-  /// The corefile may have metadata (e.g. a Mach-O "thread ext

[Lldb-commits] [lldb] Add option to not loading all DWOs when dumping separate_debug-info (PR #146166)

2025-06-27 Thread David Peixotto via lldb-commits


@@ -2547,6 +2561,7 @@ class CommandObjectTargetModulesDumpSeparateDebugInfoFiles
 
 OptionValueBoolean m_json = false;
 OptionValueBoolean m_errors_only = false;
+OptionValueBoolean m_load_all_debug_info = true;

dmpots wrote:

I wonder if it would be better to disable loading all of the debug info by 
default. Then instead of adding the `--defer-load-all-debug-info` flag we could 
add a flag like `--force-load-all-debug-info` that would force loading it.

It seems a bit odd to me that a `dump` command would modify state like this by 
default by loading up the debug info instead of reporting the current state. 
But this would be a behavior change from the current lldb so maybe not 
desirable.

@JDevlieghere @jeffreytan81 @clayborg any thoughts on this?

https://github.com/llvm/llvm-project/pull/146166
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits

https://github.com/jasonmolenda updated 
https://github.com/llvm/llvm-project/pull/144627

>From 92348b28fb02901e9437b92c1ddf8cfed31c Mon Sep 17 00:00:00 2001
From: Jason Molenda 
Date: Tue, 17 Jun 2025 18:57:11 -0700
Subject: [PATCH 01/17] [lldb][Mach-O] Allow "process metadata" LC_NOTE to
 supply registers

The "process metadata" LC_NOTE allows for thread IDs to be specified
in a Mach-O corefile.  This extends the JSON recognzied in that
LC_NOTE to allow for additional registers to be supplied on a
per-thread basis.

The registers included in a Mach-O corefile LC_THREAD load command
can only be one of the register flavors that the kernel (xnu) defines
in  for arm64 -- the general purpose
registers, floating point registers, exception registers.

JTAG style corefile producers may have access to many additional
registers beyond these that EL0 programs typically use, for instance
TCR_EL1 on AArch64, and people developing low level code need access
to these registers.  This patch defines a format for including these
registers for any thread.

The JSON in "process metadata" is a dictionary that must have a
`threads` key.  The value is an array of entries, one per LC_THREAD
in the Mach-O corefile.  The number of entries must match the
LC_THREADs so they can be correctly associated.

Each thread's dictionary must have two keys, `sets`, and `registers`.
`sets` is an array of register set names.  If a register set name
matches one from the LC_THREAD core registers, any registers that
are defined will be added to that register set.  e.g. metadata can
add a register to the "General Purpose Registers" set that lldb
shows users.

`registers` is an array of dictionaries, one per register.  Each
register must have the keys `name`, `value`, `bitsize`, and `set`.
It may provide additional keys like `alt-name`, that
`DynamicRegisterInfo::SetRegisterInfo` recognizes.

This `sets` + `registers` formatting is the same that is used by
the `target.process.python-os-plugin-path` script interface uses,
both are parsed by `DynamicRegisterInfo`.  The one addition is that
in this LC_NOTE metadata, each register must also have a `value`
field, with the value provided in big-endian base 10, as usual with
JSON.

In RegisterContextUnifiedCore, I combine the register sets & registers
from the LC_THREAD for a specific thread, and the metadata sets &
registers for that thread from the LC_NOTE.  Even if no LC_NOTE
is present, this class ingests the LC_THREAD register contexts and
reformats it to its internal stores before returning itself as the
RegisterContex, instead of shortcutting and returning the core's
native RegisterContext.  I could have gone either way with that,
but in the end I decided if the code is correct, we should live on
it always.

I added a test where we process save-core to create a userland corefile,
then use a utility "add-lcnote" to strip the existing "process metadata"
LC_NOTE that lldb put in it, and adds a new one from a JSON string.

rdar://74358787
---
 lldb/include/lldb/Symbol/ObjectFile.h |  17 +-
 .../ObjectFile/Mach-O/ObjectFileMachO.cpp |  61 ++-
 .../ObjectFile/Mach-O/ObjectFileMachO.h   |   2 +
 .../Plugins/Process/mach-core/CMakeLists.txt  |   1 +
 .../mach-core/RegisterContextUnifiedCore.cpp  | 293 +
 .../mach-core/RegisterContextUnifiedCore.h|  57 +++
 .../Process/mach-core/ThreadMachCore.cpp  |  55 ++-
 .../lc-note/additional-registers/Makefile |  11 +
 .../TestMetadataRegisters.py  | 100 +
 .../additional-registers/add-lcnote.cpp   | 384 ++
 .../lc-note/additional-registers/main.c   |  11 +
 11 files changed, 957 insertions(+), 35 deletions(-)
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.cpp
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.h
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/Makefile
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/TestMetadataRegisters.py
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/add-lcnote.cpp
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/main.c

diff --git a/lldb/include/lldb/Symbol/ObjectFile.h 
b/lldb/include/lldb/Symbol/ObjectFile.h
index 43567592dd447..1b9ae1fb31a69 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -18,6 +18,7 @@
 #include "lldb/Utility/Endian.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/FileSpecList.h"
+#include "lldb/Utility/StructuredData.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-private.h"
 #include "llvm/Support/Threading.h"
@@ -544,9 +545,9 @@ class ObjectFile : public 
std::enable_shared_from_this,
 return false;
   }
 
-  /// Get metadata about threads from the corefile.
+  /// Get metadata about thread ids from the corefile.
   ///
-  /// The corefile may have metadata (e.g. a Mach-O "thread ext

[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits

https://github.com/jasonmolenda updated 
https://github.com/llvm/llvm-project/pull/144627

>From 92348b28fb02901e9437b92c1ddf8cfed31c Mon Sep 17 00:00:00 2001
From: Jason Molenda 
Date: Tue, 17 Jun 2025 18:57:11 -0700
Subject: [PATCH 01/16] [lldb][Mach-O] Allow "process metadata" LC_NOTE to
 supply registers

The "process metadata" LC_NOTE allows for thread IDs to be specified
in a Mach-O corefile.  This extends the JSON recognzied in that
LC_NOTE to allow for additional registers to be supplied on a
per-thread basis.

The registers included in a Mach-O corefile LC_THREAD load command
can only be one of the register flavors that the kernel (xnu) defines
in  for arm64 -- the general purpose
registers, floating point registers, exception registers.

JTAG style corefile producers may have access to many additional
registers beyond these that EL0 programs typically use, for instance
TCR_EL1 on AArch64, and people developing low level code need access
to these registers.  This patch defines a format for including these
registers for any thread.

The JSON in "process metadata" is a dictionary that must have a
`threads` key.  The value is an array of entries, one per LC_THREAD
in the Mach-O corefile.  The number of entries must match the
LC_THREADs so they can be correctly associated.

Each thread's dictionary must have two keys, `sets`, and `registers`.
`sets` is an array of register set names.  If a register set name
matches one from the LC_THREAD core registers, any registers that
are defined will be added to that register set.  e.g. metadata can
add a register to the "General Purpose Registers" set that lldb
shows users.

`registers` is an array of dictionaries, one per register.  Each
register must have the keys `name`, `value`, `bitsize`, and `set`.
It may provide additional keys like `alt-name`, that
`DynamicRegisterInfo::SetRegisterInfo` recognizes.

This `sets` + `registers` formatting is the same that is used by
the `target.process.python-os-plugin-path` script interface uses,
both are parsed by `DynamicRegisterInfo`.  The one addition is that
in this LC_NOTE metadata, each register must also have a `value`
field, with the value provided in big-endian base 10, as usual with
JSON.

In RegisterContextUnifiedCore, I combine the register sets & registers
from the LC_THREAD for a specific thread, and the metadata sets &
registers for that thread from the LC_NOTE.  Even if no LC_NOTE
is present, this class ingests the LC_THREAD register contexts and
reformats it to its internal stores before returning itself as the
RegisterContex, instead of shortcutting and returning the core's
native RegisterContext.  I could have gone either way with that,
but in the end I decided if the code is correct, we should live on
it always.

I added a test where we process save-core to create a userland corefile,
then use a utility "add-lcnote" to strip the existing "process metadata"
LC_NOTE that lldb put in it, and adds a new one from a JSON string.

rdar://74358787
---
 lldb/include/lldb/Symbol/ObjectFile.h |  17 +-
 .../ObjectFile/Mach-O/ObjectFileMachO.cpp |  61 ++-
 .../ObjectFile/Mach-O/ObjectFileMachO.h   |   2 +
 .../Plugins/Process/mach-core/CMakeLists.txt  |   1 +
 .../mach-core/RegisterContextUnifiedCore.cpp  | 293 +
 .../mach-core/RegisterContextUnifiedCore.h|  57 +++
 .../Process/mach-core/ThreadMachCore.cpp  |  55 ++-
 .../lc-note/additional-registers/Makefile |  11 +
 .../TestMetadataRegisters.py  | 100 +
 .../additional-registers/add-lcnote.cpp   | 384 ++
 .../lc-note/additional-registers/main.c   |  11 +
 11 files changed, 957 insertions(+), 35 deletions(-)
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.cpp
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.h
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/Makefile
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/TestMetadataRegisters.py
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/add-lcnote.cpp
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/main.c

diff --git a/lldb/include/lldb/Symbol/ObjectFile.h 
b/lldb/include/lldb/Symbol/ObjectFile.h
index 43567592dd447..1b9ae1fb31a69 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -18,6 +18,7 @@
 #include "lldb/Utility/Endian.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/FileSpecList.h"
+#include "lldb/Utility/StructuredData.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-private.h"
 #include "llvm/Support/Threading.h"
@@ -544,9 +545,9 @@ class ObjectFile : public 
std::enable_shared_from_this,
 return false;
   }
 
-  /// Get metadata about threads from the corefile.
+  /// Get metadata about thread ids from the corefile.
   ///
-  /// The corefile may have metadata (e.g. a Mach-O "thread ext

[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits

https://github.com/jasonmolenda updated 
https://github.com/llvm/llvm-project/pull/144627

>From 92348b28fb02901e9437b92c1ddf8cfed31c Mon Sep 17 00:00:00 2001
From: Jason Molenda 
Date: Tue, 17 Jun 2025 18:57:11 -0700
Subject: [PATCH 01/15] [lldb][Mach-O] Allow "process metadata" LC_NOTE to
 supply registers

The "process metadata" LC_NOTE allows for thread IDs to be specified
in a Mach-O corefile.  This extends the JSON recognzied in that
LC_NOTE to allow for additional registers to be supplied on a
per-thread basis.

The registers included in a Mach-O corefile LC_THREAD load command
can only be one of the register flavors that the kernel (xnu) defines
in  for arm64 -- the general purpose
registers, floating point registers, exception registers.

JTAG style corefile producers may have access to many additional
registers beyond these that EL0 programs typically use, for instance
TCR_EL1 on AArch64, and people developing low level code need access
to these registers.  This patch defines a format for including these
registers for any thread.

The JSON in "process metadata" is a dictionary that must have a
`threads` key.  The value is an array of entries, one per LC_THREAD
in the Mach-O corefile.  The number of entries must match the
LC_THREADs so they can be correctly associated.

Each thread's dictionary must have two keys, `sets`, and `registers`.
`sets` is an array of register set names.  If a register set name
matches one from the LC_THREAD core registers, any registers that
are defined will be added to that register set.  e.g. metadata can
add a register to the "General Purpose Registers" set that lldb
shows users.

`registers` is an array of dictionaries, one per register.  Each
register must have the keys `name`, `value`, `bitsize`, and `set`.
It may provide additional keys like `alt-name`, that
`DynamicRegisterInfo::SetRegisterInfo` recognizes.

This `sets` + `registers` formatting is the same that is used by
the `target.process.python-os-plugin-path` script interface uses,
both are parsed by `DynamicRegisterInfo`.  The one addition is that
in this LC_NOTE metadata, each register must also have a `value`
field, with the value provided in big-endian base 10, as usual with
JSON.

In RegisterContextUnifiedCore, I combine the register sets & registers
from the LC_THREAD for a specific thread, and the metadata sets &
registers for that thread from the LC_NOTE.  Even if no LC_NOTE
is present, this class ingests the LC_THREAD register contexts and
reformats it to its internal stores before returning itself as the
RegisterContex, instead of shortcutting and returning the core's
native RegisterContext.  I could have gone either way with that,
but in the end I decided if the code is correct, we should live on
it always.

I added a test where we process save-core to create a userland corefile,
then use a utility "add-lcnote" to strip the existing "process metadata"
LC_NOTE that lldb put in it, and adds a new one from a JSON string.

rdar://74358787
---
 lldb/include/lldb/Symbol/ObjectFile.h |  17 +-
 .../ObjectFile/Mach-O/ObjectFileMachO.cpp |  61 ++-
 .../ObjectFile/Mach-O/ObjectFileMachO.h   |   2 +
 .../Plugins/Process/mach-core/CMakeLists.txt  |   1 +
 .../mach-core/RegisterContextUnifiedCore.cpp  | 293 +
 .../mach-core/RegisterContextUnifiedCore.h|  57 +++
 .../Process/mach-core/ThreadMachCore.cpp  |  55 ++-
 .../lc-note/additional-registers/Makefile |  11 +
 .../TestMetadataRegisters.py  | 100 +
 .../additional-registers/add-lcnote.cpp   | 384 ++
 .../lc-note/additional-registers/main.c   |  11 +
 11 files changed, 957 insertions(+), 35 deletions(-)
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.cpp
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.h
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/Makefile
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/TestMetadataRegisters.py
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/add-lcnote.cpp
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/main.c

diff --git a/lldb/include/lldb/Symbol/ObjectFile.h 
b/lldb/include/lldb/Symbol/ObjectFile.h
index 43567592dd447..1b9ae1fb31a69 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -18,6 +18,7 @@
 #include "lldb/Utility/Endian.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/FileSpecList.h"
+#include "lldb/Utility/StructuredData.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-private.h"
 #include "llvm/Support/Threading.h"
@@ -544,9 +545,9 @@ class ObjectFile : public 
std::enable_shared_from_this,
 return false;
   }
 
-  /// Get metadata about threads from the corefile.
+  /// Get metadata about thread ids from the corefile.
   ///
-  /// The corefile may have metadata (e.g. a Mach-O "thread ext

[Lldb-commits] [lldb] [lldb][RPC] Upstream lldb-rpc-gen tool (PR #138031)

2025-06-27 Thread Alex Langford via lldb-commits

https://github.com/bulbazord approved this pull request.

Let's get this patch in and iterate on the tool. Please watch the bots after 
landing.

https://github.com/llvm/llvm-project/pull/138031
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread John Harrison via lldb-commits

https://github.com/ashgti edited 
https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits

https://github.com/jasonmolenda updated 
https://github.com/llvm/llvm-project/pull/144627

>From 92348b28fb02901e9437b92c1ddf8cfed31c Mon Sep 17 00:00:00 2001
From: Jason Molenda 
Date: Tue, 17 Jun 2025 18:57:11 -0700
Subject: [PATCH 01/14] [lldb][Mach-O] Allow "process metadata" LC_NOTE to
 supply registers

The "process metadata" LC_NOTE allows for thread IDs to be specified
in a Mach-O corefile.  This extends the JSON recognzied in that
LC_NOTE to allow for additional registers to be supplied on a
per-thread basis.

The registers included in a Mach-O corefile LC_THREAD load command
can only be one of the register flavors that the kernel (xnu) defines
in  for arm64 -- the general purpose
registers, floating point registers, exception registers.

JTAG style corefile producers may have access to many additional
registers beyond these that EL0 programs typically use, for instance
TCR_EL1 on AArch64, and people developing low level code need access
to these registers.  This patch defines a format for including these
registers for any thread.

The JSON in "process metadata" is a dictionary that must have a
`threads` key.  The value is an array of entries, one per LC_THREAD
in the Mach-O corefile.  The number of entries must match the
LC_THREADs so they can be correctly associated.

Each thread's dictionary must have two keys, `sets`, and `registers`.
`sets` is an array of register set names.  If a register set name
matches one from the LC_THREAD core registers, any registers that
are defined will be added to that register set.  e.g. metadata can
add a register to the "General Purpose Registers" set that lldb
shows users.

`registers` is an array of dictionaries, one per register.  Each
register must have the keys `name`, `value`, `bitsize`, and `set`.
It may provide additional keys like `alt-name`, that
`DynamicRegisterInfo::SetRegisterInfo` recognizes.

This `sets` + `registers` formatting is the same that is used by
the `target.process.python-os-plugin-path` script interface uses,
both are parsed by `DynamicRegisterInfo`.  The one addition is that
in this LC_NOTE metadata, each register must also have a `value`
field, with the value provided in big-endian base 10, as usual with
JSON.

In RegisterContextUnifiedCore, I combine the register sets & registers
from the LC_THREAD for a specific thread, and the metadata sets &
registers for that thread from the LC_NOTE.  Even if no LC_NOTE
is present, this class ingests the LC_THREAD register contexts and
reformats it to its internal stores before returning itself as the
RegisterContex, instead of shortcutting and returning the core's
native RegisterContext.  I could have gone either way with that,
but in the end I decided if the code is correct, we should live on
it always.

I added a test where we process save-core to create a userland corefile,
then use a utility "add-lcnote" to strip the existing "process metadata"
LC_NOTE that lldb put in it, and adds a new one from a JSON string.

rdar://74358787
---
 lldb/include/lldb/Symbol/ObjectFile.h |  17 +-
 .../ObjectFile/Mach-O/ObjectFileMachO.cpp |  61 ++-
 .../ObjectFile/Mach-O/ObjectFileMachO.h   |   2 +
 .../Plugins/Process/mach-core/CMakeLists.txt  |   1 +
 .../mach-core/RegisterContextUnifiedCore.cpp  | 293 +
 .../mach-core/RegisterContextUnifiedCore.h|  57 +++
 .../Process/mach-core/ThreadMachCore.cpp  |  55 ++-
 .../lc-note/additional-registers/Makefile |  11 +
 .../TestMetadataRegisters.py  | 100 +
 .../additional-registers/add-lcnote.cpp   | 384 ++
 .../lc-note/additional-registers/main.c   |  11 +
 11 files changed, 957 insertions(+), 35 deletions(-)
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.cpp
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.h
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/Makefile
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/TestMetadataRegisters.py
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/add-lcnote.cpp
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/main.c

diff --git a/lldb/include/lldb/Symbol/ObjectFile.h 
b/lldb/include/lldb/Symbol/ObjectFile.h
index 43567592dd447..1b9ae1fb31a69 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -18,6 +18,7 @@
 #include "lldb/Utility/Endian.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/FileSpecList.h"
+#include "lldb/Utility/StructuredData.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-private.h"
 #include "llvm/Support/Threading.h"
@@ -544,9 +545,9 @@ class ObjectFile : public 
std::enable_shared_from_this,
 return false;
   }
 
-  /// Get metadata about threads from the corefile.
+  /// Get metadata about thread ids from the corefile.
   ///
-  /// The corefile may have metadata (e.g. a Mach-O "thread ext

[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits


@@ -70,27 +77,49 @@ lldb::RegisterContextSP 
ThreadMachCore::GetRegisterContext() {
 
 lldb::RegisterContextSP
 ThreadMachCore::CreateRegisterContextForFrame(StackFrame *frame) {
-  lldb::RegisterContextSP reg_ctx_sp;
   uint32_t concrete_frame_idx = 0;
 
   if (frame)
 concrete_frame_idx = frame->GetConcreteFrameIndex();
+  if (concrete_frame_idx > 0)
+return GetUnwinder().CreateRegisterContextForFrame(frame);
+
+  if (m_thread_reg_ctx_sp)
+return m_thread_reg_ctx_sp;
 
-  if (concrete_frame_idx == 0) {
-if (!m_thread_reg_ctx_sp) {
-  ProcessSP process_sp(GetProcess());
+  ProcessSP process_sp(GetProcess());

jasonmolenda wrote:

I mean, a Thread that wasn't constructed with a Process, you've got Problems. 
:) 

https://github.com/llvm/llvm-project/pull/144627
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits

https://github.com/jasonmolenda updated 
https://github.com/llvm/llvm-project/pull/144627

>From 92348b28fb02901e9437b92c1ddf8cfed31c Mon Sep 17 00:00:00 2001
From: Jason Molenda 
Date: Tue, 17 Jun 2025 18:57:11 -0700
Subject: [PATCH 01/18] [lldb][Mach-O] Allow "process metadata" LC_NOTE to
 supply registers

The "process metadata" LC_NOTE allows for thread IDs to be specified
in a Mach-O corefile.  This extends the JSON recognzied in that
LC_NOTE to allow for additional registers to be supplied on a
per-thread basis.

The registers included in a Mach-O corefile LC_THREAD load command
can only be one of the register flavors that the kernel (xnu) defines
in  for arm64 -- the general purpose
registers, floating point registers, exception registers.

JTAG style corefile producers may have access to many additional
registers beyond these that EL0 programs typically use, for instance
TCR_EL1 on AArch64, and people developing low level code need access
to these registers.  This patch defines a format for including these
registers for any thread.

The JSON in "process metadata" is a dictionary that must have a
`threads` key.  The value is an array of entries, one per LC_THREAD
in the Mach-O corefile.  The number of entries must match the
LC_THREADs so they can be correctly associated.

Each thread's dictionary must have two keys, `sets`, and `registers`.
`sets` is an array of register set names.  If a register set name
matches one from the LC_THREAD core registers, any registers that
are defined will be added to that register set.  e.g. metadata can
add a register to the "General Purpose Registers" set that lldb
shows users.

`registers` is an array of dictionaries, one per register.  Each
register must have the keys `name`, `value`, `bitsize`, and `set`.
It may provide additional keys like `alt-name`, that
`DynamicRegisterInfo::SetRegisterInfo` recognizes.

This `sets` + `registers` formatting is the same that is used by
the `target.process.python-os-plugin-path` script interface uses,
both are parsed by `DynamicRegisterInfo`.  The one addition is that
in this LC_NOTE metadata, each register must also have a `value`
field, with the value provided in big-endian base 10, as usual with
JSON.

In RegisterContextUnifiedCore, I combine the register sets & registers
from the LC_THREAD for a specific thread, and the metadata sets &
registers for that thread from the LC_NOTE.  Even if no LC_NOTE
is present, this class ingests the LC_THREAD register contexts and
reformats it to its internal stores before returning itself as the
RegisterContex, instead of shortcutting and returning the core's
native RegisterContext.  I could have gone either way with that,
but in the end I decided if the code is correct, we should live on
it always.

I added a test where we process save-core to create a userland corefile,
then use a utility "add-lcnote" to strip the existing "process metadata"
LC_NOTE that lldb put in it, and adds a new one from a JSON string.

rdar://74358787
---
 lldb/include/lldb/Symbol/ObjectFile.h |  17 +-
 .../ObjectFile/Mach-O/ObjectFileMachO.cpp |  61 ++-
 .../ObjectFile/Mach-O/ObjectFileMachO.h   |   2 +
 .../Plugins/Process/mach-core/CMakeLists.txt  |   1 +
 .../mach-core/RegisterContextUnifiedCore.cpp  | 293 +
 .../mach-core/RegisterContextUnifiedCore.h|  57 +++
 .../Process/mach-core/ThreadMachCore.cpp  |  55 ++-
 .../lc-note/additional-registers/Makefile |  11 +
 .../TestMetadataRegisters.py  | 100 +
 .../additional-registers/add-lcnote.cpp   | 384 ++
 .../lc-note/additional-registers/main.c   |  11 +
 11 files changed, 957 insertions(+), 35 deletions(-)
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.cpp
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.h
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/Makefile
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/TestMetadataRegisters.py
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/add-lcnote.cpp
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/main.c

diff --git a/lldb/include/lldb/Symbol/ObjectFile.h 
b/lldb/include/lldb/Symbol/ObjectFile.h
index 43567592dd447..1b9ae1fb31a69 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -18,6 +18,7 @@
 #include "lldb/Utility/Endian.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/FileSpecList.h"
+#include "lldb/Utility/StructuredData.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-private.h"
 #include "llvm/Support/Threading.h"
@@ -544,9 +545,9 @@ class ObjectFile : public 
std::enable_shared_from_this,
 return false;
   }
 
-  /// Get metadata about threads from the corefile.
+  /// Get metadata about thread ids from the corefile.
   ///
-  /// The corefile may have metadata (e.g. a Mach-O "thread ext

[Lldb-commits] [lldb] [lldb] Fix evaluating expressions without JIT in an object context (PR #145599)

2025-06-27 Thread Igor Kudrin via lldb-commits

https://github.com/igorkudrin updated 
https://github.com/llvm/llvm-project/pull/145599

>From fac89bb1b51496761b156f22dcff85cbe86bf9d2 Mon Sep 17 00:00:00 2001
From: Igor Kudrin 
Date: Mon, 23 Jun 2025 23:39:52 -0700
Subject: [PATCH 1/2] [lldb] Fix evaluating expressions without JIT in an
 object context

If a server does not support allocating memory in an inferior process or
when debugging a core file, evaluating an expression in the context of a
value object results in an error:

```
error: :43:1: use of undeclared identifier '$__lldb_class'
   43 | $__lldb_class::$__lldb_expr(void *$__lldb_arg)
  | ^
```

Such expressions require a live address to be stored in the value
object. However, `EntityResultVariable::Dematerialize()` only sets
`ret->m_live_sp` if JIT is available, even if the address points to the
process memory and no custom allocations were made. Similarly,
`EntityPersistentVariable::Dematerialize()` tries to deallocate memory
based on the same check, resulting in an error if the memory was not
previously allocated in `EntityPersistentVariable::Materialize()`.

As an unintended bonus, the patch also fixes a FIXME case in
`TestCxxChar8_t.py`.
---
 lldb/source/Expression/Materializer.cpp   |  29 ---
 .../postmortem/elf-core/expr/TestExpr.py  |  48 ++
 .../elf-core/expr/linux-x86_64.core   | Bin 0 -> 40960 bytes
 .../postmortem/elf-core/expr/linux-x86_64.out | Bin 0 -> 10816 bytes
 .../postmortem/elf-core/expr/main.cpp |  15 ++
 .../API/lang/cpp/char8_t/TestCxxChar8_t.py|   4 +-
 6 files changed, 73 insertions(+), 23 deletions(-)
 create mode 100644 
lldb/test/API/functionalities/postmortem/elf-core/expr/TestExpr.py
 create mode 100644 
lldb/test/API/functionalities/postmortem/elf-core/expr/linux-x86_64.core
 create mode 100755 
lldb/test/API/functionalities/postmortem/elf-core/expr/linux-x86_64.out
 create mode 100644 
lldb/test/API/functionalities/postmortem/elf-core/expr/main.cpp

diff --git a/lldb/source/Expression/Materializer.cpp 
b/lldb/source/Expression/Materializer.cpp
index 79c804c6c4214..5f0dcd42289f6 100644
--- a/lldb/source/Expression/Materializer.cpp
+++ b/lldb/source/Expression/Materializer.cpp
@@ -329,22 +329,10 @@ class EntityPersistentVariable : public 
Materializer::Entity {
   return;
 }
 
-lldb::ProcessSP process_sp =
-map.GetBestExecutionContextScope()->CalculateProcess();
-if (!process_sp || !process_sp->CanJIT()) {
-  // Allocations are not persistent so persistent variables cannot stay
-  // materialized.
-
-  m_persistent_variable_sp->m_flags |=
-  ExpressionVariable::EVNeedsAllocation;
-
-  DestroyAllocation(map, err);
-  if (!err.Success())
-return;
-} else if (m_persistent_variable_sp->m_flags &
-   ExpressionVariable::EVNeedsAllocation &&
-   !(m_persistent_variable_sp->m_flags &
- ExpressionVariable::EVKeepInTarget)) {
+if (m_persistent_variable_sp->m_flags &
+ExpressionVariable::EVNeedsAllocation &&
+!(m_persistent_variable_sp->m_flags &
+  ExpressionVariable::EVKeepInTarget)) {
   DestroyAllocation(map, err);
   if (!err.Success())
 return;
@@ -1086,9 +1074,8 @@ class EntityResultVariable : public Materializer::Entity {
   m_delegate->DidDematerialize(ret);
 }
 
-bool can_persist =
-(m_is_program_reference && process_sp && process_sp->CanJIT() &&
- !(address >= frame_bottom && address < frame_top));
+bool can_persist = m_is_program_reference &&
+   !(address >= frame_bottom && address < frame_top);
 
 if (can_persist && m_keep_in_memory) {
   ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
@@ -1118,7 +1105,9 @@ class EntityResultVariable : public Materializer::Entity {
 map.Free(m_temporary_allocation, free_error);
   }
 } else {
-  ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
+  ret->m_flags |= m_is_program_reference
+  ? ExpressionVariable::EVIsProgramReference
+  : ExpressionVariable::EVIsLLDBAllocated;
 }
 
 m_temporary_allocation = LLDB_INVALID_ADDRESS;
diff --git a/lldb/test/API/functionalities/postmortem/elf-core/expr/TestExpr.py 
b/lldb/test/API/functionalities/postmortem/elf-core/expr/TestExpr.py
new file mode 100644
index 0..b397359e7a476
--- /dev/null
+++ b/lldb/test/API/functionalities/postmortem/elf-core/expr/TestExpr.py
@@ -0,0 +1,48 @@
+"""
+Test evaluating expressions when debugging core file.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+@skipIfLLVMTargetMissing("X86")
+class CoreExprTestCase(TestBase):
+def test_result_var(self):
+"""Test that the result variable can be used in subsequent 
expressions."""
+
+target = self.dbg.CreateT

[Lldb-commits] [lldb] Add option to not loading all DWOs when dumping separate_debug-info (PR #146166)

2025-06-27 Thread David Peixotto via lldb-commits


@@ -2030,7 +2032,8 @@ class CommandObjectTargetModulesDumpSymtab
   }
   if (INTERRUPT_REQUESTED(GetDebugger(),
   "Interrupted in dump all symtabs with {0} "
-  "of {1} dumped.", num_dumped, num_modules))
+  "of {1} dumped.",

dmpots wrote:

It looks like there are some formatting changes here that are not related to 
the functional change. We should split those out into a separate NFC PR if we 
want to include them.

It looks like all the `INTERRRUPT_REQUESTED` changes fall into that category.

https://github.com/llvm/llvm-project/pull/146166
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread John Harrison via lldb-commits

ashgti wrote:

On my windows VM, all tests are passing now and it looks like this is also 
working for Linux. I think the current CI check is a no-op on Windows for lldb.

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread Adrian Prantl via lldb-commits

https://github.com/adrian-prantl approved this pull request.


https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][RPC] Upstream lldb-rpc-gen tool (PR #138031)

2025-06-27 Thread Chelsea Cassanova via lldb-commits

https://github.com/chelcassanova updated 
https://github.com/llvm/llvm-project/pull/138031

>From bf72ec458e7788ddd8d7cb7d42fbf55a9112722f Mon Sep 17 00:00:00 2001
From: Chelsea Cassanova 
Date: Wed, 30 Apr 2025 14:15:39 -0700
Subject: [PATCH] [lldb][RPC] Upstream lldb-rpc-gen tool

This commit upstreams the `lldb-rpc-gen` tool, a ClangTool that
generates the LLDB RPC client and server interfaces.

https://discourse.llvm.org/t/rfc-upstreaming-lldb-rpc/85804
---
 lldb/cmake/modules/LLDBConfig.cmake   |   2 +
 .../Tests/CheckRPCGenToolByproducts.test  |  11 +
 lldb/test/Shell/helper/toolchain.py   |   8 +
 lldb/tools/CMakeLists.txt |   3 +
 lldb/tools/lldb-rpc/CMakeLists.txt|  22 +
 lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake   |  58 ++
 lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake  | 101 
 .../lldb-rpc/lldb-rpc-gen/CMakeLists.txt  |  21 +
 .../tools/lldb-rpc/lldb-rpc-gen/RPCCommon.cpp | 501 ++
 lldb/tools/lldb-rpc/lldb-rpc-gen/RPCCommon.h  | 108 
 .../lldb-rpc/lldb-rpc-gen/lldb-rpc-gen.cpp| 341 
 11 files changed, 1176 insertions(+)
 create mode 100644 
lldb/test/Shell/RPC/Generator/Tests/CheckRPCGenToolByproducts.test
 create mode 100644 lldb/tools/lldb-rpc/CMakeLists.txt
 create mode 100644 lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake
 create mode 100644 lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake
 create mode 100644 lldb/tools/lldb-rpc/lldb-rpc-gen/CMakeLists.txt
 create mode 100644 lldb/tools/lldb-rpc/lldb-rpc-gen/RPCCommon.cpp
 create mode 100644 lldb/tools/lldb-rpc/lldb-rpc-gen/RPCCommon.h
 create mode 100644 lldb/tools/lldb-rpc/lldb-rpc-gen/lldb-rpc-gen.cpp

diff --git a/lldb/cmake/modules/LLDBConfig.cmake 
b/lldb/cmake/modules/LLDBConfig.cmake
index 37b823feb584b..069b5412d03f8 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -322,4 +322,6 @@ else()
 set(LLDB_CAN_USE_DEBUGSERVER OFF)
 endif()
 
+set(LLDB_BUILD_LLDBRPC ON CACHE BOOL "")
+
 include(LLDBGenerateConfig)
diff --git a/lldb/test/Shell/RPC/Generator/Tests/CheckRPCGenToolByproducts.test 
b/lldb/test/Shell/RPC/Generator/Tests/CheckRPCGenToolByproducts.test
new file mode 100644
index 0..be3eefc69b20a
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Tests/CheckRPCGenToolByproducts.test
@@ -0,0 +1,11 @@
+# For this test, we're not checking any specific output from a generated file,
+# but we do need a file to pass into lldb-rpc-gen so use SBAddress.h from 
source.
+RUN: %lldb-rpc-gen --output-dir=%t 
%S/../../../../../include/lldb/API/SBAddress.h
+
+RUN: ls %t | FileCheck %s
+
+# We're just making sure that the tool emits the class names,
+# methods and skipped methods file in the output directory.
+CHECK: SBAPI.def
+CHECK: SBClasses.def
+CHECK: SkippedMethods.txt
diff --git a/lldb/test/Shell/helper/toolchain.py 
b/lldb/test/Shell/helper/toolchain.py
index 42968128f2702..95437dba55b7d 100644
--- a/lldb/test/Shell/helper/toolchain.py
+++ b/lldb/test/Shell/helper/toolchain.py
@@ -156,6 +156,14 @@ def use_lldb_substitutions(config):
 extra_args=["platform"],
 unresolved="ignore",
 ),
+ToolSubst(
+"%lldb-rpc-gen",
+command=FindTool("lldb-rpc-gen"),
+extra_args=[
+'--extra-arg="-resource-dir=' + config.clang_resource_dir + '"'
+],
+unresolved="ignore",
+),
 "lldb-test",
 "lldb-dap",
 ToolSubst(
diff --git a/lldb/tools/CMakeLists.txt b/lldb/tools/CMakeLists.txt
index 6804dc234555b..73ffbbbee3056 100644
--- a/lldb/tools/CMakeLists.txt
+++ b/lldb/tools/CMakeLists.txt
@@ -10,6 +10,9 @@ add_subdirectory(lldb-fuzzer EXCLUDE_FROM_ALL)
 
 add_lldb_tool_subdirectory(lldb-instr)
 add_lldb_tool_subdirectory(lldb-dap)
+if (LLDB_BUILD_LLDBRPC)
+  add_lldb_tool_subdirectory(lldb-rpc)
+endif()
 
 if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
   add_lldb_tool_subdirectory(darwin-debug)
diff --git a/lldb/tools/lldb-rpc/CMakeLists.txt 
b/lldb/tools/lldb-rpc/CMakeLists.txt
new file mode 100644
index 0..fdd6cf9163e96
--- /dev/null
+++ b/lldb/tools/lldb-rpc/CMakeLists.txt
@@ -0,0 +1,22 @@
+include(CheckCXXCompilerFlag)
+# Umbrella target for the entire framework is a default target.
+add_custom_target(lldb-rpc ALL)
+
+if(LLDB_CODESIGN_IDENTITY)
+  # Use explicit LLDB identity
+  set(LLVM_CODESIGNING_IDENTITY ${LLDB_CODESIGN_IDENTITY})
+else()
+  # Use explicit LLVM identity or default to ad-hoc signing if empty
+  if(NOT LLVM_CODESIGNING_IDENTITY)
+set(LLVM_CODESIGNING_IDENTITY -)
+  endif()
+endif()
+
+# LLDBRPCGeneration.cmake needs the LLDB_RPC_GEN_EXE variable
+# which gets defined in the lldb-rpc-gen folder, so we're adding
+# this folder before we add that file.
+add_lldb_tool_subdirectory(lldb-rpc-gen)
+include(${CMAKE_CURRENT_SOURCE_DIR}/LLDBRPCGeneration.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/LLDBRPCHeaders.cmake)
+
+add_dependencies(lldb-rpc lldb-rp

[Lldb-commits] [lldb] [lldb][RPC] Upstream lldb-rpc-gen tool (PR #138031)

2025-06-27 Thread Chelsea Cassanova via lldb-commits

chelcassanova wrote:

When I updated the patch, the test now fails because of the error that it's 
missing the clang resource dir. That repros locally and I haven't changed 
anything about how the tool is built outside of adding a CMake variable, 
investigating.

https://github.com/llvm/llvm-project/pull/138031
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits


@@ -0,0 +1,300 @@
+//===-- RegisterContextUnifiedCore.cpp 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "RegisterContextUnifiedCore.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/StructuredData.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextUnifiedCore::RegisterContextUnifiedCore(
+Thread &thread, uint32_t concrete_frame_idx,
+RegisterContextSP core_thread_regctx_sp,
+StructuredData::ObjectSP metadata_thread_registers)
+: RegisterContext(thread, concrete_frame_idx) {
+
+  ProcessSP process_sp(thread.GetProcess());
+  Target &target = process_sp->GetTarget();
+  StructuredData::Dictionary *metadata_registers_dict = nullptr;
+
+  // If we have thread metadata, check if the keys for register
+  // definitions are present; if not, clear the ObjectSP.
+  if (metadata_thread_registers &&
+  metadata_thread_registers->GetAsDictionary() &&
+  metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {
+metadata_registers_dict = metadata_thread_registers->GetAsDictionary()
+  ->GetValueForKey("register_info")
+  ->GetAsDictionary();
+if (metadata_registers_dict)
+  if (!metadata_registers_dict->HasKey("sets") ||
+  !metadata_registers_dict->HasKey("registers"))
+metadata_registers_dict = nullptr;
+  }
+
+  // When creating a register set list from the two sources,
+  // the LC_THREAD aka core_thread_regctx_sp register sets
+  // will be used at the same indexes.
+  // Any additional sets named by the thread metadata registers
+  // will be added after them.  If the thread metadata
+  // specify a set with the same name as LC_THREAD, the already-used
+  // index from the core register context will be used in
+  // the RegisterInfo.
+  std::map metadata_regset_to_combined_regset;
+
+  // Calculate the total size of the register store buffer we need
+  // for all registers.  The corefile register definitions may include
+  // RegisterInfo descriptions of registers that aren't actually
+  // available.  For simplicity, calculate the size of all registers
+  // as if they are available, so we can maintain the same offsets into
+  // the buffer.
+  uint32_t core_buffer_end = 0;
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+core_buffer_end =
+std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);
+  }
+
+  // Add metadata register sizes to the total buffer size.
+  uint32_t combined_buffer_end = core_buffer_end;
+  if (metadata_registers_dict) {
+StructuredData::Array *registers = nullptr;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach(
+  [&combined_buffer_end](StructuredData::Object *ent) -> bool {
+uint32_t bitsize;
+if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
+ bitsize))
+  return false;
+combined_buffer_end += (bitsize / 8);
+return true;
+  });
+  }
+  m_register_data.resize(combined_buffer_end, 0);
+
+  // Copy the core register values into our combined data buffer,
+  // skip registers that are contained within another (e.g. w0 vs. x0)
+  // and registers that return as "unavailable".
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+RegisterValue val;
+if (!reginfo->value_regs &&
+core_thread_regctx_sp->ReadRegister(reginfo, val))
+  memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),
+ val.GetByteSize());
+  }
+
+  // Set 'offset' fields for each register definition into our combined
+  // register data buffer. DynamicRegisterInfo needs
+  // this field set to parse the JSON.
+  // Also copy the values of the registers into our register data buffer.
+  if (metadata_registers_dict) {
+size_t offset = core_buffer_end;
+ByteOrder byte_order = core_thread_regctx_sp->GetByteOrder();
+StructuredData::Array *registers;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach([this, &offset,
+  byte_order](StructuredData::Object *ent) -> bool {
+uint64_t bitsize;

[Lldb-commits] [clang] [lldb] [llvm] [lldb] Fix object format in the Triple of Mach-O files (approach 4) (PR #145157)

2025-06-27 Thread David Peixotto via lldb-commits


@@ -463,6 +463,27 @@ class Triple {
 
   const std::string &str() const { return Data; }
 
+  /// Return the triple string but only keep the first \p N components.
+  ///
+  /// The returned string will preserve the first \p N components exactly the
+  /// same as the original (including the leading "-" and the value, empty or
+  /// not).
+  ///
+  /// E.g. Triple("arm64-apple-ios").str(5) == "arm64-apple-ios"
+  /// E.g. Triple("arm64-apple-ios--").str(5) == "arm64-apple-ios--"
+  /// E.g. Triple("arm64-apple-ios--").str(4) == "arm64-apple-ios-"
+  /// E.g. Triple("arm64-apple-ios--").str(3) == "arm64-apple-ios"
+  /// E.g. Triple("arm64-apple-ios--").str(2) == "arm64-apple"
+  /// E.g. Triple("arm64-apple-ios--").str(1) == "arm64"
+  /// E.g. Triple("arm64-apple-ios--").str(0) == ""
+  ///
+  /// This method does not normalize any triple strings. Clients that need to
+  /// handle the non-canonical triples that users often specify should use the
+  /// normalize method.
+  ///
+  /// \returns the (shorterned) triple string.
+  StringRef str(size_t N) const;

dmpots wrote:

It looks like we already have this capability in the `normalize` method

https://github.com/llvm/llvm-project/blob/3ea1296b3724ec5c05f616c98dd883b54b672ff9/llvm/include/llvm/TargetParser/Triple.h#L388

For the use cases in this PR we could do 
`triple.normalize(CanonicalForm::FOUR_IDENT)`

https://github.com/llvm/llvm-project/pull/145157
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [llvm] [lldb] Fix object format in the Triple of Mach-O files (approach 4) (PR #145157)

2025-06-27 Thread David Peixotto via lldb-commits


@@ -642,9 +642,9 @@ bool SBDebugger::GetDefaultArchitecture(char *arch_name, 
size_t arch_name_len) {
 ArchSpec default_arch = Target::GetDefaultArchitecture();
 
 if (default_arch.IsValid()) {
-  const std::string &triple_str = default_arch.GetTriple().str();
+  const llvm::StringRef triple_str = default_arch.GetTriple().str(4);

dmpots wrote:

I think it would be good to add a couple of methods to `ArchSpec` so that we 
have a single place that specifies how we format the triple.

```
class ArchSpec {
...
static std::string GetTripleStr(const llvm::Triple &triple) {
return triple.normalize(CanonicalForm::FOUR_IDENT);
}

std::string GetTripleStr() {
return GetTripleStr(GetTriple());
}
};
```

Then if we have an `ArchSpec` we can just call the `GetTripleStr()` function on 
it and if we just have the `Triple` we can still use the static version.

https://github.com/llvm/llvm-project/pull/145157
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][RPC] Upstream lldb-rpc-gen tool (PR #138031)

2025-06-27 Thread Chelsea Cassanova via lldb-commits

chelcassanova wrote:

Actually, the test fails locally for me. On the pre-commit CI it's error 
message is 
`home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/lldb/test/Shell/RPC/Generator/Tests/Output/CheckRPCGenToolByproducts.test.script:
 line 1: fg: no job control`, which means that it doesn't recognize that the 
tool's binary is there.

As an aside, is there a way to retrigger a pre-commit CI check without having 
to push again?

https://github.com/llvm/llvm-project/pull/138031
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits


@@ -0,0 +1,300 @@
+//===-- RegisterContextUnifiedCore.cpp 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "RegisterContextUnifiedCore.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/StructuredData.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextUnifiedCore::RegisterContextUnifiedCore(
+Thread &thread, uint32_t concrete_frame_idx,
+RegisterContextSP core_thread_regctx_sp,
+StructuredData::ObjectSP metadata_thread_registers)
+: RegisterContext(thread, concrete_frame_idx) {
+
+  ProcessSP process_sp(thread.GetProcess());
+  Target &target = process_sp->GetTarget();
+  StructuredData::Dictionary *metadata_registers_dict = nullptr;
+
+  // If we have thread metadata, check if the keys for register
+  // definitions are present; if not, clear the ObjectSP.
+  if (metadata_thread_registers &&
+  metadata_thread_registers->GetAsDictionary() &&
+  metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {
+metadata_registers_dict = metadata_thread_registers->GetAsDictionary()
+  ->GetValueForKey("register_info")
+  ->GetAsDictionary();
+if (metadata_registers_dict)
+  if (!metadata_registers_dict->HasKey("sets") ||
+  !metadata_registers_dict->HasKey("registers"))
+metadata_registers_dict = nullptr;
+  }
+
+  // When creating a register set list from the two sources,
+  // the LC_THREAD aka core_thread_regctx_sp register sets
+  // will be used at the same indexes.
+  // Any additional sets named by the thread metadata registers
+  // will be added after them.  If the thread metadata
+  // specify a set with the same name as LC_THREAD, the already-used
+  // index from the core register context will be used in
+  // the RegisterInfo.
+  std::map metadata_regset_to_combined_regset;
+
+  // Calculate the total size of the register store buffer we need
+  // for all registers.  The corefile register definitions may include
+  // RegisterInfo descriptions of registers that aren't actually
+  // available.  For simplicity, calculate the size of all registers
+  // as if they are available, so we can maintain the same offsets into
+  // the buffer.
+  uint32_t core_buffer_end = 0;
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+core_buffer_end =
+std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);
+  }
+
+  // Add metadata register sizes to the total buffer size.
+  uint32_t combined_buffer_end = core_buffer_end;
+  if (metadata_registers_dict) {
+StructuredData::Array *registers = nullptr;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach(
+  [&combined_buffer_end](StructuredData::Object *ent) -> bool {
+uint32_t bitsize;
+if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
+ bitsize))
+  return false;
+combined_buffer_end += (bitsize / 8);
+return true;
+  });
+  }
+  m_register_data.resize(combined_buffer_end, 0);
+
+  // Copy the core register values into our combined data buffer,
+  // skip registers that are contained within another (e.g. w0 vs. x0)
+  // and registers that return as "unavailable".
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+RegisterValue val;
+if (!reginfo->value_regs &&
+core_thread_regctx_sp->ReadRegister(reginfo, val))
+  memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),
+ val.GetByteSize());
+  }
+
+  // Set 'offset' fields for each register definition into our combined
+  // register data buffer. DynamicRegisterInfo needs
+  // this field set to parse the JSON.
+  // Also copy the values of the registers into our register data buffer.
+  if (metadata_registers_dict) {
+size_t offset = core_buffer_end;
+ByteOrder byte_order = core_thread_regctx_sp->GetByteOrder();
+StructuredData::Array *registers;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach([this, &offset,
+  byte_order](StructuredData::Object *ent) -> bool {
+uint64_t bitsize;

[Lldb-commits] [lldb] [lldb] Add Model Context Protocol (MCP) support to LLDB (PR #143628)

2025-06-27 Thread David Spickett via lldb-commits

DavidSpickett wrote:

@JDevlieghere Release note please.

Feel free to put it at the the top for maximum buzzword power :) Include a link 
to the documentation page once you've added that.

https://github.com/llvm/llvm-project/pull/143628
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Support disassembling RISC-V proprietary instructions (PR #145793)

2025-06-27 Thread David Spickett via lldb-commits

DavidSpickett wrote:

> Upon realising that almost all of our custom extensions are only used in 
> assembly

Which is surprising to me, but if I looked at all the assembly only extensions 
for Arm I'd find the the same thing. I just rarely have to deal with those.

> And that's how we get here: filtering the output of objdump is fine, but it 
> would be great to also support users inside their disassembler 😄

Yes I see how you'd get there.

Even if we want to be super reductive, printing the bytes out at least means 
you can decode by hand. Which you can't do today.

So I like the direction.

> MCDisassembler::suggestBytesToSkip, which the Arm/AArch64 backends use for 
> realigning the disassembly flow. We maybe should implement this given we know 
> the instruction alignment in RISC-V is either 2 or 4, but we don't at the 
> moment.

I should check how this ends up displaying in lldb. AArch64 unlikely to be a 
problem but Thumb is variable so I hope we at least show the bytes.

@tedwoodward I think this change might be more clearly pitched as:
* Currently when an instruction is not decoded lldb prints nothing useful
* You have made lldb print something useful in this situation, for humans and 
scripts
* In addition, this format enables the use of external filters

Which I think is a net positive.

Still unsure about `if riscv` in this generic code but if there's no other use 
case for it then it's fine. That's just a code organisation issue.

Arm M profile has 
https://developer.arm.com/Architectures/Arm%20Custom%20Instructions, I'll look 
into that and see if it would benefit from a change of output format too. Just 
in theory though, I don't think we shipped support for open source debuggers 
and I'm not about to implement it myself.

https://github.com/llvm/llvm-project/pull/145793
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Update DIL to handle smart pointers; add more tests. (PR #143786)

2025-06-27 Thread Pavel Labath via lldb-commits

https://github.com/labath commented:

I meant adding a new test method (`def test_something(self): self.build(); 
self.run(); your code`), but this is fine too, especially if the switch to the 
new implementation is imminent.

https://github.com/llvm/llvm-project/pull/143786
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Update DIL to handle smart pointers; add more tests. (PR #143786)

2025-06-27 Thread Pavel Labath via lldb-commits

https://github.com/labath approved this pull request.


https://github.com/llvm/llvm-project/pull/143786
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Use llvm::is_contained (NFC) (PR #146012)

2025-06-27 Thread Tim Gymnich via lldb-commits

https://github.com/tgymnich approved this pull request.


https://github.com/llvm/llvm-project/pull/146012
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] 2c90c0b - [lldb] Extract debug server location code (#145706)

2025-06-27 Thread via lldb-commits

Author: Pavel Labath
Date: 2025-06-27T11:16:57+02:00
New Revision: 2c90c0b90cbdfbd069b2e79d6a2c3e3b160bf896

URL: 
https://github.com/llvm/llvm-project/commit/2c90c0b90cbdfbd069b2e79d6a2c3e3b160bf896
DIFF: 
https://github.com/llvm/llvm-project/commit/2c90c0b90cbdfbd069b2e79d6a2c3e3b160bf896.diff

LOG: [lldb] Extract debug server location code (#145706)

.. from the guts of GDBRemoteCommunication to ~top level.

This is motivated by #131519 and by the fact that's impossible to guess
whether the author of a symlink intended it to be a "convenience
shortcut" -- meaning it should be resolved before looking for related
files; or an "implementation detail" -- meaning the related files should
be located near the symlink itself.

This debate is particularly ridiculous when it comes to lldb-server
running in platform mode, because it also functions as a debug server,
so what we really just need to do is to pass /proc/self/exe in a
platform-independent manner.

Moving the location logic higher up achieves that as lldb-platform (on
non-macos) can pass `HostInfo::GetProgramFileSpec`, while liblldb can
use the existing complex logic (which only worked on liblldb anyway as
lldb-platform doesn't have a lldb_private::Platform instance).

Another benefit of this patch is a reduction in dependency from
GDBRemoteCommunication to the rest of liblldb (achieved by avoiding the
Platform dependency).

Added: 


Modified: 
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

lldb/test/API/commands/platform/launchgdbserver/TestPlatformLaunchGDBServer.py
lldb/test/API/tools/lldb-dap/console/TestDAP_console.py
lldb/tools/lldb-server/lldb-platform.cpp

Removed: 




diff  --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 4bb85f5d53616..d7e4b2b9546b2 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -11,7 +11,6 @@
 #include "lldb/Host/Config.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/Host.h"
-#include "lldb/Host/HostInfo.h"
 #include "lldb/Host/Pipe.h"
 #include "lldb/Host/ProcessLaunchInfo.h"
 #include "lldb/Host/Socket.h"
@@ -33,14 +32,6 @@
 #include 
 #include 
 
-#if defined(__APPLE__)
-#define DEBUGSERVER_BASENAME "debugserver"
-#elif defined(_WIN32)
-#define DEBUGSERVER_BASENAME "lldb-server.exe"
-#else
-#define DEBUGSERVER_BASENAME "lldb-server"
-#endif
-
 #if HAVE_LIBCOMPRESSION
 #include 
 #endif
@@ -836,77 +827,11 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t 
*src, size_t src_len,
   return GDBRemoteCommunication::PacketType::Invalid;
 }
 
-FileSpec GDBRemoteCommunication::GetDebugserverPath(Platform *platform) {
-  Log *log = GetLog(GDBRLog::Process);
-  // If we locate debugserver, keep that located version around
-  static FileSpec g_debugserver_file_spec;
-  FileSpec debugserver_file_spec;
-
-  Environment host_env = Host::GetEnvironment();
-
-  // Always check to see if we have an environment override for the path to the
-  // debugserver to use and use it if we do.
-  std::string env_debugserver_path = host_env.lookup("LLDB_DEBUGSERVER_PATH");
-  if (!env_debugserver_path.empty()) {
-debugserver_file_spec.SetFile(env_debugserver_path,
-  FileSpec::Style::native);
-LLDB_LOGF(log,
-  "GDBRemoteCommunication::%s() gdb-remote stub exe path set "
-  "from environment variable: %s",
-  __FUNCTION__, env_debugserver_path.c_str());
-  } else
-debugserver_file_spec = g_debugserver_file_spec;
-  bool debugserver_exists =
-  FileSystem::Instance().Exists(debugserver_file_spec);
-  if (!debugserver_exists) {
-// The debugserver binary is in the LLDB.framework/Resources directory.
-debugserver_file_spec = HostInfo::GetSupportExeDir();
-if (debugserver_file_spec) {
-  debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME);
-  debugserver_exists = 
FileSystem::Instance().Exists(debugserver_file_spec);
-  if (debugserver_exists) {
-LLDB_LOGF(log,
-  "GDBRemoteCommunication::%s() found gdb-remote stub exe 
'%s'",
-  __FUNCTION__, debugserver_file_spec.GetPath().c_str());
-
-g_debugserver_file_spec = debugserver_file_spec;
-  } else {
-if (platform)
-  debugserver_file_spec =
-  platform->LocateExecutable(DEBUGSERVER_BASENAME);
-else
-  debugserver_file_spec.Clear();
-if (debugserver_

[Lldb-commits] [lldb] [lldb] Extract debug server location code (PR #145706)

2025-06-27 Thread Pavel Labath via lldb-commits

https://github.com/labath closed 
https://github.com/llvm/llvm-project/pull/145706
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,68 @@
+# Model Context Protocol (MCP)
+
+LLDB supports for the [Model Context Protocol][1] (MCP). This structured,
+machine-friendly protocol allows AI models to access and interact with external
+tools, such as the debugger. Using MCP, an AI agent can execute LLDB commands
+to control the debugger: set breakpoints, inspect memory, step through code.
+This can range from helping you run a specific command you can't immediately
+remember to a fully agent-driven debugging experiences
+
+## MCP Server
+
+To start the MCP server in LLDB, use the `protocol-server start` command.
+Specify `MCP` as the protocol and provide a URI to listen on. For example, to
+start listening for local TCP connections on port `5`, use the following
+command:
+
+```
+(lldb) protocol-server start MCP listen://localhost:5
+MCP server started with connection listeners: connection://[::1]:5, 
connection://[127.0.0.1]:5
+```
+
+The server will automatically stop when exiting LLDB, or it can be stopped
+explicitly with the `protocol-server stop` command.

DavidSpickett wrote:

Also, how do you check if it is active? `protocol-server` start again and it 
errors?

https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,68 @@
+# Model Context Protocol (MCP)
+
+LLDB supports for the [Model Context Protocol][1] (MCP). This structured,
+machine-friendly protocol allows AI models to access and interact with external
+tools, such as the debugger. Using MCP, an AI agent can execute LLDB commands
+to control the debugger: set breakpoints, inspect memory, step through code.
+This can range from helping you run a specific command you can't immediately
+remember to a fully agent-driven debugging experiences
+
+## MCP Server
+
+To start the MCP server in LLDB, use the `protocol-server start` command.
+Specify `MCP` as the protocol and provide a URI to listen on. For example, to
+start listening for local TCP connections on port `5`, use the following
+command:
+
+```
+(lldb) protocol-server start MCP listen://localhost:5
+MCP server started with connection listeners: connection://[::1]:5, 
connection://[127.0.0.1]:5
+```
+
+The server will automatically stop when exiting LLDB, or it can be stopped
+explicitly with the `protocol-server stop` command.
+
+```
+(lldb) protocol-server stop MCP
+```
+
+## MCP Client
+
+MCP uses standard input/output (stdio) for communication between client and
+server. The exact configuration depends on the client, but most applications
+allow you to specify an MCP server as a binary and arguments. This means that
+you need to use something like `netcat` to connect to LLDB's MCP server and
+forward communication over stdio over the network connection.
+
+Configuration example for [Claude Code][2]:
+
+```
+{
+  "mcpServers": {
+"tool": {
+  "command": "/usr/bin/nc",
+  "args": ["localhost", "5"]
+}
+  }
+}
+```
+
+Configuration example for [Visual Studio Code][3]:
+
+```
+{
+  "mcp": {
+"servers": {
+  "lldb": {
+"type": "stdio",
+"command": "/usr/bin/nc",
+"args": ["localhost", "5"]
+  }
+}
+  }
+}
+```
+

DavidSpickett wrote:

Is there any way to know that you've connected properly? I suppose the MCP 
client says something if it cannot connect, right?

Are there log channels on LLDB's side you could enable if you had problems with 
it?

https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][NFC] Inline ResolveSDKPathFromDebugInfo in one of its call site (PR #146062)

2025-06-27 Thread Charles Zablit via lldb-commits

https://github.com/charles-zablit edited 
https://github.com/llvm/llvm-project/pull/146062
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][NFC] Inline ResolveSDKPathFromDebugInfo in one of its call site (PR #146062)

2025-06-27 Thread Charles Zablit via lldb-commits

https://github.com/charles-zablit created 
https://github.com/llvm/llvm-project/pull/146062

This patch is part of an effort to remove the ResolveSDKPathFromDebugInfo 
method, and more specifically the variant which takes a Module as argument.

This PR should be merged after https://github.com/llvm/llvm-project/pull/144913.

>From 6ce75177264d47ffedbf0e6ee44831eac1d3ea55 Mon Sep 17 00:00:00 2001
From: Charles Zablit 
Date: Fri, 27 Jun 2025 12:49:53 +0100
Subject: [PATCH] [lldb][NFC] Inline ResolveSDKPathFromDebugInfo in one of its
 call site

---
 .../Platform/MacOSX/PlatformDarwin.cpp| 32 +++
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp 
b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index 262a7dc731713..ae46ac63e756a 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -1130,13 +1130,33 @@ void 
PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
 
   if (target) {
 if (ModuleSP exe_module_sp = target->GetExecutableModule()) {
-  auto path_or_err = ResolveSDKPathFromDebugInfo(*exe_module_sp);
-  if (path_or_err) {
-sysroot_spec = FileSpec(*path_or_err);
+  SymbolFile *sym_file = exe_module_sp->GetSymbolFile();
+  if (!sym_file)
+return;
+
+  XcodeSDK merged_sdk;
+  for (unsigned i = 0; i < sym_file->GetNumCompileUnits(); ++i) {
+if (auto cu_sp = sym_file->GetCompileUnitAtIndex(i)) {
+  auto cu_sdk = sym_file->ParseXcodeSDK(*cu_sp);
+  merged_sdk.Merge(cu_sdk);
+}
+  }
+
+  // TODO: The result of this loop is almost equivalent to deriving the SDK
+  // from the target triple, which would be a lot cheaper.
+
+  if (FileSystem::Instance().Exists(merged_sdk.GetSysroot())) {
+sysroot_spec = merged_sdk.GetSysroot();
   } else {
-LLDB_LOG_ERROR(GetLog(LLDBLog::Types | LLDBLog::Host),
-   path_or_err.takeError(),
-   "Failed to resolve SDK path: {0}");
+auto path_or_err =
+HostInfo::GetSDKRoot(HostInfo::SDKOptions{merged_sdk});
+if (path_or_err) {
+  sysroot_spec = FileSpec(*path_or_err);
+} else {
+  LLDB_LOG_ERROR(GetLog(LLDBLog::Types | LLDBLog::Host),
+ path_or_err.takeError(),
+ "Failed to resolve SDK path: {0}");
+}
   }
 }
   }

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][NFC] Inline ResolveSDKPathFromDebugInfo in one of its call site (PR #146062)

2025-06-27 Thread via lldb-commits

llvmbot wrote:




@llvm/pr-subscribers-lldb

Author: Charles Zablit (charles-zablit)


Changes

This patch is part of an effort to remove the ResolveSDKPathFromDebugInfo 
method, and more specifically the variant which takes a Module as argument.

This PR should be merged after https://github.com/llvm/llvm-project/pull/144913.

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


1 Files Affected:

- (modified) lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp (+26-6) 


``diff
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp 
b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index 262a7dc731713..ae46ac63e756a 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -1130,13 +1130,33 @@ void 
PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
 
   if (target) {
 if (ModuleSP exe_module_sp = target->GetExecutableModule()) {
-  auto path_or_err = ResolveSDKPathFromDebugInfo(*exe_module_sp);
-  if (path_or_err) {
-sysroot_spec = FileSpec(*path_or_err);
+  SymbolFile *sym_file = exe_module_sp->GetSymbolFile();
+  if (!sym_file)
+return;
+
+  XcodeSDK merged_sdk;
+  for (unsigned i = 0; i < sym_file->GetNumCompileUnits(); ++i) {
+if (auto cu_sp = sym_file->GetCompileUnitAtIndex(i)) {
+  auto cu_sdk = sym_file->ParseXcodeSDK(*cu_sp);
+  merged_sdk.Merge(cu_sdk);
+}
+  }
+
+  // TODO: The result of this loop is almost equivalent to deriving the SDK
+  // from the target triple, which would be a lot cheaper.
+
+  if (FileSystem::Instance().Exists(merged_sdk.GetSysroot())) {
+sysroot_spec = merged_sdk.GetSysroot();
   } else {
-LLDB_LOG_ERROR(GetLog(LLDBLog::Types | LLDBLog::Host),
-   path_or_err.takeError(),
-   "Failed to resolve SDK path: {0}");
+auto path_or_err =
+HostInfo::GetSDKRoot(HostInfo::SDKOptions{merged_sdk});
+if (path_or_err) {
+  sysroot_spec = FileSpec(*path_or_err);
+} else {
+  LLDB_LOG_ERROR(GetLog(LLDBLog::Types | LLDBLog::Host),
+ path_or_err.takeError(),
+ "Failed to resolve SDK path: {0}");
+}
   }
 }
   }

``




https://github.com/llvm/llvm-project/pull/146062
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Fix a bug in the breakpoint ID verifier in CommandObjectBreakpoint. (PR #145994)

2025-06-27 Thread David Spickett via lldb-commits

DavidSpickett wrote:

Already done by 
https://github.com/llvm/llvm-project/commit/3f00cff5c7871dbde3871d31fffbf183b3ce3419.

https://github.com/llvm/llvm-project/pull/145994
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add type summaries for MSVC STL strings (PR #143177)

2025-06-27 Thread David Spickett via lldb-commits


@@ -299,6 +299,8 @@ def parseOptionsAndInitTestdirs():
 configuration.libcxx_library_dir = args.libcxx_library_dir
 configuration.cmake_build_type = args.cmake_build_type.lower()
 
+configuration.target_triple = args.target_triple
+

DavidSpickett wrote:

Also I'm bothered that there isn't any explicit enabling of the MSVC STL in the 
compiler flags, but I suppose that's what you and Pavel have been debating this 
whole time :)

What you've got is a predicate that says "does this compiler by default use 
MSVC STL" then the tests deliberately don't add any stlib related flags, so 
that they get that default. And as you mentioned above, there is no "opt in" to 
MSVC STL anyway.

Do I understand correctly? If so I think that is a reasonable way to do this. 
The fact that it relies on implicit selection seems to be out of your control.

https://github.com/llvm/llvm-project/pull/143177
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] make PlatformAndroid/AdbClient::GetSyncService threadsafe (PR #145382)

2025-06-27 Thread Chad Smith via lldb-commits

cs01 wrote:

Thank you both for the feedback. I started working on changes that add more 
mutexes to adbclient methods, use a shared pointer for the sync service, and 
has cleaner/less path dependent creation of the syncservice (I agree with your 
comments labath). I will push an update either today or sometime next week. 

https://github.com/llvm/llvm-project/pull/145382
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add type summaries for MSVC STL strings (PR #143177)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,4 @@
+CXX_SOURCES := main.cpp
+
+CXXFLAGS_EXTRAS := -std=c++20 -O0

DavidSpickett wrote:

Is there a specific reason for this to be C++20? Trying to enable as many 
features in u8string as possible perhaps?

https://github.com/llvm/llvm-project/pull/143177
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add type summaries for MSVC STL strings (PR #143177)

2025-06-27 Thread David Spickett via lldb-commits


@@ -299,6 +299,8 @@ def parseOptionsAndInitTestdirs():
 configuration.libcxx_library_dir = args.libcxx_library_dir
 configuration.cmake_build_type = args.cmake_build_type.lower()
 
+configuration.target_triple = args.target_triple
+

DavidSpickett wrote:

...unless someone has a mingw compiler and wants to use MSVC STL but I think 
that's A: asking for trouble and B: defeating part of the point of mingw? Hmm.

Anyway, the tests will run on a buildbot that will be running for a few years 
to come, that's the main thing here.

https://github.com/llvm/llvm-project/pull/143177
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][RISCV] fix LR/SC atomic sequence handling in lldb-server (PR #146072)

2025-06-27 Thread David Spickett via lldb-commits

https://github.com/DavidSpickett approved this pull request.

Please describe in the PR description the changes made since it was reverted 
(even as trivial as they are here).

This helps git archaeology a bit, and users who might want to check the state 
of a feature later and might be confused by a revert/reland sequence.

Otherwise, LGTM.

https://github.com/llvm/llvm-project/pull/146072
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [llvm] [NFC][DebugInfo][DWARF] Create new low-level dwarf library (PR #145081)

2025-06-27 Thread LLVM Continuous Integration via lldb-commits

llvm-ci wrote:

LLVM Buildbot has detected a new failure on builder `flang-aarch64-sharedlibs` 
running on `linaro-flang-aarch64-sharedlibs` while building 
`bolt,lldb,llvm,utils` at step 5 "build-unified-tree".

Full details are available at: 
https://lab.llvm.org/buildbot/#/builders/80/builds/14255


Here is the relevant piece of the build log for the reference

```
Step 5 (build-unified-tree) failure: build (failure)
...
341.980 [3462/162/4077] Building CXX object 
tools/clang/lib/Sema/CMakeFiles/obj.clangSema.dir/SemaConsumer.cpp.o
341.982 [3461/162/4078] Building CXX object 
tools/clang/lib/Sema/CMakeFiles/obj.clangSema.dir/SemaDirectX.cpp.o
341.986 [3460/162/4079] Building CXX object 
tools/clang/lib/CodeGen/CMakeFiles/obj.clangCodeGen.dir/CodeGenAction.cpp.o
341.991 [3459/162/4080] Building CXX object 
tools/clang/lib/CodeGen/CMakeFiles/obj.clangCodeGen.dir/CodeGenModule.cpp.o
341.994 [3458/162/4081] Building CXX object 
tools/clang/lib/CodeGen/CMakeFiles/obj.clangCodeGen.dir/CodeGenPGO.cpp.o
341.998 [3457/162/4082] Building CXX object 
tools/clang/lib/CodeGen/CMakeFiles/obj.clangCodeGen.dir/CoverageMappingGen.cpp.o
342.001 [3456/162/4083] Building CXX object 
tools/clang/lib/CodeGen/CMakeFiles/obj.clangCodeGen.dir/ObjectFilePCHContainerWriter.cpp.o
342.004 [3455/162/4084] Building CXX object 
tools/clang/lib/AST/CMakeFiles/obj.clangAST.dir/CommentSema.cpp.o
342.007 [3454/162/4085] Building CXX object 
tools/clang/lib/AST/CMakeFiles/obj.clangAST.dir/Expr.cpp.o
342.009 [3453/162/4086] Linking CXX shared library 
lib/libLLVMDebugInfoLogicalView.so.21.0git
FAILED: lib/libLLVMDebugInfoLogicalView.so.21.0git 
: && /usr/local/bin/c++ -fPIC -fPIC -fno-semantic-interposition 
-fvisibility-inlines-hidden -Werror=date-time 
-Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter 
-Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic 
-Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough 
-Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor 
-Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion 
-Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color 
-ffunction-sections -fdata-sections -O3 -DNDEBUG  -Wl,-z,defs -Wl,-z,nodelete   
-Wl,-rpath-link,/home/tcwg-buildbot/worker/flang-aarch64-sharedlibs/build/./lib 
 -Wl,--gc-sections -shared -Wl,-soname,libLLVMDebugInfoLogicalView.so.21.0git 
-o lib/libLLVMDebugInfoLogicalView.so.21.0git 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVCompare.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVElement.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVLine.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVLocation.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVObject.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVOptions.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVRange.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVReader.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVScope.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVSort.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVSourceLanguage.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVSupport.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVSymbol.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Core/LVType.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/LVReaderHandler.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Readers/LVBinaryReader.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Readers/LVCodeViewReader.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Readers/LVCodeViewVisitor.cpp.o
 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Readers/LVDWARFReader.cpp.o
  
-Wl,-rpath,"\$ORIGIN/../lib:/home/tcwg-buildbot/worker/flang-aarch64-sharedlibs/build/lib:"
  lib/libLLVMDebugInfoDWARF.so.21.0git  lib/libLLVMDebugInfoPDB.so.21.0git  
lib/libLLVMObject.so.21.0git  lib/libLLVMMC.so.21.0git  
lib/libLLVMBinaryFormat.so.21.0git  lib/libLLVMTargetParser.so.21.0git  
lib/libLLVMDebugInfoCodeView.so.21.0git  lib/libLLVMSupport.so.21.0git  
lib/libLLVMDemangle.so.21.0git  
-Wl,-rpath-link,/home/tcwg-buildbot/worker/flang-aarch64-sharedlibs/build/lib 
&& :
/usr/bin/ld: 
lib/DebugInfo/LogicalView/CMakeFiles/LLVMDebugInfoLogicalView.dir/Readers/LVDWARFReader.cpp.o:
 in function 
`llvm::logicalview::LVDWARFReader::processLocationList(llvm::dwarf::Attribute, 
llvm::DWARFFormValue const&, llvm::DWARFDie const&, unsigned long, 
bool)::$_0::operator()(llvm::DWARFExpression const&) const':
LVDWARFRead

[Lldb-commits] [lldb] Fix a bug in the breakpoint ID verifier in CommandObjectBreakpoint. (PR #145994)

2025-06-27 Thread Dmitry Vasilyev via lldb-commits

slydiman wrote:

The buildbot 
[lldb-x86_64-win](https://lab.llvm.org/staging/#/builders/211/builds/700) is 
broken after this patch.
Please fix it ASAP. We are planning to switch this buildbot to the production 
mode soon.

https://github.com/llvm/llvm-project/pull/145994
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread Pavel Labath via lldb-commits


@@ -21,7 +24,9 @@
 using namespace lldb;
 using namespace lldb_private;
 
-static DWORD ToTimeout(std::optional point) {
+namespace {

labath wrote:

according to the [coding 
standards](https://llvm.org/docs/CodingStandards.html#restrict-visibility) 
anonymous namespaces should be as small as possible. That means the function 
should stay static and (large) methods should be defined out of line (and out 
of the namespace)

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread Pavel Labath via lldb-commits


@@ -493,7 +496,12 @@ ConnectionFileDescriptor::BytesAvailable(const 
Timeout &timeout,
   break; // Lets keep reading to until we timeout
 }
   } else {
+#if defined(_WIN32)
+if (const auto *sock = static_cast(m_io_sp.get());

labath wrote:

probably check m_io_sp->GetFdType() first.

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread Pavel Labath via lldb-commits


@@ -31,20 +31,27 @@ class MainLoopWindows : public MainLoopBase {
 
   Status Run() override;
 
+  struct FdInfo {
+FdInfo(intptr_t event, Callback callback)
+: event(event), callback(callback) {}
+virtual ~FdInfo() {}
+virtual void WillPoll() {}
+virtual void DidPoll() {}
+virtual void Disarm() {}
+intptr_t event;

labath wrote:

could we use some more specific type for this? IOObject::WaitableHandle maybe?

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread Pavel Labath via lldb-commits


@@ -31,20 +31,27 @@ class MainLoopWindows : public MainLoopBase {
 
   Status Run() override;
 
+  struct FdInfo {
+FdInfo(intptr_t event, Callback callback)
+: event(event), callback(callback) {}
+virtual ~FdInfo() {}
+virtual void WillPoll() {}
+virtual void DidPoll() {}
+virtual void Disarm() {}
+intptr_t event;
+Callback callback;

labath wrote:

A struct with virtual methods reminds me of lldb-dap, in a bad way. Let's put 
these behind an accessor.

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread Pavel Labath via lldb-commits


@@ -31,6 +36,127 @@ static DWORD 
ToTimeout(std::optional point) {
   return ceil(dur).count();
 }
 
+class PipeFdInfo : public MainLoopWindows::FdInfo {
+public:
+  explicit PipeFdInfo(HANDLE handle, MainLoopBase::Callback callback)
+  : FdInfo((intptr_t)CreateEventW(NULL, /*bManualReset=*/FALSE,
+  /*bInitialState=*/FALSE, NULL),
+   callback),
+handle(handle), ready(CreateEventW(NULL, /*bManualReset=*/FALSE,
+   /*bInitialState=*/FALSE, NULL)) {
+assert(event && ready);
+  }
+
+  ~PipeFdInfo() override {
+if (monitor_thread.joinable()) {

labath wrote:

Can we drop the read thread? Did [this 
implementation](https://github.com/llvm/llvm-project/commit/6675e03763c7d64e3335f1582c0fd7bc639be7d7)
 not work? I believe it should be possible to plug the event from the read 
operation into the WaitForMultipleObjects call.

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread Pavel Labath via lldb-commits


@@ -313,8 +318,39 @@ Socket::DecodeHostAndPort(llvm::StringRef host_and_port) {
 }
 
 IOObject::WaitableHandle Socket::GetWaitableHandle() {
-  // TODO: On Windows, use WSAEventSelect
+#ifdef _WIN32
+  if (m_socket == kInvalidSocketValue)
+return kInvalidHandleValue;
+
+  if (m_waitable_handle == kInvalidHandleValue) {
+m_waitable_handle = WSACreateEvent();
+assert(m_waitable_handle != WSA_INVALID_EVENT);
+if (WSAEventSelect(m_socket, m_waitable_handle,
+   FD_ACCEPT | FD_READ | FD_WRITE) != 0)

labath wrote:

I think it should be fine as long as we call (like you do now) WSAEventSelect 
right before blocking. It probably won't work if those selects happen on 
different threads (concurrently), but I'm not worried about that. The "use 
case" I have in mind is someone getting a callback notification  doing 
*another* select to confirm that the data is indeed readable (that's kind of 
what happens with ConnectionFileDescriptor right now).

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread Pavel Labath via lldb-commits


@@ -31,8 +31,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
+#include 

labath wrote:

Are all of these still used?

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread Pavel Labath via lldb-commits

https://github.com/labath commented:

This looks much better. My two main questions now are:
- do we need regular file support
- do we need the pipe *thread*

(I think/hope the answer is "no" on both counts).

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread Pavel Labath via lldb-commits

https://github.com/labath edited 
https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread Pavel Labath via lldb-commits


@@ -274,7 +276,23 @@ int NativeFile::GetDescriptor() const {
 }
 
 IOObject::WaitableHandle NativeFile::GetWaitableHandle() {
+#ifdef _WIN32
+  return (HANDLE)_get_osfhandle(GetDescriptor());
+#else
   return GetDescriptor();
+#endif
+}
+
+bool NativeFile::HasReadableData() {
+#ifdef _WIN32
+  DWORD available_bytes = 0;
+  return !PeekNamedPipe((HANDLE)_get_osfhandle(GetDescriptor()), NULL, 0, NULL,

labath wrote:

That's better, but I do have a question, and a comment :)

- Do we need to support selecting on actual files? That doesn't even work on 
posix systems (the file just always comes back as "readable" -- which makes 
sense because select just tells you whether the operation will block), so if 
anything, I think we should emulate that. Waiting for file modification 
requires things like inotify(7), and fortunately, noone has had a use case for 
that for now. If we ever needed to support it, that should probably be a 
separate kind of an event. I'm assuming that `GetFileType` on a pipe handle 
will return `FILE_TYPE_PIPE`, even if that handle was passed as `stdin`.

- it my long term vision, I would like lldb-dap to create Pipe IOObject 
directly (perhaps via some helper on the File class) instead of having the 
MainLoop class guess it. However, given that Pipe is not an IOObject right now, 
this is something I can live with.

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,68 @@
+# Model Context Protocol (MCP)
+
+LLDB supports for the [Model Context Protocol][1] (MCP). This structured,
+machine-friendly protocol allows AI models to access and interact with external
+tools, such as the debugger. Using MCP, an AI agent can execute LLDB commands
+to control the debugger: set breakpoints, inspect memory, step through code.
+This can range from helping you run a specific command you can't immediately
+remember to a fully agent-driven debugging experiences
+
+## MCP Server
+
+To start the MCP server in LLDB, use the `protocol-server start` command.
+Specify `MCP` as the protocol and provide a URI to listen on. For example, to
+start listening for local TCP connections on port `5`, use the following
+command:
+
+```
+(lldb) protocol-server start MCP listen://localhost:5
+MCP server started with connection listeners: connection://[::1]:5, 
connection://[127.0.0.1]:5
+```
+
+The server will automatically stop when exiting LLDB, or it can be stopped
+explicitly with the `protocol-server stop` command.
+
+```
+(lldb) protocol-server stop MCP
+```
+
+## MCP Client
+
+MCP uses standard input/output (stdio) for communication between client and
+server. The exact configuration depends on the client, but most applications
+allow you to specify an MCP server as a binary and arguments. This means that
+you need to use something like `netcat` to connect to LLDB's MCP server and
+forward communication over stdio over the network connection.
+
+Configuration example for [Claude Code][2]:
+
+```
+{
+  "mcpServers": {
+"tool": {
+  "command": "/usr/bin/nc",
+  "args": ["localhost", "5"]
+}
+  }
+}
+```
+
+Configuration example for [Visual Studio Code][3]:
+
+```
+{
+  "mcp": {
+"servers": {
+  "lldb": {
+"type": "stdio",
+"command": "/usr/bin/nc",
+"args": ["localhost", "5"]
+  }
+}
+  }
+}
+```
+
+[1]: https://modelcontextprotocol.io
+[2]: https://modelcontextprotocol.io/quickstart/user
+[3]: https://code.visualstudio.com/docs/copilot/chat/mcp-servers

DavidSpickett wrote:

I would add these links to the text instead of making them citations like this.

If you're feeling adventurous you could see if 
https://github.blog/changelog/2021-09-30-footnotes-now-supported-in-markdown-fields/
 works in our docs generator, but I think links within the text is cleaner 
anyway.

https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,68 @@
+# Model Context Protocol (MCP)
+
+LLDB supports for the [Model Context Protocol][1] (MCP). This structured,
+machine-friendly protocol allows AI models to access and interact with external
+tools, such as the debugger. Using MCP, an AI agent can execute LLDB commands
+to control the debugger: set breakpoints, inspect memory, step through code.
+This can range from helping you run a specific command you can't immediately
+remember to a fully agent-driven debugging experiences
+
+## MCP Server
+
+To start the MCP server in LLDB, use the `protocol-server start` command.
+Specify `MCP` as the protocol and provide a URI to listen on. For example, to
+start listening for local TCP connections on port `5`, use the following
+command:
+
+```
+(lldb) protocol-server start MCP listen://localhost:5
+MCP server started with connection listeners: connection://[::1]:5, 
connection://[127.0.0.1]:5
+```
+
+The server will automatically stop when exiting LLDB, or it can be stopped
+explicitly with the `protocol-server stop` command.
+
+```
+(lldb) protocol-server stop MCP

DavidSpickett wrote:

Implies you can run multiple servers one on each transport type?

Also can you have multiple? Here would be a good place to note whether you can 
or cannot.

https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,68 @@
+# Model Context Protocol (MCP)
+
+LLDB supports for the [Model Context Protocol][1] (MCP). This structured,

DavidSpickett wrote:

`supports the`, drop the `for`

https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,68 @@
+# Model Context Protocol (MCP)
+
+LLDB supports for the [Model Context Protocol][1] (MCP). This structured,
+machine-friendly protocol allows AI models to access and interact with external
+tools, such as the debugger. Using MCP, an AI agent can execute LLDB commands
+to control the debugger: set breakpoints, inspect memory, step through code.
+This can range from helping you run a specific command you can't immediately
+remember to a fully agent-driven debugging experiences
+
+## MCP Server
+
+To start the MCP server in LLDB, use the `protocol-server start` command.
+Specify `MCP` as the protocol and provide a URI to listen on. For example, to
+start listening for local TCP connections on port `5`, use the following
+command:
+
+```
+(lldb) protocol-server start MCP listen://localhost:5
+MCP server started with connection listeners: connection://[::1]:5, 
connection://[127.0.0.1]:5
+```
+
+The server will automatically stop when exiting LLDB, or it can be stopped
+explicitly with the `protocol-server stop` command.
+
+```
+(lldb) protocol-server stop MCP
+```
+
+## MCP Client
+
+MCP uses standard input/output (stdio) for communication between client and
+server. The exact configuration depends on the client, but most applications
+allow you to specify an MCP server as a binary and arguments. This means that
+you need to use something like `netcat` to connect to LLDB's MCP server and
+forward communication over stdio over the network connection.

DavidSpickett wrote:

Add a "diagram" to show the flow like:
```
LLDB <--> socket <--> netcat <--> stdio <--> MCP client
```

https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,68 @@
+# Model Context Protocol (MCP)
+
+LLDB supports for the [Model Context Protocol][1] (MCP). This structured,
+machine-friendly protocol allows AI models to access and interact with external
+tools, such as the debugger. Using MCP, an AI agent can execute LLDB commands

DavidSpickett wrote:

`such as a debugger` if you're going to generically refer to debuggers. Or 
`such as LLDB` if you prefer.

https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,68 @@
+# Model Context Protocol (MCP)
+
+LLDB supports for the [Model Context Protocol][1] (MCP). This structured,
+machine-friendly protocol allows AI models to access and interact with external
+tools, such as the debugger. Using MCP, an AI agent can execute LLDB commands
+to control the debugger: set breakpoints, inspect memory, step through code.
+This can range from helping you run a specific command you can't immediately

DavidSpickett wrote:

I prefer to expand contractions in a technical document: can't -> cannot

https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,68 @@
+# Model Context Protocol (MCP)
+
+LLDB supports for the [Model Context Protocol][1] (MCP). This structured,
+machine-friendly protocol allows AI models to access and interact with external
+tools, such as the debugger. Using MCP, an AI agent can execute LLDB commands
+to control the debugger: set breakpoints, inspect memory, step through code.
+This can range from helping you run a specific command you can't immediately
+remember to a fully agent-driven debugging experiences

DavidSpickett wrote:

`to full agent-driven`, drop the `a`. Or rephrase `to a fully agent-driven 
debugging experience` singular.

https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Document MCP support in LLDB (PR #145935)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,68 @@
+# Model Context Protocol (MCP)
+
+LLDB supports for the [Model Context Protocol][1] (MCP). This structured,
+machine-friendly protocol allows AI models to access and interact with external
+tools, such as the debugger. Using MCP, an AI agent can execute LLDB commands
+to control the debugger: set breakpoints, inspect memory, step through code.
+This can range from helping you run a specific command you can't immediately
+remember to a fully agent-driven debugging experiences
+
+## MCP Server
+
+To start the MCP server in LLDB, use the `protocol-server start` command.
+Specify `MCP` as the protocol and provide a URI to listen on. For example, to

DavidSpickett wrote:

I presume MCP is the only supported protocol at this time and the command will 
complain if you give it anything else, right?

No need to mention it if the command is going to give a decent error anyway.

https://github.com/llvm/llvm-project/pull/145935
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] da2969b - [LLDB] Update DIL to handle smart pointers; add more tests. (#143786)

2025-06-27 Thread via lldb-commits

Author: cmtice
Date: 2025-06-27T07:30:14-07:00
New Revision: da2969b1051f4adf57d4395cd2f3e1e8c33b3d1b

URL: 
https://github.com/llvm/llvm-project/commit/da2969b1051f4adf57d4395cd2f3e1e8c33b3d1b
DIFF: 
https://github.com/llvm/llvm-project/commit/da2969b1051f4adf57d4395cd2f3e1e8c33b3d1b.diff

LOG: [LLDB] Update DIL to handle smart pointers; add more tests. (#143786)

This updates the DIL implementation to handle smart pointers (accessing
field members and dereferencing) in the same way the current 'frame
variable' implementation does. It also adds tests for handling smart
pointers, as well as some additional DIL tests.

Added: 
lldb/test/API/commands/frame/var-dil/basics/BitField/Makefile

lldb/test/API/commands/frame/var-dil/basics/BitField/TestFrameVarDILBitField.py
lldb/test/API/commands/frame/var-dil/basics/BitField/main.cpp
lldb/test/API/commands/frame/var-dil/basics/Indirection/Makefile

lldb/test/API/commands/frame/var-dil/basics/Indirection/TestFrameVarDILIndirection.py
lldb/test/API/commands/frame/var-dil/basics/Indirection/main.cpp
lldb/test/API/commands/frame/var-dil/basics/PointerDereference/Makefile

lldb/test/API/commands/frame/var-dil/basics/PointerDereference/TestFrameVarDILPointerDereference.py
lldb/test/API/commands/frame/var-dil/basics/PointerDereference/main.cpp
lldb/test/API/commands/frame/var-dil/basics/QualifiedId/Makefile

lldb/test/API/commands/frame/var-dil/basics/QualifiedId/TestFrameVarDILQualifiedId.py
lldb/test/API/commands/frame/var-dil/basics/QualifiedId/main.cpp
lldb/test/API/commands/frame/var-dil/basics/SyntheticDereference/Makefile

lldb/test/API/commands/frame/var-dil/basics/SyntheticDereference/TestFrameVarDILSyntheticDereference.py
lldb/test/API/commands/frame/var-dil/basics/SyntheticDereference/main.cpp

lldb/test/API/commands/frame/var-dil/basics/SyntheticDereference/wrapPtrSynthProvider.py

Modified: 
lldb/source/ValueObject/DILEval.cpp

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/main.cpp

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp

Removed: 




diff  --git a/lldb/source/ValueObject/DILEval.cpp 
b/lldb/source/ValueObject/DILEval.cpp
index b2bb4e20ddc24..4293990208c77 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -253,6 +253,12 @@ Interpreter::Visit(const UnaryOpNode *node) {
   rhs = dynamic_rhs;
 
 lldb::ValueObjectSP child_sp = rhs->Dereference(error);
+if (!child_sp && m_use_synthetic) {
+  if (lldb::ValueObjectSP synth_obj_sp = rhs->GetSyntheticValue()) {
+error.Clear();
+child_sp = synth_obj_sp->Dereference(error);
+  }
+}
 if (error.Fail())
   return llvm::make_error(m_expr, error.AsCString(),
   node->GetLocation());
@@ -280,6 +286,7 @@ Interpreter::Visit(const MemberOfNode *node) {
   auto base_or_err = Evaluate(node->GetBase());
   if (!base_or_err)
 return base_or_err;
+  bool expr_is_ptr = node->GetIsArrow();
   lldb::ValueObjectSP base = *base_or_err;
 
   // Perform some basic type & correctness checking.
@@ -319,11 +326,11 @@ Interpreter::Visit(const MemberOfNode *node) {
 return llvm::make_error(
 m_expr, errMsg, node->GetLocation(), node->GetFieldName().size());
   }
+  expr_is_ptr = false;
 }
   }
 
   if (m_check_ptr_vs_member) {
-bool expr_is_ptr = node->GetIsArrow();
 bool base_is_ptr = base->IsPointerType();
 
 if (expr_is_ptr != base_is_ptr) {

diff  --git a/lldb/test/API/commands/frame/var-dil/basics/BitField/Makefile 
b/lldb/test/API/commands/frame/var-dil/basics/BitField/Makefile
new file mode 100644
index 0..8b20bcb05
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/basics/BitField/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules

diff  --git 
a/lldb/test/API/commands/frame/var-dil/basics/BitField/TestFrameVarDILBitField.py
 
b/lldb/test/API/commands/frame/var-dil/basics/BitField/TestFrameVarDILBitField.py
new file mode 100644
index 0..0e35069519093
--- /dev/null
+++ 
b/lldb/test/API/commands/frame/var-dil/basics/BitField/TestFrameVarDILBitField.py
@@ -0,0 +1,43 @@
+"""
+Make sure 'frame var' using DIL parser/evaluator works for bit fields.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test import lldbutil
+
+import os
+import shutil
+import time
+
+
+class TestFrameVarDILBitField(TestBase):
+# If your test case doesn't stress debug 

[Lldb-commits] [lldb] [LLDB] Update DIL to handle smart pointers; add more tests. (PR #143786)

2025-06-27 Thread via lldb-commits

https://github.com/cmtice closed 
https://github.com/llvm/llvm-project/pull/143786
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Support disassembling RISC-V proprietary instructions (PR #145793)

2025-06-27 Thread David Spickett via lldb-commits


@@ -0,0 +1,87 @@
+"""
+Defines a command, fdis, that does filtered disassembly. The command does the
+lldb disassemble command with -b and any other arguments passed in, and
+pipes that through a provided filter program.
+
+The intention is to support disassembly of RISC-V proprietary instructions.
+This is handled with llvm-objdump by piping the output of llvm-objdump through
+a filter program. This script is intended to mimic that workflow.
+"""
+
+import lldb
+import subprocess
+
+filter_program = "crustfilt"
+
+def __lldb_init_module(debugger, dict):
+debugger.HandleCommand(
+'command script add -f filter_disasm.fdis fdis')
+print("Disassembly filter command (fdis) loaded")
+print("Filter program set to %s" % filter_program)
+
+
+def fdis(debugger, args, result, dict):

DavidSpickett wrote:

I presume you already read 
https://lldb.llvm.org/use/python-reference.html#create-a-new-lldb-command-using-a-python-function
 or at least some of it (it's a lot).

https://github.com/llvm/llvm-project/blob/main/lldb/examples/python/cmdtemplate.py
 shows the style I was thinking of, which should get you the same help 
formatting as a built in command.


https://github.com/llvm/llvm-project/pull/145793
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add type summaries for MSVC STL strings (PR #143177)

2025-06-27 Thread David Spickett via lldb-commits


@@ -299,6 +299,8 @@ def parseOptionsAndInitTestdirs():
 configuration.libcxx_library_dir = args.libcxx_library_dir
 configuration.cmake_build_type = args.cmake_build_type.lower()
 
+configuration.target_triple = args.target_triple
+

DavidSpickett wrote:

> I did apply your commit onto main, rather than building the PR branch so it 
> could be a different change causing that.

The unexpected passes are due to this change specifically.

https://github.com/llvm/llvm-project/pull/143177
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Support disassembling RISC-V proprietary instructions (PR #145793)

2025-06-27 Thread David Spickett via lldb-commits


@@ -658,8 +658,13 @@ void Instruction::Dump(lldb_private::Stream *s, uint32_t 
max_opcode_byte_size,
   // the byte dump to be able to always show 15 bytes (3 chars each) plus a
   // space
   if (max_opcode_byte_size > 0)
-m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
-  else
+// make RISC-V opcode dump look like llvm-objdump

DavidSpickett wrote:

If you say instead "Pretty print RISC-V opcodes in the same format that 
llvm-objdump uses." this hints at the motivation and what keywords to look for 
in llvm-objdump's source.

https://github.com/llvm/llvm-project/pull/145793
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Support disassembling RISC-V proprietary instructions (PR #145793)

2025-06-27 Thread David Spickett via lldb-commits


@@ -658,8 +658,13 @@ void Instruction::Dump(lldb_private::Stream *s, uint32_t 
max_opcode_byte_size,
   // the byte dump to be able to always show 15 bytes (3 chars each) plus a
   // space
   if (max_opcode_byte_size > 0)
-m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
-  else
+// make RISC-V opcode dump look like llvm-objdump
+if (exe_ctx &&
+exe_ctx->GetTargetSP()->GetArchitecture().GetTriple().isRISCV())
+  m_opcode.DumpRISCV(&ss, max_opcode_byte_size * 3 + 1);

DavidSpickett wrote:

Pull the minimum size out into:
```
auto min_byte_width = max_opcode_byte_size * 3 + 1;
```
Then use it in both calls, so it's clear they use the same minimum.

https://github.com/llvm/llvm-project/pull/145793
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Support disassembling RISC-V proprietary instructions (PR #145793)

2025-06-27 Thread David Spickett via lldb-commits

DavidSpickett wrote:

> Arm M profile has 
> https://developer.arm.com/Architectures/Arm%20Custom%20Instructions, I'll 
> look into that and see if it would benefit from a change of output format 
> too. Just in theory though, I don't think we shipped support for open source 
> debuggers and I'm not about to implement it myself.

CDE works by assigning one of the co-processors to be the encodings for the 
custom instructions and it has a few fixed formats you can use. It's not like 
RISC-V where the layout can be anything you want. Which means that the 
disassembler would probably print some form, with encoding, and that can 
already be used to filter if you wanted to.

I also checked how AArch64 works:
``
$ cat /tmp/test.c
int main() {
  asm volatile(".inst 0x4321");
  return 0;
}
```
objdump shows the bytes:
```
0714 :
 714: d10043ff  sub sp, sp, #0x10
 718: 2a1f03e0  mov w0, wzr
 71c: b9000fff  str wzr, [sp, #0xc]
 720: 4321  
 724: 910043ff  add sp, sp, #0x10
 728: d65f03c0  ret
```
As does LLDB:
```
(lldb) dis -b
test.o`main:
0xa714 <+0>:  0xd10043ff   subsp, sp, #0x10
0xa718 <+4>:  0x2a1f03e0   movw0, wzr
0xa71c <+8>:  0xb9000fff   strwzr, [sp, #0xc]
->  0xa720 <+12>: 0x4321; 
unknown opcode
0xa724 <+16>: 0x910043ff   addsp, sp, #0x10
0xa728 <+20>: 0xd65f03c0   ret
```
So for AArch64 we happen to mostly match objdump's output, and it's useful 
enough for humans and scripts because it can only ever be 32-bit encodings.

Also having looked at the pretty printer system in llvm-objdump, I think `if 
riscv` is ok here. LLDB is effectively a selective objdumper and the only 
difference between what you're adding here and what llvm-objdump has is the 
framework around it. Which we do not need when only RISC-V wants this.

https://github.com/llvm/llvm-project/pull/145793
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Support disassembling RISC-V proprietary instructions (PR #145793)

2025-06-27 Thread David Spickett via lldb-commits


@@ -78,6 +78,44 @@ lldb::ByteOrder Opcode::GetDataByteOrder() const {
   return eByteOrderInvalid;
 }
 
+// make RISC-V byte dumps look like llvm-objdump, instead of just dumping bytes
+int Opcode::DumpRISCV(Stream *s, uint32_t min_byte_width) {
+  const uint32_t previous_bytes = s->GetWrittenBytes();
+  // if m_type is not bytes, call Dump
+  if (m_type != Opcode::eTypeBytes)
+return Dump(s, min_byte_width);
+
+  // from RISCVPrettyPrinter in llvm-objdump.cpp
+  // if size % 4 == 0, print as 1 or 2 32 bit values (32 or 64 bit inst)
+  // else if size % 2 == 0, print as 1 or 3 16 bit values (16 or 48 bit inst)
+  // else fall back and print bytes

DavidSpickett wrote:

I would put these comments next to the ifs they refer to, I have to read the 
code anyway so it makes more sense to me to have the commentary interleaved.

https://github.com/llvm/llvm-project/pull/145793
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits


@@ -0,0 +1,300 @@
+//===-- RegisterContextUnifiedCore.cpp 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "RegisterContextUnifiedCore.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/StructuredData.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextUnifiedCore::RegisterContextUnifiedCore(
+Thread &thread, uint32_t concrete_frame_idx,
+RegisterContextSP core_thread_regctx_sp,
+StructuredData::ObjectSP metadata_thread_registers)
+: RegisterContext(thread, concrete_frame_idx) {
+
+  ProcessSP process_sp(thread.GetProcess());
+  Target &target = process_sp->GetTarget();
+  StructuredData::Dictionary *metadata_registers_dict = nullptr;
+
+  // If we have thread metadata, check if the keys for register
+  // definitions are present; if not, clear the ObjectSP.
+  if (metadata_thread_registers &&
+  metadata_thread_registers->GetAsDictionary() &&
+  metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {
+metadata_registers_dict = metadata_thread_registers->GetAsDictionary()
+  ->GetValueForKey("register_info")
+  ->GetAsDictionary();
+if (metadata_registers_dict)
+  if (!metadata_registers_dict->HasKey("sets") ||
+  !metadata_registers_dict->HasKey("registers"))
+metadata_registers_dict = nullptr;
+  }
+
+  // When creating a register set list from the two sources,
+  // the LC_THREAD aka core_thread_regctx_sp register sets
+  // will be used at the same indexes.
+  // Any additional sets named by the thread metadata registers
+  // will be added after them.  If the thread metadata
+  // specify a set with the same name as LC_THREAD, the already-used
+  // index from the core register context will be used in
+  // the RegisterInfo.
+  std::map metadata_regset_to_combined_regset;
+
+  // Calculate the total size of the register store buffer we need
+  // for all registers.  The corefile register definitions may include
+  // RegisterInfo descriptions of registers that aren't actually
+  // available.  For simplicity, calculate the size of all registers
+  // as if they are available, so we can maintain the same offsets into
+  // the buffer.
+  uint32_t core_buffer_end = 0;
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+core_buffer_end =
+std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);
+  }
+
+  // Add metadata register sizes to the total buffer size.
+  uint32_t combined_buffer_end = core_buffer_end;
+  if (metadata_registers_dict) {
+StructuredData::Array *registers = nullptr;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach(
+  [&combined_buffer_end](StructuredData::Object *ent) -> bool {
+uint32_t bitsize;
+if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
+ bitsize))
+  return false;
+combined_buffer_end += (bitsize / 8);
+return true;
+  });
+  }
+  m_register_data.resize(combined_buffer_end, 0);
+
+  // Copy the core register values into our combined data buffer,
+  // skip registers that are contained within another (e.g. w0 vs. x0)
+  // and registers that return as "unavailable".
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+RegisterValue val;
+if (!reginfo->value_regs &&
+core_thread_regctx_sp->ReadRegister(reginfo, val))
+  memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),
+ val.GetByteSize());
+  }
+
+  // Set 'offset' fields for each register definition into our combined
+  // register data buffer. DynamicRegisterInfo needs
+  // this field set to parse the JSON.
+  // Also copy the values of the registers into our register data buffer.
+  if (metadata_registers_dict) {
+size_t offset = core_buffer_end;
+ByteOrder byte_order = core_thread_regctx_sp->GetByteOrder();
+StructuredData::Array *registers;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach([this, &offset,
+  byte_order](StructuredData::Object *ent) -> bool {
+uint64_t bitsize;

[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits

https://github.com/jasonmolenda updated 
https://github.com/llvm/llvm-project/pull/144627

>From 92348b28fb02901e9437b92c1ddf8cfed31c Mon Sep 17 00:00:00 2001
From: Jason Molenda 
Date: Tue, 17 Jun 2025 18:57:11 -0700
Subject: [PATCH 01/19] [lldb][Mach-O] Allow "process metadata" LC_NOTE to
 supply registers

The "process metadata" LC_NOTE allows for thread IDs to be specified
in a Mach-O corefile.  This extends the JSON recognzied in that
LC_NOTE to allow for additional registers to be supplied on a
per-thread basis.

The registers included in a Mach-O corefile LC_THREAD load command
can only be one of the register flavors that the kernel (xnu) defines
in  for arm64 -- the general purpose
registers, floating point registers, exception registers.

JTAG style corefile producers may have access to many additional
registers beyond these that EL0 programs typically use, for instance
TCR_EL1 on AArch64, and people developing low level code need access
to these registers.  This patch defines a format for including these
registers for any thread.

The JSON in "process metadata" is a dictionary that must have a
`threads` key.  The value is an array of entries, one per LC_THREAD
in the Mach-O corefile.  The number of entries must match the
LC_THREADs so they can be correctly associated.

Each thread's dictionary must have two keys, `sets`, and `registers`.
`sets` is an array of register set names.  If a register set name
matches one from the LC_THREAD core registers, any registers that
are defined will be added to that register set.  e.g. metadata can
add a register to the "General Purpose Registers" set that lldb
shows users.

`registers` is an array of dictionaries, one per register.  Each
register must have the keys `name`, `value`, `bitsize`, and `set`.
It may provide additional keys like `alt-name`, that
`DynamicRegisterInfo::SetRegisterInfo` recognizes.

This `sets` + `registers` formatting is the same that is used by
the `target.process.python-os-plugin-path` script interface uses,
both are parsed by `DynamicRegisterInfo`.  The one addition is that
in this LC_NOTE metadata, each register must also have a `value`
field, with the value provided in big-endian base 10, as usual with
JSON.

In RegisterContextUnifiedCore, I combine the register sets & registers
from the LC_THREAD for a specific thread, and the metadata sets &
registers for that thread from the LC_NOTE.  Even if no LC_NOTE
is present, this class ingests the LC_THREAD register contexts and
reformats it to its internal stores before returning itself as the
RegisterContex, instead of shortcutting and returning the core's
native RegisterContext.  I could have gone either way with that,
but in the end I decided if the code is correct, we should live on
it always.

I added a test where we process save-core to create a userland corefile,
then use a utility "add-lcnote" to strip the existing "process metadata"
LC_NOTE that lldb put in it, and adds a new one from a JSON string.

rdar://74358787
---
 lldb/include/lldb/Symbol/ObjectFile.h |  17 +-
 .../ObjectFile/Mach-O/ObjectFileMachO.cpp |  61 ++-
 .../ObjectFile/Mach-O/ObjectFileMachO.h   |   2 +
 .../Plugins/Process/mach-core/CMakeLists.txt  |   1 +
 .../mach-core/RegisterContextUnifiedCore.cpp  | 293 +
 .../mach-core/RegisterContextUnifiedCore.h|  57 +++
 .../Process/mach-core/ThreadMachCore.cpp  |  55 ++-
 .../lc-note/additional-registers/Makefile |  11 +
 .../TestMetadataRegisters.py  | 100 +
 .../additional-registers/add-lcnote.cpp   | 384 ++
 .../lc-note/additional-registers/main.c   |  11 +
 11 files changed, 957 insertions(+), 35 deletions(-)
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.cpp
 create mode 100644 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.h
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/Makefile
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/TestMetadataRegisters.py
 create mode 100644 
lldb/test/API/macosx/lc-note/additional-registers/add-lcnote.cpp
 create mode 100644 lldb/test/API/macosx/lc-note/additional-registers/main.c

diff --git a/lldb/include/lldb/Symbol/ObjectFile.h 
b/lldb/include/lldb/Symbol/ObjectFile.h
index 43567592dd447..1b9ae1fb31a69 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -18,6 +18,7 @@
 #include "lldb/Utility/Endian.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/FileSpecList.h"
+#include "lldb/Utility/StructuredData.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-private.h"
 #include "llvm/Support/Threading.h"
@@ -544,9 +545,9 @@ class ObjectFile : public 
std::enable_shared_from_this,
 return false;
   }
 
-  /// Get metadata about threads from the corefile.
+  /// Get metadata about thread ids from the corefile.
   ///
-  /// The corefile may have metadata (e.g. a Mach-O "thread ext

[Lldb-commits] [lldb] a64db49 - [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (#144627)

2025-06-27 Thread via lldb-commits

Author: Jason Molenda
Date: 2025-06-27T18:43:41-07:00
New Revision: a64db49371f040859a9de7c0f4fbfb655d8dda17

URL: 
https://github.com/llvm/llvm-project/commit/a64db49371f040859a9de7c0f4fbfb655d8dda17
DIFF: 
https://github.com/llvm/llvm-project/commit/a64db49371f040859a9de7c0f4fbfb655d8dda17.diff

LOG: [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers 
(#144627)

The "process metadata" LC_NOTE allows for thread IDs to be specified in
a Mach-O corefile. This extends the JSON recognzied in that LC_NOTE to
allow for additional registers to be supplied on a per-thread basis.

The registers included in a Mach-O corefile LC_THREAD load command can
only be one of the register flavors that the kernel (xnu) defines in
 for arm64 -- the general purpose registers,
floating point registers, exception registers.

JTAG style corefile producers may have access to many additional
registers beyond these that EL0 programs typically use, for instance
TCR_EL1 on AArch64, and people developing low level code need access to
these registers. This patch defines a format for including these
registers for any thread.

The JSON in "process metadata" is a dictionary that must have a
`threads` key. The value is an array of entries, one per LC_THREAD in
the Mach-O corefile. The number of entries must match the LC_THREADs so
they can be correctly associated.

Each thread's dictionary must have two keys, `sets`, and `registers`.
`sets` is an array of register set names. If a register set name matches
one from the LC_THREAD core registers, any registers that are defined
will be added to that register set. e.g. metadata can add a register to
the "General Purpose Registers" set that lldb shows users.

`registers` is an array of dictionaries, one per register. Each register
must have the keys `name`, `value`, `bitsize`, and `set`. It may provide
additional keys like `alt-name`, that
`DynamicRegisterInfo::SetRegisterInfo` recognizes.

This `sets` + `registers` formatting is the same that is used by the
`target.process.python-os-plugin-path` script interface uses, both are
parsed by `DynamicRegisterInfo`. The one addition is that in this
LC_NOTE metadata, each register must also have a `value` field, with the
value provided in big-endian base 10, as usual with JSON.

In RegisterContextUnifiedCore, I combine the register sets & registers
from the LC_THREAD for a specific thread, and the metadata sets &
registers for that thread from the LC_NOTE. Even if no LC_NOTE is
present, this class ingests the LC_THREAD register contexts and
reformats it to its internal stores before returning itself as the
RegisterContex, instead of shortcutting and returning the core's native
RegisterContext. I could have gone either way with that, but in the end
I decided if the code is correct, we should live on it always.

I added a test where we process save-core to create a userland corefile,
then use a utility "add-lcnote" to strip the existing "process metadata"
LC_NOTE that lldb put in it, and adds a new one from a JSON string.

rdar://74358787

-

Co-authored-by: Jonas Devlieghere 

Added: 
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.cpp
lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.h
lldb/test/API/macosx/lc-note/additional-registers/Makefile
lldb/test/API/macosx/lc-note/additional-registers/TestMetadataRegisters.py
lldb/test/API/macosx/lc-note/additional-registers/add-lcnote.cpp
lldb/test/API/macosx/lc-note/additional-registers/main.c

Modified: 
lldb/include/lldb/Symbol/ObjectFile.h
lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
lldb/source/Plugins/Process/mach-core/CMakeLists.txt
lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp

Removed: 




diff  --git a/lldb/include/lldb/Symbol/ObjectFile.h 
b/lldb/include/lldb/Symbol/ObjectFile.h
index 43567592dd447..1b9ae1fb31a69 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -18,6 +18,7 @@
 #include "lldb/Utility/Endian.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/FileSpecList.h"
+#include "lldb/Utility/StructuredData.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-private.h"
 #include "llvm/Support/Threading.h"
@@ -544,9 +545,9 @@ class ObjectFile : public 
std::enable_shared_from_this,
 return false;
   }
 
-  /// Get metadata about threads from the corefile.
+  /// Get metadata about thread ids from the corefile.
   ///
-  /// The corefile may have metadata (e.g. a Mach-O "thread extrainfo"
+  /// The corefile may have metadata (e.g. a Mach-O "process metadata"
   /// LC_NOTE) which for the threads in the process; this method tries
   /// to retrieve them.
   ///
@@ -568,6 +569,18 @@ class ObjectFile : public 
std::enable_shared_from_this,
 return false;
   }
 
+  /// 

[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jason Molenda via lldb-commits


@@ -0,0 +1,300 @@
+//===-- RegisterContextUnifiedCore.cpp 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "RegisterContextUnifiedCore.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/StructuredData.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextUnifiedCore::RegisterContextUnifiedCore(
+Thread &thread, uint32_t concrete_frame_idx,
+RegisterContextSP core_thread_regctx_sp,
+StructuredData::ObjectSP metadata_thread_registers)
+: RegisterContext(thread, concrete_frame_idx) {
+
+  ProcessSP process_sp(thread.GetProcess());
+  Target &target = process_sp->GetTarget();
+  StructuredData::Dictionary *metadata_registers_dict = nullptr;
+
+  // If we have thread metadata, check if the keys for register
+  // definitions are present; if not, clear the ObjectSP.
+  if (metadata_thread_registers &&
+  metadata_thread_registers->GetAsDictionary() &&
+  metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {
+metadata_registers_dict = metadata_thread_registers->GetAsDictionary()
+  ->GetValueForKey("register_info")
+  ->GetAsDictionary();
+if (metadata_registers_dict)
+  if (!metadata_registers_dict->HasKey("sets") ||
+  !metadata_registers_dict->HasKey("registers"))
+metadata_registers_dict = nullptr;
+  }
+
+  // When creating a register set list from the two sources,
+  // the LC_THREAD aka core_thread_regctx_sp register sets
+  // will be used at the same indexes.
+  // Any additional sets named by the thread metadata registers
+  // will be added after them.  If the thread metadata
+  // specify a set with the same name as LC_THREAD, the already-used
+  // index from the core register context will be used in
+  // the RegisterInfo.
+  std::map metadata_regset_to_combined_regset;
+
+  // Calculate the total size of the register store buffer we need
+  // for all registers.  The corefile register definitions may include
+  // RegisterInfo descriptions of registers that aren't actually
+  // available.  For simplicity, calculate the size of all registers
+  // as if they are available, so we can maintain the same offsets into
+  // the buffer.
+  uint32_t core_buffer_end = 0;
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+core_buffer_end =
+std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);
+  }
+
+  // Add metadata register sizes to the total buffer size.
+  uint32_t combined_buffer_end = core_buffer_end;
+  if (metadata_registers_dict) {
+StructuredData::Array *registers = nullptr;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach(
+  [&combined_buffer_end](StructuredData::Object *ent) -> bool {
+uint32_t bitsize;
+if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
+ bitsize))
+  return false;
+combined_buffer_end += (bitsize / 8);
+return true;
+  });
+  }
+  m_register_data.resize(combined_buffer_end, 0);
+
+  // Copy the core register values into our combined data buffer,
+  // skip registers that are contained within another (e.g. w0 vs. x0)
+  // and registers that return as "unavailable".
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+RegisterValue val;
+if (!reginfo->value_regs &&
+core_thread_regctx_sp->ReadRegister(reginfo, val))
+  memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),
+ val.GetByteSize());
+  }
+
+  // Set 'offset' fields for each register definition into our combined
+  // register data buffer. DynamicRegisterInfo needs
+  // this field set to parse the JSON.
+  // Also copy the values of the registers into our register data buffer.
+  if (metadata_registers_dict) {
+size_t offset = core_buffer_end;
+ByteOrder byte_order = core_thread_regctx_sp->GetByteOrder();
+StructuredData::Array *registers;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach([this, &offset,
+  byte_order](StructuredData::Object *ent) -> bool {
+uint64_t bitsize;

[Lldb-commits] [lldb] [llvm] [NFC][DebugInfo][DWARF] Create new low-level dwarf library (PR #145081)

2025-06-27 Thread LLVM Continuous Integration via lldb-commits

llvm-ci wrote:

LLVM Buildbot has detected a new failure on builder `clang-s390x-linux` running 
on `systemz-1` while building `bolt,lldb,llvm,utils` at step 5 "ninja check 1".

Full details are available at: 
https://lab.llvm.org/buildbot/#/builders/42/builds/5136


Here is the relevant piece of the build log for the reference

```
Step 5 (ninja check 1) failure: stage 1 checked (failure)
 TEST 'libFuzzer-s390x-default-Linux :: 
fuzzer-timeout.test' FAILED 
Exit Code: 1

Command Output (stderr):
--
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/./bin/clang
-Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   
--driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer 
-I/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/lib/fuzzer 
 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/TimeoutTest.cpp
 -o 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest
 # RUN: at line 1
+ /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/./bin/clang 
-Wthread-safety -Wthread-safety-reference -Wthread-safety-beta 
--driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer 
-I/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/lib/fuzzer 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/TimeoutTest.cpp
 -o 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/./bin/clang
-Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   
--driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer 
-I/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/lib/fuzzer 
 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/TimeoutEmptyTest.cpp
 -o 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutEmptyTest
 # RUN: at line 2
+ /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/./bin/clang 
-Wthread-safety -Wthread-safety-reference -Wthread-safety-beta 
--driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer 
-I/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/lib/fuzzer 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/TimeoutEmptyTest.cpp
 -o 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutEmptyTest
not  
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest
 -timeout=1 2>&1 | FileCheck 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test
 --check-prefix=TimeoutTest # RUN: at line 3
+ FileCheck 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test
 --check-prefix=TimeoutTest
+ not 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest
 -timeout=1
/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test:7:14:
 error: TimeoutTest: expected string not found in input
TimeoutTest: #0
 ^
:20:44: note: scanning from here
==1619650== ERROR: libFuzzer: timeout after 1 seconds
   ^
:25:104: note: possible intended match here
AddressSanitizer: CHECK failed: asan_report.cpp:227 "((current_error_.kind)) == 
((kErrorKindInvalid))" (0x1, 0x0) (tid=1619650)

   ^

Input file: 
Check file: 
/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test

-dump-input=help explains the following input dump.

Input was:
<<
   .
   .
   .
  15: MS: 2 ShuffleBytes-InsertByte-; base unit: 
94dd9e08c129c785f7f256e82fbe0a30e6d1ae40 
  16: 0x48,0x69,0x21, 
  17: Hi! 
  18: artifact_prefix='./'; Test unit written to 
./timeout-c0a0ad26a634840c67a210fefdda76577b03a111 
  19: Base64: SGkh 
  20: ==1619650== ERROR: libFuzzer: timeout after 1 seconds 
check:7'0X~~ error: no 
match found
  21: AddressSanitizer:DEADLYSIGNAL 
check:7'0 ~~
  22: = 
check:7'0 

[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread John Harrison via lldb-commits

https://github.com/ashgti updated 
https://github.com/llvm/llvm-project/pull/145621

>From 954f107c85f766ee75370b349eb039819f456db5 Mon Sep 17 00:00:00 2001
From: John Harrison 
Date: Wed, 25 Jun 2025 18:03:39 -0700
Subject: [PATCH 1/4] [lldb] Adding file and pipe support to
 lldb_private::MainLoopWindows.

This updates MainLoopWindows to support events for reading from a file and a 
socket type.

This unifies both handle types using WaitForMultipleEvents which can listen to 
both sockets and files for change events.

This should allow us to unify how we handle watching files/pipes/sockets on 
Windows and Posix systems.
---
 lldb/include/lldb/Host/File.h |   2 +
 lldb/include/lldb/Host/Socket.h   |   2 +
 .../lldb/Host/windows/MainLoopWindows.h   |   3 +-
 lldb/include/lldb/Utility/IOObject.h  |   8 +-
 lldb/source/Host/common/File.cpp  |  18 +++
 lldb/source/Host/common/Socket.cpp|  49 +++-
 .../posix/ConnectionFileDescriptorPosix.cpp   |  14 ++-
 lldb/source/Host/windows/MainLoopWindows.cpp  | 116 +-
 lldb/source/Utility/IOObject.cpp  |   9 ++
 lldb/unittests/Host/FileTest.cpp  |  16 ++-
 lldb/unittests/Host/MainLoopTest.cpp  |  26 
 11 files changed, 190 insertions(+), 73 deletions(-)

diff --git a/lldb/include/lldb/Host/File.h b/lldb/include/lldb/Host/File.h
index 9e2d0abe0b1af3..36cb1922812898 100644
--- a/lldb/include/lldb/Host/File.h
+++ b/lldb/include/lldb/Host/File.h
@@ -127,6 +127,7 @@ class File : public IOObject {
   /// \return
   /// a valid handle or IOObject::kInvalidHandleValue
   WaitableHandle GetWaitableHandle() override;
+  bool HasReadableData() override;
 
   /// Get the file specification for this file, if possible.
   ///
@@ -400,6 +401,7 @@ class NativeFile : public File {
   Status Write(const void *buf, size_t &num_bytes) override;
   Status Close() override;
   WaitableHandle GetWaitableHandle() override;
+  bool HasReadableData() override;
   Status GetFileSpec(FileSpec &file_spec) const override;
   int GetDescriptor() const override;
   FILE *GetStream() override;
diff --git a/lldb/include/lldb/Host/Socket.h b/lldb/include/lldb/Host/Socket.h
index 89953ee7fd5b6e..6569e9e6ea8185 100644
--- a/lldb/include/lldb/Host/Socket.h
+++ b/lldb/include/lldb/Host/Socket.h
@@ -158,6 +158,7 @@ class Socket : public IOObject {
 
   bool IsValid() const override { return m_socket != kInvalidSocketValue; }
   WaitableHandle GetWaitableHandle() override;
+  bool HasReadableData() override;
 
   static llvm::Expected
   DecodeHostAndPort(llvm::StringRef host_and_port);
@@ -185,6 +186,7 @@ class Socket : public IOObject {
 
   SocketProtocol m_protocol;
   NativeSocket m_socket;
+  WaitableHandle m_waitable_handle;
   bool m_should_close_fd;
 };
 
diff --git a/lldb/include/lldb/Host/windows/MainLoopWindows.h 
b/lldb/include/lldb/Host/windows/MainLoopWindows.h
index 3937a24645d955..43b7d13a0e445d 100644
--- a/lldb/include/lldb/Host/windows/MainLoopWindows.h
+++ b/lldb/include/lldb/Host/windows/MainLoopWindows.h
@@ -37,11 +37,10 @@ class MainLoopWindows : public MainLoopBase {
   void Interrupt() override;
 
 private:
-  void ProcessReadObject(IOObject::WaitableHandle handle);
   llvm::Expected Poll();
 
   struct FdInfo {
-void *event;
+lldb::IOObjectSP object_sp;
 Callback callback;
   };
   llvm::DenseMap m_read_fds;
diff --git a/lldb/include/lldb/Utility/IOObject.h 
b/lldb/include/lldb/Utility/IOObject.h
index 8cf42992e7be5c..48a8a2076581f3 100644
--- a/lldb/include/lldb/Utility/IOObject.h
+++ b/lldb/include/lldb/Utility/IOObject.h
@@ -14,6 +14,7 @@
 #include 
 
 #include "lldb/lldb-private.h"
+#include "lldb/lldb-types.h"
 
 namespace lldb_private {
 
@@ -24,9 +25,9 @@ class IOObject {
 eFDTypeSocket, // Socket requiring send/recv
   };
 
-  // TODO: On Windows this should be a HANDLE, and wait should use
-  // WaitForMultipleObjects
-  typedef int WaitableHandle;
+  // A handle for integrating with the host event loop model.
+  using WaitableHandle = lldb::file_t;
+
   static const WaitableHandle kInvalidHandleValue;
 
   IOObject(FDType type) : m_fd_type(type) {}
@@ -40,6 +41,7 @@ class IOObject {
   FDType GetFdType() const { return m_fd_type; }
 
   virtual WaitableHandle GetWaitableHandle() = 0;
+  virtual bool HasReadableData() = 0;
 
 protected:
   FDType m_fd_type;
diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp
index 9aa95ffda44cba..2d33f9e2028c4b 100644
--- a/lldb/source/Host/common/File.cpp
+++ b/lldb/source/Host/common/File.cpp
@@ -118,6 +118,8 @@ IOObject::WaitableHandle File::GetWaitableHandle() {
   return IOObject::kInvalidHandleValue;
 }
 
+bool File::HasReadableData() { return false; }
+
 Status File::GetFileSpec(FileSpec &file_spec) const {
   file_spec.Clear();
   return std::error_code(ENOTSUP, std::system_category());
@@ -274,7 +276,23 @@ int NativeFile::GetDescriptor() const {
 }
 
 IOObject::Waitab

[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread John Harrison via lldb-commits


@@ -493,7 +496,12 @@ ConnectionFileDescriptor::BytesAvailable(const 
Timeout &timeout,
   break; // Lets keep reading to until we timeout
 }
   } else {
+#if defined(_WIN32)
+if (const auto *sock = static_cast(m_io_sp.get());

ashgti wrote:

Removed this change.

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread John Harrison via lldb-commits


@@ -31,8 +31,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
+#include 

ashgti wrote:

Removed.

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread John Harrison via lldb-commits


@@ -31,20 +31,27 @@ class MainLoopWindows : public MainLoopBase {
 
   Status Run() override;
 
+  struct FdInfo {
+FdInfo(intptr_t event, Callback callback)
+: event(event), callback(callback) {}
+virtual ~FdInfo() {}
+virtual void WillPoll() {}
+virtual void DidPoll() {}
+virtual void Disarm() {}
+intptr_t event;

ashgti wrote:

Changed to `IOObject::WaitableHandle`. 

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [compiler-rt] [lldb] [llvm] Reapply "[NFC][DebugInfo][DWARF] Create new low-level dwarf library (#… (#145959) (PR #146112)

2025-06-27 Thread David Blaikie via lldb-commits

https://github.com/dwblaikie approved this pull request.


https://github.com/llvm/llvm-project/pull/146112
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Adding file and pipe support to lldb_private::MainLoopWindows. (PR #145621)

2025-06-27 Thread John Harrison via lldb-commits


@@ -31,20 +31,27 @@ class MainLoopWindows : public MainLoopBase {
 
   Status Run() override;
 
+  struct FdInfo {
+FdInfo(intptr_t event, Callback callback)
+: event(event), callback(callback) {}
+virtual ~FdInfo() {}
+virtual void WillPoll() {}
+virtual void DidPoll() {}
+virtual void Disarm() {}
+intptr_t event;
+Callback callback;

ashgti wrote:

I reverted this so we have the previous `struct FdInfo` and made the event into 
its own `IOEvent` type instead. I also made this a class and used accessors 
instead of making ivars public.

https://github.com/llvm/llvm-project/pull/145621
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [compiler-rt] [lldb] [llvm] Reapply "[NFC][DebugInfo][DWARF] Create new low-level dwarf library (#… (#145959) (PR #146112)

2025-06-27 Thread via lldb-commits

https://github.com/Sterling-Augustine closed 
https://github.com/llvm/llvm-project/pull/146112
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Fix evaluating expressions without JIT in an object context (PR #145599)

2025-06-27 Thread via lldb-commits

https://github.com/jimingham approved this pull request.

This one is ready then.

https://github.com/llvm/llvm-project/pull/145599
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Correctly restore the cursor column after resizing the statusline (PR #146132)

2025-06-27 Thread Jonas Devlieghere via lldb-commits

https://github.com/JDevlieghere created 
https://github.com/llvm/llvm-project/pull/146132

This PR ensures we correctly restore the cursor column after resizing the 
statusline. To ensure we have space for the statusline, we have to emit a 
newline to move up everything on screen. The newline causes the cursor to move 
to the start of the next line, which needs to be undone.

Normally, we would use escape codes to save & restore the cursor position, but 
that doesn't work here, as the cursor position may have (purposely) changed. 
Instead, we move the cursor up one line using an escape code, but we weren't 
restoring the column.

Interestingly, Editline was able to recover from this issue through the 
LineInfo struct which contains the buffer and the cursor location, which allows 
us to compute the column. This PR addresses the bug by having Editline 
"refresh" the cursor position.

Fixes #134064

>From e601025c14fb609635dc6a9adea5b1ae8b8e4540 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere 
Date: Fri, 27 Jun 2025 11:08:08 -0700
Subject: [PATCH] [lldb] Correctly restore the cursor column after resizing the
 statusline

This PR ensures we correctly restore the cursor column after resizing
the statusline. To ensure we have space for the statusline, we have to
emit a newline to move up everything on screen. The newline causes the
cursor to move to the start of the next line, which needs to be undone.

Normally, we would use escape codes to save & restore the cursor
position, but that doesn't work here, as the cursor position may have
(purposely) changed. Instead, we move the cursor up one line using an
escape code, but we weren't restoring the column.

Interestingly, Editline was able to recover from this issue through the
LineInfo struct which contains the buffer and the cursor location, which
allows us to compute the column. This PR addresses the bug by having
Editline "refresh" the cursor position.

Fixes #134064
---
 lldb/include/lldb/Core/Debugger.h|  2 ++
 lldb/include/lldb/Core/IOHandler.h   |  4 
 lldb/include/lldb/Host/Editline.h|  2 ++
 lldb/source/Core/Debugger.cpp|  7 +++
 lldb/source/Core/IOHandler.cpp   |  7 +++
 lldb/source/Core/Statusline.cpp  | 19 +++
 lldb/source/Host/common/Editline.cpp |  7 +++
 7 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/lldb/include/lldb/Core/Debugger.h 
b/lldb/include/lldb/Core/Debugger.h
index 2087ef2a11562..504f936fe317a 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -227,6 +227,8 @@ class Debugger : public 
std::enable_shared_from_this,
 
   const char *GetIOHandlerHelpPrologue();
 
+  void RefreshIOHandler();
+
   void ClearIOHandlers();
 
   bool EnableLog(llvm::StringRef channel,
diff --git a/lldb/include/lldb/Core/IOHandler.h 
b/lldb/include/lldb/Core/IOHandler.h
index 2fb3d7a7c9cc3..2672bbe5da2b3 100644
--- a/lldb/include/lldb/Core/IOHandler.h
+++ b/lldb/include/lldb/Core/IOHandler.h
@@ -90,6 +90,8 @@ class IOHandler {
 
   virtual void TerminalSizeChanged() {}
 
+  virtual void Refresh() {}
+
   virtual const char *GetPrompt() {
 // Prompt support isn't mandatory
 return nullptr;
@@ -404,6 +406,8 @@ class IOHandlerEditline : public IOHandler {
 
   void PrintAsync(const char *s, size_t len, bool is_stdout) override;
 
+  void Refresh() override;
+
 private:
 #if LLDB_ENABLE_LIBEDIT
   bool IsInputCompleteCallback(Editline *editline, StringList &lines);
diff --git a/lldb/include/lldb/Host/Editline.h 
b/lldb/include/lldb/Host/Editline.h
index c202a76758e13..947ad3bfe5ec6 100644
--- a/lldb/include/lldb/Host/Editline.h
+++ b/lldb/include/lldb/Host/Editline.h
@@ -267,6 +267,8 @@ class Editline {
 
   size_t GetTerminalHeight() { return m_terminal_height; }
 
+  void Refresh();
+
 private:
   /// Sets the lowest line number for multi-line editing sessions.  A value of
   /// zero suppresses line number printing in the prompt.
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 445baf1f63785..ed674ee1275c7 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -1445,6 +1445,13 @@ bool Debugger::PopIOHandler(const IOHandlerSP 
&pop_reader_sp) {
   return true;
 }
 
+void Debugger::RefreshIOHandler() {
+  std::lock_guard guard(m_io_handler_stack.GetMutex());
+  IOHandlerSP reader_sp(m_io_handler_stack.Top());
+  if (reader_sp)
+reader_sp->Refresh();
+}
+
 StreamUP Debugger::GetAsyncOutputStream() {
   return std::make_unique(*this,
 StreamAsynchronousIO::STDOUT);
diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp
index 8aac507eaa0c2..f65a1113f3592 100644
--- a/lldb/source/Core/IOHandler.cpp
+++ b/lldb/source/Core/IOHandler.cpp
@@ -663,3 +663,10 @@ void IOHandlerEditline::PrintAsync(const char *s, size_t 
len, bool is_stdout) {
 #endif
   }
 }
+
+void IOHandlerEditline::Refresh() {
+#if LLDB_ENABLE_LIBEDIT
+  if 

[Lldb-commits] [lldb] [lldb] Correctly restore the cursor column after resizing the statusline (PR #146132)

2025-06-27 Thread via lldb-commits

llvmbot wrote:




@llvm/pr-subscribers-lldb

Author: Jonas Devlieghere (JDevlieghere)


Changes

This PR ensures we correctly restore the cursor column after resizing the 
statusline. To ensure we have space for the statusline, we have to emit a 
newline to move up everything on screen. The newline causes the cursor to move 
to the start of the next line, which needs to be undone.

Normally, we would use escape codes to save & restore the cursor position, 
but that doesn't work here, as the cursor position may have (purposely) 
changed. Instead, we move the cursor up one line using an escape code, but we 
weren't restoring the column.

Interestingly, Editline was able to recover from this issue through the 
LineInfo struct which contains the buffer and the cursor location, which allows 
us to compute the column. This PR addresses the bug by having Editline 
"refresh" the cursor position.

Fixes #134064

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


7 Files Affected:

- (modified) lldb/include/lldb/Core/Debugger.h (+2) 
- (modified) lldb/include/lldb/Core/IOHandler.h (+4) 
- (modified) lldb/include/lldb/Host/Editline.h (+2) 
- (modified) lldb/source/Core/Debugger.cpp (+7) 
- (modified) lldb/source/Core/IOHandler.cpp (+7) 
- (modified) lldb/source/Core/Statusline.cpp (+11-8) 
- (modified) lldb/source/Host/common/Editline.cpp (+7) 


``diff
diff --git a/lldb/include/lldb/Core/Debugger.h 
b/lldb/include/lldb/Core/Debugger.h
index 2087ef2a11562..504f936fe317a 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -227,6 +227,8 @@ class Debugger : public 
std::enable_shared_from_this,
 
   const char *GetIOHandlerHelpPrologue();
 
+  void RefreshIOHandler();
+
   void ClearIOHandlers();
 
   bool EnableLog(llvm::StringRef channel,
diff --git a/lldb/include/lldb/Core/IOHandler.h 
b/lldb/include/lldb/Core/IOHandler.h
index 2fb3d7a7c9cc3..2672bbe5da2b3 100644
--- a/lldb/include/lldb/Core/IOHandler.h
+++ b/lldb/include/lldb/Core/IOHandler.h
@@ -90,6 +90,8 @@ class IOHandler {
 
   virtual void TerminalSizeChanged() {}
 
+  virtual void Refresh() {}
+
   virtual const char *GetPrompt() {
 // Prompt support isn't mandatory
 return nullptr;
@@ -404,6 +406,8 @@ class IOHandlerEditline : public IOHandler {
 
   void PrintAsync(const char *s, size_t len, bool is_stdout) override;
 
+  void Refresh() override;
+
 private:
 #if LLDB_ENABLE_LIBEDIT
   bool IsInputCompleteCallback(Editline *editline, StringList &lines);
diff --git a/lldb/include/lldb/Host/Editline.h 
b/lldb/include/lldb/Host/Editline.h
index c202a76758e13..947ad3bfe5ec6 100644
--- a/lldb/include/lldb/Host/Editline.h
+++ b/lldb/include/lldb/Host/Editline.h
@@ -267,6 +267,8 @@ class Editline {
 
   size_t GetTerminalHeight() { return m_terminal_height; }
 
+  void Refresh();
+
 private:
   /// Sets the lowest line number for multi-line editing sessions.  A value of
   /// zero suppresses line number printing in the prompt.
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 445baf1f63785..ed674ee1275c7 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -1445,6 +1445,13 @@ bool Debugger::PopIOHandler(const IOHandlerSP 
&pop_reader_sp) {
   return true;
 }
 
+void Debugger::RefreshIOHandler() {
+  std::lock_guard guard(m_io_handler_stack.GetMutex());
+  IOHandlerSP reader_sp(m_io_handler_stack.Top());
+  if (reader_sp)
+reader_sp->Refresh();
+}
+
 StreamUP Debugger::GetAsyncOutputStream() {
   return std::make_unique(*this,
 StreamAsynchronousIO::STDOUT);
diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp
index 8aac507eaa0c2..f65a1113f3592 100644
--- a/lldb/source/Core/IOHandler.cpp
+++ b/lldb/source/Core/IOHandler.cpp
@@ -663,3 +663,10 @@ void IOHandlerEditline::PrintAsync(const char *s, size_t 
len, bool is_stdout) {
 #endif
   }
 }
+
+void IOHandlerEditline::Refresh() {
+#if LLDB_ENABLE_LIBEDIT
+  if (m_editline_up)
+m_editline_up->Refresh();
+#endif
+}
diff --git a/lldb/source/Core/Statusline.cpp b/lldb/source/Core/Statusline.cpp
index 8a8640805cac0..8ec57c9fa5bac 100644
--- a/lldb/source/Core/Statusline.cpp
+++ b/lldb/source/Core/Statusline.cpp
@@ -103,20 +103,23 @@ void Statusline::UpdateScrollWindow(ScrollWindowMode 
mode) {
   (mode == DisableStatusline) ? m_terminal_height : m_terminal_height - 1;
 
   LockedStreamFile locked_stream = stream_sp->Lock();
+
+  if (mode == EnableStatusline) {
+// Move everything on the screen up.
+locked_stream << '\n';
+locked_stream.Printf(ANSI_UP_ROWS, 1);
+  }
+
   locked_stream << ANSI_SAVE_CURSOR;
   locked_stream.Printf(ANSI_SET_SCROLL_ROWS, scroll_height);
   locked_stream << ANSI_RESTORE_CURSOR;
-  switch (mode) {
-  case EnableStatusline:
-// Move everything on the screen up.
-locked_stream.Printf(ANSI_UP_ROWS, 1);
-locked_stream << '\n';
-break;
-  case DisableStatu

[Lldb-commits] [lldb] [lldb] Correctly restore the cursor column after resizing the statusline (PR #145823)

2025-06-27 Thread Jonas Devlieghere via lldb-commits

JDevlieghere wrote:

Alternative approach: https://github.com/llvm/llvm-project/pull/146132

https://github.com/llvm/llvm-project/pull/145823
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jonas Devlieghere via lldb-commits


@@ -5857,6 +5838,50 @@ bool ObjectFileMachO::GetCorefileThreadExtraInfos(
   return false;
 }
 
+StructuredData::ObjectSP ObjectFileMachO::GetCorefileProcessMetadata() {
+  ModuleSP module_sp(GetModule());
+  if (!module_sp)
+return {};
+
+  Log *log(GetLog(LLDBLog::Object | LLDBLog::Process | LLDBLog::Thread));
+  std::lock_guard guard(module_sp->GetMutex());
+  auto lc_notes = FindLC_NOTEByName("process metadata");
+  if (lc_notes.size() == 0)
+return {};
+
+  if (lc_notes.size() > 1)
+LLDB_LOGF(
+log,
+"Multiple 'process metadata' LC_NOTEs found, only using the first.");
+
+  offset_t payload_offset = std::get<0>(lc_notes[0]);
+  offset_t strsize = std::get<1>(lc_notes[0]);

JDevlieghere wrote:

FWIW, with structured bindings in C++17 you can now write this like:
```suggestion
  auto [payload_offset, strsize] = lc_notes[0];
```

https://github.com/llvm/llvm-project/pull/144627
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jonas Devlieghere via lldb-commits


@@ -0,0 +1,300 @@
+//===-- RegisterContextUnifiedCore.cpp 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "RegisterContextUnifiedCore.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/StructuredData.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextUnifiedCore::RegisterContextUnifiedCore(
+Thread &thread, uint32_t concrete_frame_idx,
+RegisterContextSP core_thread_regctx_sp,
+StructuredData::ObjectSP metadata_thread_registers)
+: RegisterContext(thread, concrete_frame_idx) {
+
+  ProcessSP process_sp(thread.GetProcess());
+  Target &target = process_sp->GetTarget();
+  StructuredData::Dictionary *metadata_registers_dict = nullptr;
+
+  // If we have thread metadata, check if the keys for register
+  // definitions are present; if not, clear the ObjectSP.
+  if (metadata_thread_registers &&
+  metadata_thread_registers->GetAsDictionary() &&
+  metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {
+metadata_registers_dict = metadata_thread_registers->GetAsDictionary()
+  ->GetValueForKey("register_info")
+  ->GetAsDictionary();
+if (metadata_registers_dict)
+  if (!metadata_registers_dict->HasKey("sets") ||
+  !metadata_registers_dict->HasKey("registers"))
+metadata_registers_dict = nullptr;
+  }
+
+  // When creating a register set list from the two sources,
+  // the LC_THREAD aka core_thread_regctx_sp register sets
+  // will be used at the same indexes.
+  // Any additional sets named by the thread metadata registers
+  // will be added after them.  If the thread metadata
+  // specify a set with the same name as LC_THREAD, the already-used
+  // index from the core register context will be used in
+  // the RegisterInfo.
+  std::map metadata_regset_to_combined_regset;
+
+  // Calculate the total size of the register store buffer we need
+  // for all registers.  The corefile register definitions may include
+  // RegisterInfo descriptions of registers that aren't actually
+  // available.  For simplicity, calculate the size of all registers
+  // as if they are available, so we can maintain the same offsets into
+  // the buffer.
+  uint32_t core_buffer_end = 0;
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+core_buffer_end =
+std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);
+  }
+
+  // Add metadata register sizes to the total buffer size.
+  uint32_t combined_buffer_end = core_buffer_end;
+  if (metadata_registers_dict) {
+StructuredData::Array *registers = nullptr;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach(
+  [&combined_buffer_end](StructuredData::Object *ent) -> bool {
+uint32_t bitsize;
+if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
+ bitsize))
+  return false;
+combined_buffer_end += (bitsize / 8);
+return true;
+  });
+  }
+  m_register_data.resize(combined_buffer_end, 0);
+
+  // Copy the core register values into our combined data buffer,
+  // skip registers that are contained within another (e.g. w0 vs. x0)
+  // and registers that return as "unavailable".
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+RegisterValue val;
+if (!reginfo->value_regs &&
+core_thread_regctx_sp->ReadRegister(reginfo, val))
+  memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),
+ val.GetByteSize());
+  }
+
+  // Set 'offset' fields for each register definition into our combined
+  // register data buffer. DynamicRegisterInfo needs
+  // this field set to parse the JSON.
+  // Also copy the values of the registers into our register data buffer.
+  if (metadata_registers_dict) {
+size_t offset = core_buffer_end;
+ByteOrder byte_order = core_thread_regctx_sp->GetByteOrder();
+StructuredData::Array *registers;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach([this, &offset,
+  byte_order](StructuredData::Object *ent) -> bool {
+uint64_t bitsize;

[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jonas Devlieghere via lldb-commits


@@ -5857,6 +5838,50 @@ bool ObjectFileMachO::GetCorefileThreadExtraInfos(
   return false;
 }
 
+StructuredData::ObjectSP ObjectFileMachO::GetCorefileProcessMetadata() {
+  ModuleSP module_sp(GetModule());
+  if (!module_sp)
+return {};
+
+  Log *log(GetLog(LLDBLog::Object | LLDBLog::Process | LLDBLog::Thread));
+  std::lock_guard guard(module_sp->GetMutex());
+  auto lc_notes = FindLC_NOTEByName("process metadata");
+  if (lc_notes.size() == 0)
+return {};
+
+  if (lc_notes.size() > 1)
+LLDB_LOGF(
+log,
+"Multiple 'process metadata' LC_NOTEs found, only using the first.");
+
+  offset_t payload_offset = std::get<0>(lc_notes[0]);
+  offset_t strsize = std::get<1>(lc_notes[0]);
+  std::string buf(strsize, '\0');
+  if (m_data.CopyData(payload_offset, strsize, buf.data()) != strsize) {
+LLDB_LOGF(log,
+  "Unable to read %" PRIu64
+  " bytes of 'process metadata' LC_NOTE JSON contents",
+  strsize);
+return {};
+  }
+  while (buf.back() == '\0')
+buf.resize(buf.size() - 1);
+  StructuredData::ObjectSP object_sp = StructuredData::ParseJSON(buf);
+  if (!object_sp) {
+LLDB_LOGF(log, "Unable to read 'process metadata' LC_NOTE, did not "
+   "parse as valid JSON.");

JDevlieghere wrote:

No need to change anything, but another way to handle this is to make this 
function return an `Expected` and do the logging on 
the caller side. The advantage of that is that if you can do better than 
logging, it's easy to percolate the error up, while now it never leaves the 
function. 

https://github.com/llvm/llvm-project/pull/144627
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jonas Devlieghere via lldb-commits


@@ -0,0 +1,300 @@
+//===-- RegisterContextUnifiedCore.cpp 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "RegisterContextUnifiedCore.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/StructuredData.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextUnifiedCore::RegisterContextUnifiedCore(
+Thread &thread, uint32_t concrete_frame_idx,
+RegisterContextSP core_thread_regctx_sp,
+StructuredData::ObjectSP metadata_thread_registers)
+: RegisterContext(thread, concrete_frame_idx) {
+
+  ProcessSP process_sp(thread.GetProcess());
+  Target &target = process_sp->GetTarget();
+  StructuredData::Dictionary *metadata_registers_dict = nullptr;
+
+  // If we have thread metadata, check if the keys for register
+  // definitions are present; if not, clear the ObjectSP.
+  if (metadata_thread_registers &&
+  metadata_thread_registers->GetAsDictionary() &&
+  metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {
+metadata_registers_dict = metadata_thread_registers->GetAsDictionary()
+  ->GetValueForKey("register_info")
+  ->GetAsDictionary();
+if (metadata_registers_dict)
+  if (!metadata_registers_dict->HasKey("sets") ||
+  !metadata_registers_dict->HasKey("registers"))
+metadata_registers_dict = nullptr;
+  }
+
+  // When creating a register set list from the two sources,
+  // the LC_THREAD aka core_thread_regctx_sp register sets
+  // will be used at the same indexes.
+  // Any additional sets named by the thread metadata registers
+  // will be added after them.  If the thread metadata
+  // specify a set with the same name as LC_THREAD, the already-used
+  // index from the core register context will be used in
+  // the RegisterInfo.
+  std::map metadata_regset_to_combined_regset;
+
+  // Calculate the total size of the register store buffer we need
+  // for all registers.  The corefile register definitions may include
+  // RegisterInfo descriptions of registers that aren't actually
+  // available.  For simplicity, calculate the size of all registers
+  // as if they are available, so we can maintain the same offsets into
+  // the buffer.
+  uint32_t core_buffer_end = 0;
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+core_buffer_end =
+std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);
+  }
+
+  // Add metadata register sizes to the total buffer size.
+  uint32_t combined_buffer_end = core_buffer_end;
+  if (metadata_registers_dict) {
+StructuredData::Array *registers = nullptr;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach(
+  [&combined_buffer_end](StructuredData::Object *ent) -> bool {
+uint32_t bitsize;
+if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
+ bitsize))
+  return false;
+combined_buffer_end += (bitsize / 8);
+return true;
+  });
+  }
+  m_register_data.resize(combined_buffer_end, 0);
+
+  // Copy the core register values into our combined data buffer,
+  // skip registers that are contained within another (e.g. w0 vs. x0)
+  // and registers that return as "unavailable".
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+RegisterValue val;
+if (!reginfo->value_regs &&
+core_thread_regctx_sp->ReadRegister(reginfo, val))
+  memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),
+ val.GetByteSize());
+  }
+
+  // Set 'offset' fields for each register definition into our combined
+  // register data buffer. DynamicRegisterInfo needs
+  // this field set to parse the JSON.
+  // Also copy the values of the registers into our register data buffer.
+  if (metadata_registers_dict) {
+size_t offset = core_buffer_end;
+ByteOrder byte_order = core_thread_regctx_sp->GetByteOrder();
+StructuredData::Array *registers;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach([this, &offset,
+  byte_order](StructuredData::Object *ent) -> bool {
+uint64_t bitsize;

[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jonas Devlieghere via lldb-commits


@@ -0,0 +1,300 @@
+//===-- RegisterContextUnifiedCore.cpp 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "RegisterContextUnifiedCore.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/StructuredData.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextUnifiedCore::RegisterContextUnifiedCore(
+Thread &thread, uint32_t concrete_frame_idx,
+RegisterContextSP core_thread_regctx_sp,
+StructuredData::ObjectSP metadata_thread_registers)
+: RegisterContext(thread, concrete_frame_idx) {
+
+  ProcessSP process_sp(thread.GetProcess());
+  Target &target = process_sp->GetTarget();
+  StructuredData::Dictionary *metadata_registers_dict = nullptr;
+
+  // If we have thread metadata, check if the keys for register
+  // definitions are present; if not, clear the ObjectSP.
+  if (metadata_thread_registers &&
+  metadata_thread_registers->GetAsDictionary() &&
+  metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {
+metadata_registers_dict = metadata_thread_registers->GetAsDictionary()
+  ->GetValueForKey("register_info")
+  ->GetAsDictionary();
+if (metadata_registers_dict)
+  if (!metadata_registers_dict->HasKey("sets") ||
+  !metadata_registers_dict->HasKey("registers"))
+metadata_registers_dict = nullptr;
+  }
+
+  // When creating a register set list from the two sources,
+  // the LC_THREAD aka core_thread_regctx_sp register sets
+  // will be used at the same indexes.
+  // Any additional sets named by the thread metadata registers
+  // will be added after them.  If the thread metadata
+  // specify a set with the same name as LC_THREAD, the already-used
+  // index from the core register context will be used in
+  // the RegisterInfo.
+  std::map metadata_regset_to_combined_regset;
+
+  // Calculate the total size of the register store buffer we need
+  // for all registers.  The corefile register definitions may include
+  // RegisterInfo descriptions of registers that aren't actually
+  // available.  For simplicity, calculate the size of all registers
+  // as if they are available, so we can maintain the same offsets into
+  // the buffer.
+  uint32_t core_buffer_end = 0;
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+core_buffer_end =
+std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);
+  }
+
+  // Add metadata register sizes to the total buffer size.
+  uint32_t combined_buffer_end = core_buffer_end;
+  if (metadata_registers_dict) {
+StructuredData::Array *registers = nullptr;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach(
+  [&combined_buffer_end](StructuredData::Object *ent) -> bool {
+uint32_t bitsize;
+if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
+ bitsize))
+  return false;
+combined_buffer_end += (bitsize / 8);
+return true;
+  });
+  }
+  m_register_data.resize(combined_buffer_end, 0);
+
+  // Copy the core register values into our combined data buffer,
+  // skip registers that are contained within another (e.g. w0 vs. x0)
+  // and registers that return as "unavailable".
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+RegisterValue val;
+if (!reginfo->value_regs &&
+core_thread_regctx_sp->ReadRegister(reginfo, val))
+  memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),
+ val.GetByteSize());
+  }
+
+  // Set 'offset' fields for each register definition into our combined
+  // register data buffer. DynamicRegisterInfo needs
+  // this field set to parse the JSON.

JDevlieghere wrote:

Nit: looks like this needs to be reflowed.

https://github.com/llvm/llvm-project/pull/144627
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jonas Devlieghere via lldb-commits

https://github.com/JDevlieghere edited 
https://github.com/llvm/llvm-project/pull/144627
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jonas Devlieghere via lldb-commits


@@ -0,0 +1,300 @@
+//===-- RegisterContextUnifiedCore.cpp 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "RegisterContextUnifiedCore.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/StructuredData.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextUnifiedCore::RegisterContextUnifiedCore(
+Thread &thread, uint32_t concrete_frame_idx,
+RegisterContextSP core_thread_regctx_sp,
+StructuredData::ObjectSP metadata_thread_registers)
+: RegisterContext(thread, concrete_frame_idx) {
+
+  ProcessSP process_sp(thread.GetProcess());
+  Target &target = process_sp->GetTarget();
+  StructuredData::Dictionary *metadata_registers_dict = nullptr;
+
+  // If we have thread metadata, check if the keys for register
+  // definitions are present; if not, clear the ObjectSP.
+  if (metadata_thread_registers &&
+  metadata_thread_registers->GetAsDictionary() &&
+  metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {
+metadata_registers_dict = metadata_thread_registers->GetAsDictionary()
+  ->GetValueForKey("register_info")
+  ->GetAsDictionary();
+if (metadata_registers_dict)
+  if (!metadata_registers_dict->HasKey("sets") ||
+  !metadata_registers_dict->HasKey("registers"))
+metadata_registers_dict = nullptr;
+  }
+
+  // When creating a register set list from the two sources,
+  // the LC_THREAD aka core_thread_regctx_sp register sets
+  // will be used at the same indexes.
+  // Any additional sets named by the thread metadata registers
+  // will be added after them.  If the thread metadata
+  // specify a set with the same name as LC_THREAD, the already-used
+  // index from the core register context will be used in
+  // the RegisterInfo.
+  std::map metadata_regset_to_combined_regset;
+
+  // Calculate the total size of the register store buffer we need
+  // for all registers.  The corefile register definitions may include
+  // RegisterInfo descriptions of registers that aren't actually
+  // available.  For simplicity, calculate the size of all registers
+  // as if they are available, so we can maintain the same offsets into
+  // the buffer.
+  uint32_t core_buffer_end = 0;
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+core_buffer_end =
+std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);
+  }
+
+  // Add metadata register sizes to the total buffer size.
+  uint32_t combined_buffer_end = core_buffer_end;
+  if (metadata_registers_dict) {
+StructuredData::Array *registers = nullptr;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach(
+  [&combined_buffer_end](StructuredData::Object *ent) -> bool {
+uint32_t bitsize;
+if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
+ bitsize))
+  return false;
+combined_buffer_end += (bitsize / 8);
+return true;
+  });
+  }
+  m_register_data.resize(combined_buffer_end, 0);
+
+  // Copy the core register values into our combined data buffer,
+  // skip registers that are contained within another (e.g. w0 vs. x0)
+  // and registers that return as "unavailable".
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+RegisterValue val;
+if (!reginfo->value_regs &&
+core_thread_regctx_sp->ReadRegister(reginfo, val))
+  memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),
+ val.GetByteSize());
+  }
+
+  // Set 'offset' fields for each register definition into our combined
+  // register data buffer. DynamicRegisterInfo needs
+  // this field set to parse the JSON.
+  // Also copy the values of the registers into our register data buffer.
+  if (metadata_registers_dict) {
+size_t offset = core_buffer_end;
+ByteOrder byte_order = core_thread_regctx_sp->GetByteOrder();
+StructuredData::Array *registers;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach([this, &offset,
+  byte_order](StructuredData::Object *ent) -> bool {
+uint64_t bitsize;

[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jonas Devlieghere via lldb-commits


@@ -133,6 +133,8 @@ class ObjectFileMachO : public lldb_private::ObjectFile {
 
   bool GetCorefileThreadExtraInfos(std::vector &tids) override;
 
+  lldb_private::StructuredData::ObjectSP GetCorefileProcessMetadata() override;

JDevlieghere wrote:

```suggestion
 StructuredData::ObjectSP GetCorefileProcessMetadata() override;
```

https://github.com/llvm/llvm-project/pull/144627
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb][Mach-O] Allow "process metadata" LC_NOTE to supply registers (PR #144627)

2025-06-27 Thread Jonas Devlieghere via lldb-commits


@@ -0,0 +1,300 @@
+//===-- RegisterContextUnifiedCore.cpp 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "RegisterContextUnifiedCore.h"
+#include "lldb/Target/DynamicRegisterInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/StructuredData.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextUnifiedCore::RegisterContextUnifiedCore(
+Thread &thread, uint32_t concrete_frame_idx,
+RegisterContextSP core_thread_regctx_sp,
+StructuredData::ObjectSP metadata_thread_registers)
+: RegisterContext(thread, concrete_frame_idx) {
+
+  ProcessSP process_sp(thread.GetProcess());
+  Target &target = process_sp->GetTarget();
+  StructuredData::Dictionary *metadata_registers_dict = nullptr;
+
+  // If we have thread metadata, check if the keys for register
+  // definitions are present; if not, clear the ObjectSP.
+  if (metadata_thread_registers &&
+  metadata_thread_registers->GetAsDictionary() &&
+  metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {
+metadata_registers_dict = metadata_thread_registers->GetAsDictionary()
+  ->GetValueForKey("register_info")
+  ->GetAsDictionary();
+if (metadata_registers_dict)
+  if (!metadata_registers_dict->HasKey("sets") ||
+  !metadata_registers_dict->HasKey("registers"))
+metadata_registers_dict = nullptr;
+  }
+
+  // When creating a register set list from the two sources,
+  // the LC_THREAD aka core_thread_regctx_sp register sets
+  // will be used at the same indexes.
+  // Any additional sets named by the thread metadata registers
+  // will be added after them.  If the thread metadata
+  // specify a set with the same name as LC_THREAD, the already-used
+  // index from the core register context will be used in
+  // the RegisterInfo.
+  std::map metadata_regset_to_combined_regset;
+
+  // Calculate the total size of the register store buffer we need
+  // for all registers.  The corefile register definitions may include
+  // RegisterInfo descriptions of registers that aren't actually
+  // available.  For simplicity, calculate the size of all registers
+  // as if they are available, so we can maintain the same offsets into
+  // the buffer.
+  uint32_t core_buffer_end = 0;
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+core_buffer_end =
+std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);
+  }
+
+  // Add metadata register sizes to the total buffer size.
+  uint32_t combined_buffer_end = core_buffer_end;
+  if (metadata_registers_dict) {
+StructuredData::Array *registers = nullptr;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach(
+  [&combined_buffer_end](StructuredData::Object *ent) -> bool {
+uint32_t bitsize;
+if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",
+ bitsize))
+  return false;
+combined_buffer_end += (bitsize / 8);
+return true;
+  });
+  }
+  m_register_data.resize(combined_buffer_end, 0);
+
+  // Copy the core register values into our combined data buffer,
+  // skip registers that are contained within another (e.g. w0 vs. x0)
+  // and registers that return as "unavailable".
+  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) 
{
+const RegisterInfo *reginfo =
+core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);
+RegisterValue val;
+if (!reginfo->value_regs &&
+core_thread_regctx_sp->ReadRegister(reginfo, val))
+  memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),
+ val.GetByteSize());
+  }
+
+  // Set 'offset' fields for each register definition into our combined
+  // register data buffer. DynamicRegisterInfo needs
+  // this field set to parse the JSON.
+  // Also copy the values of the registers into our register data buffer.
+  if (metadata_registers_dict) {
+size_t offset = core_buffer_end;
+ByteOrder byte_order = core_thread_regctx_sp->GetByteOrder();
+StructuredData::Array *registers;
+if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))
+  registers->ForEach([this, &offset,
+  byte_order](StructuredData::Object *ent) -> bool {
+uint64_t bitsize;

  1   2   >