blob: d4d438747f64fa813b07f02f6a5f4bc89c89a4fa [file] [log] [blame]
Joe Damatof0bd98b2010-11-08 15:47:42 -08001#include "config.h"
Juan Cespedesd44c6b81998-09-25 14:48:42 +02002
Petr Machata157cc4d2012-04-04 19:00:34 +02003#include <assert.h>
Juan Cespedesd914a202004-11-10 00:15:33 +01004#include <endian.h>
Juan Cespedes96935a91997-08-09 23:45:39 +02005#include <errno.h>
Juan Cespedesd914a202004-11-10 00:15:33 +01006#include <error.h>
Juan Cespedes96935a91997-08-09 23:45:39 +02007#include <fcntl.h>
Juan Cespedesd914a202004-11-10 00:15:33 +01008#include <gelf.h>
Zachary T Welchbfb26c72010-12-06 23:21:00 -08009#include <inttypes.h>
Petr Machata157cc4d2012-04-04 19:00:34 +020010#include <search.h>
Juan Cespedesd914a202004-11-10 00:15:33 +010011#include <stdint.h>
12#include <stdlib.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020013#include <string.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010014#include <unistd.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020015
Juan Cespedesf7281232009-06-25 16:11:21 +020016#include "common.h"
Petr Machata366c2f42012-02-09 19:34:36 +010017#include "proc.h"
Petr Machata2b46cfc2012-02-18 11:17:29 +010018#include "library.h"
Petr Machatab5f80ac2012-04-04 01:46:18 +020019#include "filter.h"
Joe Damatof0bd98b2010-11-08 15:47:42 -080020
Paul Gilliambe320772006-04-24 22:06:23 +020021#ifdef PLT_REINITALISATION_BP
Ian Wienand2d45b1a2006-02-20 22:48:07 +010022extern char *PLTs_initialized_by_here;
Paul Gilliambe320772006-04-24 22:06:23 +020023#endif
Ian Wienand9a2ad352006-02-20 22:44:45 +010024
Petr Machatafe1c1712010-10-27 16:57:34 +020025#ifndef DT_PPC_GOT
26# define DT_PPC_GOT (DT_LOPROC + 0)
27#endif
28
Petr Machatafe1c1712010-10-27 16:57:34 +020029
Petr Machatae67635d2012-03-21 03:37:39 +010030#ifndef ARCH_HAVE_LTELF_DATA
31int
Petr Machatae67635d2012-03-21 03:37:39 +010032arch_elf_init(struct ltelf *lte)
33{
34 return 0;
35}
Petr Machatac67a6e62012-03-28 02:39:49 +020036
37void
38arch_elf_destroy(struct ltelf *lte)
39{
40}
Petr Machatae67635d2012-03-21 03:37:39 +010041#endif
42
Petr Machatae6523e62012-03-24 04:54:06 +010043int
44default_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
Petr Machata1be22912012-03-27 03:11:33 +020045 const char *a_name, GElf_Rela *rela, size_t ndx,
Petr Machatae6523e62012-03-24 04:54:06 +010046 struct library_symbol **ret)
47{
48 char *name = strdup(a_name);
49 if (name == NULL) {
50 fail:
51 free(name);
52 return -1;
53 }
54
Petr Machata1be22912012-03-27 03:11:33 +020055 GElf_Addr addr = arch_plt_sym_val(lte, ndx, rela);
Petr Machatae6523e62012-03-24 04:54:06 +010056
57 struct library_symbol *libsym = malloc(sizeof(*libsym));
58 if (libsym == NULL)
59 goto fail;
60
Petr Machataea8eb9a2012-04-17 01:32:07 +020061 /* XXX The double cast should be removed when
62 * target_address_t becomes integral type. */
63 target_address_t taddr = (target_address_t)
64 (uintptr_t)(addr + lte->bias);
Petr Machatabb790602012-03-25 01:41:59 +010065
Petr Machatae8d90762012-04-15 04:28:31 +020066 if (library_symbol_init(libsym, taddr, name, 1, LS_TOPLT_EXEC) < 0) {
67 free(libsym);
68 goto fail;
69 }
70
Petr Machatae6523e62012-03-24 04:54:06 +010071 *ret = libsym;
72 return 0;
73}
74
75#ifndef ARCH_HAVE_ADD_PLT_ENTRY
76enum plt_status
77arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
Petr Machata1be22912012-03-27 03:11:33 +020078 const char *a_name, GElf_Rela *rela, size_t ndx,
Petr Machatae6523e62012-03-24 04:54:06 +010079 struct library_symbol **ret)
80{
81 return plt_default;
82}
83#endif
84
Petr Machatae67635d2012-03-21 03:37:39 +010085Elf_Data *
86elf_loaddata(Elf_Scn *scn, GElf_Shdr *shdr)
Petr Machatafe1c1712010-10-27 16:57:34 +020087{
88 Elf_Data *data = elf_getdata(scn, NULL);
89 if (data == NULL || elf_getdata(scn, data) != NULL
90 || data->d_off || data->d_size != shdr->sh_size)
91 return NULL;
92 return data;
93}
94
Petr Machatae67635d2012-03-21 03:37:39 +010095static int
Petr Machataffd5aab2012-03-24 02:03:33 +010096elf_get_section_if(struct ltelf *lte, Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr,
97 int (*predicate)(Elf_Scn *, GElf_Shdr *, void *data),
98 void *data)
Petr Machatafe1c1712010-10-27 16:57:34 +020099{
100 int i;
101 for (i = 1; i < lte->ehdr.e_shnum; ++i) {
102 Elf_Scn *scn;
103 GElf_Shdr shdr;
104
105 scn = elf_getscn(lte->elf, i);
106 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
107 debug(1, "Couldn't read section or header.");
Petr Machatae67635d2012-03-21 03:37:39 +0100108 return -1;
109 }
Petr Machataffd5aab2012-03-24 02:03:33 +0100110 if (predicate(scn, &shdr, data)) {
111 *tgt_sec = scn;
112 *tgt_shdr = shdr;
Petr Machatafe1c1712010-10-27 16:57:34 +0200113 return 0;
Petr Machataffd5aab2012-03-24 02:03:33 +0100114 }
Petr Machatafe1c1712010-10-27 16:57:34 +0200115 }
Petr Machatae67635d2012-03-21 03:37:39 +0100116 return -1;
Petr Machataffd5aab2012-03-24 02:03:33 +0100117
118}
119
120static int
121inside_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data)
122{
123 GElf_Addr addr = *(GElf_Addr *)data;
124 return addr >= shdr->sh_addr
125 && addr < shdr->sh_addr + shdr->sh_size;
126}
127
128int
129elf_get_section_covering(struct ltelf *lte, GElf_Addr addr,
130 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
131{
132 return elf_get_section_if(lte, tgt_sec, tgt_shdr,
133 &inside_p, &addr);
134}
135
136static int
137type_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data)
138{
139 GElf_Word type = *(GElf_Word *)data;
140 return shdr->sh_type == type;
141}
142
143int
144elf_get_section_type(struct ltelf *lte, GElf_Word type,
145 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
146{
147 return elf_get_section_if(lte, tgt_sec, tgt_shdr,
148 &type_p, &type);
Petr Machatae67635d2012-03-21 03:37:39 +0100149}
150
151static int
152need_data(Elf_Data *data, size_t offset, size_t size)
153{
154 assert(data != NULL);
155 if (data->d_size < size || offset > data->d_size - size) {
156 debug(1, "Not enough data to read %zd-byte value"
157 " at offset %zd.", size, offset);
158 return -1;
159 }
Petr Machatafe1c1712010-10-27 16:57:34 +0200160 return 0;
161}
162
Petr Machatae67635d2012-03-21 03:37:39 +0100163#define DEF_READER(NAME, SIZE) \
164 int \
165 NAME(Elf_Data *data, size_t offset, uint##SIZE##_t *retp) \
166 { \
167 if (!need_data(data, offset, SIZE / 8) < 0) \
168 return -1; \
169 \
Petr Machata6d8ccb22012-03-27 03:11:57 +0200170 if (data->d_buf == NULL) /* NODATA section */ { \
171 *retp = 0; \
172 return 0; \
173 } \
174 \
Petr Machatae67635d2012-03-21 03:37:39 +0100175 union { \
176 uint##SIZE##_t dst; \
177 char buf[0]; \
178 } u; \
179 memcpy(u.buf, data->d_buf + offset, sizeof(u.dst)); \
180 *retp = u.dst; \
181 return 0; \
Petr Machatafe1c1712010-10-27 16:57:34 +0200182 }
183
Petr Machatae67635d2012-03-21 03:37:39 +0100184DEF_READER(elf_read_u16, 16)
185DEF_READER(elf_read_u32, 32)
186DEF_READER(elf_read_u64, 64)
Petr Machatafe1c1712010-10-27 16:57:34 +0200187
Petr Machatae67635d2012-03-21 03:37:39 +0100188#undef DEF_READER
Petr Machatafe1c1712010-10-27 16:57:34 +0200189
Petr Machata1974dbc2011-08-19 18:58:01 +0200190int
Petr Machata02bd9ec2011-09-21 17:38:59 +0200191open_elf(struct ltelf *lte, const char *filename)
192{
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100193 lte->fd = open(filename, O_RDONLY);
194 if (lte->fd == -1)
Petr Machata1974dbc2011-08-19 18:58:01 +0200195 return 1;
Juan Cespedes96935a91997-08-09 23:45:39 +0200196
Petr Machata02bd9ec2011-09-21 17:38:59 +0200197 elf_version(EV_CURRENT);
198
Juan Cespedesd914a202004-11-10 00:15:33 +0100199#ifdef HAVE_ELF_C_READ_MMAP
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100200 lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200201#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100202 lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200203#endif
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200204
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100205 if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF)
206 error(EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename);
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200207
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100208 if (gelf_getehdr(lte->elf, &lte->ehdr) == NULL)
209 error(EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"",
210 filename);
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200211
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100212 if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN)
213 error(EXIT_FAILURE, 0,
214 "\"%s\" is not an ELF executable nor shared library",
215 filename);
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200216
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100217 if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
218 || lte->ehdr.e_machine != LT_ELF_MACHINE)
Juan Cespedesd914a202004-11-10 00:15:33 +0100219#ifdef LT_ELF_MACHINE2
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100220 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2
221 || lte->ehdr.e_machine != LT_ELF_MACHINE2)
Juan Cespedesd914a202004-11-10 00:15:33 +0100222#endif
223#ifdef LT_ELF_MACHINE3
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100224 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3
225 || lte->ehdr.e_machine != LT_ELF_MACHINE3)
Juan Cespedesd914a202004-11-10 00:15:33 +0100226#endif
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100227 )
228 error(EXIT_FAILURE, 0,
229 "\"%s\" is ELF from incompatible architecture", filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100230
Petr Machata02bd9ec2011-09-21 17:38:59 +0200231 return 0;
232}
233
Petr Machatae67635d2012-03-21 03:37:39 +0100234static int
235do_init_elf(struct ltelf *lte, const char *filename, GElf_Addr bias)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100236{
Petr Machata02bd9ec2011-09-21 17:38:59 +0200237 int i;
238 GElf_Addr relplt_addr = 0;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100239 GElf_Addr soname_offset = 0;
Petr Machata02bd9ec2011-09-21 17:38:59 +0200240
241 debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename);
242 debug(1, "Reading ELF from %s...", filename);
243
244 if (open_elf(lte, filename) < 0)
245 return -1;
246
Petr Machatab120fdf2012-03-21 05:05:46 +0100247 /* Find out the base address. */
Petr Machata29add4f2012-02-18 16:38:05 +0100248 {
Petr Machata2b46cfc2012-02-18 11:17:29 +0100249 GElf_Phdr phdr;
250 for (i = 0; gelf_getphdr (lte->elf, i, &phdr) != NULL; ++i) {
251 if (phdr.p_type == PT_LOAD) {
Petr Machata49275b02012-04-03 12:38:51 +0200252 lte->base_addr = phdr.p_vaddr + bias;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100253 break;
254 }
255 }
256 }
257
Petr Machatab120fdf2012-03-21 05:05:46 +0100258 if (lte->base_addr == 0) {
259 fprintf(stderr, "Couldn't determine base address of %s\n",
260 filename);
261 return -1;
262 }
263
264 lte->bias = bias;
Petr Machata29add4f2012-02-18 16:38:05 +0100265 lte->entry_addr = lte->ehdr.e_entry + lte->bias;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100266
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100267 for (i = 1; i < lte->ehdr.e_shnum; ++i) {
268 Elf_Scn *scn;
269 GElf_Shdr shdr;
270 const char *name;
Juan Cespedesd914a202004-11-10 00:15:33 +0100271
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100272 scn = elf_getscn(lte->elf, i);
273 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
274 error(EXIT_FAILURE, 0,
275 "Couldn't get section header from \"%s\"",
276 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100277
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100278 name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name);
279 if (name == NULL)
280 error(EXIT_FAILURE, 0,
281 "Couldn't get section header from \"%s\"",
282 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100283
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100284 if (shdr.sh_type == SHT_SYMTAB) {
285 Elf_Data *data;
Juan Cespedesd914a202004-11-10 00:15:33 +0100286
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100287 lte->symtab = elf_getdata(scn, NULL);
288 lte->symtab_count = shdr.sh_size / shdr.sh_entsize;
289 if ((lte->symtab == NULL
290 || elf_getdata(scn, lte->symtab) != NULL)
Petr Machatada3edbf2012-04-04 02:20:21 +0200291 && options.static_filter != NULL)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100292 error(EXIT_FAILURE, 0,
293 "Couldn't get .symtab data from \"%s\"",
294 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100295
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100296 scn = elf_getscn(lte->elf, shdr.sh_link);
297 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
298 error(EXIT_FAILURE, 0,
299 "Couldn't get section header from \"%s\"",
300 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100301
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100302 data = elf_getdata(scn, NULL);
303 if (data == NULL || elf_getdata(scn, data) != NULL
304 || shdr.sh_size != data->d_size || data->d_off)
305 error(EXIT_FAILURE, 0,
306 "Couldn't get .strtab data from \"%s\"",
307 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100308
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100309 lte->strtab = data->d_buf;
310 } else if (shdr.sh_type == SHT_DYNSYM) {
311 Elf_Data *data;
Juan Cespedesd914a202004-11-10 00:15:33 +0100312
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100313 lte->dynsym = elf_getdata(scn, NULL);
314 lte->dynsym_count = shdr.sh_size / shdr.sh_entsize;
315 if (lte->dynsym == NULL
316 || elf_getdata(scn, lte->dynsym) != NULL)
317 error(EXIT_FAILURE, 0,
318 "Couldn't get .dynsym data from \"%s\"",
319 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100320
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100321 scn = elf_getscn(lte->elf, shdr.sh_link);
322 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
323 error(EXIT_FAILURE, 0,
324 "Couldn't get section header from \"%s\"",
325 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100326
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100327 data = elf_getdata(scn, NULL);
328 if (data == NULL || elf_getdata(scn, data) != NULL
329 || shdr.sh_size != data->d_size || data->d_off)
330 error(EXIT_FAILURE, 0,
331 "Couldn't get .dynstr data from \"%s\"",
332 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100333
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100334 lte->dynstr = data->d_buf;
335 } else if (shdr.sh_type == SHT_DYNAMIC) {
336 Elf_Data *data;
337 size_t j;
Juan Cespedesd914a202004-11-10 00:15:33 +0100338
Joe Damato87f4f582010-11-08 15:47:36 -0800339 lte->dyn_addr = shdr.sh_addr;
340 lte->dyn_sz = shdr.sh_size;
341
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100342 data = elf_getdata(scn, NULL);
343 if (data == NULL || elf_getdata(scn, data) != NULL)
344 error(EXIT_FAILURE, 0,
345 "Couldn't get .dynamic data from \"%s\"",
346 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100347
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100348 for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
349 GElf_Dyn dyn;
Juan Cespedesd914a202004-11-10 00:15:33 +0100350
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100351 if (gelf_getdyn(data, j, &dyn) == NULL)
352 error(EXIT_FAILURE, 0,
353 "Couldn't get .dynamic data from \"%s\"",
354 filename);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100355 if (dyn.d_tag == DT_JMPREL)
356 relplt_addr = dyn.d_un.d_ptr;
357 else if (dyn.d_tag == DT_PLTRELSZ)
Petr Machatae67635d2012-03-21 03:37:39 +0100358 lte->relplt_size = dyn.d_un.d_val;
359 else if (dyn.d_tag == DT_SONAME)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100360 soname_offset = dyn.d_un.d_val;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100361 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100362 } else if (shdr.sh_type == SHT_PROGBITS
363 || shdr.sh_type == SHT_NOBITS) {
364 if (strcmp(name, ".plt") == 0) {
365 lte->plt_addr = shdr.sh_addr;
366 lte->plt_size = shdr.sh_size;
Petr Machatae67635d2012-03-21 03:37:39 +0100367 lte->plt_data = elf_loaddata(scn, &shdr);
368 if (lte->plt_data == NULL)
369 fprintf(stderr,
370 "Can't load .plt data\n");
Petr Machata18c801c2012-04-07 01:24:08 +0200371 lte->plt_flags = shdr.sh_flags;
Petr Machatab3f8fef2006-11-30 14:45:07 +0100372 }
373#ifdef ARCH_SUPPORTS_OPD
374 else if (strcmp(name, ".opd") == 0) {
Paul Gilliam3f1219f2006-04-24 18:25:38 +0200375 lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100376 lte->opd_size = shdr.sh_size;
377 lte->opd = elf_rawdata(scn, NULL);
378 }
Petr Machatab3f8fef2006-11-30 14:45:07 +0100379#endif
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100380 }
Juan Cespedesd914a202004-11-10 00:15:33 +0100381 }
382
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100383 if (lte->dynsym == NULL || lte->dynstr == NULL)
384 error(EXIT_FAILURE, 0,
385 "Couldn't find .dynsym or .dynstr in \"%s\"", filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100386
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100387 if (!relplt_addr || !lte->plt_addr) {
388 debug(1, "%s has no PLT relocations", filename);
389 lte->relplt = NULL;
390 lte->relplt_count = 0;
Petr Machatae67635d2012-03-21 03:37:39 +0100391 } else if (lte->relplt_size == 0) {
Petr Machatafe1c1712010-10-27 16:57:34 +0200392 debug(1, "%s has unknown PLT size", filename);
393 lte->relplt = NULL;
394 lte->relplt_count = 0;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100395 } else {
Petr Machatafe1c1712010-10-27 16:57:34 +0200396
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100397 for (i = 1; i < lte->ehdr.e_shnum; ++i) {
398 Elf_Scn *scn;
399 GElf_Shdr shdr;
400
401 scn = elf_getscn(lte->elf, i);
402 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
403 error(EXIT_FAILURE, 0,
404 "Couldn't get section header from \"%s\"",
405 filename);
406 if (shdr.sh_addr == relplt_addr
Petr Machatae67635d2012-03-21 03:37:39 +0100407 && shdr.sh_size == lte->relplt_size) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100408 lte->relplt = elf_getdata(scn, NULL);
409 lte->relplt_count =
410 shdr.sh_size / shdr.sh_entsize;
411 if (lte->relplt == NULL
412 || elf_getdata(scn, lte->relplt) != NULL)
413 error(EXIT_FAILURE, 0,
414 "Couldn't get .rel*.plt data from \"%s\"",
415 filename);
416 break;
417 }
418 }
419
420 if (i == lte->ehdr.e_shnum)
421 error(EXIT_FAILURE, 0,
422 "Couldn't find .rel*.plt section in \"%s\"",
423 filename);
424
425 debug(1, "%s %zd PLT relocations", filename, lte->relplt_count);
426 }
Petr Machata2b46cfc2012-02-18 11:17:29 +0100427
428 if (soname_offset != 0)
429 lte->soname = lte->dynstr + soname_offset;
430
Petr Machata644d6692012-03-24 02:06:48 +0100431 if (arch_elf_init(lte) < 0) {
432 fprintf(stderr, "Backend initialization failed.\n");
433 return -1;
434 }
435
Petr Machata1974dbc2011-08-19 18:58:01 +0200436 return 0;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100437}
438
Petr Machata2b46cfc2012-02-18 11:17:29 +0100439/* XXX temporarily non-static */
Joe Damato7a2bdf82010-11-08 15:47:41 -0800440void
Juan Cespedesf1350522008-12-16 18:19:58 +0100441do_close_elf(struct ltelf *lte) {
Juan Cespedescd8976d2009-05-14 13:47:58 +0200442 debug(DEBUG_FUNCTION, "do_close_elf()");
Petr Machata4d9a91c2012-03-24 04:55:03 +0100443 arch_elf_destroy(lte);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100444 elf_end(lte->elf);
445 close(lte->fd);
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200446}
447
Petr Machatab5f80ac2012-04-04 01:46:18 +0200448static int
449populate_plt(struct Process *proc, const char *filename,
450 struct ltelf *lte, struct library *lib)
451{
452 size_t i;
453 for (i = 0; i < lte->relplt_count; ++i) {
454 GElf_Rel rel;
455 GElf_Rela rela;
456 GElf_Sym sym;
457 void *ret;
458
459 if (lte->relplt->d_type == ELF_T_REL) {
460 ret = gelf_getrel(lte->relplt, i, &rel);
461 rela.r_offset = rel.r_offset;
462 rela.r_info = rel.r_info;
463 rela.r_addend = 0;
464 } else {
465 ret = gelf_getrela(lte->relplt, i, &rela);
466 }
467
468 if (ret == NULL
469 || ELF64_R_SYM(rela.r_info) >= lte->dynsym_count
470 || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info),
471 &sym) == NULL)
472 error(EXIT_FAILURE, 0,
473 "Couldn't get relocation from \"%s\"",
474 filename);
475
476 char const *name = lte->dynstr + sym.st_name;
477
478 if (!filter_matches_symbol(options.plt_filter, name, lib))
479 continue;
480
Petr Machata218c5ff2012-04-15 04:22:39 +0200481 struct library_symbol *libsym = NULL;
Petr Machatab5f80ac2012-04-04 01:46:18 +0200482 switch (arch_elf_add_plt_entry(proc, lte, name,
483 &rela, i, &libsym)) {
484 case plt_default:
485 if (default_elf_add_plt_entry(proc, lte, name,
486 &rela, i, &libsym) < 0)
487 case plt_fail:
488 return -1;
489 case plt_ok:
490 if (libsym != NULL)
491 library_add_symbol(lib, libsym);
492 }
493 }
494 return 0;
495}
496
Petr Machata157cc4d2012-04-04 19:00:34 +0200497/* When -x rules result in request to trace several aliases, we only
498 * want to add such symbol once. The only way that those symbols
499 * differ in is their name, e.g. in glibc you have __GI___libc_free,
500 * __cfree, __free, __libc_free, cfree and free all defined on the
501 * same address. So instead we keep this unique symbol struct for
502 * each address, and replace name in libsym with a shorter variant if
503 * we find it. */
504struct unique_symbol {
505 target_address_t addr;
506 struct library_symbol *libsym;
507};
508
509static int
510unique_symbol_cmp(const void *key, const void *val)
511{
512 const struct unique_symbol *sym_key = key;
513 const struct unique_symbol *sym_val = val;
514 return sym_key->addr != sym_val->addr;
515}
516
Petr Machatada3edbf2012-04-04 02:20:21 +0200517static int
518populate_this_symtab(struct Process *proc, const char *filename,
519 struct ltelf *lte, struct library *lib,
520 Elf_Data *symtab, const char *strtab, size_t size)
521{
Petr Machata157cc4d2012-04-04 19:00:34 +0200522 /* Using sorted array would be arguably better, but this
523 * should be well enough for the number of symbols that we
524 * typically deal with. */
525 size_t num_symbols = 0;
526 struct unique_symbol *symbols = malloc(sizeof(*symbols) * size);
527 if (symbols == NULL) {
528 error(0, errno, "couldn't insert symbols for -x");
529 return -1;
530 }
531
Petr Machata40cc53b2012-04-07 01:25:38 +0200532 GElf_Word secflags[lte->ehdr.e_shnum];
Petr Machatada3edbf2012-04-04 02:20:21 +0200533 size_t i;
Petr Machata40cc53b2012-04-07 01:25:38 +0200534 for (i = 1; i < lte->ehdr.e_shnum; ++i) {
535 Elf_Scn *scn = elf_getscn(lte->elf, i);
536 if (scn == NULL)
537 continue;
538 GElf_Shdr shdr;
539 if (gelf_getshdr(scn, &shdr) == NULL)
540 continue;
541 secflags[i] = shdr.sh_flags;
542 }
543
544 size_t lib_len = strlen(lib->soname);
Petr Machatada3edbf2012-04-04 02:20:21 +0200545 for (i = 0; i < size; ++i) {
546 GElf_Sym sym;
Petr Machata074f68f2012-04-07 01:01:02 +0200547 if (gelf_getsym(symtab, i, &sym) == NULL) {
Petr Machatada3edbf2012-04-04 02:20:21 +0200548 fail:
549 error(0, errno, "couldn't get symbol #%zd from %s: %s",
550 i, filename, elf_errmsg(-1));
551 continue;
552 }
553
Petr Machata4de6b6b2012-04-04 14:06:09 +0200554 /* XXX support IFUNC as well. */
555 if (GELF_ST_TYPE(sym.st_info) != STT_FUNC
556 || sym.st_value == 0)
557 continue;
558
Petr Machatada3edbf2012-04-04 02:20:21 +0200559 const char *name = strtab + sym.st_name;
560 if (!filter_matches_symbol(options.static_filter, name, lib))
561 continue;
Petr Machatada3edbf2012-04-04 02:20:21 +0200562
Petr Machataea8eb9a2012-04-17 01:32:07 +0200563 target_address_t addr = (target_address_t)
564 (uintptr_t)(sym.st_value + lte->bias);
Petr Machatada3edbf2012-04-04 02:20:21 +0200565 target_address_t naddr;
Petr Machata40cc53b2012-04-07 01:25:38 +0200566
567 /* On arches that support OPD, the value of typical
568 * function symbol will be a pointer to .opd, but some
569 * will point directly to .text. We don't want to
570 * translate those. */
571 if (secflags[sym.st_shndx] & SHF_EXECINSTR) {
572 naddr = addr;
573 } else if (arch_translate_address(proc, addr, &naddr) < 0) {
Petr Machatada3edbf2012-04-04 02:20:21 +0200574 error(0, errno, "couldn't translate address of %s@%s",
575 name, lib->soname);
576 continue;
577 }
Petr Machata40cc53b2012-04-07 01:25:38 +0200578
579 /* If the translation actually took place, and wasn't
580 * a no-op, then bias again. XXX We shouldn't apply
581 * second bias for libraries that were open at the
582 * time that we attached. In fact what we should do
583 * is look at each translated address, whether it
584 * falls into a SHF_EXECINSTR section. If it does,
585 * it's most likely already translated. */
Petr Machatada3edbf2012-04-04 02:20:21 +0200586 if (addr != naddr)
587 naddr += lte->bias;
588
Petr Machata3840f682012-04-06 16:05:41 +0200589 char *full_name;
590 if (lib->type != LT_LIBTYPE_MAIN) {
591 full_name = malloc(strlen(name) + 1 + lib_len + 1);
592 if (full_name == NULL)
593 goto fail;
594 sprintf(full_name, "%s@%s", name, lib->soname);
595 } else {
596 full_name = strdup(name);
597 if (full_name == NULL)
598 goto fail;
599 }
Petr Machata4de6b6b2012-04-04 14:06:09 +0200600
Petr Machata157cc4d2012-04-04 19:00:34 +0200601 /* Look whether we already have a symbol for this
602 * address. If not, add this one. */
603 struct unique_symbol key = { naddr, NULL };
604 struct unique_symbol *unique
605 = lsearch(&key, symbols, &num_symbols,
606 sizeof(*symbols), &unique_symbol_cmp);
Petr Machatada3edbf2012-04-04 02:20:21 +0200607
Petr Machata157cc4d2012-04-04 19:00:34 +0200608 if (unique->libsym == NULL) {
609 struct library_symbol *libsym = malloc(sizeof(*libsym));
Petr Machatae8d90762012-04-15 04:28:31 +0200610 if (libsym == NULL
611 || library_symbol_init(libsym, naddr, full_name,
612 1, LS_TOPLT_NONE) < 0) {
Petr Machata157cc4d2012-04-04 19:00:34 +0200613 --num_symbols;
614 goto fail;
615 }
Petr Machata157cc4d2012-04-04 19:00:34 +0200616 unique->libsym = libsym;
617 unique->addr = naddr;
618
619 } else if (strlen(full_name) < strlen(unique->libsym->name)) {
620 library_symbol_set_name(unique->libsym, full_name, 1);
621
622 } else {
623 free(full_name);
624 }
Petr Machatada3edbf2012-04-04 02:20:21 +0200625 }
Petr Machata157cc4d2012-04-04 19:00:34 +0200626
627 for (i = 0; i < num_symbols; ++i) {
628 assert(symbols[i].libsym != NULL);
629 library_add_symbol(lib, symbols[i].libsym);
630 }
631
632 free(symbols);
633
Petr Machatada3edbf2012-04-04 02:20:21 +0200634 return 0;
635}
636
637static int
638populate_symtab(struct Process *proc, const char *filename,
639 struct ltelf *lte, struct library *lib)
640{
641 if (lte->symtab != NULL && lte->strtab != NULL)
642 return populate_this_symtab(proc, filename, lte, lib,
643 lte->symtab, lte->strtab,
644 lte->symtab_count);
645 else
646 return populate_this_symtab(proc, filename, lte, lib,
647 lte->dynsym, lte->dynstr,
648 lte->dynsym_count);
649}
650
Petr Machatab5f80ac2012-04-04 01:46:18 +0200651int
652ltelf_read_library(struct library *lib, struct Process *proc,
653 const char *filename, GElf_Addr bias)
Petr Machatae84fa002012-02-07 13:43:03 +0100654{
Petr Machata29add4f2012-02-18 16:38:05 +0100655 struct ltelf lte = {};
Petr Machatab120fdf2012-03-21 05:05:46 +0100656 if (do_init_elf(&lte, filename, bias) < 0)
Petr Machatab5f80ac2012-04-04 01:46:18 +0200657 return -1;
Petr Machatae67635d2012-03-21 03:37:39 +0100658 proc->e_machine = lte.ehdr.e_machine;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800659
Petr Machatab5f80ac2012-04-04 01:46:18 +0200660 int status = 0;
Petr Machatafc6ff182012-04-04 13:11:50 +0200661 if (lib == NULL)
662 goto fail;
663
664 /* Note that we set soname and pathname as soon as they are
665 * allocated, so in case of further errors, this get released
666 * when LIB is release, which should happen in the caller when
667 * we return error. */
668
669 if (lib->pathname == NULL) {
670 char *pathname = strdup(filename);
671 if (pathname == NULL)
672 goto fail;
Petr Machataf13afd52012-04-14 02:30:31 +0200673 library_set_pathname(lib, pathname, 1);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800674 }
675
Petr Machata0b55b582012-04-02 00:38:46 +0200676 if (lte.soname != NULL) {
Petr Machatafc6ff182012-04-04 13:11:50 +0200677 char *soname = strdup(lte.soname);
678 if (soname == NULL)
679 goto fail;
680 library_set_soname(lib, soname, 1);
Petr Machata0b55b582012-04-02 00:38:46 +0200681 } else {
Petr Machatafc6ff182012-04-04 13:11:50 +0200682 const char *soname = rindex(lib->pathname, '/') + 1;
683 if (soname == NULL)
684 soname = lib->pathname;
685 library_set_soname(lib, soname, 0);
Petr Machata0b55b582012-04-02 00:38:46 +0200686 }
Joe Damatofa2aefc2010-10-30 19:56:50 -0700687
Petr Machataea8eb9a2012-04-17 01:32:07 +0200688 /* XXX The double cast should be removed when
689 * target_address_t becomes integral type. */
690 target_address_t entry = (target_address_t)(uintptr_t)lte.entry_addr;
Petr Machata49275b02012-04-03 12:38:51 +0200691 if (arch_translate_address(proc, entry, &entry) < 0)
Petr Machatab120fdf2012-03-21 05:05:46 +0100692 goto fail;
693
Petr Machataea8eb9a2012-04-17 01:32:07 +0200694 /* XXX The double cast should be removed when
695 * target_address_t becomes integral type. */
696 lib->base = (target_address_t)(uintptr_t)lte.base_addr;
Petr Machatab120fdf2012-03-21 05:05:46 +0100697 lib->entry = entry;
Petr Machataea8eb9a2012-04-17 01:32:07 +0200698 /* XXX The double cast should be removed when
699 * target_address_t becomes integral type. */
700 lib->dyn_addr = (target_address_t)(uintptr_t)lte.dyn_addr;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100701
Petr Machatab5f80ac2012-04-04 01:46:18 +0200702 if (filter_matches_library(options.plt_filter, lib)
703 && populate_plt(proc, filename, &lte, lib) < 0)
704 goto fail;
Joe Damatoe2a8f572010-11-08 15:47:40 -0800705
Petr Machatada3edbf2012-04-04 02:20:21 +0200706 if (filter_matches_library(options.static_filter, lib)
707 && populate_symtab(proc, filename, &lte, lib) < 0)
708 goto fail;
709
Petr Machata2b46cfc2012-02-18 11:17:29 +0100710done:
711 do_close_elf(&lte);
Petr Machatab5f80ac2012-04-04 01:46:18 +0200712 return status;
Petr Machatafc6ff182012-04-04 13:11:50 +0200713
714fail:
715 status = -1;
716 goto done;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100717}
Petr Machatae84fa002012-02-07 13:43:03 +0100718
Petr Machata2b46cfc2012-02-18 11:17:29 +0100719struct library *
720ltelf_read_main_binary(struct Process *proc, const char *path)
721{
Petr Machatab5f80ac2012-04-04 01:46:18 +0200722 struct library *lib = malloc(sizeof(*lib));
723 if (lib == NULL)
724 return NULL;
725 library_init(lib, LT_LIBTYPE_MAIN);
Petr Machatafc6ff182012-04-04 13:11:50 +0200726 library_set_pathname(lib, path, 0);
Petr Machatab5f80ac2012-04-04 01:46:18 +0200727
Petr Machatafc6ff182012-04-04 13:11:50 +0200728 /* There is a race between running the process and reading its
729 * binary for internal consumption. So open the binary from
730 * the /proc filesystem. XXX Note that there is similar race
731 * for libraries, but there we don't have a nice answer like
732 * that. Presumably we could read the DSOs from the process
733 * memory image, but that's not currently done. */
Petr Machata2b46cfc2012-02-18 11:17:29 +0100734 char *fname = pid2name(proc->pid);
Petr Machatab5f80ac2012-04-04 01:46:18 +0200735 if (ltelf_read_library(lib, proc, fname, 0) < 0) {
736 library_destroy(lib);
737 free(lib);
738 return NULL;
Petr Machata0b55b582012-04-02 00:38:46 +0200739 }
Petr Machatab5f80ac2012-04-04 01:46:18 +0200740
Petr Machata2b46cfc2012-02-18 11:17:29 +0100741 return lib;
Juan Cespedes96935a91997-08-09 23:45:39 +0200742}