autoPatchelfHook: add keep_libc flag (#332617)

* autoPatchelfHook: add keep_libc flag

- Add keep_libc flag to disable the default libc handling. Intended
  to be used by systemd.
- Add autoPatchelfFlags to autoPatchelfHook for passing arguments to
  the autoPatchelf script

This reverts part of the change made in #307068 / 80be926.

Fixes #332533
This commit is contained in:
squalus
2024-08-14 02:54:27 -04:00
committed by GitHub
parent 1582d7624e
commit 0a3ed67ff6
3 changed files with 29 additions and 6 deletions
@@ -197,7 +197,7 @@ class Dependency:
found: bool = False # Whether it was found somewhere
def auto_patchelf_file(path: Path, runtime_deps: list[Path], append_rpaths: list[Path] = [], extra_args: list[str] = []) -> list[Dependency]:
def auto_patchelf_file(path: Path, runtime_deps: list[Path], append_rpaths: list[Path] = [], keep_libc: bool = False, extra_args: list[str] = []) -> list[Dependency]:
try:
with open_elf(path) as elf:
@@ -257,26 +257,36 @@ def auto_patchelf_file(path: Path, runtime_deps: list[Path], append_rpaths: list
# 1. If a candidate is an absolute path, it is already a
# valid dependency if that path exists, and nothing needs
# to be done. It should be an error if that path does not exist.
# 2. If a candidate is found in our library dependencies, that
# 2. If a candidate is found within libc, it should be dropped
# and resolved automatically by the dynamic linker, unless
# keep_libc is enabled.
# 3. If a candidate is found in our library dependencies, that
# dependency should be added to rpath.
# 3. If a candidate is found in libc, it will be correctly
# resolved by the dynamic linker automatically.
# 4. If all of the above fail, libc dependencies should still be
# considered found. This is in contrast to step 2, because
# enabling keep_libc should allow libc to be found in step 3
# if possible to preserve its presence in rpath.
#
# These conditions are checked in this order, because #2
# and #3 may both be true. In that case, we still want to
# add the dependency to rpath, as the original binary
# presumably had it and this should be preserved.
is_libc = (libc_lib / candidate).is_file()
if candidate.is_absolute() and candidate.is_file():
was_found = True
break
elif is_libc and not keep_libc:
was_found = True
break
elif found_dependency := find_dependency(candidate.name, file_arch, file_osabi):
rpath.append(found_dependency)
dependencies.append(Dependency(path, candidate, found=True))
print(f" {candidate} -> found: {found_dependency}")
was_found = True
break
elif (libc_lib / candidate).is_file():
elif is_libc and keep_libc:
was_found = True
break
@@ -306,6 +316,7 @@ def auto_patchelf(
recursive: bool = True,
ignore_missing: list[str] = [],
append_rpaths: list[Path] = [],
keep_libc: bool = False,
extra_args: list[str] = []) -> None:
if not paths_to_patch:
@@ -319,7 +330,7 @@ def auto_patchelf(
dependencies = []
for path in chain.from_iterable(glob(p, '*', recursive) for p in paths_to_patch):
if not path.is_symlink() and path.is_file():
dependencies += auto_patchelf_file(path, runtime_deps, append_rpaths, extra_args)
dependencies += auto_patchelf_file(path, runtime_deps, append_rpaths, keep_libc, extra_args)
missing = [dep for dep in dependencies if not dep.found]
@@ -377,6 +388,12 @@ def main() -> None:
type=Path,
help="Paths to append to all runtime paths unconditionally",
)
parser.add_argument(
"--keep-libc",
dest="keep_libc",
action="store_true",
help="Attempt to search for and relink libc dependencies.",
)
parser.add_argument(
"--extra-args",
# Undocumented Python argparse feature: consume all remaining arguments
@@ -398,6 +415,7 @@ def main() -> None:
args.recursive,
args.ignore_missing,
append_rpaths=args.append_rpaths,
keep_libc=args.keep_libc,
extra_args=args.extra_args)
@@ -58,11 +58,13 @@ autoPatchelf() {
local appendRunpathsArray=( "${appendRunpaths[@]}" )
local runtimeDependenciesArray=( "${runtimeDependencies[@]}" )
local patchelfFlagsArray=( "${patchelfFlags[@]}" )
local autoPatchelfFlagsArray=( "${autoPatchelfFlags[@]}" )
else
readarray -td' ' ignoreMissingDepsArray < <(echo -n "$autoPatchelfIgnoreMissingDeps")
local appendRunpathsArray=($appendRunpaths)
local runtimeDependenciesArray=($runtimeDependencies)
local patchelfFlagsArray=($patchelfFlags)
local autoPatchelfFlagsArray=($autoPatchelfFlags)
fi
# Check if ignoreMissingDepsArray contains "1" and if so, replace it with
@@ -85,6 +87,7 @@ autoPatchelf() {
"${extraAutoPatchelfLibs[@]}" \
--runtime-dependencies "${runtimeDependenciesArray[@]/%//lib}" \
--append-rpaths "${appendRunpathsArray[@]}" \
"${autoPatchelfFlagsArray[@]}" \
--extra-args "${patchelfFlagsArray[@]}"
}
@@ -336,6 +336,8 @@ stdenv.mkDerivation (finalAttrs: {
]
;
autoPatchelfFlags = [ "--keep-libc" ];
buildInputs =
[
libxcrypt