github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/nm/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) []Sym { 16 p, err := pe.NewFile(f) 17 if err != nil { 18 errorf("parsing %s: %v", f.Name(), err) 19 return nil 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 case *pe.OptionalHeader64: 31 imageBase = oh.ImageBase 32 default: 33 errorf("parsing %s: file format not recognized", f.Name()) 34 return nil 35 } 36 37 var syms []Sym 38 for _, s := range p.Symbols { 39 const ( 40 N_UNDEF = 0 // An undefined (extern) symbol 41 N_ABS = -1 // An absolute symbol (e_value is a constant, not an address) 42 N_DEBUG = -2 // A debugging symbol 43 ) 44 sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'} 45 switch s.SectionNumber { 46 case N_UNDEF: 47 sym.Code = 'U' 48 case N_ABS: 49 sym.Code = 'C' 50 case N_DEBUG: 51 sym.Code = '?' 52 default: 53 if s.SectionNumber < 0 { 54 errorf("parsing %s: invalid section number %d", f.Name(), s.SectionNumber) 55 return nil 56 } 57 if len(p.Sections) < int(s.SectionNumber) { 58 errorf("parsing %s: section number %d is large then max %d", f.Name(), s.SectionNumber, len(p.Sections)) 59 return nil 60 } 61 sect := p.Sections[s.SectionNumber-1] 62 const ( 63 text = 0x20 64 data = 0x40 65 bss = 0x80 66 permX = 0x20000000 67 permR = 0x40000000 68 permW = 0x80000000 69 ) 70 ch := sect.Characteristics 71 switch { 72 case ch&text != 0: 73 sym.Code = 'T' 74 case ch&data != 0: 75 if ch&permW == 0 { 76 sym.Code = 'R' 77 } else { 78 sym.Code = 'D' 79 } 80 case ch&bss != 0: 81 sym.Code = 'B' 82 } 83 sym.Addr += imageBase + uint64(sect.VirtualAddress) 84 } 85 syms = append(syms, sym) 86 addrs = append(addrs, sym.Addr) 87 } 88 89 sort.Sort(uint64s(addrs)) 90 for i := range syms { 91 j := sort.Search(len(addrs), func(x int) bool { return addrs[x] > syms[i].Addr }) 92 if j < len(addrs) { 93 syms[i].Size = int64(addrs[j] - syms[i].Addr) 94 } 95 } 96 97 return syms 98 }