patchelf icon indicating copy to clipboard operation
patchelf copied to clipboard

Allow more modifications of .gnu.version_r

Open martinetd opened this issue 2 years ago • 1 comments

This is sort of a follow-up on #84 which added support for .gnu.version_r in --replace-needed.

Is your feature request related to a problem? Please describe.

My usecase for this is a binary lib I absolutely cannot replace that was compiled for a glibc too recent for the system I need to run it on. It ends up with something like this:

$ objdump -x badlib
...
Version References:
  required from ld-linux-aarch64.so.1:
    0x06969197 0x00 03 GLIBC_2.17
  required from libc.so.6:
    0x069691b3 0x00 04 GLIBC_2.33
    0x06969197 0x00 02 GLIBC_2.17
...
$ nm -D libgbm.so | grep 2.33
                 U fstat@GLIBC_2.33

on a system with glibc 2.32, so without that fstat, so it obviously won't run.

Describe the solution you'd like

The best possible thing I can think of would be to have a partial replace-needed, so I could keep libc for whatever it finds useful in GLIBC_2.17 and replace GLIBC_2.33 with another lib. That would keep a versioned symbol for fstat (no risk of confusion) with a minimal change.

Something I thought would be simpler is to have --clear-symbol-version remove the version in .gnu.version_r if there are no other symbol with that version -- I've looked a bit at the code and it's probably possible, although would be messy e.g.

  • in clearSymbolVersions remember all distinct versyms[i] we've seen just before clearing it
  • for all of these check if they have other users, if not remember them for cleanup
  • if there is any to cleanup reproduce what is done in replaceNeeded and skip list element, truncate list early or remove lib completely as appropriate. This last part would probably be annoying to get right all the time...

Describe alternatives you've considered I've tried a few things:

  • I've tried replace-needed as is, replacing libc.so.6 with a wrapper lib, but things just segfault accessing symbols defined in the wrapper... I'm probably missing something obvious there.
  • I've managed to work around it manually by handcrafting the .gnu.version_r in a hex editor so it no longer requires GLIBC_2.33 there, patchelf --clear-symbol-version fstat to remove the binding to fstat, and patchelf --add-needed libc_2.33_compat.so to provide the fstat symbol definition without a version. This actually works, but I'd rather no have a "get a human to modify some hex string" everytime we need to upgrade it.

Additional context Happy to try any other solution if you have other ideas -- I'm throwing this here but I likely won't have time to implement anything before a few weeks, and it's just as possible we stay with my temporary solution saying it's not getting updated often anyway, but if there's a proper way of doing this I'm all ears. The real ideal solution would be to get them to provide sources or at least a build for the platform I'm targeting, but that's quite unlikely to happen...

Thanks!

martinetd avatar Mar 18 '22 07:03 martinetd