return die
}
-// Define gotype, for composite ones recurse into constituents.
-func defgotype(ctxt *Link, gotype *sym.Symbol) *sym.Symbol {
- if gotype == nil {
- return mustFind(ctxt, "<unspecified>")
- }
-
- if *FlagNewDw {
- panic("should not be called on this path")
- }
-
- if !strings.HasPrefix(gotype.Name, "type.") {
- Errorf(gotype, "dwarf: type name doesn't start with \"type.\"")
- return mustFind(ctxt, "<unspecified>")
- }
-
- name := gotype.Name[5:] // could also decode from Type.string
-
- sdie := find(ctxt, name)
-
- if sdie != nil {
- return sdie
- }
-
- return newtype(ctxt, gotype).Sym.(*sym.Symbol)
-}
-
-func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
- name := gotype.Name[5:] // could also decode from Type.string
- kind := decodetypeKind(ctxt.Arch, gotype.P)
- bytesize := decodetypeSize(ctxt.Arch, gotype.P)
-
- if *FlagNewDw {
- panic("should not be called on this path")
- }
-
- var die, typedefdie *dwarf.DWDie
- switch kind {
- case objabi.KindBool:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
- newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_boolean, 0)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
- case objabi.KindInt,
- objabi.KindInt8,
- objabi.KindInt16,
- objabi.KindInt32,
- objabi.KindInt64:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
- newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_signed, 0)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
- case objabi.KindUint,
- objabi.KindUint8,
- objabi.KindUint16,
- objabi.KindUint32,
- objabi.KindUint64,
- objabi.KindUintptr:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
- newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
- case objabi.KindFloat32,
- objabi.KindFloat64:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
- newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_float, 0)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
- case objabi.KindComplex64,
- objabi.KindComplex128:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
- newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_complex_float, 0)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
- case objabi.KindArray:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_ARRAYTYPE, name, 0)
- typedefdie = dotypedef(ctxt, &dwtypes, name, die)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
- s := decodetypeArrayElem(ctxt.Arch, gotype)
- newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
- fld := newdie(ctxt, die, dwarf.DW_ABRV_ARRAYRANGE, "range", 0)
-
- // use actual length not upper bound; correct for 0-length arrays.
- newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, decodetypeArrayLen(ctxt.Arch, gotype), 0)
-
- newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
-
- case objabi.KindChan:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_CHANTYPE, name, 0)
- s := decodetypeChanElem(ctxt.Arch, gotype)
- newrefattr(die, dwarf.DW_AT_go_elem, defgotype(ctxt, s))
- // Save elem type for synthesizechantypes. We could synthesize here
- // but that would change the order of DIEs we output.
- newrefattr(die, dwarf.DW_AT_type, s)
-
- case objabi.KindFunc:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_FUNCTYPE, name, 0)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
- typedefdie = dotypedef(ctxt, &dwtypes, name, die)
- nfields := decodetypeFuncInCount(ctxt.Arch, gotype.P)
- for i := 0; i < nfields; i++ {
- s := decodetypeFuncInType(ctxt.Arch, gotype, i)
- fld := newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0)
- newrefattr(fld, dwarf.DW_AT_type, defgotype(ctxt, s))
- }
-
- if decodetypeFuncDotdotdot(ctxt.Arch, gotype.P) {
- newdie(ctxt, die, dwarf.DW_ABRV_DOTDOTDOT, "...", 0)
- }
- nfields = decodetypeFuncOutCount(ctxt.Arch, gotype.P)
- for i := 0; i < nfields; i++ {
- s := decodetypeFuncOutType(ctxt.Arch, gotype, i)
- fld := newdie(ctxt, die, dwarf.DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0)
- newrefattr(fld, dwarf.DW_AT_type, defptrto(ctxt, defgotype(ctxt, s)))
- }
-
- case objabi.KindInterface:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_IFACETYPE, name, 0)
- typedefdie = dotypedef(ctxt, &dwtypes, name, die)
- nfields := int(decodetypeIfaceMethodCount(ctxt.Arch, gotype.P))
- var s *sym.Symbol
- if nfields == 0 {
- s = lookupOrDiag(ctxt, "type.runtime.eface")
- } else {
- s = lookupOrDiag(ctxt, "type.runtime.iface")
- }
- newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
-
- case objabi.KindMap:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_MAPTYPE, name, 0)
- s := decodetypeMapKey(ctxt.Arch, gotype)
- newrefattr(die, dwarf.DW_AT_go_key, defgotype(ctxt, s))
- s = decodetypeMapValue(ctxt.Arch, gotype)
- newrefattr(die, dwarf.DW_AT_go_elem, defgotype(ctxt, s))
- // Save gotype for use in synthesizemaptypes. We could synthesize here,
- // but that would change the order of the DIEs.
- newrefattr(die, dwarf.DW_AT_type, gotype)
-
- case objabi.KindPtr:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_PTRTYPE, name, 0)
- typedefdie = dotypedef(ctxt, &dwtypes, name, die)
- s := decodetypePtrElem(ctxt.Arch, gotype)
- newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
-
- case objabi.KindSlice:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_SLICETYPE, name, 0)
- typedefdie = dotypedef(ctxt, &dwtypes, name, die)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
- s := decodetypeArrayElem(ctxt.Arch, gotype)
- elem := defgotype(ctxt, s)
- newrefattr(die, dwarf.DW_AT_go_elem, elem)
-
- case objabi.KindString:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRINGTYPE, name, 0)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
-
- case objabi.KindStruct:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRUCTTYPE, name, 0)
- typedefdie = dotypedef(ctxt, &dwtypes, name, die)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
- nfields := decodetypeStructFieldCount(ctxt.Arch, gotype)
- for i := 0; i < nfields; i++ {
- f := decodetypeStructFieldName(ctxt.Arch, gotype, i)
- s := decodetypeStructFieldType(ctxt.Arch, gotype, i)
- if f == "" {
- f = s.Name[5:] // skip "type."
- }
- fld := newdie(ctxt, die, dwarf.DW_ABRV_STRUCTFIELD, f, 0)
- newrefattr(fld, dwarf.DW_AT_type, defgotype(ctxt, s))
- offsetAnon := decodetypeStructFieldOffsAnon(ctxt.Arch, gotype, i)
- newmemberoffsetattr(fld, int32(offsetAnon>>1))
- if offsetAnon&1 != 0 { // is embedded field
- newattr(fld, dwarf.DW_AT_go_embedded_field, dwarf.DW_CLS_FLAG, 1, 0)
- }
- }
-
- case objabi.KindUnsafePointer:
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, name, 0)
-
- default:
- Errorf(gotype, "dwarf: definition of unknown kind %d", kind)
- die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_TYPEDECL, name, 0)
- newrefattr(die, dwarf.DW_AT_type, mustFind(ctxt, "<unspecified>"))
- }
-
- newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(kind), 0)
- if gotype.Attr.Reachable() {
- newattr(die, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, gotype)
- }
-
- if _, ok := prototypedies[gotype.Name]; ok {
- prototypedies[gotype.Name] = die
- }
-
- if typedefdie != nil {
- return typedefdie
- }
- return die
-}
-
func nameFromDIESym(dwtype *sym.Symbol) string {
return strings.TrimSuffix(dwtype.Name[len(dwarf.InfoPrefix):], "..def")
}
}
}
-func findprotodie(ctxt *Link, name string) *dwarf.DWDie {
- die, ok := prototypedies[name]
- if ok && die == nil {
- defgotype(ctxt, lookupOrDiag(ctxt, name))
- die = prototypedies[name]
- }
- return die
-}
-
-func synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) {
- prototype := walktypedef(findprotodie(ctxt, "type.runtime.stringStructDWARF"))
- if prototype == nil {
- return
- }
-
- for ; die != nil; die = die.Link {
- if die.Abbrev != dwarf.DW_ABRV_STRINGTYPE {
- continue
- }
- copychildren(ctxt, die, prototype)
- }
-}
-
-func synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) {
- prototype := walktypedef(findprotodie(ctxt, "type.runtime.slice"))
- if prototype == nil {
- return
- }
-
- for ; die != nil; die = die.Link {
- if die.Abbrev != dwarf.DW_ABRV_SLICETYPE {
- continue
- }
- copychildren(ctxt, die, prototype)
- elem := getattr(die, dwarf.DW_AT_go_elem).Data.(*sym.Symbol)
- substitutetype(die, "array", defptrto(ctxt, elem))
- }
-}
-
-// synthesizemaptypes is way too closely married to runtime/hashmap.c
-
-func mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valname string, f func(*dwarf.DWDie)) *sym.Symbol {
- name := mkinternaltypename(typename, keyname, valname)
- symname := dwarf.InfoPrefix + name
- s := ctxt.Syms.ROLookup(symname, 0)
- if s != nil && s.Type == sym.SDWARFINFO {
- return s
- }
- die := newdie(ctxt, &dwtypes, abbrev, name, 0)
- f(die)
- return dtolsym(die.Sym)
-}
-
-func synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
- hash := walktypedef(findprotodie(ctxt, "type.runtime.hmap"))
- bucket := walktypedef(findprotodie(ctxt, "type.runtime.bmap"))
-
- if hash == nil {
- return
- }
-
- for ; die != nil; die = die.Link {
- if die.Abbrev != dwarf.DW_ABRV_MAPTYPE {
- continue
- }
- gotype := getattr(die, dwarf.DW_AT_type).Data.(*sym.Symbol)
- keytype := decodetypeMapKey(ctxt.Arch, gotype)
- valtype := decodetypeMapValue(ctxt.Arch, gotype)
- keysize, valsize := decodetypeSize(ctxt.Arch, keytype.P), decodetypeSize(ctxt.Arch, valtype.P)
- keytype, valtype = walksymtypedef(ctxt, defgotype(ctxt, keytype)), walksymtypedef(ctxt, defgotype(ctxt, valtype))
-
- // compute size info like hashmap.c does.
- indirectKey, indirectVal := false, false
- if keysize > MaxKeySize {
- keysize = int64(ctxt.Arch.PtrSize)
- indirectKey = true
- }
- if valsize > MaxValSize {
- valsize = int64(ctxt.Arch.PtrSize)
- indirectVal = true
- }
-
- // Construct type to represent an array of BucketSize keys
- keyname := nameFromDIESym(keytype)
- dwhks := mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) {
- newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*keysize, 0)
- t := keytype
- if indirectKey {
- t = defptrto(ctxt, keytype)
- }
- newrefattr(dwhk, dwarf.DW_AT_type, t)
- fld := newdie(ctxt, dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size", 0)
- newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0)
- newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
- })
-
- // Construct type to represent an array of BucketSize values
- valname := nameFromDIESym(valtype)
- dwhvs := mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) {
- newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize*valsize, 0)
- t := valtype
- if indirectVal {
- t = defptrto(ctxt, valtype)
- }
- newrefattr(dwhv, dwarf.DW_AT_type, t)
- fld := newdie(ctxt, dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size", 0)
- newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0)
- newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
- })
-
- // Construct bucket<K,V>
- dwhbs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *dwarf.DWDie) {
- // Copy over all fields except the field "data" from the generic
- // bucket. "data" will be replaced with keys/values below.
- copychildrenexcept(ctxt, dwhb, bucket, findchild(bucket, "data"))
-
- fld := newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys", 0)
- newrefattr(fld, dwarf.DW_AT_type, dwhks)
- newmemberoffsetattr(fld, BucketSize)
- fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values", 0)
- newrefattr(fld, dwarf.DW_AT_type, dwhvs)
- newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize))
- fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow", 0)
- newrefattr(fld, dwarf.DW_AT_type, defptrto(ctxt, dtolsym(dwhb.Sym)))
- newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize)))
- if ctxt.Arch.RegSize > ctxt.Arch.PtrSize {
- fld = newdie(ctxt, dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad", 0)
- newrefattr(fld, dwarf.DW_AT_type, mustFind(ctxt, "uintptr"))
- newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(ctxt.Arch.PtrSize))
- }
-
- newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, BucketSize+BucketSize*keysize+BucketSize*valsize+int64(ctxt.Arch.RegSize), 0)
- })
-
- // Construct hash<K,V>
- dwhs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *dwarf.DWDie) {
- copychildren(ctxt, dwh, hash)
- substitutetype(dwh, "buckets", defptrto(ctxt, dwhbs))
- substitutetype(dwh, "oldbuckets", defptrto(ctxt, dwhbs))
- newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hash, dwarf.DW_AT_byte_size).Value, nil)
- })
-
- // make map type a pointer to hash<K,V>
- newrefattr(die, dwarf.DW_AT_type, defptrto(ctxt, dwhs))
- }
-}
-
-func synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
- sudog := walktypedef(findprotodie(ctxt, "type.runtime.sudog"))
- waitq := walktypedef(findprotodie(ctxt, "type.runtime.waitq"))
- hchan := walktypedef(findprotodie(ctxt, "type.runtime.hchan"))
- if sudog == nil || waitq == nil || hchan == nil {
- return
- }
-
- sudogsize := int(getattr(sudog, dwarf.DW_AT_byte_size).Value)
-
- for ; die != nil; die = die.Link {
- if die.Abbrev != dwarf.DW_ABRV_CHANTYPE {
- continue
- }
- elemgotype := getattr(die, dwarf.DW_AT_type).Data.(*sym.Symbol)
- elemname := elemgotype.Name[5:]
- elemtype := walksymtypedef(ctxt, defgotype(ctxt, elemgotype))
-
- // sudog<T>
- dwss := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "sudog", elemname, "", func(dws *dwarf.DWDie) {
- copychildren(ctxt, dws, sudog)
- substitutetype(dws, "elem", defptrto(ctxt, elemtype))
- newattr(dws, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(sudogsize), nil)
- })
-
- // waitq<T>
- dwws := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "waitq", elemname, "", func(dww *dwarf.DWDie) {
-
- copychildren(ctxt, dww, waitq)
- substitutetype(dww, "first", defptrto(ctxt, dwss))
- substitutetype(dww, "last", defptrto(ctxt, dwss))
- newattr(dww, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(waitq, dwarf.DW_AT_byte_size).Value, nil)
- })
-
- // hchan<T>
- dwhs := mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hchan", elemname, "", func(dwh *dwarf.DWDie) {
- copychildren(ctxt, dwh, hchan)
- substitutetype(dwh, "recvq", dwws)
- substitutetype(dwh, "sendq", dwws)
- newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hchan, dwarf.DW_AT_byte_size).Value, nil)
- })
-
- newrefattr(die, dwarf.DW_AT_type, defptrto(ctxt, dwhs))
- }
-}
-
-func dwarfDefineGlobal(ctxt *Link, s *sym.Symbol, str string, v int64, gotype *sym.Symbol) {
- // Find a suitable CU DIE to include the global.
- // One would think it's as simple as just looking at the unit, but that might
- // not have any reachable code. So, we go to the runtime's CU if our unit
- // isn't otherwise reachable.
- var unit *sym.CompilationUnit
- if s.Unit != nil {
- unit = s.Unit
- } else {
- unit = ctxt.runtimeCU
- }
- dv := newdie(ctxt, unit.DWInfo, dwarf.DW_ABRV_VARIABLE, str, int(s.Version))
- newabslocexprattr(dv, v, s)
- if !s.IsFileLocal() {
- newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
- }
- dt := defgotype(ctxt, gotype)
- newrefattr(dv, dwarf.DW_AT_type, dt)
-}
-
-// For use with pass.c::genasmsym
-func defdwsymb(ctxt *Link, s *sym.Symbol, str string, t SymbolType, v int64, gotype *sym.Symbol) {
- if strings.HasPrefix(str, "go.string.") {
- return
- }
- if strings.HasPrefix(str, "runtime.gcbits.") {
- return
- }
-
- switch t {
- case DataSym, BSSSym:
- switch s.Type {
- case sym.SDATA, sym.SNOPTRDATA, sym.STYPE, sym.SBSS, sym.SNOPTRBSS, sym.STLSBSS:
- // ok
- case sym.SRODATA:
- if gotype != nil {
- defgotype(ctxt, gotype)
- }
- return
- default:
- return
- }
- if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) {
- return
- }
- dwarfDefineGlobal(ctxt, s, str, v, gotype)
-
- case AutoSym, ParamSym, DeletedAutoSym:
- defgotype(ctxt, gotype)
- }
-}
-
// createUnitLength creates the initial length field with value v and update
// offset of unit_length if needed.
func createUnitLength(ctxt *Link, s *sym.Symbol, v uint64) {
}
}
-func importInfoSymbol(ctxt *Link, dsym *sym.Symbol) {
- dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable
- dsym.Type = sym.SDWARFINFO
- for i := range dsym.R {
- r := &dsym.R[i] // Copying sym.Reloc has measurable impact on performance
- if r.Type == objabi.R_DWARFSECREF && r.Sym.Size == 0 {
- n := nameFromDIESym(r.Sym)
- defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0))
- }
- }
-}
-
func writelines(ctxt *Link, unit *sym.CompilationUnit, ls *sym.Symbol) {
var dwarfctxt dwarf.Context = dwctxt{ctxt}
return syms
}
-// dwarfGenerateDebugInfo generated debug info entries for all types,
-// variables and functions in the program.
-// Along with dwarfGenerateDebugSyms they are the two main entry points into
-// dwarf generation: dwarfGenerateDebugInfo does all the work that should be
-// done before symbol names are mangled while dwarfgeneratedebugsyms does
-// all the work that can only be done after addresses have been assigned to
-// text symbols.
-func dwarfGenerateDebugInfo(ctxt *Link) {
- if !dwarfEnabled(ctxt) {
- return
- }
- if *FlagNewDw {
- dwarfGenerateDebugInfo2(ctxt)
- return
- }
-
- if ctxt.HeadType == objabi.Haix {
- // Initial map used to store package size for each DWARF section.
- dwsectCUSize = make(map[string]uint64)
- }
-
- // Forctxt.Diagnostic messages.
- newattr(&dwtypes, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len("dwtypes")), "dwtypes")
-
- // Some types that must exist to define other ones.
- newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "<unspecified>", 0)
-
- newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "void", 0)
- newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer", 0)
-
- die := newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, "uintptr", 0) // needed for array size
- newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
- newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(ctxt.Arch.PtrSize), 0)
- newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, objabi.KindUintptr, 0)
- newattr(die, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_ADDRESS, 0, lookupOrDiag(ctxt, "type.uintptr"))
-
- // Prototypes needed for type synthesis.
- prototypedies = map[string]*dwarf.DWDie{
- "type.runtime.stringStructDWARF": nil,
- "type.runtime.slice": nil,
- "type.runtime.hmap": nil,
- "type.runtime.bmap": nil,
- "type.runtime.sudog": nil,
- "type.runtime.waitq": nil,
- "type.runtime.hchan": nil,
- }
-
- // Needed by the prettyprinter code for interface inspection.
- for _, typ := range []string{
- "type.runtime._type",
- "type.runtime.arraytype",
- "type.runtime.chantype",
- "type.runtime.functype",
- "type.runtime.maptype",
- "type.runtime.ptrtype",
- "type.runtime.slicetype",
- "type.runtime.structtype",
- "type.runtime.interfacetype",
- "type.runtime.itab",
- "type.runtime.imethod"} {
- defgotype(ctxt, lookupOrDiag(ctxt, typ))
- }
-
- // fake root DIE for compile unit DIEs
- var dwroot dwarf.DWDie
- flagVariants := make(map[string]bool)
-
- for _, lib := range ctxt.Library {
- consts := ctxt.Syms.ROLookup(dwarf.ConstInfoPrefix+lib.Pkg, 0)
- for _, unit := range lib.Units {
- // We drop the constants into the first CU.
- if consts != nil {
- importInfoSymbol(ctxt, consts)
- unit.Consts = consts
- consts = nil
- }
-
- ctxt.compUnits = append(ctxt.compUnits, unit)
-
- // We need at least one runtime unit.
- if unit.Lib.Pkg == "runtime" {
- ctxt.runtimeCU = unit
- }
-
- unit.DWInfo = newdie(ctxt, &dwroot, dwarf.DW_ABRV_COMPUNIT, unit.Lib.Pkg, 0)
- newattr(unit.DWInfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(dwarf.DW_LANG_Go), 0)
- // OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
- compDir := getCompilationDir()
- // TODO: Make this be the actual compilation directory, not
- // the linker directory. If we move CU construction into the
- // compiler, this should happen naturally.
- newattr(unit.DWInfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir)
- producerExtra := ctxt.Syms.Lookup(dwarf.CUInfoPrefix+"producer."+unit.Lib.Pkg, 0)
- producer := "Go cmd/compile " + objabi.Version
- if len(producerExtra.P) > 0 {
- // We put a semicolon before the flags to clearly
- // separate them from the version, which can be long
- // and have lots of weird things in it in development
- // versions. We promise not to put a semicolon in the
- // version, so it should be safe for readers to scan
- // forward to the semicolon.
- producer += "; " + string(producerExtra.P)
- flagVariants[string(producerExtra.P)] = true
- } else {
- flagVariants[""] = true
- }
-
- newattr(unit.DWInfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer)
-
- var pkgname string
- if s := ctxt.Syms.ROLookup(dwarf.CUInfoPrefix+"packagename."+unit.Lib.Pkg, 0); s != nil {
- pkgname = string(s.P)
- }
- newattr(unit.DWInfo, dwarf.DW_AT_go_package_name, dwarf.DW_CLS_STRING, int64(len(pkgname)), pkgname)
-
- if len(unit.Textp) == 0 {
- unit.DWInfo.Abbrev = dwarf.DW_ABRV_COMPUNIT_TEXTLESS
- }
-
- // Scan all functions in this compilation unit, create DIEs for all
- // referenced types, create the file table for debug_line, find all
- // referenced abstract functions.
- // Collect all debug_range symbols in unit.rangeSyms
- for _, s := range unit.Textp { // textp has been dead-code-eliminated already.
- dsym := dwarfFuncSym(ctxt, s, dwarf.InfoPrefix, false)
- dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable
- dsym.Type = sym.SDWARFINFO
- unit.FuncDIEs = append(unit.FuncDIEs, dsym)
-
- rangeSym := dwarfFuncSym(ctxt, s, dwarf.RangePrefix, false)
- if rangeSym != nil && rangeSym.Size > 0 {
- rangeSym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
- rangeSym.Type = sym.SDWARFRANGE
- if ctxt.HeadType == objabi.Haix {
- addDwsectCUSize(".debug_ranges", unit.Lib.Pkg, uint64(rangeSym.Size))
- }
- unit.RangeSyms = append(unit.RangeSyms, rangeSym)
- }
-
- for ri := 0; ri < len(dsym.R); ri++ {
- r := &dsym.R[ri]
- if r.Type == objabi.R_DWARFSECREF {
- rsym := r.Sym
- if strings.HasPrefix(rsym.Name, dwarf.InfoPrefix) && strings.HasSuffix(rsym.Name, dwarf.AbstractFuncSuffix) && !rsym.Attr.OnList() {
- // abstract function
- rsym.Attr |= sym.AttrOnList
- unit.AbsFnDIEs = append(unit.AbsFnDIEs, rsym)
- importInfoSymbol(ctxt, rsym)
- } else if rsym.Size == 0 {
- // a type we do not have a DIE for
- n := nameFromDIESym(rsym)
- defgotype(ctxt, ctxt.Syms.Lookup("type."+n, 0))
- }
- }
- }
- }
- }
- }
-
- // Fix for 31034: if the objects feeding into this link were compiled
- // with different sets of flags, then don't issue an error if
- // the -strictdups checks fail.
- if checkStrictDups > 1 && len(flagVariants) > 1 {
- checkStrictDups = 1
- }
-
- // Create DIEs for global variables and the types they use.
- genasmsym(ctxt, defdwsymb)
-
- // Create DIEs for variable types indirectly referenced by function
- // autos (which may not appear directly as param/var DIEs).
- for _, lib := range ctxt.Library {
- for _, unit := range lib.Units {
- lists := [][]*sym.Symbol{unit.AbsFnDIEs, unit.FuncDIEs}
- for _, list := range lists {
- for _, s := range list {
- for i := 0; i < len(s.R); i++ {
- r := &s.R[i]
- if r.Type == objabi.R_USETYPE {
- defgotype(ctxt, r.Sym)
- }
- }
- }
- }
- }
- }
-
- synthesizestringtypes(ctxt, dwtypes.Child)
- synthesizeslicetypes(ctxt, dwtypes.Child)
- synthesizemaptypes(ctxt, dwtypes.Child)
- synthesizechantypes(ctxt, dwtypes.Child)
-}
-
// dwarfGenerateDebugSyms constructs debug_line, debug_frame, debug_loc,
// debug_pubnames and debug_pubtypes. It also writes out the debug_info
// section using symbols generated in dwarfGenerateDebugInfo.