AddAddress(s Sym, t interface{}, ofs int64)
AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
AddString(s Sym, v string)
+ AddFileRef(s Sym, f interface{})
}
// AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding.
{DW_AT_low_pc, DW_FORM_addr},
{DW_AT_high_pc, DW_FORM_addr},
{DW_AT_frame_base, DW_FORM_block1},
+ {DW_AT_decl_file, DW_FORM_data4},
{DW_AT_external, DW_FORM_flag},
},
},
// PutFunc writes a DIE for a function to s.
// It also writes child DIEs for each variable in vars.
-func PutFunc(ctxt Context, info, loc, ranges Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error {
+func PutFunc(ctxt Context, info, loc, ranges, filesym Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error {
Uleb128put(ctxt, info, DW_ABRV_FUNCTION)
putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, 0, startPC)
putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, size, startPC)
putattr(ctxt, info, DW_ABRV_FUNCTION, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
+ // DW_AT_decl_file attribute
+ ctxt.AddFileRef(info, filesym)
var ev int64
if external {
ev = 1
rsym := t.(*LSym)
ls.WriteAddr(c.Link, ls.Size, size, rsym, ofs)
r := &ls.R[len(ls.R)-1]
- r.Type = objabi.R_DWARFREF
+ r.Type = objabi.R_DWARFSECREF
+}
+func (c dwCtxt) AddFileRef(s dwarf.Sym, f interface{}) {
+ ls := s.(*LSym)
+ rsym := f.(*LSym)
+ ls.WriteAddr(c.Link, ls.Size, 4, rsym, 0)
+ r := &ls.R[len(ls.R)-1]
+ r.Type = objabi.R_DWARFFILEREF
}
// dwarfSym returns the DWARF symbols for TEXT symbol.
return s.Size
}
+// fileSymbol returns a symbol corresponding to the source file of the
+// first instruction (prog) of the specified function. This will
+// presumably be the file in which the function is defined.
+func (ctxt *Link) fileSymbol(fn *LSym) *LSym {
+ p := fn.Func.Text
+ if p != nil {
+ f, _ := linkgetlineFromPos(ctxt, p.Pos)
+ fsym := ctxt.Lookup(f)
+ return fsym
+ }
+ return nil
+}
+
// populateDWARF fills in the DWARF Debugging Information Entries for TEXT symbol s.
// The DWARFs symbol must already have been initialized in InitTextSym.
func (ctxt *Link) populateDWARF(curfn interface{}, s *LSym) {
if ctxt.DebugInfo != nil {
scopes = ctxt.DebugInfo(s, curfn)
}
- err := dwarf.PutFunc(dwCtxt{ctxt}, info, loc, ranges, s.Name, !s.Static(), s, s.Size, scopes)
+
+ fs := ctxt.fileSymbol(s)
+ err := dwarf.PutFunc(dwCtxt{ctxt}, info, loc, ranges, fs, s.Name, !s.Static(), s, s.Size, scopes)
if err != nil {
ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
}
// of a JMP instruction, by encoding the address into the instruction.
// The stack nosplit check ignores this since it is not a function call.
R_JMPMIPS
- // R_DWARFREF resolves to the offset of the symbol from its section.
- R_DWARFREF
+
+ // R_DWARFSECREF resolves to the offset of the symbol from its section.
+ // Target of relocation must be size 4 (in current implementation).
+ R_DWARFSECREF
+
+ // R_DWARFFILEREF resolves to an index into the DWARF .debug_line
+ // file table for the specified file symbol. Must be applied to an
+ // attribute of form DW_FORM_data4.
+ R_DWARFFILEREF
// Platform dependent relocations. Architectures with fixed width instructions
// have the inherent issue that a 32-bit (or 64-bit!) displacement cannot be
import "fmt"
-const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLS"
+const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLS"
-var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 129, 136, 144, 152, 160, 166, 172, 178, 188, 197, 208, 219, 229, 238, 248, 262, 276, 292, 306, 320, 331, 345, 360, 377, 395, 416, 426, 437, 450}
+var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 129, 136, 144, 152, 160, 166, 172, 178, 188, 197, 208, 219, 229, 238, 251, 265, 279, 293, 309, 323, 337, 348, 362, 377, 394, 412, 433, 443, 454, 467}
func (i RelocType) String() string {
i -= 1
default:
return false
- case objabi.R_DWARFREF:
+ case objabi.R_DWARFSECREF:
v = ld.IMAGE_REL_AMD64_SECREL
case objabi.R_ADDR:
func relocsym(ctxt *Link, s *sym.Symbol) {
for ri := int32(0); ri < int32(len(s.R)); ri++ {
r := &s.R[ri]
+ if r.Done {
+ // Relocation already processed by an earlier phase.
+ continue
+ }
r.Done = true
off := r.Off
siz := int32(r.Siz)
if r.Siz == 0 { // informational relocation - no work to do
continue
}
+ if r.Type == objabi.R_DWARFFILEREF {
+ // These should have been processed previously during
+ // line table writing.
+ Errorf(s, "orphan R_DWARFFILEREF reloc to %v", r.Sym.Name)
+ continue
+ }
// We need to be able to reference dynimport symbols when linking against
// shared libraries, and Solaris needs it always
Errorf(s, "non-pc-relative relocation address for %s is too big: %#x (%#x + %#x)", r.Sym.Name, uint64(o), Symaddr(r.Sym), r.Add)
errorexit()
}
- case objabi.R_DWARFREF:
+ case objabi.R_DWARFSECREF:
if r.Sym.Sect == nil {
Errorf(s, "missing DWARF section for relocation target %s", r.Sym.Name)
}
}
// PE code emits IMAGE_REL_I386_SECREL and IMAGE_REL_AMD64_SECREL
- // for R_DWARFREF relocations, while R_ADDR is replaced with
+ // for R_DWARFSECREF relocations, while R_ADDR is replaced with
// IMAGE_REL_I386_DIR32, IMAGE_REL_AMD64_ADDR64 and IMAGE_REL_AMD64_ADDR32.
- // Do not replace R_DWARFREF with R_ADDR for windows -
+ // Do not replace R_DWARFSECREF with R_ADDR for windows -
// let PE code emit correct relocations.
if ctxt.HeadType != objabi.Hwindows {
r.Type = objabi.R_ADDR
ls.AddAddrPlus4(t.(*sym.Symbol), 0)
}
r := &ls.R[len(ls.R)-1]
- r.Type = objabi.R_DWARFREF
+ r.Type = objabi.R_DWARFSECREF
r.Add = ofs
}
+func (c dwctxt) AddFileRef(s dwarf.Sym, f interface{}) {
+ panic("should be used only in the compiler")
+}
+
var gdbscript string
var dwarfp []*sym.Symbol
result = s.AddAddrPlus4(t, 0)
}
r := &s.R[len(s.R)-1]
- r.Type = objabi.R_DWARFREF
+ r.Type = objabi.R_DWARFSECREF
return result
}
dsym.Attr |= sym.AttrNotInSymbolTable | sym.AttrReachable
dsym.Type = sym.SDWARFINFO
for _, r := range dsym.R {
- if r.Type == objabi.R_DWARFREF && r.Sym.Size == 0 {
+ if r.Type == objabi.R_DWARFSECREF && r.Sym.Size == 0 {
if ctxt.BuildMode == BuildModeShared {
// These type symbols may not be present in BuildModeShared. Skip.
continue
ls.SetUint32(ctxt.Arch, unitLengthOffset, uint32(ls.Size-unitstart))
ls.SetUint32(ctxt.Arch, headerLengthOffset, uint32(headerend-headerstart))
+ // Apply any R_DWARFFILEREF relocations, since we now know the
+ // line table file indices for this compilation unit. Note that
+ // this loop visits only subprogram DIEs: if the compiler is
+ // changed to generate DW_AT_decl_file attributes for other
+ // DIE flavors (ex: variables) then those DIEs would need to
+ // be included below.
+ for fidx := 0; fidx < len(funcs); fidx++ {
+ f := funcs[fidx]
+ for ri := 0; ri < len(f.R); ri++ {
+ r := &f.R[ri]
+ if r.Type != objabi.R_DWARFFILEREF {
+ continue
+ }
+ // Mark relocation as applied (signal to relocsym)
+ r.Done = true
+ idx, ok := fileNums[int(r.Sym.Value)]
+ if ok {
+ if int(int32(idx)) != idx {
+ Errorf(f, "bad R_DWARFFILEREF relocation: file index overflow")
+ }
+ if r.Siz != 4 {
+ Errorf(f, "bad R_DWARFFILEREF relocation: has size %d, expected 4", r.Siz)
+ }
+ if r.Off < 0 || r.Off+4 > int32(len(f.P)) {
+ Errorf(f, "bad R_DWARFFILEREF relocation offset %d + 4 would write past length %d", r.Off, len(s.P))
+ continue
+ }
+ ctxt.Arch.ByteOrder.PutUint32(f.P[r.Off:r.Off+4], uint32(idx))
+ } else {
+ Errorf(f, "R_DWARFFILEREF relocation file missing: %v", r.Sym)
+ }
+ }
+ }
+
return dwinfo, funcs
}
for _, u := range units {
for _, fn := range u.funcDIEs {
for _, reloc := range fn.R {
- if reloc.Type == objabi.R_DWARFREF && strings.HasPrefix(reloc.Sym.Name, dwarf.LocPrefix) {
+ if reloc.Type == objabi.R_DWARFSECREF && strings.HasPrefix(reloc.Sym.Name, dwarf.LocPrefix) {
reloc.Sym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable
syms = append(syms, reloc.Sym)
empty = false
}
}
-func TestVarDeclCoords(t *testing.T) {
+func TestVarDeclCoordsAndSubrogramDeclFile(t *testing.T) {
testenv.MustHaveGoBuild(t)
if runtime.GOOS == "plan9" {
rdr := d.Reader()
var iEntry *dwarf.Entry
+ var pEntry *dwarf.Entry
foundMain := false
for entry, err := rdr.Next(); entry != nil; entry, err = rdr.Next() {
if err != nil {
}
if entry.Tag == dwarf.TagSubprogram && entry.Val(dwarf.AttrName).(string) == "main.main" {
foundMain = true
+ pEntry = entry
continue
}
if !foundMain {
if line == nil || line.(int64) != 5 {
t.Errorf("DW_AT_decl_line for i is %v, want 5", line)
}
+
+ file := pEntry.Val(dwarf.AttrDeclFile)
+ if file == nil || file.(int64) != 1 {
+ t.Errorf("DW_AT_decl_file for main is %v, want 1", file)
+ }
}
default:
return false
- case objabi.R_DWARFREF:
+ case objabi.R_DWARFSECREF:
v = ld.IMAGE_REL_I386_SECREL
case objabi.R_ADDR: