plt.c revision 366c2f46d844f040458df9b7e35fc3b8527ed2d3
1#include <gelf.h>
2#include <sys/ptrace.h>
3#include "proc.h"
4#include "common.h"
5
6GElf_Addr
7arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
8	return rela->r_offset;
9}
10
11void *
12sym2addr(Process *proc, struct library_symbol *sym) {
13	void *addr = sym->enter_addr;
14	long pt_ret;
15
16	debug(3, 0);
17
18	if (sym->plt_type != LS_TOPLT_POINT) {
19		return addr;
20	}
21
22	if (proc->pid == 0) {
23		return 0;
24	}
25
26	if (options.debug >= 3) {
27		xinfdump(proc->pid, (void *)(((long)addr-32)&0xfffffff0),
28			 sizeof(void*)*8);
29	}
30
31	// On a PowerPC-64 system, a plt is three 64-bit words: the first is the
32	// 64-bit address of the routine.  Before the PLT has been initialized,
33	// this will be 0x0. In fact, the symbol table won't have the plt's
34	// address even.  Ater the PLT has been initialized, but before it has
35	// been resolved, the first word will be the address of the function in
36	// the dynamic linker that will reslove the PLT.  After the PLT is
37	// resolved, this will will be the address of the routine whose symbol
38	// is in the symbol table.
39
40	// On a PowerPC-32 system, there are two types of PLTs: secure (new) and
41	// non-secure (old).  For the secure case, the PLT is simply a pointer
42	// and we can treat it much as we do for the PowerPC-64 case.  For the
43	// non-secure case, the PLT is executable code and we can put the
44	// break-point right in the PLT.
45
46	pt_ret = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
47
48#if SIZEOF_LONG == 8
49	if (proc->mask_32bit) {
50		// Assume big-endian.
51		addr = (void *)((pt_ret >> 32) & 0xffffffff);
52	} else {
53		addr = (void *)pt_ret;
54	}
55#else
56	addr = (void *)pt_ret;
57#endif
58
59	return addr;
60}
61