From 5940a007c14af11fe35f48d8f7daa3cd9036aaa3 Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Tue, 13 Sep 2016 08:24:07 -0400 Subject: [PATCH] cmd/link: R_ADDR dynamic relocs for internal PIE This gets -buildmode=pie -ldflags=-linkmode=internal working on Ubuntu 16.04. Fixes #17068 Change-Id: Ice5036199005fb528cc58279a7f057170dc6b73d Reviewed-on: https://go-review.googlesource.com/29118 Run-TryBot: David Crawshaw TryBot-Result: Gobot Gobot Reviewed-by: Michael Hudson-Doyle Reviewed-by: Ian Lance Taylor --- src/cmd/link/internal/amd64/asm.go | 47 ++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index fe145d0b670562..0d8444eea47c4a 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -255,16 +255,59 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool { return true } - if s.Type != obj.SDATA && s.Type != obj.SRODATA { - break + // Process dynamic relocations for the data sections. + if ld.Buildmode == ld.BuildmodePIE && ld.Linkmode == ld.LinkInternal { + // When internally linking, generate dynamic relocations + // for all typical R_ADDR relocations. The exception + // are those R_ADDR that are created as part of generating + // the dynamic relocations and must be resolved statically. + // + // There are three phases relevant to understanding this: + // + // dodata() // we are here + // address() // symbol address assignment + // reloc() // resolution of static R_ADDR relocs + // + // At this point symbol addresses have not been + // assigned yet (as the final size of the .rela section + // will affect the addresses), and so we cannot write + // the Elf64_Rela.r_offset now. Instead we delay it + // until after the 'address' phase of the linker is + // complete. We do this via Addaddrplus, which creates + // a new R_ADDR relocation which will be resolved in + // the 'reloc' phase. + // + // These synthetic static R_ADDR relocs must be skipped + // now, or else we will be caught in an infinite loop + // of generating synthetic relocs for our synthetic + // relocs. + switch s.Name { + case ".dynsym", ".rela", ".got.plt", ".dynamic": + return false + } + } else { + // Either internally linking a static executable, + // in which case we can resolve these relocations + // statically in the 'reloc' phase, or externally + // linking, in which case the relocation will be + // prepared in the 'reloc' phase and passed to the + // external linker in the 'asmb' phase. + if s.Type != obj.SDATA && s.Type != obj.SRODATA { + break + } } + if ld.Iself { + // TODO: We generate a R_X86_64_64 relocation for every R_ADDR, even + // though it would be more efficient (for the dynamic linker) if we + // generated R_X86_RELATIVE instead. ld.Adddynsym(ctxt, targ) rela := ld.Linklookup(ctxt, ".rela", 0) ld.Addaddrplus(ctxt, rela, s, int64(r.Off)) if r.Siz == 8 { ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(targ.Dynid), ld.R_X86_64_64)) } else { + // TODO: never happens, remove. ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(targ.Dynid), ld.R_X86_64_32)) } ld.Adduint64(ctxt, rela, uint64(r.Add))