aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link/internal
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2020-01-31 14:45:52 -0500
committerCherry Zhang <cherryyz@google.com>2020-01-31 14:45:52 -0500
commitee04d45b8f380c2e3b3b26bc4771cd97fbd9d260 (patch)
tree5db2e0ca22bb7d54f7c6d8a8d4acc96224b2e85c /src/cmd/link/internal
parent23c96e9bbd29e3a815e6faabbc40af0d4c4d4353 (diff)
parent96002cd25c343edfb6c06d2bf1f31ae1e345b81f (diff)
downloadgo-ee04d45b8f380c2e3b3b26bc4771cd97fbd9d260.tar.xz
[dev.link] all: merge branch 'master' into dev.link
It has been a while we have not done this. Merge conflict resolution: - deleted/rewritten code modified on master - CL 214286, ported in CL 217317 (cmd/internal/obj/objfile.go) - CL 210678, it already includes a fix to new code (cmd/link/internal/ld/deadcode.go) - CL 209317, applied in this CL (cmd/link/internal/loadelf/ldelf.go) Change-Id: Ie927ea6a1d69ce49e8d03e56148cb2725e377876
Diffstat (limited to 'src/cmd/link/internal')
-rw-r--r--src/cmd/link/internal/ld/data.go46
-rw-r--r--src/cmd/link/internal/ld/deadcode2.go2
-rw-r--r--src/cmd/link/internal/ld/pcln.go7
-rw-r--r--src/cmd/link/internal/loadelf/ldelf.go65
4 files changed, 82 insertions, 38 deletions
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index 32d1111ea3..7ca01c8c25 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -1625,29 +1625,27 @@ func (ctxt *Link) dodata() {
}
if ctxt.UseRelro() {
+ segrelro := &Segrelrodata
+ if ctxt.LinkMode == LinkExternal && ctxt.HeadType != objabi.Haix {
+ // Using a separate segment with an external
+ // linker results in some programs moving
+ // their data sections unexpectedly, which
+ // corrupts the moduledata. So we use the
+ // rodata segment and let the external linker
+ // sort out a rel.ro segment.
+ segrelro = segro
+ } else {
+ // Reset datsize for new segment.
+ datsize = 0
+ }
+
addrelrosection = func(suffix string) *sym.Section {
- seg := &Segrelrodata
- if ctxt.LinkMode == LinkExternal && ctxt.HeadType != objabi.Haix {
- // Using a separate segment with an external
- // linker results in some programs moving
- // their data sections unexpectedly, which
- // corrupts the moduledata. So we use the
- // rodata segment and let the external linker
- // sort out a rel.ro segment.
- seg = &Segrodata
- }
- return addsection(ctxt.Arch, seg, ".data.rel.ro"+suffix, 06)
+ return addsection(ctxt.Arch, segrelro, ".data.rel.ro"+suffix, 06)
}
+
/* data only written by relocations */
sect = addrelrosection("")
- sect.Vaddr = 0
- if ctxt.HeadType == objabi.Haix {
- // datsize must be reset because relro datas will end up
- // in data segment.
- datsize = 0
- }
-
ctxt.Syms.Lookup("runtime.types", 0).Sect = sect
ctxt.Syms.Lookup("runtime.etypes", 0).Sect = sect
@@ -1659,7 +1657,17 @@ func (ctxt *Link) dodata() {
}
}
datsize = Rnd(datsize, int64(sect.Align))
- for _, symnro := range sym.ReadOnly {
+ sect.Vaddr = uint64(datsize)
+
+ for i, symnro := range sym.ReadOnly {
+ if i == 0 && symnro == sym.STYPE && ctxt.HeadType != objabi.Haix {
+ // Skip forward so that no type
+ // reference uses a zero offset.
+ // This is unlikely but possible in small
+ // programs with no other read-only data.
+ datsize++
+ }
+
symn := sym.RelROMap[symnro]
symnStartValue := datsize
for _, s := range data[symn] {
diff --git a/src/cmd/link/internal/ld/deadcode2.go b/src/cmd/link/internal/ld/deadcode2.go
index 915ad1d944..3d3a03215e 100644
--- a/src/cmd/link/internal/ld/deadcode2.go
+++ b/src/cmd/link/internal/ld/deadcode2.go
@@ -113,7 +113,7 @@ func (d *deadcodePass2) init() {
}
for _, name := range names {
- // Mark symbol as an data/ABI0 symbol.
+ // Mark symbol as a data/ABI0 symbol.
d.mark(d.ldr.Lookup(name, 0), 0)
// Also mark any Go functions (internal ABI).
d.mark(d.ldr.Lookup(name, sym.SymVerABIInternal), 0)
diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go
index ab703e94ee..db44c0292e 100644
--- a/src/cmd/link/internal/ld/pcln.go
+++ b/src/cmd/link/internal/ld/pcln.go
@@ -266,8 +266,13 @@ func (ctxt *Link) pclntab() {
switch ctxt.Arch.Family {
case sys.AMD64, sys.I386:
deferreturn--
- case sys.PPC64, sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64, sys.RISCV64:
+ case sys.PPC64, sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64:
// no change
+ case sys.RISCV64:
+ // TODO(jsing): The JALR instruction is marked with
+ // R_CALLRISCV, whereas the actual reloc is currently
+ // one instruction earlier starting with the AUIPC.
+ deferreturn -= 4
case sys.S390X:
deferreturn -= 2
default:
diff --git a/src/cmd/link/internal/loadelf/ldelf.go b/src/cmd/link/internal/loadelf/ldelf.go
index 7d613c7a6d..b1e420cc30 100644
--- a/src/cmd/link/internal/loadelf/ldelf.go
+++ b/src/cmd/link/internal/loadelf/ldelf.go
@@ -901,14 +901,26 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader,
p := rsect.base
for j := 0; j < n; j++ {
var add uint64
+ var symIdx int
+ var relocType uint64
+
rp := &r[j]
- var info uint64
if is64 != 0 {
// 64-bit rel/rela
rp.Off = int32(e.Uint64(p))
p = p[8:]
- info = e.Uint64(p)
+ switch arch.Family {
+ case sys.MIPS64:
+ // https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
+ // The doc shows it's different with general Linux ELF
+ symIdx = int(e.Uint32(p))
+ relocType = uint64(p[7])
+ default:
+ info := e.Uint64(p)
+ relocType = info & 0xffffffff
+ symIdx = int(info >> 32)
+ }
p = p[8:]
if rela != 0 {
add = e.Uint64(p)
@@ -919,8 +931,9 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader,
rp.Off = int32(e.Uint32(p))
p = p[4:]
- info = uint64(e.Uint32(p))
- info = info>>8<<32 | info&0xff // convert to 64-bit info
+ info := e.Uint32(p)
+ relocType = uint64(info & 0xff)
+ symIdx = int(info >> 8)
p = p[4:]
if rela != 0 {
add = uint64(e.Uint32(p))
@@ -928,29 +941,29 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader,
}
}
- if info&0xffffffff == 0 { // skip R_*_NONE relocation
+ if relocType == 0 { // skip R_*_NONE relocation
j--
n--
continue
}
- if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
+ if symIdx == 0 { // absolute relocation, don't bother reading the null symbol
rp.Sym = 0
} else {
var elfsym ElfSym
- if err := readelfsym(newSym, lookup, l, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
+ if err := readelfsym(newSym, lookup, l, arch, elfobj, int(symIdx), &elfsym, 0, 0); err != nil {
return errorf("malformed elf file: %v", err)
}
- elfsym.sym = symbols[info>>32]
+ elfsym.sym = symbols[symIdx]
if elfsym.sym == 0 {
- return errorf("malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", l.SymName(sect.sym), j, int(info>>32), elfsym.name, elfsym.shndx, elfsym.type_)
+ return errorf("malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", l.SymName(sect.sym), j, int(symIdx), elfsym.name, elfsym.shndx, elfsym.type_)
}
rp.Sym = elfsym.sym
}
- rp.Type = objabi.ElfRelocOffset + objabi.RelocType(info)
- rp.Size, err = relSize(arch, pn, uint32(info))
+ rp.Type = objabi.ElfRelocOffset + objabi.RelocType(relocType)
+ rp.Size, err = relSize(arch, pn, uint32(relocType))
if err != nil {
return nil, 0, err
}
@@ -1148,18 +1161,36 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, error) {
// performance.
const (
- AMD64 = uint32(sys.AMD64)
- ARM = uint32(sys.ARM)
- ARM64 = uint32(sys.ARM64)
- I386 = uint32(sys.I386)
- PPC64 = uint32(sys.PPC64)
- S390X = uint32(sys.S390X)
+ AMD64 = uint32(sys.AMD64)
+ ARM = uint32(sys.ARM)
+ ARM64 = uint32(sys.ARM64)
+ I386 = uint32(sys.I386)
+ PPC64 = uint32(sys.PPC64)
+ S390X = uint32(sys.S390X)
+ MIPS = uint32(sys.MIPS)
+ MIPS64 = uint32(sys.MIPS64)
)
switch uint32(arch.Family) | elftype<<16 {
default:
return 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
+ case MIPS | uint32(elf.R_MIPS_HI16)<<16,
+ MIPS | uint32(elf.R_MIPS_LO16)<<16,
+ MIPS | uint32(elf.R_MIPS_GOT16)<<16,
+ MIPS | uint32(elf.R_MIPS_GPREL16)<<16,
+ MIPS | uint32(elf.R_MIPS_GOT_PAGE)<<16,
+ MIPS | uint32(elf.R_MIPS_JALR)<<16,
+ MIPS | uint32(elf.R_MIPS_GOT_OFST)<<16,
+ MIPS64 | uint32(elf.R_MIPS_HI16)<<16,
+ MIPS64 | uint32(elf.R_MIPS_LO16)<<16,
+ MIPS64 | uint32(elf.R_MIPS_GOT16)<<16,
+ MIPS64 | uint32(elf.R_MIPS_GPREL16)<<16,
+ MIPS64 | uint32(elf.R_MIPS_GOT_PAGE)<<16,
+ MIPS64 | uint32(elf.R_MIPS_JALR)<<16,
+ MIPS64 | uint32(elf.R_MIPS_GOT_OFST)<<16:
+ return 4, nil
+
case S390X | uint32(elf.R_390_8)<<16:
return 1, nil