blob: 58cf91a5af1354c45db08852b93008c48c9d4bab [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/pe"
19 "fmt"
20 "io"
21 "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 peSymbolsFromFile(r io.ReaderAt) (*File, error) {
Colin Cross5498f852018-01-03 23:39:54 -080026 peFile, err := pe.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 extractPESymbols(peFile)
32}
33
34func extractPESymbols(peFile *pe.File) (*File, error) {
35 var prefix string
Colin Cross64c6d4b2018-02-23 17:10:34 -080036 if peFile.FileHeader.Machine == pe.IMAGE_FILE_MACHINE_I386 {
37 // symbols in win32 exes seem to be prefixed with an underscore
Colin Cross8673b5b2018-03-01 11:20:25 -080038 prefix = "_"
Colin Cross64c6d4b2018-02-23 17:10:34 -080039 }
40
Colin Crossdfce7642018-02-28 13:05:39 -080041 symbols := peFile.Symbols
Colin Cross8673b5b2018-03-01 11:20:25 -080042 sort.SliceStable(symbols, func(i, j int) bool {
Colin Crossdfce7642018-02-28 13:05:39 -080043 if symbols[i].SectionNumber != symbols[j].SectionNumber {
44 return symbols[i].SectionNumber < symbols[j].SectionNumber
Colin Cross5498f852018-01-03 23:39:54 -080045 }
Colin Crossdfce7642018-02-28 13:05:39 -080046 return symbols[i].Value < symbols[j].Value
Colin Cross5498f852018-01-03 23:39:54 -080047 })
48
Colin Cross8673b5b2018-03-01 11:20:25 -080049 file := &File{}
50
51 for _, section := range peFile.Sections {
52 file.Sections = append(file.Sections, &Section{
53 Name: section.Name,
54 Addr: uint64(section.VirtualAddress),
55 Offset: uint64(section.Offset),
56 Size: uint64(section.VirtualSize),
57 })
58 }
59
Colin Crossdfce7642018-02-28 13:05:39 -080060 for _, symbol := range symbols {
Colin Cross8673b5b2018-03-01 11:20:25 -080061 if symbol.SectionNumber > 0 {
62 file.Symbols = append(file.Symbols, &Symbol{
63 Name: strings.TrimPrefix(symbol.Name, prefix),
64 // PE symbol value is the offset of the symbol into the section
65 Addr: uint64(symbol.Value),
66 // PE symbols don't have size information
67 Size: 0,
68 Section: file.Sections[symbol.SectionNumber-1],
Colin Crossdfce7642018-02-28 13:05:39 -080069 })
Colin Cross5498f852018-01-03 23:39:54 -080070 }
71 }
72
Colin Cross8673b5b2018-03-01 11:20:25 -080073 return file, nil
74}
75
76func dumpPESymbols(r io.ReaderAt) error {
77 peFile, err := pe.NewFile(r)
78 if err != nil {
79 return cantParseError{err}
80 }
81
82 fmt.Println("&pe.File{")
83 fmt.Println("\tFileHeader: pe.FileHeader{")
84 fmt.Printf("\t\tMachine: %#v,\n", peFile.FileHeader.Machine)
85 fmt.Println("\t},")
86
87 fmt.Println("\tSections: []*pe.Section{")
88 for _, section := range peFile.Sections {
89 fmt.Printf("\t\t&pe.Section{SectionHeader: %#v},\n", section.SectionHeader)
90 }
91 fmt.Println("\t},")
92
93 fmt.Println("\tSymbols: []*pe.Symbol{")
94 for _, symbol := range peFile.Symbols {
95 fmt.Printf("\t\t%#v,\n", symbol)
96 }
97 fmt.Println("\t},")
98
99 fmt.Println("}")
100
101 return nil
Colin Cross5498f852018-01-03 23:39:54 -0800102}