Stop injecting symbols into host bionic binaries

The host bionic bootstrapping no longer needs an injected symbol.
Replace host_bionic_inject with host_bionic_verify that validates
the resulting binary, and add it as a validation dependency of the
binary.

Test: build and run host bionic binary
Change-Id: I3e303d2a164b6eef851bdc8075e6ee456c05b0a8
This commit is contained in:
Colin Cross 2021-06-11 15:22:41 -07:00
parent a4d9b86c8b
commit f04eb99acc
6 changed files with 32 additions and 56 deletions

View file

@ -401,16 +401,18 @@ func (binary *binaryDecorator) link(ctx ModuleContext,
} }
} }
var validations android.WritablePaths
// Handle host bionic linker symbols. // Handle host bionic linker symbols.
if ctx.Os() == android.LinuxBionic && !binary.static() { if ctx.Os() == android.LinuxBionic && !binary.static() {
injectedOutputFile := outputFile verifyFile := android.PathForModuleOut(ctx, "host_bionic_verify.stamp")
outputFile = android.PathForModuleOut(ctx, "prelinker", fileName)
if !deps.DynamicLinker.Valid() { if !deps.DynamicLinker.Valid() {
panic("Non-static host bionic modules must have a dynamic linker") panic("Non-static host bionic modules must have a dynamic linker")
} }
binary.injectHostBionicLinkerSymbols(ctx, outputFile, deps.DynamicLinker.Path(), injectedOutputFile) binary.verifyHostBionicLinker(ctx, outputFile, deps.DynamicLinker.Path(), verifyFile)
validations = append(validations, verifyFile)
} }
var sharedLibs android.Paths var sharedLibs android.Paths
@ -430,7 +432,7 @@ func (binary *binaryDecorator) link(ctx ModuleContext,
// Register link action. // Register link action.
transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, deps.StaticLibs, transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, deps.StaticLibs,
deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true, deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
builderFlags, outputFile, nil) builderFlags, outputFile, nil, validations)
objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...) objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...) objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
@ -532,19 +534,19 @@ func (binary *binaryDecorator) hostToolPath() android.OptionalPath {
} }
func init() { func init() {
pctx.HostBinToolVariable("hostBionicSymbolsInjectCmd", "host_bionic_inject") pctx.HostBinToolVariable("verifyHostBionicCmd", "host_bionic_verify")
} }
var injectHostBionicSymbols = pctx.AndroidStaticRule("injectHostBionicSymbols", var verifyHostBionic = pctx.AndroidStaticRule("verifyHostBionic",
blueprint.RuleParams{ blueprint.RuleParams{
Command: "$hostBionicSymbolsInjectCmd -i $in -l $linker -o $out", Command: "$verifyHostBionicCmd -i $in -l $linker && touch $out",
CommandDeps: []string{"$hostBionicSymbolsInjectCmd"}, CommandDeps: []string{"$verifyHostBionicCmd"},
}, "linker") }, "linker")
func (binary *binaryDecorator) injectHostBionicLinkerSymbols(ctx ModuleContext, in, linker android.Path, out android.WritablePath) { func (binary *binaryDecorator) verifyHostBionicLinker(ctx ModuleContext, in, linker android.Path, out android.WritablePath) {
ctx.Build(pctx, android.BuildParams{ ctx.Build(pctx, android.BuildParams{
Rule: injectHostBionicSymbols, Rule: verifyHostBionic,
Description: "inject host bionic symbols", Description: "verify host bionic",
Input: in, Input: in,
Implicit: linker, Implicit: linker,
Output: out, Output: out,

View file

@ -731,7 +731,8 @@ func transformObjToStaticLib(ctx android.ModuleContext,
// and shared libraries, to a shared library (.so) or dynamic executable // and shared libraries, to a shared library (.so) or dynamic executable
func transformObjToDynamicBinary(ctx android.ModuleContext, func transformObjToDynamicBinary(ctx android.ModuleContext,
objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths, objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths,
crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath, implicitOutputs android.WritablePaths) { crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags,
outputFile android.WritablePath, implicitOutputs android.WritablePaths, validations android.WritablePaths) {
ldCmd := "${config.ClangBin}/clang++" ldCmd := "${config.ClangBin}/clang++"
@ -805,6 +806,7 @@ func transformObjToDynamicBinary(ctx android.ModuleContext,
Inputs: objFiles, Inputs: objFiles,
Implicits: deps, Implicits: deps,
OrderOnly: sharedLibs, OrderOnly: sharedLibs,
Validations: validations.Paths(),
Args: args, Args: args,
}) })
} }

View file

@ -1343,7 +1343,7 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
linkerDeps = append(linkerDeps, objs.tidyFiles...) linkerDeps = append(linkerDeps, objs.tidyFiles...)
transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs, deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs) linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs, nil)
objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...) objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...) objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)

View file

@ -17,8 +17,7 @@ package {
} }
blueprint_go_binary { blueprint_go_binary {
name: "host_bionic_inject", name: "host_bionic_verify",
deps: ["soong-symbol_inject"], srcs: ["host_bionic_verify.go"],
srcs: ["host_bionic_inject.go"], testSrcs: ["host_bionic_verify_test.go"],
testSrcs: ["host_bionic_inject_test.go"],
} }

View file

@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// Verifies a host bionic executable with an embedded linker, then injects // Verifies a host bionic executable with an embedded linker.
// the address of the _start function for the linker_wrapper to use.
package main package main
import ( import (
@ -22,19 +21,16 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"android/soong/symbol_inject"
) )
func main() { func main() {
var inputFile, linkerFile, outputFile string var inputFile, linkerFile string
flag.StringVar(&inputFile, "i", "", "Input file") flag.StringVar(&inputFile, "i", "", "Input file")
flag.StringVar(&linkerFile, "l", "", "Linker file") flag.StringVar(&linkerFile, "l", "", "Linker file")
flag.StringVar(&outputFile, "o", "", "Output file")
flag.Parse() flag.Parse()
if inputFile == "" || linkerFile == "" || outputFile == "" || flag.NArg() != 0 { if inputFile == "" || linkerFile == "" || flag.NArg() != 0 {
flag.Usage() flag.Usage()
os.Exit(1) os.Exit(1)
} }
@ -46,75 +42,52 @@ func main() {
} }
defer r.Close() defer r.Close()
file, err := symbol_inject.OpenFile(r)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(3)
}
linker, err := elf.Open(linkerFile) linker, err := elf.Open(linkerFile)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err.Error()) fmt.Fprintln(os.Stderr, err.Error())
os.Exit(4) os.Exit(4)
} }
startAddr, err := parseElf(r, linker) err = checkElf(r, linker)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err.Error()) fmt.Fprintln(os.Stderr, err.Error())
os.Exit(5) os.Exit(5)
} }
w, err := os.OpenFile(outputFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(6)
}
defer w.Close()
err = symbol_inject.InjectUint64Symbol(file, w, "__dlwrap_original_start", startAddr)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(7)
}
} }
// Check the ELF file, and return the address to the _start function // Check the ELF file, and return the address to the _start function
func parseElf(r io.ReaderAt, linker *elf.File) (uint64, error) { func checkElf(r io.ReaderAt, linker *elf.File) error {
file, err := elf.NewFile(r) file, err := elf.NewFile(r)
if err != nil { if err != nil {
return 0, err return err
} }
symbols, err := file.Symbols() symbols, err := file.Symbols()
if err != nil { if err != nil {
return 0, err return err
} }
for _, prog := range file.Progs { for _, prog := range file.Progs {
if prog.Type == elf.PT_INTERP { if prog.Type == elf.PT_INTERP {
return 0, fmt.Errorf("File should not have a PT_INTERP header") return fmt.Errorf("File should not have a PT_INTERP header")
} }
} }
if dlwrap_start, err := findSymbol(symbols, "__dlwrap__start"); err != nil { if dlwrap_start, err := findSymbol(symbols, "__dlwrap__start"); err != nil {
return 0, err return err
} else if dlwrap_start.Value != file.Entry { } else if dlwrap_start.Value != file.Entry {
return 0, fmt.Errorf("Expected file entry(0x%x) to point to __dlwrap_start(0x%x)", return fmt.Errorf("Expected file entry(0x%x) to point to __dlwrap_start(0x%x)",
file.Entry, dlwrap_start.Value) file.Entry, dlwrap_start.Value)
} }
err = checkLinker(file, linker, symbols) err = checkLinker(file, linker, symbols)
if err != nil { if err != nil {
return 0, fmt.Errorf("Linker executable failed verification against app embedded linker: %s\n"+ return fmt.Errorf("Linker executable failed verification against app embedded linker: %s\n"+
"linker might not be in sync with crtbegin_dynamic.o.", "linker might not be in sync with crtbegin_dynamic.o.",
err) err)
} }
start, err := findSymbol(symbols, "_start") return nil
if err != nil {
return 0, fmt.Errorf("Failed to find _start symbol")
}
return start.Value, nil
} }
func findSymbol(symbols []elf.Symbol, name string) (elf.Symbol, error) { func findSymbol(symbols []elf.Symbol, name string) (elf.Symbol, error) {