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