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