-
-
Notifications
You must be signed in to change notification settings - Fork 502
Fix --remove-needed not updating .gnu.version_r #596
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Fix --remove-needed not updating .gnu.version_r #596
Conversation
Try to preserve the section's layout (skipping rather than trimming unused entries when possible).
Orphan symbolsOriginal problemI started on FreeBSD 14.2, with a simple C++ program: #include <iostream>
int main(int argc, char ** argv)
{
std::cerr << "Plouf" << std::endl;
return 0;
} This program was first compiled with the system After adding a custom I can resolve this crash either by:
However
0x0000000000000001 NEEDED Shared library: [libc++.so.1]
- 0x0000000000000001 NEEDED Shared library: [libcxxrt.so.1]
0x0000000000000001 NEEDED Shared library: [libm.so.5] But the entry still in
(here we see that the Patching patchelfWith this PR's patch, we get our
(note the offsets shifted by -0x10 due to the "first entry gets trimmed" rule, and offsets 0x20 and 0x30 not being reused, because the ghost auxiliary entries CXXABI_1.3 and GLIBCXX_3.4 still sit there). The binary then works as expected which was our primary goal. However… The internal orphan problemAlthough the binary runs well, when Both But binutils will fail gracefully, making it appear as an unversioned / corrupted symbol:
(note the However FreeBSD's readelf will stop reading those sections as soon as the first error is encountered:
(and it warns twice of "readelf: invalid versym version index 3", once per section it then stops dumping) So… Question for this PRThis partial test (limited to FreeBSD) shows that, at least on 1 platform, we can rely on the runtime loader's robustness to handle dangerously formed binaries (fallbacking to an unversioned symbol when not finding the version node's name?), Are there use cases where this PR could prove useful as is (and particularly: on NixOS, or with standard Linux distribs) |
@Ma27 Any thoughts on this? |
Fixes #214
Constructed after reading @njsmith's great work on #84 / #85 (thus some variable names being the same).
Technical considerations
Even if the section is theorically a compact array of Elf_Verneed and Elf_Vernaux entries (with the number of top Elf_Verneed entries being written in 1 or 2 places) there is redundancy with a chained list where each entry has the next entry's offset in its
vn_next
field (with a value of0
ending the list… thus giving a second way to know we have reached the end, in addition to the count field(s)).So there could be holes in the section (when
vn_next > sizeof(ElfXX_Verneed + its attached ElfXX_Vernauxs)
), and maybe (admittedly stealthy) data to preserve in those holes.To adapt to that uncertainty, the patch tries to be as conservative as possible in its writes:
instead of shifting the last entries to occupy the place let by the removed ones, we simply use the previous entry's
vn_next
to jump over the removed one (except on the first entry, which has no previous, but is pointed at by the header'ssh_offset
).To be done
Two questions still make it a work in progress (in addition to a firm code review, because I'm not familiar at all with ELF):
this question will be handled in the first comment, to avoid polluting this description once resolved