Use a linker script for host bionic embedded linker sections

Use an implicit linker script instead of flags in a file to specify
the locations of the host bionic embedded linker and to prevent it
from being stripped.

Test: build and run host bionic binary
Change-Id: I64e12118d33c67bab5e657cbc3ea8cde8f0fd7e6
diff --git a/Android.bp b/Android.bp
index 8f7f3e2..45e661e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -92,7 +92,7 @@
 }
 
 cc_genrule {
-    name: "host_bionic_linker_flags",
+    name: "host_bionic_linker_script",
     host_supported: true,
     device_supported: false,
     target: {
@@ -107,9 +107,9 @@
         },
     },
     tools: ["extract_linker"],
-    cmd: "$(location) -f $(out) $(in)",
+    cmd: "$(location) -T $(out) $(in)",
     srcs: [":linker"],
-    out: ["linker.flags"],
+    out: ["linker.script"],
 }
 
 // Instantiate the dex_bootjars singleton module.
diff --git a/cc/binary.go b/cc/binary.go
index 201fdcc..3aa3fdf 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -178,7 +178,7 @@
 		// the kernel before jumping to the embedded linker.
 		if ctx.Os() == android.LinuxBionic && !binary.static() {
 			deps.DynamicLinker = "linker"
-			deps.LinkerFlagsFile = "host_bionic_linker_flags"
+			deps.CrtBegin = append(deps.CrtBegin, "host_bionic_linker_script")
 		}
 	}
 
@@ -345,12 +345,6 @@
 
 	var linkerDeps android.Paths
 
-	// Add flags from linker flags file.
-	if deps.LinkerFlagsFile.Valid() {
-		flags.Local.LdFlags = append(flags.Local.LdFlags, "$$(cat "+deps.LinkerFlagsFile.String()+")")
-		linkerDeps = append(linkerDeps, deps.LinkerFlagsFile.Path())
-	}
-
 	if flags.DynamicLinker != "" {
 		flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-dynamic-linker,"+flags.DynamicLinker)
 	} else if ctx.toolchain().Bionic() && !binary.static() {
diff --git a/cc/cc.go b/cc/cc.go
index ef503af..6e9518d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -129,8 +129,7 @@
 	CrtBegin, CrtEnd []string
 
 	// Used for host bionic
-	LinkerFlagsFile string
-	DynamicLinker   string
+	DynamicLinker string
 
 	// List of libs that need to be excluded for APEX variant
 	ExcludeLibsForApex []string
@@ -179,9 +178,6 @@
 	// Paths to crt*.o files
 	CrtBegin, CrtEnd android.Paths
 
-	// Path to the file container flags to use with the linker
-	LinkerFlagsFile android.OptionalPath
-
 	// Path to the dynamic linker binary
 	DynamicLinker android.OptionalPath
 }
@@ -717,7 +713,6 @@
 	genHeaderDepTag       = dependencyTag{name: "gen header"}
 	genHeaderExportDepTag = dependencyTag{name: "gen header export"}
 	objDepTag             = dependencyTag{name: "obj"}
-	linkerFlagsDepTag     = dependencyTag{name: "linker flags file"}
 	dynamicLinkerDepTag   = installDependencyTag{name: "dynamic linker"}
 	reuseObjTag           = dependencyTag{name: "reuse objects"}
 	staticVariantTag      = dependencyTag{name: "static variant"}
@@ -2254,9 +2249,6 @@
 		actx.AddVariationDependencies(crtVariations, CrtEndDepTag,
 			RewriteSnapshotLib(crt, GetSnapshot(c, &snapshotInfo, actx).Objects))
 	}
-	if deps.LinkerFlagsFile != "" {
-		actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)
-	}
 	if deps.DynamicLinker != "" {
 		actx.AddDependency(c, dynamicLinkerDepTag, deps.DynamicLinker)
 	}
@@ -2555,17 +2547,6 @@
 				} else {
 					ctx.ModuleErrorf("module %q is not a genrule", depName)
 				}
