1#!/bin/bash -e 2 3# Copyright 2017 Google Inc. All rights reserved. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17# Script to handle the various ways soong may need to strip binaries 18# Inputs: 19# Environment: 20# CLANG_BIN: path to the clang bin directory 21# CROSS_COMPILE: prefix added to readelf, objcopy tools 22# XZ: path to the xz binary 23# Arguments: 24# -i ${file}: input file (required) 25# -o ${file}: output file (required) 26# -d ${file}: deps file (required) 27# -k symbols: Symbols to keep (optional) 28# --add-gnu-debuglink 29# --keep-mini-debug-info 30# --keep-symbols 31# --use-gnu-strip 32# --remove-build-id 33 34set -o pipefail 35 36OPTSTRING=d:i:o:k:-: 37 38usage() { 39 cat <<EOF 40Usage: strip.sh [options] -k symbols -i in-file -o out-file -d deps-file 41Options: 42 --add-gnu-debuglink Add a gnu-debuglink section to out-file 43 --keep-mini-debug-info Keep compressed debug info in out-file 44 --keep-symbols Keep symbols in out-file 45 --use-gnu-strip Use strip/objcopy instead of llvm-{strip,objcopy} 46 --remove-build-id Remove the gnu build-id section in out-file 47EOF 48 exit 1 49} 50 51# Without --use-gnu-strip, GNU strip is replaced with llvm-strip to work around 52# old GNU strip bug on lld output files, b/80093681. 53# Similary, calls to objcopy are replaced with llvm-objcopy, 54# with some exceptions. 55 56do_strip() { 57 # ${CROSS_COMPILE}strip --strip-all does not strip .ARM.attributes, 58 # so we tell llvm-strip to keep it too. 59 if [ -z "${use_gnu_strip}" ]; then 60 "${CLANG_BIN}/llvm-strip" --strip-all -keep-section=.ARM.attributes "${infile}" -o "${outfile}.tmp" 61 else 62 "${CROSS_COMPILE}strip" --strip-all "${infile}" -o "${outfile}.tmp" 63 fi 64} 65 66do_strip_keep_symbols() { 67 REMOVE_SECTIONS=`"${CROSS_COMPILE}readelf" -S "${infile}" | awk '/.debug_/ {print "--remove-section " $2}' | xargs` 68 if [ -z "${use_gnu_strip}" ]; then 69 "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS} 70 else 71 "${CROSS_COMPILE}objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS} 72 fi 73} 74 75do_strip_keep_symbol_list() { 76 if [ -z "${use_gnu_strip}" ]; then 77 echo "do_strip_keep_symbol_list does not work with llvm-objcopy" 78 echo "http://b/131631155" 79 usage 80 fi 81 82 echo "${symbols_to_keep}" | tr ',' '\n' > "${outfile}.symbolList" 83 KEEP_SYMBOLS="-w --strip-unneeded-symbol=* --keep-symbols=" 84 KEEP_SYMBOLS+="${outfile}.symbolList" 85 86 "${CROSS_COMPILE}objcopy" "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS} 87} 88 89do_strip_keep_mini_debug_info() { 90 rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz" 91 local fail= 92 if [ -z "${use_gnu_strip}" ]; then 93 "${CLANG_BIN}/llvm-strip" --strip-all -keep-section=.ARM.attributes -remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true 94 else 95 "${CROSS_COMPILE}strip" --strip-all -R .comment "${infile}" -o "${outfile}.tmp" || fail=true 96 fi 97 if [ -z $fail ]; then 98 # Current prebult llvm-objcopy does not support the following flags: 99 # --only-keep-debug --rename-section --keep-symbols 100 # For the following use cases, ${CROSS_COMPILE}objcopy does fine with lld linked files, 101 # except the --add-section flag. 102 "${CROSS_COMPILE}objcopy" --only-keep-debug "${infile}" "${outfile}.debug" 103 "${CROSS_COMPILE}nm" -D "${infile}" --format=posix --defined-only 2> /dev/null | awk '{ print $1 }' | sort >"${outfile}.dynsyms" 104 "${CROSS_COMPILE}nm" "${infile}" --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t" || $2 == "D") print $1 }' | sort > "${outfile}.funcsyms" 105 comm -13 "${outfile}.dynsyms" "${outfile}.funcsyms" > "${outfile}.keep_symbols" 106 echo >> "${outfile}.keep_symbols" # Ensure that the keep_symbols file is not empty. 107 "${CROSS_COMPILE}objcopy" --rename-section .debug_frame=saved_debug_frame "${outfile}.debug" "${outfile}.mini_debuginfo" 108 "${CROSS_COMPILE}objcopy" -S --remove-section .gdb_index --remove-section .comment --keep-symbols="${outfile}.keep_symbols" "${outfile}.mini_debuginfo" 109 "${CROSS_COMPILE}objcopy" --rename-section saved_debug_frame=.debug_frame "${outfile}.mini_debuginfo" 110 "${XZ}" "${outfile}.mini_debuginfo" 111 if [ -z "${use_gnu_strip}" ]; then 112 "${CLANG_BIN}/llvm-objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp" 113 else 114 "${CROSS_COMPILE}objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp" 115 fi 116 rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz" 117 else 118 cp -f "${infile}" "${outfile}.tmp" 119 fi 120} 121 122do_add_gnu_debuglink() { 123 if [ -z "${use_gnu_strip}" ]; then 124 "${CLANG_BIN}/llvm-objcopy" --add-gnu-debuglink="${infile}" "${outfile}.tmp" 125 else 126 "${CROSS_COMPILE}objcopy" --add-gnu-debuglink="${infile}" "${outfile}.tmp" 127 fi 128} 129 130do_remove_build_id() { 131 if [ -z "${use_gnu_strip}" ]; then 132 "${CLANG_BIN}/llvm-strip" -remove-section=.note.gnu.build-id "${outfile}.tmp" -o "${outfile}.tmp.no-build-id" 133 else 134 "${CROSS_COMPILE}strip" --remove-section=.note.gnu.build-id "${outfile}.tmp" -o "${outfile}.tmp.no-build-id" 135 fi 136 rm -f "${outfile}.tmp" 137 mv "${outfile}.tmp.no-build-id" "${outfile}.tmp" 138} 139 140while getopts $OPTSTRING opt; do 141 case "$opt" in 142 d) depsfile="${OPTARG}" ;; 143 i) infile="${OPTARG}" ;; 144 o) outfile="${OPTARG}" ;; 145 k) symbols_to_keep="${OPTARG}" ;; 146 -) 147 case "${OPTARG}" in 148 add-gnu-debuglink) add_gnu_debuglink=true ;; 149 keep-mini-debug-info) keep_mini_debug_info=true ;; 150 keep-symbols) keep_symbols=true ;; 151 remove-build-id) remove_build_id=true ;; 152 use-gnu-strip) use_gnu_strip=true ;; 153 *) echo "Unknown option --${OPTARG}"; usage ;; 154 esac;; 155 ?) usage ;; 156 *) echo "'${opt}' '${OPTARG}'" 157 esac 158done 159 160if [ -z "${infile}" ]; then 161 echo "-i argument is required" 162 usage 163fi 164 165if [ -z "${outfile}" ]; then 166 echo "-o argument is required" 167 usage 168fi 169 170if [ -z "${depsfile}" ]; then 171 echo "-d argument is required" 172 usage 173fi 174 175if [ ! -z "${keep_symbols}" -a ! -z "${keep_mini_debug_info}" ]; then 176 echo "--keep-symbols and --keep-mini-debug-info cannot be used together" 177 usage 178fi 179 180if [ ! -z "${symbols_to_keep}" -a ! -z "${keep_symbols}" ]; then 181 echo "--keep-symbols and -k cannot be used together" 182 usage 183fi 184 185if [ ! -z "${add_gnu_debuglink}" -a ! -z "${keep_mini_debug_info}" ]; then 186 echo "--add-gnu-debuglink cannot be used with --keep-mini-debug-info" 187 usage 188fi 189 190rm -f "${outfile}.tmp" 191 192if [ ! -z "${keep_symbols}" ]; then 193 do_strip_keep_symbols 194elif [ ! -z "${symbols_to_keep}" ]; then 195 do_strip_keep_symbol_list 196elif [ ! -z "${keep_mini_debug_info}" ]; then 197 do_strip_keep_mini_debug_info 198else 199 do_strip 200fi 201 202if [ ! -z "${add_gnu_debuglink}" ]; then 203 do_add_gnu_debuglink 204fi 205 206if [ ! -z "${remove_build_id}" ]; then 207 do_remove_build_id 208fi 209 210rm -f "${outfile}" 211mv "${outfile}.tmp" "${outfile}" 212 213if [ -z "${use_gnu_strip}" ]; then 214 USED_STRIP_OBJCOPY="${CLANG_BIN}/llvm-strip ${CLANG_BIN}/llvm-objcopy" 215else 216 USED_STRIP_OBJCOPY="${CROSS_COMPILE}strip" 217fi 218 219cat <<EOF > "${depsfile}" 220${outfile}: \ 221 ${infile} \ 222 ${CROSS_COMPILE}nm \ 223 ${CROSS_COMPILE}objcopy \ 224 ${CROSS_COMPILE}readelf \ 225 ${USED_STRIP_OBJCOPY} 226 227EOF 228