Support stripping shared libraries and binaries
Strip all shared libraries and binaries by default. Use a shell script to wrap the long sequences of commands needed by some strip variants. Change-Id: I465bf7cc48330913e60e24762fd55fa2a7731c26
This commit is contained in:
@@ -101,6 +101,18 @@ var (
|
|||||||
},
|
},
|
||||||
"objcopyCmd", "prefix")
|
"objcopyCmd", "prefix")
|
||||||
|
|
||||||
|
stripPath = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
|
||||||
|
|
||||||
|
strip = pctx.StaticRule("strip",
|
||||||
|
blueprint.RuleParams{
|
||||||
|
Depfile: "${out}.d",
|
||||||
|
Deps: blueprint.DepsGCC,
|
||||||
|
Command: "CROSS_COMPILE=$crossCompile $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
|
||||||
|
CommandDeps: []string{"$stripPath"},
|
||||||
|
Description: "strip $out",
|
||||||
|
},
|
||||||
|
"args", "crossCompile")
|
||||||
|
|
||||||
copyGccLibPath = pctx.SourcePathVariable("copyGccLibPath", "build/soong/scripts/copygcclib.sh")
|
copyGccLibPath = pctx.SourcePathVariable("copyGccLibPath", "build/soong/scripts/copygcclib.sh")
|
||||||
|
|
||||||
copyGccLib = pctx.StaticRule("copyGccLib",
|
copyGccLib = pctx.StaticRule("copyGccLib",
|
||||||
@@ -138,6 +150,10 @@ type builderFlags struct {
|
|||||||
nocrt bool
|
nocrt bool
|
||||||
toolchain Toolchain
|
toolchain Toolchain
|
||||||
clang bool
|
clang bool
|
||||||
|
|
||||||
|
stripKeepSymbols bool
|
||||||
|
stripKeepMiniDebugInfo bool
|
||||||
|
stripAddGnuDebuglink bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
|
// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
|
||||||
@@ -397,6 +413,32 @@ func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TransformStrip(ctx common.AndroidModuleContext, inputFile common.Path,
|
||||||
|
outputFile common.WritablePath, flags builderFlags) {
|
||||||
|
|
||||||
|
crossCompile := gccCmd(flags.toolchain, "")
|
||||||
|
args := ""
|
||||||
|
if flags.stripAddGnuDebuglink {
|
||||||
|
args += " --add-gnu-debuglink"
|
||||||
|
}
|
||||||
|
if flags.stripKeepMiniDebugInfo {
|
||||||
|
args += " --keep-mini-debug-info"
|
||||||
|
}
|
||||||
|
if flags.stripKeepSymbols {
|
||||||
|
args += " --keep-symbols"
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.ModuleBuild(pctx, common.ModuleBuildParams{
|
||||||
|
Rule: strip,
|
||||||
|
Output: outputFile,
|
||||||
|
Input: inputFile,
|
||||||
|
Args: map[string]string{
|
||||||
|
"crossCompile": crossCompile,
|
||||||
|
"args": args,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func CopyGccLib(ctx common.AndroidModuleContext, libName string,
|
func CopyGccLib(ctx common.AndroidModuleContext, libName string,
|
||||||
flags builderFlags, outputFile common.WritablePath) {
|
flags builderFlags, outputFile common.WritablePath) {
|
||||||
|
|
||||||
|
83
cc/cc.go
83
cc/cc.go
@@ -434,10 +434,16 @@ type InstallerProperties struct {
|
|||||||
Relative_install_path string
|
Relative_install_path string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StripProperties struct {
|
||||||
|
Strip struct {
|
||||||
|
None bool
|
||||||
|
Keep_symbols bool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type UnusedProperties struct {
|
type UnusedProperties struct {
|
||||||
Native_coverage *bool
|
Native_coverage *bool
|
||||||
Required []string
|
Required []string
|
||||||
Strip string
|
|
||||||
Tags []string
|
Tags []string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1441,6 +1447,7 @@ func (library *libraryCompiler) compile(ctx ModuleContext, flags Flags, deps Pat
|
|||||||
type libraryLinker struct {
|
type libraryLinker struct {
|
||||||
baseLinker
|
baseLinker
|
||||||
flagExporter
|
flagExporter
|
||||||
|
stripper
|
||||||
|
|
||||||
Properties LibraryLinkerProperties
|
Properties LibraryLinkerProperties
|
||||||
|
|
||||||
@@ -1465,7 +1472,8 @@ func (library *libraryLinker) props() []interface{} {
|
|||||||
return append(props,
|
return append(props,
|
||||||
&library.Properties,
|
&library.Properties,
|
||||||
&library.dynamicProperties,
|
&library.dynamicProperties,
|
||||||
&library.flagExporter.Properties)
|
&library.flagExporter.Properties,
|
||||||
|
&library.stripper.StripProperties)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (library *libraryLinker) flags(ctx ModuleContext, flags Flags) Flags {
|
func (library *libraryLinker) flags(ctx ModuleContext, flags Flags) Flags {
|
||||||
@@ -1554,9 +1562,6 @@ func (library *libraryLinker) linkStatic(ctx ModuleContext,
|
|||||||
func (library *libraryLinker) linkShared(ctx ModuleContext,
|
func (library *libraryLinker) linkShared(ctx ModuleContext,
|
||||||
flags Flags, deps PathDeps, objFiles common.Paths) common.Path {
|
flags Flags, deps PathDeps, objFiles common.Paths) common.Path {
|
||||||
|
|
||||||
outputFile := common.PathForModuleOut(ctx,
|
|
||||||
ctx.ModuleName()+library.Properties.VariantName+flags.Toolchain.ShlibSuffix())
|
|
||||||
|
|
||||||
var linkerDeps common.Paths
|
var linkerDeps common.Paths
|
||||||
|
|
||||||
versionScript := common.OptionalPathForModuleSrc(ctx, library.Properties.Version_script)
|
versionScript := common.OptionalPathForModuleSrc(ctx, library.Properties.Version_script)
|
||||||
@@ -1595,14 +1600,26 @@ func (library *libraryLinker) linkShared(ctx ModuleContext,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileName := ctx.ModuleName() + library.Properties.VariantName + flags.Toolchain.ShlibSuffix()
|
||||||
|
outputFile := common.PathForModuleOut(ctx, fileName)
|
||||||
|
ret := outputFile
|
||||||
|
|
||||||
|
builderFlags := flagsToBuilderFlags(flags)
|
||||||
|
|
||||||
|
if library.stripper.needsStrip(ctx) {
|
||||||
|
strippedOutputFile := outputFile
|
||||||
|
outputFile = common.PathForModuleOut(ctx, "unstripped", fileName)
|
||||||
|
library.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
|
||||||
|
}
|
||||||
|
|
||||||
sharedLibs := deps.SharedLibs
|
sharedLibs := deps.SharedLibs
|
||||||
sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
|
sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
|
||||||
|
|
||||||
TransformObjToDynamicBinary(ctx, objFiles, sharedLibs,
|
TransformObjToDynamicBinary(ctx, objFiles, sharedLibs,
|
||||||
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
|
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
|
||||||
linkerDeps, deps.CrtBegin, deps.CrtEnd, false, flagsToBuilderFlags(flags), outputFile)
|
linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile)
|
||||||
|
|
||||||
return outputFile
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (library *libraryLinker) link(ctx ModuleContext,
|
func (library *libraryLinker) link(ctx ModuleContext,
|
||||||
@@ -1746,6 +1763,7 @@ func (*objectLinker) installable() bool {
|
|||||||
|
|
||||||
type binaryLinker struct {
|
type binaryLinker struct {
|
||||||
baseLinker
|
baseLinker
|
||||||
|
stripper
|
||||||
|
|
||||||
Properties BinaryLinkerProperties
|
Properties BinaryLinkerProperties
|
||||||
|
|
||||||
@@ -1755,7 +1773,10 @@ type binaryLinker struct {
|
|||||||
var _ linker = (*binaryLinker)(nil)
|
var _ linker = (*binaryLinker)(nil)
|
||||||
|
|
||||||
func (binary *binaryLinker) props() []interface{} {
|
func (binary *binaryLinker) props() []interface{} {
|
||||||
return append(binary.baseLinker.props(), &binary.Properties)
|
return append(binary.baseLinker.props(),
|
||||||
|
&binary.Properties,
|
||||||
|
&binary.stripper.StripProperties)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (binary *binaryLinker) buildStatic() bool {
|
func (binary *binaryLinker) buildStatic() bool {
|
||||||
@@ -1906,18 +1927,12 @@ func (binary *binaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
|
|||||||
func (binary *binaryLinker) link(ctx ModuleContext,
|
func (binary *binaryLinker) link(ctx ModuleContext,
|
||||||
flags Flags, deps PathDeps, objFiles common.Paths) common.Path {
|
flags Flags, deps PathDeps, objFiles common.Paths) common.Path {
|
||||||
|
|
||||||
outputFile := common.PathForModuleOut(ctx, binary.getStem(ctx)+flags.Toolchain.ExecutableSuffix())
|
fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
|
||||||
|
outputFile := common.PathForModuleOut(ctx, fileName)
|
||||||
|
ret := outputFile
|
||||||
if ctx.HostOrDevice().Host() {
|
if ctx.HostOrDevice().Host() {
|
||||||
binary.hostToolPath = common.OptionalPathForPath(outputFile)
|
binary.hostToolPath = common.OptionalPathForPath(outputFile)
|
||||||
}
|
}
|
||||||
ret := outputFile
|
|
||||||
|
|
||||||
if binary.Properties.Prefix_symbols != "" {
|
|
||||||
afterPrefixSymbols := outputFile
|
|
||||||
outputFile = common.PathForModuleOut(ctx, binary.getStem(ctx)+".intermediate")
|
|
||||||
TransformBinaryPrefixSymbols(ctx, binary.Properties.Prefix_symbols, outputFile,
|
|
||||||
flagsToBuilderFlags(flags), afterPrefixSymbols)
|
|
||||||
}
|
|
||||||
|
|
||||||
var linkerDeps common.Paths
|
var linkerDeps common.Paths
|
||||||
|
|
||||||
@@ -1928,9 +1943,24 @@ func (binary *binaryLinker) link(ctx ModuleContext,
|
|||||||
flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
|
flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builderFlags := flagsToBuilderFlags(flags)
|
||||||
|
|
||||||
|
if binary.stripper.needsStrip(ctx) {
|
||||||
|
strippedOutputFile := outputFile
|
||||||
|
outputFile = common.PathForModuleOut(ctx, "unstripped", fileName)
|
||||||
|
binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
if binary.Properties.Prefix_symbols != "" {
|
||||||
|
afterPrefixSymbols := outputFile
|
||||||
|
outputFile = common.PathForModuleOut(ctx, "unprefixed", fileName)
|
||||||
|
TransformBinaryPrefixSymbols(ctx, binary.Properties.Prefix_symbols, outputFile,
|
||||||
|
flagsToBuilderFlags(flags), afterPrefixSymbols)
|
||||||
|
}
|
||||||
|
|
||||||
TransformObjToDynamicBinary(ctx, objFiles, sharedLibs, deps.StaticLibs,
|
TransformObjToDynamicBinary(ctx, objFiles, sharedLibs, deps.StaticLibs,
|
||||||
deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
|
deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
|
||||||
flagsToBuilderFlags(flags), outputFile)
|
builderFlags, outputFile)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@@ -1939,6 +1969,22 @@ func (binary *binaryLinker) HostToolPath() common.OptionalPath {
|
|||||||
return binary.hostToolPath
|
return binary.hostToolPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type stripper struct {
|
||||||
|
StripProperties StripProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
func (stripper *stripper) needsStrip(ctx ModuleContext) bool {
|
||||||
|
return !ctx.AConfig().EmbeddedInMake() && !stripper.StripProperties.Strip.None
|
||||||
|
}
|
||||||
|
|
||||||
|
func (stripper *stripper) strip(ctx ModuleContext, in, out common.ModuleOutPath,
|
||||||
|
flags builderFlags) {
|
||||||
|
flags.stripKeepSymbols = stripper.StripProperties.Strip.Keep_symbols
|
||||||
|
// TODO(ccross): don't add gnu debuglink for user builds
|
||||||
|
flags.stripAddGnuDebuglink = true
|
||||||
|
TransformStrip(ctx, in, out, flags)
|
||||||
|
}
|
||||||
|
|
||||||
func testPerSrcMutator(mctx common.AndroidBottomUpMutatorContext) {
|
func testPerSrcMutator(mctx common.AndroidBottomUpMutatorContext) {
|
||||||
if m, ok := mctx.Module().(*Module); ok {
|
if m, ok := mctx.Module().(*Module); ok {
|
||||||
if test, ok := m.linker.(*testLinker); ok {
|
if test, ok := m.linker.(*testLinker); ok {
|
||||||
@@ -2155,6 +2201,7 @@ func defaultsFactory() (blueprint.Module, []interface{}) {
|
|||||||
&UnusedProperties{},
|
&UnusedProperties{},
|
||||||
&StlProperties{},
|
&StlProperties{},
|
||||||
&SanitizeProperties{},
|
&SanitizeProperties{},
|
||||||
|
&StripProperties{},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, propertyStructs = common.InitAndroidArchModule(module, common.HostAndDeviceDefault,
|
_, propertyStructs = common.InitAndroidArchModule(module, common.HostAndDeviceDefault,
|
||||||
|
122
scripts/strip.sh
Executable file
122
scripts/strip.sh
Executable file
@@ -0,0 +1,122 @@
|
|||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# Script to handle the various ways soong may need to strip binaries
|
||||||
|
# Inputs:
|
||||||
|
# Environment:
|
||||||
|
# CROSS_COMPILE: prefix added to readelf, objcopy tools
|
||||||
|
# Arguments:
|
||||||
|
# -o ${file}: output file (required)
|
||||||
|
# -d ${file}: deps file (required)
|
||||||
|
# --keep-symbols
|
||||||
|
# --keep-mini-debug-info
|
||||||
|
# --add-gnu-debuglink
|
||||||
|
|
||||||
|
OPTSTRING=d:i:o:-:
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: strip.sh [options] -i in-file -o out-file -d deps-file
|
||||||
|
Options:
|
||||||
|
--keep-symbols Keep symbols in out-file
|
||||||
|
--keep-mini-debug-info Keep compressed debug info in out-file
|
||||||
|
--add-gnu-debuglink Add a gnu-debuglink section to out-file
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
do_strip() {
|
||||||
|
"${CROSS_COMPILE}strip" --strip-all "${infile}" -o "${outfile}.tmp"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_strip_keep_symbols() {
|
||||||
|
"${CROSS_COMPILE}objcopy" "${infile}" "${outfile}.tmp" \
|
||||||
|
`"${CROSS_COMPILE}readelf" -S "${infile}" | awk '/.debug_/ {print "-R " $2}' | xargs`
|
||||||
|
}
|
||||||
|
|
||||||
|
do_strip_keep_mini_debug_info() {
|
||||||
|
"${CROSS_COMPILE}nm" -D "${infile}" --format=posix --defined-only | awk '{ print $$1 }' | sort >"${outfile}.dynsyms"
|
||||||
|
"${CROSS_COMPILE}nm" "${infile}" --format=posix --defined-only | awk '{ if ($$2 == "T" || $$2 == "t" || $$2 == "D") print $$1 }' | sort > "${outfile}.funcsyms"
|
||||||
|
comm -13 "${outfile}.dynsyms" "${outfile}.funcsyms" > "${outfile}.keep_symbols"
|
||||||
|
"${CROSS_COMPILE}objcopy" --only-keep-debug "${infile}" "${outfile}.debug"
|
||||||
|
"${CROSS_COMPILE}objcopy" --rename-section .debug_frame=saved_debug_frame "${outfile}.debug" "${outfile}.mini_debuginfo"
|
||||||
|
"${CROSS_COMPILE}objcopy" -S --remove-section .gdb_index --remove-section .comment --keep-symbols="${outfile}.keep_symbols" "${outfile}.mini_debuginfo"
|
||||||
|
"${CROSS_COMPILE}objcopy" --rename-section saved_debug_frame=.debug_frame "${outfile}.mini_debuginfo"
|
||||||
|
"${CROSS_COMPILE}strip" --strip-all -R .comment "${infile}" -o "${outfile}.tmp"
|
||||||
|
rm -f "${outfile}.mini_debuginfo.xz"
|
||||||
|
xz "${outfile}.mini_debuginfo"
|
||||||
|
"${CROSS_COMPILE}objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
|
||||||
|
rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo.xz"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_add_gnu_debuglink() {
|
||||||
|
"${CROSS_COMPILE}objcopy" --add-gnu-debuglink="${infile}" "${outfile}.tmp"
|
||||||
|
}
|
||||||
|
|
||||||
|
while getopts $OPTSTRING opt; do
|
||||||
|
case "$opt" in
|
||||||
|
d) depsfile="${OPTARG}" ;;
|
||||||
|
i) infile="${OPTARG}" ;;
|
||||||
|
o) outfile="${OPTARG}" ;;
|
||||||
|
-)
|
||||||
|
case "${OPTARG}" in
|
||||||
|
keep-symbols) keep_symbols=true ;;
|
||||||
|
keep-mini-debug-info) keep_mini_debug_info=true ;;
|
||||||
|
add-gnu-debuglink) add_gnu_debuglink=true ;;
|
||||||
|
*) echo "Unknown option --${OPTARG}"; usage ;;
|
||||||
|
esac;;
|
||||||
|
?) usage ;;
|
||||||
|
*) echo "'${opt}' '${OPTARG}'"
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "${infile}" ]; then
|
||||||
|
echo "-i argument is required"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${outfile}" ]; then
|
||||||
|
echo "-o argument is required"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${depsfile}" ]; then
|
||||||
|
echo "-d argument is required"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "${keep_symbols}" -a ! -z "${keep_mini_debug_info}" ]; then
|
||||||
|
echo "--keep-symbols and --keep-mini-debug-info cannot be used together"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "${add_gnu_debuglink}" -a ! -z "${keep_mini_debug_info}" ]; then
|
||||||
|
echo "--add-gnu-debuglink cannot be used with --keep-mini-debug-info"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "${outfile}.tmp"
|
||||||
|
|
||||||
|
if [ ! -z "${keep_symbols}" ]; then
|
||||||
|
do_strip_keep_symbols
|
||||||
|
elif [ ! -z "${keep_mini_debug_info}" ]; then
|
||||||
|
do_strip_keep_mini_debug_info
|
||||||
|
else
|
||||||
|
do_strip
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "${add_gnu_debuglink}" ]; then
|
||||||
|
do_add_gnu_debuglink
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "${outfile}"
|
||||||
|
mv "${outfile}.tmp" "${outfile}"
|
||||||
|
|
||||||
|
cat <<EOF > "${depsfile}"
|
||||||
|
${outfile}: \
|
||||||
|
${infile} \
|
||||||
|
${CROSS_COMPILE}nm \
|
||||||
|
${CROSS_COMPILE}objcopy \
|
||||||
|
${CROSS_COMPILE}readelf \
|
||||||
|
${CROSS_COMPILE}strip
|
||||||
|
|
||||||
|
EOF
|
Reference in New Issue
Block a user