The problem was in calling GetLoadAddress on a value in the error state,
where `ValueObject::GetLoadAddress` could end up accessing the
uninitialized "address type" by-ref return value from `GetAddressOf`.
This probably happened because each function expected the other to
initialize it.
We can guarantee initialization by turning this into a proper return
value.
I've added a test, but it only (reliably) crashes if lldb is built with
ubsan.
Add an overloaded `GetTypeSystem` to specify the expected type system subclass. Changes code from `GetTypeSystem().dyn_cast_or_null<TypeSystemClang>()` to `GetTypeSystem<TypeSystemClang>()`.
The vast majority of `SyntheticChildrenFrontEnd` subclasses provide
children, and as such implement `MightHaveChildren` with a constant
value of `true`. This change makes `true` the default value. With this
change, `MightHaveChildren` only needs to be implemented by synthetic
providers that can return `false`, which is only 3 subclasses.
Change GetNumChildren()/CalculateNumChildren() methods return
llvm::Expected
This is an NFC change that does not yet add any error handling or change
any code to return any errors.
This is the second big change in the patch series started with
https://github.com/llvm/llvm-project/pull/83501
A follow-up PR will wire up error handling.
Change GetNumChildren()/CalculateNumChildren() methods return
llvm::Expected
This is an NFC change that does not yet add any error handling or change
any code to return any errors.
This is the second big change in the patch series started with
https://github.com/llvm/llvm-project/pull/83501
A follow-up PR will wire up error handling.
Existing callers of `GetChildAtIndex` pass true for can_create. This change
makes true the default value, callers don't have to pass an opaque true.
See also D151966 for the same change to `GetChildMemberWithName`.
Differential Revision: https://reviews.llvm.org/D152031
The pretty printer for `std::coroutine_handle` was running into
> Assertion failed: (target_ctx != source_ctx && "Can't import into itself")
from ClangASTImporter.h, line 270.
This commit fixes the issue by removing the `CopyType` call from the
pretty printer. While this call was necessary in the past, it seems to
be no longer required, at least all test cases are still passing. Maybe
something changed in the meantime around the handling of `TypesystemClang`
instances. I don't quite understand why `CopyType` was necessary earlier.
I am not sure how to add a regression test for this, though. It seems
the issue is already triggered by the exising `TestCoroutineHandle.py`,
but API tests seem to ignore all violations of `lldbassert` and still
report the test as "passed", even if assertions were triggered
Differential Revision: https://reviews.llvm.org/D143127
So far, the pretty printer for `std::coroutine_handle` internally
dereferenced the contained frame pointer displayed the `promise`
as a sub-value. As noticed in https://reviews.llvm.org/D132624
by @labath, this can lead to an endless loop in lldb during printing
if the coroutine frame pointers form a cycle.
This commit breaks the cycle by exposing the `promise` as a pointer
type instead of a value type. The depth to which the `frame variable`
and the `expression` commands dereference those pointers can be
controlled using the `--ptr-depth` argument.
Differential Revision: https://reviews.llvm.org/D132815
This reverts commit 4346318f5c700f4e85f866610fb8328fc429319b.
This test case is failing on macOS, reverting until it can be
looked at more closely to unblock the macOS CI bots.
```
File "/Volumes/work/llvm/llvm-project/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/TestCoroutineHandle.py", line 121, in test_libcpp
self.do_test(USE_LIBCPP)
File "/Volumes/work/llvm/llvm-project/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/TestCoroutineHandle.py", line 45, in do_test
self.expect_expr("noop_hdl",
File "/Volumes/work/llvm/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2441, in expect_expr
value_check.check_value(self, eval_result, str(eval_result))
File "/Volumes/work/llvm/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 306, in check_value
test_base.assertEqual(self.expect_summary, val.GetSummary(),
AssertionError: 'noop_coroutine' != 'coro frame = 0x100004058'
- noop_coroutine+ coro frame = 0x100004058 : (std::coroutine_handle<void>) $1 = coro frame = 0x100004058 {
resume = 0x0000000100003344 (a.out`___lldb_unnamed_symbol223)
destroy = 0x0000000100003344 (a.out`___lldb_unnamed_symbol223)
}
Checking SBValue: (std::coroutine_handle<void>) $1 = coro frame = 0x100004058 {
resume = 0x0000000100003344 (a.out`___lldb_unnamed_symbol223)
destroy = 0x0000000100003344 (a.out`___lldb_unnamed_symbol223)
}
```
Those lldb_unnamed_symbols are synthetic names that ObjectFileMachO
adds to the symbol table, most often seen with stripped binaries,
based off of the function start addresses for all the functions -
if a function has no symbol name, lldb adds one of these names.
This change was originally landed via https://reviews.llvm.org/D132624
This reverts commit cd3091a88f7c55c90d9b5fff372ce1cdfc71948d.
This change crashes on macOS systems in
formatters::StdlibCoroutineHandleSyntheticFrontEnd when
it fails to create the `ValueObjectSP promise` and calls
a method on it. The failure causes a segfault while running
TestCoroutineHandle.py on the "LLDB Incremental" CI bot,
https://green.lab.llvm.org/green/view/LLDB/job/lldb-cmake/
This change originally landed via https://reviews.llvm.org/D132815
So far, the pretty printer for `std::coroutine_handle` internally
dereferenced the contained frame pointer displayed the `promise`
as a sub-value. As noticed in https://reviews.llvm.org/D132624
by @labath, this can lead to an endless loop in lldb during printing
if the coroutine frame pointers form a cycle.
This commit breaks the cycle by exposing the `promise` as a pointer
type instead of a value type. The depth to which the `frame variable`
and the `expression` commands dereference those pointers can be
controlled using the `--ptr-depth` argument.
Differential Revision: https://reviews.llvm.org/D132815
With this commit, the `std::coroutine_handle` pretty printer now
recognizes `std::noop_coroutine()` handles. For noop coroutine handles,
we identify use the summary string `noop_coroutine` and we don't print
children
Instead of
```
(std::coroutine_handle<void>) $3 = coro frame = 0x555555559058 {
resume = 0x00005555555564f0 (a.out`std::__1::coroutine_handle<std::__1::noop_coroutine_promise>::__noop_coroutine_frame_ty_::__dummy_resume_destroy_func() at noop_coroutine_handle.h:79)
destroy = 0x00005555555564f0 (a.out`std::__1::coroutine_handle<std::__1::noop_coroutine_promise>::__noop_coroutine_frame_ty_::__dummy_resume_destroy_func() at noop_coroutine_handle.h:79)
}
```
we now print
```
(std::coroutine_handle<void>) $3 = noop_coroutine
```
Differential Revision: https://reviews.llvm.org/D132735
The original commit was missing a `ClangASTImporter::CopyType` call.
Original commit message:
This commit teaches the `std::coroutine_handle` pretty-printer to
devirtualize type-erased promise types. This is particularly useful to
resonstruct call stacks, either of asynchronous control flow or of
recursive invocations of `std::generator`. For the example recently
introduced by https://reviews.llvm.org/D132451, printing the `__promise`
variable now shows
```
(std::__coroutine_traits_sfinae<task, void>::promise_type) __promise = {
continuation = coro frame = 0x555555562430 {
resume = 0x0000555555556310 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
destroy = 0x0000555555556700 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
promise = {
continuation = coro frame = 0x5555555623e0 {
resume = 0x0000555555557070 (a.out`task detail::chain_fn<2>() at llvm-nested-example.cpp:66)
destroy = 0x0000555555557460 (a.out`task detail::chain_fn<2>() at llvm-nested-example.cpp:66)
promise = {
...
}
}
result = 0
}
}
result = 0
}
```
(shortened to keep the commit message readable) instead of
```
(std::__coroutine_traits_sfinae<task, void>::promise_type) __promise = {
continuation = coro frame = 0x555555562430 {
resume = 0x0000555555556310 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
destroy = 0x0000555555556700 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
}
result = 0
}
```
Note how the new debug output reveals the complete asynchronous call
stack: our own function resumes `chain_fn<1>` which in turn will resume
`chain_fn<2>` and so on. Thereby this change allows users of lldb to
inspect the logical coroutine call stack without using any custom debug
scripts (although the display is still a bit clumsy. It would be nicer
to also integrate this into lldb's backtrace feature, but I don't know
how to do so)
The devirtualization currently works by introspecting the function
pointed to by the `destroy` pointer. (The `resume` pointer is not worth
much, given that for the final suspend point `resume` is set to a
nullptr. We have to use the `destroy` pointer instead.) We then look
for a `__promise` variable inside the `destroy` function. This
`__promise` variable is synthetically generated by LLVM, and looking at
its type reveals the type-erased promise_type.
This approach only works for clang-generated code, though. While gcc
also adds a `_Coro_promise` variable to the `resume` function, it does
not do so for the `destroy` function. However, we can't use the `resume`
function, as it will be reset to a nullptr at the final suspension
point. For the time being, I am happy with de-virtualization only working
for clang. A follow-up commit will further improve devirtualization and
also expose the variables spilled to the coroutine frame. As part of
this, I will also revisit gcc support.
Differential Revision: https://reviews.llvm.org/D132624
When a process gets restarted TypeSystem objects associated with it
may get deleted, and any CompilerType objects holding on to a
reference to that type system are a use-after-free in waiting. Because
of the SBAPI, we don't have tight control over where CompilerTypes go
and when they are used. This is particularly a problem in the Swift
plugin, where the scratch TypeSystem can be restarted while the
process is still running. The Swift plugin has a lock to prevent
abuse, but where there's a lock there can be bugs.
This patch changes CompilerType to store a std::weak_ptr<TypeSystem>.
Most of the std::weak_ptr<TypeSystem>* uglyness is hidden by
introducing a wrapper class CompilerType::WrappedTypeSystem that has a
dyn_cast_or_null() method. The only sites that need to know about the
weak pointer implementation detail are the ones that deal with
creating TypeSystems.
rdar://101505232
Differential Revision: https://reviews.llvm.org/D136650
This commit teaches the `std::coroutine_handle` pretty-printer to
devirtualize type-erased promise types. This is particularly useful to
resonstruct call stacks, either of asynchronous control flow or of
recursive invocations of `std::generator`. For the example recently
introduced by https://reviews.llvm.org/D132451, printing the `__promise`
variable now shows
```
(std::__coroutine_traits_sfinae<task, void>::promise_type) __promise = {
continuation = coro frame = 0x555555562430 {
resume = 0x0000555555556310 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
destroy = 0x0000555555556700 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
promise = {
continuation = coro frame = 0x5555555623e0 {
resume = 0x0000555555557070 (a.out`task detail::chain_fn<2>() at llvm-nested-example.cpp:66)
destroy = 0x0000555555557460 (a.out`task detail::chain_fn<2>() at llvm-nested-example.cpp:66)
promise = {
...
}
}
result = 0
}
}
result = 0
}
```
(shortened to keep the commit message readable) instead of
```
(std::__coroutine_traits_sfinae<task, void>::promise_type) __promise = {
continuation = coro frame = 0x555555562430 {
resume = 0x0000555555556310 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
destroy = 0x0000555555556700 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
}
result = 0
}
```
Note how the new debug output reveals the complete asynchronous call
stack: our own function resumes `chain_fn<1>` which in turn will resume
`chain_fn<2>` and so on. Thereby this change allows users of lldb to
inspect the logical coroutine call stack without using any custom debug
scripts (although the display is still a bit clumsy. It would be nicer
to also integrate this into lldb's backtrace feature, but I don't know
how to do so)
The devirtualization currently works by introspecting the function
pointed to by the `destroy` pointer. (The `resume` pointer is not worth
much, given that for the final suspend point `resume` is set to a
nullptr. We have to use the `destroy` pointer instead.) We then look
for a `__promise` variable inside the `destroy` function. This
`__promise` variable is synthetically generated by LLVM, and looking at
its type reveals the type-erased promise_type.
This approach only works for clang-generated code, though. While gcc
also adds a `_Coro_promise` variable to the `resume` function, it does
not do so for the `destroy` function. However, we can't use the `resume`
function, as it will be reset to a nullptr at the final suspension
point. For the time being, I am happy with de-virtualization only working
for clang. A follow-up commit will further improve devirtualization and
also expose the variables spilled to the coroutine frame. As part of
this, I will also revisit gcc support.
Differential Revision: https://reviews.llvm.org/D132624
This patch adds a formatter for `std::coroutine_handle`, both for libc++
and libstdc++. For the type-erased `coroutine_handle<>`, it shows the
`resume` and `destroy` function pointers. For a non-type-erased
`coroutine_handle<promise_type>` it also shows the `promise` value.
With this change, executing the `v t` command on the example from
https://clang.llvm.org/docs/DebuggingCoroutines.html now outputs
```
(task) t = {
handle = coro frame = 0x55555555b2a0 {
resume = 0x0000555555555a10 (a.out`coro_task(int, int) at llvm-example.cpp:36)
destroy = 0x0000555555556090 (a.out`coro_task(int, int) at llvm-example.cpp:36)
}
}
```
instead of just
```
(task) t = {
handle = {
__handle_ = 0x55555555b2a0
}
}
```
Note, how the symbols for the `resume` and `destroy` function pointer
reveal which coroutine is stored inside the `std::coroutine_handle`.
A follow-up commit will use this fact to infer the coroutine's promise
type and the representation of its internal coroutine state based on
the `resume` and `destroy` pointers.
The same formatter is used for both libc++ and libstdc++. It would
also work for MSVC's standard library, however it is not registered
for MSVC, given that lldb does not provide pretty printers for other
MSVC types, either.
The formatter is in a newly added `Coroutines.{h,cpp}` file because there
does not seem to be an already existing place where we could share
formatters across libc++ and libstdc++. Also, I expect this code to grow
as we improve debugging experience for coroutines further.
**Testing**
* Added API test
Differential Revision: https://reviews.llvm.org/D132415