]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: set direct fn address in dwarf gen where possible
authorThan McIntosh <thanm@google.com>
Thu, 16 Apr 2020 12:29:43 +0000 (08:29 -0400)
committerThan McIntosh <thanm@google.com>
Thu, 16 Apr 2020 15:40:34 +0000 (15:40 +0000)
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>
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/loader/symbolbuilder.go

index 7bb425332515294ccd4cde3ea04f27a3653f6086..fcc15016f89fc589711ec30665b38e364ec1b973 100644 (file)
@@ -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)
 
index 558b8bbb9036fe17fad1fdbe18cec4e4e37f054b..dfbf6b8cc18f837aa15bb9e3a86d12ead75feb98 100644 (file)
@@ -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
+       }
+}