This pr fixes#167388 .
## Description
This pr adds new method `GetArchName` to `SBTarget` so that no need to
parse triple to get arch name in client code.
## Testing
### All from `TestTargetAPI.py`
run test with
```
./build/bin/lldb-dotest -v -p TestTargetAPI.py
```
<details>
<summary>existing tests (without newly added)</summary>
<img width="1425" height="804" alt="image"
src="https://github.com/user-attachments/assets/617e4c69-5c6b-44c4-9aeb-b751a47e253c"
/>
</details>
<details>
<summary>existing tests (with newly added)</summary>
<img width="1422" height="778" alt="image"
src="https://github.com/user-attachments/assets/746990a1-df88-4348-a090-224963d3c640"
/>
</details>
### Only `test_get_arch_name`
run test with
```
./build/bin/lldb-dotest -v -p TestTargetAPI.py -f test_get_arch_name_dwarf -f test_get_arch_name_dwo -f test_get_arch_name_dsym lldb/test/API/python_api/target
```
<details>
<summary>only newly added</summary>
<img width="1422" height="778" alt="image"
src="https://github.com/user-attachments/assets/fcaafa5d-2622-4171-acee-e104ecee0652"
/>
</details>
---------
Signed-off-by: Nikita B <n2h9z4@gmail.com>
Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
I've been working on some scripts that evaluate the parent and child
frame. It's been very annoying that the parent frame has a property but
not the child. So I've added this to the extensions, I would've
preferred to return None, but because the existing impl returns an
invalid SBFrame, so I'm conforming to that API.
```
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> lldb.frame
frame #0: 0x0000555555555200 fib.out`main
>>> lldb.frame.parent
frame #1: 0x00007ffff782a610 libc.so.6`__libc_start_call_main + 128
>>> lldb.frame.parent.child
frame #0: 0x0000555555555200 fib.out`main
```
We missed a handful of uses of the Python private API in the SWIG
typemaps because they are included before we include the Python header
that defines Py_LIMITED_API.
This fixes that and guards the last private use on whether or not you're
targeting the limited API. Unfortunately there doesn't appear to be an
alternative, so we have to resort to being slightly less defensive.
This is an alternative solution to the issue described in #167990, which
can be summarized as that we cannot target Python 3.8 with the stable
API and support building for Python 3.13 and later due to the buffer
protocol.
The approach taken in this PR, and proposed by Ismail, is to sidesteps
the issue by dropping support for the buffer protocol. The only two
users are SBFile::Read and SBFile::Write. Instead, we support PyBytes
and PyByteArray which are the builtin types that conform to the buffer
protocol. Technically, this means a small regression, where those
methods could previously take custom types that conform to Python's
buffer protocol. Like Ismail, I think this is acceptable given the
alternatives.
Co-authored-by: Med Ismail Bennani <ismail@bennani.ma>
This patch extends ScriptedFrame to work with real (non-scripted)
threads,
enabling frame providers to synthesize frames for native processes.
Previously, ScriptedFrame only worked within
ScriptedProcess/ScriptedThread
contexts. This patch decouples ScriptedFrame from ScriptedThread,
allowing
users to augment or replace stack frames in real debugging sessions for
use
cases like custom calling conventions, reconstructing corrupted frames
from
core files, or adding diagnostic frames.
Key changes:
- ScriptedFrame::Create() now accepts ThreadSP instead of requiring
ScriptedThread, extracting architecture from the target triple rather
than ScriptedProcess.arch
- Added SBTarget::RegisterScriptedFrameProvider() and
ClearScriptedFrameProvider() APIs, with Target storing a
SyntheticFrameProviderDescriptor template for new threads
- Added "target frame-provider register/clear" commands for CLI access
- Thread class gains LoadScriptedFrameProvider(),
ClearScriptedFrameProvider(),
and GetFrameProvider() methods for per-thread frame provider management
- New SyntheticStackFrameList overrides FetchFramesUpTo() to lazily
provide
frames from either the frame provider or the real stack
This enables practical use of the SyntheticFrameProvider infrastructure
in
real debugging workflows.
rdar://161834688
Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
This patch implements the base and python interface for the
ScriptedFrameProvider class.
This is necessary to call python APIs from the ScriptedFrameProvider
that will come in a follow-up.
Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
This patch introduces `SBFrameList`, a new SBAPI class that allows
iterating over stack frames lazily without calling
`SBThread::GetFrameAtIndex` in a loop.
The new `SBThread::GetFrames()` method returns an `SBFrameList` that
supports Python iteration (`for frame in frame_list:`), indexing
(`frame_list[0]`, `frame_list[-1]`), and length queries (`len()`).
The implementation uses `StackFrameListSP` as the opaque pointer,
sharing the thread's underlying frame list to ensure frames are
materialized on-demand.
This is particularly useful for ScriptedFrameProviders, where user
scripts will be to iterate, filter, and replace frames lazily without
materializing the entire stack upfront.
Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
When building against the Python Stable API, we should use the `abi3`
ABI tag. Otherwise, Python will refuse to import the native shared
object. This PR adds support for generating a stable ABI compatible
suffix when `LLDB_ENABLE_PYTHON_LIMITED_API` is set.
Previously, on Darwin when building against Python 3.14, you would end
up with `_lldb.cpython-314-darwin.so`. Now, when using the stable ABI,
you get `_lldb.abi3.so` instead. A different version of the Python
interpreter will not consider loading the former, but will load the
latter.
the function signature for `GetStopDescription` is
`lldb::SBThread::GetStopDescription(char *dst_or_null, size_t len)`.
To get a description you need to call the function first time to get the
buffer size. a second time to get the description.
This is little worse from the python size as the signature is
`lldb.SBThread.GetStopDescription(int: len) -> list[str]` the user has
to pass the max size as possible with no way of checking if it is
enough.
This patch adds a new api
`lldb.SBThread.GetStopDescription(desc: lldb.SBStream()) -> bool` `bool
lldb::SBThread::GetStopDescription(lldb::SBStream &description)` which
handles this case.
Adds new Test case for lua.
Modify the python wrapper to return uint32_t,
which prevents incorrect child name-to-index mapping and avoids
performing redundant operations on non-existent SBValues.
When we restart a process, send an updated 'process' event describing
the newly launched process.
I also updated the `isLocalProcess` value based on if we're on the
'host' platform or not.
This patch adds the notion of "Facade" locations which can be reported
from a ScriptedResolver instead of the actual underlying breakpoint
location for the breakpoint. Also add a "was_hit" method to the scripted
resolver that allows the breakpoint to say which of these "Facade"
locations was hit, and "get_location_description" to provide a
description for the facade locations.
I apologize in advance for the size of the patch. Almost all of what's
here was necessary to (a) make the feature testable and (b) not break
any of the current behavior.
The motivation for this feature is given in the "Providing Facade
Locations" section that I added to the python-reference.rst so I won't
repeat it here.
rdar://152112327
Earlier today I was looking at the SBProgress documentation with a
colleague and found another instance where the swig block wasn't
formatting correctly. I've adjusted the docs slightly to fix this. I
don't actually know how to see a preview of our docstrings but I believe
this will fix it.
<img width="829" height="234" alt="image"
src="https://github.com/user-attachments/assets/8ef3a2df-92b9-4157-a452-f5e1ec51aa9a"
/>
* Adds `dynamic` property to automatically convert `SBStructuredData`
instances to the associated Python type (`str`, `int`, `float`, `bool`,
`NoneType`, etc)
* Implements `__getitem__` for Pythonic array and dictionary
subscripting
* Subscripting return the result of the `dynamic` property
* Updates `__iter__` to support dictionary instances (supporting `for`
loops)
* Adds `__str__`, `__int__`, and `__float__`
With these changes, these two expressions are equal:
```py
data["name"] == data.GetValueForKey("name").GetStringValue(1024)
```
**Note**: Unlike the original commit (#155061), this re-commit removes
the `__bool__` implementation, which broke crashlog. Somewhere in the
crashlog execution, it depends on `__bool__` meaning only `IsValid()`.
Additionally did some cleanup in TestStructuredDataAPI.py.
`__str__` was implemented in #155061, however its behavior was limited
to only a some kinds of `SBStructuredData`. That was a breaking change,
and this change removes that implementation of `__str__`, relying on the
existing behavior which calls `GetDescription`.
* Adds `dynamic` property to automatically convert `SBStructuredData`
instances to the associated Python type (`str`, `int`, `float`, `bool`,
`NoneType`, etc)
* Implements `__getitem__` for Pythonic array and dictionary
subscripting
* Subscripting return the result of the `dynamic` property
* Updates `__iter__` to support dictionary instances (supporting `for`
loops)
* Adds conversion to `str`, `int`, and `float`
* Adds Pythonic `bool` conversion
With these changes, these two expressions are equal:
```py
data["name"] == data.GetValueForKey("name").GetStringValue(1024)
```
Additionally did some cleanup in TestStructuredDataAPI.py.
Updated SBMemoryRegionInfo doc strings:
- Added detailed documentation for the GetDescription() method.
- Included information about the overwritten len() and str() functions
for the SBMemoryRegionInfo type, explaining their behavior and usage.
---------
Co-authored-by: Bar Soloveychik <barsolo@fb.com>
### Context
Over a year ago, I landed support for 64b Memory ranges in Minidump
(#95312). In this patch we added the Memory64 list stream, which is
effectively a Linked List on disk. The layout is a sixteen byte header
and then however many Memory descriptors.
### The Bug
This is a classic off-by one error, where I added 8 bytes instead of 16
for the header. This caused the first region to start 8 bytes before the
correct RVA, thus shifting all memory reads by 8 bytes. We are correctly
writing all the regions to disk correctly, with no physical corruption
but the RVA is defined wrong, meaning we were incorrectly reading memory

### Why wasn't this caught?
One problem we've had is forcing Minidump to actually use the 64b mode,
it would be a massive waste of resources to have a test that actually
wrote >4.2gb of IO to validate the 64b regions, and so almost all
validation has been manual. As a weakness of manual testing, this issue
is psuedo non-deterministic, as what regions end up in 64b or 32b is
handled greedily and iterated in the order it's laid out in
/proc/pid/maps. We often validated 64b was written correctly by
hexdumping the Minidump itself, which was not corrupted (other than the
BaseRVA)

### Why is this showing up now?
During internal usage, we had a bug report that the Minidump wasn't
displaying values. I was unable to repro the issue, but during my
investigation I saw the variables were in the 64b regions which resulted
in me identifying the bug.
### How do we prevent future regressions?
To prevent regressions, and honestly to save my sanity for figuring out
where 8 bytes magically came from, I've added a new API to
SBSaveCoreOptions.
```SBSaveCoreOptions::GetMemoryRegionsToSave()```
The ability to get the memory regions that we intend to include in the Coredump. I added this so we can compare what we intended to include versus what was actually included. Traditionally we've always had issues comparing regions because Minidump includes `/proc/pid/maps` and it can be difficult to know what memoryregion read failure was a genuine error or just a page that wasn't meant to be included.
We are also leveraging this API to choose the memory regions to be generated, as well as for testing what regions should be bytewise 1:1.
After much debate with @clayborg, I've moved all non-stack memory to the Memory64 List. This list doesn't incur us any meaningful overhead and Greg originally suggested doing this in the original 64b PR. This also means we're exercising the 64b path every single time we save a Minidump, preventing regressions on this feature from slipping through testing in the future.
Snippet produced by [minidump.py](https://github.com/clayborg/scripts)
```
MINIDUMP_MEMORY_LIST:
NumberOfMemoryRanges = 0x00000002
MemoryRanges[0] = [0x00007f61085ff9f0 - 0x00007f6108601000) @ 0x0003f655
MemoryRanges[1] = [0x00007ffe47e50910 - 0x00007ffe47e52000) @ 0x00040c65
MINIDUMP_MEMORY64_LIST:
NumberOfMemoryRanges = 0x000000000000002e
BaseRva = 0x0000000000042669
MemoryRanges[0] = [0x00005584162d8000 - 0x00005584162d9000)
MemoryRanges[1] = [0x00005584162d9000 - 0x00005584162db000)
MemoryRanges[2] = [0x00005584162db000 - 0x00005584162dd000)
MemoryRanges[3] = [0x00005584162dd000 - 0x00005584162ff000)
MemoryRanges[4] = [0x00007f6100000000 - 0x00007f6100021000)
MemoryRanges[5] = [0x00007f6108800000 - 0x00007f6108828000)
MemoryRanges[6] = [0x00007f6108828000 - 0x00007f610899d000)
MemoryRanges[7] = [0x00007f610899d000 - 0x00007f61089f9000)
MemoryRanges[8] = [0x00007f61089f9000 - 0x00007f6108a08000)
MemoryRanges[9] = [0x00007f6108bf5000 - 0x00007f6108bf7000)
```
### Misc
As a part of this fix I had to look at LLDB logs a lot, you'll notice I added `0x` to many of the PRIx64 `LLDB_LOGF`. This is so the user (or I) can directly copy paste the address in the logs instead of adding the hex prefix themselves.
Added some SBSaveCore tests for the new GetMemoryAPI, and Docstrings.
CC: @DavidSpickett, @da-viper @labath because we've been working together on save-core plugins, review it optional and I didn't tag you but figured you'd want to know
Enable SWIG support for translating Doxygen comments found in interface
and header files into a target language's normal documentation language.
This feature was introduced in SWIG 4.0 and currently only supports
Python (and Java). Hand-written documentation still takes precedence.
SWIG documentation: https://www.swig.org/Doc4.0/Doxygen.html
Add a class property for the version string. This allows you to use
access the version string through `lldb.SBDebugger.version` instead of
having to call `lldb.SBDebugger.GetVersionString()`.
My current internal work requires some sensitivity to IO usage. I had a
work around to calculate the expected size of a Minidump, but I've added
this PR so an automated system could look at the expected size of an
LLDB generated Minidump and then choose if it has the space or wants to
generate it.
There are some prerequisites to calculating the correct size, so I have
the API take a reference for an SBError, I originally tried to return an
SBError and instead take a uint64_t reference, but this made the API
very difficult to use in python.
Added a test case as well.
So the dSYM can be told what target it has been loaded into.
When lldb is loading modules, while creating a target, it will run
"command script import" on any Python modules in Resources/Python in the
dSYM. However, this happens WHILE the target is being created, so it is
not yet in the target list. That means that these scripts can't act on
the target that they a part of when they get loaded.
This patch adds a new python API that lldb will call:
__lldb_module_added_to_target
if it is defined in the module, passing in the Target the module was
being added to, so that code in these dSYM's don't have to guess.
Expose u target API mutex through the SB API. This is motivated by
lldb-dap, which is built on top of the SB API and needs a way to execute
a series of SB API calls in an atomic manner (see #131242).
We can solve this problem by either introducing an additional layer of
locking at the DAP level or by exposing the existing locking at the SB
API level. This patch implements the second approach.
This was discussed in an RFC on Discourse [0]. The original
implementation exposed a move-only lock rather than a mutex [1] which
doesn't work well with SWIG 4.0 [2]. This implement the alternative
solution of exposing the mutex rather than the lock. The SBMutex
conforms to the BasicLockable requirement [3] (which is why the methods
are called `lock` and `unlock` rather than Lock and Unlock) so it can be
used as `std::lock_guard<lldb::SBMutex>` and
`std::unique_lock<lldb::SBMutex>`.
[0]: https://discourse.llvm.org/t/rfc-exposing-the-target-api-lock-through-the-sb-api/85215/6
[1]: https://github.com/llvm/llvm-project/pull/131404
[2]: https://discourse.llvm.org/t/rfc-bumping-the-minimum-swig-version-to-4-1-0/85377/9
[3]: https://en.cppreference.com/w/cpp/named_req/BasicLockable
We recently added an explicit finalize to SBProgress, #128966. I
realized while adding some additional implementations of SBProgress that
we should to add `with` support for ease of use. This patch addresses
adding and `__enter()__` method (which a no-op) and an `__exit()__` to
swig. I also refactor the emitter for the test to leverage `with`
instead of explicitly calling finalize, and I've updated the docstrings.
When adding SBLock, I realized you always have to add a new header in
two places: LLDB.h and headers.swig.
I can't think of a reason the latter can't use the umbrella header and
avoid the duplication.
This patch adds a finalize method which destroys the underlying RAII
SBProgress. My primary motivation for this is so I can write better
tests that are non-flaky, but after discussing with @clayborg in my DAP
message improvement patch (#124648) this is probably an essential API
despite that I originally argued it wasn't.
Fix#92603
This replaces #113066. I finally came back to this issue and it seems
that this approach is still very promising.
As requested, I have added a short explanation as to why CPython module
should be moved into a submodule.
cc @JDevlieghere who reviewed on the previous PR earlier.
SBFrame::GetRegisters() (and the .registers / .regs extensions in
Python) returns an array of register-set's, not registers like you might
expect from the API name. Document this.
---------
Co-authored-by: Will Hawkins <whh8b@obs.cr>
Xcode uses a pseudoterminal for the debugger console.
- The upside of this apporach is that it means that it can rely on
LLDB's IOHandlers for multiline and script input.
- The downside of this approach is that the command output is printed to
the PTY and you don't get a SBCommandReturnObject. Adrian added support
for inline diagnostics (#110901) and we'd like to access those from the
IDE.
This patch adds support for registering a callback in the command
interpreter that gives access to the `(SB)CommandReturnObject` right
before it will be printed. The callback implementation can choose
whether it likes to handle printing the result or defer to lldb. If the
callback indicated it handled the result, the command interpreter will
skip printing the result.
We considered a few other alternatives to solve this problem:
- The most obvious one is using `HandleCommand`, which returns a
`SBCommandReturnObject`. The problem with this approach is the multiline
input mentioned above. We would need a way to tell the IDE that it
should expect multiline input, which isn't known until LLDB starts
handling the command.
- To address the multiline issue,we considered exposing (some of the)
IOHandler machinery through the SB API. To solve this particular issue,
that would require reimplementing a ton of logic that already exists
today in the CommandInterpeter. Furthermore that seems like overkill
compared to the proposed solution.
rdar://141254310