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