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// 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 ( 14 "encoding/binary" 15 "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 { 27 attr Attr 28 fmt format 29 class Class 30 val int64 // for formImplicitConst 31} 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. 38func (d *Data) parseAbbrev(off uint64, vers int) (abbrevTable, error) { 39 if m, ok := d.abbrevCache[off]; ok { 40 return m, nil 41 } 42 43 data := d.abbrev 44 if off > uint64(len(data)) { 45 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 } 72 if format(fmt) == formImplicitConst { 73 b1.int() 74 } 75 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()) 89 a.field[i].class = formToClass(a.field[i].fmt, a.field[i].attr, vers, &b) 90 if a.field[i].fmt == formImplicitConst { 91 a.field[i].val = b.int() 92 } 93 } 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 106// 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, 148 // The following are new in DWARF 5. 149 AttrStrOffsetsBase: ClassStrOffsetsPtr, 150 AttrAddrBase: ClassAddrPtr, 151 AttrRnglistsBase: ClassRngListsPtr, 152 AttrLoclistsBase: ClassLocListPtr, 153} 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 164 case formIndirect: 165 return ClassUnknown 166 167 case formAddr, formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4: 168 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 182 case formData1, formData2, formData4, formData8, formSdata, formUdata, formData16, formImplicitConst: 183 // 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 196 case formRefAddr, formRef1, formRef2, formRef4, formRef8, formRefUdata, formRefSup4, formRefSup8: 197 return ClassReference 198 199 case formRefSig8: 200 return ClassReferenceSig 201 202 case formString, formStrp, formStrx, formStrpSup, formLineStrp, formStrx1, formStrx2, formStrx3, formStrx4: 203 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 } 212 return ClassUnknown 213 214 case formExprloc: 215 return ClassExprLoc 216 217 case formGnuRefAlt: 218 return ClassReferenceAlt 219 220 case formGnuStrpAlt: 221 return ClassStringAlt 222 223 case formLoclistx: 224 return ClassLocList 225 226 case formRnglistx: 227 return ClassRngList 228 } 229} 230 231// 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. 240// 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 259// 260// For unrecognized or vendor-defined attributes, Class may be 261// ClassUnknown. 262type Field struct { 263 Attr Attr 264 Val interface{} 265 Class Class 266} 267 268// A Class is the DWARF 4 class of an attribute value. 269// 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 ( 285 // ClassUnknown represents values of unknown DWARF class. 286 ClassUnknown Class = iota 287 288 // ClassAddress represents values of type uint64 that are 289 // addresses on the target machine. 290 ClassAddress 291 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 320 // ClassMacPtr represents values that are an int64 offset into 321 // 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 349 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 358 // ClassRngList represents values that are an int64 offset 359 // 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 370) 371 372//go:generate stringer -type=Class 373 374func (i Class) GoString() string { 375 return "dwarf." + i.String() 376} 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: 383// v, ok := e.Val(AttrSibling).(int64) 384// 385func (e *Entry) Val(a Attr) interface{} { 386 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 { 396 if f.Attr == a { 397 return &e.Field[i] 398 } 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. 409func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry { 410 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 } 426 for i := range e.Field { 427 e.Field[i].Attr = a.field[i].attr 428 e.Field[i].Class = a.field[i].class 429 fmt := a.field[i].fmt 430 if fmt == formIndirect { 431 fmt = format(b.uint()) 432 e.Field[i].Class = formToClass(fmt, a.field[i].attr, vers, b) 433 } 434 var val interface{} 435 switch fmt { 436 default: 437 b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16)) 438 439 // address 440 case formAddr: 441 val = b.addr() 442 case formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4: 443 var off uint64 444 switch fmt { 445 case formAddrx: 446 off = b.uint() 447 case formAddrx1: 448 off = uint64(b.uint8()) 449 case formAddrx2: 450 off = uint64(b.uint16()) 451 case formAddrx3: 452 off = uint64(b.uint24()) 453 case formAddrx4: 454 off = uint64(b.uint32()) 455 } 456 if len(b.dwarf.addr) == 0 { 457 b.error("DW_FORM_addrx with no .debug_addr section") 458 } 459 if b.err != nil { 460 return nil 461 } 462 addrsize := b.format.addrsize() 463 if addrsize == 0 { 464 b.error("unknown address size for DW_FORM_addrx") 465 } 466 off *= uint64(addrsize) 467 468 // We have to adjust by the offset of the 469 // compilation unit. This won't work if the 470 // program uses Reader.Seek to skip over the 471 // unit. Not much we can do about that. 472 if cu != nil { 473 cuOff, ok := cu.Val(AttrAddrBase).(int64) 474 if ok { 475 off += uint64(cuOff) 476 } 477 } 478 479 if uint64(int(off)) != off { 480 b.error("DW_FORM_addrx offset out of range") 481 } 482 483 b1 := makeBuf(b.dwarf, b.format, "addr", 0, b.dwarf.addr) 484 b1.skip(int(off)) 485 val = b1.addr() 486 if b1.err != nil { 487 b.err = b1.err 488 return nil 489 } 490 491 // block 492 case formDwarfBlock1: 493 val = b.bytes(int(b.uint8())) 494 case formDwarfBlock2: 495 val = b.bytes(int(b.uint16())) 496 case formDwarfBlock4: 497 val = b.bytes(int(b.uint32())) 498 case formDwarfBlock: 499 val = b.bytes(int(b.uint())) 500 501 // constant 502 case formData1: 503 val = int64(b.uint8()) 504 case formData2: 505 val = int64(b.uint16()) 506 case formData4: 507 val = int64(b.uint32()) 508 case formData8: 509 val = int64(b.uint64()) 510 case formData16: 511 val = b.bytes(16) 512 case formSdata: 513 val = int64(b.int()) 514 case formUdata: 515 val = int64(b.uint()) 516 case formImplicitConst: 517 val = a.field[i].val 518 519 // flag 520 case formFlag: 521 val = b.uint8() == 1 522 // New in DWARF 4. 523 case formFlagPresent: 524 // The attribute is implicitly indicated as present, and no value is 525 // encoded in the debugging information entry itself. 526 val = true 527 528 // reference to other entry 529 case formRefAddr: 530 vers := b.format.version() 531 if vers == 0 { 532 b.error("unknown version for DW_FORM_ref_addr") 533 } else if vers == 2 { 534 val = Offset(b.addr()) 535 } else { 536 is64, known := b.format.dwarf64() 537 if !known { 538 b.error("unknown size for DW_FORM_ref_addr") 539 } else if is64 { 540 val = Offset(b.uint64()) 541 } else { 542 val = Offset(b.uint32()) 543 } 544 } 545 case formRef1: 546 val = Offset(b.uint8()) + ubase 547 case formRef2: 548 val = Offset(b.uint16()) + ubase 549 case formRef4: 550 val = Offset(b.uint32()) + ubase 551 case formRef8: 552 val = Offset(b.uint64()) + ubase 553 case formRefUdata: 554 val = Offset(b.uint()) + ubase 555 556 // string 557 case formString: 558 val = b.string() 559 case formStrp, formLineStrp: 560 var off uint64 // offset into .debug_str 561 is64, known := b.format.dwarf64() 562 if !known { 563 b.error("unknown size for DW_FORM_strp/line_strp") 564 } else if is64 { 565 off = b.uint64() 566 } else { 567 off = uint64(b.uint32()) 568 } 569 if uint64(int(off)) != off { 570 b.error("DW_FORM_strp/line_strp offset out of range") 571 } 572 if b.err != nil { 573 return nil 574 } 575 var b1 buf 576 if fmt == formStrp { 577 b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str) 578 } else { 579 if len(b.dwarf.lineStr) == 0 { 580 b.error("DW_FORM_line_strp with no .debug_line_str section") 581 } 582 b1 = makeBuf(b.dwarf, b.format, "line_str", 0, b.dwarf.lineStr) 583 } 584 b1.skip(int(off)) 585 val = b1.string() 586 if b1.err != nil { 587 b.err = b1.err 588 return nil 589 } 590 case formStrx, formStrx1, formStrx2, formStrx3, formStrx4: 591 var off uint64 592 switch fmt { 593 case formStrx: 594 off = b.uint() 595 case formStrx1: 596 off = uint64(b.uint8()) 597 case formStrx2: 598 off = uint64(b.uint16()) 599 case formStrx3: 600 off = uint64(b.uint24()) 601 case formStrx4: 602 off = uint64(b.uint32()) 603 } 604 if len(b.dwarf.strOffsets) == 0 { 605 b.error("DW_FORM_strx with no .debug_str_offsets section") 606 } 607 is64, known := b.format.dwarf64() 608 if !known { 609 b.error("unknown offset size for DW_FORM_strx") 610 } 611 if b.err != nil { 612 return nil 613 } 614 if is64 { 615 off *= 8 616 } else { 617 off *= 4 618 } 619 620 // We have to adjust by the offset of the 621 // compilation unit. This won't work if the 622 // program uses Reader.Seek to skip over the 623 // unit. Not much we can do about that. 624 if cu != nil { 625 cuOff, ok := cu.Val(AttrStrOffsetsBase).(int64) 626 if ok { 627 off += uint64(cuOff) 628 } 629 } 630 631 if uint64(int(off)) != off { 632 b.error("DW_FORM_strx offset out of range") 633 } 634 635 b1 := makeBuf(b.dwarf, b.format, "str_offsets", 0, b.dwarf.strOffsets) 636 b1.skip(int(off)) 637 if is64 { 638 off = b1.uint64() 639 } else { 640 off = uint64(b1.uint32()) 641 } 642 if b1.err != nil { 643 b.err = b1.err 644 return nil 645 } 646 if uint64(int(off)) != off { 647 b.error("DW_FORM_strx indirect offset out of range") 648 } 649 b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str) 650 b1.skip(int(off)) 651 val = b1.string() 652 if b1.err != nil { 653 b.err = b1.err 654 return nil 655 } 656 case formStrpSup: 657 is64, known := b.format.dwarf64() 658 if !known { 659 b.error("unknown size for DW_FORM_strp_sup") 660 } else if is64 { 661 val = b.uint64() 662 } else { 663 val = b.uint32() 664 } 665 666 // lineptr, loclistptr, macptr, rangelistptr 667 // New in DWARF 4, but clang can generate them with -gdwarf-2. 668 // Section reference, replacing use of formData4 and formData8. 669 case formSecOffset, formGnuRefAlt, formGnuStrpAlt: 670 is64, known := b.format.dwarf64() 671 if !known { 672 b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16)) 673 } else if is64 { 674 val = int64(b.uint64()) 675 } else { 676 val = int64(b.uint32()) 677 } 678 679 // exprloc 680 // New in DWARF 4. 681 case formExprloc: 682 val = b.bytes(int(b.uint())) 683 684 // reference 685 // New in DWARF 4. 686 case formRefSig8: 687 // 64-bit type signature. 688 val = b.uint64() 689 case formRefSup4: 690 val = b.uint32() 691 case formRefSup8: 692 val = b.uint64() 693 694 // loclist 695 case formLoclistx: 696 val = b.uint() 697 698 // rnglist 699 case formRnglistx: 700 val = b.uint() 701 } 702 e.Field[i].Val = val 703 } 704 if b.err != nil { 705 return nil 706 } 707 return e 708} 709 710// A Reader allows reading Entry structures from a DWARF ``info'' section. 711// The Entry structures are arranged in a tree. The Reader's Next function 712// return successive entries from a pre-order traversal of the tree. 713// If an entry has children, its Children field will be true, and the children 714// follow, terminated by an Entry with Tag 0. 715type Reader struct { 716 b buf 717 d *Data 718 err error 719 unit int 720 lastChildren bool // .Children of last entry returned by Next 721 lastSibling Offset // .Val(AttrSibling) of last entry returned by Next 722 cu *Entry // current compilation unit 723} 724 725// Reader returns a new Reader for Data. 726// The reader is positioned at byte offset 0 in the DWARF ``info'' section. 727func (d *Data) Reader() *Reader { 728 r := &Reader{d: d} 729 r.Seek(0) 730 return r 731} 732 733// AddressSize returns the size in bytes of addresses in the current compilation 734// unit. 735func (r *Reader) AddressSize() int { 736 return r.d.unit[r.unit].asize 737} 738 739// ByteOrder returns the byte order in the current compilation unit. 740func (r *Reader) ByteOrder() binary.ByteOrder { 741 return r.b.order 742} 743 744// Seek positions the Reader at offset off in the encoded entry stream. 745// Offset 0 can be used to denote the first entry. 746func (r *Reader) Seek(off Offset) { 747 d := r.d 748 r.err = nil 749 r.lastChildren = false 750 if off == 0 { 751 if len(d.unit) == 0 { 752 return 753 } 754 u := &d.unit[0] 755 r.unit = 0 756 r.b = makeBuf(r.d, u, "info", u.off, u.data) 757 r.cu = nil 758 return 759 } 760 761 i := d.offsetToUnit(off) 762 if i == -1 { 763 r.err = errors.New("offset out of range") 764 return 765 } 766 if i != r.unit { 767 r.cu = nil 768 } 769 u := &d.unit[i] 770 r.unit = i 771 r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:]) 772} 773 774// maybeNextUnit advances to the next unit if this one is finished. 775func (r *Reader) maybeNextUnit() { 776 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { 777 r.unit++ 778 u := &r.d.unit[r.unit] 779 r.b = makeBuf(r.d, u, "info", u.off, u.data) 780 r.cu = nil 781 } 782} 783 784// Next reads the next entry from the encoded entry stream. 785// It returns nil, nil when it reaches the end of the section. 786// It returns an error if the current offset is invalid or the data at the 787// offset cannot be decoded as a valid Entry. 788func (r *Reader) Next() (*Entry, error) { 789 if r.err != nil { 790 return nil, r.err 791 } 792 r.maybeNextUnit() 793 if len(r.b.data) == 0 { 794 return nil, nil 795 } 796 u := &r.d.unit[r.unit] 797 e := r.b.entry(r.cu, u.atable, u.base, u.vers) 798 if r.b.err != nil { 799 r.err = r.b.err 800 return nil, r.err 801 } 802 if e != nil { 803 r.lastChildren = e.Children 804 if r.lastChildren { 805 r.lastSibling, _ = e.Val(AttrSibling).(Offset) 806 } 807 if e.Tag == TagCompileUnit || e.Tag == TagPartialUnit { 808 r.cu = e 809 } 810 } else { 811 r.lastChildren = false 812 } 813 return e, nil 814} 815 816// SkipChildren skips over the child entries associated with 817// the last Entry returned by Next. If that Entry did not have 818// children or Next has not been called, SkipChildren is a no-op. 819func (r *Reader) SkipChildren() { 820 if r.err != nil || !r.lastChildren { 821 return 822 } 823 824 // If the last entry had a sibling attribute, 825 // that attribute gives the offset of the next 826 // sibling, so we can avoid decoding the 827 // child subtrees. 828 if r.lastSibling >= r.b.off { 829 r.Seek(r.lastSibling) 830 return 831 } 832 833 for { 834 e, err := r.Next() 835 if err != nil || e == nil || e.Tag == 0 { 836 break 837 } 838 if e.Children { 839 r.SkipChildren() 840 } 841 } 842} 843 844// clone returns a copy of the reader. This is used by the typeReader 845// interface. 846func (r *Reader) clone() typeReader { 847 return r.d.Reader() 848} 849 850// offset returns the current buffer offset. This is used by the 851// typeReader interface. 852func (r *Reader) offset() Offset { 853 return r.b.off 854} 855 856// SeekPC returns the Entry for the compilation unit that includes pc, 857// and positions the reader to read the children of that unit. If pc 858// is not covered by any unit, SeekPC returns ErrUnknownPC and the 859// position of the reader is undefined. 860// 861// Because compilation units can describe multiple regions of the 862// executable, in the worst case SeekPC must search through all the 863// ranges in all the compilation units. Each call to SeekPC starts the 864// search at the compilation unit of the last call, so in general 865// looking up a series of PCs will be faster if they are sorted. If 866// the caller wishes to do repeated fast PC lookups, it should build 867// an appropriate index using the Ranges method. 868func (r *Reader) SeekPC(pc uint64) (*Entry, error) { 869 unit := r.unit 870 for i := 0; i < len(r.d.unit); i++ { 871 if unit >= len(r.d.unit) { 872 unit = 0 873 } 874 r.err = nil 875 r.lastChildren = false 876 r.unit = unit 877 u := &r.d.unit[unit] 878 r.b = makeBuf(r.d, u, "info", u.off, u.data) 879 e, err := r.Next() 880 if err != nil { 881 return nil, err 882 } 883 ranges, err := r.d.Ranges(e) 884 if err != nil { 885 return nil, err 886 } 887 for _, pcs := range ranges { 888 if pcs[0] <= pc && pc < pcs[1] { 889 return e, nil 890 } 891 } 892 unit++ 893 } 894 return nil, ErrUnknownPC 895} 896 897// Ranges returns the PC ranges covered by e, a slice of [low,high) pairs. 898// Only some entry types, such as TagCompileUnit or TagSubprogram, have PC 899// ranges; for others, this will return nil with no error. 900func (d *Data) Ranges(e *Entry) ([][2]uint64, error) { 901 var ret [][2]uint64 902 903 low, lowOK := e.Val(AttrLowpc).(uint64) 904 905 var high uint64 906 var highOK bool 907 highField := e.AttrField(AttrHighpc) 908 if highField != nil { 909 switch highField.Class { 910 case ClassAddress: 911 high, highOK = highField.Val.(uint64) 912 case ClassConstant: 913 off, ok := highField.Val.(int64) 914 if ok { 915 high = low + uint64(off) 916 highOK = true 917 } 918 } 919 } 920 921 if lowOK && highOK { 922 ret = append(ret, [2]uint64{low, high}) 923 } 924 925 ranges, rangesOK := e.Val(AttrRanges).(int64) 926 if rangesOK && d.ranges != nil { 927 // The initial base address is the lowpc attribute 928 // of the enclosing compilation unit. 929 // Although DWARF specifies the lowpc attribute, 930 // comments in gdb/dwarf2read.c say that some versions 931 // of GCC use the entrypc attribute, so we check that too. 932 var cu *Entry 933 if e.Tag == TagCompileUnit { 934 cu = e 935 } else { 936 i := d.offsetToUnit(e.Offset) 937 if i == -1 { 938 return nil, errors.New("no unit for entry") 939 } 940 u := &d.unit[i] 941 b := makeBuf(d, u, "info", u.off, u.data) 942 cu = b.entry(nil, u.atable, u.base, u.vers) 943 if b.err != nil { 944 return nil, b.err 945 } 946 } 947 948 var base uint64 949 if cuEntry, cuEntryOK := cu.Val(AttrEntrypc).(uint64); cuEntryOK { 950 base = cuEntry 951 } else if cuLow, cuLowOK := cu.Val(AttrLowpc).(uint64); cuLowOK { 952 base = cuLow 953 } 954 955 u := &d.unit[d.offsetToUnit(e.Offset)] 956 buf := makeBuf(d, u, "ranges", Offset(ranges), d.ranges[ranges:]) 957 for len(buf.data) > 0 { 958 low = buf.addr() 959 high = buf.addr() 960 961 if low == 0 && high == 0 { 962 break 963 } 964 965 if low == ^uint64(0)>>uint((8-u.addrsize())*8) { 966 base = high 967 } else { 968 ret = append(ret, [2]uint64{base + low, base + high}) 969 } 970 } 971 } 972 973 return ret, nil 974} 975