mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] cmd/link: set direct fn address in dwarf gen where possible
If we are internal linking a static executable, and address assignment has happened, then when emitting some parts of DWARF we can just emit a function address directly instead of generating a relocation. For external linking or other build modes, we are generating a relocatable binary so we still need to emit relocations. This CL inspired by Cherry's similar CL for pclntab at https://go-review.googlesource.com/c/go/+/228478. Change-Id: Ib03fbe2dd72d0ba746bf46015e0f2d6c3f3d53ab Reviewed-on: https://go-review.googlesource.com/c/go/+/228537 Run-TryBot: Than McIntosh <thanm@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
4a0bca37d2
commit
da9f383ca1
2 changed files with 29 additions and 2 deletions
|
|
@ -1140,6 +1140,9 @@ func (d *dwctxt2) writelines(unit *sym.CompilationUnit, ls loader.Sym) {
|
||||||
lsu := d.ldr.MakeSymbolUpdater(ls)
|
lsu := d.ldr.MakeSymbolUpdater(ls)
|
||||||
newattr(unit.DWInfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, lsu.Size(), dwSym(ls))
|
newattr(unit.DWInfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, lsu.Size(), dwSym(ls))
|
||||||
|
|
||||||
|
internalExec := d.linkctxt.BuildMode == BuildModeExe && d.linkctxt.IsInternal()
|
||||||
|
addAddrPlus := loader.GenAddAddrPlusFunc(internalExec)
|
||||||
|
|
||||||
// Write .debug_line Line Number Program Header (sec 6.2.4)
|
// Write .debug_line Line Number Program Header (sec 6.2.4)
|
||||||
// Fields marked with (*) must be changed for 64-bit dwarf
|
// Fields marked with (*) must be changed for 64-bit dwarf
|
||||||
unitLengthOffset := lsu.Size()
|
unitLengthOffset := lsu.Size()
|
||||||
|
|
@ -1209,7 +1212,7 @@ func (d *dwctxt2) writelines(unit *sym.CompilationUnit, ls loader.Sym) {
|
||||||
lsu.AddUint8(0)
|
lsu.AddUint8(0)
|
||||||
dwarf.Uleb128put(d, lsDwsym, 1+int64(d.arch.PtrSize))
|
dwarf.Uleb128put(d, lsDwsym, 1+int64(d.arch.PtrSize))
|
||||||
lsu.AddUint8(dwarf.DW_LNE_set_address)
|
lsu.AddUint8(dwarf.DW_LNE_set_address)
|
||||||
addr := lsu.AddAddrPlus(d.arch, fnSym, 0)
|
addr := addAddrPlus(lsu, d.arch, fnSym, 0)
|
||||||
// Make sure the units are sorted.
|
// Make sure the units are sorted.
|
||||||
if addr < lastAddr {
|
if addr < lastAddr {
|
||||||
d.linkctxt.Errorf(fnSym, "address wasn't increasing %x < %x",
|
d.linkctxt.Errorf(fnSym, "address wasn't increasing %x < %x",
|
||||||
|
|
@ -1347,6 +1350,9 @@ func (d *dwctxt2) writeframes(syms []loader.Sym) []loader.Sym {
|
||||||
Exitf("dwarf: cieReserve too small by %d bytes.", -pad)
|
Exitf("dwarf: cieReserve too small by %d bytes.", -pad)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internalExec := d.linkctxt.BuildMode == BuildModeExe && d.linkctxt.IsInternal()
|
||||||
|
addAddrPlus := loader.GenAddAddrPlusFunc(internalExec)
|
||||||
|
|
||||||
fsu.AddBytes(zeros[:pad])
|
fsu.AddBytes(zeros[:pad])
|
||||||
|
|
||||||
var deltaBuf []byte
|
var deltaBuf []byte
|
||||||
|
|
@ -1428,7 +1434,7 @@ func (d *dwctxt2) writeframes(syms []loader.Sym) []loader.Sym {
|
||||||
} else {
|
} else {
|
||||||
d.addDwarfAddrField(fsu, 0) // CIE offset
|
d.addDwarfAddrField(fsu, 0) // CIE offset
|
||||||
}
|
}
|
||||||
fsu.AddAddrPlus(d.arch, s, 0)
|
addAddrPlus(fsu, d.arch, s, 0)
|
||||||
fsu.AddUintXX(d.arch, uint64(len(d.ldr.Data(fn))), d.arch.PtrSize) // address range
|
fsu.AddUintXX(d.arch, uint64(len(d.ldr.Data(fn))), d.arch.PtrSize) // address range
|
||||||
fsu.AddBytes(deltaBuf)
|
fsu.AddBytes(deltaBuf)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -405,3 +405,24 @@ func (sb *SymbolBuilder) AddSize(arch *sys.Arch, tgt Sym) int64 {
|
||||||
sb.setReachable()
|
sb.setReachable()
|
||||||
return sb.addSymRef(tgt, 0, objabi.R_SIZE, arch.PtrSize)
|
return sb.addSymRef(tgt, 0, objabi.R_SIZE, arch.PtrSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenAddAddrPlusFunc returns a function to be called when capturing
|
||||||
|
// a function symbol's address. In later stages of the link (when
|
||||||
|
// address assignment is done) when doing internal linking and
|
||||||
|
// targeting an executable, we can just emit the address of a function
|
||||||
|
// directly instead of generating a relocation. Clients can call
|
||||||
|
// this function (setting 'internalExec' based on build mode and target)
|
||||||
|
// and then invoke the returned function in roughly the same way that
|
||||||
|
// loader.*SymbolBuilder.AddAddrPlus would be used.
|
||||||
|
func GenAddAddrPlusFunc(internalExec bool) func(s *SymbolBuilder, arch *sys.Arch, tgt Sym, add int64) int64 {
|
||||||
|
if internalExec {
|
||||||
|
return func(s *SymbolBuilder, arch *sys.Arch, tgt Sym, add int64) int64 {
|
||||||
|
if v := s.l.SymValue(tgt); v != 0 {
|
||||||
|
return s.AddUint(arch, uint64(v+add))
|
||||||
|
}
|
||||||
|
return s.AddAddrPlus(arch, tgt, add)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (*SymbolBuilder).AddAddrPlus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue