1// Copyright 2018 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package symbol_inject 16 17import ( 18 "debug/macho" 19 "fmt" 20 "io" 21 "sort" 22 "strings" 23) 24 25func machoSymbolsFromFile(r io.ReaderAt) (*File, error) { 26 machoFile, err := macho.NewFile(r) 27 if err != nil { 28 return nil, cantParseError{err} 29 } 30 31 return extractMachoSymbols(machoFile) 32} 33 34func extractMachoSymbols(machoFile *macho.File) (*File, error) { 35 symbols := machoFile.Symtab.Syms 36 sort.SliceStable(symbols, func(i, j int) bool { 37 if symbols[i].Sect != symbols[j].Sect { 38 return symbols[i].Sect < symbols[j].Sect 39 } 40 return symbols[i].Value < symbols[j].Value 41 }) 42 43 file := &File{} 44 45 for _, section := range machoFile.Sections { 46 file.Sections = append(file.Sections, &Section{ 47 Name: section.Name, 48 Addr: section.Addr, 49 Offset: uint64(section.Offset), 50 Size: section.Size, 51 }) 52 } 53 54 for _, symbol := range symbols { 55 if symbol.Sect > 0 { 56 section := file.Sections[symbol.Sect-1] 57 file.Symbols = append(file.Symbols, &Symbol{ 58 // symbols in macho files seem to be prefixed with an underscore 59 Name: strings.TrimPrefix(symbol.Name, "_"), 60 // MachO symbol value is virtual address of the symbol, convert it to offset into the section. 61 Addr: symbol.Value - section.Addr, 62 // MachO symbols don't have size information. 63 Size: 0, 64 Section: section, 65 }) 66 } 67 } 68 69 return file, nil 70} 71 72func dumpMachoSymbols(r io.ReaderAt) error { 73 machoFile, err := macho.NewFile(r) 74 if err != nil { 75 return cantParseError{err} 76 } 77 78 fmt.Println("&macho.File{") 79 80 fmt.Println("\tSections: []*macho.Section{") 81 for _, section := range machoFile.Sections { 82 fmt.Printf("\t\t&macho.Section{SectionHeader: %#v},\n", section.SectionHeader) 83 } 84 fmt.Println("\t},") 85 86 fmt.Println("\tSymtab: &macho.Symtab{") 87 fmt.Println("\t\tSyms: []macho.Symbol{") 88 for _, symbol := range machoFile.Symtab.Syms { 89 fmt.Printf("\t\t\t%#v,\n", symbol) 90 } 91 fmt.Println("\t\t},") 92 fmt.Println("\t},") 93 94 fmt.Println("}") 95 96 return nil 97} 98