Relocatable SDK / build machine leaks
v6 cover Relocatable SDK / build machine leaks
(Series formerly named: "Host-package: RPATH fixup")
Hi all,
Here is yet another round of the series aiming improving the relocatability of the SDK built by Buildroot.
Compare to the previous submissions [1,2], the biggest change in this version is the rewritting in shell of the fix-rpath script.
In details:
Patches 1 to 3:
Clean up and preparatory work for the relocatable SDK series and also helping to track build machine leaks into host, target and staging trees.
Patches 4 to 6:
Make some pieces of the Buildroot SDK relocatable (limited to some symlinks and *-config scripts).
Patches 7 to 9:
Add the fix-rpath script, then run it on the Buildroot host, target and staging trees.
Patch 10:
Clean-up speex package WRT its RPATH hook.
Patch 11:
Update the check-host-rpath to re-use the shell helpers.
Patches 12 and 13:
Add means to track build machine leaks into the host, target and staging trees. These patches will allow to identify what remains to be fixed WRT build machine leaks.
Per-patch changelog is appended to the commit message of each patch.
[1] http://lists.busybox.net/pipermail/buildroot/2015-July/132440.html
[2] http://lists.busybox.net/pipermail/buildroot/2015-July/132659.html
Regards,
Samuel
Samuel Martin (13):
package/linux-headers: cleanup installation
core: use $(CURDIR) to set TOPDIR
core: re-enter make if $(CURDIR) or $(O) are not absolute canonical
path
core: staging symlink uses a relative path when possible
core: make staging *-config scripts relocatable
core: make host *-config scripts relocatable support/scripts: add fix-rpath script + a bunch of helpers
core: add HOST_SANITIZE_RPATH_HOOK to TARGET_FINALIZE_HOOKS
core: add {TARGET,STAGING}_SANITIZE_RPATH_HOOK to
TARGET_FINALIZE_HOOKS
package/speex: remove no longer needed hook support/scripts: update check-host-rpath to use the shell helpers support/scripts: add check-host-leaks script + all needed helpers
core: add check-leaks-in-{target,host,staging} targets
Makefile | 88 +++++++++++++++++- package/linux-headers/linux-headers.mk | 1 + package/pkg-generic.mk | 14 ++- package/pkg-utils.mk | 5 + package/speex/speex.mk | 5 - support/scripts/check-host-leaks | 63 +++++++++++++ support/scripts/check-host-rpath | 67 +++++--------- support/scripts/fix-rpath | 101 ++++++++++++++++++++ support/scripts/shell/log.sh | 57 ++++++++++++ support/scripts/shell/patchelf.sh | 163 +++++++++++++++++++++++++++++++++ support/scripts/shell/readelf.sh | 151 ++++++++++++++++++++++++++++++ support/scripts/shell/sdk.sh | 141 ++++++++++++++++++++++++++++ support/scripts/shell/source.sh | 73 +++++++++++++++ support/scripts/shell/utils.sh | 142 ++++++++++++++++++++++++++++ 14 files changed, 1017 insertions(+), 54 deletions(-) create mode 100755 support/scripts/check-host-leaks create mode 100755 support/scripts/fix-rpath create mode 100644 support/scripts/shell/log.sh create mode 100644 support/scripts/shell/patchelf.sh create mode 100644 support/scripts/shell/readelf.sh create mode 100644 support/scripts/shell/sdk.sh create mode 100644 support/scripts/shell/source.sh create mode 100644 support/scripts/shell/utils.sh
--
2.7.0
PATCH v6 1/13 package/linux-headers: cleanup installation
This patch removes unnecessary files generated during installation.
---
changes v5 -> v6:
- new patch
--- package/linux-headers/linux-headers.mk | 1 + 1 file changed, 1 insertion(+)
package/linux-headers/linux-headers.mk +1 -0
@@ -53,6 +53,7 @@ define LINUX_HEADERS_INSTALL_STAGING_CMDS HOSTCXX="$(HOSTCXX)" \ INSTALL_HDR_PATH=$(STAGING_DIR)/usr \ headers_install) + find $(STAGING_DIR)/usr \( -name .install -o -name ..install.cmd \) -delete endef ifeq ($(BR2_KERNEL_HEADERS_VERSION),y)
Signature · 1 line
2.7.0
PATCH v6 1/13 package/linux-headers: cleanup installation
Dear Samuel Martin,
Quoted 16 lines · Samuel Martin
This patch removes unnecessary files generated during installation.
Signed-off-by Samuel Martin <[email protected]>---
changes v5 -> v6:
- new patch--- package/linux-headers/linux-headers.mk | 1 + 1 file changed, 1 insertion(+)package/linux-headers/linux-headers.mk +0
-0
package/linux-headers/linux-headers.mk define LINUX_HEADERS_INSTALL_STAGING_CMDS · line 56
Quoted 4 lines
package/linux-headers/linux-headers.mk +1
-0@@ -53,6 +53,7 @@ define LINUX_HEADERS_INSTALL_STAGING_CMDS HOSTCXX="$(HOSTCXX)" \ INSTALL_HDR_PATH=$(STAGING_DIR)/usr \ headers_install) + find $(STAGING_DIR)/usr \( -name .install -o -name ..install.cmd \) -delete
Why? Are they causing specific problems? Some better justification in the commit log would be good, because we generally don't add code to clean up things in staging.
Thanks!
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com
PATCH v6 2/13 core: use $(CURDIR) to set TOPDIR
In reply to Samuel MartinThis changes saves a shell call and uses a variable automatically set by make [1].
[1] http://www.gnu.org/software/make/manual/make.html#Quick-Reference
---
changes v5 -> v6:
- new patch
--- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Makefile +1 -1
@@ -69,7 +69,7 @@ endif .NOTPARALLEL: # absolute path -TOPDIR := $(shell pwd) +TOPDIR := $(CURDIR) CONFIG_CONFIG_IN = Config.in CONFIG = support/kconfig DATE := $(shell date +%Y%m%d)
Signature · 1 line
2.7.0
PATCH v6 2/13 core: use $(CURDIR) to set TOPDIR
Quoted 4 lines · Samuel Martin
This changes saves a shell call and uses a variable automatically set by make [1].
[1] http://www.gnu.org/software/make/manual/make.html#Quick-Reference
But then we should maybe remove TOPDIR, and replace it with CURDIR? You can't
change directories in make, so CURDIR will always be valid.
Regards,
Arnout
Quoted 24 lines
Signed-off-by Samuel Martin <[email protected]>---
changes v5 -> v6:
- new patch--- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)Makefile +1
-1@@ -69,7 +69,7 @@ endif .NOTPARALLEL: # absolute path -TOPDIR := $(shell pwd) +TOPDIR := $(CURDIR) CONFIG_CONFIG_IN = Config.in CONFIG = support/kconfig DATE := $(shell date +%Y%m%d)
Signature · 6 lines
Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286500 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF
PATCH v6 3/13 core: re-enter make if $(CURDIR) or $(O) are not absolute canonical path
In reply to Samuel MartinWhen $(CURDIR) or $(O) contain symlinks (or mount-bind) in their path, they can be resolved differently, depending on each package build-system (whether it uses the given paths or get the absolute canonical ones).
Thus, to make easier tracking down host machine paths leaking into the host, target or staging trees, the CURDIR and O variables are set to their absolute canonical paths.
Note that this change takes care of the makefile wrapper installed in $(O) to avoid unneeded make recursion.
---
changes v5 -> v6:
- new patch
--- Makefile | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
Makefile +18 -4
@@ -26,16 +26,30 @@ # Trick for always running with a fixed umask UMASK = 0022 -ifneq ($(shell umask),$(UMASK)) + +# Check if we need to re-enter make for one or several of the following reasons: +# 1- Wrong (too restrictive) umask: +# This prevents Buildroot and packages from creating files and directories. +# 2- CWD (i.e. $(CURDIR)) not being the absolute canonical path: +# This makes harder tracking and fixing host machine path leaks. +# 3- Output location (i.e. $(O)) not being the absolute canonical path: +# This makes harder tracking and fixing host machine path leaks. +# +# Note: +# - remove the trailing '/.' from $(O) as it can be added by the makefile +# wrapper installed in the $(O). +ifneq ($(shell umask):$(CURDIR):$(patsubst %/.,%,$(O)),$(UMASK):$(realpath $(CURDIR)):$(realpath $(O))) .PHONY: _all $(MAKECMDGOALS) $(MAKECMDGOALS): _all @: _all: - @umask $(UMASK) && $(MAKE) --no-print-directory $(MAKECMDGOALS) + umask $(UMASK) && \ + $(MAKE) -C $(realpath $(CURDIR)) --no-print-directory \ + $(MAKECMDGOALS) O=$(realpath $(O)) -else # umask +else # umask / $(CURDIR) / $(O) # This is our default rule, so must come first all:
@@ -1001,4 +1015,4 @@ include docs/manual/manual.mk .PHONY: $(noconfig_targets) -endif #umask +endif #umask / $(CURDIR) / $(O)
Signature · 1 line
2.7.0
PATCH v6 3/13 core: re-enter make if $(CURDIR) or $(O) are not absolute canonical path
Quoted 31 lines · Samuel Martin
When $(CURDIR) or $(O) contain symlinks (or mount-bind) in their path, they can be resolved differently, depending on each package build-system (whether it uses the given paths or get the absolute canonical ones).
Thus, to make easier tracking down host machine paths leaking into the host, target or staging trees, the CURDIR and O variables are set to their absolute canonical paths.
Note that this change takes care of the makefile wrapper installed in $(O) to avoid unneeded make recursion.
Signed-off-by Samuel Martin <[email protected]>---
changes v5 -> v6:
- new patch--- Makefile | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)Makefile +2
-1@@ -26,16 +26,30 @@ # Trick for always running with a fixed umask UMASK = 0022 -ifneq ($(shell umask),$(UMASK)) + +# Check if we need to re-enter make for one or several of the following reasons:
Makefile line 40
Quoted 10 lines
Makefile +10
-0+# 1- Wrong (too restrictive) umask: +# This prevents Buildroot and packages from creating files and directories. +# 2- CWD (i.e. $(CURDIR)) not being the absolute canonical path: +# This makes harder tracking and fixing host machine path leaks. +# 3- Output location (i.e. $(O)) not being the absolute canonical path: +# This makes harder tracking and fixing host machine path leaks. +# +# Note: +# - remove the trailing '/.' from $(O) as it can be added by the makefile +# wrapper installed in the $(O).
When is the trailing /. added? Can't we avoid that it is added by mkmakefile?
Otherwise looks good to me.
Regards,
Arnout
Quoted 24 lines
Makefile +6
-3+ifneq ($(shell umask):$(CURDIR):$(patsubst %/.,%,$(O)),$(UMASK):$(realpath $(CURDIR)):$(realpath $(O))) .PHONY: _all $(MAKECMDGOALS) $(MAKECMDGOALS): _all @: _all: - @umask $(UMASK) && $(MAKE) --no-print-directory $(MAKECMDGOALS) + umask $(UMASK) && \ + $(MAKE) -C $(realpath $(CURDIR)) --no-print-directory \ + $(MAKECMDGOALS) O=$(realpath $(O)) -else # umask +else # umask / $(CURDIR) / $(O) # This is our default rule, so must come first all:@@ -1001,4 +1015,4 @@ include docs/manual/manual.mk .PHONY: $(noconfig_targets) -endif #umask +endif #umask / $(CURDIR) / $(O)
Signature · 6 lines
Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286500 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF
PATCH v6 3/13 core: re-enter make if $(CURDIR) or $(O) are not absolute canonical path
In reply to Samuel MartinHello,
Quoted 4 lines · Samuel Martin
When $(CURDIR) or $(O) contain symlinks (or mount-bind) in their path, they can be resolved differently, depending on each package build-system (whether it uses the given paths or get the absolute canonical ones).
Quoted 8 lines
Thus, to make easier tracking down host machine paths leaking into the host, target or staging trees, the CURDIR and O variables are set to their absolute canonical paths.
Note that this change takes care of the makefile wrapper installed in $(O) to avoid unneeded make recursion.
Signed-off-by Samuel Martin <[email protected]>
I have to say I kind of hate how complicated our Makefile "entry" logic has become over time. But well, certainly not your fault.
Makefile line 41
Quoted 12 lines
Makefile +12
-0+# Check if we need to re-enter make for one or several of the following reasons: +# 1- Wrong (too restrictive) umask: +# This prevents Buildroot and packages from creating files and directories. +# 2- CWD (i.e. $(CURDIR)) not being the absolute canonical path: +# This makes harder tracking and fixing host machine path leaks. +# 3- Output location (i.e. $(O)) not being the absolute canonical path: +# This makes harder tracking and fixing host machine path leaks. +# +# Note: +# - remove the trailing '/.' from $(O) as it can be added by the makefile +# wrapper installed in the $(O). +ifneq ($(shell umask):$(CURDIR):$(patsubst %/.,%,$(O)),$(UMASK):$(realpath $(CURDIR)):$(realpath $(O)))
Can we simplify this a bit with an intermediate "NEED_RECURSE" or something like that ?
# umask is too restrictive ifneq ($(shell umask),$(UMASK)) NEED_RECURSE = YES endif
...
ifeq ($(NEED_RECURSE),YES)
Maybe "RECURSE" is not the appropriate word. Maybe "NEED_SUBMAKE" is better. Or other folks might have better suggestions.
Thanks!
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com
PATCH v6 4/13 core: staging symlink uses a relative path when possible
In reply to Samuel MartinA step forward toward a relocatable SDK.
---
changes v5->v6:
- no changes
changes v4->v5:
- add support when BR2_HOST_DIR is set somewhere out of BASE_DIR
changes v3->v4:
- no change
changes v2->v3:
- no change
--- Makefile | 4 ++++ 1 file changed, 4 insertions(+)
Makefile +4 -0
@@ -518,7 +518,11 @@ $(BUILD_DIR) $(TARGET_DIR) $(HOST_DIR) $(BINARIES_DIR) $(LEGAL_INFO_DIR) $(REDIS # Populating the staging with the base directories is handled by the skeleton package $(STAGING_DIR): @mkdir -p $(STAGING_DIR) +ifeq ($(BASE_DIR)/host/$(STAGING_SUBDIR),$(STAGING_DIR)) + @ln -snf host/$(STAGING_SUBDIR) $(BASE_DIR)/staging +else @ln -snf $(STAGING_DIR) $(BASE_DIR)/staging +endif RSYNC_VCS_EXCLUSIONS = \ --exclude .svn --exclude .git --exclude .hg --exclude .bzr \
Signature · 1 line
2.7.0
PATCH v6 4/13 core: staging symlink uses a relative path when possible
Dear Samuel Martin,
Quoted 2 lines · Samuel Martin
A step forward toward a relocatable SDK.
Better commit log needed.
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com
PATCH v6 5/13 core: make staging *-config scripts relocatable
In reply to Samuel MartinThis change adjusts the _CONFIG_SCRIPTS hook to set add {exec_,}prefix computed relatively to the script location.
This patch hook only fixes *-config scripts located in the staging area, the target ones are already removed. A follow-up change will fix those from the HOST_DIR location.
---
changes v5 -> v6:
- new patch
--- package/pkg-generic.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
package/pkg-generic.mk +1 -1
@@ -240,7 +240,7 @@ $(BUILD_DIR)/%/.stamp_staging_installed: $(call MESSAGE,"Fixing package configuration files") ;\ $(SED) "s,$(BASE_DIR), at BASE_DIR@,g" \ -e "s,$(STAGING_DIR), at STAGING_DIR@,g" \ - -e "s,^\(exec_\)\?prefix=.*,\1prefix=@STAGING_DIR@/usr,g" \ + -e "s,^\(exec_\)\?prefix=.*,\1prefix=\`dirname \$$0\`/../../usr,g" \ -e "s,-I/usr/,-I at STAGING_DIR@/usr/,g" \ -e "s,-L/usr/,-L at STAGING_DIR@/usr/,g" \ -e "s, at STAGING_DIR@,$(STAGING_DIR),g" \
Signature · 1 line
2.7.0
PATCH v6 5/13 core: make staging *-config scripts relocatable
Quoted 21 lines · Samuel Martin
This change adjusts the
_CONFIG_SCRIPTShook to set add {exec_,}prefix computed relatively to the script location.This patch hook only fixes *-config scripts located in the staging area, the target ones are already removed. A follow-up change will fix those from the
HOST_DIRlocation.Signed-off-by Samuel Martin <[email protected]>---
changes v5 -> v6:
- new patch--- package/pkg-generic.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)package/pkg-generic.mk +0
-0
package/pkg-generic.mk $(BUILD_DIR)/%/.stamp_staging_installed: · line 246
Quoted 8 lines
package/pkg-generic.mk +1
-1@@ -240,7 +240,7 @@ $(BUILD_DIR)/%/.stamp_staging_installed: $(call MESSAGE,"Fixing package configuration files") ;\ $(SED) "s,$(BASE_DIR), at BASE_DIR@,g" \ -e "s,$(STAGING_DIR), at STAGING_DIR@,g" \ - -e "s,^\(exec_\)\?prefix=.*,\1prefix=@STAGING_DIR@/usr,g" \ + -e "s,^\(exec_\)\?prefix=.*,\1prefix=\`dirname \$$0\`/../../usr,g" \ -e "s,-I/usr/,-I at STAGING_DIR@/usr/,g" \ -e "s,-L/usr/,-L at STAGING_DIR@/usr/,g" \ -e "s, at STAGING_DIR@,$(STAGING_DIR),g" \
Since this is still there, it is not really relocatable yet... To make it
really relocatable, we should probably use $${BR_STAGING_DIR}} and export BR_STAGING_DIR=$(STAGING_DIR).
Regards,
Arnout
Signature · 6 lines
Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286500 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF
PATCH v6 6/13 core: make host *-config scripts relocatable
In reply to Samuel MartinThis change adjusts the _CONFIG_SCRIPTS hook to set add {exec_,}prefix computed relatively to the script location.
This patch only fixes *-config scripts located in the host area, those from the target and staging area are already handled.
This hook is a kind of brute-force sed on all files matching '*-config' in the $(HOST_DIR)/usr/bin directory. This allows correctly handle script whose name may depends on the host system, not the target configuration (e.g. ncurses can be configured for the target to be ncurses6w, so ncurses6w-config ; whereas for the host it will be ncurses5, so ncurses5-config).
Since there way less host packages than target ones, it is reasonable to assume that processing all *-config scripts found when a host package (whose target package set the *_CONFIG_SCRIPTS variable) is fairly short and does not add its overhead not even noticeable.
---
changes v5 -> v6:
- new patch
--- package/pkg-generic.mk | 12 ++++++++++++ 1 file changed, 12 insertions(+)
package/pkg-generic.mk +12 -0
@@ -207,6 +207,18 @@ $(BUILD_DIR)/%/.stamp_host_installed: $(foreach hook,$($(PKG)_PRE_INSTALL_HOOKS),$(call $(hook))$(sep)) +$($(PKG)_INSTALL_CMDS) $(foreach hook,$($(PKG)_POST_INSTALL_HOOKS),$(call $(hook))$(sep)) + $(Q)if test -n "$($(RAWNAME)_CONFIG_SCRIPTS)" ; then \ + $(call MESSAGE,"Fixing package configuration files") ;\ + ls $(HOST_DIR)/usr/bin/*-config 2>/dev/null |\ + xargs --no-run-if-empty \ + $(SED) "s,$(BASE_DIR), at BASE_DIR@,g" \ + -e "s,$(HOST_DIR), at HOST_DIR@,g" \ + -e "s,^\(exec_\)\?prefix=.*,\1prefix=\`dirname \$$0\`/../../usr,g" \ + -e "s,-I/usr/,-I at HOST_DIR@/usr/,g" \ + -e "s,-L/usr/,-L at HOST_DIR@/usr/,g" \ + -e "s, at HOST_DIR@,$(HOST_DIR),g" \ + -e "s, at BASE_DIR@,$(BASE_DIR),g" ;\ + fi @$(call step_end,install-host) $(Q)touch $@
Signature · 1 line
2.7.0
PATCH v6 6/13 core: make host *-config scripts relocatable
Dear Samuel Martin,
package/pkg-generic.mk $(BUILD_DIR)/%/.stamp_host_installed: · line 210
Quoted 9 lines · Samuel Martin
package/pkg-generic.mk +1
-0@@ -207,6 +207,18 @@ $(BUILD_DIR)/%/.stamp_host_installed: $(foreach hook,$($(PKG)_PRE_INSTALL_HOOKS),$(call $(hook))$(sep)) +$($(PKG)_INSTALL_CMDS) $(foreach hook,$($(PKG)_POST_INSTALL_HOOKS),$(call $(hook))$(sep)) + $(Q)if test -n "$($(RAWNAME)_CONFIG_SCRIPTS)" ; then \
So you're testing if the current package has defined some <pkg>_CONFIG_SCRIPTS variable....
package/pkg-generic.mk $(BUILD_DIR)/%/.stamp_host_installed: · line 212
Quoted 2 lines
package/pkg-generic.mk +2
-0+ $(call MESSAGE,"Fixing package configuration files") ;\ + ls $(HOST_DIR)/usr/bin/*-config 2>/dev/null |\
But do the replacement on all *-config scripts ?
This doesn't look good, and I think we should be changing just the ones that are in <pkg>_CONFIG_SCRIPTS.
I read your commit log saying that this is a bit complicated due to some packages installing config scripts whose name depend on the host system. Can you give some specific examples to see if we can address this ?
Thanks,
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com
PATCH v6 6/13 core: make host *-config scripts relocatable
Quoted 22 lines · Thomas Petazzoni
Dear Samuel Martin,
package/pkg-generic.mk $(BUILD_DIR)/%/.stamp_host_installed: · line 210
Quoted 9 lines · Samuel Martin
package/pkg-generic.mk +1
-0@@ -207,6 +207,18 @@ $(BUILD_DIR)/%/.stamp_host_installed: $(foreach hook,$($(PKG)_PRE_INSTALL_HOOKS),$(call $(hook))$(sep)) +$($(PKG)_INSTALL_CMDS) $(foreach hook,$($(PKG)_POST_INSTALL_HOOKS),$(call $(hook))$(sep)) + $(Q)if test -n "$($(RAWNAME)_CONFIG_SCRIPTS)" ; then \So you're testing if the current package has defined some <pkg>_CONFIG_SCRIPTS variable....
package/pkg-generic.mk $(BUILD_DIR)/%/.stamp_host_installed: · line 212
Quoted 2 lines
package/pkg-generic.mk +2
-0+ $(call MESSAGE,"Fixing package configuration files") ;\ + ls $(HOST_DIR)/usr/bin/*-config 2>/dev/null |\But do the replacement on all *-config scripts ?
Quoted 7 lines
This doesn't look good, and I think we should be changing just the ones that are in <pkg>_CONFIG_SCRIPTS.
I read your commit log saying that this is a bit complicated due to some packages installing config scripts whose name depend on the host system. Can you give some specific examples to see if we can address this ?
Indeed, I would prefer an explicit HOST_PKG_CONFIG_SCRIPTS variable. You can
easily look for the ones which are needed with
git grep -l _CONFIG_SCRIPTS | xargs grep -l 'host-.*-package'
And since this fixup is completely new, it can be a separate patch per package.
Regards,
Arnout
Signature · 6 lines
Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286500 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF
PATCH v6 6/13 core: make host *-config scripts relocatable
In reply to Samuel MartinQuoted 33 lines · Samuel Martin
This change adjusts the
_CONFIG_SCRIPTShook to set add {exec_,}prefix computed relatively to the script location.This patch only fixes *-config scripts located in the host area, those from the target and staging area are already handled.
This hook is a kind of brute-force sed on all files matching '*-config' in the $(HOST_DIR)/usr/bin directory. This allows correctly handle script whose name may depends on the host system, not the target configuration (e.g. ncurses can be configured for the target to be ncurses6w, so ncurses6w-config ; whereas for the host it will be ncurses5, so ncurses5-config).
Since there way less host packages than target ones, it is reasonable to assume that processing all *-config scripts found when a host package (whose target package set the*_CONFIG_SCRIPTSvariable) is fairly short and does not add its overhead not even noticeable.Signed-off-by Samuel Martin <[email protected]>---
changes v5 -> v6:
- new patch--- package/pkg-generic.mk | 12 ++++++++++++ 1 file changed, 12 insertions(+)package/pkg-generic.mk +0
-0@@ -207,6 +207,18 @@ $(BUILD_DIR)/%/.stamp_host_installed: $(foreach hook,$($(PKG)_PRE_INSTALL_HOOKS),$(call $(hook))$(sep)) +$($(PKG)_INSTALL_CMDS)
package/pkg-generic.mk $(BUILD_DIR)/%/.stamp_host_installed: · line 218
Quoted 10 lines
package/pkg-generic.mk +9
-0$(foreach hook,$($(PKG)_POST_INSTALL_HOOKS),$(call $(hook))$(sep)) + $(Q)if test -n "$($(RAWNAME)_CONFIG_SCRIPTS)" ; then \ + $(call MESSAGE,"Fixing package configuration files") ;\ + ls $(HOST_DIR)/usr/bin/*-config 2>/dev/null |\ + xargs --no-run-if-empty \ + $(SED) "s,$(BASE_DIR), at BASE_DIR@,g" \ + -e "s,$(HOST_DIR), at HOST_DIR@,g" \ + -e "s,^\(exec_\)\?prefix=.*,\1prefix=\`dirname \$$0\`/../../usr,g" \ + -e "s,-I/usr/,-I at HOST_DIR@/usr/,g" \ + -e "s,-L/usr/,-L at HOST_DIR@/usr/,g" \
Is this correct? Host packages are installed with --prefix=$(HOST_DIR), so the
configure script should already have the correct host dir in there. If it does have /usr/something/, it's most likely because it links with a system-installed package in a non-standard path. So I think this change will break things.
Regards,
Arnout
Quoted 7 lines
package/pkg-generic.mk +3
-0+ -e "s, at HOST_DIR@,$(HOST_DIR),g" \ + -e "s, at BASE_DIR@,$(BASE_DIR),g" ;\ + fi @$(call step_end,install-host) $(Q)touch $@
Signature · 6 lines
Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286500 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF
PATCH v6 7/13 support/scripts: add fix-rpath script + a bunch of helpers
In reply to Samuel MartinThis commit introduces a fix-rpath shell-script able to scan a tree, detect ELF files, check their RPATH and fix it in a proper way.
Along to the fix-rpath script, it also adds a bunch of shell helper functions grouped into modules. This will help writing scripts handling RPATH and other things, while allowing to share and reuse these functions between scripts.
These helpers are namespaced within the filename of the module in which they are gathered.
This change adds 6 modules:
- source.sh: provides simple helper to easily source another module, taking
care of not sourcing again an already-sourced one;
- log.sh: provides logging helpers;
- utils.sh: provides simple functions to filter ELF files in a list;
- readelf.sh: provides functions retrieving ELF details from a file;
- patchelf.sh: provides function updating ELF files;
- sdk.sh: provides RPATH computation functions.
These 6 modules are used by the fix-rpath script. Follow-up patches will make some scripts leveraging these modules.
---
changes v5->v6:
- fully rewritten in shell
changes v4->v5:
- add verbose support
- rename shrink_rpath -> clear_rpath
- add sanitize_rpath function
changes v3->v4:
- fix typos and license (Baruch)
changes v2->v3:
- no change
--- support/scripts/fix-rpath | 101 +++++++++++++++++++++++ support/scripts/shell/log.sh | 57 +++++++++++++ support/scripts/shell/patchelf.sh | 163 ++++++++++++++++++++++++++++++++++++++ support/scripts/shell/readelf.sh | 52 ++++++++++++ support/scripts/shell/sdk.sh | 70 ++++++++++++++++ support/scripts/shell/source.sh | 73 +++++++++++++++++ support/scripts/shell/utils.sh | 60 ++++++++++++++ 7 files changed, 576 insertions(+) create mode 100755 support/scripts/fix-rpath create mode 100644 support/scripts/shell/log.sh create mode 100644 support/scripts/shell/patchelf.sh create mode 100644 support/scripts/shell/readelf.sh create mode 100644 support/scripts/shell/sdk.sh create mode 100644 support/scripts/shell/source.sh create mode 100644 support/scripts/shell/utils.sh
support/scripts/fix-rpath new file +101 -0
@@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 Samuel Martin <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +usage() { + cat <<EOF >&2 +Usage: ${0} TREE_KIND TREE_ROOT + +Description: + + This script scans a tree and sanitize ELF files' RPATH found in there. + + Sanitization behaves the same whatever the kindd of the processed tree, but + the resulting RPATH differs. + + Sanitization action: + - remove RPATH pointing outside of the tree + - for RPATH pointing in the tree: + - if they point to standard location (/lib, /usr/lib): remove them + - otherwise: make them relative using \$ORIGIN + + For the target tree: + - scan the whole tree for sanitization + + For the staging tree : + - scan the whole tree for sanitization + + For the host tree: + - skip the staging tree for sanitization + - add \$HOST_DIR/{lib,usr/lib} to RPATH (as relative pathes) + +Arguments: + + TREE_KIND Kind of tree to be processed. + Allowed values: host, target, staging + + TREE_ROOT Path to the root of the tree to be scaned + +EOF +} + +source "${0%/*}/shell/source.sh" + +source.load_module utils +source.load_module readelf +source.load_module patchelf + +main() { + local tree="${1}" + local basedir="$( readlink -f "${2}" )" + + local find_args=( "${basedir}" ) + local sanitize_extra_args=() + local readelf + + case "${tree}" in + host) + # do not process the sysroot (only contains target binaries) + find_args+=( "-name" "sysroot" "-prune" "-o" ) + + # do not process the external toolchain installation directory to + # to avoid breaking it. + find_args+=( "-path" "*/opt/ext-toolchain" "-prune" "-o" ) + + # make sure RPATH will point to ${hostdir}/lib and ${hostdir}/usr/lib + sanitize_extra_args+=( "keep_lib_and_usr_lib" ) + + readelf="${HOST_READELF}" + ;; + staging|target) + readelf="${TARGET_READELF}" + ;; + *) + usage + exit 1 + ;; + esac + + find_args+=( "-type" "f" "-print" ) + + while read file; do + READELF="${READELF}" PATCHELF="${PATCHELF}" \ + patchelf.sanitize_rpath "${basedir}" "${file}" ${sanitize_extra_args[@]} + done < <( find ${find_args[@]} | utils.filter_elf ) +} + +main ${@}
support/scripts/shell/log.sh new file +57 -0
57 lines not on this page · raw message
support/scripts/shell/patchelf.sh new file +163 -0
163 lines not on this page · raw message
support/scripts/shell/readelf.sh new file +52 -0
52 lines not on this page · raw message
support/scripts/shell/sdk.sh new file +70 -0
70 lines not on this page · raw message
support/scripts/shell/source.sh new file +73 -0
73 lines not on this page · raw message
support/scripts/shell/utils.sh new file +60 -0
60 lines not on this page · raw message
Signature · 1 line
2.7.0
PATCH v6 7/13 support/scripts: add fix-rpath script + a bunch of helpers
Quoted 77 lines · Samuel Martin
This commit introduces a fix-rpath shell-script able to scan a tree, detect ELF files, check their RPATH and fix it in a proper way.
Along to the fix-rpath script, it also adds a bunch of shell helper functions grouped into modules. This will help writing scripts handling RPATH and other things, while allowing to share and reuse these functions between scripts.
These helpers are namespaced within the filename of the module in which they are gathered.
This change adds 6 modules:
-source.sh: provides simple helper to easily source another module, takingcare of not sourcing again an already-sourced one;-
log.sh: provides logging helpers;
-utils.sh: provides simple functions to filter ELF files in a list;
-readelf.sh: provides functions retrieving ELF details from a file;
-patchelf.sh: provides function updating ELF files;
-sdk.sh: provides RPATH computation functions.These 6 modules are used by the fix-rpath script. Follow-up patches will make some scripts leveraging these modules.
Signed-off-by Samuel Martin <[email protected]>---
changesv5->v6:
- fully rewritten in shellchanges
v4->v5:
- add verbose support
- renameshrink_rpath->clear_rpath
- addsanitize_rpathfunctionchanges
v3->v4:
- fix typos and license (Baruch)changes
v2->v3:
- no change--- support/scripts/fix-rpath | 101 +++++++++++++++++++++++ support/scripts/shell/log.sh | 57 +++++++++++++ support/scripts/shell/patchelf.sh | 163 ++++++++++++++++++++++++++++++++++++++ support/scripts/shell/readelf.sh | 52 ++++++++++++ support/scripts/shell/sdk.sh | 70 ++++++++++++++++ support/scripts/shell/source.sh | 73 +++++++++++++++++ support/scripts/shell/utils.sh | 60 ++++++++++++++ 7 files changed, 576 insertions(+) create mode 100755 support/scripts/fix-rpath create mode 100644 support/scripts/shell/log.sh create mode 100644 support/scripts/shell/patchelf.sh create mode 100644 support/scripts/shell/readelf.sh create mode 100644 support/scripts/shell/sdk.sh create mode 100644 support/scripts/shell/source.sh create mode 100644 support/scripts/shell/utils.shsupport/scripts/fix-rpath new file +15
-0@@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 Samuel Martin <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License
support/scripts/fix-rpath line 25
Quoted 10 lines
support/scripts/fix-rpath new file +10
-0+# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +usage() { + cat <<EOF >&2 +Usage: ${0} TREE_KIND TREE_ROOT + +Description: + + This script scans a tree and sanitize ELF files' RPATH found in there.
... sanitizes the RPATH of ELF files found in there.
support/scripts/fix-rpath line 27
Quoted 2 lines
support/scripts/fix-rpath new file +2
-0+ + Sanitization behaves the same whatever the kindd of the processed tree, but
Please wrap at 80 columns. But actually, I think 4 spaces is enough for
indentation, that's what you use below as well.
kindd -> kind
But actually I don't really understand this sentence (well, I do after reading
the rest). So I'd just remove this sentence and add...
support/scripts/fix-rpath line 30
Quoted 3 lines
support/scripts/fix-rpath new file +3
-0+ the resulting RPATH differs. + + Sanitization action:
Sanitization action (for all trees):
Quoted 4 lines
support/scripts/fix-rpath new file +4
-0+ - remove RPATH pointing outside of the tree + - for RPATH pointing in the tree: + - if they point to standard location (/lib, /usr/lib): remove them + - otherwise: make them relative using \$ORIGIN
support/scripts/fix-rpath line 44
Quoted 10 lines
support/scripts/fix-rpath new file +10
-0+ + For the target tree: + - scan the whole tree for sanitization + + For the staging tree : + - scan the whole tree for sanitization + + For the host tree: + - skip the staging tree for sanitization + - add \$HOST_DIR/{lib,usr/lib} to RPATH (as relative pathes)
pathes -> paths
support/scripts/fix-rpath line 51
Quoted 7 lines
support/scripts/fix-rpath new file +7
-0+ +Arguments: + + TREE_KIND Kind of tree to be processed. + Allowed values: host, target, staging + + TREE_ROOT Path to the root of the tree to be scaned
scanned
support/scripts/fix-rpath line 60
Quoted 9 lines
support/scripts/fix-rpath new file +9
-0+ +EOF +} + +source "${0%/*}/shell/source.sh" + +source.load_module utils +source.load_module readelf +source.load_module patchelf
What is this, python? :-) I think this source.sh is a bit over the top (it
doesn't really hurt to source those modules a second time), but why not.
support/scripts/fix-rpath line 73
Quoted 13 lines
support/scripts/fix-rpath new file +13
-0+ +main() { + local tree="${1}" + local basedir="$( readlink -f "${2}" )" + + local find_args=( "${basedir}" ) + local sanitize_extra_args=() + local readelf + + case "${tree}" in + host) + # do not process the sysroot (only contains target binaries) + find_args+=( "-name" "sysroot" "-prune" "-o" )
There may be some other random file that is called sysroot, so to be safe I'd
make this
find_args+=( "-path" "${basedir}/usr/*/sysroot" "-prune" "-o" )(untested).
support/scripts/fix-rpath line 77
Quoted 4 lines
support/scripts/fix-rpath new file +4
-0+ + # do not process the external toolchain installation directory to + # to avoid breaking it. + find_args+=( "-path" "*/opt/ext-toolchain" "-prune" "-o" )
Again, to be safe against a opt/ext-toolchain appearing somewhere else in the
tree (admittedly, this is ridiculously unlikely), use . instead of *.
support/scripts/fix-rpath line 80
Quoted 3 lines
support/scripts/fix-rpath new file +3
-0+ + # make sure RPATH will point to ${hostdir}/lib and ${hostdir}/usr/lib + sanitize_extra_args+=( "keep_lib_and_usr_lib" )
Since sanitize_extra_args only contains a single argument, I don't think it's
worth making it an array. Just assign empty above and assign keep_lib_and_usr_lib here, and pass unquoted below. But that's just MHO.
Quoted 6 lines
support/scripts/fix-rpath new file +6
-0+ + readelf="${HOST_READELF}" + ;; + staging|target) + readelf="${TARGET_READELF}" + ;;
support/scripts/fix-rpath line 96
Quoted 10 lines
support/scripts/fix-rpath new file +10
-0+ *) + usage + exit 1 + ;; + esac + + find_args+=( "-type" "f" "-print" ) + + while read file; do + READELF="${READELF}" PATCHELF="${PATCHELF}" \
Shouldn't that be ${readelf}? And where does ${PATCHELF} come from? If it comes
from the environment, there's no need to export it again here.
But maybe it's cleaner to just export READELF inside the case statement, above.
support/scripts/fix-rpath line 98
Quoted 2 lines
support/scripts/fix-rpath new file +2
-0+ patchelf.sanitize_rpath "${basedir}" "${file}" ${sanitize_extra_args[@]} + done < <( find ${find_args[@]} | utils.filter_elf )
I personally don't like this reverse construct, and would write:
find ${find_args[@]} | utils.filter_elf | \
while read file; do
...Again, MHO.
Quoted 42 lines
support/scripts/fix-rpath new file +3
-0+} + +main ${@}support/scripts/shell/log.sh new file +33
-0@@ -0,0 +1,57 @@ +# Copyright (C) 2016 Samuel Martin <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Logging helpers +# +# This module defines the following functions: +# log.trace +# log.debug +# log.info +# log.warn +# log.errorN +# log.error +# +# This module sets the following variables: +# my_name +# +# This module is sensitive to the following environment variables: +# DEBUG + +source.declare_module log
support/scripts/shell/log.sh line 43
Quoted 10 lines
support/scripts/shell/log.sh new file +10
-0+ +# Debug level: +# - 0 or empty: only show errors +# - 1 : show errors and warnings +# - 2 : show errors, warnings, and info +# - 3 : show errors, warnings, info and debug +: ${DEBUG:=0} + +# Low level utility function +log.trace() { local msg="${1}"; shift; printf "%s: ${msg}" "${my_name}" "${@}"; }
I'd do the redirect directly here in the printf, rather than below.
Also, I see no reason to put it all on one line.
support/scripts/shell/log.sh line 56
Quoted 13 lines
support/scripts/shell/log.sh new file +13
-0+ +# Public logging functions +log.debug() { :; } +[ ${DEBUG} -lt 3 ] || log.debug() { log.trace "${@}" >&2; } +log.info() { :; } +[ ${DEBUG} -lt 2 ] || log.info() { log.trace "${@}" >&2; } +log.warn() { :; } +[ ${DEBUG} -lt 1 ] || log.warn() { log.trace "${@}" >&2; } +log.errorN() { local ret="${1}"; shift; log.warn "${@}"; exit ${ret}; } +log.error() { log.errorN 1 "${@}"; } + +# Program name +my_name="${0##*/}"
Isn't my_name always going to be log.sh? "source" doesn't propagate the
parent's arguments AFAIK.
Quoted 14 lines
support/scripts/shell/log.sh new file +1
-0+support/scripts/shell/patchelf.sh new file +7
-0@@ -0,0 +1,163 @@ +# Copyright (C) 2016 Samuel Martin <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +#
support/scripts/shell/patchelf.sh line 17
Quoted 10 lines
support/scripts/shell/patchelf.sh new file +10
-0+# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Patchelf helpers
AFAICS these helper will only ever be used in the fix-rpaths script (but I
haven't read the entire series yet). Unless you can see a good use case for using these functions in another script, I would prefer to see them defined directly in the fix-rpaths script rather than a separate module. IMHO it's easier to understand related code if it's in one file than if it's in separate files.
Quoted 24 lines
support/scripts/shell/patchelf.sh new file +24
-0+# +# This module defines the following functions: +# patchelf.set_xrpath +# patchelf.update_rpath +# patchelf.sanitize_rpath +# +# This module is sensitive to the following environment variables: +# PATCHELF +# READELF + +source.declare_module patchelf + +source.load_module log +source.load_module sdk +source.load_module utils +source.load_module readelf + +: ${PATCHELF:=patchelf} + +# patchelf.set_xrpath file rpath... +# +# Set RPATH in $file. +# Automatically join all RPATH with the correct separator, and also handle +# XRPATH (replacing "XORIGIN" with "$ORIGIN").
support/scripts/shell/patchelf.sh line 51
Quoted 10 lines
support/scripts/shell/patchelf.sh new file +10
-0+# +# file : ELF file path +# rpath : RPATH element +# +# environment: +# PATCHELF: patchelf program path +patchelf.set_xrpath() { + local file="${1}" + shift + local xrpath="$(sed -e 's/ +/:/g' <<<"${@}")"
In fix-rpath you put spaces inside the "$( ... )". I think this would be a good
idea here as well.
support/scripts/shell/patchelf.sh line 58
Quoted 7 lines
support/scripts/shell/patchelf.sh new file +7
-0+ "${PATCHELF}" --set-rpath "${xrpath//XORIGIN/\$ORIGIN}" "${file}" +} + +# patchelf.update_rpath basedir binary libdirs... +# +# Set RPATH in $binary computing them from the paths $libdirs (and $basedir). +# Existing RPATH in $file will be overwritten if any.
$file -> $binary ?
support/scripts/shell/patchelf.sh line 62
Quoted 4 lines
support/scripts/shell/patchelf.sh new file +4
-0+# +# basedir : absolute path of the tree in which the $bindir and $libdirs must be +# binary : ELF file absolute path +# libdirs : list of library location (absolute paths)
location -> locations
Quoted 4 lines
support/scripts/shell/patchelf.sh new file +4
-0+# +# environment: +# PATCHELF: patchelf program path +patchelf.update_rpath() {
support/scripts/shell/patchelf.sh line 76
Quoted 10 lines
support/scripts/shell/patchelf.sh new file +10
-0+ local basedir="${1}" + local binary="${2}" + shift 2 + local libdirs=( ${@} ) + log.debug " basedir: %s\n" "${basedir}" + log.debug " elf: %s\n" "${binary}" + log.debug " libdirs: %s\n" "${libdirs[*]}" + log.info " rpath: %s\n" \ + "$( sdk.compute_xrpath "${basedir}" "${binary%/*}" ${libdirs[@]} | + sed -e 's/XORIGIN/\$ORIGIN/g' )"
Maybe compute it once and store it in a variable?
Alternatively, add a helper
log.tracerun() {
log.info "%s\n" "$*"
"$@"
}and use it below.
support/scripts/shell/patchelf.sh line 77
Quoted 1 line
support/scripts/shell/patchelf.sh new file +1
-0+ PATCHELF="${PATCHELF}" patchelf.set_xrpath "${binary}" \
Again, PATCHELF is already in the environment.
support/scripts/shell/patchelf.sh line 84
Quoted 7 lines
support/scripts/shell/patchelf.sh new file +7
-0+ $( sdk.compute_xrpath "${basedir}" "${binary%/*}" ${libdirs[@]} ) +} + +# patchelf.sanitize_rpath basedir binary [keep_lib_usr_lib] +# +# Scan $binary's RPATH, remove any of them pointing outside of $basedir. +# If $keep_lib_usr_lib in not empty, the library directories $basedir/lib and
in -> is
support/scripts/shell/patchelf.sh line 88
Quoted 4 lines
support/scripts/shell/patchelf.sh new file +4
-0+# $basedir/usr/lib will be added to the RPATH. +# +# Note: +# Absolute paths is needed to correctly handle symlinks and or mount-bind in
is -> are
and or -> and/or
mount-bind -> bind-mount (though actually, I don't see how you're going to get
an absolute path through a bind mount)
Quoted 7 lines
support/scripts/shell/patchelf.sh new file +7
-0+# the $basedir path. +# +# basedir : absolute path of the tree in which the $bindir and $libdirs +# must be +# binary : ELF file absolute path +# keep_lib_usr_lib : add to RPATH $basedir/lib and $basedir/usr/lib +#
support/scripts/shell/patchelf.sh line 105
Quoted 10 lines
support/scripts/shell/patchelf.sh new file +10
-0+# environment: +# PATCHELF: patchelf program path +# READELF : readelf program path +patchelf.sanitize_rpath() { + local basedir="$( readlink -f "${1}" )" + local binary="${2}" + local keep_lib_usr_lib="${3}" + + local path abspath rpath + local libdirs=()
I think new_rpaths is a better name here.
support/scripts/shell/patchelf.sh line 113
Quoted 8 lines
support/scripts/shell/patchelf.sh new file +8
-0+ + if test -n "${keep_lib_usr_lib}" ; then + libdirs+=( "${basedir}/lib" "${basedir}/usr/lib" ) + fi + + log.info "ELF: %s\n" "${binary}" + + local rpaths="$( READELF="${READELF}" readelf.get_rpath "${binary}" )"
Again, READELF is already in the environment.
support/scripts/shell/patchelf.sh line 125
Quoted 12 lines
support/scripts/shell/patchelf.sh new file +12
-0+ + for rpath in ${rpaths//:/ } ; do + # figure out if we should keep or discard the path; there are several + # cases to handled: + # - $path starts with "$ORIGIN": + # The original build-system already took care of setting a relative + # RPATH, resolve it and test if it is worthwhile to keep it; + # - $basedir/$path exists: + # The original build-system already took care of setting an absolute + # RPATH (absolute in the final rootfs), resolve it and test if it is + # worthwhile to keep it; + # - $path start with $basedir:
start -> starts
support/scripts/shell/patchelf.sh line 132
Quoted 7 lines
support/scripts/shell/patchelf.sh new file +7
-0+ # The original build-system added some absolute RPATH (absolute on + # the build machine). While this is wrong, it can still be fixed; so + # test if it is worthwhile to keep it; + # - $path points somewhere else: + # (can be anywhere: build trees, staging tree, host location, + # non-existing location, etc.) + # Just discard such a path.
This is not correct for host packages. If a host package has picked up an RPATH
to e.g. ~/lib/foo through pkg-config, then that RPATH must still be kept. But only for host packages. For host packages, you should probably just not remove anything.
So I think you still need to distinguish between the host and staging/target
cases here. In fact, I think the whole logic of this function is easier to understand if it is separate for host and target/staging.
support/scripts/shell/patchelf.sh line 134
Quoted 2 lines
support/scripts/shell/patchelf.sh new file +2
-0+ if grep -q '^$ORIGIN/' <<<"${rpath}" ; then + path="${binary%/*}/${rpath#*ORIGIN/}"
Maybe ?ORIGIN instead of *ORIGIN, just in case there's another ORIGIN somewhere
in the path?
support/scripts/shell/patchelf.sh line 135
Quoted 1 line
support/scripts/shell/patchelf.sh new file +1
-0+ elif test -e "${basedir}/${rpath}" ; then
-e -> -d, it really must be a directory.
support/scripts/shell/patchelf.sh line 146
Quoted 11 lines
support/scripts/shell/patchelf.sh new file +11
-0+ path="${basedir}/${rpath}" + elif grep -q "^${basedir}/" <<<"$( readlink -f "${rpath}" )" ; then + path="${rpath}" + else + log.debug "\tDROPPED [out-of-tree]: %s\n" "${rpath}" + continue + fi + + abspath="$( readlink -f "${path}" )" + + # discard path pointing to default locations handled by ld-linux
ld-linux -> ld.so
Quoted 5 lines
support/scripts/shell/patchelf.sh new file +5
-0+ if grep -qE "^${basedir}/(lib|usr/lib)$" <<<"${abspath}" ; then + log.debug \ + "\tDROPPED [std libdirs]: %s (%s)\n" "${rpath}" "${abspath}" + continue + fi
support/scripts/shell/patchelf.sh line 161
Quoted 10 lines
support/scripts/shell/patchelf.sh new file +10
-0+ + log.debug "\tKEPT %s (%s)\n" "${rpath}" "${abspath}" + + libdirs+=( "${abspath}" ) + + done + + libdirs=( $( utils.list_reduce ${libdirs[@]} ) ) + + PATCHELF="${PATCHELF}" \
Again, already in the env.
Quoted 36 lines
support/scripts/shell/patchelf.sh new file +2
-0+ patchelf.update_rpath "${basedir}" "${binary}" ${libdirs[@]} +}support/scripts/shell/readelf.sh new file +28
-0@@ -0,0 +1,52 @@ +# Copyright (C) 2016 Samuel Martin <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Readelf helpers +# +# This module defines the following functions: +# readelf.get_rpath +# +# This module is sensitive to the following environment variables: +# READELF +# +# This module sets the following environment variables: +# LC_ALL=C + +source.declare_module readelf
support/scripts/shell/readelf.sh line 38
Quoted 10 lines
support/scripts/shell/readelf.sh new file +10
-0+ +# Override the user's locale so we are sure we can parse the output of +# readelf(1) and file(1) +export LC_ALL=C + +: ${READELF:=readelf} + +# readelf.get_rpath file +# +# Return the unsplitted RPATH/RUNPATH of $file.
unsplitted -> unsplit.
But it's actually not return, it's print. And to make it very explicit, write:
Print the :-separate RPATH/RUNPATH of $file.
Quoted 4 lines
support/scripts/shell/readelf.sh new file +4
-0+# +# To split the returned RPATH string and store them in an array, do: +# +# paths=( $(readelf.get_rpath "${file}" | sed -e 's/:/ /g') )
support/scripts/shell/readelf.sh line 52
Quoted 10 lines
support/scripts/shell/readelf.sh new file +10
-0+# +# file : ELF file path +# +# environment: +# READELF: readelf program path +readelf.get_rpath() { + local file="${1}" + "${READELF}" --dynamic "${file}" | + sed -r -e '/.* \(R(UN)?PATH\) +Library r(un)?path: \[(.+)\]$/!d ; s//\3/' +}
I have to go now, so reviewed until here. The rest I can hopefully review
tomorrow...
Regards,
Arnout
[snip]
Signature · 6 lines
Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286500 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF
PATCH v6 8/13 core: add HOST_SANITIZE_RPATH_HOOK to TARGET_FINALIZE_HOOKS
In reply to Samuel MartinThis patch adds host-patchelf as a target-finalize dependency, and introduces the HOST_SANITIZE_RPATH_HOOK hook to fix the ELF files' RPATH from the HOST_DIR location (excluding the sysroot).
After running this hook, the RPATH from any host ELF files is relative to the binary location itself.
Notes:
- we avoid to fix RPATH in the sysroot.
- we do not try to fix RPATH in the external toolchain installation location as they may have been built in a way, this is already correct; furthermore, fixing RPATH in those programs may result in breaking them.
- the whole host directory is processed because a number of host-package install programs that could be useful in places different from $(HOST_DIR)/{bin,sbin,usr/bin,usr/sbin}.
- the shared libraries are also processed in case they have a 'main' function.
As a step toward a fully relocatable SDK, this change allows to get the toolchain relocatable, but not yet the whole SDK.
---
changes v5->v6:
- update for the new script version
- add debug mode support
changes v4->v5:
- add verbose support
changes v3->v4:
- add host-patchelf to PACKAGES instead of target-finalize (Baruch)
- add comment
changes v2->v3:
- move hook in Makefile (Baruch)
--- Makefile | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
Makefile +25 -0
@@ -616,6 +616,31 @@ endef TARGET_FINALIZE_HOOKS += PURGE_LOCALES endif +# RPATH fixing +# - The host hook sets RPATH in host ELF binaries, using relative paths to the +# library locations. +# - The target hook sanitizes RPATH in target ELF binaries, removing paths +# pointing to package's build directories or the sysroot's libdirs. +PACKAGES += host-patchelf + +ifeq ($(BR2_DEBUG_RPATH),) +BR2_DEBUG_RPATH = 0 +endif +ifeq ($(BR2_DEBUG_RPATH),0) +DEBUG_RPATH = 0 +else +DEBUG_RPATH = $(shell echo $$(($(BR2_DEBUG_RPATH)+1))) +endif + +define HOST_SANITIZE_RPATH_HOOK + DEBUG=$(DEBUG_RPATH) \ + PATCHELF=$(HOST_DIR)/usr/bin/patchelf \ + READELF=readelf \ + $(TOPDIR)/support/scripts/fix-rpath host $(HOST_DIR) +endef + +TARGET_FINALIZE_HOOKS += HOST_SANITIZE_RPATH_HOOK + $(TARGETS_ROOTFS): target-finalize target-finalize: $(PACKAGES)
Signature · 1 line
2.7.0
PATCH v6 8/13 core: add HOST_SANITIZE_RPATH_HOOK to TARGET_FINALIZE_HOOKS
Quoted 54 lines · Samuel Martin
This patch adds host-patchelf as a target-finalize dependency, and introduces the
HOST_SANITIZE_RPATH_HOOKhook to fix the ELF files' RPATH from theHOST_DIRlocation (excluding the sysroot).After running this hook, the RPATH from any host ELF files is relative to the binary location itself.
Notes:
- we avoid to fix RPATH in the sysroot.
- we do not try to fix RPATH in the external toolchain installation location as they may have been built in a way, this is already correct; furthermore, fixing RPATH in those programs may result in breaking them.
- the whole host directory is processed because a number of host-package install programs that could be useful in places different from $(HOST_DIR)/{bin,sbin,usr/bin,usr/sbin}.
- the shared libraries are also processed in case they have a 'main' function.As a step toward a fully relocatable SDK, this change allows to get the toolchain relocatable, but not yet the whole SDK.
Signed-off-by Samuel Martin <[email protected]>---
changesv5->v6:
- update for the new script version
- add debug mode supportchanges
v4->v5:
- add verbose supportchanges
v3->v4:
- add host-patchelf to PACKAGES instead of target-finalize (Baruch)
- add commentchanges
v2->v3:
- move hook inMakefile(Baruch)--- Makefile | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)Makefile +5
-0@@ -616,6 +616,31 @@ endef TARGET_FINALIZE_HOOKS += PURGE_LOCALES endif +# RPATH fixing +# - The host hook sets RPATH in host ELF binaries, using relative paths to the +# library locations. +# - The target hook sanitizes RPATH in target ELF binaries, removing paths +# pointing to package's build directories or the sysroot's libdirs.
Makefile endef · line 633
Quoted 10 lines
Makefile +10
-0+PACKAGES += host-patchelf + +ifeq ($(BR2_DEBUG_RPATH),) +BR2_DEBUG_RPATH = 0 +endif +ifeq ($(BR2_DEBUG_RPATH),0) +DEBUG_RPATH = 0 +else +DEBUG_RPATH = $(shell echo $$(($(BR2_DEBUG_RPATH)+1))) +endif
I don't like this debug handling in the Makefile. For the toolchain wrapper,
the BR2_DEBUG_WRAPPER variable is used directly in the wrapper, so nothing specific has to be done in the Makefile. So here as well I'd prefer to use BR2_DEBUG_RPATH in the scripts.
Since the logging stuff is generic, you will indeed have to convert it to the
DEBUG variable in the fix-rpath script, but IMHO that's much more acceptable.
Also, it should be sufficient to set DEBUG=${BR_DEBUG_RPATH}. IfBR2_DEBUG_RPATH is not set, the ${DEBUG:=0} in log.sh will set it to 0.
Makefile endef · line 638
Quoted 5 lines
Makefile +5
-0+ +define HOST_SANITIZE_RPATH_HOOK + DEBUG=$(DEBUG_RPATH) \ + PATCHELF=$(HOST_DIR)/usr/bin/patchelf \ + READELF=readelf \
That's already set by the scripts, and actually it's probably better if the
user has the possibility to override readelf.
Makefile endef · line 639
Quoted 1 line
Makefile +1
-0+ $(TOPDIR)/support/scripts/fix-rpath host $(HOST_DIR)
I find this indentation a bit weird. But OK.
Regards,
Arnout
Quoted 8 lines
Makefile +4
-0+endef + +TARGET_FINALIZE_HOOKS += HOST_SANITIZE_RPATH_HOOK + $(TARGETS_ROOTFS): target-finalize target-finalize: $(PACKAGES)
Signature · 6 lines
Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286500 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF
PATCH v6 9/13 core: add {TARGET, STAGING}_SANITIZE_RPATH_HOOK to TARGET_FINALIZE_HOOKS
In reply to Samuel MartinThis patch introduces the TARGET_SANITIZE_RPATH_HOOK and STAGING_SANITIZE_RPATH_HOOK hooks fixing the ELF files' RPATH of binaries from, respectively, the TARGET_DIR and the STAGING_DIR locations.
After running this hook, the RPATH from any target ELF files from both the target and the staging locations won't contain any occurence of the sysroot or some build locations.
---
changes v5->v6:
- update for the new script version
- add debug mode support
changes v4->v5:
- target hook now sanitizes the rpath (Baruch)
- add verbose support
- update comment
changes v3->v4:
- rebase
- add comment
changes v2->v3:
- move hook in Makefile (Baruch)
--- Makefile | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
Makefile +20 -0
@@ -641,6 +641,26 @@ endef TARGET_FINALIZE_HOOKS += HOST_SANITIZE_RPATH_HOOK +# Function sanitizing target/staging ELF files' RPATH. +# i.e. it removes paths pointing to the staging or build location from the ELF +# files' RPATH. +define TARGET_SANITIZE_RPATH_HOOK + DEBUG=$(DEBUG_RPATH) \ + PATCHELF=$(HOST_DIR)/usr/bin/patchelf \ + READELF=$(TARGET_READELF) \ + $(TOPDIR)/support/scripts/fix-rpath target $(TARGET_DIR) +endef + +define STAGING_SANITIZE_RPATH_HOOK + DEBUG=$(DEBUG_RPATH) \ + PATCHELF=$(HOST_DIR)/usr/bin/patchelf \ + READELF=$(TARGET_READELF) \ + $(TOPDIR)/support/scripts/fix-rpath staging $(STAGING_DIR) +endef + +TARGET_FINALIZE_HOOKS += TARGET_SANITIZE_RPATH_HOOK \ + STAGING_SANITIZE_RPATH_HOOK + $(TARGETS_ROOTFS): target-finalize target-finalize: $(PACKAGES)
Signature · 1 line
2.7.0
PATCH v6 9/13 core: add {TARGET, STAGING}_SANITIZE_RPATH_HOOK to TARGET_FINALIZE_HOOKS
Quoted 44 lines · Samuel Martin
This patch introduces the
TARGET_SANITIZE_RPATH_HOOKandSTAGING_SANITIZE_RPATH_HOOKhooks fixing the ELF files' RPATH of binaries from, respectively, theTARGET_DIRand theSTAGING_DIRlocations.After running this hook, the RPATH from any target ELF files from both the target and the staging locations won't contain any occurence of the sysroot or some build locations.
Signed-off-by Samuel Martin <[email protected]>---
changesv5->v6:
- update for the new script version
- add debug mode supportchanges
v4->v5:
- target hook now sanitizes the rpath (Baruch)
- add verbose support
- update commentchanges
v3->v4:
- rebase
- add commentchanges
v2->v3:
- move hook inMakefile(Baruch)--- Makefile | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)Makefile +5
-0@@ -641,6 +641,26 @@ endef TARGET_FINALIZE_HOOKS += HOST_SANITIZE_RPATH_HOOK +# Function sanitizing target/staging ELF files' RPATH. +# i.e. it removes paths pointing to the staging or build location from the ELF +# files' RPATH. +define TARGET_SANITIZE_RPATH_HOOK + DEBUG=$(DEBUG_RPATH) \
Makefile endef · line 658
Quoted 10 lines
Makefile +10
-0+ PATCHELF=$(HOST_DIR)/usr/bin/patchelf \ + READELF=$(TARGET_READELF) \ + $(TOPDIR)/support/scripts/fix-rpath target $(TARGET_DIR) +endef + +define STAGING_SANITIZE_RPATH_HOOK + DEBUG=$(DEBUG_RPATH) \ + PATCHELF=$(HOST_DIR)/usr/bin/patchelf \ + READELF=$(TARGET_READELF) \ + $(TOPDIR)/support/scripts/fix-rpath staging $(STAGING_DIR)
Since target and staging are basically the same, I'd just make a single call to
fix-rpath and add a loop over basedirs there. So
.../fix-rpath target $(TARGET_DIR) $(STAGING_DIR)
Or actually, I'm not sure if it makes a lot of sense to have the fix-rpath
script the way it is now, because the only commonality between host and target is the filter_elf step. But that could in fact easily be done inside the sanitize_rpath function (which would check for an ELF file at start and exit 0 if it's not ELF).
So you could have
define HOST_SANITIZE_RPATH_HOOK
PATCHELF=$(HOST_DIR)/usr/bin/patchelf \
find $(HOST_DIR) -path "$(HOST_DIR)/usr/*/sysroot" -prune -o \
"$(HOST_DIR)/opt/ext-toolchain" -prune -o \
-type f \
-exec $(TOPDIR)/support/scripts/sanitize-rpath \
"$(HOST_DIR)" '{}' keep_lib_and_usr_lib \;endef
define TARGET_SANITIZE_RPATH_HOOK
PATCHELF=$(HOST_DIR)/usr/bin/patchelf \
READELF=$(TARGET_READELF) \
find $(STAGING_DIR) -type f \
-exec $(TOPDIR)/support/scripts/sanitize-rpath \
"$(STAGING_DIR)" '{}' \;
PATCHELF=$(HOST_DIR)/usr/bin/patchelf \
READELF=$(TARGET_READELF) \
find $(TARGET_DIR) -type f \
-exec $(TOPDIR)/support/scripts/sanitize-rpath \
"$(STAGING_DIR)" '{}' \;endef
OK, maybe some factorization should be possible here, but the fix-rpath script
is 100 lines long and those save only 3 lines in the Makefile, so really I don't think that's a good refactoring...
Regards,
Arnout
Quoted 9 lines
Makefile +5
-0+endef + +TARGET_FINALIZE_HOOKS += TARGET_SANITIZE_RPATH_HOOK \ + STAGING_SANITIZE_RPATH_HOOK + $(TARGETS_ROOTFS): target-finalize target-finalize: $(PACKAGES)
Signature · 6 lines
Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286500 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF
PATCH v6 10/13 package/speex: remove no longer needed hook
In reply to Samuel MartinRemove the LIBTOOL_FIXUP hook since RPATH are now sanitized in target-finalize hooks.
---
changes v5->v6:
- no change
changes v4->v5:
- new patch (suggested by Baruch)
--- package/speex/speex.mk | 5 ----- 1 file changed, 5 deletions(-)
package/speex/speex.mk +0 -5
@@ -24,11 +24,6 @@ ifeq ($(BR2_PACKAGE_SPEEX_ARM5E),y) SPEEX_CONF_OPTS += --enable-arm5e-asm endif -define SPEEX_LIBTOOL_FIXUP - $(SED) 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' $(@D)/libtool - $(SED) 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' $(@D)/libtool -endef - SPEEX_POST_CONFIGURE_HOOKS += SPEEX_LIBTOOL_FIXUP define SPEEX_BUILD_CMDS
Signature · 1 line
2.7.0
PATCH v6 10/13 package/speex: remove no longer needed hook
Quoted 4 lines · Samuel Martin
Remove the
LIBTOOL_FIXUPhook since RPATH are now sanitized in target-finalize hooks.Signed-off-by Samuel Martin <[email protected]>
Regards,
Arnout
Quoted 28 lines
---
changesv5->v6:
- no changechanges
v4->v5:
- new patch (suggested by Baruch)--- package/speex/speex.mk | 5 ----- 1 file changed, 5 deletions(-)package/speex/speex.mk +0
-5@@ -24,11 +24,6 @@ ifeq ($(BR2_PACKAGE_SPEEX_ARM5E),y) SPEEX_CONF_OPTS += --enable-arm5e-asm endif -define SPEEX_LIBTOOL_FIXUP - $(SED) 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' $(@D)/libtool - $(SED) 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' $(@D)/libtool -endef - SPEEX_POST_CONFIGURE_HOOKS += SPEEX_LIBTOOL_FIXUP define SPEEX_BUILD_CMDS
Signature · 6 lines
Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286500 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF
PATCH v6 11/13 support/scripts: update check-host-rpath to use the shell helpers
In reply to Samuel Martin---
changes v5->v6:
- new patch
--- support/scripts/check-host-rpath | 67 ++++++++++++++------------------------- support/scripts/shell/readelf.sh | 68 ++++++++++++++++++++++++++++++++++++++++ support/scripts/shell/utils.sh | 18 +++++++++++ 3 files changed, 110 insertions(+), 43 deletions(-)
support/scripts/check-host-rpath +24 -43
@@ -1,12 +1,30 @@ #!/usr/bin/env bash +# Copyright (C) 2015 Yann E. MORIN <[email protected]> +# Copyright (C) 2016 Samuel Martin <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + # This script scans $(HOST_DIR)/{bin,sbin} for all ELF files, and checks # they have an RPATH to $(HOST_DIR)/usr/lib if they need libraries from # there. -# Override the user's locale so we are sure we can parse the output of -# readelf(1) and file(1) -export LC_ALL=C +source "${0%/*}/shell/source.sh" + +source.load_module utils +source.load_module readelf main() { local pkg="${1}"
@@ -18,54 +36,17 @@ main() { ret=0 while read file; do - elf_needs_rpath "${file}" "${hostdir}" || continue - check_elf_has_rpath "${file}" "${hostdir}" && continue + READELF=readelf readelf.needs_rpath "${file}" "${hostdir}" || continue + READELF=readelf readelf.has_rpath "${file}" "${hostdir}" && continue if [ ${ret} -eq 0 ]; then ret=1 printf "***\n" printf "*** ERROR: package %s installs executables without proper RPATH:\n" "${pkg}" fi printf "*** %s\n" "${file}" - done < <( find "${hostdir}"/usr/{bin,sbin} -type f -exec file {} + 2>/dev/null \ - |sed -r -e '/^([^:]+):.*\<ELF\>.*\<executable\>.*/!d' \ - -e 's//\1/' \ - ) + done < <( find "${hostdir}"/usr/{bin,sbin} -type f -print | utils.filter_elf_executable ) return ${ret} } -elf_needs_rpath() { - local file="${1}" - local hostdir="${2}" - local lib - - while read lib; do - [ -e "${hostdir}/usr/lib/${lib}" ] && return 0 - done < <( readelf -d "${file}" \ - |sed -r -e '/^.* \(NEEDED\) .*Shared library: \[(.+)\]$/!d;' \ - -e 's//\1/;' \ - ) - - return 1 -} - -check_elf_has_rpath() { - local file="${1}" - local hostdir="${2}" - local rpath dir - - while read rpath; do - for dir in ${rpath//:/ }; do - # Remove duplicate and trailing '/' for proper match - dir="$( sed -r -e 's:/+:/:g; s:/$::;' <<<"${dir}" )" - [ "${dir}" = "${hostdir}/usr/lib" ] && return 0 - done - done < <( readelf -d "${file}" \ - |sed -r -e '/.* \(R(UN)?PATH\) +Library r(un)?path: \[(.+)\]$/!d' \ - -e 's//\3/;' \ - ) - - return 1 -} - main "${@}"
support/scripts/shell/readelf.sh +68 -0
84 lines not on this page · raw message
support/scripts/shell/utils.sh +18 -0
@@ -18,6 +18,7 @@ # # This module defines the following functions: # utils.list_reduce +# utils.filter_elf_executable # utils.filter_elf source.declare_module utils
@@ -42,6 +43,23 @@ utils.list_reduce() { echo ${lout[@]} } +# utils.filter_elf_executable filepath... +# +# Filter ELF files; if $file is an ELF file, $file is print, else it is +# discarded. +# This funtion can take one or several arguments, or read them from stdin. +# +# file : path of file to be filtered +utils.filter_elf_executable() { + local in file + test ${#} -gt 0 && in='printf "%s\n" ${@}' || in='dd 2>/dev/null' + eval "${in}" | + while read file ; do + file "${file}" 2>/dev/null | + sed -r -e '/^([^:]+):.*\<ELF\>.*\<executable\>.*/!d ; s//\1/' + done +} + # utils.filter_elf filepath... # # Filter ELF files; if $file is an ELF file, $file is print, else it is
Signature · 1 line
2.7.0
PATCH v6 12/13 support/scripts: add check-host-leaks script + all needed helpers
In reply to Samuel Martin---
changes v5->v6:
- new patch
--- support/scripts/check-host-leaks | 63 +++++++++++++++++++++++++++++++++++ support/scripts/shell/readelf.sh | 31 ++++++++++++++++++ support/scripts/shell/sdk.sh | 71 ++++++++++++++++++++++++++++++++++++++++ support/scripts/shell/utils.sh | 64 ++++++++++++++++++++++++++++++++++++ 4 files changed, 229 insertions(+) create mode 100755 support/scripts/check-host-leaks
support/scripts/check-host-leaks new file +63 -0
@@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +# Copyright (C) 2016 Samuel Martin <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +usage() { + cat <<EOF >&2 +Usage: ${0} TREE_DIR TOPDIR BASE_DIR HOST_DIR STAGING_DIR + +Description: + + This script scans a tree for host paths leaks into it. + Print out leaks along side to their kind. + +Arguments: + + TREE_DIR Path to the root of the tree to be scaned + + TOPDIR Buildroot's TOPDIR + + BASE_DIR Buildroot's build output base location + + HOST_DIR Buildroot's host directory + + STAGING_DIR Buildroot's staging directory + +EOF +} + +source "${0%/*}/shell/source.sh" + +READELF=readelf + +source.load_module utils +source.load_module sdk + +main() { + if test ${#} -ne 5 ; then + usage + exit 1 + fi + local to_scan="${1}" + local topdir="${2}" basedir="${3}" hostdir="${4}" stagingdir="${5}" + local gnu_target_name=$( utils.guess_gnu_target_name "${stagingdir}" ) + local tree path + sdk.check_host_leaks "${gnu_target_name}" "${to_scan}" \ + "${topdir}" "${basedir}" "${hostdir}" +} + +main "${@}"
support/scripts/shell/readelf.sh +31 -0
@@ -21,6 +21,8 @@ # readelf.get_rpath # readelf.needs_rpath # readelf.has_rpath +# readelf.list_sections +# readelf.string_section # # This module is sensitive to the following environment variables: # READELF
@@ -118,3 +120,32 @@ readelf.has_rpath() { return 1 } + +# readelf.list_sections file +# +# Return the ELF section list of $file. +# +# file : ELF file path +# +# environment: +# READELF: readelf program path +readelf.list_sections() { + local file="${1}" + "${READELF}" --sections "${file}" | + sed -re '/^ \[ *[0-9]+\] (\S+).*/!d ; s//\1/' | + sort +} + +# readelf.string_section file section +# +# Return the given $section of $file. +# +# file : ELF file path +# section : ELF section name +# +# environment: +# READELF: readelf program path +readelf.string_section() { + local file="${1}" section="${2}" + "${READELF}" --string-dump "${section}" "${file}" 2>/dev/null +}
support/scripts/shell/sdk.sh +71 -0
83 lines not on this page · raw message
support/scripts/shell/utils.sh +64 -0
81 lines not on this page · raw message
Signature · 1 line
2.7.0
PATCH v6 13/13 core: add check-leaks-in-{target, host, staging} targets
In reply to Samuel MartinThis new targets allow identifying what need to be fixed to fulfill the ultimate goal of removing any trace of the host in the target filesystem or the SDK.
---
changes v5->v6:
- new patch
--- Makefile | 15 +++++++++++++++ package/pkg-utils.mk | 5 +++++ 2 files changed, 20 insertions(+)
Makefile +15 -0
@@ -616,6 +616,21 @@ endef TARGET_FINALIZE_HOOKS += PURGE_LOCALES endif +# Checks for build machine leaks into target filesystem, SDK +check-leaks-in-target: + @$(call MESSAGE,Checking leaks in the target) + $(Q)$(call check-for-build-machine-leaks-in,$(TARGET_DIR)) + +check-leaks-in-host: + @$(call MESSAGE,Checking leaks in the host) + $(Q)$(call check-for-build-machine-leaks-in,$(HOST_DIR)) + +check-leaks-in-staging: + @$(call MESSAGE,Checking leaks in the staging) + $(Q)$(call check-for-build-machine-leaks-in,$(STAGING_DIR)) + +check-leaks: check-leaks-in-target check-leaks-in-host check-leaks-in-staging + # RPATH fixing # - The host hook sets RPATH in host ELF binaries, using relative paths to the # library locations.
package/pkg-utils.mk +5 -0
@@ -150,3 +150,8 @@ define legal-license-file # pkg, filename, file-fullpath, {HOST|TARGET} mkdir -p $(LICENSE_FILES_DIR_$(4))/$(1)/$(dir $(2)) && \ cp $(3) $(LICENSE_FILES_DIR_$(4))/$(1)/$(2) endef + +define check-for-build-machine-leaks-in + $(TOPDIR)/support/scripts/check-host-leaks $(1) \ + $(TOPDIR) $(BASE_DIR) $(HOST_DIR) $(STAGING_DIR) +endef
Signature · 1 line
2.7.0