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