aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2020-07-06 14:22:38 -0400
committerCherry Zhang <cherryyz@google.com>2020-07-06 20:17:51 +0000
commit20afbe86beda00676a608399638887538bd8f669 (patch)
tree5ca3206bb702254e09a715bdef894ef378c5d725
parentfcf1cb2cf51bae37a8d5d0425a39e21ce5073bff (diff)
downloadgo-20afbe86beda00676a608399638887538bd8f669.tar.gz
go-20afbe86beda00676a608399638887538bd8f669.zip
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>
-rw-r--r--src/cmd/oldlink/internal/arm/asm.go6
-rw-r--r--src/cmd/oldlink/internal/ld/decodesym.go32
-rw-r--r--src/cmd/oldlink/internal/ld/lib.go4
-rw-r--r--src/cmd/oldlink/internal/ld/pcln.go2
-rw-r--r--src/cmd/oldlink/internal/ppc64/asm.go6
-rw-r--r--src/cmd/oldlink/internal/sym/attribute.go6
6 files changed, 38 insertions, 18 deletions
diff --git a/src/cmd/oldlink/internal/arm/asm.go b/src/cmd/oldlink/internal/arm/asm.go
index 9dc4ca0f2a..77338e4672 100644
--- a/src/cmd/oldlink/internal/arm/asm.go
+++ b/src/cmd/oldlink/internal/arm/asm.go
@@ -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
diff --git a/src/cmd/oldlink/internal/ld/decodesym.go b/src/cmd/oldlink/internal/ld/decodesym.go
index 0676e94e2c..6c596ec78e 100644
--- a/src/cmd/oldlink/internal/ld/decodesym.go
+++ b/src/cmd/oldlink/internal/ld/decodesym.go
@@ -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)
diff --git a/src/cmd/oldlink/internal/ld/lib.go b/src/cmd/oldlink/internal/ld/lib.go
index cc42901cb6..499602f9be 100644
--- a/src/cmd/oldlink/internal/ld/lib.go
+++ b/src/cmd/oldlink/internal/ld/lib.go
@@ -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 {
diff --git a/src/cmd/oldlink/internal/ld/pcln.go b/src/cmd/oldlink/internal/ld/pcln.go
index 7d53ab8ad4..ed2e8f9e2b 100644
--- a/src/cmd/oldlink/internal/ld/pcln.go
+++ b/src/cmd/oldlink/internal/ld/pcln.go
@@ -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 {
diff --git a/src/cmd/oldlink/internal/ppc64/asm.go b/src/cmd/oldlink/internal/ppc64/asm.go
index 6b57abf564..612f9aa8d2 100644
--- a/src/cmd/oldlink/internal/ppc64/asm.go
+++ b/src/cmd/oldlink/internal/ppc64/asm.go
@@ -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
}
diff --git a/src/cmd/oldlink/internal/sym/attribute.go b/src/cmd/oldlink/internal/sym/attribute.go
index 4b69bf32d0..773b6a4ee7 100644
--- a/src/cmd/oldlink/internal/sym/attribute.go
+++ b/src/cmd/oldlink/internal/sym/attribute.go
@@ -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()