예제 #1
0
파일: asm.go 프로젝트: glycerine/zygomys
func addpltsym(ctxt *ld.Link, s *ld.LSym) {
	if s.Plt >= 0 {
		return
	}

	ld.Adddynsym(ctxt, s)

	if ld.Iself {
		plt := ld.Linklookup(ctxt, ".plt", 0)
		got := ld.Linklookup(ctxt, ".got.plt", 0)
		rel := ld.Linklookup(ctxt, ".rel.plt", 0)
		if plt.Size == 0 {
			elfsetupplt()
		}

		// jmpq *got+size
		ld.Adduint8(ctxt, plt, 0xff)

		ld.Adduint8(ctxt, plt, 0x25)
		ld.Addaddrplus(ctxt, plt, got, got.Size)

		// add to got: pointer to current pos in plt
		ld.Addaddrplus(ctxt, got, plt, plt.Size)

		// pushl $x
		ld.Adduint8(ctxt, plt, 0x68)

		ld.Adduint32(ctxt, plt, uint32(rel.Size))

		// jmp .plt
		ld.Adduint8(ctxt, plt, 0xe9)

		ld.Adduint32(ctxt, plt, uint32(-(plt.Size + 4)))

		// rel
		ld.Addaddrplus(ctxt, rel, got, got.Size-4)

		ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_JMP_SLOT))

		s.Plt = int32(plt.Size - 16)
	} else if ld.HEADTYPE == obj.Hdarwin {
		// Same laziness as in 6l.

		plt := ld.Linklookup(ctxt, ".plt", 0)

		addgotsym(ctxt, s)

		ld.Adduint32(ctxt, ld.Linklookup(ctxt, ".linkedit.plt", 0), uint32(s.Dynid))

		// jmpq *got+size(IP)
		s.Plt = int32(plt.Size)

		ld.Adduint8(ctxt, plt, 0xff)
		ld.Adduint8(ctxt, plt, 0x25)
		ld.Addaddrplus(ctxt, plt, ld.Linklookup(ctxt, ".got", 0), int64(s.Got))
	} else {
		ld.Diag("addpltsym: unsupported binary format")
	}
}
예제 #2
0
파일: asm.go 프로젝트: glycerine/zygomys
func addpltsym(ctxt *ld.Link, s *ld.LSym) {
	if s.Plt >= 0 {
		return
	}

	ld.Adddynsym(ctxt, s)

	if ld.Iself {
		plt := ld.Linklookup(ctxt, ".plt", 0)
		rela := ld.Linklookup(ctxt, ".rela.plt", 0)
		if plt.Size == 0 {
			elfsetupplt()
		}

		// Create the glink resolver if necessary
		glink := ensureglinkresolver()

		// Write symbol resolver stub (just a branch to the
		// glink resolver stub)
		r := ld.Addrel(glink)

		r.Sym = glink
		r.Off = int32(glink.Size)
		r.Siz = 4
		r.Type = obj.R_CALLPOWER
		ld.Adduint32(ctxt, glink, 0x48000000) // b .glink

		// In the ppc64 ABI, the dynamic linker is responsible
		// for writing the entire PLT.  We just need to
		// reserve 8 bytes for each PLT entry and generate a
		// JMP_SLOT dynamic relocation for it.
		//
		// TODO(austin): ABI v1 is different
		s.Plt = int32(plt.Size)

		plt.Size += 8

		ld.Addaddrplus(ctxt, rela, plt, int64(s.Plt))
		ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_PPC64_JMP_SLOT))
		ld.Adduint64(ctxt, rela, 0)
	} else {
		ld.Diag("addpltsym: unsupported binary format")
	}
}
예제 #3
0
파일: asm.go 프로젝트: glycerine/zygomys
func addpltsym(ctxt *ld.Link, s *ld.LSym) {
	if s.Plt >= 0 {
		return
	}

	ld.Adddynsym(ctxt, s)

	if ld.Iself {
		plt := ld.Linklookup(ctxt, ".plt", 0)
		got := ld.Linklookup(ctxt, ".got.plt", 0)
		rel := ld.Linklookup(ctxt, ".rel.plt", 0)
		if plt.Size == 0 {
			elfsetupplt()
		}

		// .got entry
		s.Got = int32(got.Size)

		// 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.
		ld.Addaddrplus(ctxt, got, plt, 0)

		// .plt entry, this depends on the .got entry
		s.Plt = int32(plt.Size)

		addpltreloc(ctxt, plt, got, s, obj.R_PLT0) // add lr, pc, #0xXX00000
		addpltreloc(ctxt, plt, got, s, obj.R_PLT1) // add lr, lr, #0xYY000
		addpltreloc(ctxt, plt, got, s, obj.R_PLT2) // ldr pc, [lr, #0xZZZ]!

		// rel
		ld.Addaddrplus(ctxt, rel, got, int64(s.Got))

		ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_ARM_JUMP_SLOT))
	} else {
		ld.Diag("addpltsym: unsupported binary format")
	}
}
예제 #4
0
파일: asm.go 프로젝트: glycerine/zygomys
func addpltsym(s *ld.LSym) {
	if s.Plt >= 0 {
		return
	}

	ld.Adddynsym(ld.Ctxt, s)

	if ld.Iself {
		plt := ld.Linklookup(ld.Ctxt, ".plt", 0)
		got := ld.Linklookup(ld.Ctxt, ".got.plt", 0)
		rela := ld.Linklookup(ld.Ctxt, ".rela.plt", 0)
		if plt.Size == 0 {
			elfsetupplt()
		}

		// jmpq *got+size(IP)
		ld.Adduint8(ld.Ctxt, plt, 0xff)

		ld.Adduint8(ld.Ctxt, plt, 0x25)
		ld.Addpcrelplus(ld.Ctxt, plt, got, got.Size)

		// add to got: pointer to current pos in plt
		ld.Addaddrplus(ld.Ctxt, got, plt, plt.Size)

		// pushq $x
		ld.Adduint8(ld.Ctxt, plt, 0x68)

		ld.Adduint32(ld.Ctxt, plt, uint32((got.Size-24-8)/8))

		// jmpq .plt
		ld.Adduint8(ld.Ctxt, plt, 0xe9)

		ld.Adduint32(ld.Ctxt, plt, uint32(-(plt.Size + 4)))

		// rela
		ld.Addaddrplus(ld.Ctxt, rela, got, got.Size-8)

		ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_X86_64_JMP_SLOT))
		ld.Adduint64(ld.Ctxt, rela, 0)

		s.Plt = int32(plt.Size - 16)
	} else if ld.HEADTYPE == obj.Hdarwin {
		// To do lazy symbol lookup right, we're supposed
		// to tell the dynamic loader which library each
		// symbol comes from and format the link info
		// section just so. I'm too lazy (ha!) to do that
		// so for now we'll just use non-lazy pointers,
		// which don't need to be told which library to use.
		//
		// http://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html
		// has details about what we're avoiding.

		addgotsym(s)
		plt := ld.Linklookup(ld.Ctxt, ".plt", 0)

		ld.Adduint32(ld.Ctxt, ld.Linklookup(ld.Ctxt, ".linkedit.plt", 0), uint32(s.Dynid))

		// jmpq *got+size(IP)
		s.Plt = int32(plt.Size)

		ld.Adduint8(ld.Ctxt, plt, 0xff)
		ld.Adduint8(ld.Ctxt, plt, 0x25)
		ld.Addpcrelplus(ld.Ctxt, plt, ld.Linklookup(ld.Ctxt, ".got", 0), int64(s.Got))
	} else {
		ld.Diag("addpltsym: unsupported binary format")
	}
}
예제 #5
0
파일: asm.go 프로젝트: glycerine/zygomys
func addpltsym(ctxt *ld.Link, s *ld.LSym) {
	if s.Plt >= 0 {
		return
	}

	ld.Adddynsym(ctxt, s)

	if ld.Iself {
		plt := ld.Linklookup(ctxt, ".plt", 0)
		got := ld.Linklookup(ctxt, ".got", 0)
		rela := ld.Linklookup(ctxt, ".rela.plt", 0)
		if plt.Size == 0 {
			elfsetupplt()
		}
		// larl    %r1,_GLOBAL_OFFSET_TABLE_+index

		ld.Adduint8(ctxt, plt, 0xc0)
		ld.Adduint8(ctxt, plt, 0x10)
		ld.Addpcrelplus(ctxt, plt, got, got.Size+6) // need variant?

		// add to got: pointer to current pos in plt
		ld.Addaddrplus(ctxt, got, plt, plt.Size+8) // weird but correct
		// lg      %r1,0(%r1)
		ld.Adduint8(ctxt, plt, 0xe3)
		ld.Adduint8(ctxt, plt, 0x10)
		ld.Adduint8(ctxt, plt, 0x10)
		ld.Adduint8(ctxt, plt, 0x00)
		ld.Adduint8(ctxt, plt, 0x00)
		ld.Adduint8(ctxt, plt, 0x04)
		// br      %r1
		ld.Adduint8(ctxt, plt, 0x07)
		ld.Adduint8(ctxt, plt, 0xf1)
		// basr    %r1,%r0
		ld.Adduint8(ctxt, plt, 0x0d)
		ld.Adduint8(ctxt, plt, 0x10)
		// lgf     %r1,12(%r1)
		ld.Adduint8(ctxt, plt, 0xe3)
		ld.Adduint8(ctxt, plt, 0x10)
		ld.Adduint8(ctxt, plt, 0x10)
		ld.Adduint8(ctxt, plt, 0x0c)
		ld.Adduint8(ctxt, plt, 0x00)
		ld.Adduint8(ctxt, plt, 0x14)
		// jg .plt
		ld.Adduint8(ctxt, plt, 0xc0)
		ld.Adduint8(ctxt, plt, 0xf4)

		ld.Adduint32(ctxt, plt, uint32(-((plt.Size - 2) >> 1))) // roll-your-own relocation
		//.plt index
		ld.Adduint32(ctxt, plt, uint32(rela.Size)) // rela size before current entry

		// rela
		ld.Addaddrplus(ctxt, rela, got, got.Size-8)

		ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_390_JMP_SLOT))
		ld.Adduint64(ctxt, rela, 0)

		s.Plt = int32(plt.Size - 32)

	} else {
		ld.Diag("addpltsym: unsupported binary format")
	}
}