github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/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 } 645 b1 = makeBuf(b.dwarf, b.format, "line_str", 0, b.dwarf.lineStr) 646 } 647 b1.skip(int(off)) 648 val = b1.string() 649 if b1.err != nil { 650 b.err = b1.err 651 return nil 652 } 653 case formStrx, formStrx1, formStrx2, formStrx3, formStrx4: 654 var off uint64 655 switch fmt { 656 case formStrx: 657 off = b.uint() 658 case formStrx1: 659 off = uint64(b.uint8()) 660 case formStrx2: 661 off = uint64(b.uint16()) 662 case formStrx3: 663 off = uint64(b.uint24()) 664 case formStrx4: 665 off = uint64(b.uint32()) 666 } 667 if len(b.dwarf.strOffsets) == 0 { 668 b.error("DW_FORM_strx with no .debug_str_offsets section") 669 } 670 is64, known := b.format.dwarf64() 671 if !known { 672 b.error("unknown offset size for DW_FORM_strx") 673 } 674 if b.err != nil { 675 return nil 676 } 677 if is64 { 678 off *= 8 679 } else { 680 off *= 4 681 } 682 683 // We have to adjust by the offset of the 684 // compilation unit. This won't work if the 685 // program uses Reader.Seek to skip over the 686 // unit. Not much we can do about that. 687 var strBase int64 688 if cu != nil { 689 strBase, _ = cu.Val(AttrStrOffsetsBase).(int64) 690 } else if a.tag == TagCompileUnit { 691 delay = append(delay, delayed{i, off, formStrx}) 692 break 693 } 694 695 val = resolveStrx(uint64(strBase), off) 696 697 case formStrpSup: 698 is64, known := b.format.dwarf64() 699 if !known { 700 b.error("unknown size for DW_FORM_strp_sup") 701 } else if is64 { 702 val = b.uint64() 703 } else { 704 val = b.uint32() 705 } 706 707 // lineptr, loclistptr, macptr, rangelistptr 708 // New in DWARF 4, but clang can generate them with -gdwarf-2. 709 // Section reference, replacing use of formData4 and formData8. 710 case formSecOffset, formGnuRefAlt, formGnuStrpAlt: 711 is64, known := b.format.dwarf64() 712 if !known { 713 b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16)) 714 } else if is64 { 715 val = int64(b.uint64()) 716 } else { 717 val = int64(b.uint32()) 718 } 719 720 // exprloc 721 // New in DWARF 4. 722 case formExprloc: 723 val = b.bytes(int(b.uint())) 724 725 // reference 726 // New in DWARF 4. 727 case formRefSig8: 728 // 64-bit type signature. 729 val = b.uint64() 730 case formRefSup4: 731 val = b.uint32() 732 case formRefSup8: 733 val = b.uint64() 734 735 // loclist 736 case formLoclistx: 737 val = b.uint() 738 739 // rnglist 740 case formRnglistx: 741 off := b.uint() 742 743 // We have to adjust by the rnglists_base of 744 // the compilation unit. This won't work if 745 // the program uses Reader.Seek to skip over 746 // the unit. Not much we can do about that. 747 var rnglistsBase int64 748 if cu != nil { 749 rnglistsBase, _ = cu.Val(AttrRnglistsBase).(int64) 750 } else if a.tag == TagCompileUnit { 751 delay = append(delay, delayed{i, off, formRnglistx}) 752 break 753 } 754 755 val = resolveRnglistx(uint64(rnglistsBase), off) 756 } 757 758 e.Field[i].Val = val 759 } 760 if b.err != nil { 761 return nil 762 } 763 764 for _, del := range delay { 765 switch del.fmt { 766 case formAddrx: 767 addrBase, _ := e.Val(AttrAddrBase).(int64) 768 val, err := b.dwarf.debugAddr(b.format, uint64(addrBase), del.off) 769 if err != nil { 770 b.err = err 771 return nil 772 } 773 e.Field[del.idx].Val = val 774 case formStrx: 775 strBase, _ := e.Val(AttrStrOffsetsBase).(int64) 776 e.Field[del.idx].Val = resolveStrx(uint64(strBase), del.off) 777 if b.err != nil { 778 return nil 779 } 780 case formRnglistx: 781 rnglistsBase, _ := e.Val(AttrRnglistsBase).(int64) 782 e.Field[del.idx].Val = resolveRnglistx(uint64(rnglistsBase), del.off) 783 if b.err != nil { 784 return nil 785 } 786 } 787 } 788 789 return e 790 } 791 792 // A Reader allows reading Entry structures from a DWARF ``info'' section. 793 // The Entry structures are arranged in a tree. The Reader's Next function 794 // return successive entries from a pre-order traversal of the tree. 795 // If an entry has children, its Children field will be true, and the children 796 // follow, terminated by an Entry with Tag 0. 797 type Reader struct { 798 b buf 799 d *Data 800 err error 801 unit int 802 lastUnit bool // set if last entry returned by Next is TagCompileUnit/TagPartialUnit 803 lastChildren bool // .Children of last entry returned by Next 804 lastSibling Offset // .Val(AttrSibling) of last entry returned by Next 805 cu *Entry // current compilation unit 806 } 807 808 // Reader returns a new Reader for Data. 809 // The reader is positioned at byte offset 0 in the DWARF ``info'' section. 810 func (d *Data) Reader() *Reader { 811 r := &Reader{d: d} 812 r.Seek(0) 813 return r 814 } 815 816 // AddressSize returns the size in bytes of addresses in the current compilation 817 // unit. 818 func (r *Reader) AddressSize() int { 819 return r.d.unit[r.unit].asize 820 } 821 822 // ByteOrder returns the byte order in the current compilation unit. 823 func (r *Reader) ByteOrder() binary.ByteOrder { 824 return r.b.order 825 } 826 827 // Seek positions the Reader at offset off in the encoded entry stream. 828 // Offset 0 can be used to denote the first entry. 829 func (r *Reader) Seek(off Offset) { 830 d := r.d 831 r.err = nil 832 r.lastChildren = false 833 if off == 0 { 834 if len(d.unit) == 0 { 835 return 836 } 837 u := &d.unit[0] 838 r.unit = 0 839 r.b = makeBuf(r.d, u, "info", u.off, u.data) 840 r.cu = nil 841 return 842 } 843 844 i := d.offsetToUnit(off) 845 if i == -1 { 846 r.err = errors.New("offset out of range") 847 return 848 } 849 if i != r.unit { 850 r.cu = nil 851 } 852 u := &d.unit[i] 853 r.unit = i 854 r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:]) 855 } 856 857 // maybeNextUnit advances to the next unit if this one is finished. 858 func (r *Reader) maybeNextUnit() { 859 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { 860 r.nextUnit() 861 } 862 } 863 864 // nextUnit advances to the next unit. 865 func (r *Reader) nextUnit() { 866 r.unit++ 867 u := &r.d.unit[r.unit] 868 r.b = makeBuf(r.d, u, "info", u.off, u.data) 869 r.cu = nil 870 } 871 872 // Next reads the next entry from the encoded entry stream. 873 // It returns nil, nil when it reaches the end of the section. 874 // It returns an error if the current offset is invalid or the data at the 875 // offset cannot be decoded as a valid Entry. 876 func (r *Reader) Next() (*Entry, error) { 877 if r.err != nil { 878 return nil, r.err 879 } 880 r.maybeNextUnit() 881 if len(r.b.data) == 0 { 882 return nil, nil 883 } 884 u := &r.d.unit[r.unit] 885 e := r.b.entry(r.cu, u.atable, u.base, u.vers) 886 if r.b.err != nil { 887 r.err = r.b.err 888 return nil, r.err 889 } 890 r.lastUnit = false 891 if e != nil { 892 r.lastChildren = e.Children 893 if r.lastChildren { 894 r.lastSibling, _ = e.Val(AttrSibling).(Offset) 895 } 896 if e.Tag == TagCompileUnit || e.Tag == TagPartialUnit { 897 r.lastUnit = true 898 r.cu = e 899 } 900 } else { 901 r.lastChildren = false 902 } 903 return e, nil 904 } 905 906 // SkipChildren skips over the child entries associated with 907 // the last Entry returned by Next. If that Entry did not have 908 // children or Next has not been called, SkipChildren is a no-op. 909 func (r *Reader) SkipChildren() { 910 if r.err != nil || !r.lastChildren { 911 return 912 } 913 914 // If the last entry had a sibling attribute, 915 // that attribute gives the offset of the next 916 // sibling, so we can avoid decoding the 917 // child subtrees. 918 if r.lastSibling >= r.b.off { 919 r.Seek(r.lastSibling) 920 return 921 } 922 923 if r.lastUnit && r.unit+1 < len(r.d.unit) { 924 r.nextUnit() 925 return 926 } 927 928 for { 929 e, err := r.Next() 930 if err != nil || e == nil || e.Tag == 0 { 931 break 932 } 933 if e.Children { 934 r.SkipChildren() 935 } 936 } 937 } 938 939 // clone returns a copy of the reader. This is used by the typeReader 940 // interface. 941 func (r *Reader) clone() typeReader { 942 return r.d.Reader() 943 } 944 945 // offset returns the current buffer offset. This is used by the 946 // typeReader interface. 947 func (r *Reader) offset() Offset { 948 return r.b.off 949 } 950 951 // SeekPC returns the Entry for the compilation unit that includes pc, 952 // and positions the reader to read the children of that unit. If pc 953 // is not covered by any unit, SeekPC returns ErrUnknownPC and the 954 // position of the reader is undefined. 955 // 956 // Because compilation units can describe multiple regions of the 957 // executable, in the worst case SeekPC must search through all the 958 // ranges in all the compilation units. Each call to SeekPC starts the 959 // search at the compilation unit of the last call, so in general 960 // looking up a series of PCs will be faster if they are sorted. If 961 // the caller wishes to do repeated fast PC lookups, it should build 962 // an appropriate index using the Ranges method. 963 func (r *Reader) SeekPC(pc uint64) (*Entry, error) { 964 unit := r.unit 965 for i := 0; i < len(r.d.unit); i++ { 966 if unit >= len(r.d.unit) { 967 unit = 0 968 } 969 r.err = nil 970 r.lastChildren = false 971 r.unit = unit 972 r.cu = nil 973 u := &r.d.unit[unit] 974 r.b = makeBuf(r.d, u, "info", u.off, u.data) 975 e, err := r.Next() 976 if err != nil { 977 return nil, err 978 } 979 ranges, err := r.d.Ranges(e) 980 if err != nil { 981 return nil, err 982 } 983 for _, pcs := range ranges { 984 if pcs[0] <= pc && pc < pcs[1] { 985 return e, nil 986 } 987 } 988 unit++ 989 } 990 return nil, ErrUnknownPC 991 } 992 993 // Ranges returns the PC ranges covered by e, a slice of [low,high) pairs. 994 // Only some entry types, such as TagCompileUnit or TagSubprogram, have PC 995 // ranges; for others, this will return nil with no error. 996 func (d *Data) Ranges(e *Entry) ([][2]uint64, error) { 997 var ret [][2]uint64 998 999 low, lowOK := e.Val(AttrLowpc).(uint64) 1000 1001 var high uint64 1002 var highOK bool 1003 highField := e.AttrField(AttrHighpc) 1004 if highField != nil { 1005 switch highField.Class { 1006 case ClassAddress: 1007 high, highOK = highField.Val.(uint64) 1008 case ClassConstant: 1009 off, ok := highField.Val.(int64) 1010 if ok { 1011 high = low + uint64(off) 1012 highOK = true 1013 } 1014 } 1015 } 1016 1017 if lowOK && highOK { 1018 ret = append(ret, [2]uint64{low, high}) 1019 } 1020 1021 var u *unit 1022 if uidx := d.offsetToUnit(e.Offset); uidx >= 0 && uidx < len(d.unit) { 1023 u = &d.unit[uidx] 1024 } 1025 1026 if u != nil && u.vers >= 5 && d.rngLists != nil { 1027 // DWARF version 5 and later 1028 field := e.AttrField(AttrRanges) 1029 if field == nil { 1030 return ret, nil 1031 } 1032 switch field.Class { 1033 case ClassRangeListPtr: 1034 ranges, rangesOK := field.Val.(int64) 1035 if !rangesOK { 1036 return ret, nil 1037 } 1038 cu, base, err := d.baseAddressForEntry(e) 1039 if err != nil { 1040 return nil, err 1041 } 1042 return d.dwarf5Ranges(u, cu, base, ranges, ret) 1043 1044 case ClassRngList: 1045 rnglist, ok := field.Val.(uint64) 1046 if !ok { 1047 return ret, nil 1048 } 1049 cu, base, err := d.baseAddressForEntry(e) 1050 if err != nil { 1051 return nil, err 1052 } 1053 return d.dwarf5Ranges(u, cu, base, int64(rnglist), ret) 1054 1055 default: 1056 return ret, nil 1057 } 1058 } 1059 1060 // DWARF version 2 through 4 1061 ranges, rangesOK := e.Val(AttrRanges).(int64) 1062 if rangesOK && d.ranges != nil { 1063 _, base, err := d.baseAddressForEntry(e) 1064 if err != nil { 1065 return nil, err 1066 } 1067 return d.dwarf2Ranges(u, base, ranges, ret) 1068 } 1069 1070 return ret, nil 1071 } 1072 1073 // baseAddressForEntry returns the initial base address to be used when 1074 // looking up the range list of entry e. 1075 // DWARF specifies that this should be the lowpc attribute of the enclosing 1076 // compilation unit, however comments in gdb/dwarf2read.c say that some 1077 // versions of GCC use the entrypc attribute, so we check that too. 1078 func (d *Data) baseAddressForEntry(e *Entry) (*Entry, uint64, error) { 1079 var cu *Entry 1080 if e.Tag == TagCompileUnit { 1081 cu = e 1082 } else { 1083 i := d.offsetToUnit(e.Offset) 1084 if i == -1 { 1085 return nil, 0, errors.New("no unit for entry") 1086 } 1087 u := &d.unit[i] 1088 b := makeBuf(d, u, "info", u.off, u.data) 1089 cu = b.entry(nil, u.atable, u.base, u.vers) 1090 if b.err != nil { 1091 return nil, 0, b.err 1092 } 1093 } 1094 1095 if cuEntry, cuEntryOK := cu.Val(AttrEntrypc).(uint64); cuEntryOK { 1096 return cu, cuEntry, nil 1097 } else if cuLow, cuLowOK := cu.Val(AttrLowpc).(uint64); cuLowOK { 1098 return cu, cuLow, nil 1099 } 1100 1101 return cu, 0, nil 1102 } 1103 1104 func (d *Data) dwarf2Ranges(u *unit, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) { 1105 buf := makeBuf(d, u, "ranges", Offset(ranges), d.ranges[ranges:]) 1106 for len(buf.data) > 0 { 1107 low := buf.addr() 1108 high := buf.addr() 1109 1110 if low == 0 && high == 0 { 1111 break 1112 } 1113 1114 if low == ^uint64(0)>>uint((8-u.addrsize())*8) { 1115 base = high 1116 } else { 1117 ret = append(ret, [2]uint64{base + low, base + high}) 1118 } 1119 } 1120 1121 return ret, nil 1122 } 1123 1124 // dwarf5Ranges interpets a debug_rnglists sequence, see DWARFv5 section 1125 // 2.17.3 (page 53). 1126 func (d *Data) dwarf5Ranges(u *unit, cu *Entry, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) { 1127 var addrBase int64 1128 if cu != nil { 1129 addrBase, _ = cu.Val(AttrAddrBase).(int64) 1130 } 1131 1132 buf := makeBuf(d, u, "rnglists", 0, d.rngLists) 1133 buf.skip(int(ranges)) 1134 for { 1135 opcode := buf.uint8() 1136 switch opcode { 1137 case rleEndOfList: 1138 if buf.err != nil { 1139 return nil, buf.err 1140 } 1141 return ret, nil 1142 1143 case rleBaseAddressx: 1144 baseIdx := buf.uint() 1145 var err error 1146 base, err = d.debugAddr(u, uint64(addrBase), baseIdx) 1147 if err != nil { 1148 return nil, err 1149 } 1150 1151 case rleStartxEndx: 1152 startIdx := buf.uint() 1153 endIdx := buf.uint() 1154 1155 start, err := d.debugAddr(u, uint64(addrBase), startIdx) 1156 if err != nil { 1157 return nil, err 1158 } 1159 end, err := d.debugAddr(u, uint64(addrBase), endIdx) 1160 if err != nil { 1161 return nil, err 1162 } 1163 ret = append(ret, [2]uint64{start, end}) 1164 1165 case rleStartxLength: 1166 startIdx := buf.uint() 1167 len := buf.uint() 1168 start, err := d.debugAddr(u, uint64(addrBase), startIdx) 1169 if err != nil { 1170 return nil, err 1171 } 1172 ret = append(ret, [2]uint64{start, start + len}) 1173 1174 case rleOffsetPair: 1175 off1 := buf.uint() 1176 off2 := buf.uint() 1177 ret = append(ret, [2]uint64{base + off1, base + off2}) 1178 1179 case rleBaseAddress: 1180 base = buf.addr() 1181 1182 case rleStartEnd: 1183 start := buf.addr() 1184 end := buf.addr() 1185 ret = append(ret, [2]uint64{start, end}) 1186 1187 case rleStartLength: 1188 start := buf.addr() 1189 len := buf.uint() 1190 ret = append(ret, [2]uint64{start, start + len}) 1191 } 1192 } 1193 } 1194 1195 // debugAddr returns the address at idx in debug_addr 1196 func (d *Data) debugAddr(format dataFormat, addrBase, idx uint64) (uint64, error) { 1197 off := idx*uint64(format.addrsize()) + addrBase 1198 1199 if uint64(int(off)) != off { 1200 return 0, errors.New("offset out of range") 1201 } 1202 1203 b := makeBuf(d, format, "addr", 0, d.addr) 1204 b.skip(int(off)) 1205 val := b.addr() 1206 if b.err != nil { 1207 return 0, b.err 1208 } 1209 return val, nil 1210 }