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:
parent
a4d9b86c8b
commit
f04eb99acc
6 changed files with 32 additions and 56 deletions
24
cc/binary.go
24
cc/binary.go
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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...)
|
||||||
|
|
|
@ -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"],
|
|
||||||
}
|
}
|
|
@ -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) {
|
Loading…
Reference in a new issue