Skip to contentSkip to conversation

Relocatable SDK / build machine leaks

PATCH Superseded Samuel Martin 3 participants 27 messages Feb 1, 2016 – Feb 3, 2016 Kbuild

v6 of 12 Superseded Latest is v12 →

lore
Share & tools
lore
#0 lore raw

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

#1 lore raw

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
index 1b8b81b..872ef8f 100644
@@ -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
#2 lore raw

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.

---
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
index 1b8b81b..872ef8f 100644

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
#3 lore raw

PATCH v6 2/13 core: use $(CURDIR) to set TOPDIR

In reply to 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

---
changes v5 -> v6:
- new patch

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Makefile +1 -1
index 17c181b..13c16af 100644
@@ -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
#4 lore raw

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

---
changes v5 -> v6:
- new patch

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Makefile +1 -1
index 17c181b..13c16af 100644
@@ -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
#5 lore raw

PATCH v6 3/13 core: re-enter make if $(CURDIR) or $(O) are not absolute canonical path

In reply to 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.

---
changes v5 -> v6:
- new patch

---
 Makefile | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)
Makefile +18 -4
index 13c16af..10193ba 100644
@@ -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
#6 lore raw

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.

---
changes v5 -> v6:
- new patch

---
 Makefile | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)
Makefile +2 -1
index 13c16af..10193ba 100644
@@ -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
#7 lore raw

PATCH v6 3/13 core: re-enter make if $(CURDIR) or $(O) are not absolute canonical path

In reply to Samuel Martin

Hello,

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.

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
#8 lore raw

PATCH v6 4/13 core: staging symlink uses a relative path when possible

In reply to Samuel Martin

A 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
index 10193ba..7c87177 100644
@@ -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
#9 lore raw

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
#10 lore raw

PATCH v6 5/13 core: make staging *-config scripts relocatable

In reply to Samuel Martin

This 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
index 1e024d3..1bf613e 100644
@@ -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
#11 lore raw

PATCH v6 5/13 core: make staging *-config scripts relocatable

Quoted 21 lines · Samuel Martin

This 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 +0 -0
index 1e024d3..1bf613e 100644

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
#12 lore raw

PATCH v6 6/13 core: make host *-config scripts relocatable

In reply to Samuel Martin

This 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
index 1bf613e..ca79450 100644
@@ -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
#13 lore raw

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
index 1bf613e..ca79450 100644
@@ -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
#14 lore raw

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
index 1bf613e..ca79450 100644
@@ -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
#15 lore raw

PATCH v6 6/13 core: make host *-config scripts relocatable

In reply to Samuel Martin
Quoted 33 lines · Samuel Martin

This 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 +0 -0
index 1bf613e..ca79450 100644
@@ -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
#16 lore raw

PATCH v6 7/13 support/scripts: add fix-rpath script + a bunch of helpers

In reply to 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, 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
new file mode 100755
index 0000000..938e599
@@ -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
#17 lore raw

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, 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 +15 -0
new file mode 100755
index 0000000..938e599
@@ -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
new file mode 100644
index 0000000..ffa19e8
@@ -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
new file mode 100644
index 0000000..d1eb590
@@ -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
new file mode 100644
index 0000000..82968a2
@@ -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
#18 lore raw

PATCH v6 8/13 core: add HOST_SANITIZE_RPATH_HOOK to TARGET_FINALIZE_HOOKS

In reply to Samuel Martin

This 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
index 7c87177..b1f4fcf 100644
@@ -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
#19 lore raw

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_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 +5 -0
index 7c87177..b1f4fcf 100644
@@ -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}. If
BR2_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
#20 lore raw

PATCH v6 9/13 core: add {TARGET, STAGING}_SANITIZE_RPATH_HOOK to TARGET_FINALIZE_HOOKS

In reply to Samuel Martin

This 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
index b1f4fcf..eb8a037 100644
@@ -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
#21 lore raw

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_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 +5 -0
index b1f4fcf..eb8a037 100644
@@ -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
#22 lore raw

PATCH v6 10/13 package/speex: remove no longer needed hook

In reply to Samuel Martin

Remove 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
index a34bfac..24782ec 100644
@@ -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
#23 lore raw

PATCH v6 10/13 package/speex: remove no longer needed hook

Quoted 4 lines · Samuel Martin

Remove the LIBTOOL_FIXUP hook since RPATH are now sanitized in target-finalize hooks.

Regards,
Arnout

Quoted 28 lines

---
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
index a34bfac..24782ec 100644
@@ -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
#24 lore raw

PATCH v6 11/13 support/scripts: update check-host-rpath to use the shell helpers

In reply to Samuel Martin
Cc "Yann E. MORIN" <[email protected]>

---
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
index 48d69da..55be97e 100755
@@ -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
index 6b071fc..b49a541 100644
@@ -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
#25 lore raw

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
new file mode 100755
index 0000000..42da272
@@ -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
index e0549d2..81ebbb8 100644
@@ -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
#26 lore raw

PATCH v6 13/13 core: add check-leaks-in-{target, host, staging} targets

In reply to Samuel Martin

This 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
index eb8a037..a74a016 100644
@@ -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
index 44bd2c9..21ad5ae 100644
@@ -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