github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/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.assembler file. 4 5 // Package dwarf generates DWARF debugging information. 6 // DWARF generation is split between the compiler and the linker, 7 // this package contains the shared code. 8 package dwarf 9 10 import ( 11 "bytes" 12 "errors" 13 "fmt" 14 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/buildcfg" 15 "os/exec" 16 "sort" 17 "strconv" 18 "strings" 19 20 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/objabi" 21 ) 22 23 24 const InfoPrefix = "go:info." 25 26 27 28 const ConstInfoPrefix = "go:constinfo." 29 30 31 32 const CUInfoPrefix = "go:cuinfo." 33 34 35 36 const AbstractFuncSuffix = "$abstract" 37 38 39 40 var logDwarf bool 41 42 43 type Sym interface { 44 Length(dwarfContext interface{}) int64 45 } 46 47 48 type Var struct { 49 Name string 50 Abbrev int 51 IsReturnValue bool 52 IsInlFormal bool 53 DictIndex uint16 54 StackOffset int32 55 56 57 PutLocationList func(listSym, startPC Sym) 58 Scope int32 59 Type Sym 60 DeclFile string 61 DeclLine uint 62 DeclCol uint 63 InlIndex int32 64 ChildIndex int32 65 IsInAbstract bool 66 } 67 68 69 70 71 72 73 74 type Scope struct { 75 Parent int32 76 Ranges []Range 77 Vars []*Var 78 } 79 80 81 type Range struct { 82 Start, End int64 83 } 84 85 86 87 type FnState struct { 88 Name string 89 Importpath string 90 Info Sym 91 Filesym Sym 92 Loc Sym 93 Ranges Sym 94 Absfn Sym 95 StartPC Sym 96 Size int64 97 StartLine int32 98 External bool 99 Scopes []Scope 100 InlCalls InlCalls 101 UseBASEntries bool 102 103 dictIndexToOffset []int64 104 } 105 106 func EnableLogging(doit bool) { 107 logDwarf = doit 108 } 109 110 111 112 func MergeRanges(in1, in2 []Range) []Range { 113 out := make([]Range, 0, len(in1)+len(in2)) 114 i, j := 0, 0 115 for { 116 var cur Range 117 if i < len(in2) && j < len(in1) { 118 if in2[i].Start < in1[j].Start { 119 cur = in2[i] 120 i++ 121 } else { 122 cur = in1[j] 123 j++ 124 } 125 } else if i < len(in2) { 126 cur = in2[i] 127 i++ 128 } else if j < len(in1) { 129 cur = in1[j] 130 j++ 131 } else { 132 break 133 } 134 135 if n := len(out); n > 0 && cur.Start <= out[n-1].End { 136 out[n-1].End = cur.End 137 } else { 138 out = append(out, cur) 139 } 140 } 141 142 return out 143 } 144 145 146 func (s *Scope) UnifyRanges(c *Scope) { 147 s.Ranges = MergeRanges(s.Ranges, c.Ranges) 148 } 149 150 151 152 func (s *Scope) AppendRange(r Range) { 153 if r.End <= r.Start { 154 return 155 } 156 i := len(s.Ranges) 157 if i > 0 && s.Ranges[i-1].End == r.Start { 158 s.Ranges[i-1].End = r.End 159 return 160 } 161 s.Ranges = append(s.Ranges, r) 162 } 163 164 type InlCalls struct { 165 Calls []InlCall 166 } 167 168 type InlCall struct { 169 170 InlIndex int 171 172 173 CallFile Sym 174 175 176 CallLine uint32 177 178 179 AbsFunSym Sym 180 181 182 Children []int 183 184 185 186 InlVars []*Var 187 188 189 Ranges []Range 190 191 192 Root bool 193 } 194 195 196 type Context interface { 197 PtrSize() int 198 AddInt(s Sym, size int, i int64) 199 AddBytes(s Sym, b []byte) 200 AddAddress(s Sym, t interface{}, ofs int64) 201 AddCURelativeAddress(s Sym, t interface{}, ofs int64) 202 AddSectionOffset(s Sym, size int, t interface{}, ofs int64) 203 AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64) 204 CurrentOffset(s Sym) int64 205 RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int) 206 RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32) 207 AddString(s Sym, v string) 208 AddFileRef(s Sym, f interface{}) 209 Logf(format string, args ...interface{}) 210 } 211 212 213 func AppendUleb128(b []byte, v uint64) []byte { 214 for { 215 c := uint8(v & 0x7f) 216 v >>= 7 217 if v != 0 { 218 c |= 0x80 219 } 220 b = append(b, c) 221 if c&0x80 == 0 { 222 break 223 } 224 } 225 return b 226 } 227 228 229 func AppendSleb128(b []byte, v int64) []byte { 230 for { 231 c := uint8(v & 0x7f) 232 s := uint8(v & 0x40) 233 v >>= 7 234 if (v != -1 || s == 0) && (v != 0 || s != 0) { 235 c |= 0x80 236 } 237 b = append(b, c) 238 if c&0x80 == 0 { 239 break 240 } 241 } 242 return b 243 } 244 245 246 var sevenbits = [...]byte{ 247 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 248 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 249 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 250 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 251 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 252 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 253 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 254 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 255 } 256 257 258 259 func sevenBitU(v int64) []byte { 260 if uint64(v) < uint64(len(sevenbits)) { 261 return sevenbits[v : v+1] 262 } 263 return nil 264 } 265 266 267 268 func sevenBitS(v int64) []byte { 269 if uint64(v) <= 63 { 270 return sevenbits[v : v+1] 271 } 272 if uint64(-v) <= 64 { 273 return sevenbits[128+v : 128+v+1] 274 } 275 return nil 276 } 277 278 279 func Uleb128put(ctxt Context, s Sym, v int64) { 280 b := sevenBitU(v) 281 if b == nil { 282 var encbuf [20]byte 283 b = AppendUleb128(encbuf[:0], uint64(v)) 284 } 285 ctxt.AddBytes(s, b) 286 } 287 288 289 func Sleb128put(ctxt Context, s Sym, v int64) { 290 b := sevenBitS(v) 291 if b == nil { 292 var encbuf [20]byte 293 b = AppendSleb128(encbuf[:0], v) 294 } 295 ctxt.AddBytes(s, b) 296 } 297 298 299 type dwAttrForm struct { 300 attr uint16 301 form uint8 302 } 303 304 305 const ( 306 DW_AT_go_kind = 0x2900 307 DW_AT_go_key = 0x2901 308 DW_AT_go_elem = 0x2902 309 310 311 DW_AT_go_embedded_field = 0x2903 312 DW_AT_go_runtime_type = 0x2904 313 314 DW_AT_go_package_name = 0x2905 315 DW_AT_go_dict_index = 0x2906 316 317 DW_AT_internal_location = 253 318 ) 319 320 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 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 376 377 378 379 380 381 func expandPseudoForm(form uint8) uint8 { 382 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 394 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 409 410 411 412 var abbrevs = [DW_NABRV]dwAbbrev{ 413 414 {0, 0, []dwAttrForm{}}, 415 416 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 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 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 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 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 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 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 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}, 520 }, 521 }, 522 523 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}, 532 }, 533 }, 534 535 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 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 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 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 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 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 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 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 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 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 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 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 671 { 672 DW_TAG_lexical_block, 673 DW_CHILDREN_yes, 674 []dwAttrForm{ 675 {DW_AT_ranges, DW_FORM_sec_offset}, 676 }, 677 }, 678 679 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 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 702 { 703 DW_TAG_formal_parameter, 704 DW_CHILDREN_no, 705 706 707 []dwAttrForm{ 708 {DW_AT_type, DW_FORM_ref_addr}, 709 }, 710 }, 711 712 713 { 714 DW_TAG_unspecified_parameters, 715 DW_CHILDREN_no, 716 []dwAttrForm{}, 717 }, 718 719 720 { 721 DW_TAG_subrange_type, 722 DW_CHILDREN_no, 723 724 725 []dwAttrForm{ 726 {DW_AT_type, DW_FORM_ref_addr}, 727 {DW_AT_count, DW_FORM_udata}, 728 }, 729 }, 730 731 732 733 { 734 DW_TAG_unspecified_type, 735 DW_CHILDREN_no, 736 []dwAttrForm{ 737 {DW_AT_name, DW_FORM_string}, 738 }, 739 }, 740 741 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 755 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 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 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 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 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 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 832 { 833 DW_TAG_pointer_type, 834 DW_CHILDREN_no, 835 []dwAttrForm{ 836 {DW_AT_name, DW_FORM_string}, 837 }, 838 }, 839 840 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 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 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 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 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 900 func GetAbbrev() []byte { 901 abbrevs := Abbrevs() 902 var buf []byte 903 for i := 1; i < DW_NABRV; i++ { 904 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 919 920 921 922 923 924 925 type DWAttr struct { 926 Link *DWAttr 927 Atr uint16 928 Cls uint8 929 Value int64 930 Data interface{} 931 } 932 933 934 type DWDie struct { 935 Abbrev int 936 Link *DWDie 937 Child *DWDie 938 Attr *DWAttr 939 Sym Sym 940 } 941 942 func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error { 943 switch form { 944 case DW_FORM_addr: 945 946 if data == nil && value == 0 { 947 ctxt.AddInt(s, ctxt.PtrSize(), 0) 948 break 949 } 950 if cls == DW_CLS_GO_TYPEREF { 951 ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value) 952 break 953 } 954 ctxt.AddAddress(s, data, value) 955 956 case DW_FORM_block1: 957 if cls == DW_CLS_ADDRESS { 958 ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize())) 959 ctxt.AddInt(s, 1, DW_OP_addr) 960 ctxt.AddAddress(s, data, 0) 961 break 962 } 963 964 value &= 0xff 965 ctxt.AddInt(s, 1, value) 966 p := data.([]byte)[:value] 967 ctxt.AddBytes(s, p) 968 969 case DW_FORM_block2: 970 value &= 0xffff 971 972 ctxt.AddInt(s, 2, value) 973 p := data.([]byte)[:value] 974 ctxt.AddBytes(s, p) 975 976 case DW_FORM_block4: 977 value &= 0xffffffff 978 979 ctxt.AddInt(s, 4, value) 980 p := data.([]byte)[:value] 981 ctxt.AddBytes(s, p) 982 983 case DW_FORM_block: 984 Uleb128put(ctxt, s, value) 985 986 p := data.([]byte)[:value] 987 ctxt.AddBytes(s, p) 988 989 case DW_FORM_data1: 990 ctxt.AddInt(s, 1, value) 991 992 case DW_FORM_data2: 993 ctxt.AddInt(s, 2, value) 994 995 case DW_FORM_data4: 996 if cls == DW_CLS_PTR { 997 ctxt.AddDWARFAddrSectionOffset(s, data, value) 998 break 999 } 1000 ctxt.AddInt(s, 4, value) 1001 1002 case DW_FORM_data8: 1003 ctxt.AddInt(s, 8, value) 1004 1005 case DW_FORM_sdata: 1006 Sleb128put(ctxt, s, value) 1007 1008 case DW_FORM_udata: 1009 Uleb128put(ctxt, s, value) 1010 1011 case DW_FORM_string: 1012 str := data.(string) 1013 ctxt.AddString(s, str) 1014 1015 for i := int64(len(str)); i < value; i++ { 1016 ctxt.AddInt(s, 1, 0) 1017 } 1018 1019 case DW_FORM_flag: 1020 if value != 0 { 1021 ctxt.AddInt(s, 1, 1) 1022 } else { 1023 ctxt.AddInt(s, 1, 0) 1024 } 1025 1026 1027 1028 case DW_FORM_ref_addr: 1029 fallthrough 1030 case DW_FORM_sec_offset: 1031 if data == nil { 1032 return fmt.Errorf("dwarf: null reference in %d", abbrev) 1033 } 1034 ctxt.AddDWARFAddrSectionOffset(s, data, value) 1035 1036 case DW_FORM_ref1, 1037 DW_FORM_ref2, 1038 DW_FORM_ref4, 1039 DW_FORM_ref8, 1040 DW_FORM_ref_udata, 1041 1042 DW_FORM_strp, 1043 DW_FORM_indirect: 1044 fallthrough 1045 default: 1046 return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls) 1047 } 1048 return nil 1049 } 1050 1051 1052 1053 1054 1055 func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) { 1056 abbrevs := Abbrevs() 1057 Outer: 1058 for _, f := range abbrevs[abbrev].attr { 1059 for ap := attr; ap != nil; ap = ap.Link { 1060 if ap.Atr == f.attr { 1061 putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data) 1062 continue Outer 1063 } 1064 } 1065 1066 putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil) 1067 } 1068 } 1069 1070 1071 func HasChildren(die *DWDie) bool { 1072 abbrevs := Abbrevs() 1073 return abbrevs[die.Abbrev].children != 0 1074 } 1075 1076 1077 func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) { 1078 Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT) 1079 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) 1080 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ) 1081 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil) 1082 } 1083 1084 1085 func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) { 1086 Uleb128put(ctxt, info, DW_ABRV_VARIABLE) 1087 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) 1088 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_block1, DW_CLS_ADDRESS, 0, gvar) 1089 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ) 1090 putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_flag, DW_CLS_FLAG, 1, nil) 1091 } 1092 1093 1094 1095 1096 func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) { 1097 ps := ctxt.PtrSize() 1098 1099 for _, r := range ranges { 1100 ctxt.AddInt(sym, ps, r.Start) 1101 ctxt.AddInt(sym, ps, r.End) 1102 } 1103 1104 ctxt.AddInt(sym, ps, 0) 1105 ctxt.AddInt(sym, ps, 0) 1106 } 1107 1108 1109 1110 func (s *FnState) PutRanges(ctxt Context, ranges []Range) { 1111 ps := ctxt.PtrSize() 1112 sym, base := s.Ranges, s.StartPC 1113 1114 if s.UseBASEntries { 1115 1116 1117 ctxt.AddInt(sym, ps, -1) 1118 ctxt.AddAddress(sym, base, 0) 1119 PutBasedRanges(ctxt, sym, ranges) 1120 return 1121 } 1122 1123 1124 for _, r := range ranges { 1125 ctxt.AddCURelativeAddress(sym, base, r.Start) 1126 ctxt.AddCURelativeAddress(sym, base, r.End) 1127 } 1128 1129 ctxt.AddInt(sym, ps, 0) 1130 ctxt.AddInt(sym, ps, 0) 1131 } 1132 1133 1134 1135 1136 func isEmptyInlinedCall(slot int, calls *InlCalls) bool { 1137 ic := &calls.Calls[slot] 1138 if ic.InlIndex == -2 { 1139 return true 1140 } 1141 live := false 1142 for _, k := range ic.Children { 1143 if !isEmptyInlinedCall(k, calls) { 1144 live = true 1145 } 1146 } 1147 if len(ic.Ranges) > 0 { 1148 live = true 1149 } 1150 if !live { 1151 ic.InlIndex = -2 1152 } 1153 return !live 1154 } 1155 1156 1157 1158 func inlChildren(slot int, calls *InlCalls) []int { 1159 var kids []int 1160 if slot != -1 { 1161 for _, k := range calls.Calls[slot].Children { 1162 if !isEmptyInlinedCall(k, calls) { 1163 kids = append(kids, k) 1164 } 1165 } 1166 } else { 1167 for k := 0; k < len(calls.Calls); k += 1 { 1168 if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) { 1169 kids = append(kids, k) 1170 } 1171 } 1172 } 1173 return kids 1174 } 1175 1176 func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool { 1177 vars := make(map[*Var]bool) 1178 for _, ic := range inlcalls.Calls { 1179 for _, v := range ic.InlVars { 1180 vars[v] = true 1181 } 1182 } 1183 return vars 1184 } 1185 1186 1187 1188 1189 1190 1191 1192 func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error { 1193 if len(s.Scopes) == 0 { 1194 return nil 1195 } 1196 scopes := make([]Scope, len(s.Scopes), len(s.Scopes)) 1197 pvars := inlinedVarTable(&s.InlCalls) 1198 for k, s := range s.Scopes { 1199 var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges} 1200 for i := 0; i < len(s.Vars); i++ { 1201 _, found := pvars[s.Vars[i]] 1202 if !found { 1203 pruned.Vars = append(pruned.Vars, s.Vars[i]) 1204 } 1205 } 1206 sort.Sort(byChildIndex(pruned.Vars)) 1207 scopes[k] = pruned 1208 } 1209 1210 s.dictIndexToOffset = putparamtypes(ctxt, s, scopes, fnabbrev) 1211 1212 var encbuf [20]byte 1213 if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) { 1214 return errors.New("multiple toplevel scopes") 1215 } 1216 return nil 1217 } 1218 1219 1220 1221 1222 1223 1224 1225 1226 func PutAbstractFunc(ctxt Context, s *FnState) error { 1227 1228 if logDwarf { 1229 ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn) 1230 } 1231 1232 abbrev := DW_ABRV_FUNCTION_ABSTRACT 1233 Uleb128put(ctxt, s.Absfn, int64(abbrev)) 1234 1235 fullname := s.Name 1236 if strings.HasPrefix(s.Name, "\"\".") { 1237 1238 1239 1240 1241 1242 1243 1244 fullname = objabi.PathToPrefix(s.Importpath) + "." + s.Name[3:] 1245 } 1246 putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname) 1247 1248 1249 putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil) 1250 1251 putattr(ctxt, s.Absfn, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartLine), nil) 1252 1253 var ev int64 1254 if s.External { 1255 ev = 1 1256 } 1257 putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0) 1258 1259 1260 var flattened []*Var 1261 1262 1263 1264 var offsets []int32 1265 1266 1267 if len(s.Scopes) > 0 { 1268 1269 1270 1271 pvars := inlinedVarTable(&s.InlCalls) 1272 for _, scope := range s.Scopes { 1273 for i := 0; i < len(scope.Vars); i++ { 1274 _, found := pvars[scope.Vars[i]] 1275 if found || !scope.Vars[i].IsInAbstract { 1276 continue 1277 } 1278 flattened = append(flattened, scope.Vars[i]) 1279 } 1280 } 1281 if len(flattened) > 0 { 1282 sort.Sort(byChildIndex(flattened)) 1283 1284 if logDwarf { 1285 ctxt.Logf("putAbstractScope(%v): vars:", s.Info) 1286 for i, v := range flattened { 1287 ctxt.Logf(" %d:%s", i, v.Name) 1288 } 1289 ctxt.Logf("\n") 1290 } 1291 1292 1293 1294 1295 for _, v := range flattened { 1296 offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn))) 1297 putAbstractVar(ctxt, s.Absfn, v) 1298 } 1299 } 1300 } 1301 ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets) 1302 1303 Uleb128put(ctxt, s.Absfn, 0) 1304 return nil 1305 } 1306 1307 1308 1309 1310 1311 1312 func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error { 1313 ic := s.InlCalls.Calls[callIdx] 1314 callee := ic.AbsFunSym 1315 1316 abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES 1317 if len(ic.Ranges) == 1 { 1318 abbrev = DW_ABRV_INLINED_SUBROUTINE 1319 } 1320 Uleb128put(ctxt, s.Info, int64(abbrev)) 1321 1322 if logDwarf { 1323 ctxt.Logf("putInlinedFunc(callee=%v,abbrev=%d)\n", callee, abbrev) 1324 } 1325 1326 1327 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee) 1328 1329 if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES { 1330 putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges) 1331 s.PutRanges(ctxt, ic.Ranges) 1332 } else { 1333 st := ic.Ranges[0].Start 1334 en := ic.Ranges[0].End 1335 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, s.StartPC) 1336 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, s.StartPC) 1337 } 1338 1339 1340 ctxt.AddFileRef(s.Info, ic.CallFile) 1341 form := int(expandPseudoForm(DW_FORM_udata_pseudo)) 1342 putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil) 1343 1344 1345 vars := ic.InlVars 1346 sort.Sort(byChildIndex(vars)) 1347 inlIndex := ic.InlIndex 1348 var encbuf [20]byte 1349 for _, v := range vars { 1350 if !v.IsInAbstract { 1351 continue 1352 } 1353 putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0]) 1354 } 1355 1356 1357 for _, sib := range inlChildren(callIdx, &s.InlCalls) { 1358 err := putInlinedFunc(ctxt, s, sib) 1359 if err != nil { 1360 return err 1361 } 1362 } 1363 1364 Uleb128put(ctxt, s.Info, 0) 1365 return nil 1366 } 1367 1368 1369 1370 1371 1372 1373 1374 1375 func PutConcreteFunc(ctxt Context, s *FnState, isWrapper bool) error { 1376 if logDwarf { 1377 ctxt.Logf("PutConcreteFunc(%v)\n", s.Info) 1378 } 1379 abbrev := DW_ABRV_FUNCTION_CONCRETE 1380 if isWrapper { 1381 abbrev = DW_ABRV_WRAPPER_CONCRETE 1382 } 1383 Uleb128put(ctxt, s.Info, int64(abbrev)) 1384 1385 1386 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn) 1387 1388 1389 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC) 1390 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC) 1391 1392 1393 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) 1394 1395 if isWrapper { 1396 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0) 1397 } 1398 1399 1400 if err := putPrunedScopes(ctxt, s, abbrev); err != nil { 1401 return err 1402 } 1403 1404 1405 for _, sib := range inlChildren(-1, &s.InlCalls) { 1406 err := putInlinedFunc(ctxt, s, sib) 1407 if err != nil { 1408 return err 1409 } 1410 } 1411 1412 Uleb128put(ctxt, s.Info, 0) 1413 return nil 1414 } 1415 1416 1417 1418 1419 1420 1421 func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error { 1422 if logDwarf { 1423 ctxt.Logf("PutDefaultFunc(%v)\n", s.Info) 1424 } 1425 abbrev := DW_ABRV_FUNCTION 1426 if isWrapper { 1427 abbrev = DW_ABRV_WRAPPER 1428 } 1429 Uleb128put(ctxt, s.Info, int64(abbrev)) 1430 1431 1432 name := s.Name 1433 if s.Importpath != "" { 1434 name = strings.Replace(name, "\"\".", objabi.PathToPrefix(s.Importpath)+".", -1) 1435 } 1436 1437 putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) 1438 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC) 1439 putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC) 1440 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) 1441 if isWrapper { 1442 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0) 1443 } else { 1444 ctxt.AddFileRef(s.Info, s.Filesym) 1445 putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(s.StartLine), nil) 1446 1447 var ev int64 1448 if s.External { 1449 ev = 1 1450 } 1451 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0) 1452 } 1453 1454 1455 if err := putPrunedScopes(ctxt, s, abbrev); err != nil { 1456 return err 1457 } 1458 1459 1460 for _, sib := range inlChildren(-1, &s.InlCalls) { 1461 err := putInlinedFunc(ctxt, s, sib) 1462 if err != nil { 1463 return err 1464 } 1465 } 1466 1467 Uleb128put(ctxt, s.Info, 0) 1468 return nil 1469 } 1470 1471 1472 func putparamtypes(ctxt Context, s *FnState, scopes []Scope, fnabbrev int) []int64 { 1473 if fnabbrev == DW_ABRV_FUNCTION_CONCRETE { 1474 return nil 1475 } 1476 1477 maxDictIndex := uint16(0) 1478 1479 for i := range scopes { 1480 for _, v := range scopes[i].Vars { 1481 if v.DictIndex > maxDictIndex { 1482 maxDictIndex = v.DictIndex 1483 } 1484 } 1485 } 1486 1487 if maxDictIndex == 0 { 1488 return nil 1489 } 1490 1491 dictIndexToOffset := make([]int64, maxDictIndex) 1492 1493 for i := range scopes { 1494 for _, v := range scopes[i].Vars { 1495 if v.DictIndex == 0 || dictIndexToOffset[v.DictIndex-1] != 0 { 1496 continue 1497 } 1498 1499 dictIndexToOffset[v.DictIndex-1] = ctxt.CurrentOffset(s.Info) 1500 1501 Uleb128put(ctxt, s.Info, int64(DW_ABRV_DICT_INDEX)) 1502 n := fmt.Sprintf(".param%d", v.DictIndex-1) 1503 putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) 1504 putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) 1505 putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DictIndex-1), nil) 1506 } 1507 } 1508 1509 return dictIndexToOffset 1510 } 1511 1512 func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 { 1513 1514 if logDwarf { 1515 ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope) 1516 for i, v := range scopes[curscope].Vars { 1517 ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name) 1518 } 1519 ctxt.Logf("\n") 1520 } 1521 1522 for _, v := range scopes[curscope].Vars { 1523 putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf) 1524 } 1525 this := curscope 1526 curscope++ 1527 for curscope < int32(len(scopes)) { 1528 scope := scopes[curscope] 1529 if scope.Parent != this { 1530 return curscope 1531 } 1532 1533 if len(scopes[curscope].Vars) == 0 { 1534 curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf) 1535 continue 1536 } 1537 1538 if len(scope.Ranges) == 1 { 1539 Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE) 1540 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC) 1541 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC) 1542 } else { 1543 Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES) 1544 putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges) 1545 1546 s.PutRanges(ctxt, scope.Ranges) 1547 } 1548 1549 curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf) 1550 1551 Uleb128put(ctxt, s.Info, 0) 1552 } 1553 return curscope 1554 } 1555 1556 1557 func concreteVarAbbrev(varAbbrev int) int { 1558 switch varAbbrev { 1559 case DW_ABRV_AUTO: 1560 return DW_ABRV_AUTO_CONCRETE 1561 case DW_ABRV_PARAM: 1562 return DW_ABRV_PARAM_CONCRETE 1563 case DW_ABRV_AUTO_LOCLIST: 1564 return DW_ABRV_AUTO_CONCRETE_LOCLIST 1565 case DW_ABRV_PARAM_LOCLIST: 1566 return DW_ABRV_PARAM_CONCRETE_LOCLIST 1567 default: 1568 panic("should never happen") 1569 } 1570 } 1571 1572 1573 func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) { 1574 abbrev := v.Abbrev 1575 1576 1577 1578 missing := false 1579 switch { 1580 case abbrev == DW_ABRV_AUTO_LOCLIST && v.PutLocationList == nil: 1581 missing = true 1582 abbrev = DW_ABRV_AUTO 1583 case abbrev == DW_ABRV_PARAM_LOCLIST && v.PutLocationList == nil: 1584 missing = true 1585 abbrev = DW_ABRV_PARAM 1586 } 1587 1588 1589 concrete := true 1590 switch fnabbrev { 1591 case DW_ABRV_FUNCTION, DW_ABRV_WRAPPER: 1592 concrete = false 1593 case DW_ABRV_FUNCTION_CONCRETE, DW_ABRV_WRAPPER_CONCRETE: 1594 1595 1596 1597 if !v.IsInAbstract { 1598 concrete = false 1599 } 1600 case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES: 1601 default: 1602 panic("should never happen") 1603 } 1604 1605 1606 if concrete { 1607 abbrev = concreteVarAbbrev(abbrev) 1608 } 1609 1610 return abbrev, missing, concrete 1611 } 1612 1613 func abbrevUsesLoclist(abbrev int) bool { 1614 switch abbrev { 1615 case DW_ABRV_AUTO_LOCLIST, DW_ABRV_AUTO_CONCRETE_LOCLIST, 1616 DW_ABRV_PARAM_LOCLIST, DW_ABRV_PARAM_CONCRETE_LOCLIST: 1617 return true 1618 default: 1619 return false 1620 } 1621 } 1622 1623 1624 func putAbstractVar(ctxt Context, info Sym, v *Var) { 1625 1626 abbrev := v.Abbrev 1627 switch abbrev { 1628 case DW_ABRV_AUTO, DW_ABRV_AUTO_LOCLIST: 1629 abbrev = DW_ABRV_AUTO_ABSTRACT 1630 case DW_ABRV_PARAM, DW_ABRV_PARAM_LOCLIST: 1631 abbrev = DW_ABRV_PARAM_ABSTRACT 1632 } 1633 1634 Uleb128put(ctxt, info, int64(abbrev)) 1635 putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name) 1636 1637 1638 if abbrev == DW_ABRV_PARAM_ABSTRACT { 1639 var isReturn int64 1640 if v.IsReturnValue { 1641 isReturn = 1 1642 } 1643 putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) 1644 } 1645 1646 1647 if abbrev != DW_ABRV_PARAM_ABSTRACT { 1648 1649 putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) 1650 } 1651 1652 1653 putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) 1654 1655 1656 } 1657 1658 func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) { 1659 1660 abbrev, missing, concrete := determineVarAbbrev(v, fnabbrev) 1661 1662 Uleb128put(ctxt, s.Info, int64(abbrev)) 1663 1664 1665 if concrete { 1666 1667 1668 1669 1670 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn) 1671 ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex) 1672 } else { 1673 1674 n := v.Name 1675 putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) 1676 if abbrev == DW_ABRV_PARAM || abbrev == DW_ABRV_PARAM_LOCLIST || abbrev == DW_ABRV_PARAM_ABSTRACT { 1677 var isReturn int64 1678 if v.IsReturnValue { 1679 isReturn = 1 1680 } 1681 putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) 1682 } 1683 putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) 1684 if v.DictIndex > 0 && s.dictIndexToOffset != nil && s.dictIndexToOffset[v.DictIndex-1] != 0 { 1685 1686 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, s.dictIndexToOffset[v.DictIndex-1], s.Info) 1687 } else { 1688 putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) 1689 } 1690 } 1691 1692 if abbrevUsesLoclist(abbrev) { 1693 putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Loc.Length(ctxt), s.Loc) 1694 v.PutLocationList(s.Loc, s.StartPC) 1695 } else { 1696 loc := encbuf[:0] 1697 switch { 1698 case missing: 1699 break 1700 case v.StackOffset == 0: 1701 loc = append(loc, DW_OP_call_frame_cfa) 1702 default: 1703 loc = append(loc, DW_OP_fbreg) 1704 loc = AppendSleb128(loc, int64(v.StackOffset)) 1705 } 1706 putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) 1707 } 1708 1709 1710 } 1711 1712 1713 type byChildIndex []*Var 1714 1715 func (s byChildIndex) Len() int { return len(s) } 1716 func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex } 1717 func (s byChildIndex) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 1718 1719 1720 1721 1722 1723 func IsDWARFEnabledOnAIXLd(extld []string) (bool, error) { 1724 name, args := extld[0], extld[1:] 1725 args = append(args, "-Wl,-V") 1726 out, err := exec.Command(name, args...).CombinedOutput() 1727 if err != nil { 1728 1729 1730 1731 if !bytes.Contains(out, []byte("0711-317")) { 1732 return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out) 1733 } 1734 } 1735 1736 1737 1738 out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD ")) 1739 vers := string(bytes.Split(out, []byte("("))[0]) 1740 subvers := strings.Split(vers, ".") 1741 if len(subvers) != 3 { 1742 return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err) 1743 } 1744 if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 { 1745 return false, nil 1746 } else if v > 7 { 1747 return true, nil 1748 } 1749 if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 { 1750 return false, nil 1751 } else if v > 2 { 1752 return true, nil 1753 } 1754 if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 { 1755 return false, nil 1756 } 1757 return true, nil 1758 }