Add an option to preserve symbols and debug_frame.

New strip option named keep_symbols_and_debug_frame, that will keep the
symbols and the .debug_frame. This is meant for use by libc.so only on
arm32. Other libraries might want to use it to keep better unwinding
information on device.

Bug: 132992102

Test: Built libc.so with this option and verified that it contains
Test: the .debug_frame section.
Change-Id: I823a28199dec8316e8b26fe31ff9f17e6b11d406
diff --git a/cc/builder.go b/cc/builder.go
index c99e461..0a28672 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -254,11 +254,12 @@
 
 	groupStaticLibs bool
 
-	stripKeepSymbols       bool
-	stripKeepSymbolsList   string
-	stripKeepMiniDebugInfo bool
-	stripAddGnuDebuglink   bool
-	stripUseGnuStrip       bool
+	stripKeepSymbols              bool
+	stripKeepSymbolsList          string
+	stripKeepSymbolsAndDebugFrame bool
+	stripKeepMiniDebugInfo        bool
+	stripAddGnuDebuglink          bool
+	stripUseGnuStrip              bool
 
 	proto            android.ProtoFlags
 	protoC           bool
@@ -839,6 +840,9 @@
 	if flags.stripKeepSymbolsList != "" {
 		args += " -k" + flags.stripKeepSymbolsList
 	}
+	if flags.stripKeepSymbolsAndDebugFrame {
+		args += " --keep-symbols-and-debug-frame"
+	}
 	if flags.stripUseGnuStrip {
 		args += " --use-gnu-strip"
 	}
diff --git a/cc/strip.go b/cc/strip.go
index 7122585..4daa759 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -22,11 +22,12 @@
 
 type StripProperties struct {
 	Strip struct {
-		None              *bool    `android:"arch_variant"`
-		All               *bool    `android:"arch_variant"`
-		Keep_symbols      *bool    `android:"arch_variant"`
-		Keep_symbols_list []string `android:"arch_variant"`
-		Use_gnu_strip     *bool    `android:"arch_variant"`
+		None                         *bool    `android:"arch_variant"`
+		All                          *bool    `android:"arch_variant"`
+		Keep_symbols                 *bool    `android:"arch_variant"`
+		Keep_symbols_list            []string `android:"arch_variant"`
+		Keep_symbols_and_debug_frame *bool    `android:"arch_variant"`
+		Use_gnu_strip                *bool    `android:"arch_variant"`
 	} `android:"arch_variant"`
 }
 
@@ -46,6 +47,8 @@
 	} else {
 		if Bool(stripper.StripProperties.Strip.Keep_symbols) {
 			flags.stripKeepSymbols = true
+		} else if Bool(stripper.StripProperties.Strip.Keep_symbols_and_debug_frame) {
+			flags.stripKeepSymbolsAndDebugFrame = true
 		} else if len(stripper.StripProperties.Strip.Keep_symbols_list) > 0 {
 			flags.stripKeepSymbolsList = strings.Join(stripper.StripProperties.Strip.Keep_symbols_list, ",")
 		} else if !Bool(stripper.StripProperties.Strip.All) {
diff --git a/scripts/strip.sh b/scripts/strip.sh
index 0f77da8..bd62619 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -28,6 +28,7 @@
 #   --add-gnu-debuglink
 #   --keep-mini-debug-info
 #   --keep-symbols
+#   --keep-symbols-and-debug-frame
 #   --use-gnu-strip
 #   --remove-build-id
 
@@ -39,11 +40,12 @@
     cat <<EOF
 Usage: strip.sh [options] -k symbols -i in-file -o out-file -d deps-file
 Options:
-        --add-gnu-debuglink     Add a gnu-debuglink section to out-file
-        --keep-mini-debug-info  Keep compressed debug info in out-file
-        --keep-symbols          Keep symbols in out-file
-        --use-gnu-strip         Use strip/objcopy instead of llvm-{strip,objcopy}
-        --remove-build-id       Remove the gnu build-id section in out-file
+        --add-gnu-debuglink             Add a gnu-debuglink section to out-file
+        --keep-mini-debug-info          Keep compressed debug info in out-file
+        --keep-symbols                  Keep symbols in out-file
+        --keep-symbols-and-debug-frame  Keep symbols and .debug_frame in out-file
+        --use-gnu-strip                 Use strip/objcopy instead of llvm-{strip,objcopy}
+        --remove-build-id               Remove the gnu build-id section in out-file
 EOF
     exit 1
 }
@@ -63,6 +65,15 @@
     fi
 }
 
+do_strip_keep_symbols_and_debug_frame() {
+    REMOVE_SECTIONS=`"${CROSS_COMPILE}readelf" -S "${infile}" | awk '/.debug_/ {if ($2 != ".debug_frame") {print "--remove-section " $2}}' | xargs`
+    if [ -z "${use_gnu_strip}" ]; then
+        "${CLANG_BIN}/llvm-objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
+    else
+        "${CROSS_COMPILE}objcopy" "${infile}" "${outfile}.tmp" ${REMOVE_SECTIONS}
+    fi
+}
+
 do_strip_keep_symbols() {
     REMOVE_SECTIONS=`"${CROSS_COMPILE}readelf" -S "${infile}" | awk '/.debug_/ {print "--remove-section " $2}' | xargs`
     if [ -z "${use_gnu_strip}" ]; then
@@ -148,6 +159,7 @@
                 add-gnu-debuglink) add_gnu_debuglink=true ;;
                 keep-mini-debug-info) keep_mini_debug_info=true ;;
                 keep-symbols) keep_symbols=true ;;
+                keep-symbols-and-debug-frame) keep_symbols_and_debug_frame=true ;;
                 remove-build-id) remove_build_id=true ;;
                 use-gnu-strip) use_gnu_strip=true ;;
                 *) echo "Unknown option --${OPTARG}"; usage ;;
@@ -177,6 +189,16 @@
     usage
 fi
 
+if [ ! -z "${keep_symbols}" -a ! -z "${keep_symbols_and_debug_frame}" ]; then
+    echo "--keep-symbols and --keep-symbols-and-debug-frame cannot be used together"
+    usage
+fi
+
+if [ ! -z "${keep_mini_debug_info}" -a ! -z "${keep_symbols_and_debug_frame}" ]; then
+    echo "--keep-symbols-mini-debug-info and --keep-symbols-and-debug-frame cannot be used together"
+    usage
+fi
+
 if [ ! -z "${symbols_to_keep}" -a ! -z "${keep_symbols}" ]; then
     echo "--keep-symbols and -k cannot be used together"
     usage
@@ -195,6 +217,8 @@
     do_strip_keep_symbol_list
 elif [ ! -z "${keep_mini_debug_info}" ]; then
     do_strip_keep_mini_debug_info
+elif [ ! -z "${keep_symbols_and_debug_frame}" ]; then
+    do_strip_keep_symbols_and_debug_frame
 else
     do_strip
 fi