The runtime linker needs to include a path to itself in the link map
it exports to the debugger. It currently has two choices, it can use
a compiled-in path (/libexec/ld-elf.so.1) or it can use the path stored
in the interpreter path in the binary being executed. The runtime linker
currently prefers the second. However, this is always wrong for compat32
binaries since the binary specifies the path of rtld on a 32-bit system
(/libexec/ld-elf.so.1) instead of the actual path (/libexec/ld-elf32.so.1).
For now, always assume the compiled in path (/libexec/ld-elf32.so.1) as
the rtld path and ignore the path in the binary for the 32-bit runtime
linker.
Details
gdb from the devel/gdb port can now properly examine cores from a 32-bit
(i386) process on amd64. It can also attach to running 32-bit processes
and start a new process for a 32-bit binary. Previously it emitted
warnings about ld-elf.so.1 for the first two cases (though it did work
aside from rtld symbols being wrong) and the third case resulted in a
segfault during early startup.
The in-tree gdb isn't able to grok 32-bit core dumps on amd64, but
otherwise appears to be similar.
Diff Detail
- Repository
- rS FreeBSD src repository - subversion
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
Use of the compiled-in path has the unfortunate consequence of sometimes being wrong. This is mostly true when somebody debugs rtld and builds the special binaries using the ld -I <path>.
It would be useful, and more correct, to try the vn_fullpath(9) before falling back to the compiled-in path. I see that this is currently problematic, I do not see any way to access the interpreter path except using the KERN_PROC_VMMAP, which might be an overkill for the rtld startup.
We could save the path that the kernel uses during execve and export that via a new KERN_PROC_INTERP per-process sysctl node. This would not be correct if the linker were subsequently removed or renamed, but all of the other methods (except for the vn_fullpath) break for those edge cases as well. The idea would be to prefer KERN_PROC_INTERP and fall back to the current hack of reading the binary only if that sysctl failed.
If using the kernel assist in this way, I do not like additional sysctl, as well I do not think it is needed. Right way to provide interpreter path is to use AT_INTERPPATH aux vector, similar to AT_EXECPATH.
So I still think that the workaround your pasted is fine for now, and if really feeling the need, I will code AT_INTERPPATH.