14 Commits

Author SHA1 Message Date
Adrian Vogelsgesang
d8d252fe96
[lldb] Add support for disabling frame recognizers (#109219)
Sometimes you only want to temporarily disable a frame recognizer
instead of deleting it. In particular, when dealing with one of the
builtin frame recognizers, which cannot be restored after deletion.

To be able to write test cases for this functionality, I also changed
`lldb/test/API/commands/frame/recognizer` to use normal C instead of
Objective-C
2024-09-20 22:17:42 +02:00
Adrian Vogelsgesang
fc517973c2
[lldb] Fix test expectation in TestFrameRecognizer.py (#106281) 2024-08-27 22:59:14 +02:00
Adrian Vogelsgesang
dd060bdede
[lldb] Add frame recognizers for libc++ std::invoke (#105695)
With this commit, we also hide the implementation details of
`std::invoke`. To do so, the `LibCXXFrameRecognizer` got a couple more
regular expressions.

The regular expression passed into `AddRecognizer` became problematic,
as it was evaluated on the demangled name. Those names also included
result types for C++ symbols. For `std::__invoke` the return type is a
huge `decltype(...)`, making the regular expresison really hard to
write.

Instead, I added support to `AddRecognizer` for matching on the
demangled names without result type and argument types.

By hiding the implementation details of `invoke`, also the back traces
for `std::function` become even nicer, because `std::function` is using
`__invoke` internally.

Co-authored-by: Adrian Prantl <aprantl@apple.com>
2024-08-27 19:15:42 +02:00
Adrian Prantl
3c0fba4f24 Revert "Revert "[lldb] Extend frame recognizers to hide frames from backtraces (#104523)""
This reverts commit 547917aebd1e79a8929b53f0ddf3b5185ee4df74.
2024-08-23 11:06:01 -07:00
Dmitri Gribenko
547917aebd Revert "[lldb] Extend frame recognizers to hide frames from backtraces (#104523)"
This reverts commit f01f80ce6ca7640bb0e267b84b1ed0e89b57e2d9.

This commit introduces an msan violation. See the discussion on https://github.com/llvm/llvm-project/pull/104523.
2024-08-22 13:24:57 +02:00
Adrian Prantl
f01f80ce6c
[lldb] Extend frame recognizers to hide frames from backtraces (#104523)
Compilers and language runtimes often use helper functions that are
fundamentally uninteresting when debugging anything but the
compiler/runtime itself. This patch introduces a user-extensible
mechanism that allows for these frames to be hidden from backtraces and
automatically skipped over when navigating the stack with `up` and
`down`.

This does not affect the numbering of frames, so `f <N>` will still
provide access to the hidden frames. The `bt` output will also print a
hint that frames have been hidden.

My primary motivation for this feature is to hide thunks in the Swift
programming language, but I'm including an example recognizer for
`std::function::operator()` that I wished for myself many times while
debugging LLDB.

rdar://126629381


Example output. (Yes, my proof-of-concept recognizer could hide even
more frames if we had a method that returned the function name without
the return type or I used something that isn't based off regex, but it's
really only meant as an example).

before:
```
(lldb) thread backtrace --filtered=false
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x0000000100001f04 a.out`foo(x=1, y=1) at main.cpp:4:10
    frame #1: 0x0000000100003a00 a.out`decltype(std::declval<int (*&)(int, int)>()(std::declval<int>(), std::declval<int>())) std::__1::__invoke[abi:se200000]<int (*&)(int, int), int, int>(__f=0x000000016fdff280, __args=0x000000016fdff224, __args=0x000000016fdff220) at invoke.h:149:25
    frame #2: 0x000000010000399c a.out`int std::__1::__invoke_void_return_wrapper<int, false>::__call[abi:se200000]<int (*&)(int, int), int, int>(__args=0x000000016fdff280, __args=0x000000016fdff224, __args=0x000000016fdff220) at invoke.h:216:12
    frame #3: 0x0000000100003968 a.out`std::__1::__function::__alloc_func<int (*)(int, int), std::__1::allocator<int (*)(int, int)>, int (int, int)>::operator()[abi:se200000](this=0x000000016fdff280, __arg=0x000000016fdff224, __arg=0x000000016fdff220) at function.h:171:12
    frame #4: 0x00000001000026bc a.out`std::__1::__function::__func<int (*)(int, int), std::__1::allocator<int (*)(int, int)>, int (int, int)>::operator()(this=0x000000016fdff278, __arg=0x000000016fdff224, __arg=0x000000016fdff220) at function.h:313:10
    frame #5: 0x0000000100003c38 a.out`std::__1::__function::__value_func<int (int, int)>::operator()[abi:se200000](this=0x000000016fdff278, __args=0x000000016fdff224, __args=0x000000016fdff220) const at function.h:430:12
    frame #6: 0x0000000100002038 a.out`std::__1::function<int (int, int)>::operator()(this= Function = foo(int, int) , __arg=1, __arg=1) const at function.h:989:10
    frame #7: 0x0000000100001f64 a.out`main(argc=1, argv=0x000000016fdff4f8) at main.cpp:9:10
    frame #8: 0x0000000183cdf154 dyld`start + 2476
(lldb) 
```

after

```
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x0000000100001f04 a.out`foo(x=1, y=1) at main.cpp:4:10
    frame #1: 0x0000000100003a00 a.out`decltype(std::declval<int (*&)(int, int)>()(std::declval<int>(), std::declval<int>())) std::__1::__invoke[abi:se200000]<int (*&)(int, int), int, int>(__f=0x000000016fdff280, __args=0x000000016fdff224, __args=0x000000016fdff220) at invoke.h:149:25
    frame #2: 0x000000010000399c a.out`int std::__1::__invoke_void_return_wrapper<int, false>::__call[abi:se200000]<int (*&)(int, int), int, int>(__args=0x000000016fdff280, __args=0x000000016fdff224, __args=0x000000016fdff220) at invoke.h:216:12
    frame #6: 0x0000000100002038 a.out`std::__1::function<int (int, int)>::operator()(this= Function = foo(int, int) , __arg=1, __arg=1) const at function.h:989:10
    frame #7: 0x0000000100001f64 a.out`main(argc=1, argv=0x000000016fdff4f8) at main.cpp:9:10
    frame #8: 0x0000000183cdf154 dyld`start + 2476
Note: Some frames were hidden by frame recognizers
```
2024-08-20 16:01:22 -07:00
Jonas Devlieghere
2238dcc393
[NFC][Py Reformat] Reformat python files in lldb
This is an ongoing series of commits that are reformatting our Python
code. Reformatting is done with `black` (23.1.0).

If you end up having problems merging this commit because you have made
changes to a python file, the best way to handle that is to run `git
checkout --ours <yourfile>` and then reformat it with black.

RFC: https://discourse.llvm.org/t/rfc-document-and-standardize-python-code-style

Differential revision: https://reviews.llvm.org/D151460
2023-05-25 12:54:09 -07:00
Dave Lee
4cc8f2a017 [lldb][tests] Automatically call compute_mydir (NFC)
Eliminate boilerplate of having each test manually assign to `mydir` by calling
`compute_mydir` in lldbtest.py.

Differential Revision: https://reviews.llvm.org/D128077
2022-06-17 14:34:49 -07:00
Roman Podoliaka
54c496dad6 [lldb] Allow to register frame recognizers applied beyond the first instruction
It is currently possible to register a frame recognizer, but it will be applied if and only if the frame's PC points to the very first instruction of the specified function, which limits usability of this feature.

The implementation already supports changing this behaviour by passing an additional flag, but it's not possible to set it via the command interface. Fix that.

Reviewed By: jingham

Differential Revision: https://reviews.llvm.org/D108510
2021-08-29 17:28:46 +02:00
Raphael Isemann
5477fbc294 [lldb] Make deleting frame recognizers actually work
Summary:

Frame recognizers are stored alongside a flag that indicates whether they were
deleted by the user. If the flag is set, they are supposed to be ignored by the
rest of the frame recognizer code. 'frame recognizer delete' is supposed to set
that flag. 'frame recognizer clear' however actually deletes all frame
recognizers (so, it doesn't set the flag but directly deletes them from the
list).

The current implementation of this concept is pretty broken. `frame recognizer
delete` sets the flag, but it somehow thinks that the recognizer id is an index
in the recognizer list. That's not true as it's actually just a member of each
recognizer entry. So it actually just sets the `deleted` flag for a random other
recognizer. The tests for the recognizer still pass as `frame recognizer list`
is also broken and just completely ignored the `deleted` flag and lists all
recognizers. Also `frame recognizer delete` just ignores if it can't actually
delete a recognizer if the id is invalid.

I think we can simplify this whole thing by just actually deleting recognizers
instead of making sure all code is actually respecting the `deleted` flag. I
assume the intention of this was to make sure that all recognizers are getting
unique ids over the course of an LLDB session, but as `clear` is actually
deleting them and we keep recycling ids, that didn't really work to begin with.

This patch deletes the `deleted` flag and just actually deletes the stored
recognizer. Also adds the missing error message in case it find a recognizer
with a given id.

Reviewers: mib

Reviewed By: mib

Subscribers: abidh, JDevlieghere

Differential Revision: https://reviews.llvm.org/D84404
2020-07-23 17:43:37 +02:00
Raphael Isemann
1b7c9eae6d [lldb] Store StackFrameRecognizers in the target instead of a global list
Summary:

Currently the frame recognizers are stored in a global list (the list in the
StackFrameRecognizersManagerImpl singleton to be precise). All commands and
plugins that modify the list are just modifying that global list of recognizers
which is shared by all Target and Debugger instances.

This is clearly against the idea of LLDB being usable as a library and it also
leads to some very obscure errors as now multiple tests are sharing the used
frame recognizers. For example D83400 is currently failing as it reorders some
test_ functions which permanently changes the frame recognizers of all
debuggers/targets. As all frame recognizers are also initialized in a 'once'
guard, it's also impossible to every restore back the original frame recognizers
once they are deleted in a process.

This patch just moves the frame recognizers into the current target. This seems
the way everyone assumes the system works as for example the assert frame
recognizers is using the current target to find the function/so-name to look for
(which only works if the recognizers are stored in the target).

Reviewers: jingham, mib

Reviewed By: jingham, mib

Subscribers: MrHate, JDevlieghere

Differential Revision: https://reviews.llvm.org/D83757
2020-07-17 09:26:27 +02:00
Raphael Isemann
9010cef2af [lldb] Replace StringConvert with llvm::to_integer when parsing integer values in CommandObjects
Summary:

This replaces the current use of LLDB's own `StringConvert` with LLVM's
`to_integer` which has a less error-prone API and doesn't use special 'error
values' to designate parsing problems.

Where needed I also added missing error handling code that prints a parsing
error instead of continuing with the error value returned from `StringConvert`
(which either gave a cryptic error message or just took the error value
performed an incorrect action with it. For example, `frame recognizer delete -1`
just deleted the frame recognizer at index 0).

Reviewers: #lldb, labath

Reviewed By: labath

Subscribers: labath, abidh, JDevlieghere

Differential Revision: https://reviews.llvm.org/D82297
2020-07-01 17:19:31 +02:00
Med Ismail Bennani
db31e2e1e6
[lldb/Target] Support more than 2 symbols in StackFrameRecognizer
This patch changes the way the StackFrame Recognizers match a certain
frame.

Until now, recognizers could be registered with a function
name but also an alternate symbol.
This change is motivated by a test failure for the Assert frame
recognizer on Linux. Depending the version of the libc, the abort
function (triggered by an assertion), could have more than two
signatures (i.e. `raise`, `__GI_raise` and `gsignal`).

Instead of only checking the default symbol name and the alternate one,
lldb will iterate over a list of symbols to match against.

rdar://60386577

Differential Revision: https://reviews.llvm.org/D76188

Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
2020-03-18 14:15:58 +01:00
Jordan Rupprecht
99451b4453 [lldb][test] Remove symlink for API tests.
Summary: Moves lldbsuite tests to lldb/test/API.

This is a largely mechanical change, moved with the following steps:

```
rm lldb/test/API/testcases
mkdir -p lldb/test/API/{test_runner/test,tools/lldb-{server,vscode}}
mv lldb/packages/Python/lldbsuite/test/test_runner/test lldb/test/API/test_runner
for d in $(find lldb/packages/Python/lldbsuite/test/* -maxdepth 0 -type d | egrep -v "make|plugins|test_runner|tools"); do mv $d lldb/test/API; done
for d in $(find lldb/packages/Python/lldbsuite/test/tools/lldb-vscode -maxdepth 1 -mindepth 1 | grep -v ".py"); do mv $d lldb/test/API/tools/lldb-vscode; done
for d in $(find lldb/packages/Python/lldbsuite/test/tools/lldb-server -maxdepth 1 -mindepth 1 | egrep -v "gdbremote_testcase.py|lldbgdbserverutils.py|socket_packet_pump.py"); do mv $d lldb/test/API/tools/lldb-server; done
```

lldb/packages/Python/lldbsuite/__init__.py and lldb/test/API/lit.cfg.py were also updated with the new directory structure.

Reviewers: labath, JDevlieghere

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D71151
2020-02-11 10:03:53 -08:00