diff options
Diffstat (limited to 'src/cmd/link/internal/x86/asm.go')
-rw-r--r-- | src/cmd/link/internal/x86/asm.go | 156 |
1 files changed, 79 insertions, 77 deletions
diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go index 3fe36db64d..bb7365410e 100644 --- a/src/cmd/link/internal/x86/asm.go +++ b/src/cmd/link/internal/x86/asm.go @@ -34,9 +34,11 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/ld" + "cmd/link/internal/loader" "cmd/link/internal/sym" "debug/elf" "log" + "sync" ) // Append 4 bytes to s and create a R_CALL relocation targeting t to fill them in. @@ -167,13 +169,13 @@ func gentext(ctxt *ld.Link) { initarray_entry.AddAddr(ctxt.Arch, initfunc) } -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 } @@ -195,8 +197,8 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { r.Type = objabi.R_PCREL r.Add += 4 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(targ.Plt()) } @@ -228,7 +230,7 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { return false } - addgotsym(ctxt, targ) + addgotsym(target, syms, targ) r.Type = objabi.R_CONST // write r->add during relocsym r.Sym = nil r.Add += int64(targ.Got()) @@ -240,7 +242,7 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { case objabi.ElfRelocOffset + objabi.RelocType(elf.R_386_GOTPC): r.Type = objabi.R_PCREL - r.Sym = ctxt.Syms.Lookup(".got", 0) + r.Sym = syms.GOT r.Add += 4 return true @@ -260,8 +262,8 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { case objabi.MachoRelocOffset + ld.MACHO_GENERIC_RELOC_VANILLA*2 + 1: 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(targ.Plt()) r.Type = objabi.R_PCREL return true @@ -284,8 +286,8 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { return true } - addgotsym(ctxt, targ) - r.Sym = ctxt.Syms.Lookup(".got", 0) + addgotsym(target, syms, targ) + r.Sym = syms.GOT r.Add += int64(targ.Got()) r.Type = objabi.R_PCREL return true @@ -298,12 +300,12 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { switch r.Type { case objabi.R_CALL, objabi.R_PCREL: - 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 @@ -311,17 +313,17 @@ 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_386_32))) + 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_386_32))) r.Type = objabi.R_CONST // write r->add during relocsym r.Sym = nil return true } - if ctxt.HeadType == objabi.Hdarwin && s.Size == int64(ctxt.Arch.PtrSize) && r.Off == 0 { + if target.IsDarwin() && s.Size == int64(target.Arch.PtrSize) && r.Off == 0 { // Mach-O relocations are a royal pain to lay out. // They use a compact stateful bytecode representation // that is too much bother to deal with. @@ -332,17 +334,17 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { // just in case the C code assigns to the variable, // and of course it only works for single pointers, // but we only need to support cgo and that's all it needs. - ld.Adddynsym(ctxt, targ) + ld.Adddynsym(target, syms, targ) - got := ctxt.Syms.Lookup(".got", 0) + got := syms.GOT s.Type = got.Type s.Attr |= sym.AttrSubSymbol s.Outer = got s.Sub = got.Sub got.Sub = s s.Value = got.Size - got.AddUint32(ctxt.Arch, 0) - ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(targ.Dynid)) + got.AddUint32(target.Arch, 0) + syms.LinkEditGOT.AddUint32(target.Arch, uint32(targ.Dynid)) r.Type = objabi.ElfRelocOffset // ignore during relocsym return true } @@ -492,128 +494,126 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, secto return true } -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() { return val, false } switch r.Type { 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 } 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 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 { // pushl got+4 plt.AddUint8(0xff) plt.AddUint8(0x35) - plt.AddAddrPlus(ctxt.Arch, got, 4) + plt.AddAddrPlus(ctxt.Arch, got.Sym(), 4) // jmp *got+8 plt.AddUint8(0xff) plt.AddUint8(0x25) - plt.AddAddrPlus(ctxt.Arch, got, 8) + plt.AddAddrPlus(ctxt.Arch, got.Sym(), 8) // zero pad plt.AddUint32(ctxt.Arch, 0) // assume got->size == 0 too - got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0) + got.AddAddrPlus(ctxt.Arch, dynamic, 0) got.AddUint32(ctxt.Arch, 0) got.AddUint32(ctxt.Arch, 0) } } -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") } // jmpq *got+size plt.AddUint8(0xff) plt.AddUint8(0x25) - plt.AddAddrPlus(ctxt.Arch, got, got.Size) + plt.AddAddrPlus(target.Arch, got, got.Size) // add to got: pointer to current pos in plt - got.AddAddrPlus(ctxt.Arch, plt, plt.Size) + got.AddAddrPlus(target.Arch, plt, plt.Size) // pushl $x plt.AddUint8(0x68) - plt.AddUint32(ctxt.Arch, uint32(rel.Size)) + plt.AddUint32(target.Arch, uint32(rel.Size)) // jmp .plt plt.AddUint8(0xe9) - plt.AddUint32(ctxt.Arch, uint32(-(plt.Size + 4))) + plt.AddUint32(target.Arch, uint32(-(plt.Size + 4))) // rel - rel.AddAddrPlus(ctxt.Arch, got, got.Size-4) + rel.AddAddrPlus(target.Arch, got, got.Size-4) - rel.AddUint32(ctxt.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_386_JMP_SLOT))) + rel.AddUint32(target.Arch, ld.ELF32_R_INFO(uint32(s.Dynid), uint32(elf.R_386_JMP_SLOT))) s.SetPlt(int32(plt.Size - 16)) - } else if ctxt.HeadType == objabi.Hdarwin { + } else if target.IsDarwin() { // Same laziness as in 6l. - plt := ctxt.Syms.Lookup(".plt", 0) + plt := syms.PLT - addgotsym(ctxt, s) + addgotsym(target, syms, s) - ctxt.Syms.Lookup(".linkedit.plt", 0).AddUint32(ctxt.Arch, uint32(s.Dynid)) + syms.LinkEditPLT.AddUint32(target.Arch, uint32(s.Dynid)) // jmpq *got+size(IP) s.SetPlt(int32(plt.Size)) plt.AddUint8(0xff) plt.AddUint8(0x25) - plt.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".got", 0), int64(s.Got())) + plt.AddAddrPlus(target.Arch, syms.GOT, int64(s.Got())) } else { ld.Errorf(s, "addpltsym: 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) - - 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_386_GLOB_DAT))) - } else if ctxt.HeadType == objabi.Hdarwin { - ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(s.Dynid)) + got.AddUint32(target.Arch, 0) + + 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_386_GLOB_DAT))) + } else if target.IsDarwin() { + syms.LinkEditGOT.AddUint32(target.Arch, uint32(s.Dynid)) } else { ld.Errorf(s, "addgotsym: unsupported binary format") } @@ -624,29 +624,31 @@ 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)) - // 0xCC is INT $3 - breakpoint instruction - ld.CodeblkPad(ctxt, int64(sect.Vaddr), int64(sect.Length), []byte{0xCC}) - 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 + f := func(ctxt *ld.Link, out *ld.OutBuf, start, length int64) { + ld.CodeblkPad(ctxt, out, start, length, []byte{0xCC}) + } + ld.WriteParallel(&wg, f, 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) { |