In FreeBSD 15.0 and later when lldb is doing JIT it may pick the wrong address for functions that are available in both libc and libsys.
Steps to reproduce:
- Put the following 3 lines into a file named
empty.c:
int main(void) {
return 0;
}
- Compile the program:
clang -O0 -g -o empty empty.c
- Run lldb:
lldb empty
- Execute the following lldb commands:
4.1. breakpoint set -n main
4.2. run
4.3. p (uint32_t)getuid()
The observed outcome will be one of these two:
A. The value 4294967295 is printed, which is incorrect. That value is -1 interpreted as an unsigned 32-bit integer.
In this case instead of finding an address for getuid() in libsys an address in libc is found and the wrong function gets executed. The symbol getuid is present in both libc.so.7 and libsys.so.7 which is also the case for other syscalls (or all of them?).
In the logs of lldb (when enabled) one can see these:
Process::CanJIT pid 2492 allocation test passed, CanJIT () is true
IRExecutionUnit::getSymbolAddress(Name="getuid") = 83944f90
The address value matches the address of getuid in /lib/libc.so.7.
B. The error message error: Can't evaluate the expression without a running target due to: Interpreter doesn't handle one of the expression's opcodes is displayed, which is deceptive.
The real problem is that when performing JIT lldb tried to allocate memory via mmap() in the process being debugged and failed.
In the logs of lldb (when enabled) one can see these:
Process::CanJIT pid 1677 allocation test failed, CanJIT () is false: unable to allocate 4096 bytes of memory with permissions rwx
ProcessGDBRemote::DoAllocateMemory no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?
The wrong address is picked for mmap() (in lldb_private::InferiorCallMmap()) and as a result the wrong function gets executed. The address is again from libc instead of from libsys.
The problem was observed with lldb version 19.1.7 on FreeBSD 15.0-RELEASE-p2 and FreeBSD 16.0-CURRENT on both amd64 (x86_64) and arm64.
In FreeBSD 15.0 and later when lldb is doing JIT it may pick the wrong address for functions that are available in both
libcandlibsys.Steps to reproduce:
empty.c:clang -O0 -g -o empty empty.clldb empty4.1.
breakpoint set -n main4.2.
run4.3.
p (uint32_t)getuid()The observed outcome will be one of these two:
A. The value 4294967295 is printed, which is incorrect. That value is -1 interpreted as an unsigned 32-bit integer.
In this case instead of finding an address for
getuid()inlibsysan address inlibcis found and the wrong function gets executed. The symbolgetuidis present in bothlibc.so.7andlibsys.so.7which is also the case for other syscalls (or all of them?).In the logs of lldb (when enabled) one can see these:
The address value matches the address of
getuidin/lib/libc.so.7.B. The error message
error: Can't evaluate the expression without a running target due to: Interpreter doesn't handle one of the expression's opcodesis displayed, which is deceptive.The real problem is that when performing JIT lldb tried to allocate memory via
mmap()in the process being debugged and failed.In the logs of lldb (when enabled) one can see these:
The wrong address is picked for
mmap()(inlldb_private::InferiorCallMmap()) and as a result the wrong function gets executed. The address is again fromlibcinstead of fromlibsys.The problem was observed with lldb version 19.1.7 on FreeBSD 15.0-RELEASE-p2 and FreeBSD 16.0-CURRENT on both amd64 (x86_64) and arm64.