1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Worker// This tool extracts ELF LOAD segments from our linker binary, and produces an 16*333d2b36SAndroid Build Coastguard Worker// assembly file and linker script which will embed those segments as sections 17*333d2b36SAndroid Build Coastguard Worker// in another binary. 18*333d2b36SAndroid Build Coastguard Workerpackage main 19*333d2b36SAndroid Build Coastguard Worker 20*333d2b36SAndroid Build Coastguard Workerimport ( 21*333d2b36SAndroid Build Coastguard Worker "bytes" 22*333d2b36SAndroid Build Coastguard Worker "debug/elf" 23*333d2b36SAndroid Build Coastguard Worker "flag" 24*333d2b36SAndroid Build Coastguard Worker "fmt" 25*333d2b36SAndroid Build Coastguard Worker "io" 26*333d2b36SAndroid Build Coastguard Worker "io/ioutil" 27*333d2b36SAndroid Build Coastguard Worker "log" 28*333d2b36SAndroid Build Coastguard Worker "os" 29*333d2b36SAndroid Build Coastguard Worker "strconv" 30*333d2b36SAndroid Build Coastguard Worker) 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Workerfunc main() { 33*333d2b36SAndroid Build Coastguard Worker var asmPath string 34*333d2b36SAndroid Build Coastguard Worker var scriptPath string 35*333d2b36SAndroid Build Coastguard Worker 36*333d2b36SAndroid Build Coastguard Worker flag.StringVar(&asmPath, "s", "", "Path to save the assembly file") 37*333d2b36SAndroid Build Coastguard Worker flag.StringVar(&scriptPath, "T", "", "Path to save the linker script") 38*333d2b36SAndroid Build Coastguard Worker flag.Parse() 39*333d2b36SAndroid Build Coastguard Worker 40*333d2b36SAndroid Build Coastguard Worker f, err := os.Open(flag.Arg(0)) 41*333d2b36SAndroid Build Coastguard Worker if err != nil { 42*333d2b36SAndroid Build Coastguard Worker log.Fatalf("Error opening %q: %v", flag.Arg(0), err) 43*333d2b36SAndroid Build Coastguard Worker } 44*333d2b36SAndroid Build Coastguard Worker defer f.Close() 45*333d2b36SAndroid Build Coastguard Worker 46*333d2b36SAndroid Build Coastguard Worker ef, err := elf.NewFile(f) 47*333d2b36SAndroid Build Coastguard Worker if err != nil { 48*333d2b36SAndroid Build Coastguard Worker log.Fatalf("Unable to read elf file: %v", err) 49*333d2b36SAndroid Build Coastguard Worker } 50*333d2b36SAndroid Build Coastguard Worker 51*333d2b36SAndroid Build Coastguard Worker asm := &bytes.Buffer{} 52*333d2b36SAndroid Build Coastguard Worker script := &bytes.Buffer{} 53*333d2b36SAndroid Build Coastguard Worker baseLoadAddr := uint64(0x1000) 54*333d2b36SAndroid Build Coastguard Worker load := 0 55*333d2b36SAndroid Build Coastguard Worker 56*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(asm, ".globl __dlwrap_linker_offset") 57*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(asm, ".set __dlwrap_linker_offset, 0x%x\n", baseLoadAddr) 58*333d2b36SAndroid Build Coastguard Worker 59*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(script, "ENTRY(__dlwrap__start)") 60*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(script, "SECTIONS {") 61*333d2b36SAndroid Build Coastguard Worker 62*333d2b36SAndroid Build Coastguard Worker progsWithFlagsCount := make(map[string]int) 63*333d2b36SAndroid Build Coastguard Worker 64*333d2b36SAndroid Build Coastguard Worker for _, prog := range ef.Progs { 65*333d2b36SAndroid Build Coastguard Worker if prog.Type != elf.PT_LOAD { 66*333d2b36SAndroid Build Coastguard Worker continue 67*333d2b36SAndroid Build Coastguard Worker } 68*333d2b36SAndroid Build Coastguard Worker 69*333d2b36SAndroid Build Coastguard Worker progName := progNameFromFlags(prog.Flags, progsWithFlagsCount) 70*333d2b36SAndroid Build Coastguard Worker sectionName := ".linker_" + progName 71*333d2b36SAndroid Build Coastguard Worker symName := "__dlwrap_linker_" + progName 72*333d2b36SAndroid Build Coastguard Worker 73*333d2b36SAndroid Build Coastguard Worker flags := "" 74*333d2b36SAndroid Build Coastguard Worker if prog.Flags&elf.PF_W != 0 { 75*333d2b36SAndroid Build Coastguard Worker flags += "w" 76*333d2b36SAndroid Build Coastguard Worker } 77*333d2b36SAndroid Build Coastguard Worker if prog.Flags&elf.PF_X != 0 { 78*333d2b36SAndroid Build Coastguard Worker flags += "x" 79*333d2b36SAndroid Build Coastguard Worker } 80*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(asm, ".section %s, \"a%s\"\n", sectionName, flags) 81*333d2b36SAndroid Build Coastguard Worker 82*333d2b36SAndroid Build Coastguard Worker if load == 0 { 83*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(asm, ".globl __dlwrap_linker") 84*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(asm, "__dlwrap_linker:") 85*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(asm) 86*333d2b36SAndroid Build Coastguard Worker } 87*333d2b36SAndroid Build Coastguard Worker 88*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(asm, ".globl %s\n%s:\n\n", symName, symName) 89*333d2b36SAndroid Build Coastguard Worker 90*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(script, " %s 0x%x : {\n", sectionName, baseLoadAddr+prog.Vaddr) 91*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(script, " KEEP(*(%s));\n", sectionName) 92*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(script, " }") 93*333d2b36SAndroid Build Coastguard Worker 94*333d2b36SAndroid Build Coastguard Worker buffer, _ := ioutil.ReadAll(prog.Open()) 95*333d2b36SAndroid Build Coastguard Worker bytesToAsm(asm, buffer) 96*333d2b36SAndroid Build Coastguard Worker 97*333d2b36SAndroid Build Coastguard Worker // Fill in zeros for any BSS sections. It would be nice to keep 98*333d2b36SAndroid Build Coastguard Worker // this as a true BSS, but ld/gold isn't preserving those, 99*333d2b36SAndroid Build Coastguard Worker // instead combining the segments with the following segment, 100*333d2b36SAndroid Build Coastguard Worker // and BSS only exists at the end of a LOAD segment. The 101*333d2b36SAndroid Build Coastguard Worker // linker doesn't use a lot of BSS, so this isn't a huge 102*333d2b36SAndroid Build Coastguard Worker // problem. 103*333d2b36SAndroid Build Coastguard Worker if prog.Memsz > prog.Filesz { 104*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(asm, ".fill 0x%x, 1, 0\n", prog.Memsz-prog.Filesz) 105*333d2b36SAndroid Build Coastguard Worker } 106*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(asm) 107*333d2b36SAndroid Build Coastguard Worker 108*333d2b36SAndroid Build Coastguard Worker load += 1 109*333d2b36SAndroid Build Coastguard Worker } 110*333d2b36SAndroid Build Coastguard Worker 111*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(asm, ".globl __dlwrap_linker_end") 112*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(asm, "__dlwrap_linker_end:") 113*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(asm) 114*333d2b36SAndroid Build Coastguard Worker 115*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(asm, `.section .note.android.embedded_linker,"a",%note`) 116*333d2b36SAndroid Build Coastguard Worker 117*333d2b36SAndroid Build Coastguard Worker // Discard the PT_INTERP section so that the linker doesn't need to be passed the 118*333d2b36SAndroid Build Coastguard Worker // --no-dynamic-linker flag. 119*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(script, " /DISCARD/ : { *(.interp) }") 120*333d2b36SAndroid Build Coastguard Worker 121*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(script, "}") 122*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(script, "INSERT BEFORE .note.android.embedded_linker;") 123*333d2b36SAndroid Build Coastguard Worker 124*333d2b36SAndroid Build Coastguard Worker if asmPath != "" { 125*333d2b36SAndroid Build Coastguard Worker if err := ioutil.WriteFile(asmPath, asm.Bytes(), 0777); err != nil { 126*333d2b36SAndroid Build Coastguard Worker log.Fatalf("Unable to write %q: %v", asmPath, err) 127*333d2b36SAndroid Build Coastguard Worker } 128*333d2b36SAndroid Build Coastguard Worker } 129*333d2b36SAndroid Build Coastguard Worker 130*333d2b36SAndroid Build Coastguard Worker if scriptPath != "" { 131*333d2b36SAndroid Build Coastguard Worker if err := ioutil.WriteFile(scriptPath, script.Bytes(), 0777); err != nil { 132*333d2b36SAndroid Build Coastguard Worker log.Fatalf("Unable to write %q: %v", scriptPath, err) 133*333d2b36SAndroid Build Coastguard Worker } 134*333d2b36SAndroid Build Coastguard Worker } 135*333d2b36SAndroid Build Coastguard Worker} 136*333d2b36SAndroid Build Coastguard Worker 137*333d2b36SAndroid Build Coastguard Workerfunc bytesToAsm(asm io.Writer, buf []byte) { 138*333d2b36SAndroid Build Coastguard Worker for i, b := range buf { 139*333d2b36SAndroid Build Coastguard Worker if i%64 == 0 { 140*333d2b36SAndroid Build Coastguard Worker if i != 0 { 141*333d2b36SAndroid Build Coastguard Worker fmt.Fprint(asm, "\n") 142*333d2b36SAndroid Build Coastguard Worker } 143*333d2b36SAndroid Build Coastguard Worker fmt.Fprint(asm, ".byte ") 144*333d2b36SAndroid Build Coastguard Worker } else { 145*333d2b36SAndroid Build Coastguard Worker fmt.Fprint(asm, ",") 146*333d2b36SAndroid Build Coastguard Worker } 147*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(asm, "%d", b) 148*333d2b36SAndroid Build Coastguard Worker } 149*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(asm) 150*333d2b36SAndroid Build Coastguard Worker} 151*333d2b36SAndroid Build Coastguard Worker 152*333d2b36SAndroid Build Coastguard Workerfunc progNameFromFlags(flags elf.ProgFlag, progsWithFlagsCount map[string]int) string { 153*333d2b36SAndroid Build Coastguard Worker s := "" 154*333d2b36SAndroid Build Coastguard Worker if flags&elf.PF_R != 0 { 155*333d2b36SAndroid Build Coastguard Worker s += "r" 156*333d2b36SAndroid Build Coastguard Worker } 157*333d2b36SAndroid Build Coastguard Worker if flags&elf.PF_W != 0 { 158*333d2b36SAndroid Build Coastguard Worker s += "w" 159*333d2b36SAndroid Build Coastguard Worker } 160*333d2b36SAndroid Build Coastguard Worker if flags&elf.PF_X != 0 { 161*333d2b36SAndroid Build Coastguard Worker s += "x" 162*333d2b36SAndroid Build Coastguard Worker } 163*333d2b36SAndroid Build Coastguard Worker 164*333d2b36SAndroid Build Coastguard Worker count := progsWithFlagsCount[s] 165*333d2b36SAndroid Build Coastguard Worker count++ 166*333d2b36SAndroid Build Coastguard Worker progsWithFlagsCount[s] = count 167*333d2b36SAndroid Build Coastguard Worker 168*333d2b36SAndroid Build Coastguard Worker if count > 1 { 169*333d2b36SAndroid Build Coastguard Worker s += strconv.Itoa(count) 170*333d2b36SAndroid Build Coastguard Worker } 171*333d2b36SAndroid Build Coastguard Worker 172*333d2b36SAndroid Build Coastguard Worker return s 173*333d2b36SAndroid Build Coastguard Worker} 174