blob: 6075d7dc03561b1c35f0f5a0b49b811cb1043276 [file] [log] [blame]
Juan Cespedesd914a202004-11-10 00:15:33 +01001#include <gelf.h>
Juan Cespedesa7af00d2009-07-26 13:23:18 +02002#include <sys/ptrace.h>
Petr Machatae67635d2012-03-21 03:37:39 +01003#include <errno.h>
4#include <error.h>
5#include <inttypes.h>
6#include <assert.h>
7
Petr Machata366c2f42012-02-09 19:34:36 +01008#include "proc.h"
Juan Cespedesf7281232009-06-25 16:11:21 +02009#include "common.h"
Petr Machatae67635d2012-03-21 03:37:39 +010010#include "library.h"
11
12#define PPC_PLT_STUB_SIZE 16
13
14static inline int
Petr Machata4e2073f2012-03-21 05:15:44 +010015host_powerpc64()
Petr Machatae67635d2012-03-21 03:37:39 +010016{
17#ifdef __powerpc64__
18 return 1;
19#else
20 return 0;
21#endif
22}
23
Juan Cespedesf1350522008-12-16 18:19:58 +010024GElf_Addr
Petr Machata4e2073f2012-03-21 05:15:44 +010025arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
26{
27 if (lte->ehdr.e_machine == EM_PPC && lte->arch.secure_plt) {
28 assert(lte->arch.plt_stub_vma != 0);
Petr Machatae67635d2012-03-21 03:37:39 +010029 return lte->arch.plt_stub_vma + PPC_PLT_STUB_SIZE * ndx;
Petr Machata4e2073f2012-03-21 05:15:44 +010030
31 } else if (lte->ehdr.e_machine == EM_PPC) {
Petr Machatae67635d2012-03-21 03:37:39 +010032 return rela->r_offset;
Petr Machata4e2073f2012-03-21 05:15:44 +010033
34 } else {
35 assert(lte->ehdr.e_machine == EM_PPC64);
36 fprintf(stderr, "PPC64\n");
37 abort();
38 return rela->r_offset;
39 }
Petr Machatae67635d2012-03-21 03:37:39 +010040}
41
42int
43arch_translate_address(struct Process *proc,
44 target_address_t addr, target_address_t *ret)
45{
Petr Machata4e2073f2012-03-21 05:15:44 +010046 if (host_powerpc64() && proc->e_machine == EM_PPC64) {
Petr Machatae67635d2012-03-21 03:37:39 +010047 long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
48 fprintf(stderr, "arch_translate_address %p->%#lx\n",
49 addr, l);
50 if (l == -1 && errno) {
51 error(0, errno, ".opd translation of %p", addr);
52 return -1;
53 }
54 *ret = (target_address_t)l;
55 return 0;
56 }
57
58 *ret = addr;
59 return 0;
Juan Cespedesd914a202004-11-10 00:15:33 +010060}
Ian Wienand9a2ad352006-02-20 22:44:45 +010061
Petr Machata2b46cfc2012-02-18 11:17:29 +010062/* XXX Apparently PPC64 doesn't support PLT breakpoints. */
Juan Cespedesf1350522008-12-16 18:19:58 +010063void *
Juan Cespedesa8909f72009-04-28 20:02:41 +020064sym2addr(Process *proc, struct library_symbol *sym) {
Olaf Heringa841f652006-09-15 01:57:49 +020065 void *addr = sym->enter_addr;
Paul Gilliam76c61f12006-06-14 06:55:21 +020066 long pt_ret;
Ian Wienand9a2ad352006-02-20 22:44:45 +010067
Ian Wienand2d45b1a2006-02-20 22:48:07 +010068 debug(3, 0);
Ian Wienand9a2ad352006-02-20 22:44:45 +010069
Paul Gilliam76c61f12006-06-14 06:55:21 +020070 if (sym->plt_type != LS_TOPLT_POINT) {
71 return addr;
Ian Wienand2d45b1a2006-02-20 22:48:07 +010072 }
Ian Wienand9a2ad352006-02-20 22:44:45 +010073
Paul Gilliam76c61f12006-06-14 06:55:21 +020074 if (proc->pid == 0) {
75 return 0;
76 }
77
Juan Cespedesda9b9532009-04-07 15:33:50 +020078 if (options.debug >= 3) {
Paul Gilliam76c61f12006-06-14 06:55:21 +020079 xinfdump(proc->pid, (void *)(((long)addr-32)&0xfffffff0),
80 sizeof(void*)*8);
81 }
82
83 // On a PowerPC-64 system, a plt is three 64-bit words: the first is the
84 // 64-bit address of the routine. Before the PLT has been initialized,
85 // this will be 0x0. In fact, the symbol table won't have the plt's
86 // address even. Ater the PLT has been initialized, but before it has
87 // been resolved, the first word will be the address of the function in
88 // the dynamic linker that will reslove the PLT. After the PLT is
89 // resolved, this will will be the address of the routine whose symbol
90 // is in the symbol table.
91
92 // On a PowerPC-32 system, there are two types of PLTs: secure (new) and
93 // non-secure (old). For the secure case, the PLT is simply a pointer
94 // and we can treat it much as we do for the PowerPC-64 case. For the
95 // non-secure case, the PLT is executable code and we can put the
96 // break-point right in the PLT.
97
98 pt_ret = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
99
Michael K. Edwards9bc4a9b2011-03-06 17:20:11 +0000100#if SIZEOF_LONG == 8
Paul Gilliam76c61f12006-06-14 06:55:21 +0200101 if (proc->mask_32bit) {
102 // Assume big-endian.
103 addr = (void *)((pt_ret >> 32) & 0xffffffff);
104 } else {
105 addr = (void *)pt_ret;
106 }
Michael K. Edwards9bc4a9b2011-03-06 17:20:11 +0000107#else
Petr Machata2b46cfc2012-02-18 11:17:29 +0100108 /* XXX Um, so where exactly are we dealing with the non-secure
109 PLT thing? */
Michael K. Edwards9bc4a9b2011-03-06 17:20:11 +0000110 addr = (void *)pt_ret;
111#endif
Paul Gilliam76c61f12006-06-14 06:55:21 +0200112
113 return addr;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100114}
Petr Machatae67635d2012-03-21 03:37:39 +0100115
116static GElf_Addr
117get_glink_vma(struct ltelf *lte, GElf_Addr ppcgot, Elf_Data *plt_data)
118{
119 Elf_Scn *ppcgot_sec = NULL;
120 GElf_Shdr ppcgot_shdr;
121 if (ppcgot != 0
122 && elf_get_section_covering(lte, ppcgot,
123 &ppcgot_sec, &ppcgot_shdr) < 0)
124 // xxx should be the log out
125 fprintf(stderr,
126 "DT_PPC_GOT=%#" PRIx64 ", but no such section found.\n",
127 ppcgot);
128
129 if (ppcgot_sec != NULL) {
130 Elf_Data *data = elf_loaddata(ppcgot_sec, &ppcgot_shdr);
131 if (data == NULL || data->d_size < 8 ) {
132 fprintf(stderr, "Couldn't read GOT data.\n");
133 } else {
134 // where PPCGOT begins in .got
135 size_t offset = ppcgot - ppcgot_shdr.sh_addr;
136 assert(offset % 4 == 0);
137 uint32_t glink_vma;
138 if (elf_read_u32(data, offset + 4, &glink_vma) < 0) {
139 fprintf(stderr,
140 "Couldn't read glink VMA address"
141 " at %zd@GOT\n", offset);
142 return 0;
143 }
144 if (glink_vma != 0) {
145 debug(1, "PPC GOT glink_vma address: %#" PRIx32,
146 glink_vma);
147 fprintf(stderr, "PPC GOT glink_vma "
148 "address: %#"PRIx32"\n", glink_vma);
149 return (GElf_Addr)glink_vma;
150 }
151 }
152 }
153
154 if (plt_data != NULL) {
155 uint32_t glink_vma;
156 if (elf_read_u32(plt_data, 0, &glink_vma) < 0) {
157 fprintf(stderr,
158 "Couldn't read glink VMA address at 0@.plt\n");
159 return 0;
160 }
161 debug(1, ".plt glink_vma address: %#" PRIx32, glink_vma);
162 fprintf(stderr, ".plt glink_vma address: "
163 "%#"PRIx32"\n", glink_vma);
164 return (GElf_Addr)glink_vma;
165 }
166
167 return 0;
168}
169
Petr Machata644d6692012-03-24 02:06:48 +0100170static int
171load_ppcgot(struct ltelf *lte, GElf_Addr *ppcgotp)
Petr Machatae67635d2012-03-21 03:37:39 +0100172{
Petr Machata644d6692012-03-24 02:06:48 +0100173 Elf_Scn *scn;
174 GElf_Shdr shdr;
175 if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
176 || scn == NULL) {
177 fail:
178 error(0, 0, "Couldn't get SHT_DYNAMIC: %s",
179 elf_errmsg(-1));
180 return -1;
Petr Machatae67635d2012-03-21 03:37:39 +0100181 }
Petr Machata644d6692012-03-24 02:06:48 +0100182
183 Elf_Data *data = elf_loaddata(scn, &shdr);
184 if (data == NULL)
185 goto fail;
186
187 size_t j;
188 for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
189 GElf_Dyn dyn;
190 if (gelf_getdyn(data, j, &dyn) == NULL)
191 goto fail;
192
193 if(dyn.d_tag == DT_PPC_GOT) {
194 *ppcgotp = dyn.d_un.d_ptr;
195 return 0;
196 }
197 }
198
199 return -1;
Petr Machatae67635d2012-03-21 03:37:39 +0100200}
201
202int
203arch_elf_init(struct ltelf *lte)
204{
Petr Machata4e2073f2012-03-21 05:15:44 +0100205 lte->arch.secure_plt = !(lte->lte_flags & LTE_PLT_EXECUTABLE);
206 if (lte->ehdr.e_machine == EM_PPC && lte->arch.secure_plt) {
Petr Machata644d6692012-03-24 02:06:48 +0100207 GElf_Addr ppcgot;
208 if (load_ppcgot(lte, &ppcgot) < 0) {
209 fprintf(stderr, "Couldn't find DT_PPC_GOT.\n");
210 return -1;
211 }
212 GElf_Addr glink_vma = get_glink_vma(lte, ppcgot, lte->plt_data);
Petr Machatae67635d2012-03-21 03:37:39 +0100213
214 assert (lte->relplt_size % 12 == 0);
215 size_t count = lte->relplt_size / 12; // size of RELA entry
216 lte->arch.plt_stub_vma = glink_vma
217 - (GElf_Addr)count * PPC_PLT_STUB_SIZE;
218 debug(1, "stub_vma is %#" PRIx64, lte->arch.plt_stub_vma);
219 }
220
221 /* Override the value that we gleaned from flags on the .plt
222 * section. The PLT entries are in fact executable, they are
223 * just not in .plt. */
224 lte->lte_flags |= LTE_PLT_EXECUTABLE;
225 return 0;
226}