aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pratt <mpratt@google.com>2017-07-08 16:47:16 -0700
committerIan Lance Taylor <iant@golang.org>2017-07-09 19:23:41 +0000
commit123fd4640ae27e7f179f84cd7efece07ab954b45 (patch)
treec41c84ba6987b592d41db85047b3d347c77f01aa
parenta1e7fb4eed7fbb002d2fabbd6a809a1a49dca711 (diff)
downloadgo-123fd4640ae27e7f179f84cd7efece07ab954b45.tar.gz
go-123fd4640ae27e7f179f84cd7efece07ab954b45.zip
cmd/link: skip R_ADDR relocs in .rela.plt for internal PIE
ld.addpltsym adds an R_X86_64_JMP_SLOT dynamic relocation to .rela.plt and uses Addaddrplus to reference the GOT in Elf64_Rela.r_offset. Addaddrplus results in an R_ADDR relocation, which here we transform into an R_X86_64_64 dynamic relocation. This is wrong for several reasons: 1. .rela.plt is not a writable, relro section. It is mapped read-only, causing the dynamic linker to segfault when it tried to handle the relocation. This was the immediate cause of internal PIE cgo crashes. 2. Relocations targetting other reloc sections are, as far as I can tell, undefined behavior in the ELF spec and are unlikely to be a good idea. 3. Even if the relocation did work, it isn't what we want. The relocation, if successfully handled, would have put an absolute address as the JMP_SLOT offset, but it should be the offset from the beginning of the binary, just like any other relocation. What we want is a statically resolved R_ADDR relocation, just as is used below for the R_X86_64_64 relocation. Skipping the .rela.plt allows reloc() to handle these R_ADDR relocations. With this CL, internal PIE cgo binaries work. Updates #18968 Change-Id: Ie74e6fe249e88150baa0e340b1cb128cf7f28673 Reviewed-on: https://go-review.googlesource.com/47837 Reviewed-by: Ian Lance Taylor <iant@golang.org>
-rw-r--r--src/cmd/link/internal/amd64/asm.go9
1 files changed, 8 insertions, 1 deletions
diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go
index 03bd59488e..d2f63d3d05 100644
--- a/src/cmd/link/internal/amd64/asm.go
+++ b/src/cmd/link/internal/amd64/asm.go
@@ -283,8 +283,15 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
// now, or else we will be caught in an infinite loop
// of generating synthetic relocs for our synthetic
// relocs.
+ //
+ // Furthermore, the rela sections contain dynamic
+ // relocations with R_ADDR relocations on
+ // Elf64_Rela.r_offset. This field should contain the
+ // symbol offset as determined by reloc(), not the
+ // final dynamically linked address as a dynamic
+ // relocation would provide.
switch s.Name {
- case ".dynsym", ".rela", ".got.plt", ".dynamic":
+ case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
return false
}
} else {