-			case linkerFlagsDepTag:
-				if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
-					files := genRule.GeneratedSourceFiles()
-					if len(files) == 1 {
-						depPaths.LinkerFlagsFile = android.OptionalPathForPath(files[0])
-					} else if len(files) > 1 {
-						ctx.ModuleErrorf("module %q can only generate a single file if used for a linker flag file", depName)
-					}
-				} else {
-					ctx.ModuleErrorf("module %q is not a genrule", depName)
-				}
 			case CrtBeginDepTag:
 				depPaths.CrtBegin = append(depPaths.CrtBegin, android.OutputFileForModule(ctx, dep, ""))
 			case CrtEndDepTag:
diff --git a/cc/testing.go b/cc/testing.go
index f5c5ec5..bee170f 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -490,7 +490,7 @@
 				}
 
 				cc_genrule {
-					name: "host_bionic_linker_flags",
+					name: "host_bionic_linker_script",
 					host_supported: true,
 					device_supported: false,
 					target: {
@@ -501,7 +501,7 @@
 							enabled: true,
 						},
 					},
-					out: ["linker.flags"],
+					out: ["linker.script"],
 				}
 
 				cc_defaults {
diff --git a/cmd/extract_linker/main.go b/cmd/extract_linker/main.go
index d62dea1..2dcb894 100644
--- a/cmd/extract_linker/main.go
+++ b/cmd/extract_linker/main.go
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 // This tool extracts ELF LOAD segments from our linker binary, and produces an
-// assembly file and linker flags which will embed those segments as sections
+// assembly file and linker script which will embed those segments as sections
 // in another binary.
 package main
 
@@ -31,10 +31,10 @@
 
 func main() {
 	var asmPath string
-	var flagsPath string
+	var scriptPath string
 
 	flag.StringVar(&asmPath, "s", "", "Path to save the assembly file")
-	flag.StringVar(&flagsPath, "f", "", "Path to save the linker flags")
+	flag.StringVar(&scriptPath, "T", "", "Path to save the linker script")
 	flag.Parse()
 
 	f, err := os.Open(flag.Arg(0))
@@ -49,13 +49,16 @@
 	}
 
 	asm := &bytes.Buffer{}
+	script := &bytes.Buffer{}
 	baseLoadAddr := uint64(0x1000)
 	load := 0
-	linkFlags := []string{}
 
 	fmt.Fprintln(asm, ".globl __dlwrap_linker_offset")
 	fmt.Fprintf(asm, ".set __dlwrap_linker_offset, 0x%x\n", baseLoadAddr)
 
+	fmt.Fprintln(script, "ENTRY(__dlwrap__start)")
+	fmt.Fprintln(script, "SECTIONS {")
+
 	for _, prog := range ef.Progs {
 		if prog.Type != elf.PT_LOAD {
 			continue
@@ -82,10 +85,9 @@
 
 		fmt.Fprintf(asm, ".globl %s\n%s:\n\n", symName, symName)
 
-		linkFlags = append(linkFlags,
-			fmt.Sprintf("-Wl,--undefined=%s", symName),
-			fmt.Sprintf("-Wl,--section-start=%s=0x%x",
-				sectionName, baseLoadAddr+prog.Vaddr))
+		fmt.Fprintf(script, "  %s %d : {\n", sectionName, baseLoadAddr+prog.Vaddr)
+		fmt.Fprintf(script, "    KEEP(*(%s));\n", sectionName)
+		fmt.Fprintln(script, "  }")
 
 		buffer, _ := ioutil.ReadAll(prog.Open())
 		bytesToAsm(asm, buffer)
@@ -104,16 +106,18 @@
 		load += 1
 	}
 
+	fmt.Fprintln(script, "}")
+	fmt.Fprintln(script, "INSERT BEFORE .note.android.ident;")
+
 	if asmPath != "" {
 		if err := ioutil.WriteFile(asmPath, asm.Bytes(), 0777); err != nil {
 			log.Fatalf("Unable to write %q: %v", asmPath, err)
 		}
 	}
 
-	if flagsPath != "" {
-		flags := strings.Join(linkFlags, " ")
-		if err := ioutil.WriteFile(flagsPath, []byte(flags), 0777); err != nil {
-			log.Fatalf("Unable to write %q: %v", flagsPath, err)
+	if scriptPath != "" {
+		if err := ioutil.WriteFile(scriptPath, script.Bytes(), 0777); err != nil {
+			log.Fatalf("Unable to write %q: %v", scriptPath, err)
 		}
 	}
 }