Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright 2013 The Go Authors. All rights reserved. | 1 // Copyright 2013 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Parsing of PE executables (Microsoft Windows). | 5 // Parsing of PE executables (Microsoft Windows). |
6 | 6 |
7 package main | 7 package main |
8 | 8 |
9 import ( | 9 import ( |
10 "debug/pe" | 10 "debug/pe" |
11 "os" | 11 "os" |
12 ) | 12 ) |
13 | 13 |
14 func peSymbols(f *os.File) []Sym { | 14 func peSymbols(f *os.File) []Sym { |
15 p, err := pe.NewFile(f) | 15 p, err := pe.NewFile(f) |
16 if err != nil { | 16 if err != nil { |
17 errorf("parsing %s: %v", f.Name(), err) | 17 errorf("parsing %s: %v", f.Name(), err) |
18 return nil | 18 return nil |
19 } | 19 } |
20 | 20 |
21 var imageBase uint64 | |
22 switch oh := p.OptionalHeader.(type) { | |
23 case *pe.OptionalHeader32: | |
24 imageBase = uint64(oh.ImageBase) | |
25 case *pe.OptionalHeader64: | |
26 imageBase = oh.ImageBase | |
27 default: | |
28 errorf("parsing %s: file format not recognized", f.Name()) | |
29 return nil | |
30 } | |
31 | |
21 var syms []Sym | 32 var syms []Sym |
22 for _, s := range p.Symbols { | 33 for _, s := range p.Symbols { |
34 const ( | |
35 N_UNDEF = 0 // An undefined (extern) symbol | |
36 N_ABS = -1 // An absolute symbol (e_value is a constan t, not an address) | |
37 N_DEBUG = -2 // A debugging symbol | |
38 ) | |
23 sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'} | 39 sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'} |
24 » » if s.SectionNumber == 0 { | 40 » » switch s.SectionNumber { |
41 » » case N_UNDEF: | |
25 sym.Code = 'U' | 42 sym.Code = 'U' |
26 » » } else if int(s.SectionNumber) <= len(p.Sections) { | 43 » » case N_ABS, N_DEBUG: |
44 » » » sym.Code = 'T' // not sure about this | |
ruiu
2014/04/17 00:06:58
I think it should be "A" for N_ABS.
brainman
2014/04/17 00:26:11
I don't see such symbol type defined anywhere - I
ruiu
2014/04/17 00:31:12
I was looking at GNU binutil's nm man page.
rsc
2014/04/17 02:10:40
I'll change this to C for constant and update nm/d
| |
45 » » default: | |
46 » » » if s.SectionNumber < 0 { | |
47 » » » » errorf("parsing %s: invalid section number %d", f.Name(), s.SectionNumber) | |
48 » » » » return nil | |
49 » » » } | |
50 » » » if len(p.Sections) < int(s.SectionNumber) { | |
51 » » » » errorf("parsing %s: section number %d is large t hen max %d", f.Name(), s.SectionNumber, len(p.Sections)) | |
52 » » » » return nil | |
53 » » » } | |
27 sect := p.Sections[s.SectionNumber-1] | 54 sect := p.Sections[s.SectionNumber-1] |
28 const ( | 55 const ( |
29 text = 0x20 | 56 text = 0x20 |
30 data = 0x40 | 57 data = 0x40 |
31 bss = 0x80 | 58 bss = 0x80 |
32 permX = 0x20000000 | 59 permX = 0x20000000 |
33 permR = 0x40000000 | 60 permR = 0x40000000 |
34 permW = 0x80000000 | 61 permW = 0x80000000 |
35 ) | 62 ) |
36 ch := sect.Characteristics | 63 ch := sect.Characteristics |
37 switch { | 64 switch { |
38 case ch&text != 0: | 65 case ch&text != 0: |
39 sym.Code = 'T' | 66 sym.Code = 'T' |
40 case ch&data != 0: | 67 case ch&data != 0: |
41 if ch&permW == 0 { | 68 if ch&permW == 0 { |
42 sym.Code = 'R' | 69 sym.Code = 'R' |
43 } else { | 70 } else { |
44 sym.Code = 'D' | 71 sym.Code = 'D' |
45 } | 72 } |
46 case ch&bss != 0: | 73 case ch&bss != 0: |
47 sym.Code = 'B' | 74 sym.Code = 'B' |
48 } | 75 } |
76 sym.Addr += imageBase + uint64(sect.VirtualAddress) | |
49 } | 77 } |
50 syms = append(syms, sym) | 78 syms = append(syms, sym) |
51 } | 79 } |
52 | 80 |
53 return syms | 81 return syms |
54 } | 82 } |
OLD | NEW |