1
0
mirror of https://github.com/golang/go synced 2024-11-11 22:50:22 -07:00

cmd/oldlink: port bug fixes to old linker

This CL ports CL 234105 and CL 240621 to the old linker, which
fix critical bugs (runtime crashes).

Updates #39049.
Updates #39927.

Change-Id: I47afc84349119e320d2e60d64b7188a410835d2b
Reviewed-on: https://go-review.googlesource.com/c/go/+/241087
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
This commit is contained in:
Cherry Zhang 2020-07-06 14:22:38 -04:00
parent fcf1cb2cf5
commit 20afbe86be
6 changed files with 38 additions and 18 deletions

View File

@ -390,8 +390,12 @@ func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) {
offset := (signext24(r.Add&0xffffff) + 2) * 4
var tramp *sym.Symbol
for i := 0; ; i++ {
name := r.Sym.Name + fmt.Sprintf("%+d-tramp%d", offset, i)
oName := r.Sym.Name
name := oName + fmt.Sprintf("%+d-tramp%d", offset, i)
tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version))
if oName == "runtime.deferreturn" {
tramp.Attr.Set(sym.AttrDeferReturnTramp, true)
}
if tramp.Type == sym.SDYNIMPORT {
// don't reuse trampoline defined in other module
continue

View File

@ -11,6 +11,7 @@ import (
"cmd/oldlink/internal/sym"
"debug/elf"
"fmt"
"log"
)
// Decoding the type.* symbols. This has to be in sync with
@ -93,7 +94,7 @@ func decodetypeHasUncommon(arch *sys.Arch, p []byte) bool {
func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
for _, shlib := range ctxt.Shlibs {
if shlib.Path == path {
for _, sect := range shlib.File.Sections {
for _, sect := range shlib.File.Sections[1:] { // skip the NULL section
if sect.Addr <= addr && addr <= sect.Addr+sect.Size {
return sect
}
@ -112,9 +113,15 @@ func decodetypeGcprog(ctxt *Link, s *sym.Symbol) []byte {
// A gcprog is a 4-byte uint32 indicating length, followed by
// the actual program.
progsize := make([]byte, 4)
sect.ReadAt(progsize, int64(addr-sect.Addr))
_, err := sect.ReadAt(progsize, int64(addr-sect.Addr))
if err != nil {
log.Fatal(err)
}
progbytes := make([]byte, ctxt.Arch.ByteOrder.Uint32(progsize))
sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
_, err = sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
if err != nil {
log.Fatal(err)
}
return append(progsize, progbytes...)
}
Exitf("cannot find gcprog for %s", s.Name)
@ -124,14 +131,6 @@ func decodetypeGcprog(ctxt *Link, s *sym.Symbol) []byte {
}
func decodetypeGcprogShlib(ctxt *Link, s *sym.Symbol) uint64 {
if ctxt.Arch.Family == sys.ARM64 {
for _, shlib := range ctxt.Shlibs {
if shlib.Path == s.File {
return shlib.gcdataAddresses[s]
}
}
return 0
}
return decodeInuxi(ctxt.Arch, s.P[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
}
@ -141,8 +140,15 @@ func decodetypeGcmask(ctxt *Link, s *sym.Symbol) []byte {
ptrdata := decodetypePtrdata(ctxt.Arch, s.P)
sect := findShlibSection(ctxt, s.File, addr)
if sect != nil {
r := make([]byte, ptrdata/int64(ctxt.Arch.PtrSize))
sect.ReadAt(r, int64(addr-sect.Addr))
bits := ptrdata / int64(ctxt.Arch.PtrSize)
r := make([]byte, (bits+7)/8)
// ldshlibsyms avoids closing the ELF file so sect.ReadAt works.
// If we remove this read (and the ones in decodetypeGcprog), we
// can close the file.
_, err := sect.ReadAt(r, int64(addr-sect.Addr))
if err != nil {
log.Fatal(err)
}
return r
}
Exitf("cannot find gcmask for %s", s.Name)

View File

@ -2010,7 +2010,9 @@ func ldshlibsyms(ctxt *Link, shlib string) {
Errorf(nil, "cannot open shared library: %s", libpath)
return
}
defer f.Close()
// Keep the file open as decodetypeGcprog needs to read from it.
// TODO: fix. Maybe mmap the file.
//defer f.Close()
hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
if err != nil {

View File

@ -276,7 +276,7 @@ func (ctxt *Link) pclntab() {
// set the resumption point to PC_B.
lastWasmAddr = uint32(r.Add)
}
if r.Type.IsDirectCall() && r.Sym != nil && r.Sym.Name == "runtime.deferreturn" {
if r.Type.IsDirectCall() && r.Sym != nil && (r.Sym.Name == "runtime.deferreturn" || r.Sym.Attr.DeferReturnTramp()) {
if ctxt.Arch.Family == sys.Wasm {
deferreturn = lastWasmAddr - 1
} else {

View File

@ -667,7 +667,8 @@ func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) {
// target is at some offset within the function. Calls to duff+8 and duff+256 must appear as
// distinct trampolines.
name := r.Sym.Name
oName := r.Sym.Name
name := oName
if r.Add == 0 {
name = name + fmt.Sprintf("-tramp%d", i)
} else {
@ -677,6 +678,9 @@ func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) {
// Look up the trampoline in case it already exists
tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version))
if oName == "runtime.deferreturn" {
tramp.Attr.Set(sym.AttrDeferReturnTramp, true)
}
if tramp.Value == 0 {
break
}

View File

@ -81,7 +81,10 @@ const (
// AttrReadOnly indicates whether the symbol's content (Symbol.P) is backed by
// read-only memory.
AttrReadOnly
// 19 attributes defined so far.
// AttrDeferReturnTramp indicates the symbol is a trampoline of a deferreturn
// call.
AttrDeferReturnTramp
// 20 attributes defined so far.
)
func (a Attribute) DuplicateOK() bool { return a&AttrDuplicateOK != 0 }
@ -103,6 +106,7 @@ func (a Attribute) SubSymbol() bool { return a&AttrSubSymbol != 0 }
func (a Attribute) Container() bool { return a&AttrContainer != 0 }
func (a Attribute) TopFrame() bool { return a&AttrTopFrame != 0 }
func (a Attribute) ReadOnly() bool { return a&AttrReadOnly != 0 }
func (a Attribute) DeferReturnTramp() bool { return a&AttrDeferReturnTramp != 0 }
func (a Attribute) CgoExport() bool {
return a.CgoExportDynamic() || a.CgoExportStatic()