Enable toc support for Darwin and Windows

Bug: 113936524
Test: m checkbuild
Change-Id: I0f2030ad75daae2cbe44e8cbedad329d33df55f7
diff --git a/cc/builder.go b/cc/builder.go
index be63fd7..58196f4 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -144,11 +144,11 @@
 		blueprint.RuleParams{
 			Depfile:     "${out}.d",
 			Deps:        blueprint.DepsGCC,
-			Command:     "CROSS_COMPILE=$crossCompile $tocPath -i ${in} -o ${out} -d ${out}.d",
+			Command:     "CROSS_COMPILE=$crossCompile $tocPath $format -i ${in} -o ${out} -d ${out}.d",
 			CommandDeps: []string{"$tocPath"},
 			Restat:      true,
 		},
-		"crossCompile")
+		"crossCompile", "format")
 
 	clangTidy = pctx.AndroidStaticRule("clangTidy",
 		blueprint.RuleParams{
@@ -759,7 +759,18 @@
 func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path,
 	outputFile android.WritablePath, flags builderFlags) {
 
-	crossCompile := gccCmd(flags.toolchain, "")
+	var format string
+	var crossCompile string
+	if ctx.Darwin() {
+		format = "--macho"
+		crossCompile = "${config.MacToolPath}"
+	} else if ctx.Windows() {
+		format = "--pe"
+		crossCompile = gccCmd(flags.toolchain, "")
+	} else {
+		format = "--elf"
+		crossCompile = gccCmd(flags.toolchain, "")
+	}
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        toc,
@@ -768,6 +779,7 @@
 		Input:       inputFile,
 		Args: map[string]string{
 			"crossCompile": crossCompile,
+			"format":       format,
 		},
 	})
 }
diff --git a/cc/library.go b/cc/library.go
index 7886c35..d208e1c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -544,15 +544,13 @@
 
 	builderFlags := flagsToBuilderFlags(flags)
 
-	if !ctx.Darwin() && !ctx.Windows() {
-		// Optimize out relinking against shared libraries whose interface hasn't changed by
-		// depending on a table of contents file instead of the library itself.
-		tocPath := outputFile.RelPathString()
-		tocPath = pathtools.ReplaceExtension(tocPath, flags.Toolchain.ShlibSuffix()[1:]+".toc")
-		tocFile := android.PathForOutput(ctx, tocPath)
-		library.tocFile = android.OptionalPathForPath(tocFile)
-		TransformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
-	}
+	// Optimize out relinking against shared libraries whose interface hasn't changed by
+	// depending on a table of contents file instead of the library itself.
+	tocPath := outputFile.RelPathString()
+	tocPath = pathtools.ReplaceExtension(tocPath, flags.Toolchain.ShlibSuffix()[1:]+".toc")
+	tocFile := android.PathForOutput(ctx, tocPath)
+	library.tocFile = android.OptionalPathForPath(tocFile)
+	TransformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
 
 	if library.stripper.needsStrip(ctx) {
 		// b/80093681, GNU strip/objcopy bug.
diff --git a/scripts/toc.sh b/scripts/toc.sh
index bd6425b..8b1d25f 100755
--- a/scripts/toc.sh
+++ b/scripts/toc.sh
@@ -22,6 +22,7 @@
 #   -i ${file}: input file (required)
 #   -o ${file}: output file (required)
 #   -d ${file}: deps file (required)
+#   --elf | --macho | --pe: format (required)
 
 OPTSTRING=d:i:o:-:
 
@@ -36,13 +37,34 @@
 do_elf() {
     ("${CROSS_COMPILE}readelf" -d "${infile}" | grep SONAME || echo "No SONAME for ${infile}") > "${outfile}.tmp"
     "${CROSS_COMPILE}readelf" --dyn-syms "${infile}" | awk '{$2=""; $3=""; print}' >> "${outfile}.tmp"
+
+    cat <<EOF > "${depsfile}"
+${outfile}: \\
+  ${CROSS_COMPILE}readelf \\
+EOF
 }
 
 do_macho() {
     "${CROSS_COMPILE}/otool" -l "${infile}" | grep LC_ID_DYLIB -A 5 > "${outfile}.tmp"
-    "${CROSS_COMPILE}/nm" -gP "${infile}" | cut -f1-2 -d" " | grep -v 'U$' >> "${outfile}.tmp"
+    "${CROSS_COMPILE}/nm" -gP "${infile}" | cut -f1-2 -d" " | (grep -v 'U$' >> "${outfile}.tmp" || true)
+
+    cat <<EOF > "${depsfile}"
+${outfile}: \\
+  ${CROSS_COMPILE}/otool \\
+  ${CROSS_COMPILE}/nm \\
+EOF
 }
 
+do_pe() {
+    "${CROSS_COMPILE}objdump" -x "${infile}" | grep "^Name" | cut -f3 -d" " > "${outfile}.tmp"
+    "${CROSS_COMPILE}nm" -g -f p "${infile}" | cut -f1-2 -d" " >> "${outfile}.tmp"
+
+    cat <<EOF > "${depsfile}"
+${outfile}: \\
+  ${CROSS_COMPILE}objdump \\
+  ${CROSS_COMPILE}nm \\
+EOF
+}
 
 while getopts $OPTSTRING opt; do
     case "$opt" in
@@ -51,6 +73,9 @@
         o) outfile="${OPTARG}" ;;
         -)
             case "${OPTARG}" in
+                elf) elf=1 ;;
+                macho) macho=1 ;;
+                pe) pe=1 ;;
                 *) echo "Unknown option --${OPTARG}"; usage ;;
             esac;;
         ?) usage ;;
@@ -58,21 +83,26 @@
     esac
 done
 
-if [ -z "${infile}" ]; then
+if [ -z "${infile:-}" ]; then
     echo "-i argument is required"
     usage
 fi
 
-if [ -z "${outfile}" ]; then
+if [ -z "${outfile:-}" ]; then
     echo "-o argument is required"
     usage
 fi
 
-if [ -z "${depsfile}" ]; then
+if [ -z "${depsfile:-}" ]; then
     echo "-d argument is required"
     usage
 fi
 
+if [ -z "${CROSS_COMPILE:-}" ]; then
+    echo "CROSS_COMPILE environment variable must be set"
+    usage
+fi
+
 rm -f "${outfile}.tmp"
 
 cat <<EOF > "${depsfile}"
@@ -80,7 +110,15 @@
   ${CROSS_COMPILE}readelf \\
 EOF
 
-do_elf
+if [ -n "${elf:-}" ]; then
+    do_elf
+elif [ -n "${macho:-}" ]; then
+    do_macho
+elif [ -n "${pe:-}" ]; then
+    do_pe
+else
+    echo "--elf, --macho or --pe is required"; usage
+fi
 
 if cmp "${outfile}" "${outfile}.tmp" > /dev/null 2> /dev/null; then
     rm -f "${outfile}.tmp"