github.com/karrick/go@v0.0.0-20170817181416-d5b0ec858b37/src/cmd/internal/dwarf/dwarf.go (about) 1 // Copyright 2016 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 // Package dwarf generates DWARF debugging information. 6 // DWARF generation is split between the compiler and the linker, 7 // this package contains the shared code. 8 package dwarf 9 10 import ( 11 "errors" 12 "fmt" 13 ) 14 15 // InfoPrefix is the prefix for all the symbols containing DWARF info entries. 16 const InfoPrefix = "go.info." 17 18 // RangePrefix is the prefix for all the symbols containing DWARF location lists. 19 const LocPrefix = "go.loc." 20 21 // RangePrefix is the prefix for all the symbols containing DWARF range lists. 22 const RangePrefix = "go.range." 23 24 // Sym represents a symbol. 25 type Sym interface { 26 Len() int64 27 } 28 29 // A Location represents a variable's location at a particular PC range. 30 // It becomes a location list entry in the DWARF. 31 type Location struct { 32 StartPC, EndPC int64 33 Pieces []Piece 34 } 35 36 // A Piece represents the location of a particular part of a variable. 37 // It becomes part of a location list entry (a DW_OP_piece) in the DWARF. 38 type Piece struct { 39 Length int64 40 StackOffset int32 41 RegNum int16 42 Missing bool 43 OnStack bool // if true, RegNum is unset. 44 } 45 46 // A Var represents a local variable or a function parameter. 47 type Var struct { 48 Name string 49 Abbrev int // Either DW_ABRV_AUTO or DW_ABRV_PARAM 50 StackOffset int32 51 LocationList []Location 52 Scope int32 53 Type Sym 54 } 55 56 // A Scope represents a lexical scope. All variables declared within a 57 // scope will only be visible to instructions covered by the scope. 58 // Lexical scopes are contiguous in source files but can end up being 59 // compiled to discontiguous blocks of instructions in the executable. 60 // The Ranges field lists all the blocks of instructions that belong 61 // in this scope. 62 type Scope struct { 63 Parent int32 64 Ranges []Range 65 Vars []*Var 66 } 67 68 // A Range represents a half-open interval [Start, End). 69 type Range struct { 70 Start, End int64 71 } 72 73 // UnifyRanges merges the list of ranges of c into the list of ranges of s 74 func (s *Scope) UnifyRanges(c *Scope) { 75 out := make([]Range, 0, len(s.Ranges)+len(c.Ranges)) 76 77 i, j := 0, 0 78 for { 79 var cur Range 80 if i < len(s.Ranges) && j < len(c.Ranges) { 81 if s.Ranges[i].Start < c.Ranges[j].Start { 82 cur = s.Ranges[i] 83 i++ 84 } else { 85 cur = c.Ranges[j] 86 j++ 87 } 88 } else if i < len(s.Ranges) { 89 cur = s.Ranges[i] 90 i++ 91 } else if j < len(c.Ranges) { 92 cur = c.Ranges[j] 93 j++ 94 } else { 95 break 96 } 97 98 if n := len(out); n > 0 && cur.Start <= out[n-1].End { 99 out[n-1].End = cur.End 100 } else { 101 out = append(out, cur) 102 } 103 } 104 105 s.Ranges = out 106 } 107 108 // A Context specifies how to add data to a Sym. 109 type Context interface { 110 PtrSize() int 111 AddInt(s Sym, size int, i int64) 112 AddBytes(s Sym, b []byte) 113 AddAddress(s Sym, t interface{}, ofs int64) 114 AddSectionOffset(s Sym, size int, t interface{}, ofs int64) 115 AddString(s Sym, v string) 116 SymValue(s Sym) int64 117 } 118 119 // AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding. 120 func AppendUleb128(b []byte, v uint64) []byte { 121 for { 122 c := uint8(v & 0x7f) 123 v >>= 7 124 if v != 0 { 125 c |= 0x80 126 } 127 b = append(b, c) 128 if c&0x80 == 0 { 129 break 130 } 131 } 132 return b 133 } 134 135 // AppendSleb128 appends v to b using DWARF's signed LEB128 encoding. 136 func AppendSleb128(b []byte, v int64) []byte { 137 for { 138 c := uint8(v & 0x7f) 139 s := uint8(v & 0x40) 140 v >>= 7 141 if (v != -1 || s == 0) && (v != 0 || s != 0) { 142 c |= 0x80 143 } 144 b = append(b, c) 145 if c&0x80 == 0 { 146 break 147 } 148 } 149 return b 150 } 151 152 // sevenbits contains all unsigned seven bit numbers, indexed by their value. 153 var sevenbits = [...]byte{ 154 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 155 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 156 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 157 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 158 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 159 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 160 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 161 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 162 } 163 164 // sevenBitU returns the unsigned LEB128 encoding of v if v is seven bits and nil otherwise. 165 // The contents of the returned slice must not be modified. 166 func sevenBitU(v int64) []byte { 167 if uint64(v) < uint64(len(sevenbits)) { 168 return sevenbits[v : v+1] 169 } 170 return nil 171 } 172 173 // sevenBitS returns the signed LEB128 encoding of v if v is seven bits and nil otherwise. 174 // The contents of the returned slice must not be modified. 175 func sevenBitS(v int64) []byte { 176 if uint64(v) <= 63 { 177 return sevenbits[v : v+1] 178 } 179 if uint64(-v) <= 64 { 180 return sevenbits[128+v : 128+v+1] 181 } 182 return nil 183 } 184 185 // Uleb128put appends v to s using DWARF's unsigned LEB128 encoding. 186 func Uleb128put(ctxt Context, s Sym, v int64) { 187 b := sevenBitU(v) 188 if b == nil { 189 var encbuf [20]byte 190 b = AppendUleb128(encbuf[:0], uint64(v)) 191 } 192 ctxt.AddBytes(s, b) 193 } 194 195 // Sleb128put appends v to s using DWARF's signed LEB128 encoding. 196 func Sleb128put(ctxt Context, s Sym, v int64) { 197 b := sevenBitS(v) 198 if b == nil { 199 var encbuf [20]byte 200 b = AppendSleb128(encbuf[:0], v) 201 } 202 ctxt.AddBytes(s, b) 203 } 204 205 /* 206 * Defining Abbrevs. This is hardcoded, and there will be 207 * only a handful of them. The DWARF spec places no restriction on 208 * the ordering of attributes in the Abbrevs and DIEs, and we will 209 * always write them out in the order of declaration in the abbrev. 210 */ 211 type dwAttrForm struct { 212 attr uint16 213 form uint8 214 } 215 216 // Go-specific type attributes. 217 const ( 218 DW_AT_go_kind = 0x2900 219 DW_AT_go_key = 0x2901 220 DW_AT_go_elem = 0x2902 221 // Attribute for DW_TAG_member of a struct type. 222 // Nonzero value indicates the struct field is an embedded field. 223 DW_AT_go_embedded_field = 0x2903 224 225 DW_AT_internal_location = 253 // params and locals; not emitted 226 ) 227 228 // Index into the abbrevs table below. 229 // Keep in sync with ispubname() and ispubtype() in ld/dwarf.go. 230 // ispubtype considers >= NULLTYPE public 231 const ( 232 DW_ABRV_NULL = iota 233 DW_ABRV_COMPUNIT 234 DW_ABRV_FUNCTION 235 DW_ABRV_VARIABLE 236 DW_ABRV_AUTO 237 DW_ABRV_AUTO_LOCLIST 238 DW_ABRV_PARAM 239 DW_ABRV_PARAM_LOCLIST 240 DW_ABRV_LEXICAL_BLOCK_RANGES 241 DW_ABRV_LEXICAL_BLOCK_SIMPLE 242 DW_ABRV_STRUCTFIELD 243 DW_ABRV_FUNCTYPEPARAM 244 DW_ABRV_DOTDOTDOT 245 DW_ABRV_ARRAYRANGE 246 DW_ABRV_NULLTYPE 247 DW_ABRV_BASETYPE 248 DW_ABRV_ARRAYTYPE 249 DW_ABRV_CHANTYPE 250 DW_ABRV_FUNCTYPE 251 DW_ABRV_IFACETYPE 252 DW_ABRV_MAPTYPE 253 DW_ABRV_PTRTYPE 254 DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6. 255 DW_ABRV_SLICETYPE 256 DW_ABRV_STRINGTYPE 257 DW_ABRV_STRUCTTYPE 258 DW_ABRV_TYPEDECL 259 DW_NABRV 260 ) 261 262 type dwAbbrev struct { 263 tag uint8 264 children uint8 265 attr []dwAttrForm 266 } 267 268 var abbrevs = [DW_NABRV]dwAbbrev{ 269 /* The mandatory DW_ABRV_NULL entry. */ 270 {0, 0, []dwAttrForm{}}, 271 272 /* COMPUNIT */ 273 { 274 DW_TAG_compile_unit, 275 DW_CHILDREN_yes, 276 []dwAttrForm{ 277 {DW_AT_name, DW_FORM_string}, 278 {DW_AT_language, DW_FORM_data1}, 279 {DW_AT_low_pc, DW_FORM_addr}, 280 {DW_AT_high_pc, DW_FORM_addr}, 281 {DW_AT_stmt_list, DW_FORM_sec_offset}, 282 {DW_AT_comp_dir, DW_FORM_string}, 283 {DW_AT_producer, DW_FORM_string}, 284 }, 285 }, 286 287 /* FUNCTION */ 288 { 289 DW_TAG_subprogram, 290 DW_CHILDREN_yes, 291 []dwAttrForm{ 292 {DW_AT_name, DW_FORM_string}, 293 {DW_AT_low_pc, DW_FORM_addr}, 294 {DW_AT_high_pc, DW_FORM_addr}, 295 {DW_AT_frame_base, DW_FORM_block1}, 296 {DW_AT_external, DW_FORM_flag}, 297 }, 298 }, 299 300 /* VARIABLE */ 301 { 302 DW_TAG_variable, 303 DW_CHILDREN_no, 304 []dwAttrForm{ 305 {DW_AT_name, DW_FORM_string}, 306 {DW_AT_location, DW_FORM_block1}, 307 {DW_AT_type, DW_FORM_ref_addr}, 308 {DW_AT_external, DW_FORM_flag}, 309 }, 310 }, 311 312 /* AUTO */ 313 { 314 DW_TAG_variable, 315 DW_CHILDREN_no, 316 []dwAttrForm{ 317 {DW_AT_name, DW_FORM_string}, 318 {DW_AT_location, DW_FORM_block1}, 319 {DW_AT_type, DW_FORM_ref_addr}, 320 }, 321 }, 322 323 /* AUTO_LOCLIST */ 324 { 325 DW_TAG_variable, 326 DW_CHILDREN_no, 327 []dwAttrForm{ 328 {DW_AT_name, DW_FORM_string}, 329 {DW_AT_location, DW_FORM_sec_offset}, 330 {DW_AT_type, DW_FORM_ref_addr}, 331 }, 332 }, 333 334 /* PARAM */ 335 { 336 DW_TAG_formal_parameter, 337 DW_CHILDREN_no, 338 []dwAttrForm{ 339 {DW_AT_name, DW_FORM_string}, 340 {DW_AT_location, DW_FORM_block1}, 341 {DW_AT_type, DW_FORM_ref_addr}, 342 }, 343 }, 344 345 /* PARAM_LOCLIST */ 346 { 347 DW_TAG_formal_parameter, 348 DW_CHILDREN_no, 349 []dwAttrForm{ 350 {DW_AT_name, DW_FORM_string}, 351 {DW_AT_location, DW_FORM_sec_offset}, 352 {DW_AT_type, DW_FORM_ref_addr}, 353 }, 354 }, 355 356 /* LEXICAL_BLOCK_RANGES */ 357 { 358 DW_TAG_lexical_block, 359 DW_CHILDREN_yes, 360 []dwAttrForm{ 361 {DW_AT_ranges, DW_FORM_sec_offset}, 362 }, 363 }, 364 365 /* LEXICAL_BLOCK_SIMPLE */ 366 { 367 DW_TAG_lexical_block, 368 DW_CHILDREN_yes, 369 []dwAttrForm{ 370 {DW_AT_low_pc, DW_FORM_addr}, 371 {DW_AT_high_pc, DW_FORM_addr}, 372 }, 373 }, 374 375 /* STRUCTFIELD */ 376 { 377 DW_TAG_member, 378 DW_CHILDREN_no, 379 []dwAttrForm{ 380 {DW_AT_name, DW_FORM_string}, 381 {DW_AT_data_member_location, DW_FORM_block1}, 382 {DW_AT_type, DW_FORM_ref_addr}, 383 {DW_AT_go_embedded_field, DW_FORM_flag}, 384 }, 385 }, 386 387 /* FUNCTYPEPARAM */ 388 { 389 DW_TAG_formal_parameter, 390 DW_CHILDREN_no, 391 392 // No name! 393 []dwAttrForm{ 394 {DW_AT_type, DW_FORM_ref_addr}, 395 }, 396 }, 397 398 /* DOTDOTDOT */ 399 { 400 DW_TAG_unspecified_parameters, 401 DW_CHILDREN_no, 402 []dwAttrForm{}, 403 }, 404 405 /* ARRAYRANGE */ 406 { 407 DW_TAG_subrange_type, 408 DW_CHILDREN_no, 409 410 // No name! 411 []dwAttrForm{ 412 {DW_AT_type, DW_FORM_ref_addr}, 413 {DW_AT_count, DW_FORM_udata}, 414 }, 415 }, 416 417 // Below here are the types considered public by ispubtype 418 /* NULLTYPE */ 419 { 420 DW_TAG_unspecified_type, 421 DW_CHILDREN_no, 422 []dwAttrForm{ 423 {DW_AT_name, DW_FORM_string}, 424 }, 425 }, 426 427 /* BASETYPE */ 428 { 429 DW_TAG_base_type, 430 DW_CHILDREN_no, 431 []dwAttrForm{ 432 {DW_AT_name, DW_FORM_string}, 433 {DW_AT_encoding, DW_FORM_data1}, 434 {DW_AT_byte_size, DW_FORM_data1}, 435 {DW_AT_go_kind, DW_FORM_data1}, 436 }, 437 }, 438 439 /* ARRAYTYPE */ 440 // child is subrange with upper bound 441 { 442 DW_TAG_array_type, 443 DW_CHILDREN_yes, 444 []dwAttrForm{ 445 {DW_AT_name, DW_FORM_string}, 446 {DW_AT_type, DW_FORM_ref_addr}, 447 {DW_AT_byte_size, DW_FORM_udata}, 448 {DW_AT_go_kind, DW_FORM_data1}, 449 }, 450 }, 451 452 /* CHANTYPE */ 453 { 454 DW_TAG_typedef, 455 DW_CHILDREN_no, 456 []dwAttrForm{ 457 {DW_AT_name, DW_FORM_string}, 458 {DW_AT_type, DW_FORM_ref_addr}, 459 {DW_AT_go_kind, DW_FORM_data1}, 460 {DW_AT_go_elem, DW_FORM_ref_addr}, 461 }, 462 }, 463 464 /* FUNCTYPE */ 465 { 466 DW_TAG_subroutine_type, 467 DW_CHILDREN_yes, 468 []dwAttrForm{ 469 {DW_AT_name, DW_FORM_string}, 470 {DW_AT_byte_size, DW_FORM_udata}, 471 // {DW_AT_type, DW_FORM_ref_addr}, 472 {DW_AT_go_kind, DW_FORM_data1}, 473 }, 474 }, 475 476 /* IFACETYPE */ 477 { 478 DW_TAG_typedef, 479 DW_CHILDREN_yes, 480 []dwAttrForm{ 481 {DW_AT_name, DW_FORM_string}, 482 {DW_AT_type, DW_FORM_ref_addr}, 483 {DW_AT_go_kind, DW_FORM_data1}, 484 }, 485 }, 486 487 /* MAPTYPE */ 488 { 489 DW_TAG_typedef, 490 DW_CHILDREN_no, 491 []dwAttrForm{ 492 {DW_AT_name, DW_FORM_string}, 493 {DW_AT_type, DW_FORM_ref_addr}, 494 {DW_AT_go_kind, DW_FORM_data1}, 495 {DW_AT_go_key, DW_FORM_ref_addr}, 496 {DW_AT_go_elem, DW_FORM_ref_addr}, 497 }, 498 }, 499 500 /* PTRTYPE */ 501 { 502 DW_TAG_pointer_type, 503 DW_CHILDREN_no, 504 []dwAttrForm{ 505 {DW_AT_name, DW_FORM_string}, 506 {DW_AT_type, DW_FORM_ref_addr}, 507 {DW_AT_go_kind, DW_FORM_data1}, 508 }, 509 }, 510 511 /* BARE_PTRTYPE */ 512 { 513 DW_TAG_pointer_type, 514 DW_CHILDREN_no, 515 []dwAttrForm{ 516 {DW_AT_name, DW_FORM_string}, 517 }, 518 }, 519 520 /* SLICETYPE */ 521 { 522 DW_TAG_structure_type, 523 DW_CHILDREN_yes, 524 []dwAttrForm{ 525 {DW_AT_name, DW_FORM_string}, 526 {DW_AT_byte_size, DW_FORM_udata}, 527 {DW_AT_go_kind, DW_FORM_data1}, 528 {DW_AT_go_elem, DW_FORM_ref_addr}, 529 }, 530 }, 531 532 /* STRINGTYPE */ 533 { 534 DW_TAG_structure_type, 535 DW_CHILDREN_yes, 536 []dwAttrForm{ 537 {DW_AT_name, DW_FORM_string}, 538 {DW_AT_byte_size, DW_FORM_udata}, 539 {DW_AT_go_kind, DW_FORM_data1}, 540 }, 541 }, 542 543 /* STRUCTTYPE */ 544 { 545 DW_TAG_structure_type, 546 DW_CHILDREN_yes, 547 []dwAttrForm{ 548 {DW_AT_name, DW_FORM_string}, 549 {DW_AT_byte_size, DW_FORM_udata}, 550 {DW_AT_go_kind, DW_FORM_data1}, 551 }, 552 }, 553 554 /* TYPEDECL */ 555 { 556 DW_TAG_typedef, 557 DW_CHILDREN_no, 558 []dwAttrForm{ 559 {DW_AT_name, DW_FORM_string}, 560 {DW_AT_type, DW_FORM_ref_addr}, 561 }, 562 }, 563 } 564 565 // GetAbbrev returns the contents of the .debug_abbrev section. 566 func GetAbbrev() []byte { 567 var buf []byte 568 for i := 1; i < DW_NABRV; i++ { 569 // See section 7.5.3 570 buf = AppendUleb128(buf, uint64(i)) 571 buf = AppendUleb128(buf, uint64(abbrevs[i].tag)) 572 buf = append(buf, byte(abbrevs[i].children)) 573 for _, f := range abbrevs[i].attr { 574 buf = AppendUleb128(buf, uint64(f.attr)) 575 buf = AppendUleb128(buf, uint64(f.form)) 576 } 577 buf = append(buf, 0, 0) 578 } 579 return append(buf, 0) 580 } 581 582 /* 583 * Debugging Information Entries and their attributes. 584 */ 585 586 // DWAttr represents an attribute of a DWDie. 587 // 588 // For DW_CLS_string and _block, value should contain the length, and 589 // data the data, for _reference, value is 0 and data is a DWDie* to 590 // the referenced instance, for all others, value is the whole thing 591 // and data is null. 592 type DWAttr struct { 593 Link *DWAttr 594 Atr uint16 // DW_AT_ 595 Cls uint8 // DW_CLS_ 596 Value int64 597 Data interface{} 598 } 599 600 // DWDie represents a DWARF debug info entry. 601 type DWDie struct { 602 Abbrev int 603 Link *DWDie 604 Child *DWDie 605 Attr *DWAttr 606 Sym Sym 607 } 608 609 func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error { 610 switch form { 611 case DW_FORM_addr: // address 612 ctxt.AddAddress(s, data, value) 613 614 case DW_FORM_block1: // block 615 if cls == DW_CLS_ADDRESS { 616 ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize())) 617 ctxt.AddInt(s, 1, DW_OP_addr) 618 ctxt.AddAddress(s, data, 0) 619 break 620 } 621 622 value &= 0xff 623 ctxt.AddInt(s, 1, value) 624 p := data.([]byte)[:value] 625 ctxt.AddBytes(s, p) 626 627 case DW_FORM_block2: // block 628 value &= 0xffff 629 630 ctxt.AddInt(s, 2, value) 631 p := data.([]byte)[:value] 632 ctxt.AddBytes(s, p) 633 634 case DW_FORM_block4: // block 635 value &= 0xffffffff 636 637 ctxt.AddInt(s, 4, value) 638 p := data.([]byte)[:value] 639 ctxt.AddBytes(s, p) 640 641 case DW_FORM_block: // block 642 Uleb128put(ctxt, s, value) 643 644 p := data.([]byte)[:value] 645 ctxt.AddBytes(s, p) 646 647 case DW_FORM_data1: // constant 648 ctxt.AddInt(s, 1, value) 649 650 case DW_FORM_data2: // constant 651 ctxt.AddInt(s, 2, value) 652 653 case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr 654 if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges 655 ctxt.AddSectionOffset(s, 4, data, value) 656 break 657 } 658 ctxt.AddInt(s, 4, value) 659 660 case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr 661 ctxt.AddInt(s, 8, value) 662 663 case DW_FORM_sdata: // constant 664 Sleb128put(ctxt, s, value) 665 666 case DW_FORM_udata: // constant 667 Uleb128put(ctxt, s, value) 668 669 case DW_FORM_string: // string 670 str := data.(string) 671 ctxt.AddString(s, str) 672 // TODO(ribrdb): verify padded strings are never used and remove this 673 for i := int64(len(str)); i < value; i++ { 674 ctxt.AddInt(s, 1, 0) 675 } 676 677 case DW_FORM_flag: // flag 678 if value != 0 { 679 ctxt.AddInt(s, 1, 1) 680 } else { 681 ctxt.AddInt(s, 1, 0) 682 } 683 684 // As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large 685 // (> 4 GB of debug info aka "64-bit") unit, which we don't implement. 686 case DW_FORM_ref_addr: // reference to a DIE in the .info section 687 fallthrough 688 case DW_FORM_sec_offset: // offset into a DWARF section other than .info 689 if data == nil { 690 return fmt.Errorf("dwarf: null reference in %d", abbrev) 691 } 692 ctxt.AddSectionOffset(s, 4, data, value) 693 694 case DW_FORM_ref1, // reference within the compilation unit 695 DW_FORM_ref2, // reference 696 DW_FORM_ref4, // reference 697 DW_FORM_ref8, // reference 698 DW_FORM_ref_udata, // reference 699 700 DW_FORM_strp, // string 701 DW_FORM_indirect: // (see Section 7.5.3) 702 fallthrough 703 default: 704 return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls) 705 } 706 return nil 707 } 708 709 // PutAttrs writes the attributes for a DIE to symbol 's'. 710 // 711 // Note that we can (and do) add arbitrary attributes to a DIE, but 712 // only the ones actually listed in the Abbrev will be written out. 713 func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) { 714 Outer: 715 for _, f := range abbrevs[abbrev].attr { 716 for ap := attr; ap != nil; ap = ap.Link { 717 if ap.Atr == f.attr { 718 putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data) 719 continue Outer 720 } 721 } 722 723 putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil) 724 } 725 } 726 727 // HasChildren returns true if 'die' uses an abbrev that supports children. 728 func HasChildren(die *DWDie) bool { 729 return abbrevs[die.Abbrev].children != 0 730 } 731 732 // PutFunc writes a DIE for a function to s. 733 // It also writes child DIEs for each variable in vars. 734 func PutFunc(ctxt Context, info, loc, ranges Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error { 735 Uleb128put(ctxt, info, DW_ABRV_FUNCTION) 736 putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) 737 putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, 0, startPC) 738 putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, size, startPC) 739 putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) 740 var ev int64 741 if external { 742 ev = 1 743 } 744 putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_flag, DW_CLS_FLAG, ev, 0) 745 if len(scopes) > 0 { 746 var encbuf [20]byte 747 if putscope(ctxt, info, loc, ranges, startPC, 0, scopes, encbuf[:0]) < int32(len(scopes)) { 748 return errors.New("multiple toplevel scopes") 749 } 750 } 751 Uleb128put(ctxt, info, 0) 752 return nil 753 } 754 755 func putscope(ctxt Context, info, loc, ranges, startPC Sym, curscope int32, scopes []Scope, encbuf []byte) int32 { 756 for _, v := range scopes[curscope].Vars { 757 putvar(ctxt, info, loc, v, startPC, encbuf) 758 } 759 this := curscope 760 curscope++ 761 for curscope < int32(len(scopes)) { 762 scope := scopes[curscope] 763 if scope.Parent != this { 764 return curscope 765 } 766 767 if len(scope.Ranges) == 1 { 768 Uleb128put(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE) 769 putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, startPC) 770 putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, startPC) 771 } else { 772 Uleb128put(ctxt, info, DW_ABRV_LEXICAL_BLOCK_RANGES) 773 putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, ranges.Len(), ranges) 774 775 ctxt.AddAddress(ranges, nil, -1) 776 ctxt.AddAddress(ranges, startPC, 0) 777 for _, r := range scope.Ranges { 778 ctxt.AddAddress(ranges, nil, r.Start) 779 ctxt.AddAddress(ranges, nil, r.End) 780 } 781 ctxt.AddAddress(ranges, nil, 0) 782 ctxt.AddAddress(ranges, nil, 0) 783 } 784 785 curscope = putscope(ctxt, info, loc, ranges, startPC, curscope, scopes, encbuf) 786 787 Uleb128put(ctxt, info, 0) 788 } 789 return curscope 790 } 791 792 func putvar(ctxt Context, info, loc Sym, v *Var, startPC Sym, encbuf []byte) { 793 n := v.Name 794 795 Uleb128put(ctxt, info, int64(v.Abbrev)) 796 putattr(ctxt, info, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) 797 if v.Abbrev == DW_ABRV_AUTO_LOCLIST || v.Abbrev == DW_ABRV_PARAM_LOCLIST { 798 putattr(ctxt, info, v.Abbrev, DW_FORM_sec_offset, DW_CLS_PTR, int64(loc.Len()), loc) 799 addLocList(ctxt, loc, startPC, v, encbuf) 800 } else { 801 loc := append(encbuf[:0], DW_OP_call_frame_cfa) 802 if v.StackOffset != 0 { 803 loc = append(loc, DW_OP_consts) 804 loc = AppendSleb128(loc, int64(v.StackOffset)) 805 loc = append(loc, DW_OP_plus) 806 } 807 putattr(ctxt, info, v.Abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) 808 } 809 putattr(ctxt, info, v.Abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) 810 } 811 812 func addLocList(ctxt Context, listSym, startPC Sym, v *Var, encbuf []byte) { 813 // Base address entry: max ptr followed by the base address. 814 ctxt.AddInt(listSym, ctxt.PtrSize(), ^0) 815 ctxt.AddAddress(listSym, startPC, 0) 816 for _, entry := range v.LocationList { 817 ctxt.AddInt(listSym, ctxt.PtrSize(), entry.StartPC) 818 ctxt.AddInt(listSym, ctxt.PtrSize(), entry.EndPC) 819 locBuf := encbuf[:0] 820 for _, piece := range entry.Pieces { 821 if !piece.Missing { 822 if piece.OnStack { 823 locBuf = append(locBuf, DW_OP_fbreg) 824 locBuf = AppendSleb128(locBuf, int64(piece.StackOffset)) 825 } else { 826 if piece.RegNum < 32 { 827 locBuf = append(locBuf, DW_OP_reg0+byte(piece.RegNum)) 828 } else { 829 locBuf = append(locBuf, DW_OP_regx) 830 locBuf = AppendUleb128(locBuf, uint64(piece.RegNum)) 831 } 832 } 833 } 834 if len(entry.Pieces) > 1 { 835 locBuf = append(locBuf, DW_OP_piece) 836 locBuf = AppendUleb128(locBuf, uint64(piece.Length)) 837 } 838 } 839 ctxt.AddInt(listSym, 2, int64(len(locBuf))) 840 ctxt.AddBytes(listSym, locBuf) 841 } 842 // End list 843 ctxt.AddInt(listSym, ctxt.PtrSize(), 0) 844 ctxt.AddInt(listSym, ctxt.PtrSize(), 0) 845 } 846 847 // VarsByOffset attaches the methods of sort.Interface to []*Var, 848 // sorting in increasing StackOffset. 849 type VarsByOffset []*Var 850 851 func (s VarsByOffset) Len() int { return len(s) } 852 func (s VarsByOffset) Less(i, j int) bool { return s[i].StackOffset < s[j].StackOffset } 853 func (s VarsByOffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] }