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  }