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