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