depfixer: convert unused printing code to debugging functions

When installing with 'meson install --quiet' I'd get the following output:
This file does not have an rpath.
This file does not have a runpath.

(It turns out that of the couple hundred of binaries that are installed,
this message was generated for /usr/lib/systemd/boot/efi/linuxx64.elf.stub.)

There doesn't seem to be any good reason for this output by default. But those
functions can still be used for debugging. Under a debugger, returning the
string is just as useful as printing it, but more flexible. So let's suppress
printing of anything by default, but keep the extractor functions.

The code was somewhat inconsistent wrt. to when .decode() was done. But it
seems that we'll get can expect a decodable text string in all cases, so
just call .decode() everywhere, because it's nicer to print decoded strings.
pull/9396/head
Zbigniew Jędrzejewski-Szmek 4 years ago
parent da522efc93
commit c2f1d91b8a
  1. 9
      mesonbuild/mesonlib/universal.py
  2. 54
      mesonbuild/scripts/depfixer.py

@ -87,6 +87,7 @@ __all__ = [
'exe_exists', 'exe_exists',
'expand_arguments', 'expand_arguments',
'extract_as_list', 'extract_as_list',
'generate_list',
'get_compiler_for_source', 'get_compiler_for_source',
'get_filenames_templates_dict', 'get_filenames_templates_dict',
'get_library_dirs', 'get_library_dirs',
@ -1918,6 +1919,14 @@ def run_once(func: T.Callable[..., _T]) -> T.Callable[..., _T]:
return wrapper return wrapper
def generate_list(func: T.Callable[..., T.Generator[_T, None, None]]) -> T.Callable[..., T.List[_T]]:
@wraps(func)
def wrapper(*args: T.Any, **kwargs: T.Any) -> T.List[_T]:
return list(func(*args, **kwargs))
return wrapper
class OptionOverrideProxy(collections.abc.MutableMapping): class OptionOverrideProxy(collections.abc.MutableMapping):
'''Mimic an option list but transparently override selected option '''Mimic an option list but transparently override selected option

@ -21,7 +21,7 @@ import shutil
import subprocess import subprocess
import typing as T import typing as T
from ..mesonlib import OrderedSet from ..mesonlib import OrderedSet, generate_list
SHT_STRTAB = 3 SHT_STRTAB = 3
DT_NEEDED = 1 DT_NEEDED = 1
@ -243,14 +243,14 @@ class Elf(DataSizes):
if e.d_tag == 0: if e.d_tag == 0:
break break
def print_section_names(self) -> None: @generate_list
def get_section_names(self) -> T.Generator[str, None, None]:
section_names = self.sections[self.e_shstrndx] section_names = self.sections[self.e_shstrndx]
for i in self.sections: for i in self.sections:
self.bf.seek(section_names.sh_offset + i.sh_name) self.bf.seek(section_names.sh_offset + i.sh_name)
name = self.read_str() yield self.read_str().decode()
print(name.decode())
def print_soname(self) -> None: def get_soname(self) -> T.Optional[str]:
soname = None soname = None
strtab = None strtab = None
for i in self.dynamic: for i in self.dynamic:
@ -259,10 +259,9 @@ class Elf(DataSizes):
if i.d_tag == DT_STRTAB: if i.d_tag == DT_STRTAB:
strtab = i strtab = i
if soname is None or strtab is None: if soname is None or strtab is None:
print("This file does not have a soname") return None
return
self.bf.seek(strtab.val + soname.val) self.bf.seek(strtab.val + soname.val)
print(self.read_str()) return self.read_str().decode()
def get_entry_offset(self, entrynum: int) -> T.Optional[int]: def get_entry_offset(self, entrynum: int) -> T.Optional[int]:
sec = self.find_section(b'.dynstr') sec = self.find_section(b'.dynstr')
@ -273,33 +272,28 @@ class Elf(DataSizes):
return res return res
return None return None
def print_rpath(self) -> None: def get_rpath(self) -> T.Optional[str]:
offset = self.get_entry_offset(DT_RPATH) offset = self.get_entry_offset(DT_RPATH)
if offset is None: if offset is None:
print("This file does not have an rpath.") return None
else: self.bf.seek(offset)
self.bf.seek(offset) return self.read_str().decode()
print(self.read_str())
def print_runpath(self) -> None: def get_runpath(self) -> T.Optional[str]:
offset = self.get_entry_offset(DT_RUNPATH) offset = self.get_entry_offset(DT_RUNPATH)
if offset is None: if offset is None:
print("This file does not have a runpath.") return None
else: self.bf.seek(offset)
self.bf.seek(offset) return self.read_str().decode()
print(self.read_str())
def print_deps(self) -> None: @generate_list
def get_deps(self) -> T.Generator[str, None, None]:
sec = self.find_section(b'.dynstr') sec = self.find_section(b'.dynstr')
deps = []
for i in self.dynamic: for i in self.dynamic:
if i.d_tag == DT_NEEDED: if i.d_tag == DT_NEEDED:
deps.append(i) offset = sec.sh_offset + i.val
for i in deps: self.bf.seek(offset)
offset = sec.sh_offset + i.val yield self.read_str().decode()
self.bf.seek(offset)
name = self.read_str()
print(name)
def fix_deps(self, prefix: bytes) -> None: def fix_deps(self, prefix: bytes) -> None:
sec = self.find_section(b'.dynstr') sec = self.find_section(b'.dynstr')
@ -391,11 +385,9 @@ class Elf(DataSizes):
return None return None
def fix_elf(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: T.Optional[bytes], verbose: bool = True) -> None: def fix_elf(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: T.Optional[bytes], verbose: bool = True) -> None:
with Elf(fname, verbose) as e: if new_rpath is not None:
if new_rpath is None: with Elf(fname, verbose) as e:
e.print_rpath() # note: e.get_rpath() and e.get_runpath() may be useful
e.print_runpath()
else:
e.fix_rpath(rpath_dirs_to_remove, new_rpath) e.fix_rpath(rpath_dirs_to_remove, new_rpath)
def get_darwin_rpaths_to_remove(fname: str) -> T.List[str]: def get_darwin_rpaths_to_remove(fname: str) -> T.List[str]:

Loading…
Cancel
Save