Beispiel #1
0
func addpltsym(ctxt *ld.Link, s *ld.LSym) {
	if s.Plt >= 0 {
		return
	}

	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 == ld.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")
	}
}
Beispiel #2
0
func addpltsym(ctxt *ld.Link, s *ld.LSym) {
	if s.Plt >= 0 {
		return
	}

	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 = ld.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")
	}
}
Beispiel #3
0
func addpltsym(ctxt *ld.Link, s *ld.LSym) {
	if s.Plt >= 0 {
		return
	}

	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, ld.R_PLT0) // add lr, pc, #0xXX00000
		addpltreloc(ctxt, plt, got, s, ld.R_PLT1) // add lr, lr, #0xYY000
		addpltreloc(ctxt, plt, got, s, ld.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")
	}
}
Beispiel #4
0
func addpltsym(s *ld.LSym) {
	if s.Plt >= 0 {
		return
	}

	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 == ld.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")
	}
}