github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/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 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/obj" 19 "cmd/internal/objabi" 20 "cmd/internal/sys" 21 "cmd/link/internal/sym" 22 "fmt" 23 "log" 24 "sort" 25 "strings" 26 ) 27 28 type dwctxt struct { 29 linkctxt *Link 30 } 31 32 func (c dwctxt) PtrSize() int { 33 return c.linkctxt.Arch.PtrSize 34 } 35 func (c dwctxt) AddInt(s dwarf.Sym, size int, i int64) { 36 ls := s.(*sym.Symbol) 37 ls.AddUintXX(c.linkctxt.Arch, uint64(i), size) 38 } 39 func (c dwctxt) AddBytes(s dwarf.Sym, b []byte) { 40 ls := s.(*sym.Symbol) 41 ls.AddBytes(b) 42 } 43 func (c dwctxt) AddString(s dwarf.Sym, v string) { 44 Addstring(s.(*sym.Symbol), v) 45 } 46 47 func (c dwctxt) AddAddress(s dwarf.Sym, data interface{}, value int64) { 48 if value != 0 { 49 value -= (data.(*sym.Symbol)).Value 50 } 51 s.(*sym.Symbol).AddAddrPlus(c.linkctxt.Arch, data.(*sym.Symbol), value) 52 } 53 54 func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) { 55 ls := s.(*sym.Symbol) 56 switch size { 57 default: 58 Errorf(ls, "invalid size %d in adddwarfref\n", size) 59 fallthrough 60 case c.linkctxt.Arch.PtrSize: 61 ls.AddAddr(c.linkctxt.Arch, t.(*sym.Symbol)) 62 case 4: 63 ls.AddAddrPlus4(t.(*sym.Symbol), 0) 64 } 65 r := &ls.R[len(ls.R)-1] 66 r.Type = objabi.R_ADDROFF 67 r.Add = ofs 68 } 69 70 func (c dwctxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) { 71 size := 4 72 if isDwarf64(c.linkctxt) { 73 size = 8 74 } 75 76 c.AddSectionOffset(s, size, t, ofs) 77 ls := s.(*sym.Symbol) 78 ls.R[len(ls.R)-1].Type = objabi.R_DWARFSECREF 79 } 80 81 func (c dwctxt) Logf(format string, args ...interface{}) { 82 c.linkctxt.Logf(format, args...) 83 } 84 85 // At the moment these interfaces are only used in the compiler. 86 87 func (c dwctxt) AddFileRef(s dwarf.Sym, f interface{}) { 88 panic("should be used only in the compiler") 89 } 90 91 func (c dwctxt) CurrentOffset(s dwarf.Sym) int64 { 92 panic("should be used only in the compiler") 93 } 94 95 func (c dwctxt) RecordDclReference(s dwarf.Sym, t dwarf.Sym, dclIdx int, inlIndex int) { 96 panic("should be used only in the compiler") 97 } 98 99 func (c dwctxt) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []int32) { 100 panic("should be used only in the compiler") 101 } 102 103 func isDwarf64(ctxt *Link) bool { 104 return ctxt.HeadType == objabi.Haix 105 } 106 107 var gdbscript string 108 109 var dwarfp []*sym.Symbol 110 111 func writeabbrev(ctxt *Link) *sym.Symbol { 112 s := ctxt.Syms.Lookup(".debug_abbrev", 0) 113 s.Type = sym.SDWARFSECT 114 s.AddBytes(dwarf.GetAbbrev()) 115 return s 116 } 117 118 var dwtypes dwarf.DWDie 119 120 func newattr(die *dwarf.DWDie, attr uint16, cls int, value int64, data interface{}) *dwarf.DWAttr { 121 a := new(dwarf.DWAttr) 122 a.Link = die.Attr 123 die.Attr = a 124 a.Atr = attr 125 a.Cls = uint8(cls) 126 a.Value = value 127 a.Data = data 128 return a 129 } 130 131 // Each DIE (except the root ones) has at least 1 attribute: its 132 // name. getattr moves the desired one to the front so 133 // frequently searched ones are found faster. 134 func getattr(die *dwarf.DWDie, attr uint16) *dwarf.DWAttr { 135 if die.Attr.Atr == attr { 136 return die.Attr 137 } 138 139 a := die.Attr 140 b := a.Link 141 for b != nil { 142 if b.Atr == attr { 143 a.Link = b.Link 144 b.Link = die.Attr 145 die.Attr = b 146 return b 147 } 148 149 a = b 150 b = b.Link 151 } 152 153 return nil 154 } 155 156 // Every DIE manufactured by the linker has at least an AT_name 157 // attribute (but it will only be written out if it is listed in the abbrev). 158 // The compiler does create nameless DWARF DIEs (ex: concrete subprogram 159 // instance). 160 func newdie(ctxt *Link, parent *dwarf.DWDie, abbrev int, name string, version int) *dwarf.DWDie { 161 die := new(dwarf.DWDie) 162 die.Abbrev = abbrev 163 die.Link = parent.Child 164 parent.Child = die 165 166 newattr(die, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len(name)), name) 167 168 if name != "" && (abbrev <= dwarf.DW_ABRV_VARIABLE || abbrev >= dwarf.DW_ABRV_NULLTYPE) { 169 if abbrev != dwarf.DW_ABRV_VARIABLE || version == 0 { 170 if abbrev == dwarf.DW_ABRV_COMPUNIT { 171 // Avoid collisions with "real" symbol names. 172 name = ".pkg." + name 173 } 174 s := ctxt.Syms.Lookup(dwarf.InfoPrefix+name, version) 175 s.Attr |= sym.AttrNotInSymbolTable 176 s.Type = sym.SDWARFINFO 177 die.Sym = s 178 } 179 } 180 181 return die 182 } 183 184 func walktypedef(die *dwarf.DWDie) *dwarf.DWDie { 185 if die == nil { 186 return nil 187 } 188 // Resolve typedef if present. 189 if die.Abbrev == dwarf.DW_ABRV_TYPEDECL { 190 for attr := die.Attr; attr != nil; attr = attr.Link { 191 if attr.Atr == dwarf.DW_AT_type && attr.Cls == dwarf.DW_CLS_REFERENCE && attr.Data != nil { 192 return attr.Data.(*dwarf.DWDie) 193 } 194 } 195 } 196 197 return die 198 } 199 200 func walksymtypedef(ctxt *Link, s *sym.Symbol) *sym.Symbol { 201 if t := ctxt.Syms.ROLookup(s.Name+"..def", int(s.Version)); t != nil { 202 return t 203 } 204 return s 205 } 206 207 // Find child by AT_name using hashtable if available or linear scan 208 // if not. 209 func findchild(die *dwarf.DWDie, name string) *dwarf.DWDie { 210 var prev *dwarf.DWDie 211 for ; die != prev; prev, die = die, walktypedef(die) { 212 for a := die.Child; a != nil; a = a.Link { 213 if name == getattr(a, dwarf.DW_AT_name).Data { 214 return a 215 } 216 } 217 continue 218 } 219 return nil 220 } 221 222 // Used to avoid string allocation when looking up dwarf symbols 223 var prefixBuf = []byte(dwarf.InfoPrefix) 224 225 func find(ctxt *Link, name string) *sym.Symbol { 226 n := append(prefixBuf, name...) 227 // The string allocation below is optimized away because it is only used in a map lookup. 228 s := ctxt.Syms.ROLookup(string(n), 0) 229 prefixBuf = n[:len(dwarf.InfoPrefix)] 230 if s != nil && s.Type == sym.SDWARFINFO { 231 return s 232 } 233 return nil 234 } 235 236 func mustFind(ctxt *Link, name string) *sym.Symbol { 237 r := find(ctxt, name) 238 if r == nil { 239 Exitf("dwarf find: cannot find %s", name) 240 } 241 return r 242 } 243 244 func adddwarfref(ctxt *Link, s *sym.Symbol, t *sym.Symbol, size int) int64 { 245 var result int64 246 switch size { 247 default: 248 Errorf(s, "invalid size %d in adddwarfref\n", size) 249 fallthrough 250 case ctxt.Arch.PtrSize: 251 result = s.AddAddr(ctxt.Arch, t) 252 case 4: 253 result = s.AddAddrPlus4(t, 0) 254 } 255 r := &s.R[len(s.R)-1] 256 r.Type = objabi.R_DWARFSECREF 257 return result 258 } 259 260 func newrefattr(die *dwarf.DWDie, attr uint16, ref *sym.Symbol) *dwarf.DWAttr { 261 if ref == nil { 262 return nil 263 } 264 return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, ref) 265 } 266 267 func putdies(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.DWDie) []*sym.Symbol { 268 for ; die != nil; die = die.Link { 269 syms = putdie(linkctxt, ctxt, syms, die) 270 } 271 syms[len(syms)-1].AddUint8(0) 272 273 return syms 274 } 275 276 func dtolsym(s dwarf.Sym) *sym.Symbol { 277 if s == nil { 278 return nil 279 } 280 return s.(*sym.Symbol) 281 } 282 283 func putdie(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.DWDie) []*sym.Symbol { 284 s := dtolsym(die.Sym) 285 if s == nil { 286 s = syms[len(syms)-1] 287 } else { 288 if s.Attr.OnList() { 289 log.Fatalf("symbol %s listed multiple times", s.Name) 290 } 291 s.Attr |= sym.AttrOnList 292 syms = append(syms, s) 293 } 294 dwarf.Uleb128put(ctxt, s, int64(die.Abbrev)) 295 dwarf.PutAttrs(ctxt, s, die.Abbrev, die.Attr) 296 if dwarf.HasChildren(die) { 297 return putdies(linkctxt, ctxt, syms, die.Child) 298 } 299 return syms 300 } 301 302 func reverselist(list **dwarf.DWDie) { 303 curr := *list 304 var prev *dwarf.DWDie 305 for curr != nil { 306 next := curr.Link 307 curr.Link = prev 308 prev = curr 309 curr = next 310 } 311 312 *list = prev 313 } 314 315 func reversetree(list **dwarf.DWDie) { 316 reverselist(list) 317 for die := *list; die != nil; die = die.Link { 318 if dwarf.HasChildren(die) { 319 reversetree(&die.Child) 320 } 321 } 322 } 323 324 func newmemberoffsetattr(die *dwarf.DWDie, offs int32) { 325 newattr(die, dwarf.DW_AT_data_member_location, dwarf.DW_CLS_CONSTANT, int64(offs), nil) 326 } 327 328 // GDB doesn't like FORM_addr for AT_location, so emit a 329 // location expression that evals to a const. 330 func newabslocexprattr(die *dwarf.DWDie, addr int64, sym *sym.Symbol) { 331 newattr(die, dwarf.DW_AT_location, dwarf.DW_CLS_ADDRESS, addr, sym) 332 // below 333 } 334 335 // Lookup predefined types 336 func lookupOrDiag(ctxt *Link, n string) *sym.Symbol { 337 s := ctxt.Syms.ROLookup(n, 0) 338 if s == nil || s.Size == 0 { 339 Exitf("dwarf: missing type: %s", n) 340 } 341 342 return s 343 } 344 345 func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) *dwarf.DWDie { 346 // Only emit typedefs for real names. 347 if strings.HasPrefix(name, "map[") { 348 return nil 349 } 350 if strings.HasPrefix(name, "struct {") { 351 return nil 352 } 353 if strings.HasPrefix(name, "chan ") { 354 return nil 355 } 356 if name[0] == '[' || name[0] == '*' { 357 return nil 358 } 359 if def == nil { 360 Errorf(nil, "dwarf: bad def in dotypedef") 361 } 362 363 s := ctxt.Syms.Lookup(dtolsym(def.Sym).Name+"..def", 0) 364 s.Attr |= sym.AttrNotInSymbolTable 365 s.Type = sym.SDWARFINFO 366 def.Sym = s 367 368 // The typedef entry must be created after the def, 369 // so that future lookups will find the typedef instead 370 // of the real definition. This hooks the typedef into any 371 // circular definition loops, so that gdb can understand them. 372 die := newdie(ctxt, parent, dwarf.DW_ABRV_TYPEDECL, name, 0) 373 374 newrefattr(die, dwarf.DW_AT_type, s) 375 376 return die 377 } 378 379 // Define gotype, for composite ones recurse into constituents. 380 func defgotype(ctxt *Link, gotype *sym.Symbol) *sym.Symbol { 381 if gotype == nil { 382 return mustFind(ctxt, "<unspecified>") 383 } 384 385 if !strings.HasPrefix(gotype.Name, "type.") { 386 Errorf(gotype, "dwarf: type name doesn't start with \"type.\"") 387 return mustFind(ctxt, "<unspecified>") 388 } 389 390 name := gotype.Name[5:] // could also decode from Type.string 391 392 sdie := find(ctxt, name) 393 394 if sdie != nil { 395 return sdie 396 } 397 398 return newtype(ctxt, gotype).Sym.(*sym.Symbol) 399 } 400 401 func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie { 402 name := gotype.Name[5:] // could also decode from Type.string 403 kind := decodetypeKind(ctxt.Arch, gotype) 404 bytesize := decodetypeSize(ctxt.Arch, gotype) 405 406 var die, typedefdie *dwarf.DWDie 407 switch kind { 408 case objabi.KindBool: 409 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) 410 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_boolean, 0) 411 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 412 413 case objabi.KindInt, 414 objabi.KindInt8, 415 objabi.KindInt16, 416 objabi.KindInt32, 417 objabi.KindInt64: 418 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) 419 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_signed, 0) 420 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 421 422 case objabi.KindUint, 423 objabi.KindUint8, 424 objabi.KindUint16, 425 objabi.KindUint32, 426 objabi.KindUint64, 427 objabi.KindUintptr: 428 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) 429 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0) 430 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 431 432 case objabi.KindFloat32, 433 objabi.KindFloat64: 434 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) 435 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_float, 0) 436 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 437 438 case objabi.KindComplex64, 439 objabi.KindComplex128: 440 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) 441 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_complex_float, 0) 442 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 443 444 case objabi.KindArray: 445 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_ARRAYTYPE, name, 0) 446 typedefdie = dotypedef(ctxt, &dwtypes, name, die) 447 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 448 s := decodetypeArrayElem(ctxt.Arch, gotype) 449 newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s)) 450 fld := newdie(ctxt, die, dwarf.DW_ABRV_ARRAYRANGE, "range", 0) 451 452 // use actual length not upper bound; correct for 0-length arrays. 453 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, decodetypeArrayLen(ctxt.Arch, gotype), 0) 454 455 newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr")) 456 457 case objabi.KindChan: 458 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_CHANTYPE, name, 0) 459 s := decodetypeChanElem(ctxt.Arch, gotype) 460 newrefattr(die, dwarf.DW_AT_go_elem, defgotype(ctxt, s)) 461 // Save elem type for synthesizechantypes. We could synthesize here 462 // but that would change the order of DIEs we output. 463 newrefattr(die, dwarf.DW_AT_type, s) 464 465 case objabi.KindFunc: 466 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_FUNCTYPE, name, 0) 467 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 468 typedefdie = dotypedef(ctxt, &dwtypes, name, die) 469 nfields := decodetypeFuncInCount(ctxt.Arch, gotype) 470 for i := 0; i < nfields; i++ { 471 s := decodetypeFuncInType(ctxt.Arch, gotype, i) 472 fld := newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0) 473 newrefattr(fld, dwarf.DW_AT_type, defgotype(ctxt, s)) 474 } 475 476 if decodetypeFuncDotdotdot(ctxt.Arch, gotype) { 477 newdie(ctxt, die, dwarf.DW_ABRV_DOTDOTDOT, "...", 0) 478 } 479 nfields = decodetypeFuncOutCount(ctxt.Arch, gotype) 480 for i := 0; i < nfields; i++ { 481 s := decodetypeFuncOutType(ctxt.Arch, gotype, i) 482 fld := newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0) 483 newrefattr(fld, dwarf.DW_AT_type, defptrto(ctxt, defgotype(ctxt, s))) 484 } 485 486 case objabi.KindInterface: 487 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_IFACETYPE, name, 0) 488 typedefdie = dotypedef(ctxt, &dwtypes, name, die) 489 nfields := int(decodetypeIfaceMethodCount(ctxt.Arch, gotype)) 490 var s *sym.Symbol 491 if nfields == 0 { 492 s = lookupOrDiag(ctxt, "type.runtime.eface") 493 } else { 494 s = lookupOrDiag(ctxt, "type.runtime.iface") 495 } 496 newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s)) 497 498 case objabi.KindMap: 499 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_MAPTYPE, name, 0) 500 s := decodetypeMapKey(ctxt.Arch, gotype) 501 newrefattr(die, dwarf.DW_AT_go_key, defgotype(ctxt, s)) 502 s = decodetypeMapValue(ctxt.Arch, gotype) 503 newrefattr(die, dwarf.DW_AT_go_elem, defgotype(ctxt, s)) 504 // Save gotype for use in synthesizemaptypes. We could synthesize here, 505 // but that would change the order of the DIEs. 506 newrefattr(die, dwarf.DW_AT_type, gotype) 507 508 case objabi.KindPtr: 509 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_PTRTYPE, name, 0) 510 typedefdie = dotypedef(ctxt, &dwtypes, name, die) 511 s := decodetypePtrElem(ctxt.Arch, gotype) 512 newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s)) 513 514 case objabi.KindSlice: 515 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_SLICETYPE, name, 0) 516 typedefdie = dotypedef(ctxt, &dwtypes, name, die) 517 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 518 s := decodetypeArrayElem(ctxt.Arch, gotype) 519 elem := defgotype(ctxt, s) 520 newrefattr(die, dwarf.DW_AT_go_elem, elem) 521 522 case objabi.KindString: 523 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRINGTYPE, name, 0) 524 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 525 526 case objabi.KindStruct: 527 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRUCTTYPE, name, 0) 528 typedefdie = dotypedef(ctxt, &dwtypes, name, die) 529 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) 530 nfields := decodetypeStructFieldCount(ctxt.Arch, gotype) 531 for i := 0; i < nfields; i++ { 532 f := decodetypeStructFieldName(ctxt.Arch, gotype, i) 533 s := decodetypeStructFieldType(ctxt.Arch, gotype, i) 534 if f == "" { 535 f = s.Name[5:] // skip "type." 536 } 537 fld := newdie(ctxt, die, dwarf.DW_ABRV_STRUCTFIELD, f, 0) 538 newrefattr(fld, dwarf.DW_AT_type, defgotype(ctxt, s)) 539 offsetAnon := decodetypeStructFieldOffsAnon(ctxt.Arch, gotype, i) 540 newmemberoffsetattr(fld, int32(offsetAnon>>1)) 541 if offsetAnon&1 != 0 { // is embedded field 542 newattr(fld, dwarf.DW_AT_go_embedded_field, dwarf.DW_CLS_FLAG, 1, 0) 543 } 544 } 545 546 case objabi.KindUnsafePointer: 547 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, name, 0) 548 549 default: 550 Errorf(gotype, "dwarf: definition of unknown kind %d", kind) 551 die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_TYPEDECL, name, 0) 552 newrefattr(die, dwarf.DW_AT_type, mustFind(ctxt, "<unspecified>")) 553 } 554 555 newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(kind), 0) 556 if gotype.Attr.Reachable() { 557 newattr(die, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, gotype) 558 } 559 560 if _, ok := prototypedies[gotype.Name]; ok { 561 prototypedies[gotype.Name] = die 562 } 563 564 if typedefdie != nil { 565 return typedefdie 566 } 567 return die 568 } 569 570 func nameFromDIESym(dwtype *sym.Symbol) string { 571 return strings.TrimSuffix(dwtype.Name[len(dwarf.InfoPrefix):], "..def") 572 } 573 574 // Find or construct *T given T. 575 func defptrto(ctxt *Link, dwtype *sym.Symbol) *sym.Symbol { 576 ptrname := "*" + nameFromDIESym(dwtype) 577 if die := find(ctxt, ptrname); die != nil { 578 return die 579 } 580 581 pdie := newdie(ctxt, &dwtypes, dwarf.DW_ABRV_PTRTYPE, ptrname, 0) 582 newrefattr(pdie, dwarf.DW_AT_type, dwtype) 583 584 // The DWARF info synthesizes pointer types that don't exist at the 585 // language level, like *hash<...> and *bucket<...>, and the data 586 // pointers of slices. Link to the ones we can find. 587 gotype := ctxt.Syms.ROLookup("type."+ptrname, 0) 588 if gotype != nil && gotype.Attr.Reachable() { 589 newattr(pdie, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, gotype) 590 } 591 return dtolsym(pdie.Sym) 592 } 593 594 // Copies src's children into dst. Copies attributes by value. 595 // DWAttr.data is copied as pointer only. If except is one of 596 // the top-level children, it will not be copied. 597 func copychildrenexcept(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie, except *dwarf.DWDie) { 598 for src = src.Child; src != nil; src = src.Link { 599 if src == except { 600 continue 601 } 602 c := newdie(ctxt, dst, src.Abbrev, getattr(src, dwarf.DW_AT_name).Data.(string), 0) 603 for a := src.Attr; a != nil; a = a.Link { 604 newattr(c, a.Atr, int(a.Cls), a.Value, a.Data) 605 } 606 copychildrenexcept(ctxt, c, src, nil) 607 } 608 609 reverselist(&dst.Child) 610 } 611 612 func copychildren(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWDie) { 613 copychildrenexcept(ctxt, dst, src, nil) 614 } 615 616 // Search children (assumed to have TAG_member) for the one named 617 // field and set its AT_type to dwtype 618 func substitutetype(structdie *dwarf.DWDie, field string, dwtype *sym.Symbol) { 619 child := findchild(structdie, field) 620 if child == nil { 621 Exitf("dwarf substitutetype: %s does not have member %s", 622 getattr(structdie, dwarf.DW_AT_name).Data, field) 623 return 624 } 625 626 a := getattr(child, dwarf.DW_AT_type) 627 if a != nil { 628 a.Data = dwtype 629 } else { 630 newrefattr(child, dwarf.DW_AT_type, dwtype) 631 } 632 } 633 634 func findprotodie(ctxt *Link, name string) *dwarf.DWDie { 635 die, ok := prototypedies[name] 636 if ok && die == nil { 637 defgotype(ctxt, lookupOrDiag(ctxt, name)) 638 die = prototypedies[name] 639 } 640 return die 641 } 642 643 func synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) { 644 prototype := walktypedef(findprotodie(ctxt, "type.runtime.stringStructDWARF")) 645 if prototype == nil { 646 return 647 } 648 649 for ; die != nil; die = die.Link { 650 if die.Abbrev != dwarf.DW_ABRV_STRINGTYPE { 651 continue 652 } 653 copychildren(ctxt, die, prototype) 654 } 655 } 656 657 func synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) { 658 prototype := walktypedef(findprotodie(ctxt, "type.runtime.slice")) 659 if prototype == nil { 660 return 661 } 662 663 for ; die != nil; die = die.Link { 664 if die.Abbrev != dwarf.DW_ABRV_SLICETYPE { 665 continue 666 } 667 copychildren(ctxt, die, prototype) 668 elem := getattr(die, dwarf.DW_AT_go_elem).Data.(*sym.Symbol) 669 substitutetype(die, "array", defptrto(ctxt, elem)) 670 } 671 } 672 673 func mkinternaltypename(base string, arg1 string, arg2 string) string { 674 if arg2 == "" { 675 return fmt.Sprintf("%s<%s>", base, arg1) 676 } 677 return fmt.Sprintf("%s<%s,%s>", base, arg1, arg2) 678 } 679 680 // synthesizemaptypes is way too closely married to runtime/hashmap.c 681 const ( 682 MaxKeySize = 128 683 MaxValSize = 128 684 BucketSize = 8 685 ) 686 687 func mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) *sym.Symbol { 688 name := mkinternaltypename(typename, keyname, valname) 689 symname := dwarf.InfoPrefix + name 690 s := ctxt.Syms.ROLookup(symname, 0) 691 if s != nil && s.Type == sym.SDWARFINFO { 692 return s 693 } 694 die := newdie(ctxt, &dwtypes, abbrev, name, 0) 695 f(die) 696 return dtolsym(die.Sym) 697 } 698 699 func synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) { 700 hash := walktypedef(findprotodie(ctxt, "type.runtime.hmap")) 701 bucket := walktypedef(findprotodie(ctxt, "type.runtime.bmap")) 702 703 if hash == nil { 704 return 705 } 706 707 for ; die != nil; die = die.Link { 708 if die.Abbrev != dwarf.DW_ABRV_MAPTYPE { 709 continue 710 } 711 gotype := getattr(die, dwarf.DW_AT_type).Data.(*sym.Symbol) 712 keytype := decodetypeMapKey(ctxt.Arch, gotype) 713 valtype := decodetypeMapValue(ctxt.Arch, gotype) 714 keysize, valsize := decodetypeSize(ctxt.Arch, keytype), decodetypeSize(ctxt.Arch, valtype) 715 keytype, valtype = walksymtypedef(ctxt, defgotype(ctxt, keytype)), walksymtypedef(ctxt, defgotype(ctxt, valtype)) 716 717 // compute size info like hashmap.c does. 718 indirectKey, indirectVal := false, false 719 if keysize > MaxKeySize { 720 keysize = int64(ctxt.Arch.PtrSize) 721 indirectKey = true 722 } 723 if valsize > MaxValSize { 724 valsize = int64(ctxt.Arch.PtrSize) 725 indirectVal = true 726 } 727 728 // Construct type to represent an array of BucketSize keys 729 keyname := nameFromDIESym(keytype) 730 dwhks := mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) { 731 newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*keysize, 0) 732 t := keytype 733 if indirectKey { 734 t = defptrto(ctxt, keytype) 735 } 736 newrefattr(dwhk, dwarf.DW_AT_type, t) 737 fld := newdie(ctxt, dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size", 0) 738 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0) 739 newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr")) 740 }) 741 742 // Construct type to represent an array of BucketSize values 743 valname := nameFromDIESym(valtype) 744 dwhvs := mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) { 745 newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*valsize, 0) 746 t := valtype 747 if indirectVal { 748 t = defptrto(ctxt, valtype) 749 } 750 newrefattr(dwhv, dwarf.DW_AT_type, t) 751 fld := newdie(ctxt, dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size", 0) 752 newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0) 753 newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr")) 754 }) 755 756 // Construct bucket<K,V> 757 dwhbs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *dwarf.DWDie) { 758 // Copy over all fields except the field "data" from the generic 759 // bucket. "data" will be replaced with keys/values below. 760 copychildrenexcept(ctxt, dwhb, bucket, findchild(bucket, "data")) 761 762 fld := newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys", 0) 763 newrefattr(fld, dwarf.DW_AT_type, dwhks) 764 newmemberoffsetattr(fld, BucketSize) 765 fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values", 0) 766 newrefattr(fld, dwarf.DW_AT_type, dwhvs) 767 newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize)) 768 fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow", 0) 769 newrefattr(fld, dwarf.DW_AT_type, defptrto(ctxt, dtolsym(dwhb.Sym))) 770 newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))) 771 if ctxt.Arch.RegSize > ctxt.Arch.PtrSize { 772 fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad", 0) 773 newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr")) 774 newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(ctxt.Arch.PtrSize)) 775 } 776 777 newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize+BucketSize*keysize+BucketSize*valsize+int64(ctxt.Arch.RegSize), 0) 778 }) 779 780 // Construct hash<K,V> 781 dwhs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *dwarf.DWDie) { 782 copychildren(ctxt, dwh, hash) 783 substitutetype(dwh, "buckets", defptrto(ctxt, dwhbs)) 784 substitutetype(dwh, "oldbuckets", defptrto(ctxt, dwhbs)) 785 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hash, dwarf.DW_AT_byte_size).Value, nil) 786 }) 787 788 // make map type a pointer to hash<K,V> 789 newrefattr(die, dwarf.DW_AT_type, defptrto(ctxt, dwhs)) 790 } 791 } 792 793 func synthesizechantypes(ctxt *Link, die *dwarf.DWDie) { 794 sudog := walktypedef(findprotodie(ctxt, "type.runtime.sudog")) 795 waitq := walktypedef(findprotodie(ctxt, "type.runtime.waitq")) 796 hchan := walktypedef(findprotodie(ctxt, "type.runtime.hchan")) 797 if sudog == nil || waitq == nil || hchan == nil { 798 return 799 } 800 801 sudogsize := int(getattr(sudog, dwarf.DW_AT_byte_size).Value) 802 803 for ; die != nil; die = die.Link { 804 if die.Abbrev != dwarf.DW_ABRV_CHANTYPE { 805 continue 806 } 807 elemgotype := getattr(die, dwarf.DW_AT_type).Data.(*sym.Symbol) 808 elemname := elemgotype.Name[5:] 809 elemtype := walksymtypedef(ctxt, defgotype(ctxt, elemgotype)) 810 811 // sudog<T> 812 dwss := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "sudog", elemname, "", func(dws *dwarf.DWDie) { 813 copychildren(ctxt, dws, sudog) 814 substitutetype(dws, "elem", defptrto(ctxt, elemtype)) 815 newattr(dws, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(sudogsize), nil) 816 }) 817 818 // waitq<T> 819 dwws := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "waitq", elemname, "", func(dww *dwarf.DWDie) { 820 821 copychildren(ctxt, dww, waitq) 822 substitutetype(dww, "first", defptrto(ctxt, dwss)) 823 substitutetype(dww, "last", defptrto(ctxt, dwss)) 824 newattr(dww, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(waitq, dwarf.DW_AT_byte_size).Value, nil) 825 }) 826 827 // hchan<T> 828 dwhs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hchan", elemname, "", func(dwh *dwarf.DWDie) { 829 copychildren(ctxt, dwh, hchan) 830 substitutetype(dwh, "recvq", dwws) 831 substitutetype(dwh, "sendq", dwws) 832 newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hchan, dwarf.DW_AT_byte_size).Value, nil) 833 }) 834 835 newrefattr(die, dwarf.DW_AT_type, defptrto(ctxt, dwhs)) 836 } 837 } 838 839 func dwarfDefineGlobal(ctxt *Link, s *sym.Symbol, str string, v int64, gotype *sym.Symbol) { 840 lib := s.Lib 841 if lib == nil { 842 lib = ctxt.LibraryByPkg["runtime"] 843 } 844 dv := newdie(ctxt, ctxt.compUnitByPackage[lib].dwinfo, dwarf.DW_ABRV_VARIABLE, str, int(s.Version)) 845 newabslocexprattr(dv, v, s) 846 if s.Version == 0 { 847 newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0) 848 } 849 dt := defgotype(ctxt, gotype) 850 newrefattr(dv, dwarf.DW_AT_type, dt) 851 } 852 853 // For use with pass.c::genasmsym 854 func defdwsymb(ctxt *Link, s *sym.Symbol, str string, t SymbolType, v int64, gotype *sym.Symbol) { 855 if strings.HasPrefix(str, "go.string.") { 856 return 857 } 858 if strings.HasPrefix(str, "runtime.gcbits.") { 859 return 860 } 861 862 switch t { 863 case DataSym, BSSSym: 864 switch s.Type { 865 case sym.SDATA, sym.SNOPTRDATA, sym.STYPE, sym.SBSS, sym.SNOPTRBSS, sym.STLSBSS: 866 // ok 867 case sym.SRODATA: 868 if gotype != nil { 869 defgotype(ctxt, gotype) 870 } 871 return 872 default: 873 return 874 } 875 if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) { 876 return 877 } 878 dwarfDefineGlobal(ctxt, s, str, v, gotype) 879 880 case AutoSym, ParamSym, DeletedAutoSym: 881 defgotype(ctxt, gotype) 882 } 883 } 884 885 // createUnitLength creates the initial length field with value v and update 886 // offset of unit_length if needed. 887 func createUnitLength(ctxt *Link, s *sym.Symbol, v uint64) { 888 if isDwarf64(ctxt) { 889 s.AddUint32(ctxt.Arch, 0xFFFFFFFF) 890 } 891 addDwarfAddrField(ctxt, s, v) 892 } 893 894 // addDwarfAddrField adds a DWARF field in DWARF 64bits or 32bits. 895 func addDwarfAddrField(ctxt *Link, s *sym.Symbol, v uint64) { 896 if isDwarf64(ctxt) { 897 s.AddUint(ctxt.Arch, v) 898 } else { 899 s.AddUint32(ctxt.Arch, uint32(v)) 900 } 901 } 902 903 // addDwarfAddrRef adds a DWARF pointer in DWARF 64bits or 32bits. 904 func addDwarfAddrRef(ctxt *Link, s *sym.Symbol, t *sym.Symbol) { 905 if isDwarf64(ctxt) { 906 adddwarfref(ctxt, s, t, 8) 907 } else { 908 adddwarfref(ctxt, s, t, 4) 909 } 910 } 911 912 // compilationUnit is per-compilation unit (equivalently, per-package) 913 // debug-related data. 914 type compilationUnit struct { 915 lib *sym.Library 916 consts *sym.Symbol // Package constants DIEs 917 pcs []dwarf.Range // PC ranges, relative to textp[0] 918 dwinfo *dwarf.DWDie // CU root DIE 919 funcDIEs []*sym.Symbol // Function DIE subtrees 920 absFnDIEs []*sym.Symbol // Abstract function DIE subtrees 921 rangeSyms []*sym.Symbol // symbols for debug_range 922 } 923 924 // calcCompUnitRanges calculates the PC ranges of the compilation units. 925 func calcCompUnitRanges(ctxt *Link) { 926 var prevUnit *compilationUnit 927 for _, s := range ctxt.Textp { 928 if s.FuncInfo == nil { 929 continue 930 } 931 unit := ctxt.compUnitByPackage[s.Lib] 932 933 // Update PC ranges. 934 // 935 // We don't simply compare the end of the previous 936 // symbol with the start of the next because there's 937 // often a little padding between them. Instead, we 938 // only create boundaries between symbols from 939 // different units. 940 if prevUnit != unit { 941 unit.pcs = append(unit.pcs, dwarf.Range{Start: s.Value - unit.lib.Textp[0].Value}) 942 prevUnit = unit 943 } 944 unit.pcs[len(unit.pcs)-1].End = s.Value - unit.lib.Textp[0].Value + s.Size 945 } 946 } 947 948 func movetomodule(ctxt *Link, parent *dwarf.DWDie) { 949 runtimelib := ctxt.LibraryByPkg["runtime"] 950 die := ctxt.compUnitByPackage[runtimelib].dwinfo.Child 951 if die == nil { 952 ctxt.compUnitByPackage[runtimelib].dwinfo.Child = parent.Child 953 return 954 } 955 for die.Link != nil { 956 die = die.Link 957 } 958 die.Link = parent.Child 959 } 960 961 // If the pcln table contains runtime/proc.go, use that to set gdbscript path. 962 func finddebugruntimepath(s *sym.Symbol) { 963 if gdbscript != "" { 964 return 965 } 966 967 for i := range s.FuncInfo.File { 968 f := s.FuncInfo.File[i] 969 // We can't use something that may be dead-code 970 // eliminated from a binary here. proc.go contains 971 // main and the scheduler, so it's not going anywhere. 972 if i := strings.Index(f.Name, "runtime/proc.go"); i >= 0 { 973 gdbscript = f.Name[:i] + "runtime/runtime-gdb.py" 974 break 975 } 976 } 977 } 978 979 /* 980 * Generate a sequence of opcodes that is as short as possible. 981 * See section 6.2.5 982 */ 983 const ( 984 LINE_BASE = -4 985 LINE_RANGE = 10 986 PC_RANGE = (255 - OPCODE_BASE) / LINE_RANGE 987 OPCODE_BASE = 11 988 ) 989 990 func putpclcdelta(linkctxt *Link, ctxt dwarf.Context, s *sym.Symbol, deltaPC uint64, deltaLC int64) { 991 // Choose a special opcode that minimizes the number of bytes needed to 992 // encode the remaining PC delta and LC delta. 993 var opcode int64 994 if deltaLC < LINE_BASE { 995 if deltaPC >= PC_RANGE { 996 opcode = OPCODE_BASE + (LINE_RANGE * PC_RANGE) 997 } else { 998 opcode = OPCODE_BASE + (LINE_RANGE * int64(deltaPC)) 999 } 1000 } else if deltaLC < LINE_BASE+LINE_RANGE { 1001 if deltaPC >= PC_RANGE { 1002 opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * PC_RANGE) 1003 if opcode > 255 { 1004 opcode -= LINE_RANGE 1005 } 1006 } else { 1007 opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * int64(deltaPC)) 1008 } 1009 } else { 1010 if deltaPC <= PC_RANGE { 1011 opcode = OPCODE_BASE + (LINE_RANGE - 1) + (LINE_RANGE * int64(deltaPC)) 1012 if opcode > 255 { 1013 opcode = 255 1014 } 1015 } else { 1016 // Use opcode 249 (pc+=23, lc+=5) or 255 (pc+=24, lc+=1). 1017 // 1018 // Let x=deltaPC-PC_RANGE. If we use opcode 255, x will be the remaining 1019 // deltaPC that we need to encode separately before emitting 255. If we 1020 // use opcode 249, we will need to encode x+1. If x+1 takes one more 1021 // byte to encode than x, then we use opcode 255. 1022 // 1023 // In all other cases x and x+1 take the same number of bytes to encode, 1024 // so we use opcode 249, which may save us a byte in encoding deltaLC, 1025 // for similar reasons. 1026 switch deltaPC - PC_RANGE { 1027 // PC_RANGE is the largest deltaPC we can encode in one byte, using 1028 // DW_LNS_const_add_pc. 1029 // 1030 // (1<<16)-1 is the largest deltaPC we can encode in three bytes, using 1031 // DW_LNS_fixed_advance_pc. 1032 // 1033 // (1<<(7n))-1 is the largest deltaPC we can encode in n+1 bytes for 1034 // n=1,3,4,5,..., using DW_LNS_advance_pc. 1035 case PC_RANGE, (1 << 7) - 1, (1 << 16) - 1, (1 << 21) - 1, (1 << 28) - 1, 1036 (1 << 35) - 1, (1 << 42) - 1, (1 << 49) - 1, (1 << 56) - 1, (1 << 63) - 1: 1037 opcode = 255 1038 default: 1039 opcode = OPCODE_BASE + LINE_RANGE*PC_RANGE - 1 // 249 1040 } 1041 } 1042 } 1043 if opcode < OPCODE_BASE || opcode > 255 { 1044 panic(fmt.Sprintf("produced invalid special opcode %d", opcode)) 1045 } 1046 1047 // Subtract from deltaPC and deltaLC the amounts that the opcode will add. 1048 deltaPC -= uint64((opcode - OPCODE_BASE) / LINE_RANGE) 1049 deltaLC -= (opcode-OPCODE_BASE)%LINE_RANGE + LINE_BASE 1050 1051 // Encode deltaPC. 1052 if deltaPC != 0 { 1053 if deltaPC <= PC_RANGE { 1054 // Adjust the opcode so that we can use the 1-byte DW_LNS_const_add_pc 1055 // instruction. 1056 opcode -= LINE_RANGE * int64(PC_RANGE-deltaPC) 1057 if opcode < OPCODE_BASE { 1058 panic(fmt.Sprintf("produced invalid special opcode %d", opcode)) 1059 } 1060 s.AddUint8(dwarf.DW_LNS_const_add_pc) 1061 } else if (1<<14) <= deltaPC && deltaPC < (1<<16) { 1062 s.AddUint8(dwarf.DW_LNS_fixed_advance_pc) 1063 s.AddUint16(linkctxt.Arch, uint16(deltaPC)) 1064 } else { 1065 s.AddUint8(dwarf.DW_LNS_advance_pc) 1066 dwarf.Uleb128put(ctxt, s, int64(deltaPC)) 1067 } 1068 } 1069 1070 // Encode deltaLC. 1071 if deltaLC != 0 { 1072 s.AddUint8(dwarf.DW_LNS_advance_line) 1073 dwarf.Sleb128put(ctxt, s, deltaLC) 1074 } 1075 1076 // Output the special opcode. 1077 s.AddUint8(uint8(opcode)) 1078 } 1079 1080 /* 1081 * Walk prog table, emit line program and build DIE tree. 1082 */ 1083 1084 func getCompilationDir() string { 1085 // OSX requires this be set to something, but it's not easy to choose 1086 // a value. Linking takes place in a temporary directory, so there's 1087 // no point including it here. Paths in the file table are usually 1088 // absolute, in which case debuggers will ignore this value. -trimpath 1089 // produces relative paths, but we don't know where they start, so 1090 // all we can do here is try not to make things worse. 1091 return "." 1092 } 1093 1094 func importInfoSymbol(ctxt *Link, dsym *sym.Symbol) { 1095 dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable 1096 dsym.Type = sym.SDWARFINFO 1097 for i := range dsym.R { 1098 r := &dsym.R[i] // Copying sym.Reloc has measurable impact on performance 1099 if r.Type == objabi.R_DWARFSECREF && r.Sym.Size == 0 { 1100 n := nameFromDIESym(r.Sym) 1101 defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0)) 1102 } 1103 } 1104 } 1105 1106 func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) { 1107 1108 var dwarfctxt dwarf.Context = dwctxt{ctxt} 1109 is_stmt := uint8(1) // initially = recommended default_is_stmt = 1, tracks is_stmt toggles. 1110 1111 unitstart := int64(-1) 1112 headerstart := int64(-1) 1113 headerend := int64(-1) 1114 1115 newattr(unit.dwinfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, ls.Size, ls) 1116 1117 // Write .debug_line Line Number Program Header (sec 6.2.4) 1118 // Fields marked with (*) must be changed for 64-bit dwarf 1119 unitLengthOffset := ls.Size 1120 createUnitLength(ctxt, ls, 0) // unit_length (*), filled in at end 1121 unitstart = ls.Size 1122 ls.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F) -- version 3 is incompatible w/ XCode 9.0's dsymutil, latest supported on OSX 10.12 as of 2018-05 1123 headerLengthOffset := ls.Size 1124 addDwarfAddrField(ctxt, ls, 0) // header_length (*), filled in at end 1125 headerstart = ls.Size 1126 1127 // cpos == unitstart + 4 + 2 + 4 1128 ls.AddUint8(1) // minimum_instruction_length 1129 ls.AddUint8(is_stmt) // default_is_stmt 1130 ls.AddUint8(LINE_BASE & 0xFF) // line_base 1131 ls.AddUint8(LINE_RANGE) // line_range 1132 ls.AddUint8(OPCODE_BASE) // opcode_base 1133 ls.AddUint8(0) // standard_opcode_lengths[1] 1134 ls.AddUint8(1) // standard_opcode_lengths[2] 1135 ls.AddUint8(1) // standard_opcode_lengths[3] 1136 ls.AddUint8(1) // standard_opcode_lengths[4] 1137 ls.AddUint8(1) // standard_opcode_lengths[5] 1138 ls.AddUint8(0) // standard_opcode_lengths[6] 1139 ls.AddUint8(0) // standard_opcode_lengths[7] 1140 ls.AddUint8(0) // standard_opcode_lengths[8] 1141 ls.AddUint8(1) // standard_opcode_lengths[9] 1142 ls.AddUint8(0) // standard_opcode_lengths[10] 1143 ls.AddUint8(0) // include_directories (empty) 1144 1145 // Create the file table. fileNums maps from global file 1146 // indexes (created by numberfile) to CU-local indexes. 1147 fileNums := make(map[int]int) 1148 for _, s := range unit.lib.Textp { // textp has been dead-code-eliminated already. 1149 dsym := ctxt.Syms.Lookup(dwarf.InfoPrefix+s.Name, int(s.Version)) 1150 for _, f := range s.FuncInfo.File { 1151 if _, ok := fileNums[int(f.Value)]; ok { 1152 continue 1153 } 1154 // File indexes are 1-based. 1155 fileNums[int(f.Value)] = len(fileNums) + 1 1156 Addstring(ls, f.Name) 1157 ls.AddUint8(0) 1158 ls.AddUint8(0) 1159 ls.AddUint8(0) 1160 } 1161 for ri := 0; ri < len(dsym.R); ri++ { 1162 r := &dsym.R[ri] 1163 if r.Type != objabi.R_DWARFFILEREF { 1164 continue 1165 } 1166 // A file that is only mentioned in an inlined subroutine will appear 1167 // as a R_DWARFFILEREF but not in s.FuncInfo.File 1168 if _, ok := fileNums[int(r.Sym.Value)]; ok { 1169 continue 1170 } 1171 fileNums[int(r.Sym.Value)] = len(fileNums) + 1 1172 Addstring(ls, r.Sym.Name) 1173 ls.AddUint8(0) 1174 ls.AddUint8(0) 1175 ls.AddUint8(0) 1176 } 1177 } 1178 1179 // 4 zeros: the string termination + 3 fields. 1180 ls.AddUint8(0) 1181 // terminate file_names. 1182 headerend = ls.Size 1183 1184 ls.AddUint8(0) // start extended opcode 1185 dwarf.Uleb128put(dwarfctxt, ls, 1+int64(ctxt.Arch.PtrSize)) 1186 ls.AddUint8(dwarf.DW_LNE_set_address) 1187 1188 s := unit.lib.Textp[0] 1189 pc := s.Value 1190 line := 1 1191 file := 1 1192 ls.AddAddr(ctxt.Arch, s) 1193 1194 var pcfile Pciter 1195 var pcline Pciter 1196 var pcstmt Pciter 1197 for i, s := range unit.lib.Textp { 1198 finddebugruntimepath(s) 1199 1200 pciterinit(ctxt, &pcfile, &s.FuncInfo.Pcfile) 1201 pciterinit(ctxt, &pcline, &s.FuncInfo.Pcline) 1202 pciterinit(ctxt, &pcstmt, &sym.Pcdata{P: s.FuncInfo.IsStmtSym.P}) 1203 1204 if pcstmt.done != 0 { 1205 // Assembly files lack a pcstmt section, we assume that every instruction 1206 // is a valid statement. 1207 pcstmt.value = 1 1208 } 1209 1210 var thispc uint32 1211 // TODO this loop looks like it could exit with work remaining. 1212 for pcfile.done == 0 && pcline.done == 0 { 1213 // Only changed if it advanced 1214 if int32(file) != pcfile.value { 1215 ls.AddUint8(dwarf.DW_LNS_set_file) 1216 idx, ok := fileNums[int(pcfile.value)] 1217 if !ok { 1218 Exitf("pcln table file missing from DWARF line table") 1219 } 1220 dwarf.Uleb128put(dwarfctxt, ls, int64(idx)) 1221 file = int(pcfile.value) 1222 } 1223 1224 // Only changed if it advanced 1225 if is_stmt != uint8(pcstmt.value) { 1226 new_stmt := uint8(pcstmt.value) 1227 switch new_stmt &^ 1 { 1228 case obj.PrologueEnd: 1229 ls.AddUint8(uint8(dwarf.DW_LNS_set_prologue_end)) 1230 case obj.EpilogueBegin: 1231 // TODO if there is a use for this, add it. 1232 // Don't forget to increase OPCODE_BASE by 1 and add entry for standard_opcode_lengths[11] 1233 } 1234 new_stmt &= 1 1235 if is_stmt != new_stmt { 1236 is_stmt = new_stmt 1237 ls.AddUint8(uint8(dwarf.DW_LNS_negate_stmt)) 1238 } 1239 } 1240 1241 // putpcldelta makes a row in the DWARF matrix, always, even if line is unchanged. 1242 putpclcdelta(ctxt, dwarfctxt, ls, uint64(s.Value+int64(thispc)-pc), int64(pcline.value)-int64(line)) 1243 1244 pc = s.Value + int64(thispc) 1245 line = int(pcline.value) 1246 1247 // Take the minimum step forward for the three iterators 1248 thispc = pcfile.nextpc 1249 if pcline.nextpc < thispc { 1250 thispc = pcline.nextpc 1251 } 1252 if pcstmt.done == 0 && pcstmt.nextpc < thispc { 1253 thispc = pcstmt.nextpc 1254 } 1255 1256 if pcfile.nextpc == thispc { 1257 pciternext(&pcfile) 1258 } 1259 if pcstmt.done == 0 && pcstmt.nextpc == thispc { 1260 pciternext(&pcstmt) 1261 } 1262 if pcline.nextpc == thispc { 1263 pciternext(&pcline) 1264 } 1265 } 1266 if is_stmt == 0 && i < len(unit.lib.Textp)-1 { 1267 // If there is more than one function, ensure default value is established. 1268 is_stmt = 1 1269 ls.AddUint8(uint8(dwarf.DW_LNS_negate_stmt)) 1270 } 1271 } 1272 1273 ls.AddUint8(0) // start extended opcode 1274 dwarf.Uleb128put(dwarfctxt, ls, 1) 1275 ls.AddUint8(dwarf.DW_LNE_end_sequence) 1276 1277 if ctxt.HeadType == objabi.Haix { 1278 saveDwsectCUSize(".debug_line", unit.lib.String(), uint64(ls.Size-unitLengthOffset)) 1279 } 1280 if isDwarf64(ctxt) { 1281 ls.SetUint(ctxt.Arch, unitLengthOffset+4, uint64(ls.Size-unitstart)) // +4 because of 0xFFFFFFFF 1282 ls.SetUint(ctxt.Arch, headerLengthOffset, uint64(headerend-headerstart)) 1283 } else { 1284 ls.SetUint32(ctxt.Arch, unitLengthOffset, uint32(ls.Size-unitstart)) 1285 ls.SetUint32(ctxt.Arch, headerLengthOffset, uint32(headerend-headerstart)) 1286 } 1287 1288 // Apply any R_DWARFFILEREF relocations, since we now know the 1289 // line table file indices for this compilation unit. Note that 1290 // this loop visits only subprogram DIEs: if the compiler is 1291 // changed to generate DW_AT_decl_file attributes for other 1292 // DIE flavors (ex: variables) then those DIEs would need to 1293 // be included below. 1294 missing := make(map[int]interface{}) 1295 for _, f := range unit.funcDIEs { 1296 for ri := range f.R { 1297 r := &f.R[ri] 1298 if r.Type != objabi.R_DWARFFILEREF { 1299 continue 1300 } 1301 // Mark relocation as applied (signal to relocsym) 1302 r.Done = true 1303 idx, ok := fileNums[int(r.Sym.Value)] 1304 if ok { 1305 if int(int32(idx)) != idx { 1306 Errorf(f, "bad R_DWARFFILEREF relocation: file index overflow") 1307 } 1308 if r.Siz != 4 { 1309 Errorf(f, "bad R_DWARFFILEREF relocation: has size %d, expected 4", r.Siz) 1310 } 1311 if r.Off < 0 || r.Off+4 > int32(len(f.P)) { 1312 Errorf(f, "bad R_DWARFFILEREF relocation offset %d + 4 would write past length %d", r.Off, len(s.P)) 1313 continue 1314 } 1315 ctxt.Arch.ByteOrder.PutUint32(f.P[r.Off:r.Off+4], uint32(idx)) 1316 } else { 1317 _, found := missing[int(r.Sym.Value)] 1318 if !found { 1319 Errorf(f, "R_DWARFFILEREF relocation file missing: %v idx %d", r.Sym, r.Sym.Value) 1320 missing[int(r.Sym.Value)] = nil 1321 } 1322 } 1323 } 1324 } 1325 } 1326 1327 // writepcranges generates the DW_AT_ranges table for compilation unit cu. 1328 func writepcranges(ctxt *Link, cu *dwarf.DWDie, base *sym.Symbol, pcs []dwarf.Range, ranges *sym.Symbol) { 1329 var dwarfctxt dwarf.Context = dwctxt{ctxt} 1330 1331 // Create PC ranges for this CU. 1332 newattr(cu, dwarf.DW_AT_ranges, dwarf.DW_CLS_PTR, ranges.Size, ranges) 1333 newattr(cu, dwarf.DW_AT_low_pc, dwarf.DW_CLS_ADDRESS, base.Value, base) 1334 dwarf.PutRanges(dwarfctxt, ranges, nil, pcs) 1335 } 1336 1337 /* 1338 * Emit .debug_frame 1339 */ 1340 const ( 1341 dataAlignmentFactor = -4 1342 ) 1343 1344 // appendPCDeltaCFA appends per-PC CFA deltas to b and returns the final slice. 1345 func appendPCDeltaCFA(arch *sys.Arch, b []byte, deltapc, cfa int64) []byte { 1346 b = append(b, dwarf.DW_CFA_def_cfa_offset_sf) 1347 b = dwarf.AppendSleb128(b, cfa/dataAlignmentFactor) 1348 1349 switch { 1350 case deltapc < 0x40: 1351 b = append(b, uint8(dwarf.DW_CFA_advance_loc+deltapc)) 1352 case deltapc < 0x100: 1353 b = append(b, dwarf.DW_CFA_advance_loc1) 1354 b = append(b, uint8(deltapc)) 1355 case deltapc < 0x10000: 1356 b = append(b, dwarf.DW_CFA_advance_loc2, 0, 0) 1357 arch.ByteOrder.PutUint16(b[len(b)-2:], uint16(deltapc)) 1358 default: 1359 b = append(b, dwarf.DW_CFA_advance_loc4, 0, 0, 0, 0) 1360 arch.ByteOrder.PutUint32(b[len(b)-4:], uint32(deltapc)) 1361 } 1362 return b 1363 } 1364 1365 func writeframes(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol { 1366 var dwarfctxt dwarf.Context = dwctxt{ctxt} 1367 fs := ctxt.Syms.Lookup(".debug_frame", 0) 1368 fs.Type = sym.SDWARFSECT 1369 syms = append(syms, fs) 1370 1371 // Emit the CIE, Section 6.4.1 1372 cieReserve := uint32(16) 1373 if haslinkregister(ctxt) { 1374 cieReserve = 32 1375 } 1376 createUnitLength(ctxt, fs, uint64(cieReserve)) // initial length, must be multiple of thearch.ptrsize 1377 addDwarfAddrField(ctxt, fs, 0xffffffff) // cid. 1378 fs.AddUint8(3) // dwarf version (appendix F) 1379 fs.AddUint8(0) // augmentation "" 1380 dwarf.Uleb128put(dwarfctxt, fs, 1) // code_alignment_factor 1381 dwarf.Sleb128put(dwarfctxt, fs, dataAlignmentFactor) // all CFI offset calculations include multiplication with this factor 1382 dwarf.Uleb128put(dwarfctxt, fs, int64(thearch.Dwarfreglr)) // return_address_register 1383 1384 fs.AddUint8(dwarf.DW_CFA_def_cfa) // Set the current frame address.. 1385 dwarf.Uleb128put(dwarfctxt, fs, int64(thearch.Dwarfregsp)) // ...to use the value in the platform's SP register (defined in l.go)... 1386 if haslinkregister(ctxt) { 1387 dwarf.Uleb128put(dwarfctxt, fs, int64(0)) // ...plus a 0 offset. 1388 1389 fs.AddUint8(dwarf.DW_CFA_same_value) // The platform's link register is unchanged during the prologue. 1390 dwarf.Uleb128put(dwarfctxt, fs, int64(thearch.Dwarfreglr)) 1391 1392 fs.AddUint8(dwarf.DW_CFA_val_offset) // The previous value... 1393 dwarf.Uleb128put(dwarfctxt, fs, int64(thearch.Dwarfregsp)) // ...of the platform's SP register... 1394 dwarf.Uleb128put(dwarfctxt, fs, int64(0)) // ...is CFA+0. 1395 } else { 1396 dwarf.Uleb128put(dwarfctxt, fs, int64(ctxt.Arch.PtrSize)) // ...plus the word size (because the call instruction implicitly adds one word to the frame). 1397 1398 fs.AddUint8(dwarf.DW_CFA_offset_extended) // The previous value... 1399 dwarf.Uleb128put(dwarfctxt, fs, int64(thearch.Dwarfreglr)) // ...of the return address... 1400 dwarf.Uleb128put(dwarfctxt, fs, int64(-ctxt.Arch.PtrSize)/dataAlignmentFactor) // ...is saved at [CFA - (PtrSize/4)]. 1401 } 1402 1403 // 4 is to exclude the length field. 1404 pad := int64(cieReserve) + 4 - fs.Size 1405 1406 if pad < 0 { 1407 Exitf("dwarf: cieReserve too small by %d bytes.", -pad) 1408 } 1409 1410 fs.AddBytes(zeros[:pad]) 1411 1412 var deltaBuf []byte 1413 var pcsp Pciter 1414 for _, s := range ctxt.Textp { 1415 if s.FuncInfo == nil { 1416 continue 1417 } 1418 1419 // Emit a FDE, Section 6.4.1. 1420 // First build the section contents into a byte buffer. 1421 deltaBuf = deltaBuf[:0] 1422 for pciterinit(ctxt, &pcsp, &s.FuncInfo.Pcsp); pcsp.done == 0; pciternext(&pcsp) { 1423 nextpc := pcsp.nextpc 1424 1425 // pciterinit goes up to the end of the function, 1426 // but DWARF expects us to stop just before the end. 1427 if int64(nextpc) == s.Size { 1428 nextpc-- 1429 if nextpc < pcsp.pc { 1430 continue 1431 } 1432 } 1433 1434 if haslinkregister(ctxt) { 1435 // TODO(bryanpkc): This is imprecise. In general, the instruction 1436 // that stores the return address to the stack frame is not the 1437 // same one that allocates the frame. 1438 if pcsp.value > 0 { 1439 // The return address is preserved at (CFA-frame_size) 1440 // after a stack frame has been allocated. 1441 deltaBuf = append(deltaBuf, dwarf.DW_CFA_offset_extended_sf) 1442 deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr)) 1443 deltaBuf = dwarf.AppendSleb128(deltaBuf, -int64(pcsp.value)/dataAlignmentFactor) 1444 } else { 1445 // The return address is restored into the link register 1446 // when a stack frame has been de-allocated. 1447 deltaBuf = append(deltaBuf, dwarf.DW_CFA_same_value) 1448 deltaBuf = dwarf.AppendUleb128(deltaBuf, uint64(thearch.Dwarfreglr)) 1449 } 1450 deltaBuf = appendPCDeltaCFA(ctxt.Arch, deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(pcsp.value)) 1451 } else { 1452 deltaBuf = appendPCDeltaCFA(ctxt.Arch, deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(ctxt.Arch.PtrSize)+int64(pcsp.value)) 1453 } 1454 } 1455 pad := int(Rnd(int64(len(deltaBuf)), int64(ctxt.Arch.PtrSize))) - len(deltaBuf) 1456 deltaBuf = append(deltaBuf, zeros[:pad]...) 1457 1458 // Emit the FDE header, Section 6.4.1. 1459 // 4 bytes: length, must be multiple of thearch.ptrsize 1460 // 4 bytes: Pointer to the CIE above, at offset 0 1461 // ptrsize: initial location 1462 // ptrsize: address range 1463 fs.AddUint32(ctxt.Arch, uint32(4+2*ctxt.Arch.PtrSize+len(deltaBuf))) // length (excludes itself) 1464 if ctxt.LinkMode == LinkExternal { 1465 addDwarfAddrRef(ctxt, fs, fs) 1466 } else { 1467 addDwarfAddrField(ctxt, fs, 0) // CIE offset 1468 } 1469 fs.AddAddr(ctxt.Arch, s) 1470 fs.AddUintXX(ctxt.Arch, uint64(s.Size), ctxt.Arch.PtrSize) // address range 1471 fs.AddBytes(deltaBuf) 1472 } 1473 return syms 1474 } 1475 1476 /* 1477 * Walk DWarfDebugInfoEntries, and emit .debug_info 1478 */ 1479 const ( 1480 COMPUNITHEADERSIZE = 4 + 2 + 4 + 1 1481 ) 1482 1483 func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevsym *sym.Symbol) []*sym.Symbol { 1484 infosec := ctxt.Syms.Lookup(".debug_info", 0) 1485 infosec.Type = sym.SDWARFINFO 1486 infosec.Attr |= sym.AttrReachable 1487 syms = append(syms, infosec) 1488 1489 var dwarfctxt dwarf.Context = dwctxt{ctxt} 1490 1491 for _, u := range units { 1492 compunit := u.dwinfo 1493 s := dtolsym(compunit.Sym) 1494 1495 if len(u.lib.Textp) == 0 && u.dwinfo.Child == nil { 1496 continue 1497 } 1498 1499 // Write .debug_info Compilation Unit Header (sec 7.5.1) 1500 // Fields marked with (*) must be changed for 64-bit dwarf 1501 // This must match COMPUNITHEADERSIZE above. 1502 createUnitLength(ctxt, s, 0) // unit_length (*), will be filled in later. 1503 s.AddUint16(ctxt.Arch, 4) // dwarf version (appendix F) 1504 1505 // debug_abbrev_offset (*) 1506 addDwarfAddrRef(ctxt, s, abbrevsym) 1507 1508 s.AddUint8(uint8(ctxt.Arch.PtrSize)) // address_size 1509 1510 dwarf.Uleb128put(dwarfctxt, s, int64(compunit.Abbrev)) 1511 dwarf.PutAttrs(dwarfctxt, s, compunit.Abbrev, compunit.Attr) 1512 1513 cu := []*sym.Symbol{s} 1514 cu = append(cu, u.absFnDIEs...) 1515 cu = append(cu, u.funcDIEs...) 1516 if u.consts != nil { 1517 cu = append(cu, u.consts) 1518 } 1519 cu = putdies(ctxt, dwarfctxt, cu, compunit.Child) 1520 var cusize int64 1521 for _, child := range cu { 1522 cusize += child.Size 1523 } 1524 // Save size for AIX symbol table. 1525 if ctxt.HeadType == objabi.Haix { 1526 saveDwsectCUSize(".debug_info", getPkgFromCUSym(s), uint64(cusize)) 1527 } 1528 if isDwarf64(ctxt) { 1529 cusize -= 12 // exclude the length field. 1530 s.SetUint(ctxt.Arch, 4, uint64(cusize)) // 4 because of 0XFFFFFFFF 1531 } else { 1532 cusize -= 4 // exclude the length field. 1533 s.SetUint32(ctxt.Arch, 0, uint32(cusize)) 1534 } 1535 // Leave a breadcrumb for writepub. This does not 1536 // appear in the DWARF output. 1537 newattr(compunit, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, cusize, 0) 1538 syms = append(syms, cu...) 1539 } 1540 return syms 1541 } 1542 1543 /* 1544 * Emit .debug_pubnames/_types. _info must have been written before, 1545 * because we need die->offs and infoo/infosize; 1546 */ 1547 func ispubname(die *dwarf.DWDie) bool { 1548 switch die.Abbrev { 1549 case dwarf.DW_ABRV_FUNCTION, dwarf.DW_ABRV_VARIABLE: 1550 a := getattr(die, dwarf.DW_AT_external) 1551 return a != nil && a.Value != 0 1552 } 1553 1554 return false 1555 } 1556 1557 func ispubtype(die *dwarf.DWDie) bool { 1558 return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE 1559 } 1560 1561 func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*sym.Symbol) []*sym.Symbol { 1562 s := ctxt.Syms.Lookup(sname, 0) 1563 s.Type = sym.SDWARFSECT 1564 syms = append(syms, s) 1565 1566 for _, u := range ctxt.compUnits { 1567 if len(u.lib.Textp) == 0 && u.dwinfo.Child == nil { 1568 continue 1569 } 1570 compunit := u.dwinfo 1571 sectionstart := s.Size 1572 culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4 1573 1574 // Write .debug_pubnames/types Header (sec 6.1.1) 1575 createUnitLength(ctxt, s, 0) // unit_length (*), will be filled in later. 1576 s.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F) 1577 addDwarfAddrRef(ctxt, s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header) 1578 addDwarfAddrField(ctxt, s, uint64(culength)) // debug_info_length 1579 1580 for die := compunit.Child; die != nil; die = die.Link { 1581 if !ispub(die) { 1582 continue 1583 } 1584 dwa := getattr(die, dwarf.DW_AT_name) 1585 name := dwa.Data.(string) 1586 if die.Sym == nil { 1587 fmt.Println("Missing sym for ", name) 1588 } 1589 addDwarfAddrRef(ctxt, s, dtolsym(die.Sym)) 1590 Addstring(s, name) 1591 } 1592 1593 addDwarfAddrField(ctxt, s, 0) // Null offset 1594 1595 // On AIX, save the current size of this compilation unit. 1596 if ctxt.HeadType == objabi.Haix { 1597 saveDwsectCUSize(sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(s.Size-sectionstart)) 1598 } 1599 if isDwarf64(ctxt) { 1600 s.SetUint(ctxt.Arch, sectionstart+4, uint64(s.Size-sectionstart)-12) // exclude the length field. 1601 } else { 1602 s.SetUint32(ctxt.Arch, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field. 1603 } 1604 } 1605 1606 return syms 1607 } 1608 1609 func writegdbscript(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol { 1610 // TODO (aix): make it available 1611 if ctxt.HeadType == objabi.Haix { 1612 return syms 1613 } 1614 if ctxt.LinkMode == LinkExternal && ctxt.HeadType == objabi.Hwindows && ctxt.BuildMode == BuildModeCArchive { 1615 // gcc on Windows places .debug_gdb_scripts in the wrong location, which 1616 // causes the program not to run. See https://golang.org/issue/20183 1617 // Non c-archives can avoid this issue via a linker script 1618 // (see fix near writeGDBLinkerScript). 1619 // c-archive users would need to specify the linker script manually. 1620 // For UX it's better not to deal with this. 1621 return syms 1622 } 1623 1624 if gdbscript != "" { 1625 s := ctxt.Syms.Lookup(".debug_gdb_scripts", 0) 1626 s.Type = sym.SDWARFSECT 1627 syms = append(syms, s) 1628 s.AddUint8(1) // magic 1 byte? 1629 Addstring(s, gdbscript) 1630 } 1631 1632 return syms 1633 } 1634 1635 var prototypedies map[string]*dwarf.DWDie 1636 1637 func dwarfEnabled(ctxt *Link) bool { 1638 if *FlagW { // disable dwarf 1639 return false 1640 } 1641 if *FlagS && ctxt.HeadType != objabi.Hdarwin { 1642 return false 1643 } 1644 if ctxt.HeadType == objabi.Hplan9 || ctxt.HeadType == objabi.Hjs { 1645 return false 1646 } 1647 1648 if ctxt.LinkMode == LinkExternal { 1649 switch { 1650 case ctxt.IsELF: 1651 case ctxt.HeadType == objabi.Hdarwin: 1652 case ctxt.HeadType == objabi.Hwindows: 1653 default: 1654 return false 1655 } 1656 } 1657 1658 return true 1659 } 1660 1661 // dwarfGenerateDebugInfo generated debug info entries for all types, 1662 // variables and functions in the program. 1663 // Along with dwarfGenerateDebugSyms they are the two main entry points into 1664 // dwarf generation: dwarfGenerateDebugInfo does all the work that should be 1665 // done before symbol names are mangled while dwarfgeneratedebugsyms does 1666 // all the work that can only be done after addresses have been assigned to 1667 // text symbols. 1668 func dwarfGenerateDebugInfo(ctxt *Link) { 1669 if !dwarfEnabled(ctxt) { 1670 return 1671 } 1672 1673 ctxt.compUnitByPackage = make(map[*sym.Library]*compilationUnit) 1674 1675 // Forctxt.Diagnostic messages. 1676 newattr(&dwtypes, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len("dwtypes")), "dwtypes") 1677 1678 // Some types that must exist to define other ones. 1679 newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "<unspecified>", 0) 1680 1681 newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "void", 0) 1682 newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer", 0) 1683 1684 die := newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, "uintptr", 0) // needed for array size 1685 newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0) 1686 newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(ctxt.Arch.PtrSize), 0) 1687 newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, objabi.KindUintptr, 0) 1688 newattr(die, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_ADDRESS, 0, lookupOrDiag(ctxt, "type.uintptr")) 1689 1690 // Prototypes needed for type synthesis. 1691 prototypedies = map[string]*dwarf.DWDie{ 1692 "type.runtime.stringStructDWARF": nil, 1693 "type.runtime.slice": nil, 1694 "type.runtime.hmap": nil, 1695 "type.runtime.bmap": nil, 1696 "type.runtime.sudog": nil, 1697 "type.runtime.waitq": nil, 1698 "type.runtime.hchan": nil, 1699 } 1700 1701 // Needed by the prettyprinter code for interface inspection. 1702 for _, typ := range []string{ 1703 "type.runtime._type", 1704 "type.runtime.arraytype", 1705 "type.runtime.chantype", 1706 "type.runtime.functype", 1707 "type.runtime.maptype", 1708 "type.runtime.ptrtype", 1709 "type.runtime.slicetype", 1710 "type.runtime.structtype", 1711 "type.runtime.interfacetype", 1712 "type.runtime.itab", 1713 "type.runtime.imethod"} { 1714 defgotype(ctxt, lookupOrDiag(ctxt, typ)) 1715 } 1716 1717 // fake root DIE for compile unit DIEs 1718 var dwroot dwarf.DWDie 1719 1720 for _, lib := range ctxt.Library { 1721 unit := &compilationUnit{lib: lib} 1722 if s := ctxt.Syms.ROLookup(dwarf.ConstInfoPrefix+lib.Pkg, 0); s != nil { 1723 importInfoSymbol(ctxt, s) 1724 unit.consts = s 1725 } 1726 ctxt.compUnits = append(ctxt.compUnits, unit) 1727 ctxt.compUnitByPackage[lib] = unit 1728 1729 unit.dwinfo = newdie(ctxt, &dwroot, dwarf.DW_ABRV_COMPUNIT, unit.lib.Pkg, 0) 1730 newattr(unit.dwinfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(dwarf.DW_LANG_Go), 0) 1731 // OS X linker requires compilation dir or absolute path in comp unit name to output debug info. 1732 compDir := getCompilationDir() 1733 // TODO: Make this be the actual compilation directory, not 1734 // the linker directory. If we move CU construction into the 1735 // compiler, this should happen naturally. 1736 newattr(unit.dwinfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir) 1737 producerExtra := ctxt.Syms.Lookup(dwarf.CUInfoPrefix+"producer."+unit.lib.Pkg, 0) 1738 producer := "Go cmd/compile " + objabi.Version 1739 if len(producerExtra.P) > 0 { 1740 // We put a semicolon before the flags to clearly 1741 // separate them from the version, which can be long 1742 // and have lots of weird things in it in development 1743 // versions. We promise not to put a semicolon in the 1744 // version, so it should be safe for readers to scan 1745 // forward to the semicolon. 1746 producer += "; " + string(producerExtra.P) 1747 } 1748 newattr(unit.dwinfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer) 1749 1750 if len(lib.Textp) == 0 { 1751 unit.dwinfo.Abbrev = dwarf.DW_ABRV_COMPUNIT_TEXTLESS 1752 } 1753 1754 // Scan all functions in this compilation unit, create DIEs for all 1755 // referenced types, create the file table for debug_line, find all 1756 // referenced abstract functions. 1757 // Collect all debug_range symbols in unit.rangeSyms 1758 for _, s := range lib.Textp { // textp has been dead-code-eliminated already. 1759 dsym := ctxt.Syms.ROLookup(dwarf.InfoPrefix+s.Name, int(s.Version)) 1760 dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable 1761 dsym.Type = sym.SDWARFINFO 1762 unit.funcDIEs = append(unit.funcDIEs, dsym) 1763 1764 rangeSym := ctxt.Syms.ROLookup(dwarf.RangePrefix+s.Name, int(s.Version)) 1765 if rangeSym != nil && rangeSym.Size > 0 { 1766 rangeSym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable 1767 rangeSym.Type = sym.SDWARFRANGE 1768 // LLVM doesn't support base address entries. Strip them out so LLDB and dsymutil don't get confused. 1769 if ctxt.HeadType == objabi.Hdarwin { 1770 removeDwarfAddrListBaseAddress(ctxt, dsym, rangeSym, false) 1771 } 1772 unit.rangeSyms = append(unit.rangeSyms, rangeSym) 1773 } 1774 1775 for ri := 0; ri < len(dsym.R); ri++ { 1776 r := &dsym.R[ri] 1777 if r.Type == objabi.R_DWARFSECREF { 1778 rsym := r.Sym 1779 if strings.HasPrefix(rsym.Name, dwarf.InfoPrefix) && strings.HasSuffix(rsym.Name, dwarf.AbstractFuncSuffix) && !rsym.Attr.OnList() { 1780 // abstract function 1781 rsym.Attr |= sym.AttrOnList 1782 unit.absFnDIEs = append(unit.absFnDIEs, rsym) 1783 importInfoSymbol(ctxt, rsym) 1784 } else if rsym.Size == 0 { 1785 // a type we do not have a DIE for 1786 n := nameFromDIESym(rsym) 1787 defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0)) 1788 } 1789 } 1790 } 1791 } 1792 } 1793 1794 // Create DIEs for global variables and the types they use. 1795 genasmsym(ctxt, defdwsymb) 1796 1797 synthesizestringtypes(ctxt, dwtypes.Child) 1798 synthesizeslicetypes(ctxt, dwtypes.Child) 1799 synthesizemaptypes(ctxt, dwtypes.Child) 1800 synthesizechantypes(ctxt, dwtypes.Child) 1801 } 1802 1803 // dwarfGenerateDebugSyms constructs debug_line, debug_frame, debug_loc, 1804 // debug_pubnames and debug_pubtypes. It also writes out the debug_info 1805 // section using symbols generated in dwarfGenerateDebugInfo. 1806 func dwarfGenerateDebugSyms(ctxt *Link) { 1807 if !dwarfEnabled(ctxt) { 1808 return 1809 } 1810 1811 if ctxt.Debugvlog != 0 { 1812 ctxt.Logf("%5.2f dwarf\n", Cputime()) 1813 } 1814 1815 abbrev := writeabbrev(ctxt) 1816 syms := []*sym.Symbol{abbrev} 1817 1818 calcCompUnitRanges(ctxt) 1819 sort.Sort(compilationUnitByStartPC(ctxt.compUnits)) 1820 1821 // Write per-package line and range tables and start their CU DIEs. 1822 debugLine := ctxt.Syms.Lookup(".debug_line", 0) 1823 debugLine.Type = sym.SDWARFSECT 1824 debugRanges := ctxt.Syms.Lookup(".debug_ranges", 0) 1825 debugRanges.Type = sym.SDWARFRANGE 1826 debugRanges.Attr |= sym.AttrReachable 1827 syms = append(syms, debugLine) 1828 for _, u := range ctxt.compUnits { 1829 reversetree(&u.dwinfo.Child) 1830 if u.dwinfo.Abbrev == dwarf.DW_ABRV_COMPUNIT_TEXTLESS { 1831 continue 1832 } 1833 writelines(ctxt, u, debugLine) 1834 writepcranges(ctxt, u.dwinfo, u.lib.Textp[0], u.pcs, debugRanges) 1835 } 1836 1837 // newdie adds DIEs to the *beginning* of the parent's DIE list. 1838 // Now that we're done creating DIEs, reverse the trees so DIEs 1839 // appear in the order they were created. 1840 reversetree(&dwtypes.Child) 1841 movetomodule(ctxt, &dwtypes) 1842 1843 // Need to reorder symbols so sym.SDWARFINFO is after all sym.SDWARFSECT 1844 // (but we need to generate dies before writepub) 1845 infosyms := writeinfo(ctxt, nil, ctxt.compUnits, abbrev) 1846 1847 syms = writeframes(ctxt, syms) 1848 syms = writepub(ctxt, ".debug_pubnames", ispubname, syms) 1849 syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms) 1850 syms = writegdbscript(ctxt, syms) 1851 // Now we're done writing SDWARFSECT symbols, so we can write 1852 // other SDWARF* symbols. 1853 syms = append(syms, infosyms...) 1854 syms = collectlocs(ctxt, syms, ctxt.compUnits) 1855 syms = append(syms, debugRanges) 1856 for _, unit := range ctxt.compUnits { 1857 syms = append(syms, unit.rangeSyms...) 1858 } 1859 dwarfp = syms 1860 } 1861 1862 func collectlocs(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit) []*sym.Symbol { 1863 empty := true 1864 for _, u := range units { 1865 for _, fn := range u.funcDIEs { 1866 for i := range fn.R { 1867 reloc := &fn.R[i] // Copying sym.Reloc has measurable impact on performance 1868 if reloc.Type == objabi.R_DWARFSECREF && strings.HasPrefix(reloc.Sym.Name, dwarf.LocPrefix) { 1869 reloc.Sym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable 1870 syms = append(syms, reloc.Sym) 1871 empty = false 1872 // LLVM doesn't support base address entries. Strip them out so LLDB and dsymutil don't get confused. 1873 if ctxt.HeadType == objabi.Hdarwin { 1874 removeDwarfAddrListBaseAddress(ctxt, fn, reloc.Sym, true) 1875 } 1876 // One location list entry per function, but many relocations to it. Don't duplicate. 1877 break 1878 } 1879 } 1880 } 1881 } 1882 // Don't emit .debug_loc if it's empty -- it makes the ARM linker mad. 1883 if !empty { 1884 locsym := ctxt.Syms.Lookup(".debug_loc", 0) 1885 locsym.Type = sym.SDWARFLOC 1886 locsym.Attr |= sym.AttrReachable 1887 syms = append(syms, locsym) 1888 } 1889 return syms 1890 } 1891 1892 // removeDwarfAddrListBaseAddress removes base address selector entries from 1893 // DWARF location lists and range lists. 1894 func removeDwarfAddrListBaseAddress(ctxt *Link, info, list *sym.Symbol, isloclist bool) { 1895 // The list symbol contains multiple lists, but they're all for the 1896 // same function, and it's not empty. 1897 fn := list.R[0].Sym 1898 1899 // Discard the relocations for the base address entries. 1900 list.R = list.R[:0] 1901 1902 // Add relocations for each location entry's start and end addresses, 1903 // so that the base address entries aren't necessary. 1904 // We could remove them entirely, but that's more work for a relatively 1905 // small size win. If dsymutil runs it'll throw them away anyway. 1906 1907 // relocate adds a CU-relative relocation to fn+addr at offset. 1908 relocate := func(addr uint64, offset int) { 1909 list.R = append(list.R, sym.Reloc{ 1910 Off: int32(offset), 1911 Siz: uint8(ctxt.Arch.PtrSize), 1912 Type: objabi.R_ADDRCUOFF, 1913 Add: int64(addr), 1914 Sym: fn, 1915 }) 1916 } 1917 1918 for i := 0; i < len(list.P); { 1919 first := readPtr(ctxt, list.P[i:]) 1920 second := readPtr(ctxt, list.P[i+ctxt.Arch.PtrSize:]) 1921 1922 if (first == 0 && second == 0) || 1923 first == ^uint64(0) || 1924 (ctxt.Arch.PtrSize == 4 && first == uint64(^uint32(0))) { 1925 // Base address selection entry or end of list. Ignore. 1926 i += ctxt.Arch.PtrSize * 2 1927 continue 1928 } 1929 1930 relocate(first, i) 1931 relocate(second, i+ctxt.Arch.PtrSize) 1932 1933 // Skip past the actual location. 1934 i += ctxt.Arch.PtrSize * 2 1935 if isloclist { 1936 i += 2 + int(ctxt.Arch.ByteOrder.Uint16(list.P[i:])) 1937 } 1938 } 1939 1940 // Rewrite the DIE's relocations to point to the first location entry, 1941 // not the now-useless base address selection entry. 1942 for i := range info.R { 1943 r := &info.R[i] 1944 if r.Sym != list { 1945 continue 1946 } 1947 r.Add += int64(2 * ctxt.Arch.PtrSize) 1948 } 1949 } 1950 1951 // Read a pointer-sized uint from the beginning of buf. 1952 func readPtr(ctxt *Link, buf []byte) uint64 { 1953 switch ctxt.Arch.PtrSize { 1954 case 4: 1955 return uint64(ctxt.Arch.ByteOrder.Uint32(buf)) 1956 case 8: 1957 return ctxt.Arch.ByteOrder.Uint64(buf) 1958 default: 1959 panic("unexpected pointer size") 1960 } 1961 } 1962 1963 /* 1964 * Elf. 1965 */ 1966 func dwarfaddshstrings(ctxt *Link, shstrtab *sym.Symbol) { 1967 if *FlagW { // disable dwarf 1968 return 1969 } 1970 1971 secs := []string{"abbrev", "frame", "info", "loc", "line", "pubnames", "pubtypes", "gdb_scripts", "ranges"} 1972 for _, sec := range secs { 1973 Addstring(shstrtab, ".debug_"+sec) 1974 if ctxt.LinkMode == LinkExternal { 1975 Addstring(shstrtab, elfRelType+".debug_"+sec) 1976 } else { 1977 Addstring(shstrtab, ".zdebug_"+sec) 1978 } 1979 } 1980 } 1981 1982 // Add section symbols for DWARF debug info. This is called before 1983 // dwarfaddelfheaders. 1984 func dwarfaddelfsectionsyms(ctxt *Link) { 1985 if *FlagW { // disable dwarf 1986 return 1987 } 1988 if ctxt.LinkMode != LinkExternal { 1989 return 1990 } 1991 1992 s := ctxt.Syms.Lookup(".debug_info", 0) 1993 putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum) 1994 s = ctxt.Syms.Lookup(".debug_abbrev", 0) 1995 putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum) 1996 s = ctxt.Syms.Lookup(".debug_line", 0) 1997 putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum) 1998 s = ctxt.Syms.Lookup(".debug_frame", 0) 1999 putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum) 2000 s = ctxt.Syms.Lookup(".debug_loc", 0) 2001 if s.Sect != nil { 2002 putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum) 2003 } 2004 s = ctxt.Syms.Lookup(".debug_ranges", 0) 2005 if s.Sect != nil { 2006 putelfsectionsym(ctxt.Out, s, s.Sect.Elfsect.(*ElfShdr).shnum) 2007 } 2008 } 2009 2010 // dwarfcompress compresses the DWARF sections. This must happen after 2011 // relocations are applied. After this, dwarfp will contain a 2012 // different (new) set of symbols, and sections may have been replaced. 2013 func dwarfcompress(ctxt *Link) { 2014 supported := ctxt.IsELF || ctxt.HeadType == objabi.Hwindows || ctxt.HeadType == objabi.Hdarwin 2015 if !ctxt.compressDWARF || !supported || ctxt.LinkMode != LinkInternal { 2016 return 2017 } 2018 2019 var start int 2020 var newDwarfp []*sym.Symbol 2021 Segdwarf.Sections = Segdwarf.Sections[:0] 2022 for i, s := range dwarfp { 2023 // Find the boundaries between sections and compress 2024 // the whole section once we've found the last of its 2025 // symbols. 2026 if i+1 >= len(dwarfp) || s.Sect != dwarfp[i+1].Sect { 2027 s1 := compressSyms(ctxt, dwarfp[start:i+1]) 2028 if s1 == nil { 2029 // Compression didn't help. 2030 newDwarfp = append(newDwarfp, dwarfp[start:i+1]...) 2031 Segdwarf.Sections = append(Segdwarf.Sections, s.Sect) 2032 } else { 2033 compressedSegName := ".zdebug_" + s.Sect.Name[len(".debug_"):] 2034 sect := addsection(ctxt.Arch, &Segdwarf, compressedSegName, 04) 2035 sect.Length = uint64(len(s1)) 2036 newSym := ctxt.Syms.Lookup(compressedSegName, 0) 2037 newSym.P = s1 2038 newSym.Size = int64(len(s1)) 2039 newSym.Sect = sect 2040 newDwarfp = append(newDwarfp, newSym) 2041 } 2042 start = i + 1 2043 } 2044 } 2045 dwarfp = newDwarfp 2046 2047 // Re-compute the locations of the compressed DWARF symbols 2048 // and sections, since the layout of these within the file is 2049 // based on Section.Vaddr and Symbol.Value. 2050 pos := Segdwarf.Vaddr 2051 var prevSect *sym.Section 2052 for _, s := range dwarfp { 2053 s.Value = int64(pos) 2054 if s.Sect != prevSect { 2055 s.Sect.Vaddr = uint64(s.Value) 2056 prevSect = s.Sect 2057 } 2058 if s.Sub != nil { 2059 log.Fatalf("%s: unexpected sub-symbols", s) 2060 } 2061 pos += uint64(s.Size) 2062 if ctxt.HeadType == objabi.Hwindows { 2063 pos = uint64(Rnd(int64(pos), PEFILEALIGN)) 2064 } 2065 2066 } 2067 Segdwarf.Length = pos - Segdwarf.Vaddr 2068 } 2069 2070 type compilationUnitByStartPC []*compilationUnit 2071 2072 func (v compilationUnitByStartPC) Len() int { return len(v) } 2073 func (v compilationUnitByStartPC) Swap(i, j int) { v[i], v[j] = v[j], v[i] } 2074 2075 func (v compilationUnitByStartPC) Less(i, j int) bool { 2076 switch { 2077 case len(v[i].lib.Textp) == 0 && len(v[j].lib.Textp) == 0: 2078 return v[i].lib.Pkg < v[j].lib.Pkg 2079 case len(v[i].lib.Textp) != 0 && len(v[j].lib.Textp) == 0: 2080 return true 2081 case len(v[i].lib.Textp) == 0 && len(v[j].lib.Textp) != 0: 2082 return false 2083 default: 2084 return v[i].lib.Textp[0].Value < v[j].lib.Textp[0].Value 2085 } 2086 } 2087 2088 // On AIX, the symbol table needs to know where are the compilation units parts 2089 // for a specific package in each .dw section. 2090 // dwsectCUSize map will save the size of a compilation unit for 2091 // the corresponding .dw section. 2092 // This size can later be retrieved with the index "sectionName.pkgName". 2093 var dwsectCUSize map[string]uint64 2094 2095 // getDwsectCUSize retrieves the corresponding package size inside the current section. 2096 func getDwsectCUSize(sname string, pkgname string) uint64 { 2097 return dwsectCUSize[sname+"."+pkgname] 2098 } 2099 2100 func saveDwsectCUSize(sname string, pkgname string, size uint64) { 2101 dwsectCUSize[sname+"."+pkgname] = size 2102 } 2103 2104 // getPkgFromCUSym returns the package name for the compilation unit 2105 // represented by s. 2106 // The prefix dwarf.InfoPrefix+".pkg." needs to be removed in order to get 2107 // the package name. 2108 func getPkgFromCUSym(s *sym.Symbol) string { 2109 return strings.TrimPrefix(s.Name, dwarf.InfoPrefix+".pkg.") 2110 }