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