github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/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 // ClassRangeListPtr 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 a uint64 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 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 496 for i := range e.Field { 497 e.Field[i].Attr = a.field[i].attr 498 e.Field[i].Class = a.field[i].class 499 fmt := a.field[i].fmt 500 if fmt == formIndirect { 501 fmt = format(b.uint()) 502 e.Field[i].Class = formToClass(fmt, a.field[i].attr, vers, b) 503 } 504 var val interface{} 505 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() 512 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 } 526 if b.dwarf.addr == nil { 527 b.error("DW_FORM_addrx with no .debug_addr section") 528 } 529 if b.err != nil { 530 return nil 531 } 532 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. 537 var addrBase int64 538 if cu != nil { 539 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 550 } 551 return nil 552 } 553 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()) 573 case formData16: 574 val = b.bytes(16) 575 case formSdata: 576 val = int64(b.int()) 577 case formUdata: 578 val = int64(b.uint()) 579 case formImplicitConst: 580 val = a.field[i].val 581 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() 622 case formStrp, formLineStrp: 623 var off uint64 // offset into .debug_str 624 is64, known := b.format.dwarf64() 625 if !known { 626 b.error("unknown size for DW_FORM_strp/line_strp") 627 } else if is64 { 628 off = b.uint64() 629 } else { 630 off = uint64(b.uint32()) 631 } 632 if uint64(int(off)) != off { 633 b.error("DW_FORM_strp/line_strp offset out of range") 634 } 635 if b.err != nil { 636 return nil 637 } 638 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") 644 return nil 645 } 646 b1 = makeBuf(b.dwarf, b.format, "line_str", 0, b.dwarf.lineStr) 647 } 648 b1.skip(int(off)) 649 val = b1.string() 650 if b1.err != nil { 651 b.err = b1.err 652 return nil 653 } 654 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. 688 var strBase int64 689 if cu != nil { 690 strBase, _ = cu.Val(AttrStrOffsetsBase).(int64) 691 } else if a.tag == TagCompileUnit { 692 delay = append(delay, delayed{i, off, formStrx}) 693 break 694 } 695 696 val = resolveStrx(uint64(strBase), off) 697 698 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 } 707 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() 731 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: 742 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) 757 } 758 759 e.Field[i].Val = val 760 } 761 if b.err != nil { 762 return nil 763 } 764 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 } 781 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 } 787 } 788 } 789 790 return e 791 } 792 793 // A Reader allows reading Entry structures from a DWARF ``info'' section. 794 // The Entry structures are arranged in a tree. The Reader's Next function 795 // 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. 798 type Reader struct { 799 b buf 800 d *Data 801 err error 802 unit int 803 lastUnit bool // set if last entry returned by Next is TagCompileUnit/TagPartialUnit 804 lastChildren bool // .Children of last entry returned by Next 805 lastSibling Offset // .Val(AttrSibling) of last entry returned by Next 806 cu *Entry // current compilation unit 807 } 808 809 // Reader returns a new Reader for Data. 810 // The reader is positioned at byte offset 0 in the DWARF ``info'' section. 811 func (d *Data) Reader() *Reader { 812 r := &Reader{d: d} 813 r.Seek(0) 814 return r 815 } 816 817 // AddressSize returns the size in bytes of addresses in the current compilation 818 // unit. 819 func (r *Reader) AddressSize() int { 820 return r.d.unit[r.unit].asize 821 } 822 823 // ByteOrder returns the byte order in the current compilation unit. 824 func (r *Reader) ByteOrder() binary.ByteOrder { 825 return r.b.order 826 } 827 828 // Seek positions the Reader at offset off in the encoded entry stream. 829 // Offset 0 can be used to denote the first entry. 830 func (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) 841 r.cu = nil 842 return 843 } 844 845 i := d.offsetToUnit(off) 846 if i == -1 { 847 r.err = errors.New("offset out of range") 848 return 849 } 850 if i != r.unit { 851 r.cu = nil 852 } 853 u := &d.unit[i] 854 r.unit = i 855 r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:]) 856 } 857 858 // maybeNextUnit advances to the next unit if this one is finished. 859 func (r *Reader) maybeNextUnit() { 860 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { 861 r.nextUnit() 862 } 863 } 864 865 // nextUnit advances to the next unit. 866 func (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 873 // 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. 877 func (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] 886 e := r.b.entry(r.cu, u.atable, u.base, u.vers) 887 if r.b.err != nil { 888 r.err = r.b.err 889 return nil, r.err 890 } 891 r.lastUnit = false 892 if e != nil { 893 r.lastChildren = e.Children 894 if r.lastChildren { 895 r.lastSibling, _ = e.Val(AttrSibling).(Offset) 896 } 897 if e.Tag == TagCompileUnit || e.Tag == TagPartialUnit { 898 r.lastUnit = true 899 r.cu = e 900 } 901 } else { 902 r.lastChildren = false 903 } 904 return e, nil 905 } 906 907 // SkipChildren skips over the child entries associated with 908 // the last Entry returned by Next. If that Entry did not have 909 // children or Next has not been called, SkipChildren is a no-op. 910 func (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 924 if r.lastUnit && r.unit+1 < len(r.d.unit) { 925 r.nextUnit() 926 return 927 } 928 929 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 940 // clone returns a copy of the reader. This is used by the typeReader 941 // interface. 942 func (r *Reader) clone() typeReader { 943 return r.d.Reader() 944 } 945 946 // offset returns the current buffer offset. This is used by the 947 // typeReader interface. 948 func (r *Reader) offset() Offset { 949 return r.b.off 950 } 951 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. 964 func (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 973 r.cu = nil 974 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. 997 func (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 1022 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: 1046 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) 1055 1056 default: 1057 return ret, nil 1058 } 1059 } 1060 1061 // DWARF version 2 through 4 1062 ranges, rangesOK := e.Val(AttrRanges).(int64) 1063 if rangesOK && d.ranges != nil { 1064 _, 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. 1079 func (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 1105 func (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 1117 } else { 1118 ret = append(ret, [2]uint64{base + low, base + high}) 1119 } 1120 } 1121 1122 return ret, nil 1123 } 1124 1125 // dwarf5Ranges interpets a debug_rnglists sequence, see DWARFv5 section 1126 // 2.17.3 (page 53). 1127 func (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 1197 func (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 }