diff options
Diffstat (limited to 'src/cmd/link/internal/arm/asm.go')
-rw-r--r-- | src/cmd/link/internal/arm/asm.go | 152 |
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) { |