blob: cbdc838a12b1d142064d357118a92e9ad7f31375 [file] [log] [blame]
Dan Willemsen38f2dba2016-07-08 14:54:35 -07001// Copyright 2009 The Go Authors. All rights reserved.
Brent Austinba3052e2015-04-21 16:08:23 -07002// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// DWARF debug information entry parser.
6// An entry is a sequence of data items of a given format.
7// The first word in the entry is an index into what DWARF
8// calls the ``abbreviation table.'' An abbreviation is really
9// just a type descriptor: it's an array of attribute tag/value format pairs.
10
11package dwarf
12
13import (
Patrice Arruda748609c2020-06-25 12:12:21 -070014 "encoding/binary"
Brent Austinba3052e2015-04-21 16:08:23 -070015 "errors"
16 "strconv"
17)
18
19// a single entry's description: a sequence of attributes
20type abbrev struct {
21 tag Tag
22 children bool
23 field []afield
24}
25
26type afield struct {
Dan Willemsen09eb3b12015-09-16 14:34:17 -070027 attr Attr
28 fmt format
29 class Class
Patrice Arruda748609c2020-06-25 12:12:21 -070030 val int64 // for formImplicitConst
Brent Austinba3052e2015-04-21 16:08:23 -070031}
32
33// a map from entry format ids to their descriptions
34type abbrevTable map[uint32]abbrev
35
36// ParseAbbrev returns the abbreviation table that starts at byte off
37// in the .debug_abbrev section.
Dan Willemsena3223282018-02-27 19:41:43 -080038func (d *Data) parseAbbrev(off uint64, vers int) (abbrevTable, error) {
Brent Austinba3052e2015-04-21 16:08:23 -070039 if m, ok := d.abbrevCache[off]; ok {
40 return m, nil
41 }
42
43 data := d.abbrev
Dan Willemsena3223282018-02-27 19:41:43 -080044 if off > uint64(len(data)) {
Brent Austinba3052e2015-04-21 16:08:23 -070045 data = nil
46 } else {
47 data = data[off:]
48 }
49 b := makeBuf(d, unknownFormat{}, "abbrev", 0, data)
50
51 // Error handling is simplified by the buf getters
52 // returning an endless stream of 0s after an error.
53 m := make(abbrevTable)
54 for {
55 // Table ends with id == 0.
56 id := uint32(b.uint())
57 if id == 0 {
58 break
59 }
60
61 // Walk over attributes, counting.
62 n := 0
63 b1 := b // Read from copy of b.
64 b1.uint()
65 b1.uint8()
66 for {
67 tag := b1.uint()
68 fmt := b1.uint()
69 if tag == 0 && fmt == 0 {
70 break
71 }
Patrice Arruda748609c2020-06-25 12:12:21 -070072 if format(fmt) == formImplicitConst {
73 b1.int()
74 }
Brent Austinba3052e2015-04-21 16:08:23 -070075 n++
76 }
77 if b1.err != nil {
78 return nil, b1.err
79 }
80
81 // Walk over attributes again, this time writing them down.
82 var a abbrev
83 a.tag = Tag(b.uint())
84 a.children = b.uint8() != 0
85 a.field = make([]afield, n)
86 for i := range a.field {
87 a.field[i].attr = Attr(b.uint())
88 a.field[i].fmt = format(b.uint())
Dan Willemsen09eb3b12015-09-16 14:34:17 -070089 a.field[i].class = formToClass(a.field[i].fmt, a.field[i].attr, vers, &b)
Patrice Arruda748609c2020-06-25 12:12:21 -070090 if a.field[i].fmt == formImplicitConst {
91 a.field[i].val = b.int()
92 }
Brent Austinba3052e2015-04-21 16:08:23 -070093 }
94 b.uint()
95 b.uint()
96
97 m[id] = a
98 }
99 if b.err != nil {
100 return nil, b.err
101 }
102 d.abbrevCache[off] = m
103 return m, nil
104}
105
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700106// attrIsExprloc indicates attributes that allow exprloc values that
107// are encoded as block values in DWARF 2 and 3. See DWARF 4, Figure
108// 20.
109var attrIsExprloc = map[Attr]bool{
110 AttrLocation: true,
111 AttrByteSize: true,
112 AttrBitOffset: true,
113 AttrBitSize: true,
114 AttrStringLength: true,
115 AttrLowerBound: true,
116 AttrReturnAddr: true,
117 AttrStrideSize: true,
118 AttrUpperBound: true,
119 AttrCount: true,
120 AttrDataMemberLoc: true,
121 AttrFrameBase: true,
122 AttrSegment: true,
123 AttrStaticLink: true,
124 AttrUseLocation: true,
125 AttrVtableElemLoc: true,
126 AttrAllocated: true,
127 AttrAssociated: true,
128 AttrDataLocation: true,
129 AttrStride: true,
130}
131
132// attrPtrClass indicates the *ptr class of attributes that have
133// encoding formSecOffset in DWARF 4 or formData* in DWARF 2 and 3.
134var attrPtrClass = map[Attr]Class{
135 AttrLocation: ClassLocListPtr,
136 AttrStmtList: ClassLinePtr,
137 AttrStringLength: ClassLocListPtr,
138 AttrReturnAddr: ClassLocListPtr,
139 AttrStartScope: ClassRangeListPtr,
140 AttrDataMemberLoc: ClassLocListPtr,
141 AttrFrameBase: ClassLocListPtr,
142 AttrMacroInfo: ClassMacPtr,
143 AttrSegment: ClassLocListPtr,
144 AttrStaticLink: ClassLocListPtr,
145 AttrUseLocation: ClassLocListPtr,
146 AttrVtableElemLoc: ClassLocListPtr,
147 AttrRanges: ClassRangeListPtr,
Patrice Arruda748609c2020-06-25 12:12:21 -0700148 // The following are new in DWARF 5.
149 AttrStrOffsetsBase: ClassStrOffsetsPtr,
150 AttrAddrBase: ClassAddrPtr,
151 AttrRnglistsBase: ClassRngListsPtr,
152 AttrLoclistsBase: ClassLocListPtr,
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700153}
154
155// formToClass returns the DWARF 4 Class for the given form. If the
156// DWARF version is less then 4, it will disambiguate some forms
157// depending on the attribute.
158func formToClass(form format, attr Attr, vers int, b *buf) Class {
159 switch form {
160 default:
161 b.error("cannot determine class of unknown attribute form")
162 return 0
163
Patrice Arruda748609c2020-06-25 12:12:21 -0700164 case formIndirect:
165 return ClassUnknown
166
167 case formAddr, formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4:
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700168 return ClassAddress
169
170 case formDwarfBlock1, formDwarfBlock2, formDwarfBlock4, formDwarfBlock:
171 // In DWARF 2 and 3, ClassExprLoc was encoded as a
172 // block. DWARF 4 distinguishes ClassBlock and
173 // ClassExprLoc, but there are no attributes that can
174 // be both, so we also promote ClassBlock values in
175 // DWARF 4 that should be ClassExprLoc in case
176 // producers get this wrong.
177 if attrIsExprloc[attr] {
178 return ClassExprLoc
179 }
180 return ClassBlock
181
Patrice Arruda748609c2020-06-25 12:12:21 -0700182 case formData1, formData2, formData4, formData8, formSdata, formUdata, formData16, formImplicitConst:
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700183 // In DWARF 2 and 3, ClassPtr was encoded as a
184 // constant. Unlike ClassExprLoc/ClassBlock, some
185 // DWARF 4 attributes need to distinguish Class*Ptr
186 // from ClassConstant, so we only do this promotion
187 // for versions 2 and 3.
188 if class, ok := attrPtrClass[attr]; vers < 4 && ok {
189 return class
190 }
191 return ClassConstant
192
193 case formFlag, formFlagPresent:
194 return ClassFlag
195
Patrice Arruda748609c2020-06-25 12:12:21 -0700196 case formRefAddr, formRef1, formRef2, formRef4, formRef8, formRefUdata, formRefSup4, formRefSup8:
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700197 return ClassReference
198
199 case formRefSig8:
200 return ClassReferenceSig
201
Patrice Arruda748609c2020-06-25 12:12:21 -0700202 case formString, formStrp, formStrx, formStrpSup, formLineStrp, formStrx1, formStrx2, formStrx3, formStrx4:
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700203 return ClassString
204
205 case formSecOffset:
206 // DWARF 4 defines four *ptr classes, but doesn't
207 // distinguish them in the encoding. Disambiguate
208 // these classes using the attribute.
209 if class, ok := attrPtrClass[attr]; ok {
210 return class
211 }
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700212 return ClassUnknown
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700213
214 case formExprloc:
215 return ClassExprLoc
216
217 case formGnuRefAlt:
218 return ClassReferenceAlt
219
220 case formGnuStrpAlt:
221 return ClassStringAlt
Patrice Arruda748609c2020-06-25 12:12:21 -0700222
223 case formLoclistx:
224 return ClassLocList
225
226 case formRnglistx:
227 return ClassRngList
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700228 }
229}
230
Brent Austinba3052e2015-04-21 16:08:23 -0700231// An entry is a sequence of attribute/value pairs.
232type Entry struct {
233 Offset Offset // offset of Entry in DWARF info
234 Tag Tag // tag (kind of Entry)
235 Children bool // whether Entry is followed by children
236 Field []Field
237}
238
239// A Field is a single attribute/value pair in an Entry.
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700240//
241// A value can be one of several "attribute classes" defined by DWARF.
242// The Go types corresponding to each class are:
243//
244// DWARF class Go type Class
245// ----------- ------- -----
246// address uint64 ClassAddress
247// block []byte ClassBlock
248// constant int64 ClassConstant
249// flag bool ClassFlag
250// reference
251// to info dwarf.Offset ClassReference
252// to type unit uint64 ClassReferenceSig
253// string string ClassString
254// exprloc []byte ClassExprLoc
255// lineptr int64 ClassLinePtr
256// loclistptr int64 ClassLocListPtr
257// macptr int64 ClassMacPtr
258// rangelistptr int64 ClassRangeListPtr
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700259//
260// For unrecognized or vendor-defined attributes, Class may be
261// ClassUnknown.
Brent Austinba3052e2015-04-21 16:08:23 -0700262type Field struct {
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700263 Attr Attr
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800264 Val any
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700265 Class Class
266}
267
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700268// A Class is the DWARF 4 class of an attribute value.
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700269//
270// In general, a given attribute's value may take on one of several
271// possible classes defined by DWARF, each of which leads to a
272// slightly different interpretation of the attribute.
273//
274// DWARF version 4 distinguishes attribute value classes more finely
275// than previous versions of DWARF. The reader will disambiguate
276// coarser classes from earlier versions of DWARF into the appropriate
277// DWARF 4 class. For example, DWARF 2 uses "constant" for constants
278// as well as all types of section offsets, but the reader will
279// canonicalize attributes in DWARF 2 files that refer to section
280// offsets to one of the Class*Ptr classes, even though these classes
281// were only defined in DWARF 3.
282type Class int
283
284const (
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700285 // ClassUnknown represents values of unknown DWARF class.
286 ClassUnknown Class = iota
287
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700288 // ClassAddress represents values of type uint64 that are
289 // addresses on the target machine.
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700290 ClassAddress
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700291
292 // ClassBlock represents values of type []byte whose
293 // interpretation depends on the attribute.
294 ClassBlock
295
296 // ClassConstant represents values of type int64 that are
297 // constants. The interpretation of this constant depends on
298 // the attribute.
299 ClassConstant
300
301 // ClassExprLoc represents values of type []byte that contain
302 // an encoded DWARF expression or location description.
303 ClassExprLoc
304
305 // ClassFlag represents values of type bool.
306 ClassFlag
307
308 // ClassLinePtr represents values that are an int64 offset
309 // into the "line" section.
310 ClassLinePtr
311
312 // ClassLocListPtr represents values that are an int64 offset
313 // into the "loclist" section.
314 ClassLocListPtr
315
316 // ClassMacPtr represents values that are an int64 offset into
317 // the "mac" section.
318 ClassMacPtr
319
Dan Willemsencc753b72021-08-31 13:25:42 -0700320 // ClassRangeListPtr represents values that are an int64 offset into
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700321 // the "rangelist" section.
322 ClassRangeListPtr
323
324 // ClassReference represents values that are an Offset offset
325 // of an Entry in the info section (for use with Reader.Seek).
326 // The DWARF specification combines ClassReference and
327 // ClassReferenceSig into class "reference".
328 ClassReference
329
330 // ClassReferenceSig represents values that are a uint64 type
331 // signature referencing a type Entry.
332 ClassReferenceSig
333
334 // ClassString represents values that are strings. If the
335 // compilation unit specifies the AttrUseUTF8 flag (strongly
336 // recommended), the string value will be encoded in UTF-8.
337 // Otherwise, the encoding is unspecified.
338 ClassString
339
340 // ClassReferenceAlt represents values of type int64 that are
341 // an offset into the DWARF "info" section of an alternate
342 // object file.
343 ClassReferenceAlt
344
345 // ClassStringAlt represents values of type int64 that are an
346 // offset into the DWARF string section of an alternate object
347 // file.
348 ClassStringAlt
Patrice Arruda748609c2020-06-25 12:12:21 -0700349
350 // ClassAddrPtr represents values that are an int64 offset
351 // into the "addr" section.
352 ClassAddrPtr
353
354 // ClassLocList represents values that are an int64 offset
355 // into the "loclists" section.
356 ClassLocList
357
Dan Willemsencc753b72021-08-31 13:25:42 -0700358 // ClassRngList represents values that are a uint64 offset
Patrice Arruda748609c2020-06-25 12:12:21 -0700359 // from the base of the "rnglists" section.
360 ClassRngList
361
362 // ClassRngListsPtr represents values that are an int64 offset
363 // into the "rnglists" section. These are used as the base for
364 // ClassRngList values.
365 ClassRngListsPtr
366
367 // ClassStrOffsetsPtr represents values that are an int64
368 // offset into the "str_offsets" section.
369 ClassStrOffsetsPtr
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700370)
371
372//go:generate stringer -type=Class
373
374func (i Class) GoString() string {
375 return "dwarf." + i.String()
Brent Austinba3052e2015-04-21 16:08:23 -0700376}
377
378// Val returns the value associated with attribute Attr in Entry,
379// or nil if there is no such attribute.
380//
381// A common idiom is to merge the check for nil return with
382// the check that the value has the expected dynamic type, as in:
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700383// v, ok := e.Val(AttrSibling).(int64)
Brent Austinba3052e2015-04-21 16:08:23 -0700384//
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800385func (e *Entry) Val(a Attr) any {
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700386 if f := e.AttrField(a); f != nil {
387 return f.Val
388 }
389 return nil
390}
391
392// AttrField returns the Field associated with attribute Attr in
393// Entry, or nil if there is no such attribute.
394func (e *Entry) AttrField(a Attr) *Field {
395 for i, f := range e.Field {
Brent Austinba3052e2015-04-21 16:08:23 -0700396 if f.Attr == a {
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700397 return &e.Field[i]
Brent Austinba3052e2015-04-21 16:08:23 -0700398 }
399 }
400 return nil
401}
402
403// An Offset represents the location of an Entry within the DWARF info.
404// (See Reader.Seek.)
405type Offset uint32
406
407// Entry reads a single entry from buf, decoding
408// according to the given abbreviation table.
Patrice Arruda748609c2020-06-25 12:12:21 -0700409func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry {
Brent Austinba3052e2015-04-21 16:08:23 -0700410 off := b.off
411 id := uint32(b.uint())
412 if id == 0 {
413 return &Entry{}
414 }
415 a, ok := atab[id]
416 if !ok {
417 b.error("unknown abbreviation table index")
418 return nil
419 }
420 e := &Entry{
421 Offset: off,
422 Tag: a.tag,
423 Children: a.children,
424 Field: make([]Field, len(a.field)),
425 }
Colin Cross1f805522021-05-14 11:10:59 -0700426
427 // If we are currently parsing the compilation unit,
428 // we can't evaluate Addrx or Strx until we've seen the
429 // relevant base entry.
430 type delayed struct {
431 idx int
432 off uint64
433 fmt format
434 }
435 var delay []delayed
436
437 resolveStrx := func(strBase, off uint64) string {
438 off += strBase
439 if uint64(int(off)) != off {
440 b.error("DW_FORM_strx offset out of range")
441 }
442
443 b1 := makeBuf(b.dwarf, b.format, "str_offsets", 0, b.dwarf.strOffsets)
444 b1.skip(int(off))
445 is64, _ := b.format.dwarf64()
446 if is64 {
447 off = b1.uint64()
448 } else {
449 off = uint64(b1.uint32())
450 }
451 if b1.err != nil {
452 b.err = b1.err
453 return ""
454 }
455 if uint64(int(off)) != off {
456 b.error("DW_FORM_strx indirect offset out of range")
457 }
458 b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
459 b1.skip(int(off))
460 val := b1.string()
461 if b1.err != nil {
462 b.err = b1.err
463 }
464 return val
465 }
466
Dan Willemsencc753b72021-08-31 13:25:42 -0700467 resolveRnglistx := func(rnglistsBase, off uint64) uint64 {
468 is64, _ := b.format.dwarf64()
469 if is64 {
470 off *= 8
471 } else {
472 off *= 4
473 }
474 off += rnglistsBase
475 if uint64(int(off)) != off {
476 b.error("DW_FORM_rnglistx offset out of range")
477 }
478
479 b1 := makeBuf(b.dwarf, b.format, "rnglists", 0, b.dwarf.rngLists)
480 b1.skip(int(off))
481 if is64 {
482 off = b1.uint64()
483 } else {
484 off = uint64(b1.uint32())
485 }
486 if b1.err != nil {
487 b.err = b1.err
488 return 0
489 }
490 if uint64(int(off)) != off {
491 b.error("DW_FORM_rnglistx indirect offset out of range")
492 }
493 return rnglistsBase + off
494 }
495
Brent Austinba3052e2015-04-21 16:08:23 -0700496 for i := range e.Field {
497 e.Field[i].Attr = a.field[i].attr
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700498 e.Field[i].Class = a.field[i].class
Brent Austinba3052e2015-04-21 16:08:23 -0700499 fmt := a.field[i].fmt
500 if fmt == formIndirect {
501 fmt = format(b.uint())
Patrice Arruda748609c2020-06-25 12:12:21 -0700502 e.Field[i].Class = formToClass(fmt, a.field[i].attr, vers, b)
Brent Austinba3052e2015-04-21 16:08:23 -0700503 }
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800504 var val any
Brent Austinba3052e2015-04-21 16:08:23 -0700505 switch fmt {
506 default:
507 b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
508
509 // address
510 case formAddr:
511 val = b.addr()
Patrice Arruda748609c2020-06-25 12:12:21 -0700512 case formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4:
513 var off uint64
514 switch fmt {
515 case formAddrx:
516 off = b.uint()
517 case formAddrx1:
518 off = uint64(b.uint8())
519 case formAddrx2:
520 off = uint64(b.uint16())
521 case formAddrx3:
522 off = uint64(b.uint24())
523 case formAddrx4:
524 off = uint64(b.uint32())
525 }
Colin Cross1f805522021-05-14 11:10:59 -0700526 if b.dwarf.addr == nil {
Patrice Arruda748609c2020-06-25 12:12:21 -0700527 b.error("DW_FORM_addrx with no .debug_addr section")
528 }
529 if b.err != nil {
530 return nil
531 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700532
533 // We have to adjust by the offset of the
534 // compilation unit. This won't work if the
535 // program uses Reader.Seek to skip over the
536 // unit. Not much we can do about that.
Colin Cross1f805522021-05-14 11:10:59 -0700537 var addrBase int64
Patrice Arruda748609c2020-06-25 12:12:21 -0700538 if cu != nil {
Colin Cross1f805522021-05-14 11:10:59 -0700539 addrBase, _ = cu.Val(AttrAddrBase).(int64)
540 } else if a.tag == TagCompileUnit {
541 delay = append(delay, delayed{i, off, formAddrx})
542 break
543 }
544
545 var err error
546 val, err = b.dwarf.debugAddr(b.format, uint64(addrBase), off)
547 if err != nil {
548 if b.err == nil {
549 b.err = err
Patrice Arruda748609c2020-06-25 12:12:21 -0700550 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700551 return nil
552 }
Brent Austinba3052e2015-04-21 16:08:23 -0700553
554 // block
555 case formDwarfBlock1:
556 val = b.bytes(int(b.uint8()))
557 case formDwarfBlock2:
558 val = b.bytes(int(b.uint16()))
559 case formDwarfBlock4:
560 val = b.bytes(int(b.uint32()))
561 case formDwarfBlock:
562 val = b.bytes(int(b.uint()))
563
564 // constant
565 case formData1:
566 val = int64(b.uint8())
567 case formData2:
568 val = int64(b.uint16())
569 case formData4:
570 val = int64(b.uint32())
571 case formData8:
572 val = int64(b.uint64())
Patrice Arruda748609c2020-06-25 12:12:21 -0700573 case formData16:
574 val = b.bytes(16)
Brent Austinba3052e2015-04-21 16:08:23 -0700575 case formSdata:
576 val = int64(b.int())
577 case formUdata:
578 val = int64(b.uint())
Patrice Arruda748609c2020-06-25 12:12:21 -0700579 case formImplicitConst:
580 val = a.field[i].val
Brent Austinba3052e2015-04-21 16:08:23 -0700581
582 // flag
583 case formFlag:
584 val = b.uint8() == 1
585 // New in DWARF 4.
586 case formFlagPresent:
587 // The attribute is implicitly indicated as present, and no value is
588 // encoded in the debugging information entry itself.
589 val = true
590
591 // reference to other entry
592 case formRefAddr:
593 vers := b.format.version()
594 if vers == 0 {
595 b.error("unknown version for DW_FORM_ref_addr")
596 } else if vers == 2 {
597 val = Offset(b.addr())
598 } else {
599 is64, known := b.format.dwarf64()
600 if !known {
601 b.error("unknown size for DW_FORM_ref_addr")
602 } else if is64 {
603 val = Offset(b.uint64())
604 } else {
605 val = Offset(b.uint32())
606 }
607 }
608 case formRef1:
609 val = Offset(b.uint8()) + ubase
610 case formRef2:
611 val = Offset(b.uint16()) + ubase
612 case formRef4:
613 val = Offset(b.uint32()) + ubase
614 case formRef8:
615 val = Offset(b.uint64()) + ubase
616 case formRefUdata:
617 val = Offset(b.uint()) + ubase
618
619 // string
620 case formString:
621 val = b.string()
Patrice Arruda748609c2020-06-25 12:12:21 -0700622 case formStrp, formLineStrp:
Dan Willemsenc7413322018-08-27 23:21:26 -0700623 var off uint64 // offset into .debug_str
624 is64, known := b.format.dwarf64()
625 if !known {
Patrice Arruda748609c2020-06-25 12:12:21 -0700626 b.error("unknown size for DW_FORM_strp/line_strp")
Dan Willemsenc7413322018-08-27 23:21:26 -0700627 } else if is64 {
628 off = b.uint64()
629 } else {
630 off = uint64(b.uint32())
631 }
632 if uint64(int(off)) != off {
Patrice Arruda748609c2020-06-25 12:12:21 -0700633 b.error("DW_FORM_strp/line_strp offset out of range")
Dan Willemsenc7413322018-08-27 23:21:26 -0700634 }
Brent Austinba3052e2015-04-21 16:08:23 -0700635 if b.err != nil {
636 return nil
637 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700638 var b1 buf
639 if fmt == formStrp {
640 b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
641 } else {
642 if len(b.dwarf.lineStr) == 0 {
643 b.error("DW_FORM_line_strp with no .debug_line_str section")
Dan Willemsenbc60c3c2021-12-15 01:09:00 -0800644 return nil
Patrice Arruda748609c2020-06-25 12:12:21 -0700645 }
646 b1 = makeBuf(b.dwarf, b.format, "line_str", 0, b.dwarf.lineStr)
647 }
Brent Austinba3052e2015-04-21 16:08:23 -0700648 b1.skip(int(off))
649 val = b1.string()
650 if b1.err != nil {
651 b.err = b1.err
652 return nil
653 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700654 case formStrx, formStrx1, formStrx2, formStrx3, formStrx4:
655 var off uint64
656 switch fmt {
657 case formStrx:
658 off = b.uint()
659 case formStrx1:
660 off = uint64(b.uint8())
661 case formStrx2:
662 off = uint64(b.uint16())
663 case formStrx3:
664 off = uint64(b.uint24())
665 case formStrx4:
666 off = uint64(b.uint32())
667 }
668 if len(b.dwarf.strOffsets) == 0 {
669 b.error("DW_FORM_strx with no .debug_str_offsets section")
670 }
671 is64, known := b.format.dwarf64()
672 if !known {
673 b.error("unknown offset size for DW_FORM_strx")
674 }
675 if b.err != nil {
676 return nil
677 }
678 if is64 {
679 off *= 8
680 } else {
681 off *= 4
682 }
683
684 // We have to adjust by the offset of the
685 // compilation unit. This won't work if the
686 // program uses Reader.Seek to skip over the
687 // unit. Not much we can do about that.
Colin Cross1f805522021-05-14 11:10:59 -0700688 var strBase int64
Patrice Arruda748609c2020-06-25 12:12:21 -0700689 if cu != nil {
Colin Cross1f805522021-05-14 11:10:59 -0700690 strBase, _ = cu.Val(AttrStrOffsetsBase).(int64)
691 } else if a.tag == TagCompileUnit {
692 delay = append(delay, delayed{i, off, formStrx})
693 break
Patrice Arruda748609c2020-06-25 12:12:21 -0700694 }
695
Colin Cross1f805522021-05-14 11:10:59 -0700696 val = resolveStrx(uint64(strBase), off)
Patrice Arruda748609c2020-06-25 12:12:21 -0700697
Patrice Arruda748609c2020-06-25 12:12:21 -0700698 case formStrpSup:
699 is64, known := b.format.dwarf64()
700 if !known {
701 b.error("unknown size for DW_FORM_strp_sup")
702 } else if is64 {
703 val = b.uint64()
704 } else {
705 val = b.uint32()
706 }
Brent Austinba3052e2015-04-21 16:08:23 -0700707
708 // lineptr, loclistptr, macptr, rangelistptr
709 // New in DWARF 4, but clang can generate them with -gdwarf-2.
710 // Section reference, replacing use of formData4 and formData8.
711 case formSecOffset, formGnuRefAlt, formGnuStrpAlt:
712 is64, known := b.format.dwarf64()
713 if !known {
714 b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16))
715 } else if is64 {
716 val = int64(b.uint64())
717 } else {
718 val = int64(b.uint32())
719 }
720
721 // exprloc
722 // New in DWARF 4.
723 case formExprloc:
724 val = b.bytes(int(b.uint()))
725
726 // reference
727 // New in DWARF 4.
728 case formRefSig8:
729 // 64-bit type signature.
730 val = b.uint64()
Patrice Arruda748609c2020-06-25 12:12:21 -0700731 case formRefSup4:
732 val = b.uint32()
733 case formRefSup8:
734 val = b.uint64()
735
736 // loclist
737 case formLoclistx:
738 val = b.uint()
739
740 // rnglist
741 case formRnglistx:
Dan Willemsencc753b72021-08-31 13:25:42 -0700742 off := b.uint()
743
744 // We have to adjust by the rnglists_base of
745 // the compilation unit. This won't work if
746 // the program uses Reader.Seek to skip over
747 // the unit. Not much we can do about that.
748 var rnglistsBase int64
749 if cu != nil {
750 rnglistsBase, _ = cu.Val(AttrRnglistsBase).(int64)
751 } else if a.tag == TagCompileUnit {
752 delay = append(delay, delayed{i, off, formRnglistx})
753 break
754 }
755
756 val = resolveRnglistx(uint64(rnglistsBase), off)
Brent Austinba3052e2015-04-21 16:08:23 -0700757 }
Colin Cross1f805522021-05-14 11:10:59 -0700758
Brent Austinba3052e2015-04-21 16:08:23 -0700759 e.Field[i].Val = val
760 }
761 if b.err != nil {
762 return nil
763 }
Colin Cross1f805522021-05-14 11:10:59 -0700764
765 for _, del := range delay {
766 switch del.fmt {
767 case formAddrx:
768 addrBase, _ := e.Val(AttrAddrBase).(int64)
769 val, err := b.dwarf.debugAddr(b.format, uint64(addrBase), del.off)
770 if err != nil {
771 b.err = err
772 return nil
773 }
774 e.Field[del.idx].Val = val
775 case formStrx:
776 strBase, _ := e.Val(AttrStrOffsetsBase).(int64)
777 e.Field[del.idx].Val = resolveStrx(uint64(strBase), del.off)
778 if b.err != nil {
779 return nil
780 }
Dan Willemsencc753b72021-08-31 13:25:42 -0700781 case formRnglistx:
782 rnglistsBase, _ := e.Val(AttrRnglistsBase).(int64)
783 e.Field[del.idx].Val = resolveRnglistx(uint64(rnglistsBase), del.off)
784 if b.err != nil {
785 return nil
786 }
Colin Cross1f805522021-05-14 11:10:59 -0700787 }
788 }
789
Brent Austinba3052e2015-04-21 16:08:23 -0700790 return e
791}
792
793// A Reader allows reading Entry structures from a DWARF ``info'' section.
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700794// The Entry structures are arranged in a tree. The Reader's Next function
Brent Austinba3052e2015-04-21 16:08:23 -0700795// return successive entries from a pre-order traversal of the tree.
796// If an entry has children, its Children field will be true, and the children
797// follow, terminated by an Entry with Tag 0.
798type Reader struct {
799 b buf
800 d *Data
801 err error
802 unit int
Colin Cross1f805522021-05-14 11:10:59 -0700803 lastUnit bool // set if last entry returned by Next is TagCompileUnit/TagPartialUnit
Brent Austinba3052e2015-04-21 16:08:23 -0700804 lastChildren bool // .Children of last entry returned by Next
805 lastSibling Offset // .Val(AttrSibling) of last entry returned by Next
Patrice Arruda748609c2020-06-25 12:12:21 -0700806 cu *Entry // current compilation unit
Brent Austinba3052e2015-04-21 16:08:23 -0700807}
808
809// Reader returns a new Reader for Data.
810// The reader is positioned at byte offset 0 in the DWARF ``info'' section.
811func (d *Data) Reader() *Reader {
812 r := &Reader{d: d}
813 r.Seek(0)
814 return r
815}
816
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700817// AddressSize returns the size in bytes of addresses in the current compilation
818// unit.
819func (r *Reader) AddressSize() int {
820 return r.d.unit[r.unit].asize
821}
822
Patrice Arruda748609c2020-06-25 12:12:21 -0700823// ByteOrder returns the byte order in the current compilation unit.
824func (r *Reader) ByteOrder() binary.ByteOrder {
825 return r.b.order
826}
827
Brent Austinba3052e2015-04-21 16:08:23 -0700828// Seek positions the Reader at offset off in the encoded entry stream.
829// Offset 0 can be used to denote the first entry.
830func (r *Reader) Seek(off Offset) {
831 d := r.d
832 r.err = nil
833 r.lastChildren = false
834 if off == 0 {
835 if len(d.unit) == 0 {
836 return
837 }
838 u := &d.unit[0]
839 r.unit = 0
840 r.b = makeBuf(r.d, u, "info", u.off, u.data)
Patrice Arruda748609c2020-06-25 12:12:21 -0700841 r.cu = nil
Brent Austinba3052e2015-04-21 16:08:23 -0700842 return
843 }
844
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700845 i := d.offsetToUnit(off)
846 if i == -1 {
847 r.err = errors.New("offset out of range")
848 return
Brent Austinba3052e2015-04-21 16:08:23 -0700849 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700850 if i != r.unit {
851 r.cu = nil
852 }
Dan Willemsen09eb3b12015-09-16 14:34:17 -0700853 u := &d.unit[i]
854 r.unit = i
855 r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
Brent Austinba3052e2015-04-21 16:08:23 -0700856}
857
858// maybeNextUnit advances to the next unit if this one is finished.
859func (r *Reader) maybeNextUnit() {
860 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
Colin Cross1f805522021-05-14 11:10:59 -0700861 r.nextUnit()
Brent Austinba3052e2015-04-21 16:08:23 -0700862 }
863}
864
Colin Cross1f805522021-05-14 11:10:59 -0700865// nextUnit advances to the next unit.
866func (r *Reader) nextUnit() {
867 r.unit++
868 u := &r.d.unit[r.unit]
869 r.b = makeBuf(r.d, u, "info", u.off, u.data)
870 r.cu = nil
871}
872
Brent Austinba3052e2015-04-21 16:08:23 -0700873// Next reads the next entry from the encoded entry stream.
874// It returns nil, nil when it reaches the end of the section.
875// It returns an error if the current offset is invalid or the data at the
876// offset cannot be decoded as a valid Entry.
877func (r *Reader) Next() (*Entry, error) {
878 if r.err != nil {
879 return nil, r.err
880 }
881 r.maybeNextUnit()
882 if len(r.b.data) == 0 {
883 return nil, nil
884 }
885 u := &r.d.unit[r.unit]
Patrice Arruda748609c2020-06-25 12:12:21 -0700886 e := r.b.entry(r.cu, u.atable, u.base, u.vers)
Brent Austinba3052e2015-04-21 16:08:23 -0700887 if r.b.err != nil {
888 r.err = r.b.err
889 return nil, r.err
890 }
Colin Cross1f805522021-05-14 11:10:59 -0700891 r.lastUnit = false
Brent Austinba3052e2015-04-21 16:08:23 -0700892 if e != nil {
893 r.lastChildren = e.Children
894 if r.lastChildren {
895 r.lastSibling, _ = e.Val(AttrSibling).(Offset)
896 }
Patrice Arruda748609c2020-06-25 12:12:21 -0700897 if e.Tag == TagCompileUnit || e.Tag == TagPartialUnit {
Colin Cross1f805522021-05-14 11:10:59 -0700898 r.lastUnit = true
Patrice Arruda748609c2020-06-25 12:12:21 -0700899 r.cu = e
900 }
Brent Austinba3052e2015-04-21 16:08:23 -0700901 } else {
902 r.lastChildren = false
903 }
904 return e, nil
905}
906
907// SkipChildren skips over the child entries associated with
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700908// the last Entry returned by Next. If that Entry did not have
Brent Austinba3052e2015-04-21 16:08:23 -0700909// children or Next has not been called, SkipChildren is a no-op.
910func (r *Reader) SkipChildren() {
911 if r.err != nil || !r.lastChildren {
912 return
913 }
914
915 // If the last entry had a sibling attribute,
916 // that attribute gives the offset of the next
917 // sibling, so we can avoid decoding the
918 // child subtrees.
919 if r.lastSibling >= r.b.off {
920 r.Seek(r.lastSibling)
921 return
922 }
923
Colin Cross1f805522021-05-14 11:10:59 -0700924 if r.lastUnit && r.unit+1 < len(r.d.unit) {
925 r.nextUnit()
926 return
927 }
928
Brent Austinba3052e2015-04-21 16:08:23 -0700929 for {
930 e, err := r.Next()
931 if err != nil || e == nil || e.Tag == 0 {
932 break
933 }
934 if e.Children {
935 r.SkipChildren()
936 }
937 }
938}
939
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700940// clone returns a copy of the reader. This is used by the typeReader
Brent Austinba3052e2015-04-21 16:08:23 -0700941// interface.
942func (r *Reader) clone() typeReader {
943 return r.d.Reader()
944}
945
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700946// offset returns the current buffer offset. This is used by the
Brent Austinba3052e2015-04-21 16:08:23 -0700947// typeReader interface.
948func (r *Reader) offset() Offset {
949 return r.b.off
950}
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700951
952// SeekPC returns the Entry for the compilation unit that includes pc,
953// and positions the reader to read the children of that unit. If pc
954// is not covered by any unit, SeekPC returns ErrUnknownPC and the
955// position of the reader is undefined.
956//
957// Because compilation units can describe multiple regions of the
958// executable, in the worst case SeekPC must search through all the
959// ranges in all the compilation units. Each call to SeekPC starts the
960// search at the compilation unit of the last call, so in general
961// looking up a series of PCs will be faster if they are sorted. If
962// the caller wishes to do repeated fast PC lookups, it should build
963// an appropriate index using the Ranges method.
964func (r *Reader) SeekPC(pc uint64) (*Entry, error) {
965 unit := r.unit
966 for i := 0; i < len(r.d.unit); i++ {
967 if unit >= len(r.d.unit) {
968 unit = 0
969 }
970 r.err = nil
971 r.lastChildren = false
972 r.unit = unit
Colin Cross1f805522021-05-14 11:10:59 -0700973 r.cu = nil
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700974 u := &r.d.unit[unit]
975 r.b = makeBuf(r.d, u, "info", u.off, u.data)
976 e, err := r.Next()
977 if err != nil {
978 return nil, err
979 }
980 ranges, err := r.d.Ranges(e)
981 if err != nil {
982 return nil, err
983 }
984 for _, pcs := range ranges {
985 if pcs[0] <= pc && pc < pcs[1] {
986 return e, nil
987 }
988 }
989 unit++
990 }
991 return nil, ErrUnknownPC
992}
993
994// Ranges returns the PC ranges covered by e, a slice of [low,high) pairs.
995// Only some entry types, such as TagCompileUnit or TagSubprogram, have PC
996// ranges; for others, this will return nil with no error.
997func (d *Data) Ranges(e *Entry) ([][2]uint64, error) {
998 var ret [][2]uint64
999
1000 low, lowOK := e.Val(AttrLowpc).(uint64)
1001
1002 var high uint64
1003 var highOK bool
1004 highField := e.AttrField(AttrHighpc)
1005 if highField != nil {
1006 switch highField.Class {
1007 case ClassAddress:
1008 high, highOK = highField.Val.(uint64)
1009 case ClassConstant:
1010 off, ok := highField.Val.(int64)
1011 if ok {
1012 high = low + uint64(off)
1013 highOK = true
1014 }
1015 }
1016 }
1017
1018 if lowOK && highOK {
1019 ret = append(ret, [2]uint64{low, high})
1020 }
1021
Colin Cross1f805522021-05-14 11:10:59 -07001022 var u *unit
1023 if uidx := d.offsetToUnit(e.Offset); uidx >= 0 && uidx < len(d.unit) {
1024 u = &d.unit[uidx]
1025 }
1026
1027 if u != nil && u.vers >= 5 && d.rngLists != nil {
1028 // DWARF version 5 and later
1029 field := e.AttrField(AttrRanges)
1030 if field == nil {
1031 return ret, nil
1032 }
1033 switch field.Class {
1034 case ClassRangeListPtr:
1035 ranges, rangesOK := field.Val.(int64)
1036 if !rangesOK {
1037 return ret, nil
1038 }
1039 cu, base, err := d.baseAddressForEntry(e)
1040 if err != nil {
1041 return nil, err
1042 }
1043 return d.dwarf5Ranges(u, cu, base, ranges, ret)
1044
1045 case ClassRngList:
Dan Willemsencc753b72021-08-31 13:25:42 -07001046 rnglist, ok := field.Val.(uint64)
1047 if !ok {
1048 return ret, nil
1049 }
1050 cu, base, err := d.baseAddressForEntry(e)
1051 if err != nil {
1052 return nil, err
1053 }
1054 return d.dwarf5Ranges(u, cu, base, int64(rnglist), ret)
Colin Cross1f805522021-05-14 11:10:59 -07001055
1056 default:
1057 return ret, nil
1058 }
1059 }
1060
1061 // DWARF version 2 through 4
Dan Willemsen38f2dba2016-07-08 14:54:35 -07001062 ranges, rangesOK := e.Val(AttrRanges).(int64)
1063 if rangesOK && d.ranges != nil {
Colin Cross1f805522021-05-14 11:10:59 -07001064 _, base, err := d.baseAddressForEntry(e)
1065 if err != nil {
1066 return nil, err
1067 }
1068 return d.dwarf2Ranges(u, base, ranges, ret)
1069 }
1070
1071 return ret, nil
1072}
1073
1074// baseAddressForEntry returns the initial base address to be used when
1075// looking up the range list of entry e.
1076// DWARF specifies that this should be the lowpc attribute of the enclosing
1077// compilation unit, however comments in gdb/dwarf2read.c say that some
1078// versions of GCC use the entrypc attribute, so we check that too.
1079func (d *Data) baseAddressForEntry(e *Entry) (*Entry, uint64, error) {
1080 var cu *Entry
1081 if e.Tag == TagCompileUnit {
1082 cu = e
1083 } else {
1084 i := d.offsetToUnit(e.Offset)
1085 if i == -1 {
1086 return nil, 0, errors.New("no unit for entry")
1087 }
1088 u := &d.unit[i]
1089 b := makeBuf(d, u, "info", u.off, u.data)
1090 cu = b.entry(nil, u.atable, u.base, u.vers)
1091 if b.err != nil {
1092 return nil, 0, b.err
1093 }
1094 }
1095
1096 if cuEntry, cuEntryOK := cu.Val(AttrEntrypc).(uint64); cuEntryOK {
1097 return cu, cuEntry, nil
1098 } else if cuLow, cuLowOK := cu.Val(AttrLowpc).(uint64); cuLowOK {
1099 return cu, cuLow, nil
1100 }
1101
1102 return cu, 0, nil
1103}
1104
1105func (d *Data) dwarf2Ranges(u *unit, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) {
1106 buf := makeBuf(d, u, "ranges", Offset(ranges), d.ranges[ranges:])
1107 for len(buf.data) > 0 {
1108 low := buf.addr()
1109 high := buf.addr()
1110
1111 if low == 0 && high == 0 {
1112 break
1113 }
1114
1115 if low == ^uint64(0)>>uint((8-u.addrsize())*8) {
1116 base = high
Dan Willemsen38f2dba2016-07-08 14:54:35 -07001117 } else {
Colin Cross1f805522021-05-14 11:10:59 -07001118 ret = append(ret, [2]uint64{base + low, base + high})
Dan Willemsen38f2dba2016-07-08 14:54:35 -07001119 }
1120 }
1121
1122 return ret, nil
1123}
Colin Cross1f805522021-05-14 11:10:59 -07001124
1125// dwarf5Ranges interpets a debug_rnglists sequence, see DWARFv5 section
1126// 2.17.3 (page 53).
1127func (d *Data) dwarf5Ranges(u *unit, cu *Entry, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) {
1128 var addrBase int64
1129 if cu != nil {
1130 addrBase, _ = cu.Val(AttrAddrBase).(int64)
1131 }
1132
1133 buf := makeBuf(d, u, "rnglists", 0, d.rngLists)
1134 buf.skip(int(ranges))
1135 for {
1136 opcode := buf.uint8()
1137 switch opcode {
1138 case rleEndOfList:
1139 if buf.err != nil {
1140 return nil, buf.err
1141 }
1142 return ret, nil
1143
1144 case rleBaseAddressx:
1145 baseIdx := buf.uint()
1146 var err error
1147 base, err = d.debugAddr(u, uint64(addrBase), baseIdx)
1148 if err != nil {
1149 return nil, err
1150 }
1151
1152 case rleStartxEndx:
1153 startIdx := buf.uint()
1154 endIdx := buf.uint()
1155
1156 start, err := d.debugAddr(u, uint64(addrBase), startIdx)
1157 if err != nil {
1158 return nil, err
1159 }
1160 end, err := d.debugAddr(u, uint64(addrBase), endIdx)
1161 if err != nil {
1162 return nil, err
1163 }
1164 ret = append(ret, [2]uint64{start, end})
1165
1166 case rleStartxLength:
1167 startIdx := buf.uint()
1168 len := buf.uint()
1169 start, err := d.debugAddr(u, uint64(addrBase), startIdx)
1170 if err != nil {
1171 return nil, err
1172 }
1173 ret = append(ret, [2]uint64{start, start + len})
1174
1175 case rleOffsetPair:
1176 off1 := buf.uint()
1177 off2 := buf.uint()
1178 ret = append(ret, [2]uint64{base + off1, base + off2})
1179
1180 case rleBaseAddress:
1181 base = buf.addr()
1182
1183 case rleStartEnd:
1184 start := buf.addr()
1185 end := buf.addr()
1186 ret = append(ret, [2]uint64{start, end})
1187
1188 case rleStartLength:
1189 start := buf.addr()
1190 len := buf.uint()
1191 ret = append(ret, [2]uint64{start, start + len})
1192 }
1193 }
1194}
1195
1196// debugAddr returns the address at idx in debug_addr
1197func (d *Data) debugAddr(format dataFormat, addrBase, idx uint64) (uint64, error) {
1198 off := idx*uint64(format.addrsize()) + addrBase
1199
1200 if uint64(int(off)) != off {
1201 return 0, errors.New("offset out of range")
1202 }
1203
1204 b := makeBuf(d, format, "addr", 0, d.addr)
1205 b.skip(int(off))
1206 val := b.addr()
1207 if b.err != nil {
1208 return 0, b.err
1209 }
1210 return val, nil
1211}