--- /dev/null
+#!/bin/bash
+###############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2021 Pakfire development team #
+# #
+# 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 3 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, see <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+# XXX should this be hardcoded?
+SOURCE_DIR="/builddir/source"
+
+DEBUG_DIR="/usr/lib/debug"
+DEBUG_SOURCE_DIR="/usr/src/debug"
+
+error() {
+ echo "${0#/}: $@" >&2
+}
+
+build_id() {
+ local file="${1}"
+
+ LANG=C readelf -n "${file}" | sed -n "/Build ID/ { s/.*: //p; q; }"
+}
+
+list_sources() {
+ local file="${1}"
+
+ LANG=C readelf "${file}" --debug-dump 2>/dev/null | \
+ awk '/DW_AT_name +:/{name=$NF}/DW_AT_comp_dir +:/{{if (name == "<artificial>") next}{if (name !~ /^[<\/]/) {printf "%s/", $NF}}{print name}}'
+}
+
+extract_sources() {
+ local file="${1}"
+
+ local source
+ for source in $(list_sources "${file}"); do
+ local destination="${source/${SOURCE_DIR}/${debug_source_dir}}"
+ if [ -e "${source}" -a ! -e "${destination}" ]; then
+ mkdir -p "${destination%/*}"
+ if ! install -m 444 -o root -g root "${source}" "${destination}"; then
+ return 1
+ fi
+ fi
+ done
+
+ return 0
+}
+
+process_file() {
+ local file="${1}"
+
+ # The path of the file in BUILDROOT
+ local path="${file/${buildroot}/}"
+
+ echo " ${path}"
+
+ local build_id="$(build_id "${file}")"
+
+ # Check if this file has already been stripped
+ if [ -n "${build_id}" ]; then
+ if [ -f "${debug_dir}/.build-id/${build_id:0:2}/${build_id:2}.debug" ]; then
+ return 0
+ fi
+ else
+ if [ -f "${debug_dir}/${path}.debug" ]; then
+ return 0
+ fi
+ fi
+
+ # Extract sources
+ if ! extract_sources "${file}"; then
+ error "Could not extract sources from ${file}"
+ return 1
+ fi
+
+ mkdir -p "${debug_dir}${path%/*}"
+
+ # Copy all debug sections to the debug directory
+ if ! objcopy --only-keep-debug "${file}" "${debug_dir}/${path}.debug"; then
+ error "Could not extract debug information of ${path}"
+ return 1
+ fi
+
+ local tempfile="$(mktemp "${file}.XXXXXX")"
+
+ # Add a debuglink section to the binary
+ if ! objcopy --add-gnu-debuglink="${debug_dir}/${path}.debug" "${file}" "${tempfile}"; then
+ error "Could not add debuglink section to ${path}"
+ rm -f "${tempfile}"
+ return 1
+ fi
+
+ # Create any hardlinks
+ local link
+ for link in $(find "${buildroot}" -not -path "${file}" -samefile "${file}"); do
+ mkdir -p "${link%/*}"
+
+ if ! ln "${file}" "${link}"; then
+ return 1
+ fi
+ done
+
+ # Create links using build_id
+ if [ -n "${build_id}" ]; then
+ mkdir -p "${debug_dir}/.build-id/${build_id:0:2}"
+
+ # Link to the binary
+ if ! ln -s --relative "${file}" \
+ "${debug_dir}/.build-id/${build_id:0:2}/${build_id:2}"; then
+ return 1
+ fi
+
+ # Link the debug files
+ if ! ln -s --relative "${debug_dir}/${path}.debug" \
+ "${debug_dir}/.build-id/${build_id:0:2}/${build_id:2}.debug"; then
+ return 1
+ fi
+ fi
+
+ # Strip all debug symbols
+ if ! strip --strip-debug "${file}" -o "${tempfile}"; then
+ error "Could not strip ${path}"
+ rm -f "${tempfile}"
+ return 1
+ fi
+
+ # Copy back the stripped file
+ cat "${tempfile}" > "${file}"
+ rm -f "${tempfile}"
+
+ return 0
+}
+
+main() {
+ local buildroot="${1}"
+ shift
+
+ # Check if BUILDROOT exists
+ if [ ! -d "${buildroot}" ]; then
+ error "BUILDROOT does not exist"
+ return 1
+ fi
+
+ echo "Stripping unneeded symbols from binaries and libraries..."
+
+ local debug_dir="${buildroot}${DEBUG_DIR}"
+ local debug_source_dir="${buildroot}${DEBUG_SOURCE_DIR}"
+
+ local file
+ for file in $(find "${buildroot}" -type f \
+ \( -perm -0100 -or -perm -0010 -or -perm -0001 \) | sort); do
+ # Determine the file type
+ local type="$(readelf -h "${file}" 2>/dev/null)"
+
+ case "${type}" in
+ # Libraries and Relocatable binaries
+ *Type:*"DYN (Shared object file)"*)
+ ;;
+
+ # Binaries
+ *Type:*"EXEC (Executable file)"*)
+ ;;
+
+ # Static libraries
+ *Type:*"REL (Relocatable file)"*)
+ ;;
+
+ # Skip any unrecognised files
+ *)
+ continue
+ ;;
+ esac
+
+ if ! process_file "${file}"; then
+ error "Could not strip ${file/${buildroot}/}"
+ return 1
+ fi
+ done
+
+ return 0
+}
+
+main "$@" || exit $?