From da9f383ca1d9c7c7011f8d32a55d06f4cebfd623 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Thu, 16 Apr 2020 08:29:43 -0400 Subject: [PATCH] [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 TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- src/cmd/link/internal/ld/dwarf.go | 10 +++++++-- src/cmd/link/internal/loader/symbolbuilder.go | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 7bb4253325..fcc15016f8 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1140,6 +1140,9 @@ func (d *dwctxt2) writelines(unit *sym.CompilationUnit, ls loader.Sym) { lsu := d.ldr.MakeSymbolUpdater(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) // Fields marked with (*) must be changed for 64-bit dwarf unitLengthOffset := lsu.Size() @@ -1209,7 +1212,7 @@ func (d *dwctxt2) writelines(unit *sym.CompilationUnit, ls loader.Sym) { lsu.AddUint8(0) dwarf.Uleb128put(d, lsDwsym, 1+int64(d.arch.PtrSize)) 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. if addr < lastAddr { 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) } + internalExec := d.linkctxt.BuildMode == BuildModeExe && d.linkctxt.IsInternal() + addAddrPlus := loader.GenAddAddrPlusFunc(internalExec) + fsu.AddBytes(zeros[:pad]) var deltaBuf []byte @@ -1428,7 +1434,7 @@ func (d *dwctxt2) writeframes(syms []loader.Sym) []loader.Sym { } else { 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.AddBytes(deltaBuf) diff --git a/src/cmd/link/internal/loader/symbolbuilder.go b/src/cmd/link/internal/loader/symbolbuilder.go index 558b8bbb90..dfbf6b8cc1 100644 --- a/src/cmd/link/internal/loader/symbolbuilder.go +++ b/src/cmd/link/internal/loader/symbolbuilder.go @@ -405,3 +405,24 @@ func (sb *SymbolBuilder) AddSize(arch *sys.Arch, tgt Sym) int64 { sb.setReachable() 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 + } +} -- 2.50.0