github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/objdump/pe.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Parsing of PE executables (Microsoft Windows). 6 7 package main 8 9 import ( 10 "debug/pe" 11 "os" 12 "sort" 13 ) 14 15 func peSymbols(f *os.File) (syms []Sym, goarch string) { 16 p, err := pe.NewFile(f) 17 if err != nil { 18 errorf("parsing %s: %v", f.Name(), err) 19 return 20 } 21 22 // Build sorted list of addresses of all symbols. 23 // We infer the size of a symbol by looking at where the next symbol begins. 24 var addrs []uint64 25 26 var imageBase uint64 27 switch oh := p.OptionalHeader.(type) { 28 case *pe.OptionalHeader32: 29 imageBase = uint64(oh.ImageBase) 30 goarch = "386" 31 case *pe.OptionalHeader64: 32 imageBase = oh.ImageBase 33 goarch = "amd64" 34 default: 35 errorf("parsing %s: file format not recognized", f.Name()) 36 return 37 } 38 39 for _, s := range p.Symbols { 40 const ( 41 N_UNDEF = 0 // An undefined (extern) symbol 42 N_ABS = -1 // An absolute symbol (e_value is a constant, not an address) 43 N_DEBUG = -2 // A debugging symbol 44 ) 45 sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'} 46 switch s.SectionNumber { 47 case N_UNDEF: 48 sym.Code = 'U' 49 case N_ABS: 50 sym.Code = 'C' 51 case N_DEBUG: 52 sym.Code = '?' 53 default: 54 if s.SectionNumber < 0 { 55 errorf("parsing %s: invalid section number %d", f.Name(), s.SectionNumber) 56 return 57 } 58 if len(p.Sections) < int(s.SectionNumber) { 59 errorf("parsing %s: section number %d is large then max %d", f.Name(), s.SectionNumber, len(p.Sections)) 60 return 61 } 62 sect := p.Sections[s.SectionNumber-1] 63 const ( 64 text = 0x20 65 data = 0x40 66 bss = 0x80 67 permX = 0x20000000 68 permR = 0x40000000 69 permW = 0x80000000 70 ) 71 ch := sect.Characteristics 72 switch { 73 case ch&text != 0: 74 sym.Code = 'T' 75 case ch&data != 0: 76 if ch&permW == 0 { 77 sym.Code = 'R' 78 } else { 79 sym.Code = 'D' 80 } 81 case ch&bss != 0: 82 sym.Code = 'B' 83 } 84 sym.Addr += imageBase + uint64(sect.VirtualAddress) 85 } 86 syms = append(syms, sym) 87 addrs = append(addrs, sym.Addr) 88 } 89 90 sort.Sort(uint64s(addrs)) 91 for i := range syms { 92 j := sort.Search(len(addrs), func(x int) bool { return addrs[x] > syms[i].Addr }) 93 if j < len(addrs) { 94 syms[i].Size = int64(addrs[j] - syms[i].Addr) 95 } 96 } 97 98 return 99 }