Open chenhuimao opened 1 month ago
@llvm/issue-subscribers-lldb
Author: mao2020 (chenhuimao)
Make sure that your address location is actually listed as "resolved" in the cases where you aren't seeing your callback called.
(lldb) break list
...
1.1: address = 0x000000018deb2000, unresolved, hit count = 0
That's an address breakpoint that we did NOT set. If you set an address breakpoint before running that didn't resolve to a section in a binary plus an offset, either because there was no binary at that address pre-run or there were more than one, then on run lldb won't set it for you. You have to re-enable it for it to be set.
Writing a trap into the executable is a dangerous thing to do. For instance, if lldb gets the address wrong and write the trap into some data in the program, it will have caused a subtle and hard to track down debugger-caused bug. So given we know libraries can slide around when you re-run, we don't automatically reset "by address" breakpoints.
The fact that by name breakpoints don't have this problem leads me to think the breakpoint trap just might not be getting inserted when this fails for you. We know that when we find a symbol, it will point to the beginning of an instruction, so it is safe, but that's not true for bare addresses.
If you know you are setting a pre-run breakpoint at some address in some shared library, you can tell lldb that by passing the --shlib
argument to break set
. On most systems, pre-run all the libraries overlap; that's the most common reason why we can't turn your address into a "offset from section A in binary B" form, and telling us which shared library to use resolves
that ambiguity.
@jimingham Thanks for your answer. But I executed the custom_command
command after running the program, and the breakpoint was marked as "resolved". The x86_64 architecture also has this problem. The following is the process of reproducing it with Xcode 16.0.
// main.m
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"Hello, World!");
}
return 0;
}
First, use Xcode to create a main
symbolic breakpoint, then run the program. After hitting the breakpoint, the disassembly is as follows:
test_lldb_script`main:
0x100000f40 <+0>: pushq %rbp
0x100000f41 <+1>: movq %rsp, %rbp
0x100000f44 <+4>: subq $0x20, %rsp
0x100000f48 <+8>: movl $0x0, -0x4(%rbp)
0x100000f4f <+15>: movl %edi, -0x8(%rbp)
0x100000f52 <+18>: movq %rsi, -0x10(%rbp)
-> 0x100000f56 <+22>: callq 0x100000f8a ; symbol stub for: objc_autoreleasePoolPush
0x100000f5b <+27>: movq %rax, -0x18(%rbp)
0x100000f5f <+31>: leaq 0xb2(%rip), %rdi ; @"Hello, World!"
0x100000f66 <+38>: movb $0x0, %al
0x100000f68 <+40>: callq 0x100000f7e ; symbol stub for: NSLog
0x100000f6d <+45>: movq -0x18(%rbp), %rdi
0x100000f71 <+49>: callq 0x100000f84 ; symbol stub for: objc_autoreleasePoolPop
0x100000f76 <+54>: xorl %eax, %eax
0x100000f78 <+56>: addq $0x20, %rsp
0x100000f7c <+60>: popq %rbp
0x100000f7d <+61>: retq
The subsequent steps are indicated by the console message (I omitted the other 13 breakpoint locations from the system framework):
(lldb) register read $rip
rip = 0x0000000100000f56 test_lldb_script`main + 22 at main.m:3:22
(lldb) breakpoint list
Current breakpoints:
1: name = 'main', locations = 14, resolved = 14, hit count = 1
1.1: where = test_lldb_script`main + 22 at main.m:4:22, address = 0x0000000100000f56, resolved, hit count = 1
......
(lldb) command script import /Users/fermichen/Desktop/My_Projects/HMLLDB/commands/MyScript.py
(lldb) custom_command 0x100000f6d
(lldb) breakpoint list
Current breakpoints:
1: name = 'main', locations = 14, resolved = 14, hit count = 1
1.1: where = test_lldb_script`main + 22 at main.m:4:22, address = 0x0000000100000f56, resolved, hit count = 1
......
2: address = test_lldb_script[0x0000000100000f6d], locations = 1, resolved = 1, hit count = 0
2.1: where = test_lldb_script`main + 45 at main.m:5:9, address = 0x0000000100000f6d, resolved, hit count = 0
(lldb) continue
Process 96934 resuming
Hello, World!
(lldb) register read $rip
rip = 0x0000000100000f6d test_lldb_script`main + 45 at main.m:5:9
(lldb) breakpoint list
Current breakpoints:
1: name = 'main', locations = 14, resolved = 14, hit count = 1
1.1: where = test_lldb_script`main + 22 at main.m:4:22, address = 0x0000000100000f56, resolved, hit count = 1
......
2: address = test_lldb_script[0x0000000100000f6d], locations = 1, resolved = 1, hit count = 1
2.1: where = test_lldb_script`main + 45 at main.m:5:9, address = 0x0000000100000f6d, resolved, hit count = 1
From the console message, we can see that after hitting breakpoint 2, there is no output of "hit breakpoint" and the callback function breakpoint_function_wrapper
is not executed.
If I switch to Xcode 15.2, the console will output "hit breakpoint" and breakpoint list
will display the callback function information:
(lldb) breakpoint list
......
2: address = test_lldb_script[0x0000000100003f6d], locations = 1, resolved = 1, hit count = 1
Breakpoint commands (Python):
MyScript.breakpoint_function_wrapper(frame, bp_loc, extra_args, internal_dict)
2.1: where = test_lldb_script`main + 45 at main.m:5:9, address = 0x0000000100003f6d, resolved, hit count = 1
Your break list output shows that in the failing case we don't add the script to the breakpoint at all. I tried this on an AS Mac with Xcode 16.0 and it worked correctly, the callback got registered, and was run when the breakpoint was hit.
I can't see how this could be target architecture specific, however.
I tried to start it in the terminal and was able to successfully register the callback function. The lldb version is the same. Maybe there is some configuration in my Xcode that I don't know about yet. I have to spend some time to check it.
I asked another developer to try it according to this issue, and he reproduced this problem.
In addition, I found that when using Xcode16.0, using time.sleep(0.1)
before calling SetScriptCallbackFunction
can solve this problem 🤔
When I use lldb python script, calling
SBBreakpoint.SetScriptCallbackFunction
does not work in some cases. This is my script:I made sure that the address entered is valid, but the
breakpoint_function_wrapper
function is not executed after hitting the breakpoint. In addition, when I create a breakpoint using another interfaceBreakpointCreateByName
,SetScriptCallbackFunction
worked:Environment: [sys version] macOS 15.0 Python 3.9.6 (default, Aug 9 2024, 14:24:13) [Clang 16.0.0 (clang-1600.0.26.3)] [LLDB version] lldb-1600.0.36.3 Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2) [Target triple] arm64-apple-ios- [Xcode version] 1600 (16A242d) [Model identifier] iPhone13,2 [iOS version] iOS 18.0.1