github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/debug/dwarf/entry.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 // 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 11 package dwarf 12 13 import ( 14 "encoding/binary" 15 "errors" 16 "strconv" 17 ) 18 19 // a single entry's description: a sequence of attributes 20 type abbrev struct { 21 tag Tag 22 children bool 23 field []afield 24 } 25 26 type 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 34 type abbrevTable map[uint32]abbrev 35 36 // ParseAbbrev returns the abbreviation table that starts at byte off 37 // in the .debug_abbrev section. 38 func (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. 109 var 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. 134 var 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. 158 func 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. 232 type 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. 262 type 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. 282 type Class int 283 284 const ( 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 374 func (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 // 385 func (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. 394 func (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.) 405 type Offset uint32 406 407 // Entry reads a single entry from buf, decoding 408 // according to the given abbreviation table. 409 func (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 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 467 for i := range e.Field { 468 e.Field[i].Attr = a.field[i].attr 469 e.Field[i].Class = a.field[i].class 470 fmt := a.field[i].fmt 471 if fmt == formIndirect { 472 fmt = format(b.uint()) 473 e.Field[i].Class = formToClass(fmt, a.field[i].attr, vers, b) 474 } 475 var val interface{} 476 switch fmt { 477 default: 478 b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16)) 479 480 // address 481 case formAddr: 482 val = b.addr() 483 case formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4: 484 var off uint64 485 switch fmt { 486 case formAddrx: 487 off = b.uint() 488 case formAddrx1: 489 off = uint64(b.uint8()) 490 case formAddrx2: 491 off = uint64(b.uint16()) 492 case formAddrx3: 493 off = uint64(b.uint24()) 494 case formAddrx4: 495 off = uint64(b.uint32()) 496 } 497 if b.dwarf.addr == nil { 498 b.error("DW_FORM_addrx with no .debug_addr section") 499 } 500 if b.err != nil { 501 return nil 502 } 503 504 // We have to adjust by the offset of the 505 // compilation unit. This won't work if the 506 // program uses Reader.Seek to skip over the 507 // unit. Not much we can do about that. 508 var addrBase int64 509 if cu != nil { 510 addrBase, _ = cu.Val(AttrAddrBase).(int64) 511 } else if a.tag == TagCompileUnit { 512 delay = append(delay, delayed{i, off, formAddrx}) 513 break 514 } 515 516 var err error 517 val, err = b.dwarf.debugAddr(b.format, uint64(addrBase), off) 518 if err != nil { 519 if b.err == nil { 520 b.err = err 521 } 522 return nil 523 } 524 525 // block 526 case formDwarfBlock1: 527 val = b.bytes(int(b.uint8())) 528 case formDwarfBlock2: 529 val = b.bytes(int(b.uint16())) 530 case formDwarfBlock4: 531 val = b.bytes(int(b.uint32())) 532 case formDwarfBlock: 533 val = b.bytes(int(b.uint())) 534 535 // constant 536 case formData1: 537 val = int64(b.uint8()) 538 case formData2: 539 val = int64(b.uint16()) 540 case formData4: 541 val = int64(b.uint32()) 542 case formData8: 543 val = int64(b.uint64()) 544 case formData16: 545 val = b.bytes(16) 546 case formSdata: 547 val = int64(b.int()) 548 case formUdata: 549 val = int64(b.uint()) 550 case formImplicitConst: 551 val = a.field[i].val 552 553 // flag 554 case formFlag: 555 val = b.uint8() == 1 556 // New in DWARF 4. 557 case formFlagPresent: 558 // The attribute is implicitly indicated as present, and no value is 559 // encoded in the debugging information entry itself. 560 val = true 561 562 // reference to other entry 563 case formRefAddr: 564 vers := b.format.version() 565 if vers == 0 { 566 b.error("unknown version for DW_FORM_ref_addr") 567 } else if vers == 2 { 568 val = Offset(b.addr()) 569 } else { 570 is64, known := b.format.dwarf64() 571 if !known { 572 b.error("unknown size for DW_FORM_ref_addr") 573 } else if is64 { 574 val = Offset(b.uint64()) 575 } else { 576 val = Offset(b.uint32()) 577 } 578 } 579 case formRef1: 580 val = Offset(b.uint8()) + ubase 581 case formRef2: 582 val = Offset(b.uint16()) + ubase 583 case formRef4: 584 val = Offset(b.uint32()) + ubase 585 case formRef8: 586 val = Offset(b.uint64()) + ubase 587 case formRefUdata: 588 val = Offset(b.uint()) + ubase 589 590 // string 591 case formString: 592 val = b.string() 593 case formStrp, formLineStrp: 594 var off uint64 // offset into .debug_str 595 is64, known := b.format.dwarf64() 596 if !known { 597 b.error("unknown size for DW_FORM_strp/line_strp") 598 } else if is64 { 599 off = b.uint64() 600 } else { 601 off = uint64(b.uint32()) 602 } 603 if uint64(int(off)) != off { 604 b.error("DW_FORM_strp/line_strp offset out of range") 605 } 606 if b.err != nil { 607 return nil 608 } 609 var b1 buf 610 if fmt == formStrp { 611 b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str) 612 } else { 613 if len(b.dwarf.lineStr) == 0 { 614 b.error("DW_FORM_line_strp with no .debug_line_str section") 615 } 616 b1 = makeBuf(b.dwarf, b.format, "line_str", 0, b.dwarf.lineStr) 617 } 618 b1.skip(int(off)) 619 val = b1.string() 620 if b1.err != nil { 621 b.err = b1.err 622 return nil 623 } 624 case formStrx, formStrx1, formStrx2, formStrx3, formStrx4: 625 var off uint64 626 switch fmt { 627 case formStrx: 628 off = b.uint() 629 case formStrx1: 630 off = uint64(b.uint8()) 631 case formStrx2: 632 off = uint64(b.uint16()) 633 case formStrx3: 634 off = uint64(b.uint24()) 635 case formStrx4: 636 off = uint64(b.uint32()) 637 } 638 if len(b.dwarf.strOffsets) == 0 { 639 b.error("DW_FORM_strx with no .debug_str_offsets section") 640 } 641 is64, known := b.format.dwarf64() 642 if !known { 643 b.error("unknown offset size for DW_FORM_strx") 644 } 645 if b.err != nil { 646 return nil 647 } 648 if is64 { 649 off *= 8 650 } else { 651 off *= 4 652 } 653 654 // We have to adjust by the offset of the 655 // compilation unit. This won't work if the 656 // program uses Reader.Seek to skip over the 657 // unit. Not much we can do about that. 658 var strBase int64 659 if cu != nil { 660 strBase, _ = cu.Val(AttrStrOffsetsBase).(int64) 661 } else if a.tag == TagCompileUnit { 662 delay = append(delay, delayed{i, off, formStrx}) 663 break 664 } 665 666 val = resolveStrx(uint64(strBase), off) 667 668 case formStrpSup: 669 is64, known := b.format.dwarf64() 670 if !known { 671 b.error("unknown size for DW_FORM_strp_sup") 672 } else if is64 { 673 val = b.uint64() 674 } else { 675 val = b.uint32() 676 } 677 678 // lineptr, loclistptr, macptr, rangelistptr 679 // New in DWARF 4, but clang can generate them with -gdwarf-2. 680 // Section reference, replacing use of formData4 and formData8. 681 case formSecOffset, formGnuRefAlt, formGnuStrpAlt: 682 is64, known := b.format.dwarf64() 683 if !known { 684 b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16)) 685 } else if is64 { 686 val = int64(b.uint64()) 687 } else { 688 val = int64(b.uint32()) 689 } 690 691 // exprloc 692 // New in DWARF 4. 693 case formExprloc: 694 val = b.bytes(int(b.uint())) 695 696 // reference 697 // New in DWARF 4. 698 case formRefSig8: 699 // 64-bit type signature. 700 val = b.uint64() 701 case formRefSup4: 702 val = b.uint32() 703 case formRefSup8: 704 val = b.uint64() 705 706 // loclist 707 case formLoclistx: 708 val = b.uint() 709 710 // rnglist 711 case formRnglistx: 712 val = b.uint() 713 } 714 715 e.Field[i].Val = val 716 } 717 if b.err != nil { 718 return nil 719 } 720 721 for _, del := range delay { 722 switch del.fmt { 723 case formAddrx: 724 addrBase, _ := e.Val(AttrAddrBase).(int64) 725 val, err := b.dwarf.debugAddr(b.format, uint64(addrBase), del.off) 726 if err != nil { 727 b.err = err 728 return nil 729 } 730 e.Field[del.idx].Val = val 731 case formStrx: 732 strBase, _ := e.Val(AttrStrOffsetsBase).(int64) 733 e.Field[del.idx].Val = resolveStrx(uint64(strBase), del.off) 734 if b.err != nil { 735 return nil 736 } 737 } 738 } 739 740 return e 741 } 742 743 // A Reader allows reading Entry structures from a DWARF ``info'' section. 744 // The Entry structures are arranged in a tree. The Reader's Next function 745 // return successive entries from a pre-order traversal of the tree. 746 // If an entry has children, its Children field will be true, and the children 747 // follow, terminated by an Entry with Tag 0. 748 type Reader struct { 749 b buf 750 d *Data 751 err error 752 unit int 753 lastUnit bool // set if last entry returned by Next is TagCompileUnit/TagPartialUnit 754 lastChildren bool // .Children of last entry returned by Next 755 lastSibling Offset // .Val(AttrSibling) of last entry returned by Next 756 cu *Entry // current compilation unit 757 } 758 759 // Reader returns a new Reader for Data. 760 // The reader is positioned at byte offset 0 in the DWARF ``info'' section. 761 func (d *Data) Reader() *Reader { 762 r := &Reader{d: d} 763 r.Seek(0) 764 return r 765 } 766 767 // AddressSize returns the size in bytes of addresses in the current compilation 768 // unit. 769 func (r *Reader) AddressSize() int { 770 return r.d.unit[r.unit].asize 771 } 772 773 // ByteOrder returns the byte order in the current compilation unit. 774 func (r *Reader) ByteOrder() binary.ByteOrder { 775 return r.b.order 776 } 777 778 // Seek positions the Reader at offset off in the encoded entry stream. 779 // Offset 0 can be used to denote the first entry. 780 func (r *Reader) Seek(off Offset) { 781 d := r.d 782 r.err = nil 783 r.lastChildren = false 784 if off == 0 { 785 if len(d.unit) == 0 { 786 return 787 } 788 u := &d.unit[0] 789 r.unit = 0 790 r.b = makeBuf(r.d, u, "info", u.off, u.data) 791 r.cu = nil 792 return 793 } 794 795 i := d.offsetToUnit(off) 796 if i == -1 { 797 r.err = errors.New("offset out of range") 798 return 799 } 800 if i != r.unit { 801 r.cu = nil 802 } 803 u := &d.unit[i] 804 r.unit = i 805 r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:]) 806 } 807 808 // maybeNextUnit advances to the next unit if this one is finished. 809 func (r *Reader) maybeNextUnit() { 810 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { 811 r.nextUnit() 812 } 813 } 814 815 // nextUnit advances to the next unit. 816 func (r *Reader) nextUnit() { 817 r.unit++ 818 u := &r.d.unit[r.unit] 819 r.b = makeBuf(r.d, u, "info", u.off, u.data) 820 r.cu = nil 821 } 822 823 // Next reads the next entry from the encoded entry stream. 824 // It returns nil, nil when it reaches the end of the section. 825 // It returns an error if the current offset is invalid or the data at the 826 // offset cannot be decoded as a valid Entry. 827 func (r *Reader) Next() (*Entry, error) { 828 if r.err != nil { 829 return nil, r.err 830 } 831 r.maybeNextUnit() 832 if len(r.b.data) == 0 { 833 return nil, nil 834 } 835 u := &r.d.unit[r.unit] 836 e := r.b.entry(r.cu, u.atable, u.base, u.vers) 837 if r.b.err != nil { 838 r.err = r.b.err 839 return nil, r.err 840 } 841 r.lastUnit = false 842 if e != nil { 843 r.lastChildren = e.Children 844 if r.lastChildren { 845 r.lastSibling, _ = e.Val(AttrSibling).(Offset) 846 } 847 if e.Tag == TagCompileUnit || e.Tag == TagPartialUnit { 848 r.lastUnit = true 849 r.cu = e 850 } 851 } else { 852 r.lastChildren = false 853 } 854 return e, nil 855 } 856 857 // SkipChildren skips over the child entries associated with 858 // the last Entry returned by Next. If that Entry did not have 859 // children or Next has not been called, SkipChildren is a no-op. 860 func (r *Reader) SkipChildren() { 861 if r.err != nil || !r.lastChildren { 862 return 863 } 864 865 // If the last entry had a sibling attribute, 866 // that attribute gives the offset of the next 867 // sibling, so we can avoid decoding the 868 // child subtrees. 869 if r.lastSibling >= r.b.off { 870 r.Seek(r.lastSibling) 871 return 872 } 873 874 if r.lastUnit && r.unit+1 < len(r.d.unit) { 875 r.nextUnit() 876 return 877 } 878 879 for { 880 e, err := r.Next() 881 if err != nil || e == nil || e.Tag == 0 { 882 break 883 } 884 if e.Children { 885 r.SkipChildren() 886 } 887 } 888 } 889 890 // clone returns a copy of the reader. This is used by the typeReader 891 // interface. 892 func (r *Reader) clone() typeReader { 893 return r.d.Reader() 894 } 895 896 // offset returns the current buffer offset. This is used by the 897 // typeReader interface. 898 func (r *Reader) offset() Offset { 899 return r.b.off 900 } 901 902 // SeekPC returns the Entry for the compilation unit that includes pc, 903 // and positions the reader to read the children of that unit. If pc 904 // is not covered by any unit, SeekPC returns ErrUnknownPC and the 905 // position of the reader is undefined. 906 // 907 // Because compilation units can describe multiple regions of the 908 // executable, in the worst case SeekPC must search through all the 909 // ranges in all the compilation units. Each call to SeekPC starts the 910 // search at the compilation unit of the last call, so in general 911 // looking up a series of PCs will be faster if they are sorted. If 912 // the caller wishes to do repeated fast PC lookups, it should build 913 // an appropriate index using the Ranges method. 914 func (r *Reader) SeekPC(pc uint64) (*Entry, error) { 915 unit := r.unit 916 for i := 0; i < len(r.d.unit); i++ { 917 if unit >= len(r.d.unit) { 918 unit = 0 919 } 920 r.err = nil 921 r.lastChildren = false 922 r.unit = unit 923 r.cu = nil 924 u := &r.d.unit[unit] 925 r.b = makeBuf(r.d, u, "info", u.off, u.data) 926 e, err := r.Next() 927 if err != nil { 928 return nil, err 929 } 930 ranges, err := r.d.Ranges(e) 931 if err != nil { 932 return nil, err 933 } 934 for _, pcs := range ranges { 935 if pcs[0] <= pc && pc < pcs[1] { 936 return e, nil 937 } 938 } 939 unit++ 940 } 941 return nil, ErrUnknownPC 942 } 943 944 // Ranges returns the PC ranges covered by e, a slice of [low,high) pairs. 945 // Only some entry types, such as TagCompileUnit or TagSubprogram, have PC 946 // ranges; for others, this will return nil with no error. 947 func (d *Data) Ranges(e *Entry) ([][2]uint64, error) { 948 var ret [][2]uint64 949 950 low, lowOK := e.Val(AttrLowpc).(uint64) 951 952 var high uint64 953 var highOK bool 954 highField := e.AttrField(AttrHighpc) 955 if highField != nil { 956 switch highField.Class { 957 case ClassAddress: 958 high, highOK = highField.Val.(uint64) 959 case ClassConstant: 960 off, ok := highField.Val.(int64) 961 if ok { 962 high = low + uint64(off) 963 highOK = true 964 } 965 } 966 } 967 968 if lowOK && highOK { 969 ret = append(ret, [2]uint64{low, high}) 970 } 971 972 var u *unit 973 if uidx := d.offsetToUnit(e.Offset); uidx >= 0 && uidx < len(d.unit) { 974 u = &d.unit[uidx] 975 } 976 977 if u != nil && u.vers >= 5 && d.rngLists != nil { 978 // DWARF version 5 and later 979 field := e.AttrField(AttrRanges) 980 if field == nil { 981 return ret, nil 982 } 983 switch field.Class { 984 case ClassRangeListPtr: 985 ranges, rangesOK := field.Val.(int64) 986 if !rangesOK { 987 return ret, nil 988 } 989 cu, base, err := d.baseAddressForEntry(e) 990 if err != nil { 991 return nil, err 992 } 993 return d.dwarf5Ranges(u, cu, base, ranges, ret) 994 995 case ClassRngList: 996 // TODO: support DW_FORM_rnglistx 997 return ret, nil 998 999 default: 1000 return ret, nil 1001 } 1002 } 1003 1004 // DWARF version 2 through 4 1005 ranges, rangesOK := e.Val(AttrRanges).(int64) 1006 if rangesOK && d.ranges != nil { 1007 _, base, err := d.baseAddressForEntry(e) 1008 if err != nil { 1009 return nil, err 1010 } 1011 return d.dwarf2Ranges(u, base, ranges, ret) 1012 } 1013 1014 return ret, nil 1015 } 1016 1017 // baseAddressForEntry returns the initial base address to be used when 1018 // looking up the range list of entry e. 1019 // DWARF specifies that this should be the lowpc attribute of the enclosing 1020 // compilation unit, however comments in gdb/dwarf2read.c say that some 1021 // versions of GCC use the entrypc attribute, so we check that too. 1022 func (d *Data) baseAddressForEntry(e *Entry) (*Entry, uint64, error) { 1023 var cu *Entry 1024 if e.Tag == TagCompileUnit { 1025 cu = e 1026 } else { 1027 i := d.offsetToUnit(e.Offset) 1028 if i == -1 { 1029 return nil, 0, errors.New("no unit for entry") 1030 } 1031 u := &d.unit[i] 1032 b := makeBuf(d, u, "info", u.off, u.data) 1033 cu = b.entry(nil, u.atable, u.base, u.vers) 1034 if b.err != nil { 1035 return nil, 0, b.err 1036 } 1037 } 1038 1039 if cuEntry, cuEntryOK := cu.Val(AttrEntrypc).(uint64); cuEntryOK { 1040 return cu, cuEntry, nil 1041 } else if cuLow, cuLowOK := cu.Val(AttrLowpc).(uint64); cuLowOK { 1042 return cu, cuLow, nil 1043 } 1044 1045 return cu, 0, nil 1046 } 1047 1048 func (d *Data) dwarf2Ranges(u *unit, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) { 1049 buf := makeBuf(d, u, "ranges", Offset(ranges), d.ranges[ranges:]) 1050 for len(buf.data) > 0 { 1051 low := buf.addr() 1052 high := buf.addr() 1053 1054 if low == 0 && high == 0 { 1055 break 1056 } 1057 1058 if low == ^uint64(0)>>uint((8-u.addrsize())*8) { 1059 base = high 1060 } else { 1061 ret = append(ret, [2]uint64{base + low, base + high}) 1062 } 1063 } 1064 1065 return ret, nil 1066 } 1067 1068 // dwarf5Ranges interpets a debug_rnglists sequence, see DWARFv5 section 1069 // 2.17.3 (page 53). 1070 func (d *Data) dwarf5Ranges(u *unit, cu *Entry, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) { 1071 var addrBase int64 1072 if cu != nil { 1073 addrBase, _ = cu.Val(AttrAddrBase).(int64) 1074 } 1075 1076 buf := makeBuf(d, u, "rnglists", 0, d.rngLists) 1077 buf.skip(int(ranges)) 1078 for { 1079 opcode := buf.uint8() 1080 switch opcode { 1081 case rleEndOfList: 1082 if buf.err != nil { 1083 return nil, buf.err 1084 } 1085 return ret, nil 1086 1087 case rleBaseAddressx: 1088 baseIdx := buf.uint() 1089 var err error 1090 base, err = d.debugAddr(u, uint64(addrBase), baseIdx) 1091 if err != nil { 1092 return nil, err 1093 } 1094 1095 case rleStartxEndx: 1096 startIdx := buf.uint() 1097 endIdx := buf.uint() 1098 1099 start, err := d.debugAddr(u, uint64(addrBase), startIdx) 1100 if err != nil { 1101 return nil, err 1102 } 1103 end, err := d.debugAddr(u, uint64(addrBase), endIdx) 1104 if err != nil { 1105 return nil, err 1106 } 1107 ret = append(ret, [2]uint64{start, end}) 1108 1109 case rleStartxLength: 1110 startIdx := buf.uint() 1111 len := buf.uint() 1112 start, err := d.debugAddr(u, uint64(addrBase), startIdx) 1113 if err != nil { 1114 return nil, err 1115 } 1116 ret = append(ret, [2]uint64{start, start + len}) 1117 1118 case rleOffsetPair: 1119 off1 := buf.uint() 1120 off2 := buf.uint() 1121 ret = append(ret, [2]uint64{base + off1, base + off2}) 1122 1123 case rleBaseAddress: 1124 base = buf.addr() 1125 1126 case rleStartEnd: 1127 start := buf.addr() 1128 end := buf.addr() 1129 ret = append(ret, [2]uint64{start, end}) 1130 1131 case rleStartLength: 1132 start := buf.addr() 1133 len := buf.uint() 1134 ret = append(ret, [2]uint64{start, start + len}) 1135 } 1136 } 1137 } 1138 1139 // debugAddr returns the address at idx in debug_addr 1140 func (d *Data) debugAddr(format dataFormat, addrBase, idx uint64) (uint64, error) { 1141 off := idx*uint64(format.addrsize()) + addrBase 1142 1143 if uint64(int(off)) != off { 1144 return 0, errors.New("offset out of range") 1145 } 1146 1147 b := makeBuf(d, format, "addr", 0, d.addr) 1148 b.skip(int(off)) 1149 val := b.addr() 1150 if b.err != nil { 1151 return 0, b.err 1152 } 1153 return val, nil 1154 }