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
This commit is contained in:
Colin Cross 2021-06-11 18:02:22 -07:00
parent cef792e467
commit 9cfe6119fe
5 changed files with 23 additions and 44 deletions

View file

@ -92,7 +92,7 @@ cc_genrule {
}
cc_genrule {
name: "host_bionic_linker_flags",
name: "host_bionic_linker_script",
host_supported: true,
device_supported: false,
target: {
@ -107,9 +107,9 @@ cc_genrule {
},
},
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.

View file

@ -178,7 +178,7 @@ func (binary *binaryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
// 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 @@ func (binary *binaryDecorator) link(ctx ModuleContext,
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() {

View file

@ -129,7 +129,6 @@ type Deps struct {
CrtBegin, CrtEnd []string
// Used for host bionic
LinkerFlagsFile string
DynamicLinker string
// List of libs that need to be excluded for APEX variant
@ -179,9 +178,6 @@ type PathDeps struct {
// 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 @@ var (
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 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
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 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
} 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:

View file

@ -490,7 +490,7 @@ func withLinuxBionic() string {
}
cc_genrule {
name: "host_bionic_linker_flags",
name: "host_bionic_linker_script",
host_supported: true,
device_supported: false,
target: {
@ -501,7 +501,7 @@ func withLinuxBionic() string {
enabled: true,
},
},
out: ["linker.flags"],
out: ["linker.script"],
}
cc_defaults {

View file

@ -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 @@ import (
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 @@ func main() {
}
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 @@ func main() {
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 @@ func main() {
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)
}
}
}