github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/debug/dwarf/open.go (about) 1 // Copyright 2009 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 // Package dwarf provides access to DWARF debugging information loaded from 6 // executable files, as defined in the DWARF 2.0 Standard at 7 // http://dwarfstd.org/doc/dwarf-2.0.0.pdf 8 package dwarf 9 10 import "encoding/binary" 11 12 // Data represents the DWARF debugging information 13 // loaded from an executable file (for example, an ELF or Mach-O executable). 14 type Data struct { 15 // raw data 16 abbrev []byte 17 aranges []byte 18 frame []byte 19 info []byte 20 line []byte 21 pubnames []byte 22 ranges []byte 23 str []byte 24 25 // New sections added in DWARF 5. 26 addr []byte 27 lineStr []byte 28 strOffsets []byte 29 30 // parsed data 31 abbrevCache map[uint64]abbrevTable 32 bigEndian bool 33 order binary.ByteOrder 34 typeCache map[Offset]Type 35 typeSigs map[uint64]*typeUnit 36 unit []unit 37 } 38 39 // New returns a new Data object initialized from the given parameters. 40 // Rather than calling this function directly, clients should typically use 41 // the DWARF method of the File type of the appropriate package debug/elf, 42 // debug/macho, debug/pe, or debug/xcoff. 43 // 44 // The []byte arguments are the data from the corresponding debug section 45 // in the object file; for example, for an ELF object, abbrev is the contents of 46 // the ".debug_abbrev" section. 47 func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Data, error) { 48 d := &Data{ 49 abbrev: abbrev, 50 aranges: aranges, 51 frame: frame, 52 info: info, 53 line: line, 54 pubnames: pubnames, 55 ranges: ranges, 56 str: str, 57 abbrevCache: make(map[uint64]abbrevTable), 58 typeCache: make(map[Offset]Type), 59 typeSigs: make(map[uint64]*typeUnit), 60 } 61 62 // Sniff .debug_info to figure out byte order. 63 // 32-bit DWARF: 4 byte length, 2 byte version. 64 // 64-bit DWARf: 4 bytes of 0xff, 8 byte length, 2 byte version. 65 if len(d.info) < 6 { 66 return nil, DecodeError{"info", Offset(len(d.info)), "too short"} 67 } 68 offset := 4 69 if d.info[0] == 0xff && d.info[1] == 0xff && d.info[2] == 0xff && d.info[3] == 0xff { 70 if len(d.info) < 14 { 71 return nil, DecodeError{"info", Offset(len(d.info)), "too short"} 72 } 73 offset = 12 74 } 75 // Fetch the version, a tiny 16-bit number (1, 2, 3, 4, 5). 76 x, y := d.info[offset], d.info[offset+1] 77 switch { 78 case x == 0 && y == 0: 79 return nil, DecodeError{"info", 4, "unsupported version 0"} 80 case x == 0: 81 d.bigEndian = true 82 d.order = binary.BigEndian 83 case y == 0: 84 d.bigEndian = false 85 d.order = binary.LittleEndian 86 default: 87 return nil, DecodeError{"info", 4, "cannot determine byte order"} 88 } 89 90 u, err := d.parseUnits() 91 if err != nil { 92 return nil, err 93 } 94 d.unit = u 95 return d, nil 96 } 97 98 // AddTypes will add one .debug_types section to the DWARF data. A 99 // typical object with DWARF version 4 debug info will have multiple 100 // .debug_types sections. The name is used for error reporting only, 101 // and serves to distinguish one .debug_types section from another. 102 func (d *Data) AddTypes(name string, types []byte) error { 103 return d.parseTypes(name, types) 104 } 105 106 // AddSection adds another DWARF section by name. The name should be a 107 // DWARF section name such as ".debug_addr", ".debug_str_offsets", and 108 // so forth. This approach is used for new DWARF sections added in 109 // DWARF 5 and later. 110 func (d *Data) AddSection(name string, contents []byte) error { 111 switch name { 112 case ".debug_addr": 113 d.addr = contents 114 case ".debug_line_str": 115 d.lineStr = contents 116 case ".debug_str_offsets": 117 d.strOffsets = contents 118 } 119 // Just ignore names that we don't yet support. 120 return nil 121 }