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