github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/ld/dwarf.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/ld/dwarf.go 2 3 // Copyright 2010 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 // TODO/NICETOHAVE: 8 // - eliminate DW_CLS_ if not used 9 // - package info in compilation units 10 // - assign global variables and types to their packages 11 // - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg 12 // ptype struct '[]uint8' and qualifiers need to be quoted away 13 // - lexical scoping is lost, so gdb gets confused as to which 'main.i' you mean. 14 // - file:line info for variables 15 // - make strings a typedef so prettyprinters can see the underlying string type 16 17 package ld 18 19 import ( 20 "rsc.io/tmp/bootstrap/internal/obj" 21 "fmt" 22 "strings" 23 ) 24 25 /* 26 * Offsets and sizes of the debug_* sections in the cout file. 27 */ 28 var abbrevo int64 29 30 var abbrevsize int64 31 32 var abbrevsym *LSym 33 34 var abbrevsympos int64 35 36 var lineo int64 37 38 var linesize int64 39 40 var linesym *LSym 41 42 var linesympos int64 43 44 var infoo int64 // also the base for DWDie->offs and reference attributes. 45 46 var infosize int64 47 48 var infosym *LSym 49 50 var infosympos int64 51 52 var frameo int64 53 54 var framesize int64 55 56 var framesym *LSym 57 58 var framesympos int64 59 60 var pubnameso int64 61 62 var pubnamessize int64 63 64 var pubtypeso int64 65 66 var pubtypessize int64 67 68 var arangeso int64 69 70 var arangessize int64 71 72 var gdbscripto int64 73 74 var gdbscriptsize int64 75 76 var infosec *LSym 77 78 var inforeloco int64 79 80 var inforelocsize int64 81 82 var arangessec *LSym 83 84 var arangesreloco int64 85 86 var arangesrelocsize int64 87 88 var linesec *LSym 89 90 var linereloco int64 91 92 var linerelocsize int64 93 94 var framesec *LSym 95 96 var framereloco int64 97 98 var framerelocsize int64 99 100 var gdbscript string 101 102 /* 103 * Basic I/O 104 */ 105 func addrput(addr int64) { 106 switch Thearch.Ptrsize { 107 case 4: 108 Thearch.Lput(uint32(addr)) 109 110 case 8: 111 Thearch.Vput(uint64(addr)) 112 } 113 } 114 115 func uleb128enc(v uint64, dst []byte) int { 116 var c uint8 117 118 length := uint8(0) 119 for { 120 c = uint8(v & 0x7f) 121 v >>= 7 122 if v != 0 { 123 c |= 0x80 124 } 125 if dst != nil { 126 dst[0] = byte(c) 127 dst = dst[1:] 128 } 129 length++ 130 if c&0x80 == 0 { 131 break 132 } 133 } 134 135 return int(length) 136 } 137 138 func sleb128enc(v int64, dst []byte) int { 139 var c uint8 140 var s uint8 141 142 length := uint8(0) 143 for { 144 c = uint8(v & 0x7f) 145 s = uint8(v & 0x40) 146 v >>= 7 147 if (v != -1 || s == 0) && (v != 0 || s != 0) { 148 c |= 0x80 149 } 150 if dst != nil { 151 dst[0] = byte(c) 152 dst = dst[1:] 153 } 154 length++ 155 if c&0x80 == 0 { 156 break 157 } 158 } 159 160 return int(length) 161 } 162 163 var encbuf [10]byte 164 165 func uleb128put(v int64) { 166 n := uleb128enc(uint64(v), encbuf[:]) 167 Cwrite(encbuf[:n]) 168 } 169 170 func sleb128put(v int64) { 171 n := sleb128enc(v, encbuf[:]) 172 Cwrite(encbuf[:n]) 173 } 174 175 /* 176 * Defining Abbrevs. This is hardcoded, and there will be 177 * only a handful of them. The DWARF spec places no restriction on 178 * the ordering of attributes in the Abbrevs and DIEs, and we will 179 * always write them out in the order of declaration in the abbrev. 180 */ 181 type DWAttrForm struct { 182 attr uint16 183 form uint8 184 } 185 186 // Go-specific type attributes. 187 const ( 188 DW_AT_go_kind = 0x2900 189 DW_AT_go_key = 0x2901 190 DW_AT_go_elem = 0x2902 191 192 DW_AT_internal_location = 253 // params and locals; not emitted 193 ) 194 195 // Index into the abbrevs table below. 196 // Keep in sync with ispubname() and ispubtype() below. 197 // ispubtype considers >= NULLTYPE public 198 const ( 199 DW_ABRV_NULL = iota 200 DW_ABRV_COMPUNIT 201 DW_ABRV_FUNCTION 202 DW_ABRV_VARIABLE 203 DW_ABRV_AUTO 204 DW_ABRV_PARAM 205 DW_ABRV_STRUCTFIELD 206 DW_ABRV_FUNCTYPEPARAM 207 DW_ABRV_DOTDOTDOT 208 DW_ABRV_ARRAYRANGE 209 DW_ABRV_NULLTYPE 210 DW_ABRV_BASETYPE 211 DW_ABRV_ARRAYTYPE 212 DW_ABRV_CHANTYPE 213 DW_ABRV_FUNCTYPE 214 DW_ABRV_IFACETYPE 215 DW_ABRV_MAPTYPE 216 DW_ABRV_PTRTYPE 217 DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6. 218 DW_ABRV_SLICETYPE 219 DW_ABRV_STRINGTYPE 220 DW_ABRV_STRUCTTYPE 221 DW_ABRV_TYPEDECL 222 DW_NABRV 223 ) 224 225 type DWAbbrev struct { 226 tag uint8 227 children uint8 228 attr []DWAttrForm 229 } 230 231 var abbrevs = [DW_NABRV]DWAbbrev{ 232 /* The mandatory DW_ABRV_NULL entry. */ 233 {0, 0, []DWAttrForm{}}, 234 235 /* COMPUNIT */ 236 { 237 DW_TAG_compile_unit, 238 DW_CHILDREN_yes, 239 []DWAttrForm{ 240 {DW_AT_name, DW_FORM_string}, 241 {DW_AT_language, DW_FORM_data1}, 242 {DW_AT_low_pc, DW_FORM_addr}, 243 {DW_AT_high_pc, DW_FORM_addr}, 244 {DW_AT_stmt_list, DW_FORM_data4}, 245 }, 246 }, 247 248 /* FUNCTION */ 249 { 250 DW_TAG_subprogram, 251 DW_CHILDREN_yes, 252 []DWAttrForm{ 253 {DW_AT_name, DW_FORM_string}, 254 {DW_AT_low_pc, DW_FORM_addr}, 255 {DW_AT_high_pc, DW_FORM_addr}, 256 {DW_AT_external, DW_FORM_flag}, 257 }, 258 }, 259 260 /* VARIABLE */ 261 { 262 DW_TAG_variable, 263 DW_CHILDREN_no, 264 []DWAttrForm{ 265 {DW_AT_name, DW_FORM_string}, 266 {DW_AT_location, DW_FORM_block1}, 267 {DW_AT_type, DW_FORM_ref_addr}, 268 {DW_AT_external, DW_FORM_flag}, 269 }, 270 }, 271 272 /* AUTO */ 273 { 274 DW_TAG_variable, 275 DW_CHILDREN_no, 276 []DWAttrForm{ 277 {DW_AT_name, DW_FORM_string}, 278 {DW_AT_location, DW_FORM_block1}, 279 {DW_AT_type, DW_FORM_ref_addr}, 280 }, 281 }, 282 283 /* PARAM */ 284 { 285 DW_TAG_formal_parameter, 286 DW_CHILDREN_no, 287 []DWAttrForm{ 288 {DW_AT_name, DW_FORM_string}, 289 {DW_AT_location, DW_FORM_block1}, 290 {DW_AT_type, DW_FORM_ref_addr}, 291 }, 292 }, 293 294 /* STRUCTFIELD */ 295 { 296 DW_TAG_member, 297 DW_CHILDREN_no, 298 []DWAttrForm{ 299 {DW_AT_name, DW_FORM_string}, 300 {DW_AT_data_member_location, DW_FORM_block1}, 301 {DW_AT_type, DW_FORM_ref_addr}, 302 }, 303 }, 304 305 /* FUNCTYPEPARAM */ 306 { 307 DW_TAG_formal_parameter, 308 DW_CHILDREN_no, 309 310 // No name! 311 []DWAttrForm{ 312 {DW_AT_type, DW_FORM_ref_addr}, 313 }, 314 }, 315 316 /* DOTDOTDOT */ 317 { 318 DW_TAG_unspecified_parameters, 319 DW_CHILDREN_no, 320 []DWAttrForm{}, 321 }, 322 323 /* ARRAYRANGE */ 324 { 325 DW_TAG_subrange_type, 326 DW_CHILDREN_no, 327 328 // No name! 329 []DWAttrForm{ 330 {DW_AT_type, DW_FORM_ref_addr}, 331 {DW_AT_count, DW_FORM_udata}, 332 }, 333 }, 334 335 // Below here are the types considered public by ispubtype 336 /* NULLTYPE */ 337 { 338 DW_TAG_unspecified_type, 339 DW_CHILDREN_no, 340 []DWAttrForm{ 341 {DW_AT_name, DW_FORM_string}, 342 }, 343 }, 344 345 /* BASETYPE */ 346 { 347 DW_TAG_base_type, 348 DW_CHILDREN_no, 349 []DWAttrForm{ 350 {DW_AT_name, DW_FORM_string}, 351 {DW_AT_encoding, DW_FORM_data1}, 352 {DW_AT_byte_size, DW_FORM_data1}, 353 {DW_AT_go_kind, DW_FORM_data1}, 354 }, 355 }, 356 357 /* ARRAYTYPE */ 358 // child is subrange with upper bound 359 { 360 DW_TAG_array_type, 361 DW_CHILDREN_yes, 362 []DWAttrForm{ 363 {DW_AT_name, DW_FORM_string}, 364 {DW_AT_type, DW_FORM_ref_addr}, 365 {DW_AT_byte_size, DW_FORM_udata}, 366 {DW_AT_go_kind, DW_FORM_data1}, 367 }, 368 }, 369 370 /* CHANTYPE */ 371 { 372 DW_TAG_typedef, 373 DW_CHILDREN_no, 374 []DWAttrForm{ 375 {DW_AT_name, DW_FORM_string}, 376 {DW_AT_type, DW_FORM_ref_addr}, 377 {DW_AT_go_kind, DW_FORM_data1}, 378 {DW_AT_go_elem, DW_FORM_ref_addr}, 379 }, 380 }, 381 382 /* FUNCTYPE */ 383 { 384 DW_TAG_subroutine_type, 385 DW_CHILDREN_yes, 386 []DWAttrForm{ 387 {DW_AT_name, DW_FORM_string}, 388 // {DW_AT_type, DW_FORM_ref_addr}, 389 {DW_AT_go_kind, DW_FORM_data1}, 390 }, 391 }, 392 393 /* IFACETYPE */ 394 { 395 DW_TAG_typedef, 396 DW_CHILDREN_yes, 397 []DWAttrForm{ 398 {DW_AT_name, DW_FORM_string}, 399 {DW_AT_type, DW_FORM_ref_addr}, 400 {DW_AT_go_kind, DW_FORM_data1}, 401 }, 402 }, 403 404 /* MAPTYPE */ 405 { 406 DW_TAG_typedef, 407 DW_CHILDREN_no, 408 []DWAttrForm{ 409 {DW_AT_name, DW_FORM_string}, 410 {DW_AT_type, DW_FORM_ref_addr}, 411 {DW_AT_go_kind, DW_FORM_data1}, 412 {DW_AT_go_key, DW_FORM_ref_addr}, 413 {DW_AT_go_elem, DW_FORM_ref_addr}, 414 }, 415 }, 416 417 /* PTRTYPE */ 418 { 419 DW_TAG_pointer_type, 420 DW_CHILDREN_no, 421 []DWAttrForm{ 422 {DW_AT_name, DW_FORM_string}, 423 {DW_AT_type, DW_FORM_ref_addr}, 424 {DW_AT_go_kind, DW_FORM_data1}, 425 }, 426 }, 427 428 /* BARE_PTRTYPE */ 429 { 430 DW_TAG_pointer_type, 431 DW_CHILDREN_no, 432 []DWAttrForm{ 433 {DW_AT_name, DW_FORM_string}, 434 }, 435 }, 436 437 /* SLICETYPE */ 438 { 439 DW_TAG_structure_type, 440 DW_CHILDREN_yes, 441 []DWAttrForm{ 442 {DW_AT_name, DW_FORM_string}, 443 {DW_AT_byte_size, DW_FORM_udata}, 444 {DW_AT_go_kind, DW_FORM_data1}, 445 {DW_AT_go_elem, DW_FORM_ref_addr}, 446 }, 447 }, 448 449 /* STRINGTYPE */ 450 { 451 DW_TAG_structure_type, 452 DW_CHILDREN_yes, 453 []DWAttrForm{ 454 {DW_AT_name, DW_FORM_string}, 455 {DW_AT_byte_size, DW_FORM_udata}, 456 {DW_AT_go_kind, DW_FORM_data1}, 457 }, 458 }, 459 460 /* STRUCTTYPE */ 461 { 462 DW_TAG_structure_type, 463 DW_CHILDREN_yes, 464 []DWAttrForm{ 465 {DW_AT_name, DW_FORM_string}, 466 {DW_AT_byte_size, DW_FORM_udata}, 467 {DW_AT_go_kind, DW_FORM_data1}, 468 }, 469 }, 470 471 /* TYPEDECL */ 472 { 473 DW_TAG_typedef, 474 DW_CHILDREN_no, 475 []DWAttrForm{ 476 {DW_AT_name, DW_FORM_string}, 477 {DW_AT_type, DW_FORM_ref_addr}, 478 }, 479 }, 480 } 481 482 func writeabbrev() { 483 abbrevo = Cpos() 484 for i := 1; i < DW_NABRV; i++ { 485 // See section 7.5.3 486 uleb128put(int64(i)) 487 488 uleb128put(int64(abbrevs[i].tag)) 489 Cput(abbrevs[i].children) 490 for _, f := range abbrevs[i].attr { 491 uleb128put(int64(f.attr)) 492 uleb128put(int64(f.form)) 493 } 494 uleb128put(0) 495 uleb128put(0) 496 } 497 498 Cput(0) 499 abbrevsize = Cpos() - abbrevo 500 } 501 502 /* 503 * Debugging Information Entries and their attributes. 504 */ 505 const ( 506 HASHSIZE = 107 507 ) 508 509 func dwarfhashstr(s string) uint32 { 510 h := uint32(0) 511 for s != "" { 512 h = h + h + h + uint32(s[0]) 513 s = s[1:] 514 } 515 return h % HASHSIZE 516 } 517 518 // For DW_CLS_string and _block, value should contain the length, and 519 // data the data, for _reference, value is 0 and data is a DWDie* to 520 // the referenced instance, for all others, value is the whole thing 521 // and data is null. 522 523 type DWAttr struct { 524 link *DWAttr 525 atr uint16 // DW_AT_ 526 cls uint8 // DW_CLS_ 527 value int64 528 data interface{} 529 } 530 531 type DWDie struct { 532 abbrev int 533 link *DWDie 534 child *DWDie 535 attr *DWAttr 536 // offset into .debug_info section, i.e relative to 537 // infoo. only valid after call to putdie() 538 offs int64 539 hash []*DWDie // optional index of children by name, enabled by mkindex() 540 hlink *DWDie // bucket chain in parent's index 541 } 542 543 /* 544 * Root DIEs for compilation units, types and global variables. 545 */ 546 var dwroot DWDie 547 548 var dwtypes DWDie 549 550 var dwglobals DWDie 551 552 func newattr(die *DWDie, attr uint16, cls int, value int64, data interface{}) *DWAttr { 553 a := new(DWAttr) 554 a.link = die.attr 555 die.attr = a 556 a.atr = attr 557 a.cls = uint8(cls) 558 a.value = value 559 a.data = data 560 return a 561 } 562 563 // Each DIE (except the root ones) has at least 1 attribute: its 564 // name. getattr moves the desired one to the front so 565 // frequently searched ones are found faster. 566 func getattr(die *DWDie, attr uint16) *DWAttr { 567 if die.attr.atr == attr { 568 return die.attr 569 } 570 571 a := die.attr 572 b := a.link 573 for b != nil { 574 if b.atr == attr { 575 a.link = b.link 576 b.link = die.attr 577 die.attr = b 578 return b 579 } 580 581 a = b 582 b = b.link 583 } 584 585 return nil 586 } 587 588 // Every DIE has at least a DW_AT_name attribute (but it will only be 589 // written out if it is listed in the abbrev). If its parent is 590 // keeping an index, the new DIE will be inserted there. 591 func newdie(parent *DWDie, abbrev int, name string) *DWDie { 592 die := new(DWDie) 593 die.abbrev = abbrev 594 die.link = parent.child 595 parent.child = die 596 597 newattr(die, DW_AT_name, DW_CLS_STRING, int64(len(name)), name) 598 599 if parent.hash != nil { 600 h := int(dwarfhashstr(name)) 601 die.hlink = parent.hash[h] 602 parent.hash[h] = die 603 } 604 605 return die 606 } 607 608 func mkindex(die *DWDie) { 609 die.hash = make([]*DWDie, HASHSIZE) 610 } 611 612 func walktypedef(die *DWDie) *DWDie { 613 // Resolve typedef if present. 614 if die.abbrev == DW_ABRV_TYPEDECL { 615 for attr := die.attr; attr != nil; attr = attr.link { 616 if attr.atr == DW_AT_type && attr.cls == DW_CLS_REFERENCE && attr.data != nil { 617 return attr.data.(*DWDie) 618 } 619 } 620 } 621 622 return die 623 } 624 625 // Find child by AT_name using hashtable if available or linear scan 626 // if not. 627 func find(die *DWDie, name string) *DWDie { 628 var a *DWDie 629 var b *DWDie 630 var die2 *DWDie 631 var h int 632 633 top: 634 if die.hash == nil { 635 for a = die.child; a != nil; a = a.link { 636 if name == getattr(a, DW_AT_name).data { 637 return a 638 } 639 } 640 goto notfound 641 } 642 643 h = int(dwarfhashstr(name)) 644 a = die.hash[h] 645 646 if a == nil { 647 goto notfound 648 } 649 650 if name == getattr(a, DW_AT_name).data { 651 return a 652 } 653 654 // Move found ones to head of the list. 655 b = a.hlink 656 657 for b != nil { 658 if name == getattr(b, DW_AT_name).data { 659 a.hlink = b.hlink 660 b.hlink = die.hash[h] 661 die.hash[h] = b 662 return b 663 } 664 665 a = b 666 b = b.hlink 667 } 668 669 notfound: 670 die2 = walktypedef(die) 671 if die2 != die { 672 die = die2 673 goto top 674 } 675 676 return nil 677 } 678 679 func mustFind(die *DWDie, name string) *DWDie { 680 r := find(die, name) 681 if r == nil { 682 Exitf("dwarf find: %s %p has no %s", getattr(die, DW_AT_name).data, die, name) 683 } 684 return r 685 } 686 687 func adddwarfrel(sec *LSym, sym *LSym, offsetbase int64, siz int, addend int64) { 688 r := Addrel(sec) 689 r.Sym = sym 690 r.Xsym = sym 691 r.Off = int32(Cpos() - offsetbase) 692 r.Siz = uint8(siz) 693 r.Type = obj.R_ADDR 694 r.Add = addend 695 r.Xadd = addend 696 if Iself && Thearch.Thechar == '6' { 697 addend = 0 698 } 699 switch siz { 700 case 4: 701 Thearch.Lput(uint32(addend)) 702 703 case 8: 704 Thearch.Vput(uint64(addend)) 705 706 default: 707 Diag("bad size in adddwarfrel") 708 } 709 } 710 711 func newrefattr(die *DWDie, attr uint16, ref *DWDie) *DWAttr { 712 if ref == nil { 713 return nil 714 } 715 return newattr(die, attr, DW_CLS_REFERENCE, 0, ref) 716 } 717 718 var fwdcount int 719 720 func putattr(abbrev int, form int, cls int, value int64, data interface{}) { 721 switch form { 722 case DW_FORM_addr: // address 723 if Linkmode == LinkExternal { 724 value -= (data.(*LSym)).Value 725 adddwarfrel(infosec, data.(*LSym), infoo, Thearch.Ptrsize, value) 726 break 727 } 728 729 addrput(value) 730 731 case DW_FORM_block1: // block 732 if cls == DW_CLS_ADDRESS { 733 Cput(uint8(1 + Thearch.Ptrsize)) 734 Cput(DW_OP_addr) 735 if Linkmode == LinkExternal { 736 value -= (data.(*LSym)).Value 737 adddwarfrel(infosec, data.(*LSym), infoo, Thearch.Ptrsize, value) 738 break 739 } 740 741 addrput(value) 742 break 743 } 744 745 value &= 0xff 746 Cput(uint8(value)) 747 p := data.([]byte) 748 for i := 0; int64(i) < value; i++ { 749 Cput(uint8(p[i])) 750 } 751 752 case DW_FORM_block2: // block 753 value &= 0xffff 754 755 Thearch.Wput(uint16(value)) 756 p := data.([]byte) 757 for i := 0; int64(i) < value; i++ { 758 Cput(uint8(p[i])) 759 } 760 761 case DW_FORM_block4: // block 762 value &= 0xffffffff 763 764 Thearch.Lput(uint32(value)) 765 p := data.([]byte) 766 for i := 0; int64(i) < value; i++ { 767 Cput(uint8(p[i])) 768 } 769 770 case DW_FORM_block: // block 771 uleb128put(value) 772 773 p := data.([]byte) 774 for i := 0; int64(i) < value; i++ { 775 Cput(uint8(p[i])) 776 } 777 778 case DW_FORM_data1: // constant 779 Cput(uint8(value)) 780 781 case DW_FORM_data2: // constant 782 Thearch.Wput(uint16(value)) 783 784 case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr 785 if Linkmode == LinkExternal && cls == DW_CLS_PTR { 786 adddwarfrel(infosec, linesym, infoo, 4, value) 787 break 788 } 789 790 Thearch.Lput(uint32(value)) 791 792 case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr 793 Thearch.Vput(uint64(value)) 794 795 case DW_FORM_sdata: // constant 796 sleb128put(value) 797 798 case DW_FORM_udata: // constant 799 uleb128put(value) 800 801 case DW_FORM_string: // string 802 strnput(data.(string), int(value+1)) 803 804 case DW_FORM_flag: // flag 805 if value != 0 { 806 Cput(1) 807 } else { 808 Cput(0) 809 } 810 811 // In DWARF 2 (which is what we claim to generate), 812 // the ref_addr is the same size as a normal address. 813 // In DWARF 3 it is always 32 bits, unless emitting a large 814 // (> 4 GB of debug info aka "64-bit") unit, which we don't implement. 815 case DW_FORM_ref_addr: // reference to a DIE in the .info section 816 if data == nil { 817 Diag("dwarf: null reference in %d", abbrev) 818 if Thearch.Ptrsize == 8 { 819 Thearch.Vput(0) // invalid dwarf, gdb will complain. 820 } else { 821 Thearch.Lput(0) // invalid dwarf, gdb will complain. 822 } 823 } else { 824 off := (data.(*DWDie)).offs 825 if off == 0 { 826 fwdcount++ 827 } 828 if Linkmode == LinkExternal { 829 adddwarfrel(infosec, infosym, infoo, Thearch.Ptrsize, off) 830 break 831 } 832 833 addrput(off) 834 } 835 836 case DW_FORM_ref1, // reference within the compilation unit 837 DW_FORM_ref2, // reference 838 DW_FORM_ref4, // reference 839 DW_FORM_ref8, // reference 840 DW_FORM_ref_udata, // reference 841 842 DW_FORM_strp, // string 843 DW_FORM_indirect: // (see Section 7.5.3) 844 fallthrough 845 default: 846 Exitf("dwarf: unsupported attribute form %d / class %d", form, cls) 847 } 848 } 849 850 // Note that we can (and do) add arbitrary attributes to a DIE, but 851 // only the ones actually listed in the Abbrev will be written out. 852 func putattrs(abbrev int, attr *DWAttr) { 853 Outer: 854 for _, f := range abbrevs[abbrev].attr { 855 for ap := attr; ap != nil; ap = ap.link { 856 if ap.atr == f.attr { 857 putattr(abbrev, int(f.form), int(ap.cls), ap.value, ap.data) 858 continue Outer 859 } 860 } 861 862 putattr(abbrev, int(f.form), 0, 0, nil) 863 } 864 } 865 866 func putdies(die *DWDie) { 867 for ; die != nil; die = die.link { 868 putdie(die) 869 } 870 } 871 872 func putdie(die *DWDie) { 873 die.offs = Cpos() - infoo 874 uleb128put(int64(die.abbrev)) 875 putattrs(die.abbrev, die.attr) 876 if abbrevs[die.abbrev].children != 0 { 877 putdies(die.child) 878 Cput(0) 879 } 880 } 881 882 func reverselist(list **DWDie) { 883 curr := *list 884 var prev *DWDie 885 for curr != nil { 886 var next *DWDie = curr.link 887 curr.link = prev 888 prev = curr 889 curr = next 890 } 891 892 *list = prev 893 } 894 895 func reversetree(list **DWDie) { 896 reverselist(list) 897 for die := *list; die != nil; die = die.link { 898 if abbrevs[die.abbrev].children != 0 { 899 reversetree(&die.child) 900 } 901 } 902 } 903 904 func newmemberoffsetattr(die *DWDie, offs int32) { 905 var block [20]byte 906 907 i := 0 908 block[i] = DW_OP_plus_uconst 909 i++ 910 i += uleb128enc(uint64(offs), block[i:]) 911 newattr(die, DW_AT_data_member_location, DW_CLS_BLOCK, int64(i), block[:i]) 912 } 913 914 // GDB doesn't like DW_FORM_addr for DW_AT_location, so emit a 915 // location expression that evals to a const. 916 func newabslocexprattr(die *DWDie, addr int64, sym *LSym) { 917 newattr(die, DW_AT_location, DW_CLS_ADDRESS, addr, sym) 918 // below 919 } 920 921 // Lookup predefined types 922 func lookup_or_diag(n string) *LSym { 923 s := Linkrlookup(Ctxt, n, 0) 924 if s == nil || s.Size == 0 { 925 Exitf("dwarf: missing type: %s", n) 926 } 927 928 return s 929 } 930 931 func dotypedef(parent *DWDie, name string, def *DWDie) { 932 // Only emit typedefs for real names. 933 if strings.HasPrefix(name, "map[") { 934 return 935 } 936 if strings.HasPrefix(name, "struct {") { 937 return 938 } 939 if strings.HasPrefix(name, "chan ") { 940 return 941 } 942 if name[0] == '[' || name[0] == '*' { 943 return 944 } 945 if def == nil { 946 Diag("dwarf: bad def in dotypedef") 947 } 948 949 // The typedef entry must be created after the def, 950 // so that future lookups will find the typedef instead 951 // of the real definition. This hooks the typedef into any 952 // circular definition loops, so that gdb can understand them. 953 die := newdie(parent, DW_ABRV_TYPEDECL, name) 954 955 newrefattr(die, DW_AT_type, def) 956 } 957 958 // Define gotype, for composite ones recurse into constituents. 959 func defgotype(gotype *LSym) *DWDie { 960 if gotype == nil { 961 return mustFind(&dwtypes, "<unspecified>") 962 } 963 964 if !strings.HasPrefix(gotype.Name, "type.") { 965 Diag("dwarf: type name doesn't start with \".type\": %s", gotype.Name) 966 return mustFind(&dwtypes, "<unspecified>") 967 } 968 969 name := gotype.Name[5:] // could also decode from Type.string 970 971 die := find(&dwtypes, name) 972 973 if die != nil { 974 return die 975 } 976 977 if false && Debug['v'] > 2 { 978 fmt.Printf("new type: %v\n", gotype) 979 } 980 981 kind := decodetype_kind(gotype) 982 bytesize := decodetype_size(gotype) 983 984 switch kind { 985 case obj.KindBool: 986 die = newdie(&dwtypes, DW_ABRV_BASETYPE, name) 987 newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_boolean, 0) 988 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 989 990 case obj.KindInt, 991 obj.KindInt8, 992 obj.KindInt16, 993 obj.KindInt32, 994 obj.KindInt64: 995 die = newdie(&dwtypes, DW_ABRV_BASETYPE, name) 996 newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_signed, 0) 997 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 998 999 case obj.KindUint, 1000 obj.KindUint8, 1001 obj.KindUint16, 1002 obj.KindUint32, 1003 obj.KindUint64, 1004 obj.KindUintptr: 1005 die = newdie(&dwtypes, DW_ABRV_BASETYPE, name) 1006 newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0) 1007 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 1008 1009 case obj.KindFloat32, 1010 obj.KindFloat64: 1011 die = newdie(&dwtypes, DW_ABRV_BASETYPE, name) 1012 newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_float, 0) 1013 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 1014 1015 case obj.KindComplex64, 1016 obj.KindComplex128: 1017 die = newdie(&dwtypes, DW_ABRV_BASETYPE, name) 1018 newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_complex_float, 0) 1019 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 1020 1021 case obj.KindArray: 1022 die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name) 1023 dotypedef(&dwtypes, name, die) 1024 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 1025 s := decodetype_arrayelem(gotype) 1026 newrefattr(die, DW_AT_type, defgotype(s)) 1027 fld := newdie(die, DW_ABRV_ARRAYRANGE, "range") 1028 1029 // use actual length not upper bound; correct for 0-length arrays. 1030 newattr(fld, DW_AT_count, DW_CLS_CONSTANT, decodetype_arraylen(gotype), 0) 1031 1032 newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr")) 1033 1034 case obj.KindChan: 1035 die = newdie(&dwtypes, DW_ABRV_CHANTYPE, name) 1036 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 1037 s := decodetype_chanelem(gotype) 1038 newrefattr(die, DW_AT_go_elem, defgotype(s)) 1039 1040 case obj.KindFunc: 1041 die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name) 1042 dotypedef(&dwtypes, name, die) 1043 newrefattr(die, DW_AT_type, mustFind(&dwtypes, "void")) 1044 nfields := decodetype_funcincount(gotype) 1045 var fld *DWDie 1046 var s *LSym 1047 for i := 0; i < nfields; i++ { 1048 s = decodetype_funcintype(gotype, i) 1049 fld = newdie(die, DW_ABRV_FUNCTYPEPARAM, s.Name[5:]) 1050 newrefattr(fld, DW_AT_type, defgotype(s)) 1051 } 1052 1053 if decodetype_funcdotdotdot(gotype) != 0 { 1054 newdie(die, DW_ABRV_DOTDOTDOT, "...") 1055 } 1056 nfields = decodetype_funcoutcount(gotype) 1057 for i := 0; i < nfields; i++ { 1058 s = decodetype_funcouttype(gotype, i) 1059 fld = newdie(die, DW_ABRV_FUNCTYPEPARAM, s.Name[5:]) 1060 newrefattr(fld, DW_AT_type, defptrto(defgotype(s))) 1061 } 1062 1063 case obj.KindInterface: 1064 die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name) 1065 dotypedef(&dwtypes, name, die) 1066 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 1067 nfields := int(decodetype_ifacemethodcount(gotype)) 1068 var s *LSym 1069 if nfields == 0 { 1070 s = lookup_or_diag("type.runtime.eface") 1071 } else { 1072 s = lookup_or_diag("type.runtime.iface") 1073 } 1074 newrefattr(die, DW_AT_type, defgotype(s)) 1075 1076 case obj.KindMap: 1077 die = newdie(&dwtypes, DW_ABRV_MAPTYPE, name) 1078 s := decodetype_mapkey(gotype) 1079 newrefattr(die, DW_AT_go_key, defgotype(s)) 1080 s = decodetype_mapvalue(gotype) 1081 newrefattr(die, DW_AT_go_elem, defgotype(s)) 1082 1083 case obj.KindPtr: 1084 die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name) 1085 dotypedef(&dwtypes, name, die) 1086 s := decodetype_ptrelem(gotype) 1087 newrefattr(die, DW_AT_type, defgotype(s)) 1088 1089 case obj.KindSlice: 1090 die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name) 1091 dotypedef(&dwtypes, name, die) 1092 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 1093 s := decodetype_arrayelem(gotype) 1094 newrefattr(die, DW_AT_go_elem, defgotype(s)) 1095 1096 case obj.KindString: 1097 die = newdie(&dwtypes, DW_ABRV_STRINGTYPE, name) 1098 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 1099 1100 case obj.KindStruct: 1101 die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name) 1102 dotypedef(&dwtypes, name, die) 1103 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) 1104 nfields := decodetype_structfieldcount(gotype) 1105 var f string 1106 var fld *DWDie 1107 var s *LSym 1108 for i := 0; i < nfields; i++ { 1109 f = decodetype_structfieldname(gotype, i) 1110 s = decodetype_structfieldtype(gotype, i) 1111 if f == "" { 1112 f = s.Name[5:] // skip "type." 1113 } 1114 fld = newdie(die, DW_ABRV_STRUCTFIELD, f) 1115 newrefattr(fld, DW_AT_type, defgotype(s)) 1116 newmemberoffsetattr(fld, int32(decodetype_structfieldoffs(gotype, i))) 1117 } 1118 1119 case obj.KindUnsafePointer: 1120 die = newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, name) 1121 1122 default: 1123 Diag("dwarf: definition of unknown kind %d: %s", kind, gotype.Name) 1124 die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name) 1125 newrefattr(die, DW_AT_type, mustFind(&dwtypes, "<unspecified>")) 1126 } 1127 1128 newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, int64(kind), 0) 1129 1130 return die 1131 } 1132 1133 // Find or construct *T given T. 1134 func defptrto(dwtype *DWDie) *DWDie { 1135 ptrname := fmt.Sprintf("*%s", getattr(dwtype, DW_AT_name).data) 1136 die := find(&dwtypes, ptrname) 1137 if die == nil { 1138 die = newdie(&dwtypes, DW_ABRV_PTRTYPE, ptrname) 1139 newrefattr(die, DW_AT_type, dwtype) 1140 } 1141 1142 return die 1143 } 1144 1145 // Copies src's children into dst. Copies attributes by value. 1146 // DWAttr.data is copied as pointer only. If except is one of 1147 // the top-level children, it will not be copied. 1148 func copychildrenexcept(dst *DWDie, src *DWDie, except *DWDie) { 1149 var c *DWDie 1150 var a *DWAttr 1151 1152 for src = src.child; src != nil; src = src.link { 1153 if src == except { 1154 continue 1155 } 1156 c = newdie(dst, src.abbrev, getattr(src, DW_AT_name).data.(string)) 1157 for a = src.attr; a != nil; a = a.link { 1158 newattr(c, a.atr, int(a.cls), a.value, a.data) 1159 } 1160 copychildrenexcept(c, src, nil) 1161 } 1162 1163 reverselist(&dst.child) 1164 } 1165 1166 func copychildren(dst *DWDie, src *DWDie) { 1167 copychildrenexcept(dst, src, nil) 1168 } 1169 1170 // Search children (assumed to have DW_TAG_member) for the one named 1171 // field and set its DW_AT_type to dwtype 1172 func substitutetype(structdie *DWDie, field string, dwtype *DWDie) { 1173 child := mustFind(structdie, field) 1174 if child == nil { 1175 return 1176 } 1177 1178 a := getattr(child, DW_AT_type) 1179 if a != nil { 1180 a.data = dwtype 1181 } else { 1182 newrefattr(child, DW_AT_type, dwtype) 1183 } 1184 } 1185 1186 func synthesizestringtypes(die *DWDie) { 1187 prototype := walktypedef(defgotype(lookup_or_diag("type.runtime._string"))) 1188 if prototype == nil { 1189 return 1190 } 1191 1192 for ; die != nil; die = die.link { 1193 if die.abbrev != DW_ABRV_STRINGTYPE { 1194 continue 1195 } 1196 copychildren(die, prototype) 1197 } 1198 } 1199 1200 func synthesizeslicetypes(die *DWDie) { 1201 prototype := walktypedef(defgotype(lookup_or_diag("type.runtime.slice"))) 1202 if prototype == nil { 1203 return 1204 } 1205 1206 var elem *DWDie 1207 for ; die != nil; die = die.link { 1208 if die.abbrev != DW_ABRV_SLICETYPE { 1209 continue 1210 } 1211 copychildren(die, prototype) 1212 elem = getattr(die, DW_AT_go_elem).data.(*DWDie) 1213 substitutetype(die, "array", defptrto(elem)) 1214 } 1215 } 1216 1217 func mkinternaltypename(base string, arg1 string, arg2 string) string { 1218 var buf string 1219 1220 if arg2 == "" { 1221 buf = fmt.Sprintf("%s<%s>", base, arg1) 1222 } else { 1223 buf = fmt.Sprintf("%s<%s,%s>", base, arg1, arg2) 1224 } 1225 n := buf 1226 return n 1227 } 1228 1229 // synthesizemaptypes is way too closely married to runtime/hashmap.c 1230 const ( 1231 MaxKeySize = 128 1232 MaxValSize = 128 1233 BucketSize = 8 1234 ) 1235 1236 func synthesizemaptypes(die *DWDie) { 1237 hash := walktypedef(defgotype(lookup_or_diag("type.runtime.hmap"))) 1238 bucket := walktypedef(defgotype(lookup_or_diag("type.runtime.bmap"))) 1239 1240 if hash == nil { 1241 return 1242 } 1243 1244 var a *DWAttr 1245 var dwh *DWDie 1246 var dwhb *DWDie 1247 var dwhk *DWDie 1248 var dwhv *DWDie 1249 var fld *DWDie 1250 var indirect_key int 1251 var indirect_val int 1252 var keysize int 1253 var keytype *DWDie 1254 var t *DWDie 1255 var valsize int 1256 var valtype *DWDie 1257 for ; die != nil; die = die.link { 1258 if die.abbrev != DW_ABRV_MAPTYPE { 1259 continue 1260 } 1261 1262 keytype = walktypedef(getattr(die, DW_AT_go_key).data.(*DWDie)) 1263 valtype = walktypedef(getattr(die, DW_AT_go_elem).data.(*DWDie)) 1264 1265 // compute size info like hashmap.c does. 1266 a = getattr(keytype, DW_AT_byte_size) 1267 1268 if a != nil { 1269 keysize = int(a.value) 1270 } else { 1271 keysize = Thearch.Ptrsize 1272 } 1273 a = getattr(valtype, DW_AT_byte_size) 1274 if a != nil { 1275 valsize = int(a.value) 1276 } else { 1277 valsize = Thearch.Ptrsize 1278 } 1279 indirect_key = 0 1280 indirect_val = 0 1281 if keysize > MaxKeySize { 1282 keysize = Thearch.Ptrsize 1283 indirect_key = 1 1284 } 1285 1286 if valsize > MaxValSize { 1287 valsize = Thearch.Ptrsize 1288 indirect_val = 1 1289 } 1290 1291 // Construct type to represent an array of BucketSize keys 1292 dwhk = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, mkinternaltypename("[]key", getattr(keytype, DW_AT_name).data.(string), "")) 1293 1294 newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(keysize), 0) 1295 t = keytype 1296 if indirect_key != 0 { 1297 t = defptrto(keytype) 1298 } 1299 newrefattr(dwhk, DW_AT_type, t) 1300 fld = newdie(dwhk, DW_ABRV_ARRAYRANGE, "size") 1301 newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0) 1302 newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr")) 1303 1304 // Construct type to represent an array of BucketSize values 1305 dwhv = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, mkinternaltypename("[]val", getattr(valtype, DW_AT_name).data.(string), "")) 1306 1307 newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(valsize), 0) 1308 t = valtype 1309 if indirect_val != 0 { 1310 t = defptrto(valtype) 1311 } 1312 newrefattr(dwhv, DW_AT_type, t) 1313 fld = newdie(dwhv, DW_ABRV_ARRAYRANGE, "size") 1314 newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0) 1315 newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr")) 1316 1317 // Construct bucket<K,V> 1318 dwhb = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("bucket", getattr(keytype, DW_AT_name).data.(string), getattr(valtype, DW_AT_name).data.(string))) 1319 1320 // Copy over all fields except the field "data" from the generic bucket. 1321 // "data" will be replaced with keys/values below. 1322 copychildrenexcept(dwhb, bucket, find(bucket, "data")) 1323 1324 fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "keys") 1325 newrefattr(fld, DW_AT_type, dwhk) 1326 newmemberoffsetattr(fld, BucketSize) 1327 fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "values") 1328 newrefattr(fld, DW_AT_type, dwhv) 1329 newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize)) 1330 fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "overflow") 1331 newrefattr(fld, DW_AT_type, defptrto(dwhb)) 1332 newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))) 1333 if Thearch.Regsize > Thearch.Ptrsize { 1334 fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "pad") 1335 newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr")) 1336 newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(Thearch.Ptrsize)) 1337 } 1338 1339 newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize+BucketSize*int64(keysize)+BucketSize*int64(valsize)+int64(Thearch.Regsize), 0) 1340 1341 // Construct hash<K,V> 1342 dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("hash", getattr(keytype, DW_AT_name).data.(string), getattr(valtype, DW_AT_name).data.(string))) 1343 1344 copychildren(dwh, hash) 1345 substitutetype(dwh, "buckets", defptrto(dwhb)) 1346 substitutetype(dwh, "oldbuckets", defptrto(dwhb)) 1347 newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(hash, DW_AT_byte_size).value, nil) 1348 1349 // make map type a pointer to hash<K,V> 1350 newrefattr(die, DW_AT_type, defptrto(dwh)) 1351 } 1352 } 1353 1354 func synthesizechantypes(die *DWDie) { 1355 sudog := walktypedef(defgotype(lookup_or_diag("type.runtime.sudog"))) 1356 waitq := walktypedef(defgotype(lookup_or_diag("type.runtime.waitq"))) 1357 hchan := walktypedef(defgotype(lookup_or_diag("type.runtime.hchan"))) 1358 if sudog == nil || waitq == nil || hchan == nil { 1359 return 1360 } 1361 1362 sudogsize := int(getattr(sudog, DW_AT_byte_size).value) 1363 1364 var a *DWAttr 1365 var dwh *DWDie 1366 var dws *DWDie 1367 var dww *DWDie 1368 var elemsize int 1369 var elemtype *DWDie 1370 for ; die != nil; die = die.link { 1371 if die.abbrev != DW_ABRV_CHANTYPE { 1372 continue 1373 } 1374 elemtype = getattr(die, DW_AT_go_elem).data.(*DWDie) 1375 a = getattr(elemtype, DW_AT_byte_size) 1376 if a != nil { 1377 elemsize = int(a.value) 1378 } else { 1379 elemsize = Thearch.Ptrsize 1380 } 1381 1382 // sudog<T> 1383 dws = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("sudog", getattr(elemtype, DW_AT_name).data.(string), "")) 1384 1385 copychildren(dws, sudog) 1386 substitutetype(dws, "elem", elemtype) 1387 if elemsize > 8 { 1388 elemsize -= 8 1389 } else { 1390 elemsize = 0 1391 } 1392 newattr(dws, DW_AT_byte_size, DW_CLS_CONSTANT, int64(sudogsize)+int64(elemsize), nil) 1393 1394 // waitq<T> 1395 dww = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("waitq", getattr(elemtype, DW_AT_name).data.(string), "")) 1396 1397 copychildren(dww, waitq) 1398 substitutetype(dww, "first", defptrto(dws)) 1399 substitutetype(dww, "last", defptrto(dws)) 1400 newattr(dww, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(waitq, DW_AT_byte_size).value, nil) 1401 1402 // hchan<T> 1403 dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("hchan", getattr(elemtype, DW_AT_name).data.(string), "")) 1404 1405 copychildren(dwh, hchan) 1406 substitutetype(dwh, "recvq", dww) 1407 substitutetype(dwh, "sendq", dww) 1408 newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(hchan, DW_AT_byte_size).value, nil) 1409 1410 newrefattr(die, DW_AT_type, defptrto(dwh)) 1411 } 1412 } 1413 1414 // For use with pass.c::genasmsym 1415 func defdwsymb(sym *LSym, s string, t int, v int64, size int64, ver int, gotype *LSym) { 1416 if strings.HasPrefix(s, "go.string.") { 1417 return 1418 } 1419 1420 if strings.HasPrefix(s, "type.") && s != "type.*" && !strings.HasPrefix(s, "type..") { 1421 defgotype(sym) 1422 return 1423 } 1424 1425 var dv *DWDie 1426 1427 var dt *DWDie 1428 switch t { 1429 default: 1430 return 1431 1432 case 'd', 'b', 'D', 'B': 1433 dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s) 1434 newabslocexprattr(dv, v, sym) 1435 if ver == 0 { 1436 newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0) 1437 } 1438 fallthrough 1439 1440 case 'a', 'p': 1441 dt = defgotype(gotype) 1442 } 1443 1444 if dv != nil { 1445 newrefattr(dv, DW_AT_type, dt) 1446 } 1447 } 1448 1449 func movetomodule(parent *DWDie) { 1450 die := dwroot.child.child 1451 for die.link != nil { 1452 die = die.link 1453 } 1454 die.link = parent.child 1455 } 1456 1457 // If the pcln table contains runtime/runtime.go, use that to set gdbscript path. 1458 func finddebugruntimepath(s *LSym) { 1459 if gdbscript != "" { 1460 return 1461 } 1462 1463 var f *LSym 1464 var p string 1465 for i := 0; i < s.Pcln.Nfile; i++ { 1466 f = s.Pcln.File[i] 1467 _ = p 1468 if i := strings.Index(f.Name, "runtime/runtime.go"); i >= 0 { 1469 gdbscript = f.Name[:i] + "runtime/runtime-gdb.py" 1470 break 1471 } 1472 } 1473 } 1474 1475 /* 1476 * Generate short opcodes when possible, long ones when necessary. 1477 * See section 6.2.5 1478 */ 1479 const ( 1480 LINE_BASE = -1 1481 LINE_RANGE = 4 1482 OPCODE_BASE = 10 1483 ) 1484 1485 func putpclcdelta(delta_pc int64, delta_lc int64) { 1486 if LINE_BASE <= delta_lc && delta_lc < LINE_BASE+LINE_RANGE { 1487 var opcode int64 = OPCODE_BASE + (delta_lc - LINE_BASE) + (LINE_RANGE * delta_pc) 1488 if OPCODE_BASE <= opcode && opcode < 256 { 1489 Cput(uint8(opcode)) 1490 return 1491 } 1492 } 1493 1494 if delta_pc != 0 { 1495 Cput(DW_LNS_advance_pc) 1496 sleb128put(delta_pc) 1497 } 1498 1499 Cput(DW_LNS_advance_line) 1500 sleb128put(delta_lc) 1501 Cput(DW_LNS_copy) 1502 } 1503 1504 func newcfaoffsetattr(die *DWDie, offs int32) { 1505 var block [20]byte 1506 1507 i := 0 1508 1509 block[i] = DW_OP_call_frame_cfa 1510 i++ 1511 if offs != 0 { 1512 block[i] = DW_OP_consts 1513 i++ 1514 i += sleb128enc(int64(offs), block[i:]) 1515 block[i] = DW_OP_plus 1516 i++ 1517 } 1518 1519 newattr(die, DW_AT_location, DW_CLS_BLOCK, int64(i), block[:i]) 1520 } 1521 1522 func mkvarname(name string, da int) string { 1523 buf := fmt.Sprintf("%s#%d", name, da) 1524 n := buf 1525 return n 1526 } 1527 1528 /* 1529 * Walk prog table, emit line program and build DIE tree. 1530 */ 1531 1532 // flush previous compilation unit. 1533 func flushunit(dwinfo *DWDie, pc int64, pcsym *LSym, unitstart int64, header_length int32) { 1534 if dwinfo != nil && pc != 0 { 1535 newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, pcsym) 1536 } 1537 1538 if unitstart >= 0 { 1539 Cput(0) // start extended opcode 1540 uleb128put(1) 1541 Cput(DW_LNE_end_sequence) 1542 1543 here := Cpos() 1544 Cseek(unitstart) 1545 Thearch.Lput(uint32(here - unitstart - 4)) // unit_length 1546 Thearch.Wput(2) // dwarf version 1547 Thearch.Lput(uint32(header_length)) // header length starting here 1548 Cseek(here) 1549 } 1550 } 1551 1552 func writelines() { 1553 if linesec == nil { 1554 linesec = Linklookup(Ctxt, ".dwarfline", 0) 1555 } 1556 linesec.R = linesec.R[:0] 1557 1558 unitstart := int64(-1) 1559 headerend := int64(-1) 1560 epc := int64(0) 1561 var epcs *LSym 1562 lineo = Cpos() 1563 var dwinfo *DWDie 1564 1565 flushunit(dwinfo, epc, epcs, unitstart, int32(headerend-unitstart-10)) 1566 unitstart = Cpos() 1567 1568 lang := DW_LANG_Go 1569 1570 s := Ctxt.Textp 1571 1572 dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, "go") 1573 newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT, int64(lang), 0) 1574 newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart-lineo, 0) 1575 newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s.Value, s) 1576 1577 // Write .debug_line Line Number Program Header (sec 6.2.4) 1578 // Fields marked with (*) must be changed for 64-bit dwarf 1579 Thearch.Lput(0) // unit_length (*), will be filled in by flushunit. 1580 Thearch.Wput(2) // dwarf version (appendix F) 1581 Thearch.Lput(0) // header_length (*), filled in by flushunit. 1582 1583 // cpos == unitstart + 4 + 2 + 4 1584 Cput(1) // minimum_instruction_length 1585 Cput(1) // default_is_stmt 1586 Cput(LINE_BASE & 0xFF) // line_base 1587 Cput(LINE_RANGE) // line_range 1588 Cput(OPCODE_BASE) // opcode_base 1589 Cput(0) // standard_opcode_lengths[1] 1590 Cput(1) // standard_opcode_lengths[2] 1591 Cput(1) // standard_opcode_lengths[3] 1592 Cput(1) // standard_opcode_lengths[4] 1593 Cput(1) // standard_opcode_lengths[5] 1594 Cput(0) // standard_opcode_lengths[6] 1595 Cput(0) // standard_opcode_lengths[7] 1596 Cput(0) // standard_opcode_lengths[8] 1597 Cput(1) // standard_opcode_lengths[9] 1598 Cput(0) // include_directories (empty) 1599 1600 files := make([]*LSym, Ctxt.Nhistfile) 1601 1602 for f := Ctxt.Filesyms; f != nil; f = f.Next { 1603 files[f.Value-1] = f 1604 } 1605 1606 for i := 0; int32(i) < Ctxt.Nhistfile; i++ { 1607 strnput(files[i].Name, len(files[i].Name)+4) 1608 } 1609 1610 // 4 zeros: the string termination + 3 fields. 1611 Cput(0) 1612 // terminate file_names. 1613 headerend = Cpos() 1614 1615 Cput(0) // start extended opcode 1616 uleb128put(1 + int64(Thearch.Ptrsize)) 1617 Cput(DW_LNE_set_address) 1618 1619 pc := s.Value 1620 line := 1 1621 file := 1 1622 if Linkmode == LinkExternal { 1623 adddwarfrel(linesec, s, lineo, Thearch.Ptrsize, 0) 1624 } else { 1625 addrput(pc) 1626 } 1627 1628 var a *Auto 1629 var da int 1630 var dt int 1631 var dwfunc *DWDie 1632 var dws **DWDie 1633 var dwvar *DWDie 1634 var n string 1635 var nn string 1636 var offs int64 1637 var pcfile Pciter 1638 var pcline Pciter 1639 var varhash [HASHSIZE]*DWDie 1640 for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next { 1641 s = Ctxt.Cursym 1642 1643 dwfunc = newdie(dwinfo, DW_ABRV_FUNCTION, s.Name) 1644 newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s.Value, s) 1645 epc = s.Value + s.Size 1646 epcs = s 1647 newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, s) 1648 if s.Version == 0 { 1649 newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0) 1650 } 1651 1652 if s.Pcln == nil { 1653 continue 1654 } 1655 1656 finddebugruntimepath(s) 1657 1658 pciterinit(Ctxt, &pcfile, &s.Pcln.Pcfile) 1659 pciterinit(Ctxt, &pcline, &s.Pcln.Pcline) 1660 epc = pc 1661 for pcfile.done == 0 && pcline.done == 0 { 1662 if epc-s.Value >= int64(pcfile.nextpc) { 1663 pciternext(&pcfile) 1664 continue 1665 } 1666 1667 if epc-s.Value >= int64(pcline.nextpc) { 1668 pciternext(&pcline) 1669 continue 1670 } 1671 1672 if int32(file) != pcfile.value { 1673 Cput(DW_LNS_set_file) 1674 uleb128put(int64(pcfile.value)) 1675 file = int(pcfile.value) 1676 } 1677 1678 putpclcdelta(s.Value+int64(pcline.pc)-pc, int64(pcline.value)-int64(line)) 1679 1680 pc = s.Value + int64(pcline.pc) 1681 line = int(pcline.value) 1682 if pcfile.nextpc < pcline.nextpc { 1683 epc = int64(pcfile.nextpc) 1684 } else { 1685 epc = int64(pcline.nextpc) 1686 } 1687 epc += s.Value 1688 } 1689 1690 da = 0 1691 dwfunc.hash = varhash[:] // enable indexing of children by name 1692 varhash = [HASHSIZE]*DWDie{} 1693 for a = s.Autom; a != nil; a = a.Link { 1694 switch a.Name { 1695 case obj.A_AUTO: 1696 dt = DW_ABRV_AUTO 1697 offs = int64(a.Aoffset) - int64(Thearch.Ptrsize) 1698 1699 case obj.A_PARAM: 1700 dt = DW_ABRV_PARAM 1701 offs = int64(a.Aoffset) 1702 1703 default: 1704 continue 1705 } 1706 1707 if strings.Contains(a.Asym.Name, ".autotmp_") { 1708 continue 1709 } 1710 if find(dwfunc, a.Asym.Name) != nil { 1711 n = mkvarname(a.Asym.Name, da) 1712 } else { 1713 n = a.Asym.Name 1714 } 1715 1716 // Drop the package prefix from locals and arguments. 1717 _ = nn 1718 if i := strings.LastIndex(n, "."); i >= 0 { 1719 n = n[i+1:] 1720 } 1721 1722 dwvar = newdie(dwfunc, dt, n) 1723 newcfaoffsetattr(dwvar, int32(offs)) 1724 newrefattr(dwvar, DW_AT_type, defgotype(a.Gotype)) 1725 1726 // push dwvar down dwfunc->child to preserve order 1727 newattr(dwvar, DW_AT_internal_location, DW_CLS_CONSTANT, offs, nil) 1728 1729 dwfunc.child = dwvar.link // take dwvar out from the top of the list 1730 for dws = &dwfunc.child; *dws != nil; dws = &(*dws).link { 1731 if offs > getattr(*dws, DW_AT_internal_location).value { 1732 break 1733 } 1734 } 1735 dwvar.link = *dws 1736 *dws = dwvar 1737 1738 da++ 1739 } 1740 1741 dwfunc.hash = nil 1742 } 1743 1744 flushunit(dwinfo, epc, epcs, unitstart, int32(headerend-unitstart-10)) 1745 linesize = Cpos() - lineo 1746 } 1747 1748 /* 1749 * Emit .debug_frame 1750 */ 1751 const ( 1752 CIERESERVE = 16 1753 DATAALIGNMENTFACTOR = -4 1754 FAKERETURNCOLUMN = 16 // TODO gdb6 doesn't like > 15? 1755 ) 1756 1757 func putpccfadelta(deltapc int64, cfa int64) { 1758 Cput(DW_CFA_def_cfa_offset_sf) 1759 sleb128put(cfa / DATAALIGNMENTFACTOR) 1760 1761 if deltapc < 0x40 { 1762 Cput(uint8(DW_CFA_advance_loc + deltapc)) 1763 } else if deltapc < 0x100 { 1764 Cput(DW_CFA_advance_loc1) 1765 Cput(uint8(deltapc)) 1766 } else if deltapc < 0x10000 { 1767 Cput(DW_CFA_advance_loc2) 1768 Thearch.Wput(uint16(deltapc)) 1769 } else { 1770 Cput(DW_CFA_advance_loc4) 1771 Thearch.Lput(uint32(deltapc)) 1772 } 1773 } 1774 1775 func writeframes() { 1776 if framesec == nil { 1777 framesec = Linklookup(Ctxt, ".dwarfframe", 0) 1778 } 1779 framesec.R = framesec.R[:0] 1780 frameo = Cpos() 1781 1782 // Emit the CIE, Section 6.4.1 1783 Thearch.Lput(CIERESERVE) // initial length, must be multiple of thearch.ptrsize 1784 Thearch.Lput(0xffffffff) // cid. 1785 Cput(3) // dwarf version (appendix F) 1786 Cput(0) // augmentation "" 1787 uleb128put(1) // code_alignment_factor 1788 sleb128put(DATAALIGNMENTFACTOR) // guess 1789 uleb128put(FAKERETURNCOLUMN) // return_address_register 1790 1791 Cput(DW_CFA_def_cfa) 1792 1793 uleb128put(int64(Thearch.Dwarfregsp)) // register SP (**ABI-dependent, defined in l.h) 1794 uleb128put(int64(Thearch.Ptrsize)) // offset 1795 1796 Cput(DW_CFA_offset + FAKERETURNCOLUMN) // return address 1797 uleb128put(int64(-Thearch.Ptrsize) / DATAALIGNMENTFACTOR) // at cfa - x*4 1798 1799 // 4 is to exclude the length field. 1800 pad := CIERESERVE + frameo + 4 - Cpos() 1801 1802 if pad < 0 { 1803 Exitf("dwarf: CIERESERVE too small by %d bytes.", -pad) 1804 } 1805 1806 strnput("", int(pad)) 1807 1808 var fdeo int64 1809 var fdesize int64 1810 var nextpc uint32 1811 var pcsp Pciter 1812 var s *LSym 1813 for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next { 1814 s = Ctxt.Cursym 1815 if s.Pcln == nil { 1816 continue 1817 } 1818 1819 fdeo = Cpos() 1820 1821 // Emit a FDE, Section 6.4.1, starting wit a placeholder. 1822 Thearch.Lput(0) // length, must be multiple of thearch.ptrsize 1823 Thearch.Lput(0) // Pointer to the CIE above, at offset 0 1824 addrput(0) // initial location 1825 addrput(0) // address range 1826 1827 for pciterinit(Ctxt, &pcsp, &s.Pcln.Pcsp); pcsp.done == 0; pciternext(&pcsp) { 1828 nextpc = pcsp.nextpc 1829 1830 // pciterinit goes up to the end of the function, 1831 // but DWARF expects us to stop just before the end. 1832 if int64(nextpc) == s.Size { 1833 nextpc-- 1834 if nextpc < pcsp.pc { 1835 continue 1836 } 1837 } 1838 1839 putpccfadelta(int64(nextpc)-int64(pcsp.pc), int64(Thearch.Ptrsize)+int64(pcsp.value)) 1840 } 1841 1842 fdesize = Cpos() - fdeo - 4 // exclude the length field. 1843 pad = Rnd(fdesize, int64(Thearch.Ptrsize)) - fdesize 1844 strnput("", int(pad)) 1845 fdesize += pad 1846 1847 // Emit the FDE header for real, Section 6.4.1. 1848 Cseek(fdeo) 1849 1850 Thearch.Lput(uint32(fdesize)) 1851 if Linkmode == LinkExternal { 1852 adddwarfrel(framesec, framesym, frameo, 4, 0) 1853 adddwarfrel(framesec, s, frameo, Thearch.Ptrsize, 0) 1854 } else { 1855 Thearch.Lput(0) 1856 addrput(s.Value) 1857 } 1858 1859 addrput(s.Size) 1860 Cseek(fdeo + 4 + fdesize) 1861 } 1862 1863 Cflush() 1864 framesize = Cpos() - frameo 1865 } 1866 1867 /* 1868 * Walk DWarfDebugInfoEntries, and emit .debug_info 1869 */ 1870 const ( 1871 COMPUNITHEADERSIZE = 4 + 2 + 4 + 1 1872 ) 1873 1874 func writeinfo() { 1875 fwdcount = 0 1876 if infosec == nil { 1877 infosec = Linklookup(Ctxt, ".dwarfinfo", 0) 1878 } 1879 infosec.R = infosec.R[:0] 1880 1881 if arangessec == nil { 1882 arangessec = Linklookup(Ctxt, ".dwarfaranges", 0) 1883 } 1884 arangessec.R = arangessec.R[:0] 1885 1886 var here int64 1887 var unitstart int64 1888 for compunit := dwroot.child; compunit != nil; compunit = compunit.link { 1889 unitstart = Cpos() 1890 1891 // Write .debug_info Compilation Unit Header (sec 7.5.1) 1892 // Fields marked with (*) must be changed for 64-bit dwarf 1893 // This must match COMPUNITHEADERSIZE above. 1894 Thearch.Lput(0) // unit_length (*), will be filled in later. 1895 Thearch.Wput(2) // dwarf version (appendix F) 1896 1897 // debug_abbrev_offset (*) 1898 if Linkmode == LinkExternal { 1899 adddwarfrel(infosec, abbrevsym, infoo, 4, 0) 1900 } else { 1901 Thearch.Lput(0) 1902 } 1903 1904 Cput(uint8(Thearch.Ptrsize)) // address_size 1905 1906 putdie(compunit) 1907 1908 here = Cpos() 1909 Cseek(unitstart) 1910 Thearch.Lput(uint32(here - unitstart - 4)) // exclude the length field. 1911 Cseek(here) 1912 } 1913 1914 Cflush() 1915 } 1916 1917 /* 1918 * Emit .debug_pubnames/_types. _info must have been written before, 1919 * because we need die->offs and infoo/infosize; 1920 */ 1921 func ispubname(die *DWDie) bool { 1922 switch die.abbrev { 1923 case DW_ABRV_FUNCTION, DW_ABRV_VARIABLE: 1924 a := getattr(die, DW_AT_external) 1925 return a != nil && a.value != 0 1926 } 1927 1928 return false 1929 } 1930 1931 func ispubtype(die *DWDie) bool { 1932 return die.abbrev >= DW_ABRV_NULLTYPE 1933 } 1934 1935 func writepub(ispub func(*DWDie) bool) int64 { 1936 var die *DWDie 1937 var dwa *DWAttr 1938 var unitstart int64 1939 var unitend int64 1940 var here int64 1941 1942 sectionstart := Cpos() 1943 1944 for compunit := dwroot.child; compunit != nil; compunit = compunit.link { 1945 unitstart = compunit.offs - COMPUNITHEADERSIZE 1946 if compunit.link != nil { 1947 unitend = compunit.link.offs - COMPUNITHEADERSIZE 1948 } else { 1949 unitend = infoo + infosize 1950 } 1951 1952 // Write .debug_pubnames/types Header (sec 6.1.1) 1953 Thearch.Lput(0) // unit_length (*), will be filled in later. 1954 Thearch.Wput(2) // dwarf version (appendix F) 1955 Thearch.Lput(uint32(unitstart)) // debug_info_offset (of the Comp unit Header) 1956 Thearch.Lput(uint32(unitend - unitstart)) // debug_info_length 1957 1958 for die = compunit.child; die != nil; die = die.link { 1959 if !ispub(die) { 1960 continue 1961 } 1962 Thearch.Lput(uint32(die.offs - unitstart)) 1963 dwa = getattr(die, DW_AT_name) 1964 strnput(dwa.data.(string), int(dwa.value+1)) 1965 } 1966 1967 Thearch.Lput(0) 1968 1969 here = Cpos() 1970 Cseek(sectionstart) 1971 Thearch.Lput(uint32(here - sectionstart - 4)) // exclude the length field. 1972 Cseek(here) 1973 } 1974 1975 return sectionstart 1976 } 1977 1978 /* 1979 * emit .debug_aranges. _info must have been written before, 1980 * because we need die->offs of dw_globals. 1981 */ 1982 func writearanges() int64 { 1983 var b *DWAttr 1984 var e *DWAttr 1985 var value int64 1986 1987 sectionstart := Cpos() 1988 headersize := int(Rnd(4+2+4+1+1, int64(Thearch.Ptrsize))) // don't count unit_length field itself 1989 1990 for compunit := dwroot.child; compunit != nil; compunit = compunit.link { 1991 b = getattr(compunit, DW_AT_low_pc) 1992 if b == nil { 1993 continue 1994 } 1995 e = getattr(compunit, DW_AT_high_pc) 1996 if e == nil { 1997 continue 1998 } 1999 2000 // Write .debug_aranges Header + entry (sec 6.1.2) 2001 Thearch.Lput(uint32(headersize) + 4*uint32(Thearch.Ptrsize) - 4) // unit_length (*) 2002 Thearch.Wput(2) // dwarf version (appendix F) 2003 2004 value = compunit.offs - COMPUNITHEADERSIZE // debug_info_offset 2005 if Linkmode == LinkExternal { 2006 adddwarfrel(arangessec, infosym, sectionstart, 4, value) 2007 } else { 2008 Thearch.Lput(uint32(value)) 2009 } 2010 2011 Cput(uint8(Thearch.Ptrsize)) // address_size 2012 Cput(0) // segment_size 2013 strnput("", headersize-(4+2+4+1+1)) // align to thearch.ptrsize 2014 2015 if Linkmode == LinkExternal { 2016 adddwarfrel(arangessec, b.data.(*LSym), sectionstart, Thearch.Ptrsize, b.value-(b.data.(*LSym)).Value) 2017 } else { 2018 addrput(b.value) 2019 } 2020 2021 addrput(e.value - b.value) 2022 addrput(0) 2023 addrput(0) 2024 } 2025 2026 Cflush() 2027 return sectionstart 2028 } 2029 2030 func writegdbscript() int64 { 2031 sectionstart := Cpos() 2032 2033 if gdbscript != "" { 2034 Cput(1) // magic 1 byte? 2035 strnput(gdbscript, len(gdbscript)+1) 2036 Cflush() 2037 } 2038 2039 return sectionstart 2040 } 2041 2042 func align(size int64) { 2043 if HEADTYPE == obj.Hwindows { // Only Windows PE need section align. 2044 strnput("", int(Rnd(size, PEFILEALIGN)-size)) 2045 } 2046 } 2047 2048 func writedwarfreloc(s *LSym) int64 { 2049 var i int 2050 var r *Reloc 2051 2052 start := Cpos() 2053 for ri := 0; ri < len(s.R); ri++ { 2054 r = &s.R[ri] 2055 if Iself { 2056 i = Thearch.Elfreloc1(r, int64(r.Off)) 2057 } else if HEADTYPE == obj.Hdarwin { 2058 i = Thearch.Machoreloc1(r, int64(r.Off)) 2059 } else { 2060 i = -1 2061 } 2062 if i < 0 { 2063 Diag("unsupported obj reloc %d/%d to %s", r.Type, r.Siz, r.Sym.Name) 2064 } 2065 } 2066 2067 return start 2068 } 2069 2070 /* 2071 * This is the main entry point for generating dwarf. After emitting 2072 * the mandatory debug_abbrev section, it calls writelines() to set up 2073 * the per-compilation unit part of the DIE tree, while simultaneously 2074 * emitting the debug_line section. When the final tree contains 2075 * forward references, it will write the debug_info section in 2 2076 * passes. 2077 * 2078 */ 2079 func Dwarfemitdebugsections() { 2080 if Debug['w'] != 0 { // disable dwarf 2081 return 2082 } 2083 2084 if Linkmode == LinkExternal && !Iself { 2085 return 2086 } 2087 2088 // For diagnostic messages. 2089 newattr(&dwtypes, DW_AT_name, DW_CLS_STRING, int64(len("dwtypes")), "dwtypes") 2090 2091 mkindex(&dwroot) 2092 mkindex(&dwtypes) 2093 mkindex(&dwglobals) 2094 2095 // Some types that must exist to define other ones. 2096 newdie(&dwtypes, DW_ABRV_NULLTYPE, "<unspecified>") 2097 2098 newdie(&dwtypes, DW_ABRV_NULLTYPE, "void") 2099 newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer") 2100 2101 die := newdie(&dwtypes, DW_ABRV_BASETYPE, "uintptr") // needed for array size 2102 newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0) 2103 newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, int64(Thearch.Ptrsize), 0) 2104 newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, obj.KindUintptr, 0) 2105 2106 // Needed by the prettyprinter code for interface inspection. 2107 defgotype(lookup_or_diag("type.runtime._type")) 2108 2109 defgotype(lookup_or_diag("type.runtime.interfacetype")) 2110 defgotype(lookup_or_diag("type.runtime.itab")) 2111 2112 genasmsym(defdwsymb) 2113 2114 writeabbrev() 2115 align(abbrevsize) 2116 writelines() 2117 align(linesize) 2118 writeframes() 2119 align(framesize) 2120 2121 synthesizestringtypes(dwtypes.child) 2122 synthesizeslicetypes(dwtypes.child) 2123 synthesizemaptypes(dwtypes.child) 2124 synthesizechantypes(dwtypes.child) 2125 2126 reversetree(&dwroot.child) 2127 reversetree(&dwtypes.child) 2128 reversetree(&dwglobals.child) 2129 2130 movetomodule(&dwtypes) 2131 movetomodule(&dwglobals) 2132 2133 infoo = Cpos() 2134 writeinfo() 2135 infoe := Cpos() 2136 pubnameso = infoe 2137 pubtypeso = infoe 2138 arangeso = infoe 2139 gdbscripto = infoe 2140 2141 if fwdcount > 0 { 2142 if Debug['v'] != 0 { 2143 fmt.Fprintf(&Bso, "%5.2f dwarf pass 2.\n", obj.Cputime()) 2144 } 2145 Cseek(infoo) 2146 writeinfo() 2147 if fwdcount > 0 { 2148 Exitf("dwarf: unresolved references after first dwarf info pass") 2149 } 2150 2151 if infoe != Cpos() { 2152 Exitf("dwarf: inconsistent second dwarf info pass") 2153 } 2154 } 2155 2156 infosize = infoe - infoo 2157 align(infosize) 2158 2159 pubnameso = writepub(ispubname) 2160 pubnamessize = Cpos() - pubnameso 2161 align(pubnamessize) 2162 2163 pubtypeso = writepub(ispubtype) 2164 pubtypessize = Cpos() - pubtypeso 2165 align(pubtypessize) 2166 2167 arangeso = writearanges() 2168 arangessize = Cpos() - arangeso 2169 align(arangessize) 2170 2171 gdbscripto = writegdbscript() 2172 gdbscriptsize = Cpos() - gdbscripto 2173 align(gdbscriptsize) 2174 2175 for Cpos()&7 != 0 { 2176 Cput(0) 2177 } 2178 inforeloco = writedwarfreloc(infosec) 2179 inforelocsize = Cpos() - inforeloco 2180 align(inforelocsize) 2181 2182 arangesreloco = writedwarfreloc(arangessec) 2183 arangesrelocsize = Cpos() - arangesreloco 2184 align(arangesrelocsize) 2185 2186 linereloco = writedwarfreloc(linesec) 2187 linerelocsize = Cpos() - linereloco 2188 align(linerelocsize) 2189 2190 framereloco = writedwarfreloc(framesec) 2191 framerelocsize = Cpos() - framereloco 2192 align(framerelocsize) 2193 } 2194 2195 /* 2196 * Elf. 2197 */ 2198 const ( 2199 ElfStrDebugAbbrev = iota 2200 ElfStrDebugAranges 2201 ElfStrDebugFrame 2202 ElfStrDebugInfo 2203 ElfStrDebugLine 2204 ElfStrDebugLoc 2205 ElfStrDebugMacinfo 2206 ElfStrDebugPubNames 2207 ElfStrDebugPubTypes 2208 ElfStrDebugRanges 2209 ElfStrDebugStr 2210 ElfStrGDBScripts 2211 ElfStrRelDebugInfo 2212 ElfStrRelDebugAranges 2213 ElfStrRelDebugLine 2214 ElfStrRelDebugFrame 2215 NElfStrDbg 2216 ) 2217 2218 var elfstrdbg [NElfStrDbg]int64 2219 2220 func dwarfaddshstrings(shstrtab *LSym) { 2221 if Debug['w'] != 0 { // disable dwarf 2222 return 2223 } 2224 2225 elfstrdbg[ElfStrDebugAbbrev] = Addstring(shstrtab, ".debug_abbrev") 2226 elfstrdbg[ElfStrDebugAranges] = Addstring(shstrtab, ".debug_aranges") 2227 elfstrdbg[ElfStrDebugFrame] = Addstring(shstrtab, ".debug_frame") 2228 elfstrdbg[ElfStrDebugInfo] = Addstring(shstrtab, ".debug_info") 2229 elfstrdbg[ElfStrDebugLine] = Addstring(shstrtab, ".debug_line") 2230 elfstrdbg[ElfStrDebugLoc] = Addstring(shstrtab, ".debug_loc") 2231 elfstrdbg[ElfStrDebugMacinfo] = Addstring(shstrtab, ".debug_macinfo") 2232 elfstrdbg[ElfStrDebugPubNames] = Addstring(shstrtab, ".debug_pubnames") 2233 elfstrdbg[ElfStrDebugPubTypes] = Addstring(shstrtab, ".debug_pubtypes") 2234 elfstrdbg[ElfStrDebugRanges] = Addstring(shstrtab, ".debug_ranges") 2235 elfstrdbg[ElfStrDebugStr] = Addstring(shstrtab, ".debug_str") 2236 elfstrdbg[ElfStrGDBScripts] = Addstring(shstrtab, ".debug_gdb_scripts") 2237 if Linkmode == LinkExternal { 2238 switch Thearch.Thechar { 2239 case '6', '7', '9': 2240 elfstrdbg[ElfStrRelDebugInfo] = Addstring(shstrtab, ".rela.debug_info") 2241 elfstrdbg[ElfStrRelDebugAranges] = Addstring(shstrtab, ".rela.debug_aranges") 2242 elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, ".rela.debug_line") 2243 elfstrdbg[ElfStrRelDebugFrame] = Addstring(shstrtab, ".rela.debug_frame") 2244 default: 2245 elfstrdbg[ElfStrRelDebugInfo] = Addstring(shstrtab, ".rel.debug_info") 2246 elfstrdbg[ElfStrRelDebugAranges] = Addstring(shstrtab, ".rel.debug_aranges") 2247 elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, ".rel.debug_line") 2248 elfstrdbg[ElfStrRelDebugFrame] = Addstring(shstrtab, ".rel.debug_frame") 2249 } 2250 2251 infosym = Linklookup(Ctxt, ".debug_info", 0) 2252 infosym.Hide = 1 2253 2254 abbrevsym = Linklookup(Ctxt, ".debug_abbrev", 0) 2255 abbrevsym.Hide = 1 2256 2257 linesym = Linklookup(Ctxt, ".debug_line", 0) 2258 linesym.Hide = 1 2259 2260 framesym = Linklookup(Ctxt, ".debug_frame", 0) 2261 framesym.Hide = 1 2262 } 2263 } 2264 2265 // Add section symbols for DWARF debug info. This is called before 2266 // dwarfaddelfheaders. 2267 func dwarfaddelfsectionsyms() { 2268 if infosym != nil { 2269 infosympos = Cpos() 2270 putelfsectionsym(infosym, 0) 2271 } 2272 2273 if abbrevsym != nil { 2274 abbrevsympos = Cpos() 2275 putelfsectionsym(abbrevsym, 0) 2276 } 2277 2278 if linesym != nil { 2279 linesympos = Cpos() 2280 putelfsectionsym(linesym, 0) 2281 } 2282 2283 if framesym != nil { 2284 framesympos = Cpos() 2285 putelfsectionsym(framesym, 0) 2286 } 2287 } 2288 2289 func dwarfaddelfrelocheader(elfstr int, shdata *ElfShdr, off int64, size int64) { 2290 sh := newElfShdr(elfstrdbg[elfstr]) 2291 switch Thearch.Thechar { 2292 case '6', '7', '9': 2293 sh.type_ = SHT_RELA 2294 default: 2295 sh.type_ = SHT_REL 2296 } 2297 2298 sh.entsize = uint64(Thearch.Ptrsize) * 2 2299 if sh.type_ == SHT_RELA { 2300 sh.entsize += uint64(Thearch.Ptrsize) 2301 } 2302 sh.link = uint32(elfshname(".symtab").shnum) 2303 sh.info = uint32(shdata.shnum) 2304 sh.off = uint64(off) 2305 sh.size = uint64(size) 2306 sh.addralign = uint64(Thearch.Ptrsize) 2307 } 2308 2309 func dwarfaddelfheaders() { 2310 if Debug['w'] != 0 { // disable dwarf 2311 return 2312 } 2313 2314 sh := newElfShdr(elfstrdbg[ElfStrDebugAbbrev]) 2315 sh.type_ = SHT_PROGBITS 2316 sh.off = uint64(abbrevo) 2317 sh.size = uint64(abbrevsize) 2318 sh.addralign = 1 2319 if abbrevsympos > 0 { 2320 putelfsymshndx(abbrevsympos, sh.shnum) 2321 } 2322 2323 sh = newElfShdr(elfstrdbg[ElfStrDebugLine]) 2324 sh.type_ = SHT_PROGBITS 2325 sh.off = uint64(lineo) 2326 sh.size = uint64(linesize) 2327 sh.addralign = 1 2328 if linesympos > 0 { 2329 putelfsymshndx(linesympos, sh.shnum) 2330 } 2331 shline := sh 2332 2333 sh = newElfShdr(elfstrdbg[ElfStrDebugFrame]) 2334 sh.type_ = SHT_PROGBITS 2335 sh.off = uint64(frameo) 2336 sh.size = uint64(framesize) 2337 sh.addralign = 1 2338 if framesympos > 0 { 2339 putelfsymshndx(framesympos, sh.shnum) 2340 } 2341 shframe := sh 2342 2343 sh = newElfShdr(elfstrdbg[ElfStrDebugInfo]) 2344 sh.type_ = SHT_PROGBITS 2345 sh.off = uint64(infoo) 2346 sh.size = uint64(infosize) 2347 sh.addralign = 1 2348 if infosympos > 0 { 2349 putelfsymshndx(infosympos, sh.shnum) 2350 } 2351 shinfo := sh 2352 2353 if pubnamessize > 0 { 2354 sh := newElfShdr(elfstrdbg[ElfStrDebugPubNames]) 2355 sh.type_ = SHT_PROGBITS 2356 sh.off = uint64(pubnameso) 2357 sh.size = uint64(pubnamessize) 2358 sh.addralign = 1 2359 } 2360 2361 if pubtypessize > 0 { 2362 sh := newElfShdr(elfstrdbg[ElfStrDebugPubTypes]) 2363 sh.type_ = SHT_PROGBITS 2364 sh.off = uint64(pubtypeso) 2365 sh.size = uint64(pubtypessize) 2366 sh.addralign = 1 2367 } 2368 2369 var sharanges *ElfShdr 2370 if arangessize != 0 { 2371 sh := newElfShdr(elfstrdbg[ElfStrDebugAranges]) 2372 sh.type_ = SHT_PROGBITS 2373 sh.off = uint64(arangeso) 2374 sh.size = uint64(arangessize) 2375 sh.addralign = 1 2376 sharanges = sh 2377 } 2378 2379 if gdbscriptsize != 0 { 2380 sh := newElfShdr(elfstrdbg[ElfStrGDBScripts]) 2381 sh.type_ = SHT_PROGBITS 2382 sh.off = uint64(gdbscripto) 2383 sh.size = uint64(gdbscriptsize) 2384 sh.addralign = 1 2385 } 2386 2387 if inforelocsize != 0 { 2388 dwarfaddelfrelocheader(ElfStrRelDebugInfo, shinfo, inforeloco, inforelocsize) 2389 } 2390 2391 if arangesrelocsize != 0 { 2392 dwarfaddelfrelocheader(ElfStrRelDebugAranges, sharanges, arangesreloco, arangesrelocsize) 2393 } 2394 2395 if linerelocsize != 0 { 2396 dwarfaddelfrelocheader(ElfStrRelDebugLine, shline, linereloco, linerelocsize) 2397 } 2398 2399 if framerelocsize != 0 { 2400 dwarfaddelfrelocheader(ElfStrRelDebugFrame, shframe, framereloco, framerelocsize) 2401 } 2402 } 2403 2404 /* 2405 * Macho 2406 */ 2407 func dwarfaddmachoheaders() { 2408 if Debug['w'] != 0 { // disable dwarf 2409 return 2410 } 2411 2412 // Zero vsize segments won't be loaded in memory, even so they 2413 // have to be page aligned in the file. 2414 fakestart := abbrevo &^ 0xfff 2415 2416 nsect := 4 2417 if pubnamessize > 0 { 2418 nsect++ 2419 } 2420 if pubtypessize > 0 { 2421 nsect++ 2422 } 2423 if arangessize > 0 { 2424 nsect++ 2425 } 2426 if gdbscriptsize > 0 { 2427 nsect++ 2428 } 2429 2430 ms := newMachoSeg("__DWARF", nsect) 2431 ms.fileoffset = uint64(fakestart) 2432 ms.filesize = uint64(abbrevo) - uint64(fakestart) 2433 ms.vaddr = ms.fileoffset + Segdata.Vaddr - Segdata.Fileoff 2434 2435 msect := newMachoSect(ms, "__debug_abbrev", "__DWARF") 2436 msect.off = uint32(abbrevo) 2437 msect.size = uint64(abbrevsize) 2438 msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff 2439 ms.filesize += msect.size 2440 2441 msect = newMachoSect(ms, "__debug_line", "__DWARF") 2442 msect.off = uint32(lineo) 2443 msect.size = uint64(linesize) 2444 msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff 2445 ms.filesize += msect.size 2446 2447 msect = newMachoSect(ms, "__debug_frame", "__DWARF") 2448 msect.off = uint32(frameo) 2449 msect.size = uint64(framesize) 2450 msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff 2451 ms.filesize += msect.size 2452 2453 msect = newMachoSect(ms, "__debug_info", "__DWARF") 2454 msect.off = uint32(infoo) 2455 msect.size = uint64(infosize) 2456 msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff 2457 ms.filesize += msect.size 2458 2459 if pubnamessize > 0 { 2460 msect := newMachoSect(ms, "__debug_pubnames", "__DWARF") 2461 msect.off = uint32(pubnameso) 2462 msect.size = uint64(pubnamessize) 2463 msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff 2464 ms.filesize += msect.size 2465 } 2466 2467 if pubtypessize > 0 { 2468 msect := newMachoSect(ms, "__debug_pubtypes", "__DWARF") 2469 msect.off = uint32(pubtypeso) 2470 msect.size = uint64(pubtypessize) 2471 msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff 2472 ms.filesize += msect.size 2473 } 2474 2475 if arangessize > 0 { 2476 msect := newMachoSect(ms, "__debug_aranges", "__DWARF") 2477 msect.off = uint32(arangeso) 2478 msect.size = uint64(arangessize) 2479 msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff 2480 ms.filesize += msect.size 2481 } 2482 2483 // TODO(lvd) fix gdb/python to load MachO (16 char section name limit) 2484 if gdbscriptsize > 0 { 2485 msect := newMachoSect(ms, "__debug_gdb_scripts", "__DWARF") 2486 msect.off = uint32(gdbscripto) 2487 msect.size = uint64(gdbscriptsize) 2488 msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff 2489 ms.filesize += msect.size 2490 } 2491 } 2492 2493 /* 2494 * Windows PE 2495 */ 2496 func dwarfaddpeheaders() { 2497 if Debug['w'] != 0 { // disable dwarf 2498 return 2499 } 2500 2501 newPEDWARFSection(".debug_abbrev", abbrevsize) 2502 newPEDWARFSection(".debug_line", linesize) 2503 newPEDWARFSection(".debug_frame", framesize) 2504 newPEDWARFSection(".debug_info", infosize) 2505 newPEDWARFSection(".debug_pubnames", pubnamessize) 2506 newPEDWARFSection(".debug_pubtypes", pubtypessize) 2507 newPEDWARFSection(".debug_aranges", arangessize) 2508 newPEDWARFSection(".debug_gdb_scripts", gdbscriptsize) 2509 }