github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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 "cmd/internal/objabi" 12 "errors" 13 "fmt" 14 "sort" 15 "strings" 16 ) 17 18 // InfoPrefix is the prefix for all the symbols containing DWARF info entries. 19 const InfoPrefix = "go.info." 20 21 // RangePrefix is the prefix for all the symbols containing DWARF location lists. 22 const LocPrefix = "go.loc." 23 24 // RangePrefix is the prefix for all the symbols containing DWARF range lists. 25 const RangePrefix = "go.range." 26 27 // IsStmtPrefix is the prefix for all the symbols containing DWARF is_stmt info for the line number table. 28 const IsStmtPrefix = "go.isstmt." 29 30 // ConstInfoPrefix is the prefix for all symbols containing DWARF info 31 // entries that contain constants. 32 const ConstInfoPrefix = "go.constinfo." 33 34 // CUInfoPrefix is the prefix for symbols containing information to 35 // populate the DWARF compilation unit info entries. 36 const CUInfoPrefix = "go.cuinfo." 37 38 // Used to form the symbol name assigned to the DWARF 'abstract subprogram" 39 // info entry for a function 40 const AbstractFuncSuffix = "$abstract" 41 42 // Controls logging/debugging for selected aspects of DWARF subprogram 43 // generation (functions, scopes). 44 var logDwarf bool 45 46 // Sym represents a symbol. 47 type Sym interface { 48 Len() int64 49 } 50 51 // A Var represents a local variable or a function parameter. 52 type Var struct { 53 Name string 54 Abbrev int // Either DW_ABRV_AUTO[_LOCLIST] or DW_ABRV_PARAM[_LOCLIST] 55 IsReturnValue bool 56 IsInlFormal bool 57 StackOffset int32 58 // This package can't use the ssa package, so it can't mention ssa.FuncDebug, 59 // so indirect through a closure. 60 PutLocationList func(listSym, startPC Sym) 61 Scope int32 62 Type Sym 63 DeclFile string 64 DeclLine uint 65 DeclCol uint 66 InlIndex int32 // subtract 1 to form real index into InlTree 67 ChildIndex int32 // child DIE index in abstract function 68 IsInAbstract bool // variable exists in abstract function 69 } 70 71 // A Scope represents a lexical scope. All variables declared within a 72 // scope will only be visible to instructions covered by the scope. 73 // Lexical scopes are contiguous in source files but can end up being 74 // compiled to discontiguous blocks of instructions in the executable. 75 // The Ranges field lists all the blocks of instructions that belong 76 // in this scope. 77 type Scope struct { 78 Parent int32 79 Ranges []Range 80 Vars []*Var 81 } 82 83 // A Range represents a half-open interval [Start, End). 84 type Range struct { 85 Start, End int64 86 } 87 88 // This container is used by the PutFunc* variants below when 89 // creating the DWARF subprogram DIE(s) for a function. 90 type FnState struct { 91 Name string 92 Importpath string 93 Info Sym 94 Filesym Sym 95 Loc Sym 96 Ranges Sym 97 Absfn Sym 98 StartPC Sym 99 Size int64 100 External bool 101 Scopes []Scope 102 InlCalls InlCalls 103 } 104 105 func EnableLogging(doit bool) { 106 logDwarf = doit 107 } 108 109 // UnifyRanges merges the list of ranges of c into the list of ranges of s 110 func (s *Scope) UnifyRanges(c *Scope) { 111 out := make([]Range, 0, len(s.Ranges)+len(c.Ranges)) 112 113 i, j := 0, 0 114 for { 115 var cur Range 116 if i < len(s.Ranges) && j < len(c.Ranges) { 117 if s.Ranges[i].Start < c.Ranges[j].Start { 118 cur = s.Ranges[i] 119 i++ 120 } else { 121 cur = c.Ranges[j] 122 j++ 123 } 124 } else if i < len(s.Ranges) { 125 cur = s.Ranges[i] 126 i++ 127 } else if j < len(c.Ranges) { 128 cur = c.Ranges[j] 129 j++ 130 } else { 131 break 132 } 133 134 if n := len(out); n > 0 && cur.Start <= out[n-1].End { 135 out[n-1].End = cur.End 136 } else { 137 out = append(out, cur) 138 } 139 } 140 141 s.Ranges = out 142 } 143 144 type InlCalls struct { 145 Calls []InlCall 146 } 147 148 type InlCall struct { 149 // index into ctx.InlTree describing the call inlined here 150 InlIndex int 151 152 // Symbol of file containing inlined call site (really *obj.LSym). 153 CallFile Sym 154 155 // Line number of inlined call site. 156 CallLine uint32 157 158 // Dwarf abstract subroutine symbol (really *obj.LSym). 159 AbsFunSym Sym 160 161 // Indices of child inlines within Calls array above. 162 Children []int 163 164 // entries in this list are PAUTO's created by the inliner to 165 // capture the promoted formals and locals of the inlined callee. 166 InlVars []*Var 167 168 // PC ranges for this inlined call. 169 Ranges []Range 170 171 // Root call (not a child of some other call). 172 Root bool 173 } 174 175 // A Context specifies how to add data to a Sym. 176 type Context interface { 177 PtrSize() int 178 AddInt(s Sym, size int, i int64) 179 AddBytes(s Sym, b []byte) 180 AddAddress(s Sym, t interface{}, ofs int64) 181 AddSectionOffset(s Sym, size int, t interface{}, ofs int64) 182 AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64) 183 CurrentOffset(s Sym) int64 184 RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int) 185 RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32) 186 AddString(s Sym, v string) 187 AddFileRef(s Sym, f interface{}) 188 Logf(format string, args ...interface{}) 189 } 190 191 // AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding. 192 func AppendUleb128(b []byte, v uint64) []byte { 193 for { 194 c := uint8(v & 0x7f) 195 v >>= 7 196 if v != 0 { 197 c |= 0x80 198 } 199 b = append(b, c) 200 if c&0x80 == 0 { 201 break 202 } 203 } 204 return b 205 } 206 207 // AppendSleb128 appends v to b using DWARF's signed LEB128 encoding. 208 func AppendSleb128(b []byte, v int64) []byte { 209 for { 210 c := uint8(v & 0x7f) 211 s := uint8(v & 0x40) 212 v >>= 7 213 if (v != -1 || s == 0) && (v != 0 || s != 0) { 214 c |= 0x80 215 } 216 b = append(b, c) 217 if c&0x80 == 0 { 218 break 219 } 220 } 221 return b 222 } 223 224 // sevenbits contains all unsigned seven bit numbers, indexed by their value. 225 var sevenbits = [...]byte{ 226 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 227 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 228 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 229 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 230 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 231 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 232 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 233 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 234 } 235 236 // sevenBitU returns the unsigned LEB128 encoding of v if v is seven bits and nil otherwise. 237 // The contents of the returned slice must not be modified. 238 func sevenBitU(v int64) []byte { 239 if uint64(v) < uint64(len(sevenbits)) { 240 return sevenbits[v : v+1] 241 } 242 return nil 243 } 244 245 // sevenBitS returns the signed LEB128 encoding of v if v is seven bits and nil otherwise. 246 // The contents of the returned slice must not be modified. 247 func sevenBitS(v int64) []byte { 248 if uint64(v) <= 63 { 249 return sevenbits[v : v+1] 250 } 251 if uint64(-v) <= 64 { 252 return sevenbits[128+v : 128+v+1] 253 } 254 return nil 255 } 256 257 // Uleb128put appends v to s using DWARF's unsigned LEB128 encoding. 258 func Uleb128put(ctxt Context, s Sym, v int64) { 259 b := sevenBitU(v) 260 if b == nil { 261 var encbuf [20]byte 262 b = AppendUleb128(encbuf[:0], uint64(v)) 263 } 264 ctxt.AddBytes(s, b) 265 } 266 267 // Sleb128put appends v to s using DWARF's signed LEB128 encoding. 268 func Sleb128put(ctxt Context, s Sym, v int64) { 269 b := sevenBitS(v) 270 if b == nil { 271 var encbuf [20]byte 272 b = AppendSleb128(encbuf[:0], v) 273 } 274 ctxt.AddBytes(s, b) 275 } 276 277 /* 278 * Defining Abbrevs. This is hardcoded, and there will be 279 * only a handful of them. The DWARF spec places no restriction on 280 * the ordering of attributes in the Abbrevs and DIEs, and we will 281 * always write them out in the order of declaration in the abbrev. 282 */ 283 type dwAttrForm struct { 284 attr uint16 285 form uint8 286 } 287 288 // Go-specific type attributes. 289 const ( 290 DW_AT_go_kind = 0x2900 291 DW_AT_go_key = 0x2901 292 DW_AT_go_elem = 0x2902 293 // Attribute for DW_TAG_member of a struct type. 294 // Nonzero value indicates the struct field is an embedded field. 295 DW_AT_go_embedded_field = 0x2903 296 DW_AT_go_runtime_type = 0x2904 297 298 DW_AT_internal_location = 253 // params and locals; not emitted 299 ) 300 301 // Index into the abbrevs table below. 302 // Keep in sync with ispubname() and ispubtype() in ld/dwarf.go. 303 // ispubtype considers >= NULLTYPE public 304 const ( 305 DW_ABRV_NULL = iota 306 DW_ABRV_COMPUNIT 307 DW_ABRV_COMPUNIT_TEXTLESS 308 DW_ABRV_FUNCTION 309 DW_ABRV_FUNCTION_ABSTRACT 310 DW_ABRV_FUNCTION_CONCRETE 311 DW_ABRV_INLINED_SUBROUTINE 312 DW_ABRV_INLINED_SUBROUTINE_RANGES 313 DW_ABRV_VARIABLE 314 DW_ABRV_INT_CONSTANT 315 DW_ABRV_AUTO 316 DW_ABRV_AUTO_LOCLIST 317 DW_ABRV_AUTO_ABSTRACT 318 DW_ABRV_AUTO_CONCRETE 319 DW_ABRV_AUTO_CONCRETE_LOCLIST 320 DW_ABRV_PARAM 321 DW_ABRV_PARAM_LOCLIST 322 DW_ABRV_PARAM_ABSTRACT 323 DW_ABRV_PARAM_CONCRETE 324 DW_ABRV_PARAM_CONCRETE_LOCLIST 325 DW_ABRV_LEXICAL_BLOCK_RANGES 326 DW_ABRV_LEXICAL_BLOCK_SIMPLE 327 DW_ABRV_STRUCTFIELD 328 DW_ABRV_FUNCTYPEPARAM 329 DW_ABRV_DOTDOTDOT 330 DW_ABRV_ARRAYRANGE 331 DW_ABRV_NULLTYPE 332 DW_ABRV_BASETYPE 333 DW_ABRV_ARRAYTYPE 334 DW_ABRV_CHANTYPE 335 DW_ABRV_FUNCTYPE 336 DW_ABRV_IFACETYPE 337 DW_ABRV_MAPTYPE 338 DW_ABRV_PTRTYPE 339 DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6. 340 DW_ABRV_SLICETYPE 341 DW_ABRV_STRINGTYPE 342 DW_ABRV_STRUCTTYPE 343 DW_ABRV_TYPEDECL 344 DW_NABRV 345 ) 346 347 type dwAbbrev struct { 348 tag uint8 349 children uint8 350 attr []dwAttrForm 351 } 352 353 var abbrevs = [DW_NABRV]dwAbbrev{ 354 /* The mandatory DW_ABRV_NULL entry. */ 355 {0, 0, []dwAttrForm{}}, 356 357 /* COMPUNIT */ 358 { 359 DW_TAG_compile_unit, 360 DW_CHILDREN_yes, 361 []dwAttrForm{ 362 {DW_AT_name, DW_FORM_string}, 363 {DW_AT_language, DW_FORM_data1}, 364 {DW_AT_stmt_list, DW_FORM_sec_offset}, 365 {DW_AT_low_pc, DW_FORM_addr}, 366 {DW_AT_ranges, DW_FORM_sec_offset}, 367 {DW_AT_comp_dir, DW_FORM_string}, 368 {DW_AT_producer, DW_FORM_string}, 369 }, 370 }, 371 372 /* COMPUNIT_TEXTLESS */ 373 { 374 DW_TAG_compile_unit, 375 DW_CHILDREN_yes, 376 []dwAttrForm{ 377 {DW_AT_name, DW_FORM_string}, 378 {DW_AT_language, DW_FORM_data1}, 379 {DW_AT_comp_dir, DW_FORM_string}, 380 {DW_AT_producer, DW_FORM_string}, 381 }, 382 }, 383 384 /* FUNCTION */ 385 { 386 DW_TAG_subprogram, 387 DW_CHILDREN_yes, 388 []dwAttrForm{ 389 {DW_AT_name, DW_FORM_string}, 390 {DW_AT_low_pc, DW_FORM_addr}, 391 {DW_AT_high_pc, DW_FORM_addr}, 392 {DW_AT_frame_base, DW_FORM_block1}, 393 {DW_AT_decl_file, DW_FORM_data4}, 394 {DW_AT_external, DW_FORM_flag}, 395 }, 396 }, 397 398 /* FUNCTION_ABSTRACT */ 399 { 400 DW_TAG_subprogram, 401 DW_CHILDREN_yes, 402 []dwAttrForm{ 403 {DW_AT_name, DW_FORM_string}, 404 {DW_AT_inline, DW_FORM_data1}, 405 {DW_AT_external, DW_FORM_flag}, 406 }, 407 }, 408 409 /* FUNCTION_CONCRETE */ 410 { 411 DW_TAG_subprogram, 412 DW_CHILDREN_yes, 413 []dwAttrForm{ 414 {DW_AT_abstract_origin, DW_FORM_ref_addr}, 415 {DW_AT_low_pc, DW_FORM_addr}, 416 {DW_AT_high_pc, DW_FORM_addr}, 417 {DW_AT_frame_base, DW_FORM_block1}, 418 }, 419 }, 420 421 /* INLINED_SUBROUTINE */ 422 { 423 DW_TAG_inlined_subroutine, 424 DW_CHILDREN_yes, 425 []dwAttrForm{ 426 {DW_AT_abstract_origin, DW_FORM_ref_addr}, 427 {DW_AT_low_pc, DW_FORM_addr}, 428 {DW_AT_high_pc, DW_FORM_addr}, 429 {DW_AT_call_file, DW_FORM_data4}, 430 {DW_AT_call_line, DW_FORM_udata}, 431 }, 432 }, 433 434 /* INLINED_SUBROUTINE_RANGES */ 435 { 436 DW_TAG_inlined_subroutine, 437 DW_CHILDREN_yes, 438 []dwAttrForm{ 439 {DW_AT_abstract_origin, DW_FORM_ref_addr}, 440 {DW_AT_ranges, DW_FORM_sec_offset}, 441 {DW_AT_call_file, DW_FORM_data4}, 442 {DW_AT_call_line, DW_FORM_udata}, 443 }, 444 }, 445 446 /* VARIABLE */ 447 { 448 DW_TAG_variable, 449 DW_CHILDREN_no, 450 []dwAttrForm{ 451 {DW_AT_name, DW_FORM_string}, 452 {DW_AT_location, DW_FORM_block1}, 453 {DW_AT_type, DW_FORM_ref_addr}, 454 {DW_AT_external, DW_FORM_flag}, 455 }, 456 }, 457 458 /* INT CONSTANT */ 459 { 460 DW_TAG_constant, 461 DW_CHILDREN_no, 462 []dwAttrForm{ 463 {DW_AT_name, DW_FORM_string}, 464 {DW_AT_type, DW_FORM_ref_addr}, 465 {DW_AT_const_value, DW_FORM_sdata}, 466 }, 467 }, 468 469 /* AUTO */ 470 { 471 DW_TAG_variable, 472 DW_CHILDREN_no, 473 []dwAttrForm{ 474 {DW_AT_name, DW_FORM_string}, 475 {DW_AT_decl_line, DW_FORM_udata}, 476 {DW_AT_type, DW_FORM_ref_addr}, 477 {DW_AT_location, DW_FORM_block1}, 478 }, 479 }, 480 481 /* AUTO_LOCLIST */ 482 { 483 DW_TAG_variable, 484 DW_CHILDREN_no, 485 []dwAttrForm{ 486 {DW_AT_name, DW_FORM_string}, 487 {DW_AT_decl_line, DW_FORM_udata}, 488 {DW_AT_type, DW_FORM_ref_addr}, 489 {DW_AT_location, DW_FORM_sec_offset}, 490 }, 491 }, 492 493 /* AUTO_ABSTRACT */ 494 { 495 DW_TAG_variable, 496 DW_CHILDREN_no, 497 []dwAttrForm{ 498 {DW_AT_name, DW_FORM_string}, 499 {DW_AT_decl_line, DW_FORM_udata}, 500 {DW_AT_type, DW_FORM_ref_addr}, 501 }, 502 }, 503 504 /* AUTO_CONCRETE */ 505 { 506 DW_TAG_variable, 507 DW_CHILDREN_no, 508 []dwAttrForm{ 509 {DW_AT_abstract_origin, DW_FORM_ref_addr}, 510 {DW_AT_location, DW_FORM_block1}, 511 }, 512 }, 513 514 /* AUTO_CONCRETE_LOCLIST */ 515 { 516 DW_TAG_variable, 517 DW_CHILDREN_no, 518 []dwAttrForm{ 519 {DW_AT_abstract_origin, DW_FORM_ref_addr}, 520 {DW_AT_location, DW_FORM_sec_offset}, 521 }, 522 }, 523 524 /* PARAM */ 525 { 526 DW_TAG_formal_parameter, 527 DW_CHILDREN_no, 528 []dwAttrForm{ 529 {DW_AT_name, DW_FORM_string}, 530 {DW_AT_variable_parameter, DW_FORM_flag}, 531 {DW_AT_decl_line, DW_FORM_udata}, 532 {DW_AT_type, DW_FORM_ref_addr}, 533 {DW_AT_location, DW_FORM_block1}, 534 }, 535 }, 536 537 /* PARAM_LOCLIST */ 538 { 539 DW_TAG_formal_parameter, 540 DW_CHILDREN_no, 541 []dwAttrForm{ 542 {DW_AT_name, DW_FORM_string}, 543 {DW_AT_variable_parameter, DW_FORM_flag}, 544 {DW_AT_decl_line, DW_FORM_udata}, 545 {DW_AT_type, DW_FORM_ref_addr}, 546 {DW_AT_location, DW_FORM_sec_offset}, 547 }, 548 }, 549 550 /* PARAM_ABSTRACT */ 551 { 552 DW_TAG_formal_parameter, 553 DW_CHILDREN_no, 554 []dwAttrForm{ 555 {DW_AT_name, DW_FORM_string}, 556 {DW_AT_variable_parameter, DW_FORM_flag}, 557 {DW_AT_type, DW_FORM_ref_addr}, 558 }, 559 }, 560 561 /* PARAM_CONCRETE */ 562 { 563 DW_TAG_formal_parameter, 564 DW_CHILDREN_no, 565 []dwAttrForm{ 566 {DW_AT_abstract_origin, DW_FORM_ref_addr}, 567 {DW_AT_location, DW_FORM_block1}, 568 }, 569 }, 570 571 /* PARAM_CONCRETE_LOCLIST */ 572 { 573 DW_TAG_formal_parameter, 574 DW_CHILDREN_no, 575 []dwAttrForm{ 576 {DW_AT_abstract_origin, DW_FORM_ref_addr}, 577 {DW_AT_location, DW_FORM_sec_offset}, 578 }, 579 }, 580 581 /* LEXICAL_BLOCK_RANGES */ 582 { 583 DW_TAG_lexical_block, 584 DW_CHILDREN_yes, 585 []dwAttrForm{ 586 {DW_AT_ranges, DW_FORM_sec_offset}, 587 }, 588 }, 589 590 /* LEXICAL_BLOCK_SIMPLE */ 591 { 592 DW_TAG_lexical_block, 593 DW_CHILDREN_yes, 594 []dwAttrForm{ 595 {DW_AT_low_pc, DW_FORM_addr}, 596 {DW_AT_high_pc, DW_FORM_addr}, 597 }, 598 }, 599 600 /* STRUCTFIELD */ 601 { 602 DW_TAG_member, 603 DW_CHILDREN_no, 604 []dwAttrForm{ 605 {DW_AT_name, DW_FORM_string}, 606 {DW_AT_data_member_location, DW_FORM_udata}, 607 {DW_AT_type, DW_FORM_ref_addr}, 608 {DW_AT_go_embedded_field, DW_FORM_flag}, 609 }, 610 }, 611 612 /* FUNCTYPEPARAM */ 613 { 614 DW_TAG_formal_parameter, 615 DW_CHILDREN_no, 616 617 // No name! 618 []dwAttrForm{ 619 {DW_AT_type, DW_FORM_ref_addr}, 620 }, 621 }, 622 623 /* DOTDOTDOT */ 624 { 625 DW_TAG_unspecified_parameters, 626 DW_CHILDREN_no, 627 []dwAttrForm{}, 628 }, 629 630 /* ARRAYRANGE */ 631 { 632 DW_TAG_subrange_type, 633 DW_CHILDREN_no, 634 635 // No name! 636 []dwAttrForm{ 637 {DW_AT_type, DW_FORM_ref_addr}, 638 {DW_AT_count, DW_FORM_udata}, 639 }, 640 }, 641 642 // Below here are the types considered public by ispubtype 643 /* NULLTYPE */ 644 { 645 DW_TAG_unspecified_type, 646 DW_CHILDREN_no, 647 []dwAttrForm{ 648 {DW_AT_name, DW_FORM_string}, 649 }, 650 }, 651 652 /* BASETYPE */ 653 { 654 DW_TAG_base_type, 655 DW_CHILDREN_no, 656 []dwAttrForm{ 657 {DW_AT_name, DW_FORM_string}, 658 {DW_AT_encoding, DW_FORM_data1}, 659 {DW_AT_byte_size, DW_FORM_data1}, 660 {DW_AT_go_kind, DW_FORM_data1}, 661 {DW_AT_go_runtime_type, DW_FORM_addr}, 662 }, 663 }, 664 665 /* ARRAYTYPE */ 666 // child is subrange with upper bound 667 { 668 DW_TAG_array_type, 669 DW_CHILDREN_yes, 670 []dwAttrForm{ 671 {DW_AT_name, DW_FORM_string}, 672 {DW_AT_type, DW_FORM_ref_addr}, 673 {DW_AT_byte_size, DW_FORM_udata}, 674 {DW_AT_go_kind, DW_FORM_data1}, 675 {DW_AT_go_runtime_type, DW_FORM_addr}, 676 }, 677 }, 678 679 /* CHANTYPE */ 680 { 681 DW_TAG_typedef, 682 DW_CHILDREN_no, 683 []dwAttrForm{ 684 {DW_AT_name, DW_FORM_string}, 685 {DW_AT_type, DW_FORM_ref_addr}, 686 {DW_AT_go_kind, DW_FORM_data1}, 687 {DW_AT_go_runtime_type, DW_FORM_addr}, 688 {DW_AT_go_elem, DW_FORM_ref_addr}, 689 }, 690 }, 691 692 /* FUNCTYPE */ 693 { 694 DW_TAG_subroutine_type, 695 DW_CHILDREN_yes, 696 []dwAttrForm{ 697 {DW_AT_name, DW_FORM_string}, 698 {DW_AT_byte_size, DW_FORM_udata}, 699 {DW_AT_go_kind, DW_FORM_data1}, 700 {DW_AT_go_runtime_type, DW_FORM_addr}, 701 }, 702 }, 703 704 /* IFACETYPE */ 705 { 706 DW_TAG_typedef, 707 DW_CHILDREN_yes, 708 []dwAttrForm{ 709 {DW_AT_name, DW_FORM_string}, 710 {DW_AT_type, DW_FORM_ref_addr}, 711 {DW_AT_go_kind, DW_FORM_data1}, 712 {DW_AT_go_runtime_type, DW_FORM_addr}, 713 }, 714 }, 715 716 /* MAPTYPE */ 717 { 718 DW_TAG_typedef, 719 DW_CHILDREN_no, 720 []dwAttrForm{ 721 {DW_AT_name, DW_FORM_string}, 722 {DW_AT_type, DW_FORM_ref_addr}, 723 {DW_AT_go_kind, DW_FORM_data1}, 724 {DW_AT_go_runtime_type, DW_FORM_addr}, 725 {DW_AT_go_key, DW_FORM_ref_addr}, 726 {DW_AT_go_elem, DW_FORM_ref_addr}, 727 }, 728 }, 729 730 /* PTRTYPE */ 731 { 732 DW_TAG_pointer_type, 733 DW_CHILDREN_no, 734 []dwAttrForm{ 735 {DW_AT_name, DW_FORM_string}, 736 {DW_AT_type, DW_FORM_ref_addr}, 737 {DW_AT_go_kind, DW_FORM_data1}, 738 {DW_AT_go_runtime_type, DW_FORM_addr}, 739 }, 740 }, 741 742 /* BARE_PTRTYPE */ 743 { 744 DW_TAG_pointer_type, 745 DW_CHILDREN_no, 746 []dwAttrForm{ 747 {DW_AT_name, DW_FORM_string}, 748 }, 749 }, 750 751 /* SLICETYPE */ 752 { 753 DW_TAG_structure_type, 754 DW_CHILDREN_yes, 755 []dwAttrForm{ 756 {DW_AT_name, DW_FORM_string}, 757 {DW_AT_byte_size, DW_FORM_udata}, 758 {DW_AT_go_kind, DW_FORM_data1}, 759 {DW_AT_go_runtime_type, DW_FORM_addr}, 760 {DW_AT_go_elem, DW_FORM_ref_addr}, 761 }, 762 }, 763 764 /* STRINGTYPE */ 765 { 766 DW_TAG_structure_type, 767 DW_CHILDREN_yes, 768 []dwAttrForm{ 769 {DW_AT_name, DW_FORM_string}, 770 {DW_AT_byte_size, DW_FORM_udata}, 771 {DW_AT_go_kind, DW_FORM_data1}, 772 {DW_AT_go_runtime_type, DW_FORM_addr}, 773 }, 774 }, 775 776 /* STRUCTTYPE */ 777 { 778 DW_TAG_structure_type, 779 DW_CHILDREN_yes, 780 []dwAttrForm{ 781 {DW_AT_name, DW_FORM_string}, 782 {DW_AT_byte_size, DW_FORM_udata}, 783 {DW_AT_go_kind, DW_FORM_data1}, 784 {DW_AT_go_runtime_type, DW_FORM_addr}, 785 }, 786 }, 787 788 /* TYPEDECL */ 789 { 790 DW_TAG_typedef, 791 DW_CHILDREN_no, 792 []dwAttrForm{ 793 {DW_AT_name, DW_FORM_string}, 794 {DW_AT_type, DW_FORM_ref_addr}, 795 }, 796 }, 797 } 798 799 // GetAbbrev returns the contents of the .debug_abbrev section. 800 func GetAbbrev() []byte { 801 var buf []byte 802 for i := 1; i < DW_NABRV; i++ { 803 // See section 7.5.3 804 buf = AppendUleb128(buf, uint64(i)) 805 buf = AppendUleb128(buf, uint64(abbrevs[i].tag)) 806 buf = append(buf, abbrevs[i].children) 807 for _, f := range abbrevs[i].attr { 808 buf = AppendUleb128(buf, uint64(f.attr)) 809 buf = AppendUleb128(buf, uint64(f.form)) 810 } 811 buf = append(buf, 0, 0) 812 } 813 return append(buf, 0) 814 } 815 816 /* 817 * Debugging Information Entries and their attributes. 818 */ 819 820 // DWAttr represents an attribute of a DWDie. 821 // 822 // For DW_CLS_string and _block, value should contain the length, and 823 // data the data, for _reference, value is 0 and data is a DWDie* to 824 // the referenced instance, for all others, value is the whole thing 825 // and data is null. 826 type DWAttr struct { 827 Link *DWAttr 828 Atr uint16 // DW_AT_ 829 Cls uint8 // DW_CLS_ 830 Value int64 831 Data interface{} 832 } 833 834 // DWDie represents a DWARF debug info entry. 835 type DWDie struct { 836 Abbrev int 837 Link *DWDie 838 Child *DWDie 839 Attr *DWAttr 840 Sym Sym 841 } 842 843 func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error { 844 switch form { 845 case DW_FORM_addr: // address 846 // Allow nil addresses for DW_AT_go_runtime_type. 847 if data == nil && value == 0 { 848 ctxt.AddInt(s, ctxt.PtrSize(), 0) 849 break 850 } 851 if cls == DW_CLS_GO_TYPEREF { 852 ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value) 853 break 854 } 855 ctxt.AddAddress(s, data, value) 856 857 case DW_FORM_block1: // block 858 if cls == DW_CLS_ADDRESS { 859 ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize())) 860 ctxt.AddInt(s, 1, DW_OP_addr) 861 ctxt.AddAddress(s, data, 0) 862 break 863 } 864 865 value &= 0xff 866 ctxt.AddInt(s, 1, value) 867 p := data.([]byte)[:value] 868 ctxt.AddBytes(s, p) 869 870 case DW_FORM_block2: // block 871 value &= 0xffff 872 873 ctxt.AddInt(s, 2, value) 874 p := data.([]byte)[:value] 875 ctxt.AddBytes(s, p) 876 877 case DW_FORM_block4: // block 878 value &= 0xffffffff 879 880 ctxt.AddInt(s, 4, value) 881 p := data.([]byte)[:value] 882 ctxt.AddBytes(s, p) 883 884 case DW_FORM_block: // block 885 Uleb128put(ctxt, s, value) 886 887 p := data.([]byte)[:value] 888 ctxt.AddBytes(s, p) 889 890 case DW_FORM_data1: // constant 891 ctxt.AddInt(s, 1, value) 892 893 case DW_FORM_data2: // constant 894 ctxt.AddInt(s, 2, value) 895 896 case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr 897 if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges 898 ctxt.AddDWARFAddrSectionOffset(s, data, value) 899 break 900 } 901 ctxt.AddInt(s, 4, value) 902 903 case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr 904 ctxt.AddInt(s, 8, value) 905 906 case DW_FORM_sdata: // constant 907 Sleb128put(ctxt, s, value) 908 909 case DW_FORM_udata: // constant 910 Uleb128put(ctxt, s, value) 911 912 case DW_FORM_string: // string 913 str := data.(string) 914 ctxt.AddString(s, str) 915 // TODO(ribrdb): verify padded strings are never used and remove this 916 for i := int64(len(str)); i < value; i++ { 917 ctxt.AddInt(s, 1, 0) 918 } 919 920 case DW_FORM_flag: // flag 921 if value != 0 { 922 ctxt.AddInt(s, 1, 1) 923 } else { 924 ctxt.AddInt(s, 1, 0) 925 } 926 927 // As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large 928 // (> 4 GB of debug info aka "64-bit") unit, which we don't implement. 929 case DW_FORM_ref_addr: // reference to a DIE in the .info section 930 fallthrough 931 case DW_FORM_sec_offset: // offset into a DWARF section other than .info 932 if data == nil { 933 return fmt.Errorf("dwarf: null reference in %d", abbrev) 934 } 935 ctxt.AddDWARFAddrSectionOffset(s, data, value) 936 937 case DW_FORM_ref1, // reference within the compilation unit 938 DW_FORM_ref2, // reference 939 DW_FORM_ref4, // reference 940 DW_FORM_ref8, // reference 941 DW_FORM_ref_udata, // reference 942 943 DW_FORM_strp, // string 944 DW_FORM_indirect: // (see Section 7.5.3) 945 fallthrough 946 default: 947 return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls) 948 } 949 return nil 950 } 951 952 // PutAttrs writes the attributes for a DIE to symbol 's'. 953 // 954 // Note that we can (and do) add arbitrary attributes to a DIE, but 955 // only the ones actually listed in the Abbrev will be written out. 956 func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) { 957 Outer: 958 for _, f := range abbrevs[abbrev].attr { 959 for ap := attr; ap != nil; ap = ap.Link { 960 if ap.Atr == f.attr { 961 putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data) 962 continue Outer 963 } 964 } 965 966 putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil) 967 } 968 } 969 970 // HasChildren reports whether 'die' uses an abbrev that supports children. 971 func HasChildren(die *DWDie) bool { 972 return abbrevs[die.Abbrev].children != 0 973 } 974 975 // PutIntConst writes a DIE for an integer constant 976 func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) { 977 Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT) 978 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) 979 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ) 980 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil) 981 } 982 983 // PutRanges writes a range table to sym. All addresses in ranges are 984 // relative to some base address. If base is not nil, then they're 985 // relative to the start of base. If base is nil, then the caller must 986 // arrange a base address some other way (such as a DW_AT_low_pc 987 // attribute). 988 func PutRanges(ctxt Context, sym Sym, base Sym, ranges []Range) { 989 ps := ctxt.PtrSize() 990 // Write base address entry. 991 if base != nil { 992 ctxt.AddInt(sym, ps, -1) 993 ctxt.AddAddress(sym, base, 0) 994 } 995 // Write ranges. 996 for _, r := range ranges { 997 ctxt.AddInt(sym, ps, r.Start) 998 ctxt.AddInt(sym, ps, r.End) 999 } 1000 // Write trailer. 1001 ctxt.AddInt(sym, ps, 0) 1002 ctxt.AddInt(sym, ps, 0) 1003 } 1004 1005 // Return TRUE if the inlined call in the specified slot is empty, 1006 // meaning it has a zero-length range (no instructions), and all 1007 // of its children are empty. 1008 func isEmptyInlinedCall(slot int, calls *InlCalls) bool { 1009 ic := &calls.Calls[slot] 1010 if ic.InlIndex == -2 { 1011 return true 1012 } 1013 live := false 1014 for _, k := range ic.Children { 1015 if !isEmptyInlinedCall(k, calls) { 1016 live = true 1017 } 1018 } 1019 if len(ic.Ranges) > 0 { 1020 live = true 1021 } 1022 if !live { 1023 ic.InlIndex = -2 1024 } 1025 return !live 1026 } 1027 1028 // Slot -1: return top-level inlines 1029 // Slot >= 0: return children of that slot 1030 func inlChildren(slot int, calls *InlCalls) []int { 1031 var kids []int 1032 if slot != -1 { 1033 for _, k := range calls.Calls[slot].Children { 1034 if !isEmptyInlinedCall(k, calls) { 1035 kids = append(kids, k) 1036 } 1037 } 1038 } else { 1039 for k := 0; k < len(calls.Calls); k += 1 { 1040 if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) { 1041 kids = append(kids, k) 1042 } 1043 } 1044 } 1045 return kids 1046 } 1047 1048 func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool { 1049 vars := make(map[*Var]bool) 1050 for _, ic := range inlcalls.Calls { 1051 for _, v := range ic.InlVars { 1052 vars[v] = true 1053 } 1054 } 1055 return vars 1056 } 1057 1058 // The s.Scopes slice contains variables were originally part of the 1059 // function being emitted, as well as variables that were imported 1060 // from various callee functions during the inlining process. This 1061 // function prunes out any variables from the latter category (since 1062 // they will be emitted as part of DWARF inlined_subroutine DIEs) and 1063 // then generates scopes for vars in the former category. 1064 func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error { 1065 if len(s.Scopes) == 0 { 1066 return nil 1067 } 1068 scopes := make([]Scope, len(s.Scopes), len(s.Scopes)) 1069 pvars := inlinedVarTable(&s.InlCalls) 1070 for k, s := range s.Scopes { 1071 var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges} 1072 for i := 0; i < len(s.Vars); i++ { 1073 _, found := pvars[s.Vars[i]] 1074 if !found { 1075 pruned.Vars = append(pruned.Vars, s.Vars[i]) 1076 } 1077 } 1078 sort.Sort(byChildIndex(pruned.Vars)) 1079 scopes[k] = pruned 1080 } 1081 var encbuf [20]byte 1082 if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) { 1083 return errors.New("multiple toplevel scopes") 1084 } 1085 return nil 1086 } 1087 1088 // Emit DWARF attributes and child DIEs for an 'abstract' subprogram. 1089 // The abstract subprogram DIE for a function contains its 1090 // location-independent attributes (name, type, etc). Other instances 1091 // of the function (any inlined copy of it, or the single out-of-line 1092 // 'concrete' instance) will contain a pointer back to this abstract 1093 // DIE (as a space-saving measure, so that name/type etc doesn't have 1094 // to be repeated for each inlined copy). 1095 func PutAbstractFunc(ctxt Context, s *FnState) error { 1096 1097 if logDwarf { 1098 ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn) 1099 } 1100 1101 abbrev := DW_ABRV_FUNCTION_ABSTRACT 1102 Uleb128put(ctxt, s.Absfn, int64(abbrev)) 1103 1104 fullname := s.Name 1105 if strings.HasPrefix(s.Name, "\"\".") { 1106 // Generate a fully qualified name for the function in the 1107 // abstract case. This is so as to avoid the need for the 1108 // linker to process the DIE with patchDWARFName(); we can't 1109 // allow the name attribute of an abstract subprogram DIE to 1110 // be rewritten, since it would change the offsets of the 1111 // child DIEs (which we're relying on in order for abstract 1112 // origin references to work). 1113 fullname = objabi.PathToPrefix(s.Importpath) + "." + s.Name[3:] 1114 } 1115 putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname) 1116 1117 // DW_AT_inlined value 1118 putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil) 1119 1120 var ev int64 1121 if s.External { 1122 ev = 1 1123 } 1124 putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0) 1125 1126 // Child variables (may be empty) 1127 var flattened []*Var 1128 1129 // This slice will hold the offset in bytes for each child var DIE 1130 // with respect to the start of the parent subprogram DIE. 1131 var offsets []int32 1132 1133 // Scopes/vars 1134 if len(s.Scopes) > 0 { 1135 // For abstract subprogram DIEs we want to flatten out scope info: 1136 // lexical scope DIEs contain range and/or hi/lo PC attributes, 1137 // which we explicitly don't want for the abstract subprogram DIE. 1138 pvars := inlinedVarTable(&s.InlCalls) 1139 for _, scope := range s.Scopes { 1140 for i := 0; i < len(scope.Vars); i++ { 1141 _, found := pvars[scope.Vars[i]] 1142 if found || !scope.Vars[i].IsInAbstract { 1143 continue 1144 } 1145 flattened = append(flattened, scope.Vars[i]) 1146 } 1147 } 1148 if len(flattened) > 0 { 1149 sort.Sort(byChildIndex(flattened)) 1150 1151 if logDwarf { 1152 ctxt.Logf("putAbstractScope(%v): vars:", s.Info) 1153 for i, v := range flattened { 1154 ctxt.Logf(" %d:%s", i, v.Name) 1155 } 1156 ctxt.Logf("\n") 1157 } 1158 1159 // This slice will hold the offset in bytes for each child 1160 // variable DIE with respect to the start of the parent 1161 // subprogram DIE. 1162 for _, v := range flattened { 1163 offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn))) 1164 putAbstractVar(ctxt, s.Absfn, v) 1165 } 1166 } 1167 } 1168 ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets) 1169 1170 Uleb128put(ctxt, s.Absfn, 0) 1171 return nil 1172 } 1173 1174 // Emit DWARF attributes and child DIEs for an inlined subroutine. The 1175 // first attribute of an inlined subroutine DIE is a reference back to 1176 // its corresponding 'abstract' DIE (containing location-independent 1177 // attributes such as name, type, etc). Inlined subroutine DIEs can 1178 // have other inlined subroutine DIEs as children. 1179 func PutInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error { 1180 ic := s.InlCalls.Calls[callIdx] 1181 callee := ic.AbsFunSym 1182 1183 abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES 1184 if len(ic.Ranges) == 1 { 1185 abbrev = DW_ABRV_INLINED_SUBROUTINE 1186 } 1187 Uleb128put(ctxt, s.Info, int64(abbrev)) 1188 1189 if logDwarf { 1190 ctxt.Logf("PutInlinedFunc(caller=%v,callee=%v,abbrev=%d)\n", callersym, callee, abbrev) 1191 } 1192 1193 // Abstract origin. 1194 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee) 1195 1196 if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES { 1197 putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Len(), s.Ranges) 1198 PutRanges(ctxt, s.Ranges, s.StartPC, ic.Ranges) 1199 } else { 1200 st := ic.Ranges[0].Start 1201 en := ic.Ranges[0].End 1202 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, s.StartPC) 1203 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, s.StartPC) 1204 } 1205 1206 // Emit call file, line attrs. 1207 ctxt.AddFileRef(s.Info, ic.CallFile) 1208 putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(ic.CallLine), nil) 1209 1210 // Variables associated with this inlined routine instance. 1211 vars := ic.InlVars 1212 sort.Sort(byChildIndex(vars)) 1213 inlIndex := ic.InlIndex 1214 var encbuf [20]byte 1215 for _, v := range vars { 1216 if !v.IsInAbstract { 1217 continue 1218 } 1219 putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0]) 1220 } 1221 1222 // Children of this inline. 1223 for _, sib := range inlChildren(callIdx, &s.InlCalls) { 1224 absfn := s.InlCalls.Calls[sib].AbsFunSym 1225 err := PutInlinedFunc(ctxt, s, absfn, sib) 1226 if err != nil { 1227 return err 1228 } 1229 } 1230 1231 Uleb128put(ctxt, s.Info, 0) 1232 return nil 1233 } 1234 1235 // Emit DWARF attributes and child DIEs for a 'concrete' subprogram, 1236 // meaning the out-of-line copy of a function that was inlined at some 1237 // point during the compilation of its containing package. The first 1238 // attribute for a concrete DIE is a reference to the 'abstract' DIE 1239 // for the function (which holds location-independent attributes such 1240 // as name, type), then the remainder of the attributes are specific 1241 // to this instance (location, frame base, etc). 1242 func PutConcreteFunc(ctxt Context, s *FnState) error { 1243 if logDwarf { 1244 ctxt.Logf("PutConcreteFunc(%v)\n", s.Info) 1245 } 1246 abbrev := DW_ABRV_FUNCTION_CONCRETE 1247 Uleb128put(ctxt, s.Info, int64(abbrev)) 1248 1249 // Abstract origin. 1250 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn) 1251 1252 // Start/end PC. 1253 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC) 1254 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC) 1255 1256 // cfa / frame base 1257 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) 1258 1259 // Scopes 1260 if err := putPrunedScopes(ctxt, s, abbrev); err != nil { 1261 return err 1262 } 1263 1264 // Inlined subroutines. 1265 for _, sib := range inlChildren(-1, &s.InlCalls) { 1266 absfn := s.InlCalls.Calls[sib].AbsFunSym 1267 err := PutInlinedFunc(ctxt, s, absfn, sib) 1268 if err != nil { 1269 return err 1270 } 1271 } 1272 1273 Uleb128put(ctxt, s.Info, 0) 1274 return nil 1275 } 1276 1277 // Emit DWARF attributes and child DIEs for a subprogram. Here 1278 // 'default' implies that the function in question was not inlined 1279 // when its containing package was compiled (hence there is no need to 1280 // emit an abstract version for it to use as a base for inlined 1281 // routine records). 1282 func PutDefaultFunc(ctxt Context, s *FnState) error { 1283 if logDwarf { 1284 ctxt.Logf("PutDefaultFunc(%v)\n", s.Info) 1285 } 1286 abbrev := DW_ABRV_FUNCTION 1287 Uleb128put(ctxt, s.Info, int64(abbrev)) 1288 1289 putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(s.Name)), s.Name) 1290 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC) 1291 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC) 1292 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) 1293 ctxt.AddFileRef(s.Info, s.Filesym) 1294 1295 var ev int64 1296 if s.External { 1297 ev = 1 1298 } 1299 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0) 1300 1301 // Scopes 1302 if err := putPrunedScopes(ctxt, s, abbrev); err != nil { 1303 return err 1304 } 1305 1306 // Inlined subroutines. 1307 for _, sib := range inlChildren(-1, &s.InlCalls) { 1308 absfn := s.InlCalls.Calls[sib].AbsFunSym 1309 err := PutInlinedFunc(ctxt, s, absfn, sib) 1310 if err != nil { 1311 return err 1312 } 1313 } 1314 1315 Uleb128put(ctxt, s.Info, 0) 1316 return nil 1317 } 1318 1319 func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 { 1320 1321 if logDwarf { 1322 ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope) 1323 for i, v := range scopes[curscope].Vars { 1324 ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name) 1325 } 1326 ctxt.Logf("\n") 1327 } 1328 1329 for _, v := range scopes[curscope].Vars { 1330 putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf) 1331 } 1332 this := curscope 1333 curscope++ 1334 for curscope < int32(len(scopes)) { 1335 scope := scopes[curscope] 1336 if scope.Parent != this { 1337 return curscope 1338 } 1339 1340 if len(scopes[curscope].Vars) == 0 { 1341 curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf) 1342 continue 1343 } 1344 1345 if len(scope.Ranges) == 1 { 1346 Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE) 1347 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC) 1348 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC) 1349 } else { 1350 Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES) 1351 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Len(), s.Ranges) 1352 1353 PutRanges(ctxt, s.Ranges, s.StartPC, scope.Ranges) 1354 } 1355 1356 curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf) 1357 1358 Uleb128put(ctxt, s.Info, 0) 1359 } 1360 return curscope 1361 } 1362 1363 // Given a default var abbrev code, select corresponding concrete code. 1364 func concreteVarAbbrev(varAbbrev int) int { 1365 switch varAbbrev { 1366 case DW_ABRV_AUTO: 1367 return DW_ABRV_AUTO_CONCRETE 1368 case DW_ABRV_PARAM: 1369 return DW_ABRV_PARAM_CONCRETE 1370 case DW_ABRV_AUTO_LOCLIST: 1371 return DW_ABRV_AUTO_CONCRETE_LOCLIST 1372 case DW_ABRV_PARAM_LOCLIST: 1373 return DW_ABRV_PARAM_CONCRETE_LOCLIST 1374 default: 1375 panic("should never happen") 1376 } 1377 } 1378 1379 // Pick the correct abbrev code for variable or parameter DIE. 1380 func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) { 1381 abbrev := v.Abbrev 1382 1383 // If the variable was entirely optimized out, don't emit a location list; 1384 // convert to an inline abbreviation and emit an empty location. 1385 missing := false 1386 switch { 1387 case abbrev == DW_ABRV_AUTO_LOCLIST && v.PutLocationList == nil: 1388 missing = true 1389 abbrev = DW_ABRV_AUTO 1390 case abbrev == DW_ABRV_PARAM_LOCLIST && v.PutLocationList == nil: 1391 missing = true 1392 abbrev = DW_ABRV_PARAM 1393 } 1394 1395 // Determine whether to use a concrete variable or regular variable DIE. 1396 concrete := true 1397 switch fnabbrev { 1398 case DW_ABRV_FUNCTION: 1399 concrete = false 1400 break 1401 case DW_ABRV_FUNCTION_CONCRETE: 1402 // If we're emitting a concrete subprogram DIE and the variable 1403 // in question is not part of the corresponding abstract function DIE, 1404 // then use the default (non-concrete) abbrev for this param. 1405 if !v.IsInAbstract { 1406 concrete = false 1407 } 1408 case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES: 1409 default: 1410 panic("should never happen") 1411 } 1412 1413 // Select proper abbrev based on concrete/non-concrete 1414 if concrete { 1415 abbrev = concreteVarAbbrev(abbrev) 1416 } 1417 1418 return abbrev, missing, concrete 1419 } 1420 1421 func abbrevUsesLoclist(abbrev int) bool { 1422 switch abbrev { 1423 case DW_ABRV_AUTO_LOCLIST, DW_ABRV_AUTO_CONCRETE_LOCLIST, 1424 DW_ABRV_PARAM_LOCLIST, DW_ABRV_PARAM_CONCRETE_LOCLIST: 1425 return true 1426 default: 1427 return false 1428 } 1429 } 1430 1431 // Emit DWARF attributes for a variable belonging to an 'abstract' subprogram. 1432 func putAbstractVar(ctxt Context, info Sym, v *Var) { 1433 // Remap abbrev 1434 abbrev := v.Abbrev 1435 switch abbrev { 1436 case DW_ABRV_AUTO, DW_ABRV_AUTO_LOCLIST: 1437 abbrev = DW_ABRV_AUTO_ABSTRACT 1438 case DW_ABRV_PARAM, DW_ABRV_PARAM_LOCLIST: 1439 abbrev = DW_ABRV_PARAM_ABSTRACT 1440 } 1441 1442 Uleb128put(ctxt, info, int64(abbrev)) 1443 putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name) 1444 1445 // Isreturn attribute if this is a param 1446 if abbrev == DW_ABRV_PARAM_ABSTRACT { 1447 var isReturn int64 1448 if v.IsReturnValue { 1449 isReturn = 1 1450 } 1451 putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) 1452 } 1453 1454 // Line 1455 if abbrev != DW_ABRV_PARAM_ABSTRACT { 1456 // See issue 23374 for more on why decl line is skipped for abs params. 1457 putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) 1458 } 1459 1460 // Type 1461 putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) 1462 1463 // Var has no children => no terminator 1464 } 1465 1466 func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) { 1467 // Remap abbrev according to parent DIE abbrev 1468 abbrev, missing, concrete := determineVarAbbrev(v, fnabbrev) 1469 1470 Uleb128put(ctxt, s.Info, int64(abbrev)) 1471 1472 // Abstract origin for concrete / inlined case 1473 if concrete { 1474 // Here we are making a reference to a child DIE of an abstract 1475 // function subprogram DIE. The child DIE has no LSym, so instead 1476 // after the call to 'putattr' below we make a call to register 1477 // the child DIE reference. 1478 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn) 1479 ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex) 1480 } else { 1481 // Var name, line for abstract and default cases 1482 n := v.Name 1483 putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) 1484 if abbrev == DW_ABRV_PARAM || abbrev == DW_ABRV_PARAM_LOCLIST || abbrev == DW_ABRV_PARAM_ABSTRACT { 1485 var isReturn int64 1486 if v.IsReturnValue { 1487 isReturn = 1 1488 } 1489 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) 1490 } 1491 putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) 1492 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) 1493 } 1494 1495 if abbrevUsesLoclist(abbrev) { 1496 putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Loc.Len(), s.Loc) 1497 v.PutLocationList(s.Loc, s.StartPC) 1498 } else { 1499 loc := encbuf[:0] 1500 switch { 1501 case missing: 1502 break // no location 1503 case v.StackOffset == 0: 1504 loc = append(loc, DW_OP_call_frame_cfa) 1505 default: 1506 loc = append(loc, DW_OP_fbreg) 1507 loc = AppendSleb128(loc, int64(v.StackOffset)) 1508 } 1509 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) 1510 } 1511 1512 // Var has no children => no terminator 1513 } 1514 1515 // VarsByOffset attaches the methods of sort.Interface to []*Var, 1516 // sorting in increasing StackOffset. 1517 type VarsByOffset []*Var 1518 1519 func (s VarsByOffset) Len() int { return len(s) } 1520 func (s VarsByOffset) Less(i, j int) bool { return s[i].StackOffset < s[j].StackOffset } 1521 func (s VarsByOffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 1522 1523 // byChildIndex implements sort.Interface for []*dwarf.Var by child index. 1524 type byChildIndex []*Var 1525 1526 func (s byChildIndex) Len() int { return len(s) } 1527 func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex } 1528 func (s byChildIndex) Swap(i, j int) { s[i], s[j] = s[j], s[i] }