Home | History | Annotate | Download | only in symbol_inject
      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 
     15 package main
     16 
     17 import (
     18 	"debug/macho"
     19 	"fmt"
     20 	"io"
     21 	"sort"
     22 	"strings"
     23 )
     24 
     25 func 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 
     34 func 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 
     72 func 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