aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link/internal/arm/asm.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/link/internal/arm/asm.go')
-rw-r--r--src/cmd/link/internal/arm/asm.go152
1 files changed, 76 insertions, 76 deletions
diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go
index f2fb6543d0..43ee4bf200 100644
--- a/src/cmd/link/internal/arm/asm.go
+++ b/src/cmd/link/internal/arm/asm.go
@@ -34,10 +34,12 @@ import (
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/ld"
+ "cmd/link/internal/loader"
"cmd/link/internal/sym"
"debug/elf"
"fmt"
"log"
+ "sync"
)
// This assembler:
@@ -115,13 +117,13 @@ func braddoff(a int32, b int32) int32 {
return int32((uint32(a))&0xff000000 | 0x00ffffff&uint32(a+b))
}
-func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
+func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s *sym.Symbol, r *sym.Reloc) bool {
targ := r.Sym
switch r.Type {
default:
if r.Type >= objabi.ElfRelocOffset {
- ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
+ ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(target.Arch, r.Type))
return false
}
@@ -130,8 +132,8 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
r.Type = objabi.R_CALLARM
if targ.Type == sym.SDYNIMPORT {
- addpltsym(ctxt, targ)
- r.Sym = ctxt.Syms.Lookup(".plt", 0)
+ addpltsym(target, syms, targ)
+ r.Sym = syms.PLT
r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
}
@@ -143,9 +145,9 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT32): // R_ARM_GOT_BREL
if targ.Type != sym.SDYNIMPORT {
- addgotsyminternal(ctxt, targ)
+ addgotsyminternal(target, syms, targ)
} else {
- addgotsym(ctxt, targ)
+ addgotsym(target, syms, targ)
}
r.Type = objabi.R_CONST // write r->add during relocsym
@@ -155,13 +157,13 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOT_PREL): // GOT(nil) + A - nil
if targ.Type != sym.SDYNIMPORT {
- addgotsyminternal(ctxt, targ)
+ addgotsyminternal(target, syms, targ)
} else {
- addgotsym(ctxt, targ)
+ addgotsym(target, syms, targ)
}
r.Type = objabi.R_PCREL
- r.Sym = ctxt.Syms.Lookup(".got", 0)
+ r.Sym = syms.GOT
r.Add += int64(targ.Got()) + 4
return true
@@ -173,15 +175,15 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_GOTPC): // R_ARM_BASE_PREL
r.Type = objabi.R_PCREL
- r.Sym = ctxt.Syms.Lookup(".got", 0)
+ r.Sym = syms.GOT
r.Add += 4
return true
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_CALL):
r.Type = objabi.R_CALLARM
if targ.Type == sym.SDYNIMPORT {
- addpltsym(ctxt, targ)
- r.Sym = ctxt.Syms.Lookup(".plt", 0)
+ addpltsym(target, syms, targ)
+ r.Sym = syms.PLT
r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
}
@@ -214,8 +216,8 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_JUMP24):
r.Type = objabi.R_CALLARM
if targ.Type == sym.SDYNIMPORT {
- addpltsym(ctxt, targ)
- r.Sym = ctxt.Syms.Lookup(".plt", 0)
+ addpltsym(target, syms, targ)
+ r.Sym = syms.PLT
r.Add = int64(braddoff(int32(r.Add), targ.Plt()/4))
}
@@ -229,12 +231,12 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
switch r.Type {
case objabi.R_CALLARM:
- if ctxt.LinkMode == ld.LinkExternal {
+ if target.IsExternal() {
// External linker will do this relocation.
return true
}
- addpltsym(ctxt, targ)
- r.Sym = ctxt.Syms.Lookup(".plt", 0)
+ addpltsym(target, syms, targ)
+ r.Sym = syms.PLT
r.Add = int64(targ.Plt())
return true
@@ -242,12 +244,12 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
if s.Type != sym.SDATA {
break
}
- if ctxt.IsELF {
- ld.Adddynsym(ctxt, targ)
- rel := ctxt.Syms.Lookup(".rel", 0)
- rel.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
- rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(targ.Dynid), uint32(elf.R_ARM_GLOB_DAT))) // we need a nil + A dynamic reloc
- r.Type = objabi.R_CONST // write r->add during relocsym
+ if target.IsElf() {
+ ld.Adddynsym(target, syms, targ)
+ rel := syms.Rel
+ rel.AddAddrPlus(target.Arch, s, int64(r.Off))
+ rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(targ.Dynid), uint32(elf.R_ARM_GLOB_DAT))) // we need a nil + A dynamic reloc
+ r.Type = objabi.R_CONST // write r->add during relocsym
r.Sym = nil
return true
}
@@ -300,10 +302,8 @@ func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
return true
}
-func elfsetupplt(ctxt *ld.Link) {
- plt := ctxt.Syms.Lookup(".plt", 0)
- got := ctxt.Syms.Lookup(".got.plt", 0)
- if plt.Size == 0 {
+func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
+ if plt.Size() == 0 {
// str lr, [sp, #-4]!
plt.AddUint32(ctxt.Arch, 0xe52de004)
@@ -317,7 +317,7 @@ func elfsetupplt(ctxt *ld.Link) {
plt.AddUint32(ctxt.Arch, 0xe5bef008)
// .word &GLOBAL_OFFSET_TABLE[0] - .
- plt.AddPCRelPlus(ctxt.Arch, got, 4)
+ plt.AddPCRelPlus(ctxt.Arch, got.Sym(), 4)
// the first .plt entry requires 3 .plt.got entries
got.AddUint32(ctxt.Arch, 0)
@@ -597,8 +597,8 @@ func gentrampdyn(arch *sys.Arch, tramp, target *sym.Symbol, offset int64) {
}
}
-func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
- if ctxt.LinkMode == ld.LinkExternal {
+func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
+ if target.IsExternal() {
switch r.Type {
case objabi.R_CALLARM:
r.Done = false
@@ -623,7 +623,7 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
// the section load address.
// we need to compensate that by removing the instruction's address
// from addend.
- if ctxt.HeadType == objabi.Hdarwin {
+ if target.IsDarwin() {
r.Xadd -= ld.Symaddr(s) + int64(r.Off)
}
@@ -641,19 +641,19 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
case objabi.R_CONST:
return r.Add, true
case objabi.R_GOTOFF:
- return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
+ return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true
// The following three arch specific relocations are only for generation of
// Linux/ARM ELF's PLT entry (3 assembler instruction)
case objabi.R_PLT0: // add ip, pc, #0xXX00000
- if ld.Symaddr(ctxt.Syms.Lookup(".got.plt", 0)) < ld.Symaddr(ctxt.Syms.Lookup(".plt", 0)) {
+ if ld.Symaddr(syms.GOTPLT) < ld.Symaddr(syms.PLT) {
ld.Errorf(s, ".got.plt should be placed after .plt section.")
}
- return 0xe28fc600 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add)) >> 20)), true
+ return 0xe28fc600 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(syms.PLT)+int64(r.Off))+r.Add)) >> 20)), true
case objabi.R_PLT1: // add ip, ip, #0xYY000
- return 0xe28cca00 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add+4)) >> 12)), true
+ return 0xe28cca00 + (0xff & (int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(syms.PLT)+int64(r.Off))+r.Add+4)) >> 12)), true
case objabi.R_PLT2: // ldr pc, [ip, #0xZZZ]!
- return 0xe5bcf000 + (0xfff & int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(ctxt.Syms.Lookup(".plt", 0))+int64(r.Off))+r.Add+8))), true
+ return 0xe5bcf000 + (0xfff & int64(uint32(ld.Symaddr(r.Sym)-(ld.Symaddr(syms.PLT)+int64(r.Off))+r.Add+8))), true
case objabi.R_CALLARM: // bl XXXXXX or b YYYYYY
// r.Add is the instruction
// low 24-bit encodes the target address
@@ -667,12 +667,12 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
return val, false
}
-func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
+func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
log.Fatalf("unexpected relocation variant")
return t
}
-func addpltreloc(ctxt *ld.Link, plt *sym.Symbol, got *sym.Symbol, s *sym.Symbol, typ objabi.RelocType) {
+func addpltreloc(plt *sym.Symbol, got *sym.Symbol, s *sym.Symbol, typ objabi.RelocType) {
r := plt.AddRel()
r.Sym = got
r.Off = int32(plt.Size)
@@ -685,19 +685,19 @@ func addpltreloc(ctxt *ld.Link, plt *sym.Symbol, got *sym.Symbol, s *sym.Symbol,
plt.Grow(plt.Size)
}
-func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
+func addpltsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
if s.Plt() >= 0 {
return
}
- ld.Adddynsym(ctxt, s)
+ ld.Adddynsym(target, syms, s)
- if ctxt.IsELF {
- plt := ctxt.Syms.Lookup(".plt", 0)
- got := ctxt.Syms.Lookup(".got.plt", 0)
- rel := ctxt.Syms.Lookup(".rel.plt", 0)
+ if target.IsElf() {
+ plt := syms.PLT
+ got := syms.GOTPLT
+ rel := syms.RelPLT
if plt.Size == 0 {
- elfsetupplt(ctxt)
+ panic("plt is not set up")
}
// .got entry
@@ -706,54 +706,54 @@ func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
// In theory, all GOT should point to the first PLT entry,
// Linux/ARM's dynamic linker will do that for us, but FreeBSD/ARM's
// dynamic linker won't, so we'd better do it ourselves.
- got.AddAddrPlus(ctxt.Arch, plt, 0)
+ got.AddAddrPlus(target.Arch, plt, 0)
// .plt entry, this depends on the .got entry
s.SetPlt(int32(plt.Size))
- addpltreloc(ctxt, plt, got, s, objabi.R_PLT0) // add lr, pc, #0xXX00000
- addpltreloc(ctxt, plt, got, s, objabi.R_PLT1) // add lr, lr, #0xYY000
- addpltreloc(ctxt, plt, got, s, objabi.R_PLT2) // ldr pc, [lr, #0xZZZ]!
+ addpltreloc(plt, got, s, objabi.R_PLT0) // add lr, pc, #0xXX00000
+ addpltreloc(plt, got, s, objabi.R_PLT1) // add lr, lr, #0xYY000
+ addpltreloc(plt, got, s, objabi.R_PLT2) // ldr pc, [lr, #0xZZZ]!
// rel
- rel.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
+ rel.AddAddrPlus(target.Arch, got, int64(s.Got()))
- rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_JUMP_SLOT)))
+ rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_JUMP_SLOT)))
} else {
ld.Errorf(s, "addpltsym: unsupported binary format")
}
}
-func addgotsyminternal(ctxt *ld.Link, s *sym.Symbol) {
+func addgotsyminternal(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
if s.Got() >= 0 {
return
}
- got := ctxt.Syms.Lookup(".got", 0)
+ got := syms.GOT
s.SetGot(int32(got.Size))
- got.AddAddrPlus(ctxt.Arch, s, 0)
+ got.AddAddrPlus(target.Arch, s, 0)
- if ctxt.IsELF {
+ if target.IsElf() {
} else {
ld.Errorf(s, "addgotsyminternal: unsupported binary format")
}
}
-func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
+func addgotsym(target *ld.Target, syms *ld.ArchSyms, s *sym.Symbol) {
if s.Got() >= 0 {
return
}
- ld.Adddynsym(ctxt, s)
- got := ctxt.Syms.Lookup(".got", 0)
+ ld.Adddynsym(target, syms, s)
+ got := syms.GOT
s.SetGot(int32(got.Size))
- got.AddUint32(ctxt.Arch, 0)
+ got.AddUint32(target.Arch, 0)
- if ctxt.IsELF {
- rel := ctxt.Syms.Lookup(".rel", 0)
- rel.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
- rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_GLOB_DAT)))
+ if target.IsElf() {
+ rel := syms.Rel
+ rel.AddAddrPlus(target.Arch, got, int64(s.Got()))
+ rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_ARM_GLOB_DAT)))
} else {
ld.Errorf(s, "addgotsym: unsupported binary format")
}
@@ -764,28 +764,28 @@ func asmb(ctxt *ld.Link) {
ld.Asmbelfsetup()
}
+ var wg sync.WaitGroup
sect := ld.Segtext.Sections[0]
- ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
- ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
- for _, sect = range ld.Segtext.Sections[1:] {
- ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
- ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
+ offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
+ ld.WriteParallel(&wg, ld.Codeblk, ctxt, offset, sect.Vaddr, sect.Length)
+
+ for _, sect := range ld.Segtext.Sections[1:] {
+ offset := sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff
+ ld.WriteParallel(&wg, ld.Datblk, ctxt, offset, sect.Vaddr, sect.Length)
}
if ld.Segrodata.Filelen > 0 {
- ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
- ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
+ ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrodata.Fileoff, ld.Segrodata.Vaddr, ld.Segrodata.Filelen)
}
+
if ld.Segrelrodata.Filelen > 0 {
- ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
- ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
+ ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segrelrodata.Fileoff, ld.Segrelrodata.Vaddr, ld.Segrelrodata.Filelen)
}
- ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
- ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+ ld.WriteParallel(&wg, ld.Datblk, ctxt, ld.Segdata.Fileoff, ld.Segdata.Vaddr, ld.Segdata.Filelen)
- ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
- ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
+ ld.WriteParallel(&wg, ld.Dwarfblk, ctxt, ld.Segdwarf.Fileoff, ld.Segdwarf.Vaddr, ld.Segdwarf.Filelen)
+ wg.Wait()
}
func asmb2(ctxt *ld.Link) {