mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-12 06:57:57 +04:00
tools/meson: update to 1.11.2
Remove upstreamed patch and refresh others. Signed-off-by: Rosen Penev <rosenp@gmail.com> Link: https://github.com/openwrt/openwrt/pull/24560 Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
This commit is contained in:
1 parent
8d3e35e763
commit
fc636dac86
4 files changed
+59
-219
No files matched your search
@@ -1,11 +1,11 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=meson
|
||||
PKG_VERSION:=1.6.1
|
||||
PKG_VERSION:=1.11.2
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/mesonbuild/meson/releases/download/$(PKG_VERSION)
|
||||
PKG_HASH:=1eca49eb6c26d58bbee67fd3337d8ef557c0804e30a6d16bfdf269db997464de
|
||||
PKG_HASH:=698feae069cef3ecd4d7aaf281d7df359bdfcf555a9a1564383d3b913fa8a736
|
||||
|
||||
PKG_MAINTAINER:=Andre Heider <a.heider@gmail.com>
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
From 8586a5eff0c117c627fe3f71003dd30e3785796a Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Sat, 11 Oct 2025 01:48:51 +0200
|
||||
Subject: [PATCH] depfixer: zero-out rpath entry string on removing entry
|
||||
|
||||
While investigating a reproducible problem with a binary compiled with
|
||||
Meson, it was notice that the RPATH entry was never removed.
|
||||
|
||||
By comparing the binary from 2 different build system it was observed
|
||||
that altough the RPATH entry was removed (verified by the readelf -d
|
||||
command) the actual path was still present causing 2 different binary.
|
||||
|
||||
Going deeper in the Meson build process, it was discovered that
|
||||
remove_rpath_entry only deletes the entry in the '.dynamic' section but
|
||||
never actually 'clean' (or better say zero-out) the path from the
|
||||
.dynstr section producing binary dependendt of the build system.
|
||||
|
||||
To address this, introduce a new helper to to zero-out the entry from
|
||||
the .dynstr section permitting to produce REAL reproducible binary.
|
||||
|
||||
Additional logic was needed to handle GCC linker optimization for dynstr
|
||||
table where the rpath string might be reused for other dym function
|
||||
string. The setion that is actually removed is filled with 'X' following
|
||||
patchelf behaviour.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
mesonbuild/scripts/depfixer.py | 79 ++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 79 insertions(+)
|
||||
|
||||
--- a/mesonbuild/scripts/depfixer.py
|
||||
+++ b/mesonbuild/scripts/depfixer.py
|
||||
@@ -31,8 +31,12 @@ class DataSizes:
|
||||
p = '<'
|
||||
else:
|
||||
p = '>'
|
||||
+ self.Char = p + 'c'
|
||||
+ self.CharSize = 1
|
||||
self.Half = p + 'h'
|
||||
self.HalfSize = 2
|
||||
+ self.Section = p + 'h'
|
||||
+ self.SectionSize = 2
|
||||
self.Word = p + 'I'
|
||||
self.WordSize = 4
|
||||
self.Sword = p + 'i'
|
||||
@@ -71,6 +75,24 @@ class DynamicEntry(DataSizes):
|
||||
ofile.write(struct.pack(self.Sword, self.d_tag))
|
||||
ofile.write(struct.pack(self.Word, self.val))
|
||||
|
||||
+class DynsymEntry(DataSizes):
|
||||
+ def __init__(self, ifile: T.BinaryIO, ptrsize: int, is_le: bool) -> None:
|
||||
+ super().__init__(ptrsize, is_le)
|
||||
+ is_64 = ptrsize == 64
|
||||
+ self.st_name = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
|
||||
+ if is_64:
|
||||
+ self.st_info = struct.unpack(self.Char, ifile.read(self.CharSize))[0]
|
||||
+ self.st_other = struct.unpack(self.Char, ifile.read(self.CharSize))[0]
|
||||
+ self.st_shndx = struct.unpack(self.Section, ifile.read(self.SectionSize))[0]
|
||||
+ self.st_value = struct.unpack(self.Addr, ifile.read(self.AddrSize))[0]
|
||||
+ self.st_size = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0]
|
||||
+ else:
|
||||
+ self.st_value = struct.unpack(self.Addr, ifile.read(self.AddrSize))[0]
|
||||
+ self.st_size = struct.unpack(self.Word, ifile.read(self.WordSize))[0]
|
||||
+ self.st_info = struct.unpack(self.Char, ifile.read(self.CharSize))[0]
|
||||
+ self.st_other = struct.unpack(self.Char, ifile.read(self.CharSize))[0]
|
||||
+ self.st_shndx = struct.unpack(self.Section, ifile.read(self.SectionSize))[0]
|
||||
+
|
||||
class SectionHeader(DataSizes):
|
||||
def __init__(self, ifile: T.BinaryIO, ptrsize: int, is_le: bool) -> None:
|
||||
super().__init__(ptrsize, is_le)
|
||||
@@ -115,6 +137,8 @@ class Elf(DataSizes):
|
||||
self.verbose = verbose
|
||||
self.sections: T.List[SectionHeader] = []
|
||||
self.dynamic: T.List[DynamicEntry] = []
|
||||
+ self.dynsym: T.List[DynsymEntry] = []
|
||||
+ self.dynsym_strings: T.List[str] = []
|
||||
self.open_bf(bfile)
|
||||
try:
|
||||
(self.ptrsize, self.is_le) = self.detect_elf_type()
|
||||
@@ -122,6 +146,8 @@ class Elf(DataSizes):
|
||||
self.parse_header()
|
||||
self.parse_sections()
|
||||
self.parse_dynamic()
|
||||
+ self.parse_dynsym()
|
||||
+ self.parse_dynsym_strings()
|
||||
except (struct.error, RuntimeError):
|
||||
self.close_bf()
|
||||
raise
|
||||
@@ -232,6 +258,23 @@ class Elf(DataSizes):
|
||||
if e.d_tag == 0:
|
||||
break
|
||||
|
||||
+ def parse_dynsym(self) -> None:
|
||||
+ sec = self.find_section(b'.dynsym')
|
||||
+ if sec is None:
|
||||
+ return
|
||||
+ self.bf.seek(sec.sh_offset)
|
||||
+ for i in range(sec.sh_size // sec.sh_entsize):
|
||||
+ e = DynsymEntry(self.bf, self.ptrsize, self.is_le)
|
||||
+ self.dynsym.append(e)
|
||||
+
|
||||
+ def parse_dynsym_strings(self) -> None:
|
||||
+ sec = self.find_section(b'.dynstr')
|
||||
+ if sec is None:
|
||||
+ return
|
||||
+ for i in self.dynsym:
|
||||
+ self.bf.seek(sec.sh_offset + i.st_name)
|
||||
+ self.dynsym_strings.append(self.read_str().decode())
|
||||
+
|
||||
@generate_list
|
||||
def get_section_names(self) -> T.Generator[str, None, None]:
|
||||
section_names = self.sections[self.e_shstrndx]
|
||||
@@ -353,12 +396,48 @@ class Elf(DataSizes):
|
||||
self.bf.write(new_rpath)
|
||||
self.bf.write(b'\0')
|
||||
|
||||
+ def clean_rpath_entry_string(self, entrynum: int) -> None:
|
||||
+ # Get the rpath string
|
||||
+ offset = self.get_entry_offset(entrynum)
|
||||
+ self.bf.seek(offset)
|
||||
+ rpath_string = self.read_str().decode()
|
||||
+ reused_str = ''
|
||||
+
|
||||
+ # Inspect the dyn strings and check if our rpath string
|
||||
+ # ends with one of them.
|
||||
+ # This is to handle a subtle optimization of the linker
|
||||
+ # where one of the dyn function name offset in the dynstr
|
||||
+ # table might be set at the an offset of the rpath string.
|
||||
+ # Example:
|
||||
+ #
|
||||
+ # rpath offset = 1314 string = /usr/lib/foo
|
||||
+ # dym function offset = 1322 string = foo
|
||||
+ #
|
||||
+ # In the following case, the dym function string offset is
|
||||
+ # placed at the offset +10 of the rpath.
|
||||
+ # To correctly clear the rpath entry AND keep normal
|
||||
+ # functionality of this optimization (and the binary),
|
||||
+ # parse the maximum string we can remove from the rpath entry.
|
||||
+ #
|
||||
+ # Since strings MUST be null terminated, we can always check
|
||||
+ # if the rpath string ends with the dyn function string and
|
||||
+ # calculate what we can actually remove accordingly.
|
||||
+ for dynsym_string in self.dynsym_strings:
|
||||
+ if rpath_string.endswith(dynsym_string):
|
||||
+ if len(dynsym_string) > len(reused_str):
|
||||
+ reused_str = dynsym_string
|
||||
+
|
||||
+ # Seek back to start of string
|
||||
+ self.bf.seek(offset)
|
||||
+ self.bf.write(b'X' * (len(rpath_string) - len(reused_str)))
|
||||
+
|
||||
def remove_rpath_entry(self, entrynum: int) -> None:
|
||||
sec = self.find_section(b'.dynamic')
|
||||
if sec is None:
|
||||
return None
|
||||
for (i, entry) in enumerate(self.dynamic):
|
||||
if entry.d_tag == entrynum:
|
||||
+ self.clean_rpath_entry_string(entrynum)
|
||||
rpentry = self.dynamic[i]
|
||||
rpentry.d_tag = 0
|
||||
self.dynamic = self.dynamic[:i] + self.dynamic[i + 1:] + [rpentry]
|
||||
+7
-6
@@ -15,10 +15,10 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
|
||||
--- a/mesonbuild/environment.py
|
||||
+++ b/mesonbuild/environment.py
|
||||
@@ -999,3 +999,10 @@ class Environment:
|
||||
|
||||
def has_exe_wrapper(self) -> bool:
|
||||
return self.exe_wrapper and self.exe_wrapper.found()
|
||||
@@ -632,3 +632,10 @@ class Environment:
|
||||
machines = self.machines.miss_defaulting()
|
||||
machines.build = detect_machine_info(compilers)
|
||||
self.machines = machines.default_missing()
|
||||
+
|
||||
+ def can_run_host_binaries(self) -> bool:
|
||||
+ return not (
|
||||
@@ -28,9 +28,9 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
+ )
|
||||
--- a/mesonbuild/interpreter/mesonmain.py
|
||||
+++ b/mesonbuild/interpreter/mesonmain.py
|
||||
@@ -277,20 +277,13 @@ class MesonMain(MesonInterpreterObject):
|
||||
@noKwargs
|
||||
@@ -258,21 +258,14 @@ class MesonMain(MesonInterpreterObject):
|
||||
@FeatureDeprecated('meson.has_exe_wrapper', '0.55.0', 'use meson.can_run_host_binaries instead.')
|
||||
@InterpreterObject.method('has_exe_wrapper')
|
||||
def has_exe_wrapper_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
|
||||
- return self._can_run_host_binaries_impl()
|
||||
+ return self.build.environment.can_run_host_binaries()
|
||||
@@ -38,6 +38,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
@noPosargs
|
||||
@noKwargs
|
||||
@FeatureNew('meson.can_run_host_binaries', '0.55.0')
|
||||
@InterpreterObject.method('can_run_host_binaries')
|
||||
def can_run_host_binaries_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
|
||||
- return self._can_run_host_binaries_impl()
|
||||
-
|
||||
|
||||
+50
-50
@@ -32,9 +32,9 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
|
||||
--- a/mesonbuild/linkers/linkers.py
|
||||
+++ b/mesonbuild/linkers/linkers.py
|
||||
@@ -523,11 +523,11 @@ class MetrowerksStaticLinkerARM(Metrower
|
||||
class MetrowerksStaticLinkerEmbeddedPowerPC(MetrowerksStaticLinker):
|
||||
id = 'mwldeppc'
|
||||
@@ -588,11 +588,11 @@ class EmxomfArLinker(ArLinker):
|
||||
def get_std_link_args(self, env: 'Environment', is_thin: bool) -> T.List[str]:
|
||||
return ['cr']
|
||||
|
||||
-def prepare_rpaths(raw_rpaths: T.Tuple[str, ...], build_dir: str, from_dir: str) -> T.List[str]:
|
||||
+def prepare_rpaths(env: Environment, raw_rpaths: T.Tuple[str, ...], build_dir: str, from_dir: str) -> T.List[str]:
|
||||
@@ -46,7 +46,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
ordered_rpaths = order_rpaths(internal_format_rpaths)
|
||||
return ordered_rpaths
|
||||
|
||||
@@ -544,11 +544,16 @@ def order_rpaths(rpath_list: T.List[str]
|
||||
@@ -609,11 +609,16 @@ def order_rpaths(rpath_list: T.List[str]
|
||||
return sorted(rpath_list, key=os.path.isabs)
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
+def evaluate_rpath(env: Environment, p: str, build_dir: str, from_dir: str) -> str:
|
||||
if p == from_dir:
|
||||
return '' # relpath errors out in this case
|
||||
elif os.path.isabs(p):
|
||||
elif path_has_root(p):
|
||||
- return p # These can be outside of build dir.
|
||||
+ if env.can_run_host_binaries():
|
||||
+ return p # These can be outside of build dir.
|
||||
@@ -65,103 +65,103 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
else:
|
||||
return os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir))
|
||||
|
||||
@@ -673,7 +678,7 @@ class GnuLikeDynamicLinkerMixin(DynamicL
|
||||
@@ -752,7 +757,7 @@ class GnuLikeDynamicLinkerMixin(DynamicL
|
||||
return ([], set())
|
||||
args: T.List[str] = []
|
||||
origin_placeholder = '$ORIGIN'
|
||||
- processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
|
||||
+ processed_rpaths = prepare_rpaths(env, rpath_paths, build_dir, from_dir)
|
||||
+ processed_rpaths = prepare_rpaths(self.environment, rpath_paths, build_dir, from_dir)
|
||||
# Need to deduplicate rpaths, as macOS's install_name_tool
|
||||
# is *very* allergic to duplicate -delete_rpath arguments
|
||||
# when calling depfixer on installation.
|
||||
@@ -683,9 +688,13 @@ class GnuLikeDynamicLinkerMixin(DynamicL
|
||||
@@ -762,9 +767,13 @@ class GnuLikeDynamicLinkerMixin(DynamicL
|
||||
rpath_dirs_to_remove.add(p.encode('utf8'))
|
||||
# Build_rpath is used as-is (it is usually absolute).
|
||||
if build_rpath != '':
|
||||
- all_paths.add(build_rpath)
|
||||
- for p in build_rpath.split(':'):
|
||||
if target.build_rpath != '':
|
||||
- all_paths.add(target.build_rpath)
|
||||
- for p in target.build_rpath.split(':'):
|
||||
- rpath_dirs_to_remove.add(p.encode('utf8'))
|
||||
+ paths = build_rpath.split(':')
|
||||
+ paths = target.build_rpath.split(':')
|
||||
+ for p in paths:
|
||||
+ # Only include relative paths if we can't run binaries on host system.
|
||||
+ # (cross-compilation and no exe_wrapper)
|
||||
+ if env.can_run_host_binaries() or not os.path.isabs(p):
|
||||
+ if self.environment.can_run_host_binaries() or not os.path.isabs(p):
|
||||
+ all_paths.add(p)
|
||||
+ rpath_dirs_to_remove.add(p.encode('utf8'))
|
||||
if extra_paths:
|
||||
all_paths.update(extra_paths)
|
||||
|
||||
# TODO: should this actually be "for (dragonfly|open)bsd"?
|
||||
if mesonlib.is_dragonflybsd() or mesonlib.is_openbsd():
|
||||
@@ -828,10 +837,15 @@ class AppleDynamicLinker(PosixDynamicLin
|
||||
@@ -937,10 +946,15 @@ class AppleDynamicLinker(PosixDynamicLin
|
||||
# @loader_path is the equivalent of $ORIGIN on macOS
|
||||
# https://stackoverflow.com/q/26280738
|
||||
origin_placeholder = '@loader_path'
|
||||
- processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
|
||||
+ processed_rpaths = prepare_rpaths(env, rpath_paths, build_dir, from_dir)
|
||||
+ processed_rpaths = prepare_rpaths(self.environment, rpath_paths, build_dir, from_dir)
|
||||
all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
|
||||
if build_rpath != '':
|
||||
- all_paths.update(build_rpath.split(':'))
|
||||
+ paths = build_rpath.split(':')
|
||||
if target.build_rpath != '':
|
||||
- all_paths.update(target.build_rpath.split(':'))
|
||||
+ paths = target.build_rpath.split(':')
|
||||
+ for p in paths:
|
||||
+ # Only include relative paths if we can't run binaries on host system.
|
||||
+ # (cross-compilation and no exe_wrapper)
|
||||
+ if env.can_run_host_binaries() or not os.path.isabs(p):
|
||||
+ if self.environment.can_run_host_binaries() or not os.path.isabs(p):
|
||||
+ all_paths.add(p)
|
||||
if extra_paths:
|
||||
all_paths.update(extra_paths)
|
||||
for rp in all_paths:
|
||||
rpath_dirs_to_remove.add(rp.encode('utf8'))
|
||||
args.extend(self._apply_prefix('-rpath,' + rp))
|
||||
@@ -1200,10 +1214,15 @@ class NAGDynamicLinker(PosixDynamicLinke
|
||||
@@ -1356,10 +1370,15 @@ class NAGDynamicLinker(PosixDynamicLinke
|
||||
return ([], set())
|
||||
args: T.List[str] = []
|
||||
origin_placeholder = '$ORIGIN'
|
||||
- processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
|
||||
+ processed_rpaths = prepare_rpaths(env, rpath_paths, build_dir, from_dir)
|
||||
+ processed_rpaths = prepare_rpaths(self.environment, rpath_paths, build_dir, from_dir)
|
||||
all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
|
||||
if build_rpath != '':
|
||||
- all_paths.add(build_rpath)
|
||||
+ paths = build_rpath.split(':')
|
||||
if target.build_rpath != '':
|
||||
- all_paths.add(target.build_rpath)
|
||||
+ paths = target.build_rpath.split(':')
|
||||
+ for p in paths:
|
||||
+ # Only include relative paths if we can't run binaries on host system.
|
||||
+ # (cross-compilation and no exe_wrapper)
|
||||
+ if env.can_run_host_binaries() or not os.path.isabs(p):
|
||||
+ if self.environment.can_run_host_binaries() or not os.path.isabs(p):
|
||||
+ all_paths.add(p)
|
||||
if extra_paths:
|
||||
all_paths.update(extra_paths)
|
||||
for rp in all_paths:
|
||||
args.extend(self._apply_prefix('-Wl,-Wl,,-rpath,,' + rp))
|
||||
|
||||
@@ -1454,15 +1473,19 @@ class SolarisDynamicLinker(PosixDynamicL
|
||||
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
|
||||
if not rpath_paths and not install_rpath and not build_rpath:
|
||||
@@ -1627,15 +1646,19 @@ class SolarisDynamicLinker(PosixDynamicL
|
||||
rpath_paths = target.determine_rpath_dirs()
|
||||
if not rpath_paths and not target.install_rpath and not target.build_rpath and not extra_paths:
|
||||
return ([], set())
|
||||
- processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
|
||||
+ processed_rpaths = prepare_rpaths(env, rpath_paths, build_dir, from_dir)
|
||||
+ processed_rpaths = prepare_rpaths(self.environment, rpath_paths, build_dir, from_dir)
|
||||
all_paths = mesonlib.OrderedSet([os.path.join('$ORIGIN', p) for p in processed_rpaths])
|
||||
rpath_dirs_to_remove: T.Set[bytes] = set()
|
||||
for p in all_paths:
|
||||
rpath_dirs_to_remove.add(p.encode('utf8'))
|
||||
if build_rpath != '':
|
||||
- all_paths.add(build_rpath)
|
||||
- for p in build_rpath.split(':'):
|
||||
if target.build_rpath != '':
|
||||
- all_paths.add(target.build_rpath)
|
||||
- for p in target.build_rpath.split(':'):
|
||||
- rpath_dirs_to_remove.add(p.encode('utf8'))
|
||||
+ paths = build_rpath.split(':')
|
||||
+ paths = target.build_rpath.split(':')
|
||||
+ for p in paths:
|
||||
+ # Only include relative paths if we can't run binaries on host system.
|
||||
+ # (cross-compilation and no exe_wrapper)
|
||||
+ if env.can_run_host_binaries() or not os.path.isabs(p):
|
||||
+ if self.environment.can_run_host_binaries() or not os.path.isabs(p):
|
||||
+ all_paths.add(p)
|
||||
+ rpath_dirs_to_remove.add(p.encode('utf8'))
|
||||
if extra_paths:
|
||||
all_paths.update(extra_paths)
|
||||
|
||||
# In order to avoid relinking for RPATH removal, the binary needs to contain just
|
||||
# enough space in the ELF header to hold the final installation RPATH.
|
||||
@@ -1525,7 +1548,12 @@ class AIXDynamicLinker(PosixDynamicLinke
|
||||
if install_rpath != '':
|
||||
all_paths.add(install_rpath)
|
||||
if build_rpath != '':
|
||||
- all_paths.add(build_rpath)
|
||||
+ paths = build_rpath.split(':')
|
||||
@@ -1703,7 +1726,12 @@ class AIXDynamicLinker(PosixDynamicLinke
|
||||
if target.install_rpath != '':
|
||||
all_paths.add(target.install_rpath)
|
||||
if target.build_rpath != '':
|
||||
- all_paths.add(target.build_rpath)
|
||||
+ paths = target.build_rpath.split(':')
|
||||
+ for p in paths:
|
||||
+ # Only include relative paths if we can't run binaries on host system.
|
||||
+ # (cross-compilation and no exe_wrapper)
|
||||
+ if env.can_run_host_binaries() or not os.path.isabs(p):
|
||||
+ if self.environment.can_run_host_binaries() or not os.path.isabs(p):
|
||||
+ all_paths.add(p)
|
||||
for p in rpath_paths:
|
||||
for p in target.determine_rpath_dirs():
|
||||
all_paths.add(os.path.join(build_dir, p))
|
||||
# We should consider allowing the $LIBPATH environment variable
|
||||
Reference in new issue
Block a user