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) { ...@@ -323,7 +323,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
func elfreloc1(r *ld.Reloc, sectoff int64) int { func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Vput(uint64(sectoff)) ld.Thearch.Vput(uint64(sectoff))
elfsym := r.Xsym.Elfsym elfsym := r.Xsym.ElfsymForReloc()
switch r.Type { switch r.Type {
default: default:
return -1 return -1
......
...@@ -193,7 +193,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) { ...@@ -193,7 +193,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
func elfreloc1(r *ld.Reloc, sectoff int64) int { func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Lput(uint32(sectoff)) ld.Thearch.Lput(uint32(sectoff))
elfsym := r.Xsym.Elfsym elfsym := r.Xsym.ElfsymForReloc()
switch r.Type { switch r.Type {
default: default:
return -1 return -1
......
...@@ -51,7 +51,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) { ...@@ -51,7 +51,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
func elfreloc1(r *ld.Reloc, sectoff int64) int { func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Vput(uint64(sectoff)) ld.Thearch.Vput(uint64(sectoff))
elfsym := r.Xsym.Elfsym elfsym := r.Xsym.ElfsymForReloc()
switch r.Type { switch r.Type {
default: default:
return -1 return -1
......
...@@ -1615,7 +1615,7 @@ func elfrelocsect(sect *Section, first *LSym) { ...@@ -1615,7 +1615,7 @@ func elfrelocsect(sect *Section, first *LSym) {
continue 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) 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 { if Thearch.Elfreloc1(r, int64(uint64(sym.Value+int64(r.Off))-sect.Vaddr)) < 0 {
......
...@@ -1031,14 +1031,6 @@ func hostlink() { ...@@ -1031,14 +1031,6 @@ func hostlink() {
argv = append(argv, "-shared", "-Wl,-z,nodelete") argv = append(argv, "-shared", "-Wl,-z,nodelete")
} }
case BuildmodeShared: 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() { if UseRelro() {
argv = append(argv, "-Wl,-z,relro") argv = append(argv, "-Wl,-z,relro")
} }
......
...@@ -63,6 +63,7 @@ type LSym struct { ...@@ -63,6 +63,7 @@ type LSym struct {
Got int32 Got int32
Align int32 Align int32
Elfsym int32 Elfsym int32
LocalElfsym int32
Args int32 Args int32
Locals int32 Locals int32
Value int64 Value int64
...@@ -92,6 +93,16 @@ func (s *LSym) String() string { ...@@ -92,6 +93,16 @@ func (s *LSym) String() string {
return fmt.Sprintf("%s<%d>", s.Name, s.Version) 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 { type Reloc struct {
Off int32 Off int32
Siz uint8 Siz uint8
......
...@@ -155,11 +155,6 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L ...@@ -155,11 +155,6 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L
bind = STB_LOCAL bind = STB_LOCAL
} }
if bind != elfbind {
return
}
off := putelfstr(s)
if Linkmode == LinkExternal && elfshnum != SHN_UNDEF { if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
addr -= int64(xo.Sect.Vaddr) 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 ...@@ -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 { if x.Type&obj.SHIDDEN != 0 {
other = STV_HIDDEN 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) x.Elfsym = int32(numelfsym)
numelfsym++ numelfsym++
} }
......
...@@ -231,7 +231,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) { ...@@ -231,7 +231,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
func elfreloc1(r *ld.Reloc, sectoff int64) int { func elfreloc1(r *ld.Reloc, sectoff int64) int {
ld.Thearch.Lput(uint32(sectoff)) ld.Thearch.Lput(uint32(sectoff))
elfsym := r.Xsym.Elfsym elfsym := r.Xsym.ElfsymForReloc()
switch r.Type { switch r.Type {
default: default:
return -1 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