Loading cmd/host_bionic_inject/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -16,4 +16,5 @@ blueprint_go_binary { name: "host_bionic_inject", deps: ["soong-symbol_inject"], srcs: ["host_bionic_inject.go"], testSrcs: ["host_bionic_inject_test.go"], } cmd/host_bionic_inject/host_bionic_inject.go +9 −14 Original line number Diff line number Diff line Loading @@ -136,33 +136,28 @@ func checkLinker(file, linker *elf.File, fileSyms []elf.Symbol) error { continue } laddr := lprog.Vaddr + dlwrap_linker_offset.Value found := false for j, prog := range file.Progs { for _, prog := range file.Progs { if prog.Type != elf.PT_LOAD { continue } if lprog.Vaddr+dlwrap_linker_offset.Value != prog.Vaddr { if laddr < prog.Vaddr || laddr > prog.Vaddr+prog.Memsz { continue } found = true if lprog.Memsz != prog.Memsz { return fmt.Errorf("Linker prog %d (0x%x) memsz (0x%x) does not match (0x%x)", i, lprog.Vaddr, lprog.Memsz, prog.Memsz) } // The linker shouldn't be using BSS, since only one // BSS section is supported per ELF file. if prog.Memsz != prog.Filesz { return fmt.Errorf("Embedded prog %d (0x%x) memsz (0x%x) does not match filesz (0x%x)", j, prog.Vaddr, prog.Memsz, prog.Filesz) } if lprog.Flags != prog.Flags { return fmt.Errorf("Linker prog %d (0x%x) flags (%s) do not match (%s)", i, lprog.Vaddr, lprog.Flags, prog.Flags) } if laddr+lprog.Memsz > prog.Vaddr+prog.Filesz { return fmt.Errorf("Linker prog %d (0x%x) not fully present (0x%x > 0x%x)", i, lprog.Vaddr, laddr+lprog.Memsz, prog.Vaddr+prog.Filesz) } } if !found { return fmt.Errorf("Linker prog %d (0x%x) not found at offset 0x%x", Loading cmd/host_bionic_inject/host_bionic_inject_test.go 0 → 100644 +146 −0 Original line number Diff line number Diff line // Copyright 2018 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "debug/elf" "fmt" "testing" ) // prog is a shortcut to fill out a elf.Prog structure func prog(flags elf.ProgFlag, offset, addr, filesz, memsz uint64) *elf.Prog { return &elf.Prog{ ProgHeader: elf.ProgHeader{ Type: elf.PT_LOAD, Flags: flags, Off: offset, Vaddr: addr, Paddr: addr, Filesz: filesz, Memsz: memsz, }, } } // linkerGold returns an example elf.File from a linker binary that was linked // with gold. func linkerGold() *elf.File { return &elf.File{ Progs: []*elf.Prog{ prog(elf.PF_R|elf.PF_X, 0, 0, 0xd0fac, 0xd0fac), prog(elf.PF_R|elf.PF_W, 0xd1050, 0xd2050, 0x6890, 0xd88c), }, } } // fileGold returns an example elf binary with a properly embedded linker. The // embedded linker was the one returned by linkerGold. func fileGold() *elf.File { return &elf.File{ Progs: []*elf.Prog{ prog(elf.PF_R, 0, 0, 0x2e0, 0x2e0), prog(elf.PF_R|elf.PF_X, 0x1000, 0x1000, 0xd0fac, 0xd0fac), prog(elf.PF_R|elf.PF_W, 0xd2050, 0xd3050, 0xd88c, 0xd88c), prog(elf.PF_R, 0xe0000, 0xe1000, 0x10e4, 0x10e4), prog(elf.PF_R|elf.PF_X, 0xe2000, 0xe3000, 0x1360, 0x1360), prog(elf.PF_R|elf.PF_W, 0xe4000, 0xe5000, 0x1358, 0x1358), }, } } // linkerLld returns an example elf.File from a linker binary that was linked // with lld. func linkerLld() *elf.File { return &elf.File{ Progs: []*elf.Prog{ prog(elf.PF_R, 0, 0, 0x3c944, 0x3c944), prog(elf.PF_R|elf.PF_X, 0x3d000, 0x3d000, 0x946fa, 0x946fa), prog(elf.PF_R|elf.PF_W, 0xd2000, 0xd2000, 0x7450, 0xf778), }, } } // fileGold returns an example elf binary with a properly embedded linker. The // embedded linker was the one returned by linkerLld. func fileLld() *elf.File { return &elf.File{ Progs: []*elf.Prog{ prog(elf.PF_R, 0, 0, 0x3d944, 0x3d944), prog(elf.PF_R|elf.PF_X, 0x3e000, 0x3e000, 0x946fa, 0x946fa), prog(elf.PF_R|elf.PF_W, 0xd3000, 0xd3000, 0xf778, 0xf778), prog(elf.PF_R, 0xe3000, 0xe3000, 0x10e4, 0x10e4), prog(elf.PF_R|elf.PF_X, 0xe5000, 0xe5000, 0x1360, 0x1360), prog(elf.PF_R|elf.PF_W, 0xe7000, 0xe7000, 0x1358, 0x1358), }, } } // linkerOffset returns the symbol representing the linker offset used by both // fileGold and fileLld func linkerOffset() []elf.Symbol { return []elf.Symbol{ elf.Symbol{ Name: "__dlwrap_linker_offset", Value: 0x1000, }, } } func TestCheckLinker(t *testing.T) { cases := []struct { name string err error file func() *elf.File linker func() *elf.File }{ { name: "good gold-linked linker", file: fileGold, linker: linkerGold, }, { name: "good lld-linked linker", file: fileLld, linker: linkerLld, }, { name: "truncated RO section", err: fmt.Errorf("Linker prog 0 (0x0) not fully present (0x3d944 > 0x3d943)"), file: func() *elf.File { f := fileLld() f.Progs[0].Filesz -= 1 f.Progs[0].Memsz -= 1 return f }, linker: linkerLld, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { err := checkLinker(tc.file(), tc.linker(), linkerOffset()) if tc.err == nil { if err != nil { t.Fatalf("No error expected, but got: %v", err) } } else if err == nil { t.Fatalf("Returned no error, but wanted: %v", tc.err) } else if err.Error() != tc.err.Error() { t.Fatalf("Different error found:\nwant: %v\n got: %v", tc.err, err) } }) } } Loading
cmd/host_bionic_inject/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -16,4 +16,5 @@ blueprint_go_binary { name: "host_bionic_inject", deps: ["soong-symbol_inject"], srcs: ["host_bionic_inject.go"], testSrcs: ["host_bionic_inject_test.go"], }
cmd/host_bionic_inject/host_bionic_inject.go +9 −14 Original line number Diff line number Diff line Loading @@ -136,33 +136,28 @@ func checkLinker(file, linker *elf.File, fileSyms []elf.Symbol) error { continue } laddr := lprog.Vaddr + dlwrap_linker_offset.Value found := false for j, prog := range file.Progs { for _, prog := range file.Progs { if prog.Type != elf.PT_LOAD { continue } if lprog.Vaddr+dlwrap_linker_offset.Value != prog.Vaddr { if laddr < prog.Vaddr || laddr > prog.Vaddr+prog.Memsz { continue } found = true if lprog.Memsz != prog.Memsz { return fmt.Errorf("Linker prog %d (0x%x) memsz (0x%x) does not match (0x%x)", i, lprog.Vaddr, lprog.Memsz, prog.Memsz) } // The linker shouldn't be using BSS, since only one // BSS section is supported per ELF file. if prog.Memsz != prog.Filesz { return fmt.Errorf("Embedded prog %d (0x%x) memsz (0x%x) does not match filesz (0x%x)", j, prog.Vaddr, prog.Memsz, prog.Filesz) } if lprog.Flags != prog.Flags { return fmt.Errorf("Linker prog %d (0x%x) flags (%s) do not match (%s)", i, lprog.Vaddr, lprog.Flags, prog.Flags) } if laddr+lprog.Memsz > prog.Vaddr+prog.Filesz { return fmt.Errorf("Linker prog %d (0x%x) not fully present (0x%x > 0x%x)", i, lprog.Vaddr, laddr+lprog.Memsz, prog.Vaddr+prog.Filesz) } } if !found { return fmt.Errorf("Linker prog %d (0x%x) not found at offset 0x%x", Loading
cmd/host_bionic_inject/host_bionic_inject_test.go 0 → 100644 +146 −0 Original line number Diff line number Diff line // Copyright 2018 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "debug/elf" "fmt" "testing" ) // prog is a shortcut to fill out a elf.Prog structure func prog(flags elf.ProgFlag, offset, addr, filesz, memsz uint64) *elf.Prog { return &elf.Prog{ ProgHeader: elf.ProgHeader{ Type: elf.PT_LOAD, Flags: flags, Off: offset, Vaddr: addr, Paddr: addr, Filesz: filesz, Memsz: memsz, }, } } // linkerGold returns an example elf.File from a linker binary that was linked // with gold. func linkerGold() *elf.File { return &elf.File{ Progs: []*elf.Prog{ prog(elf.PF_R|elf.PF_X, 0, 0, 0xd0fac, 0xd0fac), prog(elf.PF_R|elf.PF_W, 0xd1050, 0xd2050, 0x6890, 0xd88c), }, } } // fileGold returns an example elf binary with a properly embedded linker. The // embedded linker was the one returned by linkerGold. func fileGold() *elf.File { return &elf.File{ Progs: []*elf.Prog{ prog(elf.PF_R, 0, 0, 0x2e0, 0x2e0), prog(elf.PF_R|elf.PF_X, 0x1000, 0x1000, 0xd0fac, 0xd0fac), prog(elf.PF_R|elf.PF_W, 0xd2050, 0xd3050, 0xd88c, 0xd88c), prog(elf.PF_R, 0xe0000, 0xe1000, 0x10e4, 0x10e4), prog(elf.PF_R|elf.PF_X, 0xe2000, 0xe3000, 0x1360, 0x1360), prog(elf.PF_R|elf.PF_W, 0xe4000, 0xe5000, 0x1358, 0x1358), }, } } // linkerLld returns an example elf.File from a linker binary that was linked // with lld. func linkerLld() *elf.File { return &elf.File{ Progs: []*elf.Prog{ prog(elf.PF_R, 0, 0, 0x3c944, 0x3c944), prog(elf.PF_R|elf.PF_X, 0x3d000, 0x3d000, 0x946fa, 0x946fa), prog(elf.PF_R|elf.PF_W, 0xd2000, 0xd2000, 0x7450, 0xf778), }, } } // fileGold returns an example elf binary with a properly embedded linker. The // embedded linker was the one returned by linkerLld. func fileLld() *elf.File { return &elf.File{ Progs: []*elf.Prog{ prog(elf.PF_R, 0, 0, 0x3d944, 0x3d944), prog(elf.PF_R|elf.PF_X, 0x3e000, 0x3e000, 0x946fa, 0x946fa), prog(elf.PF_R|elf.PF_W, 0xd3000, 0xd3000, 0xf778, 0xf778), prog(elf.PF_R, 0xe3000, 0xe3000, 0x10e4, 0x10e4), prog(elf.PF_R|elf.PF_X, 0xe5000, 0xe5000, 0x1360, 0x1360), prog(elf.PF_R|elf.PF_W, 0xe7000, 0xe7000, 0x1358, 0x1358), }, } } // linkerOffset returns the symbol representing the linker offset used by both // fileGold and fileLld func linkerOffset() []elf.Symbol { return []elf.Symbol{ elf.Symbol{ Name: "__dlwrap_linker_offset", Value: 0x1000, }, } } func TestCheckLinker(t *testing.T) { cases := []struct { name string err error file func() *elf.File linker func() *elf.File }{ { name: "good gold-linked linker", file: fileGold, linker: linkerGold, }, { name: "good lld-linked linker", file: fileLld, linker: linkerLld, }, { name: "truncated RO section", err: fmt.Errorf("Linker prog 0 (0x0) not fully present (0x3d944 > 0x3d943)"), file: func() *elf.File { f := fileLld() f.Progs[0].Filesz -= 1 f.Progs[0].Memsz -= 1 return f }, linker: linkerLld, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { err := checkLinker(tc.file(), tc.linker(), linkerOffset()) if tc.err == nil { if err != nil { t.Fatalf("No error expected, but got: %v", err) } } else if err == nil { t.Fatalf("Returned no error, but wanted: %v", tc.err) } else if err.Error() != tc.err.Error() { t.Fatalf("Different error found:\nwant: %v\n got: %v", tc.err, err) } }) } }