github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/cmd/internal/dwarf/dwarf.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package dwarf generates DWARF debugging information. 6 // DWARF generation is split between the compiler and the linker, 7 // this package contains the shared code. 8 package dwarf 9 10 import ( 11 "errors" 12 "fmt" 13 ) 14 15 // InfoPrefix is the prefix for all the symbols containing DWARF info entries. 16 const InfoPrefix = "go.info." 17 18 // RangePrefix is the prefix for all the symbols containing DWARF location lists. 19 const LocPrefix = "go.loc." 20 21 // RangePrefix is the prefix for all the symbols containing DWARF range lists. 22 const RangePrefix = "go.range." 23 24 // ConstInfoPrefix is the prefix for all symbols containing DWARF info 25 // entries that contain constants. 26 const ConstInfoPrefix = "go.constinfo." 27 28 // CUInfoPrefix is the prefix for symbols containing information to 29 // populate the DWARF compilation unit info entries. 30 const CUInfoPrefix = "go.cuinfo." 31 32 // Sym represents a symbol. 33 type Sym interface { 34 Len() int64 35 } 36 37 // A Location represents a variable's location at a particular PC range. 38 // It becomes a location list entry in the DWARF. 39 type Location struct { 40 StartPC, EndPC int64 41 Pieces []Piece 42 } 43 44 // A Piece represents the location of a particular part of a variable. 45 // It becomes part of a location list entry (a DW_OP_piece) in the DWARF. 46 type Piece struct { 47 Length int64 48 StackOffset int32 49 RegNum int16 50 Missing bool 51 OnStack bool // if true, RegNum is unset. 52 } 53 54 // A Var represents a local variable or a function parameter. 55 type Var struct { 56 Name string 57 Abbrev int // Either DW_ABRV_AUTO[_LOCLIST] or DW_ABRV_PARAM[_LOCLIST] 58 IsReturnValue bool 59 StackOffset int32 60 LocationList []Location 61 Scope int32 62 Type Sym 63 DeclLine uint 64 } 65 66 // A Scope represents a lexical scope. All variables declared within a 67 // scope will only be visible to instructions covered by the scope. 68 // Lexical scopes are contiguous in source files but can end up being 69 // compiled to discontiguous blocks of instructions in the executable. 70 // The Ranges field lists all the blocks of instructions that belong 71 // in this scope. 72 type Scope struct { 73 Parent int32 74 Ranges []Range 75 Vars []*Var 76 } 77 78 // A Range represents a half-open interval [Start, End). 79 type Range struct { 80 Start, End int64 81 } 82 83 // UnifyRanges merges the list of ranges of c into the list of ranges of s 84 func (s *Scope) UnifyRanges(c *Scope) { 85 out := make([]Range, 0, len(s.Ranges)+len(c.Ranges)) 86 87 i, j := 0, 0 88 for { 89 var cur Range 90 if i < len(s.Ranges) && j < len(c.Ranges) { 91 if s.Ranges[i].Start < c.Ranges[j].Start { 92 cur = s.Ranges[i] 93 i++ 94 } else { 95 cur = c.Ranges[j] 96 j++ 97 } 98 } else if i < len(s.Ranges) { 99 cur = s.Ranges[i] 100 i++ 101 } else if j < len(c.Ranges) { 102 cur = c.Ranges[j] 103 j++ 104 } else { 105 break 106 } 107 108 if n := len(out); n > 0 && cur.Start <= out[n-1].End { 109 out[n-1].End = cur.End 110 } else { 111 out = append(out, cur) 112 } 113 } 114 115 s.Ranges = out 116 } 117 118 // A Context specifies how to add data to a Sym. 119 type Context interface { 120 PtrSize() int 121 AddInt(s Sym, size int, i int64) 122 AddBytes(s Sym, b []byte) 123 AddAddress(s Sym, t interface{}, ofs int64) 124 AddCURelativeAddress(s Sym, t interface{}, ofs int64) 125 AddSectionOffset(s Sym, size int, t interface{}, ofs int64) 126 AddString(s Sym, v string) 127 AddFileRef(s Sym, f interface{}) 128 } 129 130 // AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding. 131 func AppendUleb128(b []byte, v uint64) []byte { 132 for { 133 c := uint8(v & 0x7f) 134 v >>= 7 135 if v != 0 { 136 c |= 0x80 137 } 138 b = append(b, c) 139 if c&0x80 == 0 { 140 break 141 } 142 } 143 return b 144 } 145 146 // AppendSleb128 appends v to b using DWARF's signed LEB128 encoding. 147 func AppendSleb128(b []byte, v int64) []byte { 148 for { 149 c := uint8(v & 0x7f) 150 s := uint8(v & 0x40) 151 v >>= 7 152 if (v != -1 || s == 0) && (v != 0 || s != 0) { 153 c |= 0x80 154 } 155 b = append(b, c) 156 if c&0x80 == 0 { 157 break 158 } 159 } 160 return b 161 } 162 163 // sevenbits contains all unsigned seven bit numbers, indexed by their value. 164 var sevenbits = [...]byte{ 165 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 166 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 167 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 168 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 169 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 170 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 171 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 172 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 173 } 174 175 // sevenBitU returns the unsigned LEB128 encoding of v if v is seven bits and nil otherwise. 176 // The contents of the returned slice must not be modified. 177 func sevenBitU(v int64) []byte { 178 if uint64(v) < uint64(len(sevenbits)) { 179 return sevenbits[v : v+1] 180 } 181 return nil 182 } 183 184 // sevenBitS returns the signed LEB128 encoding of v if v is seven bits and nil otherwise. 185 // The contents of the returned slice must not be modified. 186 func sevenBitS(v int64) []byte { 187 if uint64(v) <= 63 { 188 return sevenbits[v : v+1] 189 } 190 if uint64(-v) <= 64 { 191 return sevenbits[128+v : 128+v+1] 192 } 193 return nil 194 } 195 196 // Uleb128put appends v to s using DWARF's unsigned LEB128 encoding. 197 func Uleb128put(ctxt Context, s Sym, v int64) { 198 b := sevenBitU(v) 199 if b == nil { 200 var encbuf [20]byte 201 b = AppendUleb128(encbuf[:0], uint64(v)) 202 } 203 ctxt.AddBytes(s, b) 204 } 205 206 // Sleb128put appends v to s using DWARF's signed LEB128 encoding. 207 func Sleb128put(ctxt Context, s Sym, v int64) { 208 b := sevenBitS(v) 209 if b == nil { 210 var encbuf [20]byte 211 b = AppendSleb128(encbuf[:0], v) 212 } 213 ctxt.AddBytes(s, b) 214 } 215 216 /* 217 * Defining Abbrevs. This is hardcoded, and there will be 218 * only a handful of them. The DWARF spec places no restriction on 219 * the ordering of attributes in the Abbrevs and DIEs, and we will 220 * always write them out in the order of declaration in the abbrev. 221 */ 222 type dwAttrForm struct { 223 attr uint16 224 form uint8 225 } 226 227 // Go-specific type attributes. 228 const ( 229 DW_AT_go_kind = 0x2900 230 DW_AT_go_key = 0x2901 231 DW_AT_go_elem = 0x2902 232 // Attribute for DW_TAG_member of a struct type. 233 // Nonzero value indicates the struct field is an embedded field. 234 DW_AT_go_embedded_field = 0x2903 235 236 DW_AT_internal_location = 253 // params and locals; not emitted 237 ) 238 239 // Index into the abbrevs table below. 240 // Keep in sync with ispubname() and ispubtype() in ld/dwarf.go. 241 // ispubtype considers >= NULLTYPE public 242 const ( 243 DW_ABRV_NULL = iota 244 DW_ABRV_COMPUNIT 245 DW_ABRV_FUNCTION 246 DW_ABRV_VARIABLE 247 DW_ABRV_INT_CONSTANT 248 DW_ABRV_AUTO 249 DW_ABRV_AUTO_LOCLIST 250 DW_ABRV_PARAM 251 DW_ABRV_PARAM_LOCLIST 252 DW_ABRV_LEXICAL_BLOCK_RANGES 253 DW_ABRV_LEXICAL_BLOCK_SIMPLE 254 DW_ABRV_STRUCTFIELD 255 DW_ABRV_FUNCTYPEPARAM 256 DW_ABRV_DOTDOTDOT 257 DW_ABRV_ARRAYRANGE 258 DW_ABRV_NULLTYPE 259 DW_ABRV_BASETYPE 260 DW_ABRV_ARRAYTYPE 261 DW_ABRV_CHANTYPE 262 DW_ABRV_FUNCTYPE 263 DW_ABRV_IFACETYPE 264 DW_ABRV_MAPTYPE 265 DW_ABRV_PTRTYPE 266 DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6. 267 DW_ABRV_SLICETYPE 268 DW_ABRV_STRINGTYPE 269 DW_ABRV_STRUCTTYPE 270 DW_ABRV_TYPEDECL 271 DW_NABRV 272 ) 273 274 type dwAbbrev struct { 275 tag uint8 276 children uint8 277 attr []dwAttrForm 278 } 279 280 var abbrevs = [DW_NABRV]dwAbbrev{ 281 /* The mandatory DW_ABRV_NULL entry. */ 282 {0, 0, []dwAttrForm{}}, 283 284 /* COMPUNIT */ 285 { 286 DW_TAG_compile_unit, 287 DW_CHILDREN_yes, 288 []dwAttrForm{ 289 {DW_AT_name, DW_FORM_string}, 290 {DW_AT_language, DW_FORM_data1}, 291 {DW_AT_stmt_list, DW_FORM_sec_offset}, 292 {DW_AT_low_pc, DW_FORM_addr}, 293 {DW_AT_ranges, DW_FORM_sec_offset}, 294 {DW_AT_comp_dir, DW_FORM_string}, 295 {DW_AT_producer, DW_FORM_string}, 296 }, 297 }, 298 299 /* FUNCTION */ 300 { 301 DW_TAG_subprogram, 302 DW_CHILDREN_yes, 303 []dwAttrForm{ 304 {DW_AT_name, DW_FORM_string}, 305 {DW_AT_low_pc, DW_FORM_addr}, 306 {DW_AT_high_pc, DW_FORM_addr}, 307 {DW_AT_frame_base, DW_FORM_block1}, 308 {DW_AT_decl_file, DW_FORM_data4}, 309 {DW_AT_external, DW_FORM_flag}, 310 }, 311 }, 312 313 /* VARIABLE */ 314 { 315 DW_TAG_variable, 316 DW_CHILDREN_no, 317 []dwAttrForm{ 318 {DW_AT_name, DW_FORM_string}, 319 {DW_AT_location, DW_FORM_block1}, 320 {DW_AT_type, DW_FORM_ref_addr}, 321 {DW_AT_external, DW_FORM_flag}, 322 }, 323 }, 324 325 /* INT CONSTANT */ 326 { 327 DW_TAG_constant, 328 DW_CHILDREN_no, 329 []dwAttrForm{ 330 {DW_AT_name, DW_FORM_string}, 331 {DW_AT_type, DW_FORM_ref_addr}, 332 {DW_AT_const_value, DW_FORM_sdata}, 333 }, 334 }, 335 336 /* AUTO */ 337 { 338 DW_TAG_variable, 339 DW_CHILDREN_no, 340 []dwAttrForm{ 341 {DW_AT_name, DW_FORM_string}, 342 {DW_AT_decl_line, DW_FORM_udata}, 343 {DW_AT_location, DW_FORM_block1}, 344 {DW_AT_type, DW_FORM_ref_addr}, 345 }, 346 }, 347 348 /* AUTO_LOCLIST */ 349 { 350 DW_TAG_variable, 351 DW_CHILDREN_no, 352 []dwAttrForm{ 353 {DW_AT_name, DW_FORM_string}, 354 {DW_AT_decl_line, DW_FORM_udata}, 355 {DW_AT_location, DW_FORM_sec_offset}, 356 {DW_AT_type, DW_FORM_ref_addr}, 357 }, 358 }, 359 360 /* PARAM */ 361 { 362 DW_TAG_formal_parameter, 363 DW_CHILDREN_no, 364 []dwAttrForm{ 365 {DW_AT_name, DW_FORM_string}, 366 {DW_AT_variable_parameter, DW_FORM_flag}, 367 {DW_AT_decl_line, DW_FORM_udata}, 368 {DW_AT_location, DW_FORM_block1}, 369 {DW_AT_type, DW_FORM_ref_addr}, 370 }, 371 }, 372 373 /* PARAM_LOCLIST */ 374 { 375 DW_TAG_formal_parameter, 376 DW_CHILDREN_no, 377 []dwAttrForm{ 378 {DW_AT_name, DW_FORM_string}, 379 {DW_AT_variable_parameter, DW_FORM_flag}, 380 {DW_AT_decl_line, DW_FORM_udata}, 381 {DW_AT_location, DW_FORM_sec_offset}, 382 {DW_AT_type, DW_FORM_ref_addr}, 383 }, 384 }, 385 386 /* LEXICAL_BLOCK_RANGES */ 387 { 388 DW_TAG_lexical_block, 389 DW_CHILDREN_yes, 390 []dwAttrForm{ 391 {DW_AT_ranges, DW_FORM_sec_offset}, 392 }, 393 }, 394 395 /* LEXICAL_BLOCK_SIMPLE */ 396 { 397 DW_TAG_lexical_block, 398 DW_CHILDREN_yes, 399 []dwAttrForm{ 400 {DW_AT_low_pc, DW_FORM_addr}, 401 {DW_AT_high_pc, DW_FORM_addr}, 402 }, 403 }, 404 405 /* STRUCTFIELD */ 406 { 407 DW_TAG_member, 408 DW_CHILDREN_no, 409 []dwAttrForm{ 410 {DW_AT_name, DW_FORM_string}, 411 {DW_AT_data_member_location, DW_FORM_udata}, 412 {DW_AT_type, DW_FORM_ref_addr}, 413 {DW_AT_go_embedded_field, DW_FORM_flag}, 414 }, 415 }, 416 417 /* FUNCTYPEPARAM */ 418 { 419 DW_TAG_formal_parameter, 420 DW_CHILDREN_no, 421 422 // No name! 423 []dwAttrForm{ 424 {DW_AT_type, DW_FORM_ref_addr}, 425 }, 426 }, 427 428 /* DOTDOTDOT */ 429 { 430 DW_TAG_unspecified_parameters, 431 DW_CHILDREN_no, 432 []dwAttrForm{}, 433 }, 434 435 /* ARRAYRANGE */ 436 { 437 DW_TAG_subrange_type, 438 DW_CHILDREN_no, 439 440 // No name! 441 []dwAttrForm{ 442 {DW_AT_type, DW_FORM_ref_addr}, 443 {DW_AT_count, DW_FORM_udata}, 444 }, 445 }, 446 447 // Below here are the types considered public by ispubtype 448 /* NULLTYPE */ 449 { 450 DW_TAG_unspecified_type, 451 DW_CHILDREN_no, 452 []dwAttrForm{ 453 {DW_AT_name, DW_FORM_string}, 454 }, 455 }, 456 457 /* BASETYPE */ 458 { 459 DW_TAG_base_type, 460 DW_CHILDREN_no, 461 []dwAttrForm{ 462 {DW_AT_name, DW_FORM_string}, 463 {DW_AT_encoding, DW_FORM_data1}, 464 {DW_AT_byte_size, DW_FORM_data1}, 465 {DW_AT_go_kind, DW_FORM_data1}, 466 }, 467 }, 468 469 /* ARRAYTYPE */ 470 // child is subrange with upper bound 471 { 472 DW_TAG_array_type, 473 DW_CHILDREN_yes, 474 []dwAttrForm{ 475 {DW_AT_name, DW_FORM_string}, 476 {DW_AT_type, DW_FORM_ref_addr}, 477 {DW_AT_byte_size, DW_FORM_udata}, 478 {DW_AT_go_kind, DW_FORM_data1}, 479 }, 480 }, 481 482 /* CHANTYPE */ 483 { 484 DW_TAG_typedef, 485 DW_CHILDREN_no, 486 []dwAttrForm{ 487 {DW_AT_name, DW_FORM_string}, 488 {DW_AT_type, DW_FORM_ref_addr}, 489 {DW_AT_go_kind, DW_FORM_data1}, 490 {DW_AT_go_elem, DW_FORM_ref_addr}, 491 }, 492 }, 493 494 /* FUNCTYPE */ 495 { 496 DW_TAG_subroutine_type, 497 DW_CHILDREN_yes, 498 []dwAttrForm{ 499 {DW_AT_name, DW_FORM_string}, 500 {DW_AT_byte_size, DW_FORM_udata}, 501 // {DW_AT_type, DW_FORM_ref_addr}, 502 {DW_AT_go_kind, DW_FORM_data1}, 503 }, 504 }, 505 506 /* IFACETYPE */ 507 { 508 DW_TAG_typedef, 509 DW_CHILDREN_yes, 510 []dwAttrForm{ 511 {DW_AT_name, DW_FORM_string}, 512 {DW_AT_type, DW_FORM_ref_addr}, 513 {DW_AT_go_kind, DW_FORM_data1}, 514 }, 515 }, 516 517 /* MAPTYPE */ 518 { 519 DW_TAG_typedef, 520 DW_CHILDREN_no, 521 []dwAttrForm{ 522 {DW_AT_name, DW_FORM_string}, 523 {DW_AT_type, DW_FORM_ref_addr}, 524 {DW_AT_go_kind, DW_FORM_data1}, 525 {DW_AT_go_key, DW_FORM_ref_addr}, 526 {DW_AT_go_elem, DW_FORM_ref_addr}, 527 }, 528 }, 529 530 /* PTRTYPE */ 531 { 532 DW_TAG_pointer_type, 533 DW_CHILDREN_no, 534 []dwAttrForm{ 535 {DW_AT_name, DW_FORM_string}, 536 {DW_AT_type, DW_FORM_ref_addr}, 537 {DW_AT_go_kind, DW_FORM_data1}, 538 }, 539 }, 540 541 /* BARE_PTRTYPE */ 542 { 543 DW_TAG_pointer_type, 544 DW_CHILDREN_no, 545 []dwAttrForm{ 546 {DW_AT_name, DW_FORM_string}, 547 }, 548 }, 549 550 /* SLICETYPE */ 551 { 552 DW_TAG_structure_type, 553 DW_CHILDREN_yes, 554 []dwAttrForm{ 555 {DW_AT_name, DW_FORM_string}, 556 {DW_AT_byte_size, DW_FORM_udata}, 557 {DW_AT_go_kind, DW_FORM_data1}, 558 {DW_AT_go_elem, DW_FORM_ref_addr}, 559 }, 560 }, 561 562 /* STRINGTYPE */ 563 { 564 DW_TAG_structure_type, 565 DW_CHILDREN_yes, 566 []dwAttrForm{ 567 {DW_AT_name, DW_FORM_string}, 568 {DW_AT_byte_size, DW_FORM_udata}, 569 {DW_AT_go_kind, DW_FORM_data1}, 570 }, 571 }, 572 573 /* STRUCTTYPE */ 574 { 575 DW_TAG_structure_type, 576 DW_CHILDREN_yes, 577 []dwAttrForm{ 578 {DW_AT_name, DW_FORM_string}, 579 {DW_AT_byte_size, DW_FORM_udata}, 580 {DW_AT_go_kind, DW_FORM_data1}, 581 }, 582 }, 583 584 /* TYPEDECL */ 585 { 586 DW_TAG_typedef, 587 DW_CHILDREN_no, 588 []dwAttrForm{ 589 {DW_AT_name, DW_FORM_string}, 590 {DW_AT_type, DW_FORM_ref_addr}, 591 }, 592 }, 593 } 594 595 // GetAbbrev returns the contents of the .debug_abbrev section. 596 func GetAbbrev() []byte { 597 var buf []byte 598 for i := 1; i < DW_NABRV; i++ { 599 // See section 7.5.3 600 buf = AppendUleb128(buf, uint64(i)) 601 buf = AppendUleb128(buf, uint64(abbrevs[i].tag)) 602 buf = append(buf, byte(abbrevs[i].children)) 603 for _, f := range abbrevs[i].attr { 604 buf = AppendUleb128(buf, uint64(f.attr)) 605 buf = AppendUleb128(buf, uint64(f.form)) 606 } 607 buf = append(buf, 0, 0) 608 } 609 return append(buf, 0) 610 } 611 612 /* 613 * Debugging Information Entries and their attributes. 614 */ 615 616 // DWAttr represents an attribute of a DWDie. 617 // 618 // For DW_CLS_string and _block, value should contain the length, and 619 // data the data, for _reference, value is 0 and data is a DWDie* to 620 // the referenced instance, for all others, value is the whole thing 621 // and data is null. 622 type DWAttr struct { 623 Link *DWAttr 624 Atr uint16 // DW_AT_ 625 Cls uint8 // DW_CLS_ 626 Value int64 627 Data interface{} 628 } 629 630 // DWDie represents a DWARF debug info entry. 631 type DWDie struct { 632 Abbrev int 633 Link *DWDie 634 Child *DWDie 635 Attr *DWAttr 636 Sym Sym 637 } 638 639 func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error { 640 switch form { 641 case DW_FORM_addr: // address 642 ctxt.AddAddress(s, data, value) 643 644 case DW_FORM_block1: // block 645 if cls == DW_CLS_ADDRESS { 646 ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize())) 647 ctxt.AddInt(s, 1, DW_OP_addr) 648 ctxt.AddAddress(s, data, 0) 649 break 650 } 651 652 value &= 0xff 653 ctxt.AddInt(s, 1, value) 654 p := data.([]byte)[:value] 655 ctxt.AddBytes(s, p) 656 657 case DW_FORM_block2: // block 658 value &= 0xffff 659 660 ctxt.AddInt(s, 2, value) 661 p := data.([]byte)[:value] 662 ctxt.AddBytes(s, p) 663 664 case DW_FORM_block4: // block 665 value &= 0xffffffff 666 667 ctxt.AddInt(s, 4, value) 668 p := data.([]byte)[:value] 669 ctxt.AddBytes(s, p) 670 671 case DW_FORM_block: // block 672 Uleb128put(ctxt, s, value) 673 674 p := data.([]byte)[:value] 675 ctxt.AddBytes(s, p) 676 677 case DW_FORM_data1: // constant 678 ctxt.AddInt(s, 1, value) 679 680 case DW_FORM_data2: // constant 681 ctxt.AddInt(s, 2, value) 682 683 case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr 684 if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges 685 ctxt.AddSectionOffset(s, 4, data, value) 686 break 687 } 688 ctxt.AddInt(s, 4, value) 689 690 case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr 691 ctxt.AddInt(s, 8, value) 692 693 case DW_FORM_sdata: // constant 694 Sleb128put(ctxt, s, value) 695 696 case DW_FORM_udata: // constant 697 Uleb128put(ctxt, s, value) 698 699 case DW_FORM_string: // string 700 str := data.(string) 701 ctxt.AddString(s, str) 702 // TODO(ribrdb): verify padded strings are never used and remove this 703 for i := int64(len(str)); i < value; i++ { 704 ctxt.AddInt(s, 1, 0) 705 } 706 707 case DW_FORM_flag: // flag 708 if value != 0 { 709 ctxt.AddInt(s, 1, 1) 710 } else { 711 ctxt.AddInt(s, 1, 0) 712 } 713 714 // As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large 715 // (> 4 GB of debug info aka "64-bit") unit, which we don't implement. 716 case DW_FORM_ref_addr: // reference to a DIE in the .info section 717 fallthrough 718 case DW_FORM_sec_offset: // offset into a DWARF section other than .info 719 if data == nil { 720 return fmt.Errorf("dwarf: null reference in %d", abbrev) 721 } 722 ctxt.AddSectionOffset(s, 4, data, value) 723 724 case DW_FORM_ref1, // reference within the compilation unit 725 DW_FORM_ref2, // reference 726 DW_FORM_ref4, // reference 727 DW_FORM_ref8, // reference 728 DW_FORM_ref_udata, // reference 729 730 DW_FORM_strp, // string 731 DW_FORM_indirect: // (see Section 7.5.3) 732 fallthrough 733 default: 734 return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls) 735 } 736 return nil 737 } 738 739 // PutAttrs writes the attributes for a DIE to symbol 's'. 740 // 741 // Note that we can (and do) add arbitrary attributes to a DIE, but 742 // only the ones actually listed in the Abbrev will be written out. 743 func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) { 744 Outer: 745 for _, f := range abbrevs[abbrev].attr { 746 for ap := attr; ap != nil; ap = ap.Link { 747 if ap.Atr == f.attr { 748 putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data) 749 continue Outer 750 } 751 } 752 753 putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil) 754 } 755 } 756 757 // HasChildren returns true if 'die' uses an abbrev that supports children. 758 func HasChildren(die *DWDie) bool { 759 return abbrevs[die.Abbrev].children != 0 760 } 761 762 // PutIntConst writes a DIE for an integer constant 763 func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) { 764 Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT) 765 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) 766 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ) 767 putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil) 768 } 769 770 // PutRanges writes a range table to sym. All addresses in ranges are 771 // relative to some base address. If base is not nil, then they're 772 // relative to the start of base. If base is nil, then the caller must 773 // arrange a base address some other way (such as a DW_AT_low_pc 774 // attribute). 775 func PutRanges(ctxt Context, sym Sym, base Sym, ranges []Range) { 776 ps := ctxt.PtrSize() 777 // Write ranges. 778 // We do not emit base address entries here, even though they would reduce 779 // the number of relocations, because dsymutil (which is used on macOS when 780 // linking externally) does not support them. 781 for _, r := range ranges { 782 if base == nil { 783 ctxt.AddInt(sym, ps, r.Start) 784 ctxt.AddInt(sym, ps, r.End) 785 } else { 786 ctxt.AddCURelativeAddress(sym, base, r.Start) 787 ctxt.AddCURelativeAddress(sym, base, r.End) 788 } 789 } 790 // Write trailer. 791 ctxt.AddInt(sym, ps, 0) 792 ctxt.AddInt(sym, ps, 0) 793 } 794 795 // PutFunc writes a DIE for a function to s. 796 // It also writes child DIEs for each variable in vars. 797 func PutFunc(ctxt Context, info, loc, ranges, filesym Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error { 798 Uleb128put(ctxt, info, DW_ABRV_FUNCTION) 799 putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) 800 putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, 0, startPC) 801 putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, size, startPC) 802 putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) 803 // DW_AT_decl_file attribute 804 ctxt.AddFileRef(info, filesym) 805 var ev int64 806 if external { 807 ev = 1 808 } 809 putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_flag, DW_CLS_FLAG, ev, 0) 810 if len(scopes) > 0 { 811 var encbuf [20]byte 812 if putscope(ctxt, info, loc, ranges, startPC, 0, scopes, encbuf[:0]) < int32(len(scopes)) { 813 return errors.New("multiple toplevel scopes") 814 } 815 } 816 Uleb128put(ctxt, info, 0) 817 return nil 818 } 819 820 func putscope(ctxt Context, info, loc, ranges, startPC Sym, curscope int32, scopes []Scope, encbuf []byte) int32 { 821 for _, v := range scopes[curscope].Vars { 822 putvar(ctxt, info, loc, v, startPC, encbuf) 823 } 824 this := curscope 825 curscope++ 826 for curscope < int32(len(scopes)) { 827 scope := scopes[curscope] 828 if scope.Parent != this { 829 return curscope 830 } 831 832 if len(scope.Ranges) == 1 { 833 Uleb128put(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE) 834 putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, startPC) 835 putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, startPC) 836 } else { 837 Uleb128put(ctxt, info, DW_ABRV_LEXICAL_BLOCK_RANGES) 838 putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, ranges.Len(), ranges) 839 840 PutRanges(ctxt, ranges, startPC, scope.Ranges) 841 } 842 843 curscope = putscope(ctxt, info, loc, ranges, startPC, curscope, scopes, encbuf) 844 845 Uleb128put(ctxt, info, 0) 846 } 847 return curscope 848 } 849 850 func putvar(ctxt Context, info, loc Sym, v *Var, startPC Sym, encbuf []byte) { 851 // If the variable was entirely optimized out, don't emit a location list; 852 // convert to an inline abbreviation and emit an empty location. 853 missing := false 854 switch { 855 case v.Abbrev == DW_ABRV_AUTO_LOCLIST && len(v.LocationList) == 0: 856 missing = true 857 v.Abbrev = DW_ABRV_AUTO 858 case v.Abbrev == DW_ABRV_PARAM_LOCLIST && len(v.LocationList) == 0: 859 missing = true 860 v.Abbrev = DW_ABRV_PARAM 861 } 862 863 Uleb128put(ctxt, info, int64(v.Abbrev)) 864 putattr(ctxt, info, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name) 865 if v.Abbrev == DW_ABRV_PARAM || v.Abbrev == DW_ABRV_PARAM_LOCLIST { 866 var isReturn int64 867 if v.IsReturnValue { 868 isReturn = 1 869 } 870 putattr(ctxt, info, v.Abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) 871 } 872 putattr(ctxt, info, v.Abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) 873 if v.Abbrev == DW_ABRV_AUTO_LOCLIST || v.Abbrev == DW_ABRV_PARAM_LOCLIST { 874 putattr(ctxt, info, v.Abbrev, DW_FORM_sec_offset, DW_CLS_PTR, int64(loc.Len()), loc) 875 addLocList(ctxt, loc, startPC, v, encbuf) 876 } else { 877 loc := encbuf[:0] 878 switch { 879 case missing: 880 break // no location 881 case v.StackOffset == 0: 882 loc = append(loc, DW_OP_call_frame_cfa) 883 default: 884 loc = append(loc, DW_OP_fbreg) 885 loc = AppendSleb128(loc, int64(v.StackOffset)) 886 } 887 putattr(ctxt, info, v.Abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) 888 } 889 putattr(ctxt, info, v.Abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) 890 } 891 892 func addLocList(ctxt Context, listSym, startPC Sym, v *Var, encbuf []byte) { 893 // Base address entry: max ptr followed by the base address. 894 ctxt.AddInt(listSym, ctxt.PtrSize(), ^0) 895 ctxt.AddAddress(listSym, startPC, 0) 896 for _, entry := range v.LocationList { 897 ctxt.AddInt(listSym, ctxt.PtrSize(), entry.StartPC) 898 ctxt.AddInt(listSym, ctxt.PtrSize(), entry.EndPC) 899 locBuf := encbuf[:0] 900 for _, piece := range entry.Pieces { 901 if !piece.Missing { 902 if piece.OnStack { 903 if piece.StackOffset == 0 { 904 locBuf = append(locBuf, DW_OP_call_frame_cfa) 905 } else { 906 locBuf = append(locBuf, DW_OP_fbreg) 907 locBuf = AppendSleb128(locBuf, int64(piece.StackOffset)) 908 } 909 } else { 910 if piece.RegNum < 32 { 911 locBuf = append(locBuf, DW_OP_reg0+byte(piece.RegNum)) 912 } else { 913 locBuf = append(locBuf, DW_OP_regx) 914 locBuf = AppendUleb128(locBuf, uint64(piece.RegNum)) 915 } 916 } 917 } 918 if len(entry.Pieces) > 1 { 919 locBuf = append(locBuf, DW_OP_piece) 920 locBuf = AppendUleb128(locBuf, uint64(piece.Length)) 921 } 922 } 923 ctxt.AddInt(listSym, 2, int64(len(locBuf))) 924 ctxt.AddBytes(listSym, locBuf) 925 } 926 // End list 927 ctxt.AddInt(listSym, ctxt.PtrSize(), 0) 928 ctxt.AddInt(listSym, ctxt.PtrSize(), 0) 929 } 930 931 // VarsByOffset attaches the methods of sort.Interface to []*Var, 932 // sorting in increasing StackOffset. 933 type VarsByOffset []*Var 934 935 func (s VarsByOffset) Len() int { return len(s) } 936 func (s VarsByOffset) Less(i, j int) bool { return s[i].StackOffset < s[j].StackOffset } 937 func (s VarsByOffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] }