-
-
Notifications
You must be signed in to change notification settings - Fork 482
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
Section re-ordering confuses strip
#10
Comments
lib.so -> strip -> patchelf -> ldconfig
lib.so -> patchelf -> strip
lib.so -> patchelf -> ldconfig
|
I'm seeing this error as well, which makes it impossible to run |
FWIW this problem affects me too, via https://github.com/schmir/bbfreeze |
Yeah, I'm seeing something similar. On CentOS 7 strip (2.23.52.0.1-30.el7_1.2) I don't get that exact error, but patchelf 0.9 followed by strip does produce a broken binary. In the post-patchelf'ed binary, DT_STRTAB seems to end up in the first page of the executable, which includes references to things like needed libraries.
but after running strip on it , they're no longer in that position of the file:
However, when I've been walking through the dynamic linker code in gdb, it seems that in
I'm still digging a bit, hoping to find at least a workaround. Unfortunately I need to produce unstripped binaries to hand to our release engineering process where do the final strip before shipping, so right now trying to use patchelf to fix the rpath inside is resulting in binaries that can't be stripped. |
OK, I dug into this more. The problem doesn't seem specific to the re-ordering, but that the
The Now after running patchelf 0.9 things get odd:
so now there are three LOAD segments. The first
...it starts in the first Anyway, then when we run
...notice that the
...and thus ld-linux.so can no longer find our dependencies. The will appear to be there if you look at the file with objdump since they're present in the file, but they're no longer in a section of the file that gets memory mapped in at |
I'm having a hard time with this issue as well. @mitchblank Did you find a work around the issue since you narrowed it down ? Or do you just don't strip your executable after patchelf ? |
No, I didn't find a workaround. For now I'm pursuing other options. |
Any idea how to fix this issue? The problem is also affecting binary wheel packages for Python using the manylinux1 specification ( |
I made some progress on this tonight; here are the results of my investigations:
|
Thanks @staticfloat, I will try to test your branch in the manylinux1 / Python workflow sometimes this week (if nobody does it first). |
Thanks, Elliot! That's great news. I see this error message |
I tried to build a manylinux1 wheel (fixed by your version of patchelf) for the lxml project (that uses external libraries lxml2 and libxslt). Here is the kind of errors I got prior to using your fix when trying to strip the resulting .so files:
with your fix I get the following output:
the I can put the resulting binaries (after patchelf but before strip) online if that helps. |
If I could get the original |
Oh, also, if you're using a docker image to do your development inside of, I'd like to use that as well, as there can be a lot of different pieces in this puzzle (version of binutils, etc..) and I'd like to eliminate as many variables as possible. |
The docker image is https://github.com/pypa/manylinux Today I don't have access on the computer I used yesterday. Let me generate the binaries again. |
Here are the precise
The original binaries can be found in this https://dl.dropboxusercontent.com/u/5743203/tmp/lxml-3.7.2-cp36-cp36m-linux_x86_64.whl Here are the original system libs (from /usr/local/lib) that are being grafted into the package using patchelf: https://dl.dropboxusercontent.com/u/5743203/tmp/libexslt.so.0 Here is the resulting package (with your fix): and here is the copy of the same results without your fix in patchelf: |
Thanks @ogrisel, that was really helpful! When I'm testing this out using this docker repo, the scripts in there will download everything you need to play around with this stuff, in case for some reason you want to. I don't have an easy way to test that the libraries that |
I think it's worth asking the |
@matthew-brett do you think you could adapt your manylinux1 testing infrastructure to ensure that this patchelf fix does not introduce a regression on all the manylinux1 packages you tested in the past? |
Olivier - just to clarify - you want me to try building and testing a few wheels with the patchelf fix you refer to here : pypa/manylinux#78 (comment) ? |
Yes I was thinking about leveraging https://github.com/matthew-brett/manylinux-builds to check that the branch https://github.com/staticfloat/patchelf/tree/sf/pr_10 does not cause a regression on a variety of packages at once. However know I realize that the I guess some manual testing is required then. |
Hmm - I guess we could modify the upload container for the manylinux-builds .travis.yml, and then run manylinux-testing, reading from that new container... |
Is this issue fixed by #117 ? |
As @darealshinji mentioned, I believe this is fixed by #117. Would a maintainer mind closing it if this is indeed true? Also, as we've seen, there are a lot of tools depending on this new, correct behavior. Are there plans to cut a new release of |
Is a new release of |
This is not fixed. With the latest version, even with #127 applied, when I create a binary with rpath larger than it was before (e.g. via |
This is based on Jan Tojnar's work in NixOS#31228. When patchelf has to grow rpath beyond original capacity, it sets dontStrip, to work around NixOS/patchelf#10.
startPage is adjusted unconditionally for all executables. This results in incorrect addresses assigned to INTERP and LOAD program headers, which breaks patched executable. Adjusting startPage variable only when startOffset > startPage should fix this. This change is related to the issue NixOS#10 Signed-off-by: Ed Bartosh <[email protected]>
Cool work around:
|
@staticfloat Has this issue been resolved? Is there a related PR that fixes this issue? |
It looks to me like #117 fixed this. |
Excellent! Are there plans for a new stable release of |
It doesn't look like there's been a release for quite a while; we use |
The current approach to changing sections in ET_DYN executables is to move the INTERP section to the end of the file. +This means changing PT_PHDR to add an extra PT_LOAD section so that the new section is mmaped into memory by the elf loader in the kernel. In order to extend PHDR, this means moving it to the end of the file. Its documented in BUGS there is a kernel 'bug' which means that if you have holes in memory between the base load address and the PT_LOAD segment that contains PHDR, it will pass an incorrect PHDR address to ld.so and fail to load the binary, segfaulting. To avoid this, the code currently inserts space into the binary to ensure that when loaded into memory there are no holes between the PT_LOAD sections. This inflates the binaries by many MBs in some cases. Whilst we could make them sparse, there is a second issue which is that strip can fail to process these binaries: $ strip fixincl Not enough room for program headers, try linking with -N [.note.ABI-tag]: Bad value This turns out to be due to libbfd not liking the relocated PHDR section either (NixOS#10). Instead this patch implements a different approach, leaving PHDR where it is but extending it in place to allow addition of a new PT_LOAD section. This overwrites sections in the binary but those get moved to the end of the file in the new PT_LOAD section. This is based on patches linked from the above github issue, however whilst the idea was good, the implementation wasn't correct and they've been rewritten here. Signed-off-by: Richard Purdie <[email protected]> (cherry picked from commit c4deb5e) Signed-off-by: Claudio Matsuoka <[email protected]>
startPage is adjusted unconditionally for all executables. This results in incorrect addresses assigned to INTERP and LOAD program headers, which breaks patched executable. Adjusting startPage variable only when startOffset > startPage should fix this. This change is related to the issue NixOS#10 Signed-off-by: Ed Bartosh <[email protected]>
startPage is adjusted unconditionally for all executables. This results in incorrect addresses assigned to INTERP and LOAD program headers, which breaks patched executable. Adjusting startPage variable only when startOffset > startPage should fix this. This change is related to the issue NixOS#10 Signed-off-by: Ed Bartosh <[email protected]>
startPage is adjusted unconditionally for all executables. This results in incorrect addresses assigned to INTERP and LOAD program headers, which breaks patched executable. Adjusting startPage variable only when startOffset > startPage should fix this. This change is related to the issue NixOS#10 Signed-off-by: Ed Bartosh <[email protected]> (cherry picked from commit 1cc234f) Signed-off-by: Claudio Matsuoka <[email protected]>
Running
patchelf
to enlarge my RUNPATH entry causes my section headers to change from this:To this:
This confuses tools such as
strip
because they use a header offset of 0 as an error code; here's the relevant functionassign_file_positions_for_non_load_sections
in elf.c from binutils. Running e.g.gdb --args strip -g my_binary
, and setting a breakpoint at that position shows that we get a valid section, but since itsfilepos
is equal to zero, binutils ignores it and continues on, getting confused. Note that evenreadelf
gets a little confused by this, as it doesn't even list the.dynsym
segment:I theorize that if we keep the
.interp
section at the beginning of the file, we might be able to still use tools such asstrip
, but I don't actually know. Is there an easy way to permute the order of headers thatpatchelf
outputs? If you can just point me in the direction of how to do this, I can submit a PR.The text was updated successfully, but these errors were encountered: