Open mvanotti opened 1 month ago
@llvm/issue-subscribers-lldb
Author: Marco Vanotti (mvanotti)
LLDB will have created two breakpoints here, one for each instantiation. You could set a breakpoint on only one of these from the CLI with br se -n 'Read<int>' -c 'result != 0'
. E.g.,:
$ lldb a.out -o "br se -n 'Read<int>' -c 'result != 0'" -o run
(lldb) target create "a.out"
(lldb) br se -n 'Read<int>' -c 'result != 0'
Breakpoint 1: where = a.out`int Read<int>() + 4 at break.cpp:4:10, address = 0x0000000100003f74
(lldb) run
Process 20706 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100003f74 a.out`int Read<int>() at break.cpp:4:10
1 template <typename T>
2 T Read() {
3 T result;
-> 4 return result;
5 }
6
7 struct FooStruct {};
Target 0: (a.out) stopped.
Or as you point out, delete the breakpoints in the instantiations you don't care about. I don't see how LLDB could know not to run the expression in one of the instantiations (there's no way we would know that the expression fails to run until we actually run it). CC @jimingham to confirm whether we'd want/can do anything about this in the SBAPI. The breakpoint resolvers could be of use https://lldb.llvm.org/use/python-reference.html#using-the-python-api-s-to-create-custom-breakpoints perhaps?
If you add a condition to a breakpoint, lldb should run it, it shouldn't try to figure out whether it might work or not. We have to solve this in setting the breakpoint if you want to be able to add the condition to the breakpoint itself.
Note, BTW, you can add conditions to breakpoint locations as well as breakpoints. So you can make this work for each of the locations by adding the condition appropriate to the location. Just set the breakpoint, then do:
(lldb) break list
Current breakpoints:
1: source regex = "return result", exact_match = 0, locations = 2
1.1: where = templates`FooStruct Read<FooStruct>(unsigned char*, unsigned long) + 88 at templates.cpp:18:3, address = templates[0x0000000100003e88], unresolved, hit count = 0
1.2: where = templates`unsigned long long Read<unsigned long long>(unsigned char*, unsigned long) + 88 at templates.cpp:18:10, address = templates[0x0000000100003ef4], unresolved, hit count = 0
(lldb) break modify -c "result == 0" 1.2
You can also do this with the SB API (SBBreakpointLocation.SetCondition).
If we want to make file & line breakpoint ALSO filter on function name, we could certainly allow -n
as an optional option to break set -f <> -l <>
. If you supply a -n as well as a file and line, we would only set the breakpoint for that line if the function name also matches the -n value. So then you could say:
(lldb) break set -l 18 -n Read<int> -c "result == 0"
The file and line would be the primary filter, then we'd run over all those matches again, and throw out the ones that are in functions that don't match the given name.
For the SB API, we'd need to add an overload to SBTarget. BreakpointCreateByLocation that takes an optional function_name string.
You could fix this as it stands by writing a custom breakpoint resolver that sets the file & line breakpoint, then runs through that breakpoint's locations and adds to itself the ones that match the function name, then deletes the file & line breakpoint.
You could alternately write a little python based command:
(lldb) add_condition --condition "result == 0" --name "Read<int>" <BKPTNO>
That went through the breakpoint locations in BKPTNO and added the condition only to the ones whose containing function matched the --name
option.
The latter is probably the easiest.
In lldb it is hard to set up a conditional breakpoint in a templated function, if the condition depends on the template type.
See the following example:
let's say we want to set a breakpoint on line 18 to check if
result
is not zero:This will throw an error when we evaluate it, which is less than ideal. It is understandable that it fails, but it is a bit hard to specify the correct breakpoint location here.
The issue is a bit worse if using the LLDB Python API: When you specify the breakpoint by location (file + line), you have no way to specify which version of the template you want to use (or which function name?). Instead, you would have to disable all the other breakpoints afterwards.
The workaround I found is to look up all the locations, from there call GetAddress(), then get the function name, and disable the breakpoint if the function name does not match what you expect.
I'm not sure what the right fix would look like here.