1*333d2b36SAndroid Build Coastguard Worker// Copyright 2018 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 Workerpackage symbol_inject 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "debug/elf" 19*333d2b36SAndroid Build Coastguard Worker "fmt" 20*333d2b36SAndroid Build Coastguard Worker "io" 21*333d2b36SAndroid Build Coastguard Worker) 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Workertype mockableElfFile interface { 24*333d2b36SAndroid Build Coastguard Worker Symbols() ([]elf.Symbol, error) 25*333d2b36SAndroid Build Coastguard Worker Sections() []elf.SectionHeader 26*333d2b36SAndroid Build Coastguard Worker Type() elf.Type 27*333d2b36SAndroid Build Coastguard Worker} 28*333d2b36SAndroid Build Coastguard Worker 29*333d2b36SAndroid Build Coastguard Workervar _ mockableElfFile = elfFileWrapper{} 30*333d2b36SAndroid Build Coastguard Worker 31*333d2b36SAndroid Build Coastguard Workertype elfFileWrapper struct { 32*333d2b36SAndroid Build Coastguard Worker *elf.File 33*333d2b36SAndroid Build Coastguard Worker} 34*333d2b36SAndroid Build Coastguard Worker 35*333d2b36SAndroid Build Coastguard Workerfunc (f elfFileWrapper) Sections() []elf.SectionHeader { 36*333d2b36SAndroid Build Coastguard Worker ret := make([]elf.SectionHeader, len(f.File.Sections)) 37*333d2b36SAndroid Build Coastguard Worker for i, section := range f.File.Sections { 38*333d2b36SAndroid Build Coastguard Worker ret[i] = section.SectionHeader 39*333d2b36SAndroid Build Coastguard Worker } 40*333d2b36SAndroid Build Coastguard Worker 41*333d2b36SAndroid Build Coastguard Worker return ret 42*333d2b36SAndroid Build Coastguard Worker} 43*333d2b36SAndroid Build Coastguard Worker 44*333d2b36SAndroid Build Coastguard Workerfunc (f elfFileWrapper) Type() elf.Type { 45*333d2b36SAndroid Build Coastguard Worker return f.File.Type 46*333d2b36SAndroid Build Coastguard Worker} 47*333d2b36SAndroid Build Coastguard Worker 48*333d2b36SAndroid Build Coastguard Workertype mockElfFile struct { 49*333d2b36SAndroid Build Coastguard Worker symbols []elf.Symbol 50*333d2b36SAndroid Build Coastguard Worker sections []elf.SectionHeader 51*333d2b36SAndroid Build Coastguard Worker t elf.Type 52*333d2b36SAndroid Build Coastguard Worker} 53*333d2b36SAndroid Build Coastguard Worker 54*333d2b36SAndroid Build Coastguard Workerfunc (f mockElfFile) Sections() []elf.SectionHeader { return f.sections } 55*333d2b36SAndroid Build Coastguard Workerfunc (f mockElfFile) Symbols() ([]elf.Symbol, error) { return f.symbols, nil } 56*333d2b36SAndroid Build Coastguard Workerfunc (f mockElfFile) Type() elf.Type { return f.t } 57*333d2b36SAndroid Build Coastguard Worker 58*333d2b36SAndroid Build Coastguard Workerfunc elfSymbolsFromFile(r io.ReaderAt) (*File, error) { 59*333d2b36SAndroid Build Coastguard Worker elfFile, err := elf.NewFile(r) 60*333d2b36SAndroid Build Coastguard Worker if err != nil { 61*333d2b36SAndroid Build Coastguard Worker return nil, cantParseError{err} 62*333d2b36SAndroid Build Coastguard Worker } 63*333d2b36SAndroid Build Coastguard Worker return extractElfSymbols(elfFileWrapper{elfFile}) 64*333d2b36SAndroid Build Coastguard Worker} 65*333d2b36SAndroid Build Coastguard Worker 66*333d2b36SAndroid Build Coastguard Workerfunc extractElfSymbols(elfFile mockableElfFile) (*File, error) { 67*333d2b36SAndroid Build Coastguard Worker symbols, err := elfFile.Symbols() 68*333d2b36SAndroid Build Coastguard Worker if err != nil { 69*333d2b36SAndroid Build Coastguard Worker return nil, err 70*333d2b36SAndroid Build Coastguard Worker } 71*333d2b36SAndroid Build Coastguard Worker 72*333d2b36SAndroid Build Coastguard Worker file := &File{} 73*333d2b36SAndroid Build Coastguard Worker 74*333d2b36SAndroid Build Coastguard Worker for _, section := range elfFile.Sections() { 75*333d2b36SAndroid Build Coastguard Worker file.Sections = append(file.Sections, &Section{ 76*333d2b36SAndroid Build Coastguard Worker Name: section.Name, 77*333d2b36SAndroid Build Coastguard Worker Addr: section.Addr, 78*333d2b36SAndroid Build Coastguard Worker Offset: section.Offset, 79*333d2b36SAndroid Build Coastguard Worker Size: section.Size, 80*333d2b36SAndroid Build Coastguard Worker }) 81*333d2b36SAndroid Build Coastguard Worker } 82*333d2b36SAndroid Build Coastguard Worker 83*333d2b36SAndroid Build Coastguard Worker _ = elf.Section{} 84*333d2b36SAndroid Build Coastguard Worker 85*333d2b36SAndroid Build Coastguard Worker for _, symbol := range symbols { 86*333d2b36SAndroid Build Coastguard Worker if elf.ST_TYPE(symbol.Info) != elf.STT_OBJECT { 87*333d2b36SAndroid Build Coastguard Worker continue 88*333d2b36SAndroid Build Coastguard Worker } 89*333d2b36SAndroid Build Coastguard Worker if symbol.Section == elf.SHN_UNDEF || symbol.Section >= elf.SHN_LORESERVE { 90*333d2b36SAndroid Build Coastguard Worker continue 91*333d2b36SAndroid Build Coastguard Worker } 92*333d2b36SAndroid Build Coastguard Worker if int(symbol.Section) >= len(file.Sections) { 93*333d2b36SAndroid Build Coastguard Worker return nil, fmt.Errorf("invalid section index %d", symbol.Section) 94*333d2b36SAndroid Build Coastguard Worker } 95*333d2b36SAndroid Build Coastguard Worker 96*333d2b36SAndroid Build Coastguard Worker section := file.Sections[symbol.Section] 97*333d2b36SAndroid Build Coastguard Worker 98*333d2b36SAndroid Build Coastguard Worker var addr uint64 99*333d2b36SAndroid Build Coastguard Worker switch elfFile.Type() { 100*333d2b36SAndroid Build Coastguard Worker case elf.ET_REL: 101*333d2b36SAndroid Build Coastguard Worker // "In relocatable files, st_value holds a section offset for a defined symbol. 102*333d2b36SAndroid Build Coastguard Worker // That is, st_value is an offset from the beginning of the section that st_shndx identifies." 103*333d2b36SAndroid Build Coastguard Worker addr = symbol.Value 104*333d2b36SAndroid Build Coastguard Worker case elf.ET_EXEC, elf.ET_DYN: 105*333d2b36SAndroid Build Coastguard Worker // "In executable and shared object files, st_value holds a virtual address. To make these 106*333d2b36SAndroid Build Coastguard Worker // files’ symbols more useful for the dynamic linker, the section offset (file interpretation) 107*333d2b36SAndroid Build Coastguard Worker // gives way to a virtual address (memory interpretation) for which the section number is 108*333d2b36SAndroid Build Coastguard Worker // irrelevant." 109*333d2b36SAndroid Build Coastguard Worker if symbol.Value < section.Addr { 110*333d2b36SAndroid Build Coastguard Worker return nil, fmt.Errorf("symbol starts before the start of its section") 111*333d2b36SAndroid Build Coastguard Worker } 112*333d2b36SAndroid Build Coastguard Worker addr = symbol.Value - section.Addr 113*333d2b36SAndroid Build Coastguard Worker if addr+symbol.Size > section.Size { 114*333d2b36SAndroid Build Coastguard Worker return nil, fmt.Errorf("symbol extends past the end of its section") 115*333d2b36SAndroid Build Coastguard Worker } 116*333d2b36SAndroid Build Coastguard Worker default: 117*333d2b36SAndroid Build Coastguard Worker return nil, fmt.Errorf("unsupported elf file type %d", elfFile.Type()) 118*333d2b36SAndroid Build Coastguard Worker } 119*333d2b36SAndroid Build Coastguard Worker 120*333d2b36SAndroid Build Coastguard Worker file.Symbols = append(file.Symbols, &Symbol{ 121*333d2b36SAndroid Build Coastguard Worker Name: symbol.Name, 122*333d2b36SAndroid Build Coastguard Worker Addr: addr, 123*333d2b36SAndroid Build Coastguard Worker Size: symbol.Size, 124*333d2b36SAndroid Build Coastguard Worker Section: section, 125*333d2b36SAndroid Build Coastguard Worker }) 126*333d2b36SAndroid Build Coastguard Worker } 127*333d2b36SAndroid Build Coastguard Worker 128*333d2b36SAndroid Build Coastguard Worker return file, nil 129*333d2b36SAndroid Build Coastguard Worker} 130*333d2b36SAndroid Build Coastguard Worker 131*333d2b36SAndroid Build Coastguard Workerfunc dumpElfSymbols(r io.ReaderAt) error { 132*333d2b36SAndroid Build Coastguard Worker elfFile, err := elf.NewFile(r) 133*333d2b36SAndroid Build Coastguard Worker if err != nil { 134*333d2b36SAndroid Build Coastguard Worker return cantParseError{err} 135*333d2b36SAndroid Build Coastguard Worker } 136*333d2b36SAndroid Build Coastguard Worker 137*333d2b36SAndroid Build Coastguard Worker symbols, err := elfFile.Symbols() 138*333d2b36SAndroid Build Coastguard Worker if err != nil { 139*333d2b36SAndroid Build Coastguard Worker return err 140*333d2b36SAndroid Build Coastguard Worker } 141*333d2b36SAndroid Build Coastguard Worker 142*333d2b36SAndroid Build Coastguard Worker fmt.Println("mockElfFile{") 143*333d2b36SAndroid Build Coastguard Worker fmt.Printf("\tt: %#v,\n", elfFile.Type) 144*333d2b36SAndroid Build Coastguard Worker 145*333d2b36SAndroid Build Coastguard Worker fmt.Println("\tsections: []elf.SectionHeader{") 146*333d2b36SAndroid Build Coastguard Worker for _, section := range elfFile.Sections { 147*333d2b36SAndroid Build Coastguard Worker fmt.Printf("\t\t%#v,\n", section.SectionHeader) 148*333d2b36SAndroid Build Coastguard Worker } 149*333d2b36SAndroid Build Coastguard Worker fmt.Println("\t},") 150*333d2b36SAndroid Build Coastguard Worker 151*333d2b36SAndroid Build Coastguard Worker fmt.Println("\tsymbols: []elf.Symbol{") 152*333d2b36SAndroid Build Coastguard Worker for _, symbol := range symbols { 153*333d2b36SAndroid Build Coastguard Worker fmt.Printf("\t\t%#v,\n", symbol) 154*333d2b36SAndroid Build Coastguard Worker } 155*333d2b36SAndroid Build Coastguard Worker fmt.Println("\t},") 156*333d2b36SAndroid Build Coastguard Worker 157*333d2b36SAndroid Build Coastguard Worker fmt.Println("}") 158*333d2b36SAndroid Build Coastguard Worker 159*333d2b36SAndroid Build Coastguard Worker return nil 160*333d2b36SAndroid Build Coastguard Worker} 161