blob: 6ee3f4fbdc35329be064d95b7194fac13de1feaf [file] [log] [blame]
Colin Cross5498f852018-01-03 23:39:54 -08001// 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
Dan Willemsen2249dc82018-10-15 00:35:59 -070015package symbol_inject
Colin Cross5498f852018-01-03 23:39:54 -080016
17import (
18 "debug/macho"
19 "fmt"
20 "io"
Colin Crossc4a18e02018-02-23 22:43:24 -080021 "sort"
Colin Cross8673b5b2018-03-01 11:20:25 -080022 "strings"
Colin Cross5498f852018-01-03 23:39:54 -080023)
24
Colin Cross8673b5b2018-03-01 11:20:25 -080025func machoSymbolsFromFile(r io.ReaderAt) (*File, error) {
Colin Cross5498f852018-01-03 23:39:54 -080026 machoFile, err := macho.NewFile(r)
27 if err != nil {
Colin Cross8673b5b2018-03-01 11:20:25 -080028 return nil, cantParseError{err}
Colin Cross5498f852018-01-03 23:39:54 -080029 }
30
Colin Cross8673b5b2018-03-01 11:20:25 -080031 return extractMachoSymbols(machoFile)
32}
Colin Cross5498f852018-01-03 23:39:54 -080033
Colin Cross8673b5b2018-03-01 11:20:25 -080034func extractMachoSymbols(machoFile *macho.File) (*File, error) {
Colin Crossc4a18e02018-02-23 22:43:24 -080035 symbols := machoFile.Symtab.Syms
Colin Cross8673b5b2018-03-01 11:20:25 -080036 sort.SliceStable(symbols, func(i, j int) bool {
Colin Crossc4a18e02018-02-23 22:43:24 -080037 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
Colin Cross8673b5b2018-03-01 11:20:25 -080043 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
Colin Crossdfce7642018-02-28 13:05:39 -080054 for _, symbol := range symbols {
Colin Cross8673b5b2018-03-01 11:20:25 -080055 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,
Colin Crossdfce7642018-02-28 13:05:39 -080065 })
Colin Cross5498f852018-01-03 23:39:54 -080066 }
67 }
68
Colin Cross8673b5b2018-03-01 11:20:25 -080069 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
Colin Cross5498f852018-01-03 23:39:54 -080097}