cmd/6l, cmd/internal/ld: handle R_PCREL to function in other shared library
An ELF linker handles a PC-relative reference to an STT_FUNC defined in a
shared library by building a PLT entry and referring to that, so do the
same in 6l.
Fixes #10690
Change-Id: I061a96fd4400d957e301d0ac86760ce256910e1d
Reviewed-on: https://go-review.googlesource.com/9711
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/cmd/6l/asm.go b/src/cmd/6l/asm.go
index deaeb82..4df8ac7 100644
--- a/src/cmd/6l/asm.go
+++ b/src/cmd/6l/asm.go
@@ -33,6 +33,7 @@
import (
"cmd/internal/ld"
"cmd/internal/obj"
+ "debug/elf"
"fmt"
"log"
)
@@ -381,7 +382,11 @@
case obj.R_PCREL:
if r.Siz == 4 {
- ld.Thearch.Vput(ld.R_X86_64_PC32 | uint64(elfsym)<<32)
+ if r.Xsym.Type == obj.SDYNIMPORT && r.Xsym.ElfType == elf.STT_FUNC {
+ ld.Thearch.Vput(ld.R_X86_64_PLT32 | uint64(elfsym)<<32)
+ } else {
+ ld.Thearch.Vput(ld.R_X86_64_PC32 | uint64(elfsym)<<32)
+ }
} else {
return -1
}
diff --git a/src/cmd/internal/ld/lib.go b/src/cmd/internal/ld/lib.go
index cdf2dca..184175e 100644
--- a/src/cmd/internal/ld/lib.go
+++ b/src/cmd/internal/ld/lib.go
@@ -1197,6 +1197,7 @@
s.Name, shlib, lsym.File)
}
lsym.Type = obj.SDYNIMPORT
+ lsym.ElfType = elf.ST_TYPE(s.Info)
lsym.File = libpath
if strings.HasPrefix(lsym.Name, "type.") {
data := make([]byte, s.Size)
diff --git a/src/cmd/internal/ld/link.go b/src/cmd/internal/ld/link.go
index 52390e7..03da52a 100644
--- a/src/cmd/internal/ld/link.go
+++ b/src/cmd/internal/ld/link.go
@@ -32,26 +32,31 @@
import (
"cmd/internal/obj"
+ "debug/elf"
"encoding/binary"
)
type LSym struct {
- Name string
- Extname string
- Type int16
- Version int16
- Dupok uint8
- Cfunc uint8
- External uint8
- Nosplit uint8
- Reachable bool
- Cgoexport uint8
- Special uint8
- Stkcheck uint8
- Hide uint8
- Leaf uint8
- Localentry uint8
- Onlist uint8
+ Name string
+ Extname string
+ Type int16
+ Version int16
+ Dupok uint8
+ Cfunc uint8
+ External uint8
+ Nosplit uint8
+ Reachable bool
+ Cgoexport uint8
+ Special uint8
+ Stkcheck uint8
+ Hide uint8
+ Leaf uint8
+ Localentry uint8
+ Onlist uint8
+ // ElfType is set for symbols read from shared libraries by ldshlibsyms. It
+ // is not set for symbols defined by the packages being linked or by symbols
+ // read by ldelf (and so is left as elf.STT_NOTYPE).
+ ElfType elf.SymType
Dynid int32
Plt int32
Got int32
diff --git a/src/cmd/internal/ld/symtab.go b/src/cmd/internal/ld/symtab.go
index 31baba0..d6e79dc 100644
--- a/src/cmd/internal/ld/symtab.go
+++ b/src/cmd/internal/ld/symtab.go
@@ -106,10 +106,9 @@
type_ = STT_OBJECT
case 'U':
- type_ = STT_NOTYPE
- if x == Ctxt.Tlsg {
- type_ = STT_TLS
- }
+ // ElfType is only set for symbols read from Go shared libraries, but
+ // for other symbols it is left as STT_NOTYPE which is fine.
+ type_ = int(x.ElfType)
case 't':
type_ = STT_TLS