github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/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 return ClassUnknown 197 198 case formExprloc: 199 return ClassExprLoc 200 201 case formGnuRefAlt: 202 return ClassReferenceAlt 203 204 case formGnuStrpAlt: 205 return ClassStringAlt 206 } 207 } 208 209 // An entry is a sequence of attribute/value pairs. 210 type Entry struct { 211 Offset Offset // offset of Entry in DWARF info 212 Tag Tag // tag (kind of Entry) 213 Children bool // whether Entry is followed by children 214 Field []Field 215 } 216 217 // A Field is a single attribute/value pair in an Entry. 218 // 219 // A value can be one of several "attribute classes" defined by DWARF. 220 // The Go types corresponding to each class are: 221 // 222 // DWARF class Go type Class 223 // ----------- ------- ----- 224 // address uint64 ClassAddress 225 // block []byte ClassBlock 226 // constant int64 ClassConstant 227 // flag bool ClassFlag 228 // reference 229 // to info dwarf.Offset ClassReference 230 // to type unit uint64 ClassReferenceSig 231 // string string ClassString 232 // exprloc []byte ClassExprLoc 233 // lineptr int64 ClassLinePtr 234 // loclistptr int64 ClassLocListPtr 235 // macptr int64 ClassMacPtr 236 // rangelistptr int64 ClassRangeListPtr 237 // 238 // For unrecognized or vendor-defined attributes, Class may be 239 // ClassUnknown. 240 type Field struct { 241 Attr Attr 242 Val interface{} 243 Class Class 244 } 245 246 // A Class is the DWARF 4 class of an attibute value. 247 // 248 // In general, a given attribute's value may take on one of several 249 // possible classes defined by DWARF, each of which leads to a 250 // slightly different interpretation of the attribute. 251 // 252 // DWARF version 4 distinguishes attribute value classes more finely 253 // than previous versions of DWARF. The reader will disambiguate 254 // coarser classes from earlier versions of DWARF into the appropriate 255 // DWARF 4 class. For example, DWARF 2 uses "constant" for constants 256 // as well as all types of section offsets, but the reader will 257 // canonicalize attributes in DWARF 2 files that refer to section 258 // offsets to one of the Class*Ptr classes, even though these classes 259 // were only defined in DWARF 3. 260 type Class int 261 262 const ( 263 // ClassUnknown represents values of unknown DWARF class. 264 ClassUnknown Class = iota 265 266 // ClassAddress represents values of type uint64 that are 267 // addresses on the target machine. 268 ClassAddress 269 270 // ClassBlock represents values of type []byte whose 271 // interpretation depends on the attribute. 272 ClassBlock 273 274 // ClassConstant represents values of type int64 that are 275 // constants. The interpretation of this constant depends on 276 // the attribute. 277 ClassConstant 278 279 // ClassExprLoc represents values of type []byte that contain 280 // an encoded DWARF expression or location description. 281 ClassExprLoc 282 283 // ClassFlag represents values of type bool. 284 ClassFlag 285 286 // ClassLinePtr represents values that are an int64 offset 287 // into the "line" section. 288 ClassLinePtr 289 290 // ClassLocListPtr represents values that are an int64 offset 291 // into the "loclist" section. 292 ClassLocListPtr 293 294 // ClassMacPtr represents values that are an int64 offset into 295 // the "mac" section. 296 ClassMacPtr 297 298 // ClassMacPtr represents values that are an int64 offset into 299 // the "rangelist" section. 300 ClassRangeListPtr 301 302 // ClassReference represents values that are an Offset offset 303 // of an Entry in the info section (for use with Reader.Seek). 304 // The DWARF specification combines ClassReference and 305 // ClassReferenceSig into class "reference". 306 ClassReference 307 308 // ClassReferenceSig represents values that are a uint64 type 309 // signature referencing a type Entry. 310 ClassReferenceSig 311 312 // ClassString represents values that are strings. If the 313 // compilation unit specifies the AttrUseUTF8 flag (strongly 314 // recommended), the string value will be encoded in UTF-8. 315 // Otherwise, the encoding is unspecified. 316 ClassString 317 318 // ClassReferenceAlt represents values of type int64 that are 319 // an offset into the DWARF "info" section of an alternate 320 // object file. 321 ClassReferenceAlt 322 323 // ClassStringAlt represents values of type int64 that are an 324 // offset into the DWARF string section of an alternate object 325 // file. 326 ClassStringAlt 327 ) 328 329 //go:generate stringer -type=Class 330 331 func (i Class) GoString() string { 332 return "dwarf." + i.String() 333 } 334 335 // Val returns the value associated with attribute Attr in Entry, 336 // or nil if there is no such attribute. 337 // 338 // A common idiom is to merge the check for nil return with 339 // the check that the value has the expected dynamic type, as in: 340 // v, ok := e.Val(AttrSibling).(int64) 341 // 342 func (e *Entry) Val(a Attr) interface{} { 343 if f := e.AttrField(a); f != nil { 344 return f.Val 345 } 346 return nil 347 } 348 349 // AttrField returns the Field associated with attribute Attr in 350 // Entry, or nil if there is no such attribute. 351 func (e *Entry) AttrField(a Attr) *Field { 352 for i, f := range e.Field { 353 if f.Attr == a { 354 return &e.Field[i] 355 } 356 } 357 return nil 358 } 359 360 // An Offset represents the location of an Entry within the DWARF info. 361 // (See Reader.Seek.) 362 type Offset uint32 363 364 // Entry reads a single entry from buf, decoding 365 // according to the given abbreviation table. 366 func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { 367 off := b.off 368 id := uint32(b.uint()) 369 if id == 0 { 370 return &Entry{} 371 } 372 a, ok := atab[id] 373 if !ok { 374 b.error("unknown abbreviation table index") 375 return nil 376 } 377 e := &Entry{ 378 Offset: off, 379 Tag: a.tag, 380 Children: a.children, 381 Field: make([]Field, len(a.field)), 382 } 383 for i := range e.Field { 384 e.Field[i].Attr = a.field[i].attr 385 e.Field[i].Class = a.field[i].class 386 fmt := a.field[i].fmt 387 if fmt == formIndirect { 388 fmt = format(b.uint()) 389 } 390 var val interface{} 391 switch fmt { 392 default: 393 b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16)) 394 395 // address 396 case formAddr: 397 val = b.addr() 398 399 // block 400 case formDwarfBlock1: 401 val = b.bytes(int(b.uint8())) 402 case formDwarfBlock2: 403 val = b.bytes(int(b.uint16())) 404 case formDwarfBlock4: 405 val = b.bytes(int(b.uint32())) 406 case formDwarfBlock: 407 val = b.bytes(int(b.uint())) 408 409 // constant 410 case formData1: 411 val = int64(b.uint8()) 412 case formData2: 413 val = int64(b.uint16()) 414 case formData4: 415 val = int64(b.uint32()) 416 case formData8: 417 val = int64(b.uint64()) 418 case formSdata: 419 val = int64(b.int()) 420 case formUdata: 421 val = int64(b.uint()) 422 423 // flag 424 case formFlag: 425 val = b.uint8() == 1 426 // New in DWARF 4. 427 case formFlagPresent: 428 // The attribute is implicitly indicated as present, and no value is 429 // encoded in the debugging information entry itself. 430 val = true 431 432 // reference to other entry 433 case formRefAddr: 434 vers := b.format.version() 435 if vers == 0 { 436 b.error("unknown version for DW_FORM_ref_addr") 437 } else if vers == 2 { 438 val = Offset(b.addr()) 439 } else { 440 is64, known := b.format.dwarf64() 441 if !known { 442 b.error("unknown size for DW_FORM_ref_addr") 443 } else if is64 { 444 val = Offset(b.uint64()) 445 } else { 446 val = Offset(b.uint32()) 447 } 448 } 449 case formRef1: 450 val = Offset(b.uint8()) + ubase 451 case formRef2: 452 val = Offset(b.uint16()) + ubase 453 case formRef4: 454 val = Offset(b.uint32()) + ubase 455 case formRef8: 456 val = Offset(b.uint64()) + ubase 457 case formRefUdata: 458 val = Offset(b.uint()) + ubase 459 460 // string 461 case formString: 462 val = b.string() 463 case formStrp: 464 off := b.uint32() // offset into .debug_str 465 if b.err != nil { 466 return nil 467 } 468 b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str) 469 b1.skip(int(off)) 470 val = b1.string() 471 if b1.err != nil { 472 b.err = b1.err 473 return nil 474 } 475 476 // lineptr, loclistptr, macptr, rangelistptr 477 // New in DWARF 4, but clang can generate them with -gdwarf-2. 478 // Section reference, replacing use of formData4 and formData8. 479 case formSecOffset, formGnuRefAlt, formGnuStrpAlt: 480 is64, known := b.format.dwarf64() 481 if !known { 482 b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16)) 483 } else if is64 { 484 val = int64(b.uint64()) 485 } else { 486 val = int64(b.uint32()) 487 } 488 489 // exprloc 490 // New in DWARF 4. 491 case formExprloc: 492 val = b.bytes(int(b.uint())) 493 494 // reference 495 // New in DWARF 4. 496 case formRefSig8: 497 // 64-bit type signature. 498 val = b.uint64() 499 } 500 e.Field[i].Val = val 501 } 502 if b.err != nil { 503 return nil 504 } 505 return e 506 } 507 508 // A Reader allows reading Entry structures from a DWARF ``info'' section. 509 // The Entry structures are arranged in a tree. The Reader's Next function 510 // return successive entries from a pre-order traversal of the tree. 511 // If an entry has children, its Children field will be true, and the children 512 // follow, terminated by an Entry with Tag 0. 513 type Reader struct { 514 b buf 515 d *Data 516 err error 517 unit int 518 lastChildren bool // .Children of last entry returned by Next 519 lastSibling Offset // .Val(AttrSibling) of last entry returned by Next 520 } 521 522 // Reader returns a new Reader for Data. 523 // The reader is positioned at byte offset 0 in the DWARF ``info'' section. 524 func (d *Data) Reader() *Reader { 525 r := &Reader{d: d} 526 r.Seek(0) 527 return r 528 } 529 530 // AddressSize returns the size in bytes of addresses in the current compilation 531 // unit. 532 func (r *Reader) AddressSize() int { 533 return r.d.unit[r.unit].asize 534 } 535 536 // Seek positions the Reader at offset off in the encoded entry stream. 537 // Offset 0 can be used to denote the first entry. 538 func (r *Reader) Seek(off Offset) { 539 d := r.d 540 r.err = nil 541 r.lastChildren = false 542 if off == 0 { 543 if len(d.unit) == 0 { 544 return 545 } 546 u := &d.unit[0] 547 r.unit = 0 548 r.b = makeBuf(r.d, u, "info", u.off, u.data) 549 return 550 } 551 552 i := d.offsetToUnit(off) 553 if i == -1 { 554 r.err = errors.New("offset out of range") 555 return 556 } 557 u := &d.unit[i] 558 r.unit = i 559 r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:]) 560 } 561 562 // maybeNextUnit advances to the next unit if this one is finished. 563 func (r *Reader) maybeNextUnit() { 564 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { 565 r.unit++ 566 u := &r.d.unit[r.unit] 567 r.b = makeBuf(r.d, u, "info", u.off, u.data) 568 } 569 } 570 571 // Next reads the next entry from the encoded entry stream. 572 // It returns nil, nil when it reaches the end of the section. 573 // It returns an error if the current offset is invalid or the data at the 574 // offset cannot be decoded as a valid Entry. 575 func (r *Reader) Next() (*Entry, error) { 576 if r.err != nil { 577 return nil, r.err 578 } 579 r.maybeNextUnit() 580 if len(r.b.data) == 0 { 581 return nil, nil 582 } 583 u := &r.d.unit[r.unit] 584 e := r.b.entry(u.atable, u.base) 585 if r.b.err != nil { 586 r.err = r.b.err 587 return nil, r.err 588 } 589 if e != nil { 590 r.lastChildren = e.Children 591 if r.lastChildren { 592 r.lastSibling, _ = e.Val(AttrSibling).(Offset) 593 } 594 } else { 595 r.lastChildren = false 596 } 597 return e, nil 598 } 599 600 // SkipChildren skips over the child entries associated with 601 // the last Entry returned by Next. If that Entry did not have 602 // children or Next has not been called, SkipChildren is a no-op. 603 func (r *Reader) SkipChildren() { 604 if r.err != nil || !r.lastChildren { 605 return 606 } 607 608 // If the last entry had a sibling attribute, 609 // that attribute gives the offset of the next 610 // sibling, so we can avoid decoding the 611 // child subtrees. 612 if r.lastSibling >= r.b.off { 613 r.Seek(r.lastSibling) 614 return 615 } 616 617 for { 618 e, err := r.Next() 619 if err != nil || e == nil || e.Tag == 0 { 620 break 621 } 622 if e.Children { 623 r.SkipChildren() 624 } 625 } 626 } 627 628 // clone returns a copy of the reader. This is used by the typeReader 629 // interface. 630 func (r *Reader) clone() typeReader { 631 return r.d.Reader() 632 } 633 634 // offset returns the current buffer offset. This is used by the 635 // typeReader interface. 636 func (r *Reader) offset() Offset { 637 return r.b.off 638 }