github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/src/cmd/link/internal/ld/dwarf.go (about) 1 // Copyright 2010 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 // TODO/NICETOHAVE: 6 // - eliminate DW_CLS_ if not used 7 // - package info in compilation units 8 // - assign global variables and types to their packages 9 // - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg 10 // ptype struct '[]uint8' and qualifiers need to be quoted away 11 // - file:line info for variables 12 // - make strings a typedef so prettyprinters can see the underlying string type 13 14 package ld 15 16 import ( 17 "cmd/internal/dwarf" 18 "cmd/internal/objabi" 19 "fmt" 20 "log" 21 "os" 22 "strings" 23 ) 24 25 type dwctxt struct { 26 linkctxt *Link 27 } 28 29 func (c dwctxt) PtrSize() int { 30 return SysArch.PtrSize 31 } 32 func (c dwctxt) AddInt(s dwarf.Sym, size int, i int64) { 33 ls := s.(*Symbol) 34 adduintxx(c.linkctxt, ls, uint64(i), size) 35 } 36 func (c dwctxt) AddBytes(s dwarf.Sym, b []byte) { 37 ls := s.(*Symbol) 38 Addbytes(ls, b) 39 } 40 func (c dwctxt) AddString(s dwarf.Sym, v string) { 41 Addstring(s.(*Symbol), v) 42 } 43 func (c dwctxt) SymValue(s dwarf.Sym) int64 { 44 return s.(*Symbol).Value 45 } 46 47 func (c dwctxt) AddAddress(s dwarf.Sym, data interface{}, value int64) { 48 if value != 0 { 49 value -= (data.(*Symbol)).Value 50 } 51 Addaddrplus(c.linkctxt, s.(*Symbol), data.(*Symbol), value) 52 } 53 54 func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) { 55 ls := s.(*Symbol) 56 switch size { 57 default: 58 Errorf(ls, "invalid size %d in adddwarfref\n", size) 59 fallthrough 60 case SysArch.PtrSize: 61 Addaddr(c.linkctxt, ls, t.(*Symbol)) 62 case 4: 63 addaddrplus4(c.linkctxt, ls, t.(*Symbol), 0) 64 } 65 r := &ls.R[len(ls.R)-1] 66 r.Type = objabi.R_DWARFREF 67 r.Add = ofs 68 } 69 70 var gdbscript string 71 72 var dwarfp []*Symbol 73 74 func writeabbrev(ctxt *Link) *Symbol { 75 s := ctxt.Syms.Lookup(".debug_abbrev", 0) 76 s.Type = SDWARFSECT 77 Addbytes(s, dwarf.GetAbbrev()) 78 return s 79 } 80 81 /* 82 * Root DIEs for compilation units, types and global variables. 83 */ 84 var dwroot dwarf.DWDie 85 86 var dwtypes dwarf.DWDie 87 88 var dwglobals dwarf.DWDie 89 90 func newattr(die *dwarf.DWDie, attr uint16, cls int, value int64, data interface{}) *dwarf.DWAttr { 91 a := new(dwarf.DWAttr) 92 a.Link = die.Attr 93 die.Attr = a 94 a.Atr = attr 95 a.Cls = uint8(cls) 96 a.Value = value 97 a.Data = data 98 return a 99 } 100 101 // Each DIE (except the root ones) has at least 1 attribute: its 102 // name. getattr moves the desired one to the front so 103 // frequently searched ones are found faster. 104 func getattr(die *dwarf.DWDie, attr uint16) *dwarf.DWAttr { 105 if die.Attr.Atr == attr { 106 return die.Attr 107 } 108 109 a := die.Attr 110 b := a.Link 111 for b != nil { 112 if b.Atr == attr { 113 a.Link = b.Link 114 b.Link = die.Attr 115 die.Attr = b 116 return b 117 } 118 119 a = b 120 b = b.Link 121 } 122 123 return nil 124 } 125 126 // Every DIE has at least a AT_name attribute (but it will only be 127 // written out if it is listed in the abbrev). 128 func newdie(ctxt *Link, parent *dwarf.DWDie, abbrev int, name string, version int) *dwarf.DWDie { 129 die := new(dwarf.DWDie) 130 die.Abbrev = abbrev 131 die.Link = parent.Child 132 parent.Child = die 133 134 newattr(die, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len(name)), name) 135 136 if name != "" && (abbrev <= dwarf.DW_ABRV_VARIABLE || abbrev >= dwarf.DW_ABRV_NULLTYPE) { 137 if abbrev != dwarf.DW_ABRV_VARIABLE || version == 0 { 138 sym := ctxt.Syms.Lookup(dwarf.InfoPrefix+name, version) 139 sym.Attr |= AttrNotInSymbolTable 140 sym.Type = SDWARFINFO 141 die.Sym = sym 142 } 143 } 144 145 return die 146 } 147 148 func walktypedef(die *dwarf.DWDie) *dwarf.DWDie { 149 if die == nil { 150 return nil 151 } 152 // Resolve typedef if present. 153 if die.Abbrev == dwarf.DW_ABRV_TYPEDECL { 154 for attr := die.Attr; attr != nil; attr = attr.Link { 155 if attr.Atr == dwarf.DW_AT_type && attr.Cls == dwarf.DW_CLS_REFERENCE && attr.Data != nil { 156 return attr.Data.(*dwarf.DWDie) 157 } 158 } 159 } 160 161 return die 162 } 163 164 func walksymtypedef(ctxt *Link, s *Symbol) *Symbol { 165 if t := ctxt.Syms.ROLookup(s.Name+"..def", int(s.Version)); t != nil { 166 return t 167 } 168 return s 169 } 170 171 // Find child by AT_name using hashtable if available or linear scan 172 // if not. 173 func findchild(die *dwarf.DWDie, name string) *dwarf.DWDie { 174 var prev *dwarf.DWDie 175 for ; die != prev; prev, die = die, walktypedef(die) { 176 for a := die.Child; a != nil; a = a.Link { 177 if name == getattr(a, dwarf.DW_AT_name).Data { 178 return a 179 } 180 } 181 continue 182 } 183 return nil 184 } 185 186 // Used to avoid string allocation when looking up dwarf symbols 187 var prefixBuf = []byte(dwarf.InfoPrefix) 188 189 func find(ctxt *Link, name string) *Symbol { 190 n := append(prefixBuf, name...) 191 // The string allocation below is optimized away because it is only used in a map lookup. 192 s := ctxt.Syms.ROLookup(string(n), 0) 193 prefixBuf = n[:len(dwarf.InfoPrefix)] 194 if s != nil && s.Type == SDWARFINFO { 195 return s 196 } 197 return nil 198 } 199 200 func mustFind(ctxt *Link, name string) *Symbol { 201 r := find(ctxt, name) 202 if r == nil { 203 Exitf("dwarf find: cannot find %s", name) 204 } 205 return r 206 } 207 208 func adddwarfref(ctxt *Link, s *Symbol, t *Symbol, size int) int64 { 209 var result int64 210 switch size { 211 default: 212 Errorf(s, "invalid size %d in adddwarfref\n", size) 213 fallthrough 214 case SysArch.PtrSize: 215 result = Addaddr(ctxt, s, t) 216 case 4: 217 result = addaddrplus4(ctxt, s, t, 0) 218 } 219 r := &s.R[len(s.R)-1] 220 r.Type = objabi.R_DWARFREF 221 return result 222 } 223 224 func newrefattr(die *dwarf.DWDie, attr uint16, ref *Symbol) *dwarf.DWAttr { 225 if ref == nil { 226 return nil 227 } 228 return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, ref) 229 } 230 231 func putdies(linkctxt *Link, ctxt dwarf.Context, syms []*Symbol, die *dwarf.DWDie) []*Symbol { 232 for ; die != nil; die = die.Link { 233 syms = putdie(linkctxt, ctxt, syms, die) 234 } 235 Adduint8(linkctxt, syms[len(syms)-1], 0) 236 237 return syms 238 } 239 240 func dtolsym(s dwarf.Sym) *Symbol { 241 if s == nil { 242 return nil 243 } 244 return s.(*Symbol) 245 } 246 247 func putdie(linkctxt *Link, ctxt dwarf.Context, syms []*Symbol, die *dwarf.DWDie) []*Symbol { 248 s := dtolsym(die.Sym) 249 if s == nil { 250 s = syms[len(syms)-1] 251 } else { 252 if s.Attr.OnList() { 253 log.Fatalf("symbol %s listed multiple times", s.Name) 254 } 255 s.Attr |= AttrOnList 256 syms = append(syms, s) 257 } 258 dwarf.Uleb128put(ctxt, s, int64(die.Abbrev)) 259 dwarf.PutAttrs(ctxt, s, die.Abbrev, die.Attr) 260 if dwarf.HasChildren(die) { 261 return putdies(linkctxt, ctxt, syms, die.Child) 262 } 263 return syms 264 } 265 266 func reverselist(list **dwarf.DWDie) { 267 curr := *list 268 var prev *dwarf.DWDie 269 for curr != nil { 270 var next *dwarf.DWDie = curr.Link 271 curr.Link = prev 272 prev = curr 273 curr = next 274 } 275 276 *list = prev 277 } 278 279 func reversetree(list **dwarf.DWDie) { 280 reverselist(list) 281 for die := *list; die != nil; die = die.Link { 282 if dwarf.HasChildren(die) { 283 reversetree(&die.Child) 284 } 285 } 286 } 287 288 func newmemberoffsetattr(die *dwarf.DWDie, offs int32) { 289 newattr(die, dwarf.DW_AT_data_member_location, dwarf.DW_CLS_CONSTANT, int64(offs), nil) 290 } 291 292 // GDB doesn't like FORM_addr for AT_location, so emit a 293 // location expression that evals to a const. 294 func newabslocexprattr(die *dwarf.DWDie, addr int64, sym *Symbol) { 295 newattr(die, dwarf.DW_AT_location, dwarf.DW_CLS_ADDRESS, addr, sym) 296 // below 297 } 298 299 // Lookup predefined types 300 func lookupOrDiag(ctxt *Link, n string) *Symbol { 301 s := ctxt.Syms.ROLookup(n, 0) 302 if s == nil || s.Size == 0 { 303 Exitf("dwarf: missing type: %s", n) 304 } 305 306 return s 307 } 308 309 func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) { 310 // Only emit typedefs for real names. 311 if strings.HasPrefix(name, "map[") { 312 return 313 } 314 if strings.HasPrefix(name, "struct {") { 315 return 316 } 317 if strings.HasPrefix(name, "chan ") { 318 return 319 } 320 if name[0] == '[' || name[0] == '*' { 321 return 322 } 323 if def == nil { 324 Errorf(nil, "dwarf: bad def in dotypedef") 325 } 326 327 sym := ctxt.Syms.Lookup(dtolsym(def.Sym).Name+"..def", 0) 328 sym.Attr |= AttrNotInSymbolTable 329 sym.Type = SDWARFINFO 330 def.Sym = sym 331 332 // The typedef entry must be created after the def, 333 // so that future lookups will find the typedef instead 334 // of the real definition. This hooks the typedef into any 335 // circular definition loops, so that gdb can understand them. 336 die := newdie(ctxt, parent, dwarf.DW_ABRV_TYPEDECL, name, 0) 337 338 newrefattr(die, dwarf.DW_AT_type, sym) 339 } 340 341 // Define gotype, for composite ones recurse into constituents. 342 func defgotype(ctxt *Link, gotype *Symbol) *Symbol { 343 if gotype == nil { 344 return mustFind(ctxt, "<unspecified>") 345 } 346 347 if !strings.HasPrefix(gotype.Name, "type.") { 348 Errorf(gotype, "dwarf: type name doesn't start with \"type.\"") 349 return mustFind(ctxt, "<unspecified>") 350 } 351 352 name := gotype.Name[5:] // could also decode from Type.string 353 354 sdie := find(ctxt, name) 355 356 if sdie != nil { 357 return sdie 358 } 359 360 return newtype(ctxt, gotype).Sym.(*Symbol) 361 } 362 363 func newtype(ctxt *Link, gotype *Symbol) *dwarf.DWDie { 364 name := gotype.Name[5:] // could also decode from Type.string 365 kind := decodetypeKind(gotype) 366 bytesize := decodetypeSize(ctxt.Arch, gotype) 367 368 var die *dwarf.DWDie 369 switch kind { 370 case objabi.KindBool: 371 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) 372 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_boolean, 0) 373 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 374 375 case objabi.KindInt, 376 objabi.KindInt8, 377 objabi.KindInt16, 378 objabi.KindInt32, 379 objabi.KindInt64: 380 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) 381 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_signed, 0) 382 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 383 384 case objabi.KindUint, 385 objabi.KindUint8, 386 objabi.KindUint16, 387 objabi.KindUint32, 388 objabi.KindUint64, 389 objabi.KindUintptr: 390 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) 391 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0) 392 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 393 394 case objabi.KindFloat32, 395 objabi.KindFloat64: 396 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) 397 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_float, 0) 398 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 399 400 case objabi.KindComplex64, 401 objabi.KindComplex128: 402 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) 403 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_complex_float, 0) 404 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 405 406 case objabi.KindArray: 407 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_ARRAYTYPE, name, 0) 408 dotypedef(ctxt, &dwtypes, name, die) 409 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 410 s := decodetypeArrayElem(gotype) 411 newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s)) 412 fld := newdie(ctxt, die, dwarf.DW_ABRV_ARRAYRANGE, "range", 0) 413 414 // use actual length not upper bound; correct for 0-length arrays. 415 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, decodetypeArrayLen(ctxt.Arch, gotype), 0) 416 417 newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr")) 418 419 case objabi.KindChan: 420 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_CHANTYPE, name, 0) 421 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 422 s := decodetypeChanElem(gotype) 423 newrefattr(die, dwarf.DW_AT_go_elem, defgotype(ctxt, s)) 424 // Save elem type for synthesizechantypes. We could synthesize here 425 // but that would change the order of DIEs we output. 426 newrefattr(die, dwarf.DW_AT_type, s) 427 428 case objabi.KindFunc: 429 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_FUNCTYPE, name, 0) 430 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 431 dotypedef(ctxt, &dwtypes, name, die) 432 newrefattr(die, dwarf.DW_AT_type, mustFind(ctxt, "void")) 433 nfields := decodetypeFuncInCount(ctxt.Arch, gotype) 434 var fld *dwarf.DWDie 435 var s *Symbol 436 for i := 0; i < nfields; i++ { 437 s = decodetypeFuncInType(gotype, i) 438 fld = newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0) 439 newrefattr(fld, dwarf.DW_AT_type, defgotype(ctxt, s)) 440 } 441 442 if decodetypeFuncDotdotdot(ctxt.Arch, gotype) { 443 newdie(ctxt, die, dwarf.DW_ABRV_DOTDOTDOT, "...", 0) 444 } 445 nfields = decodetypeFuncOutCount(ctxt.Arch, gotype) 446 for i := 0; i < nfields; i++ { 447 s = decodetypeFuncOutType(ctxt.Arch, gotype, i) 448 fld = newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0) 449 newrefattr(fld, dwarf.DW_AT_type, defptrto(ctxt, defgotype(ctxt, s))) 450 } 451 452 case objabi.KindInterface: 453 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_IFACETYPE, name, 0) 454 dotypedef(ctxt, &dwtypes, name, die) 455 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 456 nfields := int(decodetypeIfaceMethodCount(ctxt.Arch, gotype)) 457 var s *Symbol 458 if nfields == 0 { 459 s = lookupOrDiag(ctxt, "type.runtime.eface") 460 } else { 461 s = lookupOrDiag(ctxt, "type.runtime.iface") 462 } 463 newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s)) 464 465 case objabi.KindMap: 466 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_MAPTYPE, name, 0) 467 s := decodetypeMapKey(gotype) 468 newrefattr(die, dwarf.DW_AT_go_key, defgotype(ctxt, s)) 469 s = decodetypeMapValue(gotype) 470 newrefattr(die, dwarf.DW_AT_go_elem, defgotype(ctxt, s)) 471 // Save gotype for use in synthesizemaptypes. We could synthesize here, 472 // but that would change the order of the DIEs. 473 newrefattr(die, dwarf.DW_AT_type, gotype) 474 475 case objabi.KindPtr: 476 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_PTRTYPE, name, 0) 477 dotypedef(ctxt, &dwtypes, name, die) 478 s := decodetypePtrElem(gotype) 479 newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s)) 480 481 case objabi.KindSlice: 482 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_SLICETYPE, name, 0) 483 dotypedef(ctxt, &dwtypes, name, die) 484 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 485 s := decodetypeArrayElem(gotype) 486 elem := defgotype(ctxt, s) 487 newrefattr(die, dwarf.DW_AT_go_elem, elem) 488 489 case objabi.KindString: 490 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRINGTYPE, name, 0) 491 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 492 493 case objabi.KindStruct: 494 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRUCTTYPE, name, 0) 495 dotypedef(ctxt, &dwtypes, name, die) 496 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 497 nfields := decodetypeStructFieldCount(ctxt.Arch, gotype) 498 for i := 0; i < nfields; i++ { 499 f := decodetypeStructFieldName(gotype, i) 500 s := decodetypeStructFieldType(gotype, i) 501 if f == "" { 502 f = s.Name[5:] // skip "type." 503 } 504 fld := newdie(ctxt, die, dwarf.DW_ABRV_STRUCTFIELD, f, 0) 505 newrefattr(fld, dwarf.DW_AT_type, defgotype(ctxt, s)) 506 offsetAnon := decodetypeStructFieldOffsAnon(ctxt.Arch, gotype, i) 507 newmemberoffsetattr(fld, int32(offsetAnon>>1)) 508 if offsetAnon&1 != 0 { // is embedded field 509 newattr(fld, dwarf.DW_AT_go_embedded_field, dwarf.DW_CLS_FLAG, 1, 0) 510 } 511 } 512 513 case objabi.KindUnsafePointer: 514 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, name, 0) 515 516 default: 517 Errorf(gotype, "dwarf: definition of unknown kind %d", kind) 518 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_TYPEDECL, name, 0) 519 newrefattr(die, dwarf.DW_AT_type, mustFind(ctxt, "<unspecified>")) 520 } 521 522 newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(kind), 0) 523 524 if _, ok := prototypedies[gotype.Name]; ok { 525 prototypedies[gotype.Name] = die 526 } 527 528 return die 529 } 530 531 func nameFromDIESym(dwtype *Symbol) string { 532 return strings.TrimSuffix(dwtype.Name[len(dwarf.InfoPrefix):], "..def") 533 } 534 535 // Find or construct *T given T. 536 func defptrto(ctxt *Link, dwtype *Symbol) *Symbol { 537 ptrname := "*" + nameFromDIESym(dwtype) 538 die := find(ctxt, ptrname) 539 if die == nil { 540 pdie := newdie(ctxt, &dwtypes, dwarf.DW_ABRV_PTRTYPE, ptrname, 0) 541 newrefattr(pdie, dwarf.DW_AT_type, dwtype) 542 return dtolsym(pdie.Sym) 543 } 544 545 return die 546 } 547 548 // Copies src's children into dst. Copies attributes by value. 549 // DWAttr.data is copied as pointer only. If except is one of 550 // the top-level children, it will not be copied. 551 func copychildrenexcept(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie, except *dwarf.DWDie) { 552 for src = src.Child; src != nil; src = src.Link { 553 if src == except { 554 continue 555 } 556 c := newdie(ctxt, dst, src.Abbrev, getattr(src, dwarf.DW_AT_name).Data.(string), 0) 557 for a := src.Attr; a != nil; a = a.Link { 558 newattr(c, a.Atr, int(a.Cls), a.Value, a.Data) 559 } 560 copychildrenexcept(ctxt, c, src, nil) 561 } 562 563 reverselist(&dst.Child) 564 } 565 566 func copychildren(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie) { 567 copychildrenexcept(ctxt, dst, src, nil) 568 } 569 570 // Search children (assumed to have TAG_member) for the one named 571 // field and set its AT_type to dwtype 572 func substitutetype(structdie *dwarf.DWDie, field string, dwtype *Symbol) { 573 child := findchild(structdie, field) 574 if child == nil { 575 Exitf("dwarf substitutetype: %s does not have member %s", 576 getattr(structdie, dwarf.DW_AT_name).Data, field) 577 return 578 } 579 580 a := getattr(child, dwarf.DW_AT_type) 581 if a != nil { 582 a.Data = dwtype 583 } else { 584 newrefattr(child, dwarf.DW_AT_type, dwtype) 585 } 586 } 587 588 func findprotodie(ctxt *Link, name string) *dwarf.DWDie { 589 die, ok := prototypedies[name] 590 if ok && die == nil { 591 defgotype(ctxt, lookupOrDiag(ctxt, name)) 592 die = prototypedies[name] 593 } 594 return die 595 } 596 597 func synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) { 598 prototype := walktypedef(findprotodie(ctxt, "type.runtime.stringStructDWARF")) 599 if prototype == nil { 600 return 601 } 602 603 for ; die != nil; die = die.Link { 604 if die.Abbrev != dwarf.DW_ABRV_STRINGTYPE { 605 continue 606 } 607 copychildren(ctxt, die, prototype) 608 } 609 } 610 611 func synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) { 612 prototype := walktypedef(findprotodie(ctxt, "type.runtime.slice")) 613 if prototype == nil { 614 return 615 } 616 617 for ; die != nil; die = die.Link { 618 if die.Abbrev != dwarf.DW_ABRV_SLICETYPE { 619 continue 620 } 621 copychildren(ctxt, die, prototype) 622 elem := getattr(die, dwarf.DW_AT_go_elem).Data.(*Symbol) 623 substitutetype(die, "array", defptrto(ctxt, elem)) 624 } 625 } 626 627 func mkinternaltypename(base string, arg1 string, arg2 string) string { 628 var buf string 629 630 if arg2 == "" { 631 buf = fmt.Sprintf("%s<%s>", base, arg1) 632 } else { 633 buf = fmt.Sprintf("%s<%s,%s>", base, arg1, arg2) 634 } 635 n := buf 636 return n 637 } 638 639 // synthesizemaptypes is way too closely married to runtime/hashmap.c 640 const ( 641 MaxKeySize = 128 642 MaxValSize = 128 643 BucketSize = 8 644 ) 645 646 func mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) *Symbol { 647 name := mkinternaltypename(typename, keyname, valname) 648 symname := dwarf.InfoPrefix + name 649 s := ctxt.Syms.ROLookup(symname, 0) 650 if s != nil && s.Type == SDWARFINFO { 651 return s 652 } 653 die := newdie(ctxt, &dwtypes, abbrev, name, 0) 654 f(die) 655 return dtolsym(die.Sym) 656 } 657 658 func synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) { 659 hash := walktypedef(findprotodie(ctxt, "type.runtime.hmap")) 660 bucket := walktypedef(findprotodie(ctxt, "type.runtime.bmap")) 661 662 if hash == nil { 663 return 664 } 665 666 for ; die != nil; die = die.Link { 667 if die.Abbrev != dwarf.DW_ABRV_MAPTYPE { 668 continue 669 } 670 gotype := getattr(die, dwarf.DW_AT_type).Data.(*Symbol) 671 keytype := decodetypeMapKey(gotype) 672 valtype := decodetypeMapValue(gotype) 673 keysize, valsize := decodetypeSize(ctxt.Arch, keytype), decodetypeSize(ctxt.Arch, valtype) 674 keytype, valtype = walksymtypedef(ctxt, defgotype(ctxt, keytype)), walksymtypedef(ctxt, defgotype(ctxt, valtype)) 675 676 // compute size info like hashmap.c does. 677 indirectKey, indirectVal := false, false 678 if keysize > MaxKeySize { 679 keysize = int64(SysArch.PtrSize) 680 indirectKey = true 681 } 682 if valsize > MaxValSize { 683 valsize = int64(SysArch.PtrSize) 684 indirectVal = true 685 } 686 687 // Construct type to represent an array of BucketSize keys 688 keyname := nameFromDIESym(keytype) 689 dwhks := mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) { 690 newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*keysize, 0) 691 t := keytype 692 if indirectKey { 693 t = defptrto(ctxt, keytype) 694 } 695 newrefattr(dwhk, dwarf.DW_AT_type, t) 696 fld := newdie(ctxt, dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size", 0) 697 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0) 698 newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr")) 699 }) 700 701 // Construct type to represent an array of BucketSize values 702 valname := nameFromDIESym(valtype) 703 dwhvs := mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) { 704 newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*valsize, 0) 705 t := valtype 706 if indirectVal { 707 t = defptrto(ctxt, valtype) 708 } 709 newrefattr(dwhv, dwarf.DW_AT_type, t) 710 fld := newdie(ctxt, dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size", 0) 711 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0) 712 newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr")) 713 }) 714 715 // Construct bucket<K,V> 716 dwhbs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *dwarf.DWDie) { 717 // Copy over all fields except the field "data" from the generic 718 // bucket. "data" will be replaced with keys/values below. 719 copychildrenexcept(ctxt, dwhb, bucket, findchild(bucket, "data")) 720 721 fld := newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys", 0) 722 newrefattr(fld, dwarf.DW_AT_type, dwhks) 723 newmemberoffsetattr(fld, BucketSize) 724 fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values", 0) 725 newrefattr(fld, dwarf.DW_AT_type, dwhvs) 726 newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize)) 727 fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow", 0) 728 newrefattr(fld, dwarf.DW_AT_type, defptrto(ctxt, dtolsym(dwhb.Sym))) 729 newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))) 730 if SysArch.RegSize > SysArch.PtrSize { 731 fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad", 0) 732 newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr")) 733 newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(SysArch.PtrSize)) 734 } 735 736 newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize+BucketSize*keysize+BucketSize*valsize+int64(SysArch.RegSize), 0) 737 }) 738 739 // Construct hash<K,V> 740 dwhs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *dwarf.DWDie) { 741 copychildren(ctxt, dwh, hash) 742 substitutetype(dwh, "buckets", defptrto(ctxt, dwhbs)) 743 substitutetype(dwh, "oldbuckets", defptrto(ctxt, dwhbs)) 744 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hash, dwarf.DW_AT_byte_size).Value, nil) 745 }) 746 747 // make map type a pointer to hash<K,V> 748 newrefattr(die, dwarf.DW_AT_type, defptrto(ctxt, dwhs)) 749 } 750 } 751 752 func synthesizechantypes(ctxt *Link, die *dwarf.DWDie) { 753 sudog := walktypedef(findprotodie(ctxt, "type.runtime.sudog")) 754 waitq := walktypedef(findprotodie(ctxt, "type.runtime.waitq")) 755 hchan := walktypedef(findprotodie(ctxt, "type.runtime.hchan")) 756 if sudog == nil || waitq == nil || hchan == nil { 757 return 758 } 759 760 sudogsize := int(getattr(sudog, dwarf.DW_AT_byte_size).Value) 761 762 for ; die != nil; die = die.Link { 763 if die.Abbrev != dwarf.DW_ABRV_CHANTYPE { 764 continue 765 } 766 elemgotype := getattr(die, dwarf.DW_AT_type).Data.(*Symbol) 767 elemname := elemgotype.Name[5:] 768 elemtype := walksymtypedef(ctxt, defgotype(ctxt, elemgotype)) 769 770 // sudog<T> 771 dwss := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "sudog", elemname, "", func(dws *dwarf.DWDie) { 772 copychildren(ctxt, dws, sudog) 773 substitutetype(dws, "elem", defptrto(ctxt, elemtype)) 774 newattr(dws, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(sudogsize), nil) 775 }) 776 777 // waitq<T> 778 dwws := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "waitq", elemname, "", func(dww *dwarf.DWDie) { 779 780 copychildren(ctxt, dww, waitq) 781 substitutetype(dww, "first", defptrto(ctxt, dwss)) 782 substitutetype(dww, "last", defptrto(ctxt, dwss)) 783 newattr(dww, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(waitq, dwarf.DW_AT_byte_size).Value, nil) 784 }) 785 786 // hchan<T> 787 dwhs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hchan", elemname, "", func(dwh *dwarf.DWDie) { 788 copychildren(ctxt, dwh, hchan) 789 substitutetype(dwh, "recvq", dwws) 790 substitutetype(dwh, "sendq", dwws) 791 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hchan, dwarf.DW_AT_byte_size).Value, nil) 792 }) 793 794 newrefattr(die, dwarf.DW_AT_type, defptrto(ctxt, dwhs)) 795 } 796 } 797 798 // For use with pass.c::genasmsym 799 func defdwsymb(ctxt *Link, sym *Symbol, s string, t SymbolType, v int64, gotype *Symbol) { 800 if strings.HasPrefix(s, "go.string.") { 801 return 802 } 803 if strings.HasPrefix(s, "runtime.gcbits.") { 804 return 805 } 806 807 if strings.HasPrefix(s, "type.") && s != "type.*" && !strings.HasPrefix(s, "type..") { 808 defgotype(ctxt, sym) 809 return 810 } 811 812 var dv *dwarf.DWDie 813 814 var dt *Symbol 815 switch t { 816 default: 817 return 818 819 case DataSym, BSSSym: 820 dv = newdie(ctxt, &dwglobals, dwarf.DW_ABRV_VARIABLE, s, int(sym.Version)) 821 newabslocexprattr(dv, v, sym) 822 if sym.Version == 0 { 823 newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0) 824 } 825 fallthrough 826 827 case AutoSym, ParamSym: 828 dt = defgotype(ctxt, gotype) 829 } 830 831 if dv != nil { 832 newrefattr(dv, dwarf.DW_AT_type, dt) 833 } 834 } 835 836 func movetomodule(parent *dwarf.DWDie) { 837 die := dwroot.Child.Child 838 if die == nil { 839 dwroot.Child.Child = parent.Child 840 return 841 } 842 for die.Link != nil { 843 die = die.Link 844 } 845 die.Link = parent.Child 846 } 847 848 // If the pcln table contains runtime/runtime.go, use that to set gdbscript path. 849 func finddebugruntimepath(s *Symbol) { 850 if gdbscript != "" { 851 return 852 } 853 854 for i := range s.FuncInfo.File { 855 f := s.FuncInfo.File[i] 856 if i := strings.Index(f.Name, "runtime/debug.go"); i >= 0 { 857 gdbscript = f.Name[:i] + "runtime/runtime-gdb.py" 858 break 859 } 860 } 861 } 862 863 /* 864 * Generate a sequence of opcodes that is as short as possible. 865 * See section 6.2.5 866 */ 867 const ( 868 LINE_BASE = -4 869 LINE_RANGE = 10 870 PC_RANGE = (255 - OPCODE_BASE) / LINE_RANGE 871 OPCODE_BASE = 10 872 ) 873 874 func putpclcdelta(linkctxt *Link, ctxt dwarf.Context, s *Symbol, deltaPC uint64, deltaLC int64) { 875 // Choose a special opcode that minimizes the number of bytes needed to 876 // encode the remaining PC delta and LC delta. 877 var opcode int64 878 if deltaLC < LINE_BASE { 879 if deltaPC >= PC_RANGE { 880 opcode = OPCODE_BASE + (LINE_RANGE * PC_RANGE) 881 } else { 882 opcode = OPCODE_BASE + (LINE_RANGE * int64(deltaPC)) 883 } 884 } else if deltaLC < LINE_BASE+LINE_RANGE { 885 if deltaPC >= PC_RANGE { 886 opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * PC_RANGE) 887 if opcode > 255 { 888 opcode -= LINE_RANGE 889 } 890 } else { 891 opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * int64(deltaPC)) 892 } 893 } else { 894 if deltaPC <= PC_RANGE { 895 opcode = OPCODE_BASE + (LINE_RANGE - 1) + (LINE_RANGE * int64(deltaPC)) 896 if opcode > 255 { 897 opcode = 255 898 } 899 } else { 900 // Use opcode 249 (pc+=23, lc+=5) or 255 (pc+=24, lc+=1). 901 // 902 // Let x=deltaPC-PC_RANGE. If we use opcode 255, x will be the remaining 903 // deltaPC that we need to encode separately before emitting 255. If we 904 // use opcode 249, we will need to encode x+1. If x+1 takes one more 905 // byte to encode than x, then we use opcode 255. 906 // 907 // In all other cases x and x+1 take the same number of bytes to encode, 908 // so we use opcode 249, which may save us a byte in encoding deltaLC, 909 // for similar reasons. 910 switch deltaPC - PC_RANGE { 911 // PC_RANGE is the largest deltaPC we can encode in one byte, using 912 // DW_LNS_const_add_pc. 913 // 914 // (1<<16)-1 is the largest deltaPC we can encode in three bytes, using 915 // DW_LNS_fixed_advance_pc. 916 // 917 // (1<<(7n))-1 is the largest deltaPC we can encode in n+1 bytes for 918 // n=1,3,4,5,..., using DW_LNS_advance_pc. 919 case PC_RANGE, (1 << 7) - 1, (1 << 16) - 1, (1 << 21) - 1, (1 << 28) - 1, 920 (1 << 35) - 1, (1 << 42) - 1, (1 << 49) - 1, (1 << 56) - 1, (1 << 63) - 1: 921 opcode = 255 922 default: 923 opcode = OPCODE_BASE + LINE_RANGE*PC_RANGE - 1 // 249 924 } 925 } 926 } 927 if opcode < OPCODE_BASE || opcode > 255 { 928 panic(fmt.Sprintf("produced invalid special opcode %d", opcode)) 929 } 930 931 // Subtract from deltaPC and deltaLC the amounts that the opcode will add. 932 deltaPC -= uint64((opcode - OPCODE_BASE) / LINE_RANGE) 933 deltaLC -= int64((opcode-OPCODE_BASE)%LINE_RANGE + LINE_BASE) 934 935 // Encode deltaPC. 936 if deltaPC != 0 { 937 if deltaPC <= PC_RANGE { 938 // Adjust the opcode so that we can use the 1-byte DW_LNS_const_add_pc 939 // instruction. 940 opcode -= LINE_RANGE * int64(PC_RANGE-deltaPC) 941 if opcode < OPCODE_BASE { 942 panic(fmt.Sprintf("produced invalid special opcode %d", opcode)) 943 } 944 Adduint8(linkctxt, s, dwarf.DW_LNS_const_add_pc) 945 } else if (1<<14) <= deltaPC && deltaPC < (1<<16) { 946 Adduint8(linkctxt, s, dwarf.DW_LNS_fixed_advance_pc) 947 Adduint16(linkctxt, s, uint16(deltaPC)) 948 } else { 949 Adduint8(linkctxt, s, dwarf.DW_LNS_advance_pc) 950 dwarf.Uleb128put(ctxt, s, int64(deltaPC)) 951 } 952 } 953 954 // Encode deltaLC. 955 if deltaLC != 0 { 956 Adduint8(linkctxt, s, dwarf.DW_LNS_advance_line) 957 dwarf.Sleb128put(ctxt, s, deltaLC) 958 } 959 960 // Output the special opcode. 961 Adduint8(linkctxt, s, uint8(opcode)) 962 } 963 964 /* 965 * Walk prog table, emit line program and build DIE tree. 966 */ 967 968 func getCompilationDir() string { 969 if dir, err := os.Getwd(); err == nil { 970 return dir 971 } 972 return "/" 973 } 974 975 func writelines(ctxt *Link, syms []*Symbol) ([]*Symbol, []*Symbol) { 976 var dwarfctxt dwarf.Context = dwctxt{ctxt} 977 ls := ctxt.Syms.Lookup(".debug_line", 0) 978 ls.Type = SDWARFSECT 979 ls.R = ls.R[:0] 980 981 syms = append(syms, ls) 982 var funcs []*Symbol 983 984 unitstart := int64(-1) 985 headerstart := int64(-1) 986 headerend := int64(-1) 987 epc := int64(0) 988 var epcs *Symbol 989 var dwinfo *dwarf.DWDie 990 991 lang := dwarf.DW_LANG_Go 992 993 s := ctxt.Textp[0] 994 if ctxt.DynlinkingGo() && Headtype == objabi.Hdarwin { 995 s = ctxt.Textp[1] // skip runtime.text 996 } 997 998 dwinfo = newdie(ctxt, &dwroot, dwarf.DW_ABRV_COMPUNIT, "go", 0) 999 newattr(dwinfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(lang), 0) 1000 newattr(dwinfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, 0, ls) 1001 newattr(dwinfo, dwarf.DW_AT_low_pc, dwarf.DW_CLS_ADDRESS, s.Value, s) 1002 // OS X linker requires compilation dir or absolute path in comp unit name to output debug info. 1003 compDir := getCompilationDir() 1004 newattr(dwinfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir) 1005 producer := "Go cmd/compile " + objabi.Version 1006 newattr(dwinfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer) 1007 1008 // Write .debug_line Line Number Program Header (sec 6.2.4) 1009 // Fields marked with (*) must be changed for 64-bit dwarf 1010 unitLengthOffset := ls.Size 1011 Adduint32(ctxt, ls, 0) // unit_length (*), filled in at end. 1012 unitstart = ls.Size 1013 Adduint16(ctxt, ls, 2) // dwarf version (appendix F) 1014 headerLengthOffset := ls.Size 1015 Adduint32(ctxt, ls, 0) // header_length (*), filled in at end. 1016 headerstart = ls.Size 1017 1018 // cpos == unitstart + 4 + 2 + 4 1019 Adduint8(ctxt, ls, 1) // minimum_instruction_length 1020 Adduint8(ctxt, ls, 1) // default_is_stmt 1021 Adduint8(ctxt, ls, LINE_BASE&0xFF) // line_base 1022 Adduint8(ctxt, ls, LINE_RANGE) // line_range 1023 Adduint8(ctxt, ls, OPCODE_BASE) // opcode_base 1024 Adduint8(ctxt, ls, 0) // standard_opcode_lengths[1] 1025 Adduint8(ctxt, ls, 1) // standard_opcode_lengths[2] 1026 Adduint8(ctxt, ls, 1) // standard_opcode_lengths[3] 1027 Adduint8(ctxt, ls, 1) // standard_opcode_lengths[4] 1028 Adduint8(ctxt, ls, 1) // standard_opcode_lengths[5] 1029 Adduint8(ctxt, ls, 0) // standard_opcode_lengths[6] 1030 Adduint8(ctxt, ls, 0) // standard_opcode_lengths[7] 1031 Adduint8(ctxt, ls, 0) // standard_opcode_lengths[8] 1032 Adduint8(ctxt, ls, 1) // standard_opcode_lengths[9] 1033 Adduint8(ctxt, ls, 0) // include_directories (empty) 1034 1035 for _, f := range ctxt.Filesyms { 1036 Addstring(ls, f.Name) 1037 Adduint8(ctxt, ls, 0) 1038 Adduint8(ctxt, ls, 0) 1039 Adduint8(ctxt, ls, 0) 1040 } 1041 1042 // 4 zeros: the string termination + 3 fields. 1043 Adduint8(ctxt, ls, 0) 1044 // terminate file_names. 1045 headerend = ls.Size 1046 1047 Adduint8(ctxt, ls, 0) // start extended opcode 1048 dwarf.Uleb128put(dwarfctxt, ls, 1+int64(SysArch.PtrSize)) 1049 Adduint8(ctxt, ls, dwarf.DW_LNE_set_address) 1050 1051 pc := s.Value 1052 line := 1 1053 file := 1 1054 Addaddr(ctxt, ls, s) 1055 1056 var pcfile Pciter 1057 var pcline Pciter 1058 for _, s := range ctxt.Textp { 1059 if s.FuncInfo == nil { 1060 continue 1061 } 1062 1063 epc = s.Value + s.Size 1064 epcs = s 1065 1066 dsym := ctxt.Syms.Lookup(dwarf.InfoPrefix+s.Name, int(s.Version)) 1067 dsym.Attr |= AttrNotInSymbolTable | AttrReachable 1068 dsym.Type = SDWARFINFO 1069 for _, r := range dsym.R { 1070 if r.Type == objabi.R_DWARFREF && r.Sym.Size == 0 { 1071 if Buildmode == BuildmodeShared { 1072 // These type symbols may not be present in BuildmodeShared. Skip. 1073 continue 1074 } 1075 n := nameFromDIESym(r.Sym) 1076 defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0)) 1077 } 1078 } 1079 funcs = append(funcs, dsym) 1080 1081 finddebugruntimepath(s) 1082 1083 pciterinit(ctxt, &pcfile, &s.FuncInfo.Pcfile) 1084 pciterinit(ctxt, &pcline, &s.FuncInfo.Pcline) 1085 epc = pc 1086 for pcfile.done == 0 && pcline.done == 0 { 1087 if epc-s.Value >= int64(pcfile.nextpc) { 1088 pciternext(&pcfile) 1089 continue 1090 } 1091 1092 if epc-s.Value >= int64(pcline.nextpc) { 1093 pciternext(&pcline) 1094 continue 1095 } 1096 1097 if int32(file) != pcfile.value { 1098 Adduint8(ctxt, ls, dwarf.DW_LNS_set_file) 1099 dwarf.Uleb128put(dwarfctxt, ls, int64(pcfile.value)) 1100 file = int(pcfile.value) 1101 } 1102 1103 putpclcdelta(ctxt, dwarfctxt, ls, uint64(s.Value+int64(pcline.pc)-pc), int64(pcline.value)-int64(line)) 1104 1105 pc = s.Value + int64(pcline.pc) 1106 line = int(pcline.value) 1107 if pcfile.nextpc < pcline.nextpc { 1108 epc = int64(pcfile.nextpc) 1109 } else { 1110 epc = int64(pcline.nextpc) 1111 } 1112 epc += s.Value 1113 } 1114 } 1115 1116 Adduint8(ctxt, ls, 0) // start extended opcode 1117 dwarf.Uleb128put(dwarfctxt, ls, 1) 1118 Adduint8(ctxt, ls, dwarf.DW_LNE_end_sequence) 1119 1120 newattr(dwinfo, dwarf.DW_AT_high_pc, dwarf.DW_CLS_ADDRESS, epc+1, epcs) 1121 1122 setuint32(ctxt, ls, unitLengthOffset, uint32(ls.Size-unitstart)) 1123 setuint32(ctxt, ls, headerLengthOffset, uint32(headerend-headerstart)) 1124 1125 return syms, funcs 1126 } 1127 1128 /* 1129 * Emit .debug_frame 1130 */ 1131 const ( 1132 dataAlignmentFactor = -4 1133 ) 1134 1135 // appendPCDeltaCFA appends per-PC CFA deltas to b and returns the final slice. 1136 func appendPCDeltaCFA(b []byte, deltapc, cfa int64) []byte { 1137 b = append(b, dwarf.DW_CFA_def_cfa_offset_sf) 1138 b = dwarf.AppendSleb128(b, cfa/dataAlignmentFactor) 1139 1140 switch { 1141 case deltapc < 0x40: 1142 b = append(b, uint8(dwarf.DW_CFA_advance_loc+deltapc)) 1143 case deltapc < 0x100: 1144 b = append(b, dwarf.DW_CFA_advance_loc1) 1145 b = append(b, uint8(deltapc)) 1146 case deltapc < 0x10000: 1147 b = append(b, dwarf.DW_CFA_advance_loc2) 1148 b = Thearch.Append16(b, uint16(deltapc)) 1149 default: 1150 b = append(b, dwarf.DW_CFA_advance_loc4) 1151 b = Thearch.Append32(b, uint32(deltapc)) 1152 } 1153 return b 1154 } 1155 1156 func writeframes(ctxt *Link, syms []*Symbol) []*Symbol { 1157 var dwarfctxt dwarf.Context = dwctxt{ctxt} 1158 fs := ctxt.Syms.Lookup(".debug_frame", 0) 1159 fs.Type = SDWARFSECT 1160 fs.R = fs.R[:0] 1161 syms = append(syms, fs) 1162 1163 // Emit the CIE, Section 6.4.1 1164 cieReserve := uint32(16) 1165 if haslinkregister(ctxt) { 1166 cieReserve = 32 1167 } 1168 Adduint32(ctxt, fs, cieReserve) // initial length, must be multiple of thearch.ptrsize 1169 Adduint32(ctxt, fs, 0xffffffff) // cid. 1170 Adduint8(ctxt, fs, 3) // dwarf version (appendix F) 1171 Adduint8(ctxt, fs, 0) // augmentation "" 1172 dwarf.Uleb128put(dwarfctxt, fs, 1) // code_alignment_factor 1173 dwarf.Sleb128put(dwarfctxt, fs, dataAlignmentFactor) // all CFI offset calculations include multiplication with this factor 1174 dwarf.Uleb128put(dwarfctxt, fs, int64(Thearch.Dwarfreglr)) // return_address_register 1175 1176 Adduint8(ctxt, fs, dwarf.DW_CFA_def_cfa) // Set the current frame address.. 1177 dwarf.Uleb128put(dwarfctxt, fs, int64(Thearch.Dwarfregsp)) // ...to use the value in the platform's SP register (defined in l.go)... 1178 if haslinkregister(ctxt) { 1179 dwarf.Uleb128put(dwarfctxt, fs, int64(0)) // ...plus a 0 offset. 1180 1181 Adduint8(ctxt, fs, dwarf.DW_CFA_same_value) // The platform's link register is unchanged during the prologue. 1182 dwarf.Uleb128put(dwarfctxt, fs, int64(Thearch.Dwarfreglr)) 1183 1184 Adduint8(ctxt, fs, dwarf.DW_CFA_val_offset) // The previous value... 1185 dwarf.Uleb128put(dwarfctxt, fs, int64(Thearch.Dwarfregsp)) // ...of the platform's SP register... 1186 dwarf.Uleb128put(dwarfctxt, fs, int64(0)) // ...is CFA+0. 1187 } else { 1188 dwarf.Uleb128put(dwarfctxt, fs, int64(SysArch.PtrSize)) // ...plus the word size (because the call instruction implicitly adds one word to the frame). 1189 1190 Adduint8(ctxt, fs, dwarf.DW_CFA_offset_extended) // The previous value... 1191 dwarf.Uleb128put(dwarfctxt, fs, int64(Thearch.Dwarfreglr)) // ...of the return address... 1192 dwarf.Uleb128put(dwarfctxt, fs, int64(-SysArch.PtrSize)/dataAlignmentFactor) // ...is saved at [CFA - (PtrSize/4)]. 1193 } 1194 1195 // 4 is to exclude the length field. 1196 pad := int64(cieReserve) + 4 - fs.Size 1197 1198 if pad < 0 { 1199 Exitf("dwarf: cieReserve too small by %d bytes.", -pad) 1200 } 1201 1202 Addbytes(fs, zeros[:pad]) 1203 1204 var deltaBuf []byte 1205 var pcsp Pciter 1206 for _, s := range ctxt.Textp { 1207 if s.FuncInfo == nil { 1208 continue 1209 } 1210 1211 // Emit a FDE, Section 6.4.1. 1212 // First build the section contents into a byte buffer. 1213 deltaBuf = deltaBuf[:0] 1214 for pciterinit(ctxt, &pcsp, &s.FuncInfo.Pcsp); pcsp.done == 0; pciternext(&pcsp) { 1215 nextpc := pcsp.nextpc 1216 1217 // pciterinit goes up to the end of the function, 1218 // but DWARF expects us to stop just before the end. 1219 if int64(nextpc) == s.Size { 1220 nextpc-- 1221 if nextpc < pcsp.pc { 1222 continue 1223 } 1224 } 1225 1226 if haslinkregister(ctxt) { 1227 // TODO(bryanpkc): This is imprecise. In general, the instruction 1228 // that stores the return address to the stack frame is not the 1229 // same one that allocates the frame. 1230 if pcsp.value > 0 { 1231 // The return address is preserved at (CFA-frame_size) 1232 // after a stack frame has been allocated. 1233 deltaBuf = append(deltaBuf, dwarf.DW_CFA_offset_extended_sf) 1234 deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(Thearch.Dwarfreglr)) 1235 deltaBuf = dwarf.AppendSleb128(deltaBuf, -int64(pcsp.value)/dataAlignmentFactor) 1236 } else { 1237 // The return address is restored into the link register 1238 // when a stack frame has been de-allocated. 1239 deltaBuf = append(deltaBuf, dwarf.DW_CFA_same_value) 1240 deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(Thearch.Dwarfreglr)) 1241 } 1242 deltaBuf = appendPCDeltaCFA(deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(pcsp.value)) 1243 } else { 1244 deltaBuf = appendPCDeltaCFA(deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(SysArch.PtrSize)+int64(pcsp.value)) 1245 } 1246 } 1247 pad := int(Rnd(int64(len(deltaBuf)), int64(SysArch.PtrSize))) - len(deltaBuf) 1248 deltaBuf = append(deltaBuf, zeros[:pad]...) 1249 1250 // Emit the FDE header, Section 6.4.1. 1251 // 4 bytes: length, must be multiple of thearch.ptrsize 1252 // 4 bytes: Pointer to the CIE above, at offset 0 1253 // ptrsize: initial location 1254 // ptrsize: address range 1255 Adduint32(ctxt, fs, uint32(4+2*SysArch.PtrSize+len(deltaBuf))) // length (excludes itself) 1256 if Linkmode == LinkExternal { 1257 adddwarfref(ctxt, fs, fs, 4) 1258 } else { 1259 Adduint32(ctxt, fs, 0) // CIE offset 1260 } 1261 Addaddr(ctxt, fs, s) 1262 adduintxx(ctxt, fs, uint64(s.Size), SysArch.PtrSize) // address range 1263 Addbytes(fs, deltaBuf) 1264 } 1265 return syms 1266 } 1267 1268 func writeranges(ctxt *Link, syms []*Symbol) []*Symbol { 1269 empty := true 1270 for _, s := range ctxt.Textp { 1271 rangeSym := ctxt.Syms.Lookup(dwarf.RangePrefix+s.Name, int(s.Version)) 1272 if rangeSym.Size == 0 { 1273 continue 1274 } 1275 rangeSym.Attr |= AttrReachable | AttrNotInSymbolTable 1276 rangeSym.Type = SDWARFRANGE 1277 syms = append(syms, rangeSym) 1278 empty = false 1279 } 1280 if !empty { 1281 // PE does not like empty sections 1282 rangesec := ctxt.Syms.Lookup(".debug_ranges", 0) 1283 rangesec.Type = SDWARFRANGE 1284 rangesec.Attr |= AttrReachable 1285 rangesec.R = rangesec.R[:0] 1286 1287 syms = append(syms, rangesec) 1288 } 1289 return syms 1290 } 1291 1292 /* 1293 * Walk DWarfDebugInfoEntries, and emit .debug_info 1294 */ 1295 const ( 1296 COMPUNITHEADERSIZE = 4 + 2 + 4 + 1 1297 ) 1298 1299 func writeinfo(ctxt *Link, syms []*Symbol, funcs []*Symbol, abbrevsym *Symbol) []*Symbol { 1300 infosec := ctxt.Syms.Lookup(".debug_info", 0) 1301 infosec.R = infosec.R[:0] 1302 infosec.Type = SDWARFINFO 1303 infosec.Attr |= AttrReachable 1304 syms = append(syms, infosec) 1305 1306 arangessec := ctxt.Syms.Lookup(".dwarfaranges", 0) 1307 arangessec.R = arangessec.R[:0] 1308 1309 var dwarfctxt dwarf.Context = dwctxt{ctxt} 1310 1311 for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link { 1312 s := dtolsym(compunit.Sym) 1313 1314 // Write .debug_info Compilation Unit Header (sec 7.5.1) 1315 // Fields marked with (*) must be changed for 64-bit dwarf 1316 // This must match COMPUNITHEADERSIZE above. 1317 Adduint32(ctxt, s, 0) // unit_length (*), will be filled in later. 1318 Adduint16(ctxt, s, 4) // dwarf version (appendix F) 1319 1320 // debug_abbrev_offset (*) 1321 adddwarfref(ctxt, s, abbrevsym, 4) 1322 1323 Adduint8(ctxt, s, uint8(SysArch.PtrSize)) // address_size 1324 1325 dwarf.Uleb128put(dwarfctxt, s, int64(compunit.Abbrev)) 1326 dwarf.PutAttrs(dwarfctxt, s, compunit.Abbrev, compunit.Attr) 1327 1328 cu := []*Symbol{s} 1329 if funcs != nil { 1330 cu = append(cu, funcs...) 1331 funcs = nil 1332 } 1333 cu = putdies(ctxt, dwarfctxt, cu, compunit.Child) 1334 var cusize int64 1335 for _, child := range cu { 1336 cusize += child.Size 1337 } 1338 cusize -= 4 // exclude the length field. 1339 setuint32(ctxt, s, 0, uint32(cusize)) 1340 newattr(compunit, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, cusize, 0) 1341 syms = append(syms, cu...) 1342 } 1343 return syms 1344 } 1345 1346 /* 1347 * Emit .debug_pubnames/_types. _info must have been written before, 1348 * because we need die->offs and infoo/infosize; 1349 */ 1350 func ispubname(die *dwarf.DWDie) bool { 1351 switch die.Abbrev { 1352 case dwarf.DW_ABRV_FUNCTION, dwarf.DW_ABRV_VARIABLE: 1353 a := getattr(die, dwarf.DW_AT_external) 1354 return a != nil && a.Value != 0 1355 } 1356 1357 return false 1358 } 1359 1360 func ispubtype(die *dwarf.DWDie) bool { 1361 return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE 1362 } 1363 1364 func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*Symbol) []*Symbol { 1365 s := ctxt.Syms.Lookup(sname, 0) 1366 s.Type = SDWARFSECT 1367 syms = append(syms, s) 1368 1369 for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link { 1370 sectionstart := s.Size 1371 culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4 1372 1373 // Write .debug_pubnames/types Header (sec 6.1.1) 1374 Adduint32(ctxt, s, 0) // unit_length (*), will be filled in later. 1375 Adduint16(ctxt, s, 2) // dwarf version (appendix F) 1376 adddwarfref(ctxt, s, dtolsym(compunit.Sym), 4) // debug_info_offset (of the Comp unit Header) 1377 Adduint32(ctxt, s, culength) // debug_info_length 1378 1379 for die := compunit.Child; die != nil; die = die.Link { 1380 if !ispub(die) { 1381 continue 1382 } 1383 dwa := getattr(die, dwarf.DW_AT_name) 1384 name := dwa.Data.(string) 1385 if die.Sym == nil { 1386 fmt.Println("Missing sym for ", name) 1387 } 1388 adddwarfref(ctxt, s, dtolsym(die.Sym), 4) 1389 Addstring(s, name) 1390 } 1391 1392 Adduint32(ctxt, s, 0) 1393 1394 setuint32(ctxt, s, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field. 1395 } 1396 1397 return syms 1398 } 1399 1400 /* 1401 * emit .debug_aranges. _info must have been written before, 1402 * because we need die->offs of dwarf.DW_globals. 1403 */ 1404 func writearanges(ctxt *Link, syms []*Symbol) []*Symbol { 1405 s := ctxt.Syms.Lookup(".debug_aranges", 0) 1406 s.Type = SDWARFSECT 1407 // The first tuple is aligned to a multiple of the size of a single tuple 1408 // (twice the size of an address) 1409 headersize := int(Rnd(4+2+4+1+1, int64(SysArch.PtrSize*2))) // don't count unit_length field itself 1410 1411 for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link { 1412 b := getattr(compunit, dwarf.DW_AT_low_pc) 1413 if b == nil { 1414 continue 1415 } 1416 e := getattr(compunit, dwarf.DW_AT_high_pc) 1417 if e == nil { 1418 continue 1419 } 1420 1421 // Write .debug_aranges Header + entry (sec 6.1.2) 1422 unitlength := uint32(headersize) + 4*uint32(SysArch.PtrSize) - 4 1423 Adduint32(ctxt, s, unitlength) // unit_length (*) 1424 Adduint16(ctxt, s, 2) // dwarf version (appendix F) 1425 1426 adddwarfref(ctxt, s, dtolsym(compunit.Sym), 4) 1427 1428 Adduint8(ctxt, s, uint8(SysArch.PtrSize)) // address_size 1429 Adduint8(ctxt, s, 0) // segment_size 1430 padding := headersize - (4 + 2 + 4 + 1 + 1) 1431 for i := 0; i < padding; i++ { 1432 Adduint8(ctxt, s, 0) 1433 } 1434 1435 Addaddrplus(ctxt, s, b.Data.(*Symbol), b.Value-(b.Data.(*Symbol)).Value) 1436 adduintxx(ctxt, s, uint64(e.Value-b.Value), SysArch.PtrSize) 1437 adduintxx(ctxt, s, 0, SysArch.PtrSize) 1438 adduintxx(ctxt, s, 0, SysArch.PtrSize) 1439 } 1440 if s.Size > 0 { 1441 syms = append(syms, s) 1442 } 1443 return syms 1444 } 1445 1446 func writegdbscript(ctxt *Link, syms []*Symbol) []*Symbol { 1447 if Linkmode == LinkExternal && Headtype == objabi.Hwindows && Buildmode == BuildmodeCArchive { 1448 // gcc on Windows places .debug_gdb_scripts in the wrong location, which 1449 // causes the program not to run. See https://golang.org/issue/20183 1450 // Non c-archives can avoid this issue via a linker script 1451 // (see fix near writeGDBLinkerScript). 1452 // c-archive users would need to specify the linker script manually. 1453 // For UX it's better not to deal with this. 1454 return syms 1455 } 1456 1457 if gdbscript != "" { 1458 s := ctxt.Syms.Lookup(".debug_gdb_scripts", 0) 1459 s.Type = SDWARFSECT 1460 syms = append(syms, s) 1461 Adduint8(ctxt, s, 1) // magic 1 byte? 1462 Addstring(s, gdbscript) 1463 } 1464 1465 return syms 1466 } 1467 1468 var prototypedies map[string]*dwarf.DWDie 1469 1470 /* 1471 * This is the main entry point for generating dwarf. After emitting 1472 * the mandatory debug_abbrev section, it calls writelines() to set up 1473 * the per-compilation unit part of the DIE tree, while simultaneously 1474 * emitting the debug_line section. When the final tree contains 1475 * forward references, it will write the debug_info section in 2 1476 * passes. 1477 * 1478 */ 1479 func dwarfgeneratedebugsyms(ctxt *Link) { 1480 if *FlagW { // disable dwarf 1481 return 1482 } 1483 if *FlagS && Headtype != objabi.Hdarwin { 1484 return 1485 } 1486 if Headtype == objabi.Hplan9 { 1487 return 1488 } 1489 1490 if Linkmode == LinkExternal { 1491 switch { 1492 case Iself: 1493 case Headtype == objabi.Hdarwin: 1494 case Headtype == objabi.Hwindows: 1495 default: 1496 return 1497 } 1498 } 1499 1500 if ctxt.Debugvlog != 0 { 1501 ctxt.Logf("%5.2f dwarf\n", Cputime()) 1502 } 1503 1504 // Forctxt.Diagnostic messages. 1505 newattr(&dwtypes, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len("dwtypes")), "dwtypes") 1506 1507 // Some types that must exist to define other ones. 1508 newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "<unspecified>", 0) 1509 1510 newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "void", 0) 1511 newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer", 0) 1512 1513 die := newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, "uintptr", 0) // needed for array size 1514 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0) 1515 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(SysArch.PtrSize), 0) 1516 newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, objabi.KindUintptr, 0) 1517 1518 // Prototypes needed for type synthesis. 1519 prototypedies = map[string]*dwarf.DWDie{ 1520 "type.runtime.stringStructDWARF": nil, 1521 "type.runtime.slice": nil, 1522 "type.runtime.hmap": nil, 1523 "type.runtime.bmap": nil, 1524 "type.runtime.sudog": nil, 1525 "type.runtime.waitq": nil, 1526 "type.runtime.hchan": nil, 1527 } 1528 1529 // Needed by the prettyprinter code for interface inspection. 1530 for _, typ := range []string{ 1531 "type.runtime._type", 1532 "type.runtime.arraytype", 1533 "type.runtime.chantype", 1534 "type.runtime.functype", 1535 "type.runtime.maptype", 1536 "type.runtime.ptrtype", 1537 "type.runtime.slicetype", 1538 "type.runtime.structtype", 1539 "type.runtime.interfacetype", 1540 "type.runtime.itab", 1541 "type.runtime.imethod"} { 1542 defgotype(ctxt, lookupOrDiag(ctxt, typ)) 1543 } 1544 1545 genasmsym(ctxt, defdwsymb) 1546 1547 abbrev := writeabbrev(ctxt) 1548 syms := []*Symbol{abbrev} 1549 syms, funcs := writelines(ctxt, syms) 1550 syms = writeframes(ctxt, syms) 1551 1552 synthesizestringtypes(ctxt, dwtypes.Child) 1553 synthesizeslicetypes(ctxt, dwtypes.Child) 1554 synthesizemaptypes(ctxt, dwtypes.Child) 1555 synthesizechantypes(ctxt, dwtypes.Child) 1556 1557 reversetree(&dwroot.Child) 1558 reversetree(&dwtypes.Child) 1559 reversetree(&dwglobals.Child) 1560 1561 movetomodule(&dwtypes) 1562 movetomodule(&dwglobals) 1563 1564 // Need to reorder symbols so SDWARFINFO is after all SDWARFSECT 1565 // (but we need to generate dies before writepub) 1566 infosyms := writeinfo(ctxt, nil, funcs, abbrev) 1567 1568 syms = writepub(ctxt, ".debug_pubnames", ispubname, syms) 1569 syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms) 1570 syms = writearanges(ctxt, syms) 1571 syms = writegdbscript(ctxt, syms) 1572 syms = append(syms, infosyms...) 1573 syms = collectlocs(ctxt, syms, funcs) 1574 syms = writeranges(ctxt, syms) 1575 dwarfp = syms 1576 } 1577 1578 func collectlocs(ctxt *Link, syms []*Symbol, funcs []*Symbol) []*Symbol { 1579 empty := true 1580 for _, fn := range funcs { 1581 for _, reloc := range fn.R { 1582 if reloc.Type == objabi.R_DWARFREF && strings.HasPrefix(reloc.Sym.Name, dwarf.LocPrefix) { 1583 reloc.Sym.Attr |= AttrReachable | AttrNotInSymbolTable 1584 syms = append(syms, reloc.Sym) 1585 empty = false 1586 // One location list entry per function, but many relocations to it. Don't duplicate. 1587 break 1588 } 1589 } 1590 } 1591 // Don't emit .debug_loc if it's empty -- it makes the ARM linker mad. 1592 if !empty { 1593 locsym := ctxt.Syms.Lookup(".debug_loc", 0) 1594 locsym.R = locsym.R[:0] 1595 locsym.Type = SDWARFLOC 1596 locsym.Attr |= AttrReachable 1597 syms = append(syms, locsym) 1598 } 1599 return syms 1600 } 1601 1602 /* 1603 * Elf. 1604 */ 1605 func dwarfaddshstrings(ctxt *Link, shstrtab *Symbol) { 1606 if *FlagW { // disable dwarf 1607 return 1608 } 1609 1610 Addstring(shstrtab, ".debug_abbrev") 1611 Addstring(shstrtab, ".debug_aranges") 1612 Addstring(shstrtab, ".debug_frame") 1613 Addstring(shstrtab, ".debug_info") 1614 Addstring(shstrtab, ".debug_loc") 1615 Addstring(shstrtab, ".debug_line") 1616 Addstring(shstrtab, ".debug_pubnames") 1617 Addstring(shstrtab, ".debug_pubtypes") 1618 Addstring(shstrtab, ".debug_gdb_scripts") 1619 Addstring(shstrtab, ".debug_ranges") 1620 if Linkmode == LinkExternal { 1621 Addstring(shstrtab, elfRelType+".debug_info") 1622 Addstring(shstrtab, elfRelType+".debug_loc") 1623 Addstring(shstrtab, elfRelType+".debug_aranges") 1624 Addstring(shstrtab, elfRelType+".debug_line") 1625 Addstring(shstrtab, elfRelType+".debug_frame") 1626 Addstring(shstrtab, elfRelType+".debug_pubnames") 1627 Addstring(shstrtab, elfRelType+".debug_pubtypes") 1628 Addstring(shstrtab, elfRelType+".debug_ranges") 1629 } 1630 } 1631 1632 // Add section symbols for DWARF debug info. This is called before 1633 // dwarfaddelfheaders. 1634 func dwarfaddelfsectionsyms(ctxt *Link) { 1635 if *FlagW { // disable dwarf 1636 return 1637 } 1638 if Linkmode != LinkExternal { 1639 return 1640 } 1641 sym := ctxt.Syms.Lookup(".debug_info", 0) 1642 putelfsectionsym(sym, sym.Sect.Elfsect.shnum) 1643 sym = ctxt.Syms.Lookup(".debug_abbrev", 0) 1644 putelfsectionsym(sym, sym.Sect.Elfsect.shnum) 1645 sym = ctxt.Syms.Lookup(".debug_line", 0) 1646 putelfsectionsym(sym, sym.Sect.Elfsect.shnum) 1647 sym = ctxt.Syms.Lookup(".debug_frame", 0) 1648 putelfsectionsym(sym, sym.Sect.Elfsect.shnum) 1649 sym = ctxt.Syms.Lookup(".debug_loc", 0) 1650 if sym.Sect != nil { 1651 putelfsectionsym(sym, sym.Sect.Elfsect.shnum) 1652 } 1653 sym = ctxt.Syms.Lookup(".debug_ranges", 0) 1654 if sym.Sect != nil { 1655 putelfsectionsym(sym, sym.Sect.Elfsect.shnum) 1656 } 1657 }