Commit c34fb3cf authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

cmd/link: always resolve functions locally when linking dynamically

When dynamically linking, we want references to functions defined
in this module to always be to the function object, not to the
PLT. We force this by writing an additional local symbol for
every global function symbol and making all relocations against
the global symbol refer to this local symbol instead. This is
approximately equivalent to the ELF linker -Bsymbolic-functions
option, but that is buggy on several platforms.

Change-Id: Ie6983eb4d1947f8543736fd349f9a90df3cce91a
Reviewed-on: https://go-review.googlesource.com/16436Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent ab7e82ef
......@@ -323,7 +323,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Vput(uint64(sectoff))
elfsym := r.Xsym.Elfsym
elfsym := r.Xsym.ElfsymForReloc()
switch r.Type {
default:
return -1
......
......@@ -193,7 +193,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Lput(uint32(sectoff))
elfsym := r.Xsym.Elfsym
elfsym := r.Xsym.ElfsymForReloc()
switch r.Type {
default:
return -1
......
......@@ -51,7 +51,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Vput(uint64(sectoff))
elfsym := r.Xsym.Elfsym
elfsym := r.Xsym.ElfsymForReloc()
switch r.Type {
default:
return -1
......
......@@ -1615,7 +1615,7 @@ func elfrelocsect(sect *Section, first *LSym) {
continue
}
if r.Xsym.Elfsym == 0 {
if r.Xsym.ElfsymForReloc() == 0 {
Diag("reloc %d to non-elf symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
}
if Thearch.Elfreloc1(r, int64(uint64(sym.Value+int64(r.Off))-sect.Vaddr)) < 0 {
......
......@@ -1031,14 +1031,6 @@ func hostlink() {
argv = append(argv, "-shared", "-Wl,-z,nodelete")
}
case BuildmodeShared:
// TODO(mwhudson): unless you do this, dynamic relocations fill
// out the findfunctab table and for some reason shared libraries
// and the executable both define a main function and putting the
// address of executable's main into the shared libraries
// findfunctab violates the assumptions of the runtime. TBH, I
// think we may well end up wanting to use -Bsymbolic here
// anyway.
argv = append(argv, "-Wl,-Bsymbolic-functions")
if UseRelro() {
argv = append(argv, "-Wl,-z,relro")
}
......
......@@ -63,6 +63,7 @@ type LSym struct {
Got int32
Align int32
Elfsym int32
LocalElfsym int32
Args int32
Locals int32
Value int64
......@@ -92,6 +93,16 @@ func (s *LSym) String() string {
return fmt.Sprintf("%s<%d>", s.Name, s.Version)
}
func (s *LSym) ElfsymForReloc() int32 {
// If putelfsym created a local version of this symbol, use that in all
// relocations.
if s.LocalElfsym != 0 {
return s.LocalElfsym
} else {
return s.Elfsym
}
}
type Reloc struct {
Off int32
Siz uint8
......
......@@ -155,11 +155,6 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L
bind = STB_LOCAL
}
if bind != elfbind {
return
}
off := putelfstr(s)
if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
addr -= int64(xo.Sect.Vaddr)
}
......@@ -167,7 +162,24 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L
if x.Type&obj.SHIDDEN != 0 {
other = STV_HIDDEN
}
putelfsyment(off, addr, size, bind<<4|type_&0xf, elfshnum, other)
if DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == obj.STEXT {
// When dynamically linking, we want references to functions defined
// in this module to always be to the function object, not to the
// PLT. We force this by writing an additional local symbol for every
// global function symbol and making all relocations against the
// global symbol refer to this local symbol instead (see
// (*LSym).ElfsymForReloc). This is approximately equivalent to the
// ELF linker -Bsymbolic-functions option, but that is buggy on
// several platforms.
putelfsyment(putelfstr("local."+s), addr, size, STB_LOCAL<<4|type_&0xf, elfshnum, other)
x.LocalElfsym = int32(numelfsym)
numelfsym++
} else if bind != elfbind {
return
}
putelfsyment(putelfstr(s), addr, size, bind<<4|type_&0xf, elfshnum, other)
x.Elfsym = int32(numelfsym)
numelfsym++
}
......
......@@ -231,7 +231,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Lput(uint32(sectoff))
elfsym := r.Xsym.Elfsym
elfsym := r.Xsym.ElfsymForReloc()
switch r.Type {
default:
return -1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment