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