github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/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 "errors" 15 "strconv" 16 ) 17 18 // a single entry's description: a sequence of attributes 19 type abbrev struct { 20 tag Tag 21 children bool 22 field []afield 23 } 24 25 type afield struct { 26 attr Attr 27 fmt format 28 class Class 29 } 30 31 // a map from entry format ids to their descriptions 32 type abbrevTable map[uint32]abbrev 33 34 // ParseAbbrev returns the abbreviation table that starts at byte off 35 // in the .debug_abbrev section. 36 func (d *Data) parseAbbrev(off uint32, vers int) (abbrevTable, error) { 37 if m, ok := d.abbrevCache[off]; ok { 38 return m, nil 39 } 40 41 data := d.abbrev 42 if off > uint32(len(data)) { 43 data = nil 44 } else { 45 data = data[off:] 46 } 47 b := makeBuf(d, unknownFormat{}, "abbrev", 0, data) 48 49 // Error handling is simplified by the buf getters 50 // returning an endless stream of 0s after an error. 51 m := make(abbrevTable) 52 for { 53 // Table ends with id == 0. 54 id := uint32(b.uint()) 55 if id == 0 { 56 break 57 } 58 59 // Walk over attributes, counting. 60 n := 0 61 b1 := b // Read from copy of b. 62 b1.uint() 63 b1.uint8() 64 for { 65 tag := b1.uint() 66 fmt := b1.uint() 67 if tag == 0 && fmt == 0 { 68 break 69 } 70 n++ 71 } 72 if b1.err != nil { 73 return nil, b1.err 74 } 75 76 // Walk over attributes again, this time writing them down. 77 var a abbrev 78 a.tag = Tag(b.uint()) 79 a.children = b.uint8() != 0 80 a.field = make([]afield, n) 81 for i := range a.field { 82 a.field[i].attr = Attr(b.uint()) 83 a.field[i].fmt = format(b.uint()) 84 a.field[i].class = formToClass(a.field[i].fmt, a.field[i].attr, vers, &b) 85 } 86 b.uint() 87 b.uint() 88 89 m[id] = a 90 } 91 if b.err != nil { 92 return nil, b.err 93 } 94 d.abbrevCache[off] = m 95 return m, nil 96 } 97 98 // attrIsExprloc indicates attributes that allow exprloc values that 99 // are encoded as block values in DWARF 2 and 3. See DWARF 4, Figure 100 // 20. 101 var attrIsExprloc = map[Attr]bool{ 102 AttrLocation: true, 103 AttrByteSize: true, 104 AttrBitOffset: true, 105 AttrBitSize: true, 106 AttrStringLength: true, 107 AttrLowerBound: true, 108 AttrReturnAddr: true, 109 AttrStrideSize: true, 110 AttrUpperBound: true, 111 AttrCount: true, 112 AttrDataMemberLoc: true, 113 AttrFrameBase: true, 114 AttrSegment: true, 115 AttrStaticLink: true, 116 AttrUseLocation: true, 117 AttrVtableElemLoc: true, 118 AttrAllocated: true, 119 AttrAssociated: true, 120 AttrDataLocation: true, 121 AttrStride: true, 122 } 123 124 // attrPtrClass indicates the *ptr class of attributes that have 125 // encoding formSecOffset in DWARF 4 or formData* in DWARF 2 and 3. 126 var attrPtrClass = map[Attr]Class{ 127 AttrLocation: ClassLocListPtr, 128 AttrStmtList: ClassLinePtr, 129 AttrStringLength: ClassLocListPtr, 130 AttrReturnAddr: ClassLocListPtr, 131 AttrStartScope: ClassRangeListPtr, 132 AttrDataMemberLoc: ClassLocListPtr, 133 AttrFrameBase: ClassLocListPtr, 134 AttrMacroInfo: ClassMacPtr, 135 AttrSegment: ClassLocListPtr, 136 AttrStaticLink: ClassLocListPtr, 137 AttrUseLocation: ClassLocListPtr, 138 AttrVtableElemLoc: ClassLocListPtr, 139 AttrRanges: ClassRangeListPtr, 140 } 141 142 // formToClass returns the DWARF 4 Class for the given form. If the 143 // DWARF version is less then 4, it will disambiguate some forms 144 // depending on the attribute. 145 func formToClass(form format, attr Attr, vers int, b *buf) Class { 146 switch form { 147 default: 148 b.error("cannot determine class of unknown attribute form") 149 return 0 150 151 case formAddr: 152 return ClassAddress 153 154 case formDwarfBlock1, formDwarfBlock2, formDwarfBlock4, formDwarfBlock: 155 // In DWARF 2 and 3, ClassExprLoc was encoded as a 156 // block. DWARF 4 distinguishes ClassBlock and 157 // ClassExprLoc, but there are no attributes that can 158 // be both, so we also promote ClassBlock values in 159 // DWARF 4 that should be ClassExprLoc in case 160 // producers get this wrong. 161 if attrIsExprloc[attr] { 162 return ClassExprLoc 163 } 164 return ClassBlock 165 166 case formData1, formData2, formData4, formData8, formSdata, formUdata: 167 // In DWARF 2 and 3, ClassPtr was encoded as a 168 // constant. Unlike ClassExprLoc/ClassBlock, some 169 // DWARF 4 attributes need to distinguish Class*Ptr 170 // from ClassConstant, so we only do this promotion 171 // for versions 2 and 3. 172 if class, ok := attrPtrClass[attr]; vers < 4 && ok { 173 return class 174 } 175 return ClassConstant 176 177 case formFlag, formFlagPresent: 178 return ClassFlag 179 180 case formRefAddr, formRef1, formRef2, formRef4, formRef8, formRefUdata: 181 return ClassReference 182 183 case formRefSig8: 184 return ClassReferenceSig 185 186 case formString, formStrp: 187 return ClassString 188 189 case formSecOffset: 190 // DWARF 4 defines four *ptr classes, but doesn't 191 // distinguish them in the encoding. Disambiguate 192 // these classes using the attribute. 193 if class, ok := attrPtrClass[attr]; ok { 194 return class 195 } 196 b.error("cannot determine class of unknown attribute with formSecOffset") 197 return 0 198 199 case formExprloc: 200 return ClassExprLoc 201 202 case formGnuRefAlt: 203 return ClassReferenceAlt 204 205 case formGnuStrpAlt: 206 return ClassStringAlt 207 } 208 } 209 210 // An entry is a sequence of attribute/value pairs. 211 type Entry struct { 212 Offset Offset // offset of Entry in DWARF info 213 Tag Tag // tag (kind of Entry) 214 Children bool // whether Entry is followed by children 215 Field []Field 216 } 217 218 // A Field is a single attribute/value pair in an Entry. 219 // 220 // A value can be one of several "attribute classes" defined by DWARF. 221 // The Go types corresponding to each class are: 222 // 223 // DWARF class Go type Class 224 // ----------- ------- ----- 225 // address uint64 ClassAddress 226 // block []byte ClassBlock 227 // constant int64 ClassConstant 228 // flag bool ClassFlag 229 // reference 230 // to info dwarf.Offset ClassReference 231 // to type unit uint64 ClassReferenceSig 232 // string string ClassString 233 // exprloc []byte ClassExprLoc 234 // lineptr int64 ClassLinePtr 235 // loclistptr int64 ClassLocListPtr 236 // macptr int64 ClassMacPtr 237 // rangelistptr int64 ClassRangeListPtr 238 type Field struct { 239 Attr Attr 240 Val interface{} 241 Class Class 242 } 243 244 // A Class is the DWARF 4 class of an attibute value. 245 // 246 // In general, a given attribute's value may take on one of several 247 // possible classes defined by DWARF, each of which leads to a 248 // slightly different interpretation of the attribute. 249 // 250 // DWARF version 4 distinguishes attribute value classes more finely 251 // than previous versions of DWARF. The reader will disambiguate 252 // coarser classes from earlier versions of DWARF into the appropriate 253 // DWARF 4 class. For example, DWARF 2 uses "constant" for constants 254 // as well as all types of section offsets, but the reader will 255 // canonicalize attributes in DWARF 2 files that refer to section 256 // offsets to one of the Class*Ptr classes, even though these classes 257 // were only defined in DWARF 3. 258 type Class int 259 260 const ( 261 // ClassAddress represents values of type uint64 that are 262 // addresses on the target machine. 263 ClassAddress Class = 1 + iota 264 265 // ClassBlock represents values of type []byte whose 266 // interpretation depends on the attribute. 267 ClassBlock 268 269 // ClassConstant represents values of type int64 that are 270 // constants. The interpretation of this constant depends on 271 // the attribute. 272 ClassConstant 273 274 // ClassExprLoc represents values of type []byte that contain 275 // an encoded DWARF expression or location description. 276 ClassExprLoc 277 278 // ClassFlag represents values of type bool. 279 ClassFlag 280 281 // ClassLinePtr represents values that are an int64 offset 282 // into the "line" section. 283 ClassLinePtr 284 285 // ClassLocListPtr represents values that are an int64 offset 286 // into the "loclist" section. 287 ClassLocListPtr 288 289 // ClassMacPtr represents values that are an int64 offset into 290 // the "mac" section. 291 ClassMacPtr 292 293 // ClassMacPtr represents values that are an int64 offset into 294 // the "rangelist" section. 295 ClassRangeListPtr 296 297 // ClassReference represents values that are an Offset offset 298 // of an Entry in the info section (for use with Reader.Seek). 299 // The DWARF specification combines ClassReference and 300 // ClassReferenceSig into class "reference". 301 ClassReference 302 303 // ClassReferenceSig represents values that are a uint64 type 304 // signature referencing a type Entry. 305 ClassReferenceSig 306 307 // ClassString represents values that are strings. If the 308 // compilation unit specifies the AttrUseUTF8 flag (strongly 309 // recommended), the string value will be encoded in UTF-8. 310 // Otherwise, the encoding is unspecified. 311 ClassString 312 313 // ClassReferenceAlt represents values of type int64 that are 314 // an offset into the DWARF "info" section of an alternate 315 // object file. 316 ClassReferenceAlt 317 318 // ClassStringAlt represents values of type int64 that are an 319 // offset into the DWARF string section of an alternate object 320 // file. 321 ClassStringAlt 322 ) 323 324 //go:generate stringer -type=Class 325 326 func (i Class) GoString() string { 327 return "dwarf." + i.String() 328 } 329 330 // Val returns the value associated with attribute Attr in Entry, 331 // or nil if there is no such attribute. 332 // 333 // A common idiom is to merge the check for nil return with 334 // the check that the value has the expected dynamic type, as in: 335 // v, ok := e.Val(AttrSibling).(int64) 336 // 337 func (e *Entry) Val(a Attr) interface{} { 338 if f := e.AttrField(a); f != nil { 339 return f.Val 340 } 341 return nil 342 } 343 344 // AttrField returns the Field associated with attribute Attr in 345 // Entry, or nil if there is no such attribute. 346 func (e *Entry) AttrField(a Attr) *Field { 347 for i, f := range e.Field { 348 if f.Attr == a { 349 return &e.Field[i] 350 } 351 } 352 return nil 353 } 354 355 // An Offset represents the location of an Entry within the DWARF info. 356 // (See Reader.Seek.) 357 type Offset uint32 358 359 // Entry reads a single entry from buf, decoding 360 // according to the given abbreviation table. 361 func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { 362 off := b.off 363 id := uint32(b.uint()) 364 if id == 0 { 365 return &Entry{} 366 } 367 a, ok := atab[id] 368 if !ok { 369 b.error("unknown abbreviation table index") 370 return nil 371 } 372 e := &Entry{ 373 Offset: off, 374 Tag: a.tag, 375 Children: a.children, 376 Field: make([]Field, len(a.field)), 377 } 378 for i := range e.Field { 379 e.Field[i].Attr = a.field[i].attr 380 e.Field[i].Class = a.field[i].class 381 fmt := a.field[i].fmt 382 if fmt == formIndirect { 383 fmt = format(b.uint()) 384 } 385 var val interface{} 386 switch fmt { 387 default: 388 b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16)) 389 390 // address 391 case formAddr: 392 val = b.addr() 393 394 // block 395 case formDwarfBlock1: 396 val = b.bytes(int(b.uint8())) 397 case formDwarfBlock2: 398 val = b.bytes(int(b.uint16())) 399 case formDwarfBlock4: 400 val = b.bytes(int(b.uint32())) 401 case formDwarfBlock: 402 val = b.bytes(int(b.uint())) 403 404 // constant 405 case formData1: 406 val = int64(b.uint8()) 407 case formData2: 408 val = int64(b.uint16()) 409 case formData4: 410 val = int64(b.uint32()) 411 case formData8: 412 val = int64(b.uint64()) 413 case formSdata: 414 val = int64(b.int()) 415 case formUdata: 416 val = int64(b.uint()) 417 418 // flag 419 case formFlag: 420 val = b.uint8() == 1 421 // New in DWARF 4. 422 case formFlagPresent: 423 // The attribute is implicitly indicated as present, and no value is 424 // encoded in the debugging information entry itself. 425 val = true 426 427 // reference to other entry 428 case formRefAddr: 429 vers := b.format.version() 430 if vers == 0 { 431 b.error("unknown version for DW_FORM_ref_addr") 432 } else if vers == 2 { 433 val = Offset(b.addr()) 434 } else { 435 is64, known := b.format.dwarf64() 436 if !known { 437 b.error("unknown size for DW_FORM_ref_addr") 438 } else if is64 { 439 val = Offset(b.uint64()) 440 } else { 441 val = Offset(b.uint32()) 442 } 443 } 444 case formRef1: 445 val = Offset(b.uint8()) + ubase 446 case formRef2: 447 val = Offset(b.uint16()) + ubase 448 case formRef4: 449 val = Offset(b.uint32()) + ubase 450 case formRef8: 451 val = Offset(b.uint64()) + ubase 452 case formRefUdata: 453 val = Offset(b.uint()) + ubase 454 455 // string 456 case formString: 457 val = b.string() 458 case formStrp: 459 off := b.uint32() // offset into .debug_str 460 if b.err != nil { 461 return nil 462 } 463 b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str) 464 b1.skip(int(off)) 465 val = b1.string() 466 if b1.err != nil { 467 b.err = b1.err 468 return nil 469 } 470 471 // lineptr, loclistptr, macptr, rangelistptr 472 // New in DWARF 4, but clang can generate them with -gdwarf-2. 473 // Section reference, replacing use of formData4 and formData8. 474 case formSecOffset, formGnuRefAlt, formGnuStrpAlt: 475 is64, known := b.format.dwarf64() 476 if !known { 477 b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16)) 478 } else if is64 { 479 val = int64(b.uint64()) 480 } else { 481 val = int64(b.uint32()) 482 } 483 484 // exprloc 485 // New in DWARF 4. 486 case formExprloc: 487 val = b.bytes(int(b.uint())) 488 489 // reference 490 // New in DWARF 4. 491 case formRefSig8: 492 // 64-bit type signature. 493 val = b.uint64() 494 } 495 e.Field[i].Val = val 496 } 497 if b.err != nil { 498 return nil 499 } 500 return e 501 } 502 503 // A Reader allows reading Entry structures from a DWARF ``info'' section. 504 // The Entry structures are arranged in a tree. The Reader's Next function 505 // return successive entries from a pre-order traversal of the tree. 506 // If an entry has children, its Children field will be true, and the children 507 // follow, terminated by an Entry with Tag 0. 508 type Reader struct { 509 b buf 510 d *Data 511 err error 512 unit int 513 lastChildren bool // .Children of last entry returned by Next 514 lastSibling Offset // .Val(AttrSibling) of last entry returned by Next 515 } 516 517 // Reader returns a new Reader for Data. 518 // The reader is positioned at byte offset 0 in the DWARF ``info'' section. 519 func (d *Data) Reader() *Reader { 520 r := &Reader{d: d} 521 r.Seek(0) 522 return r 523 } 524 525 // AddressSize returns the size in bytes of addresses in the current compilation 526 // unit. 527 func (r *Reader) AddressSize() int { 528 return r.d.unit[r.unit].asize 529 } 530 531 // Seek positions the Reader at offset off in the encoded entry stream. 532 // Offset 0 can be used to denote the first entry. 533 func (r *Reader) Seek(off Offset) { 534 d := r.d 535 r.err = nil 536 r.lastChildren = false 537 if off == 0 { 538 if len(d.unit) == 0 { 539 return 540 } 541 u := &d.unit[0] 542 r.unit = 0 543 r.b = makeBuf(r.d, u, "info", u.off, u.data) 544 return 545 } 546 547 i := d.offsetToUnit(off) 548 if i == -1 { 549 r.err = errors.New("offset out of range") 550 return 551 } 552 u := &d.unit[i] 553 r.unit = i 554 r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:]) 555 } 556 557 // maybeNextUnit advances to the next unit if this one is finished. 558 func (r *Reader) maybeNextUnit() { 559 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { 560 r.unit++ 561 u := &r.d.unit[r.unit] 562 r.b = makeBuf(r.d, u, "info", u.off, u.data) 563 } 564 } 565 566 // Next reads the next entry from the encoded entry stream. 567 // It returns nil, nil when it reaches the end of the section. 568 // It returns an error if the current offset is invalid or the data at the 569 // offset cannot be decoded as a valid Entry. 570 func (r *Reader) Next() (*Entry, error) { 571 if r.err != nil { 572 return nil, r.err 573 } 574 r.maybeNextUnit() 575 if len(r.b.data) == 0 { 576 return nil, nil 577 } 578 u := &r.d.unit[r.unit] 579 e := r.b.entry(u.atable, u.base) 580 if r.b.err != nil { 581 r.err = r.b.err 582 return nil, r.err 583 } 584 if e != nil { 585 r.lastChildren = e.Children 586 if r.lastChildren { 587 r.lastSibling, _ = e.Val(AttrSibling).(Offset) 588 } 589 } else { 590 r.lastChildren = false 591 } 592 return e, nil 593 } 594 595 // SkipChildren skips over the child entries associated with 596 // the last Entry returned by Next. If that Entry did not have 597 // children or Next has not been called, SkipChildren is a no-op. 598 func (r *Reader) SkipChildren() { 599 if r.err != nil || !r.lastChildren { 600 return 601 } 602 603 // If the last entry had a sibling attribute, 604 // that attribute gives the offset of the next 605 // sibling, so we can avoid decoding the 606 // child subtrees. 607 if r.lastSibling >= r.b.off { 608 r.Seek(r.lastSibling) 609 return 610 } 611 612 for { 613 e, err := r.Next() 614 if err != nil || e == nil || e.Tag == 0 { 615 break 616 } 617 if e.Children { 618 r.SkipChildren() 619 } 620 } 621 } 622 623 // clone returns a copy of the reader. This is used by the typeReader 624 // interface. 625 func (r *Reader) clone() typeReader { 626 return r.d.Reader() 627 } 628 629 // offset returns the current buffer offset. This is used by the 630 // typeReader interface. 631 func (r *Reader) offset() Offset { 632 return r.b.off 633 }