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