blob: 14826c0fefd65b7e28d34321a6a26dbe14bfba0d [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>
Andrey Zonov9d878c92012-08-05 00:19:51 +04004#ifdef __linux__
Juan Cespedesd914a202004-11-10 00:15:33 +01005#include <endian.h>
Andrey Zonov9d878c92012-08-05 00:19:51 +04006#endif
Juan Cespedes96935a91997-08-09 23:45:39 +02007#include <errno.h>
Juan Cespedes96935a91997-08-09 23:45:39 +02008#include <fcntl.h>
Juan Cespedesd914a202004-11-10 00:15:33 +01009#include <gelf.h>
Zachary T Welchbfb26c72010-12-06 23:21:00 -080010#include <inttypes.h>
Petr Machata157cc4d2012-04-04 19:00:34 +020011#include <search.h>
Juan Cespedesd914a202004-11-10 00:15:33 +010012#include <stdint.h>
Petr Machatacc0e1e42012-04-25 13:42:07 +020013#include <stdio.h>
Juan Cespedesd914a202004-11-10 00:15:33 +010014#include <stdlib.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020015#include <string.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010016#include <unistd.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020017
Juan Cespedesf7281232009-06-25 16:11:21 +020018#include "common.h"
Petr Machata366c2f42012-02-09 19:34:36 +010019#include "proc.h"
Petr Machata2b46cfc2012-02-18 11:17:29 +010020#include "library.h"
Petr Machatab5f80ac2012-04-04 01:46:18 +020021#include "filter.h"
Joe Damatof0bd98b2010-11-08 15:47:42 -080022
Paul Gilliambe320772006-04-24 22:06:23 +020023#ifdef PLT_REINITALISATION_BP
Ian Wienand2d45b1a2006-02-20 22:48:07 +010024extern char *PLTs_initialized_by_here;
Paul Gilliambe320772006-04-24 22:06:23 +020025#endif
Ian Wienand9a2ad352006-02-20 22:44:45 +010026
Petr Machatae67635d2012-03-21 03:37:39 +010027#ifndef ARCH_HAVE_LTELF_DATA
28int
Petr Machatae0615ab2012-04-17 05:17:48 +020029arch_elf_init(struct ltelf *lte, struct library *lib)
Petr Machatae67635d2012-03-21 03:37:39 +010030{
31 return 0;
32}
Petr Machatac67a6e62012-03-28 02:39:49 +020033
34void
35arch_elf_destroy(struct ltelf *lte)
36{
37}
Petr Machatae67635d2012-03-21 03:37:39 +010038#endif
39
Petr Machatae6523e62012-03-24 04:54:06 +010040int
41default_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
Petr Machata1be22912012-03-27 03:11:33 +020042 const char *a_name, GElf_Rela *rela, size_t ndx,
Petr Machatae6523e62012-03-24 04:54:06 +010043 struct library_symbol **ret)
44{
45 char *name = strdup(a_name);
46 if (name == NULL) {
47 fail:
48 free(name);
49 return -1;
50 }
51
Petr Machata1be22912012-03-27 03:11:33 +020052 GElf_Addr addr = arch_plt_sym_val(lte, ndx, rela);
Petr Machatae6523e62012-03-24 04:54:06 +010053
54 struct library_symbol *libsym = malloc(sizeof(*libsym));
55 if (libsym == NULL)
56 goto fail;
57
Petr Machataea8eb9a2012-04-17 01:32:07 +020058 /* XXX The double cast should be removed when
59 * target_address_t becomes integral type. */
60 target_address_t taddr = (target_address_t)
61 (uintptr_t)(addr + lte->bias);
Petr Machatabb790602012-03-25 01:41:59 +010062
Petr Machatae8d90762012-04-15 04:28:31 +020063 if (library_symbol_init(libsym, taddr, name, 1, LS_TOPLT_EXEC) < 0) {
64 free(libsym);
65 goto fail;
66 }
67
Petr Machatae6523e62012-03-24 04:54:06 +010068 *ret = libsym;
69 return 0;
70}
71
72#ifndef ARCH_HAVE_ADD_PLT_ENTRY
73enum plt_status
74arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
Petr Machata1be22912012-03-27 03:11:33 +020075 const char *a_name, GElf_Rela *rela, size_t ndx,
Petr Machatae6523e62012-03-24 04:54:06 +010076 struct library_symbol **ret)
77{
78 return plt_default;
79}
80#endif
81
Petr Machatae67635d2012-03-21 03:37:39 +010082Elf_Data *
83elf_loaddata(Elf_Scn *scn, GElf_Shdr *shdr)
Petr Machatafe1c1712010-10-27 16:57:34 +020084{
85 Elf_Data *data = elf_getdata(scn, NULL);
86 if (data == NULL || elf_getdata(scn, data) != NULL
87 || data->d_off || data->d_size != shdr->sh_size)
88 return NULL;
89 return data;
90}
91
Petr Machatae67635d2012-03-21 03:37:39 +010092static int
Petr Machataffd5aab2012-03-24 02:03:33 +010093elf_get_section_if(struct ltelf *lte, Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr,
94 int (*predicate)(Elf_Scn *, GElf_Shdr *, void *data),
95 void *data)
Petr Machatafe1c1712010-10-27 16:57:34 +020096{
97 int i;
98 for (i = 1; i < lte->ehdr.e_shnum; ++i) {
99 Elf_Scn *scn;
100 GElf_Shdr shdr;
101
102 scn = elf_getscn(lte->elf, i);
103 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
104 debug(1, "Couldn't read section or header.");
Petr Machatae67635d2012-03-21 03:37:39 +0100105 return -1;
106 }
Petr Machataffd5aab2012-03-24 02:03:33 +0100107 if (predicate(scn, &shdr, data)) {
108 *tgt_sec = scn;
109 *tgt_shdr = shdr;
Petr Machatafe1c1712010-10-27 16:57:34 +0200110 return 0;
Petr Machataffd5aab2012-03-24 02:03:33 +0100111 }
Petr Machatafe1c1712010-10-27 16:57:34 +0200112 }
Petr Machatae67635d2012-03-21 03:37:39 +0100113 return -1;
Petr Machataffd5aab2012-03-24 02:03:33 +0100114
115}
116
117static int
118inside_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data)
119{
120 GElf_Addr addr = *(GElf_Addr *)data;
121 return addr >= shdr->sh_addr
122 && addr < shdr->sh_addr + shdr->sh_size;
123}
124
125int
126elf_get_section_covering(struct ltelf *lte, GElf_Addr addr,
127 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
128{
129 return elf_get_section_if(lte, tgt_sec, tgt_shdr,
130 &inside_p, &addr);
131}
132
133static int
134type_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data)
135{
136 GElf_Word type = *(GElf_Word *)data;
137 return shdr->sh_type == type;
138}
139
140int
141elf_get_section_type(struct ltelf *lte, GElf_Word type,
142 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
143{
144 return elf_get_section_if(lte, tgt_sec, tgt_shdr,
145 &type_p, &type);
Petr Machatae67635d2012-03-21 03:37:39 +0100146}
147
Petr Machata5b3e26a2012-04-30 20:53:22 +0200148struct section_named_data {
149 struct ltelf *lte;
150 const char *name;
151};
152
153static int
154name_p(Elf_Scn *scn, GElf_Shdr *shdr, void *d)
155{
156 struct section_named_data *data = d;
157 const char *name = elf_strptr(data->lte->elf,
158 data->lte->ehdr.e_shstrndx,
159 shdr->sh_name);
160 return strcmp(name, data->name) == 0;
161}
162
163int
164elf_get_section_named(struct ltelf *lte, const char *name,
165 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
166{
167 struct section_named_data data = {
168 .lte = lte,
169 .name = name,
170 };
171 return elf_get_section_if(lte, tgt_sec, tgt_shdr,
172 &name_p, &data);
173}
174
Petr Machatae67635d2012-03-21 03:37:39 +0100175static int
Petr Machata3a01cd72012-04-30 20:50:20 +0200176need_data(Elf_Data *data, GElf_Xword offset, GElf_Xword size)
Petr Machatae67635d2012-03-21 03:37:39 +0100177{
178 assert(data != NULL);
179 if (data->d_size < size || offset > data->d_size - size) {
Petr Machataa82d3222012-05-01 01:04:27 +0200180 debug(1, "Not enough data to read %"PRId64"-byte value"
181 " at offset %"PRId64".", size, offset);
Petr Machatae67635d2012-03-21 03:37:39 +0100182 return -1;
183 }
Petr Machatafe1c1712010-10-27 16:57:34 +0200184 return 0;
185}
186
Petr Machatae67635d2012-03-21 03:37:39 +0100187#define DEF_READER(NAME, SIZE) \
188 int \
Petr Machata3a01cd72012-04-30 20:50:20 +0200189 NAME(Elf_Data *data, GElf_Xword offset, uint##SIZE##_t *retp) \
Petr Machatae67635d2012-03-21 03:37:39 +0100190 { \
191 if (!need_data(data, offset, SIZE / 8) < 0) \
192 return -1; \
193 \
Petr Machata6d8ccb22012-03-27 03:11:57 +0200194 if (data->d_buf == NULL) /* NODATA section */ { \
195 *retp = 0; \
196 return 0; \
197 } \
198 \
Petr Machatae67635d2012-03-21 03:37:39 +0100199 union { \
200 uint##SIZE##_t dst; \
201 char buf[0]; \
202 } u; \
203 memcpy(u.buf, data->d_buf + offset, sizeof(u.dst)); \
204 *retp = u.dst; \
205 return 0; \
Petr Machatafe1c1712010-10-27 16:57:34 +0200206 }
207
Petr Machatae67635d2012-03-21 03:37:39 +0100208DEF_READER(elf_read_u16, 16)
209DEF_READER(elf_read_u32, 32)
210DEF_READER(elf_read_u64, 64)
Petr Machatafe1c1712010-10-27 16:57:34 +0200211
Petr Machatae67635d2012-03-21 03:37:39 +0100212#undef DEF_READER
Petr Machatafe1c1712010-10-27 16:57:34 +0200213
Petr Machata1974dbc2011-08-19 18:58:01 +0200214int
Petr Machata02bd9ec2011-09-21 17:38:59 +0200215open_elf(struct ltelf *lte, const char *filename)
216{
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100217 lte->fd = open(filename, O_RDONLY);
218 if (lte->fd == -1)
Petr Machata1974dbc2011-08-19 18:58:01 +0200219 return 1;
Juan Cespedes96935a91997-08-09 23:45:39 +0200220
Petr Machata02bd9ec2011-09-21 17:38:59 +0200221 elf_version(EV_CURRENT);
222
Juan Cespedesd914a202004-11-10 00:15:33 +0100223#ifdef HAVE_ELF_C_READ_MMAP
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100224 lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200225#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100226 lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200227#endif
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200228
Petr Machatacc0e1e42012-04-25 13:42:07 +0200229 if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF) {
230 fprintf(stderr, "\"%s\" is not an ELF file\n", filename);
231 exit(EXIT_FAILURE);
232 }
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200233
Petr Machatacc0e1e42012-04-25 13:42:07 +0200234 if (gelf_getehdr(lte->elf, &lte->ehdr) == NULL) {
235 fprintf(stderr, "can't read ELF header of \"%s\": %s\n",
236 filename, elf_errmsg(-1));
237 exit(EXIT_FAILURE);
238 }
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200239
Petr Machatacc0e1e42012-04-25 13:42:07 +0200240 if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN) {
241 fprintf(stderr, "\"%s\" is neither an ELF executable"
242 " nor a shared library\n", filename);
243 exit(EXIT_FAILURE);
244 }
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200245
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100246 if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
247 || lte->ehdr.e_machine != LT_ELF_MACHINE)
Juan Cespedesd914a202004-11-10 00:15:33 +0100248#ifdef LT_ELF_MACHINE2
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100249 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2
250 || lte->ehdr.e_machine != LT_ELF_MACHINE2)
Juan Cespedesd914a202004-11-10 00:15:33 +0100251#endif
252#ifdef LT_ELF_MACHINE3
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100253 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3
254 || lte->ehdr.e_machine != LT_ELF_MACHINE3)
Juan Cespedesd914a202004-11-10 00:15:33 +0100255#endif
Petr Machatacc0e1e42012-04-25 13:42:07 +0200256 ) {
257 fprintf(stderr,
258 "\"%s\" is ELF from incompatible architecture\n",
259 filename);
260 exit(EXIT_FAILURE);
261 }
Juan Cespedesd914a202004-11-10 00:15:33 +0100262
Petr Machata02bd9ec2011-09-21 17:38:59 +0200263 return 0;
264}
265
Petr Machatacc0e1e42012-04-25 13:42:07 +0200266static void
267read_symbol_table(struct ltelf *lte, const char *filename,
268 Elf_Scn *scn, GElf_Shdr *shdr, const char *name,
269 Elf_Data **datap, size_t *countp, const char **strsp)
270{
271 *datap = elf_getdata(scn, NULL);
272 *countp = shdr->sh_size / shdr->sh_entsize;
273 if ((*datap == NULL || elf_getdata(scn, *datap) != NULL)
274 && options.static_filter != NULL) {
275 fprintf(stderr, "Couldn't get data of section"
276 " %s from \"%s\": %s\n",
277 name, filename, elf_errmsg(-1));
278 exit(EXIT_FAILURE);
279 }
280
281 scn = elf_getscn(lte->elf, shdr->sh_link);
282 GElf_Shdr shdr2;
283 if (scn == NULL || gelf_getshdr(scn, &shdr2) == NULL) {
284 fprintf(stderr, "Couldn't get header of section"
285 " #%d from \"%s\": %s\n",
286 shdr2.sh_link, filename, elf_errmsg(-1));
287 exit(EXIT_FAILURE);
288 }
289
290 Elf_Data *data = elf_getdata(scn, NULL);
291 if (data == NULL || elf_getdata(scn, data) != NULL
292 || shdr2.sh_size != data->d_size || data->d_off) {
293 fprintf(stderr, "Couldn't get data of section"
294 " #%d from \"%s\": %s\n",
295 shdr2.sh_link, filename, elf_errmsg(-1));
296 exit(EXIT_FAILURE);
297 }
298
299 *strsp = data->d_buf;
300}
301
Petr Machatae67635d2012-03-21 03:37:39 +0100302static int
303do_init_elf(struct ltelf *lte, const char *filename, GElf_Addr bias)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100304{
Petr Machata02bd9ec2011-09-21 17:38:59 +0200305 int i;
306 GElf_Addr relplt_addr = 0;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100307 GElf_Addr soname_offset = 0;
Petr Machata02bd9ec2011-09-21 17:38:59 +0200308
309 debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename);
310 debug(1, "Reading ELF from %s...", filename);
311
312 if (open_elf(lte, filename) < 0)
313 return -1;
314
Petr Machatab120fdf2012-03-21 05:05:46 +0100315 /* Find out the base address. */
Petr Machata29add4f2012-02-18 16:38:05 +0100316 {
Petr Machata2b46cfc2012-02-18 11:17:29 +0100317 GElf_Phdr phdr;
318 for (i = 0; gelf_getphdr (lte->elf, i, &phdr) != NULL; ++i) {
319 if (phdr.p_type == PT_LOAD) {
Petr Machata49275b02012-04-03 12:38:51 +0200320 lte->base_addr = phdr.p_vaddr + bias;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100321 break;
322 }
323 }
324 }
325
Petr Machatab120fdf2012-03-21 05:05:46 +0100326 if (lte->base_addr == 0) {
327 fprintf(stderr, "Couldn't determine base address of %s\n",
328 filename);
329 return -1;
330 }
331
332 lte->bias = bias;
Petr Machata29add4f2012-02-18 16:38:05 +0100333 lte->entry_addr = lte->ehdr.e_entry + lte->bias;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100334
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100335 for (i = 1; i < lte->ehdr.e_shnum; ++i) {
336 Elf_Scn *scn;
337 GElf_Shdr shdr;
338 const char *name;
Juan Cespedesd914a202004-11-10 00:15:33 +0100339
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100340 scn = elf_getscn(lte->elf, i);
Petr Machatacc0e1e42012-04-25 13:42:07 +0200341 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
342 fprintf(stderr, "Couldn't get section #%d from"
343 " \"%s\": %s\n", i, filename, elf_errmsg(-1));
344 exit(EXIT_FAILURE);
345 }
Juan Cespedesd914a202004-11-10 00:15:33 +0100346
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100347 name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name);
Petr Machatacc0e1e42012-04-25 13:42:07 +0200348 if (name == NULL) {
349 fprintf(stderr, "Couldn't get name of section #%d from"
350 " \"%s\": %s\n", i, filename, elf_errmsg(-1));
351 exit(EXIT_FAILURE);
352 }
Juan Cespedesd914a202004-11-10 00:15:33 +0100353
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100354 if (shdr.sh_type == SHT_SYMTAB) {
Petr Machatacc0e1e42012-04-25 13:42:07 +0200355 read_symbol_table(lte, filename,
356 scn, &shdr, name, &lte->symtab,
357 &lte->symtab_count, &lte->strtab);
Juan Cespedesd914a202004-11-10 00:15:33 +0100358
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100359 } else if (shdr.sh_type == SHT_DYNSYM) {
Petr Machatacc0e1e42012-04-25 13:42:07 +0200360 read_symbol_table(lte, filename,
361 scn, &shdr, name, &lte->dynsym,
362 &lte->dynsym_count, &lte->dynstr);
Juan Cespedesd914a202004-11-10 00:15:33 +0100363
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100364 } else if (shdr.sh_type == SHT_DYNAMIC) {
365 Elf_Data *data;
366 size_t j;
Juan Cespedesd914a202004-11-10 00:15:33 +0100367
Joe Damato87f4f582010-11-08 15:47:36 -0800368 lte->dyn_addr = shdr.sh_addr;
369 lte->dyn_sz = shdr.sh_size;
370
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100371 data = elf_getdata(scn, NULL);
Petr Machatacc0e1e42012-04-25 13:42:07 +0200372 if (data == NULL || elf_getdata(scn, data) != NULL) {
373 fprintf(stderr, "Couldn't get .dynamic data"
374 " from \"%s\": %s\n",
375 filename, strerror(errno));
376 exit(EXIT_FAILURE);
377 }
Juan Cespedesd914a202004-11-10 00:15:33 +0100378
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100379 for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
380 GElf_Dyn dyn;
Juan Cespedesd914a202004-11-10 00:15:33 +0100381
Petr Machatacc0e1e42012-04-25 13:42:07 +0200382 if (gelf_getdyn(data, j, &dyn) == NULL) {
383 fprintf(stderr, "Couldn't get .dynamic"
384 " data from \"%s\": %s\n",
385 filename, strerror(errno));
386 exit(EXIT_FAILURE);
387 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100388 if (dyn.d_tag == DT_JMPREL)
389 relplt_addr = dyn.d_un.d_ptr;
390 else if (dyn.d_tag == DT_PLTRELSZ)
Petr Machatae67635d2012-03-21 03:37:39 +0100391 lte->relplt_size = dyn.d_un.d_val;
392 else if (dyn.d_tag == DT_SONAME)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100393 soname_offset = dyn.d_un.d_val;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100394 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100395 } else if (shdr.sh_type == SHT_PROGBITS
396 || shdr.sh_type == SHT_NOBITS) {
397 if (strcmp(name, ".plt") == 0) {
398 lte->plt_addr = shdr.sh_addr;
399 lte->plt_size = shdr.sh_size;
Petr Machatae67635d2012-03-21 03:37:39 +0100400 lte->plt_data = elf_loaddata(scn, &shdr);
401 if (lte->plt_data == NULL)
402 fprintf(stderr,
403 "Can't load .plt data\n");
Petr Machata18c801c2012-04-07 01:24:08 +0200404 lte->plt_flags = shdr.sh_flags;
Petr Machatab3f8fef2006-11-30 14:45:07 +0100405 }
406#ifdef ARCH_SUPPORTS_OPD
407 else if (strcmp(name, ".opd") == 0) {
Paul Gilliam3f1219f2006-04-24 18:25:38 +0200408 lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100409 lte->opd_size = shdr.sh_size;
410 lte->opd = elf_rawdata(scn, NULL);
411 }
Petr Machatab3f8fef2006-11-30 14:45:07 +0100412#endif
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100413 }
Juan Cespedesd914a202004-11-10 00:15:33 +0100414 }
415
Petr Machatacc0e1e42012-04-25 13:42:07 +0200416 if (lte->dynsym == NULL || lte->dynstr == NULL) {
417 fprintf(stderr, "Couldn't find .dynsym or .dynstr in \"%s\"\n",
418 filename);
419 exit(EXIT_FAILURE);
420 }
Juan Cespedesd914a202004-11-10 00:15:33 +0100421
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100422 if (!relplt_addr || !lte->plt_addr) {
423 debug(1, "%s has no PLT relocations", filename);
424 lte->relplt = NULL;
425 lte->relplt_count = 0;
Petr Machatae67635d2012-03-21 03:37:39 +0100426 } else if (lte->relplt_size == 0) {
Petr Machatafe1c1712010-10-27 16:57:34 +0200427 debug(1, "%s has unknown PLT size", filename);
428 lte->relplt = NULL;
429 lte->relplt_count = 0;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100430 } else {
Petr Machatafe1c1712010-10-27 16:57:34 +0200431
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100432 for (i = 1; i < lte->ehdr.e_shnum; ++i) {
433 Elf_Scn *scn;
434 GElf_Shdr shdr;
435
436 scn = elf_getscn(lte->elf, i);
Petr Machatacc0e1e42012-04-25 13:42:07 +0200437 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
438 fprintf(stderr, "Couldn't get section header"
439 " from \"%s\": %s\n",
440 filename, elf_errmsg(-1));
441 exit(EXIT_FAILURE);
442 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100443 if (shdr.sh_addr == relplt_addr
Petr Machatae67635d2012-03-21 03:37:39 +0100444 && shdr.sh_size == lte->relplt_size) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100445 lte->relplt = elf_getdata(scn, NULL);
446 lte->relplt_count =
447 shdr.sh_size / shdr.sh_entsize;
448 if (lte->relplt == NULL
Petr Machatacc0e1e42012-04-25 13:42:07 +0200449 || elf_getdata(scn, lte->relplt) != NULL) {
450 fprintf(stderr, "Couldn't get .rel*.plt"
451 " data from \"%s\": %s\n",
452 filename, elf_errmsg(-1));
453 exit(EXIT_FAILURE);
454 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100455 break;
456 }
457 }
458
Petr Machatacc0e1e42012-04-25 13:42:07 +0200459 if (i == lte->ehdr.e_shnum) {
460 fprintf(stderr,
461 "Couldn't find .rel*.plt section in \"%s\"\n",
462 filename);
463 exit(EXIT_FAILURE);
464 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100465
466 debug(1, "%s %zd PLT relocations", filename, lte->relplt_count);
467 }
Petr Machata2b46cfc2012-02-18 11:17:29 +0100468
469 if (soname_offset != 0)
470 lte->soname = lte->dynstr + soname_offset;
471
Petr Machata1974dbc2011-08-19 18:58:01 +0200472 return 0;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100473}
474
Petr Machata2b46cfc2012-02-18 11:17:29 +0100475/* XXX temporarily non-static */
Joe Damato7a2bdf82010-11-08 15:47:41 -0800476void
Juan Cespedesf1350522008-12-16 18:19:58 +0100477do_close_elf(struct ltelf *lte) {
Juan Cespedescd8976d2009-05-14 13:47:58 +0200478 debug(DEBUG_FUNCTION, "do_close_elf()");
Petr Machata4d9a91c2012-03-24 04:55:03 +0100479 arch_elf_destroy(lte);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100480 elf_end(lte->elf);
481 close(lte->fd);
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200482}
483
Petr Machatab5f80ac2012-04-04 01:46:18 +0200484static int
485populate_plt(struct Process *proc, const char *filename,
486 struct ltelf *lte, struct library *lib)
487{
488 size_t i;
489 for (i = 0; i < lte->relplt_count; ++i) {
490 GElf_Rel rel;
491 GElf_Rela rela;
492 GElf_Sym sym;
493 void *ret;
494
495 if (lte->relplt->d_type == ELF_T_REL) {
496 ret = gelf_getrel(lte->relplt, i, &rel);
497 rela.r_offset = rel.r_offset;
498 rela.r_info = rel.r_info;
499 rela.r_addend = 0;
500 } else {
501 ret = gelf_getrela(lte->relplt, i, &rela);
502 }
503
504 if (ret == NULL
505 || ELF64_R_SYM(rela.r_info) >= lte->dynsym_count
506 || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info),
Petr Machatacc0e1e42012-04-25 13:42:07 +0200507 &sym) == NULL) {
508 fprintf(stderr,
509 "Couldn't get relocation from \"%s\": %s\n",
510 filename, elf_errmsg(-1));
511 exit(EXIT_FAILURE);
512 }
Petr Machatab5f80ac2012-04-04 01:46:18 +0200513
514 char const *name = lte->dynstr + sym.st_name;
515
516 if (!filter_matches_symbol(options.plt_filter, name, lib))
517 continue;
518
Petr Machata218c5ff2012-04-15 04:22:39 +0200519 struct library_symbol *libsym = NULL;
Petr Machatab5f80ac2012-04-04 01:46:18 +0200520 switch (arch_elf_add_plt_entry(proc, lte, name,
521 &rela, i, &libsym)) {
522 case plt_default:
523 if (default_elf_add_plt_entry(proc, lte, name,
524 &rela, i, &libsym) < 0)
Petr Machata8eb0d932012-04-17 05:18:18 +0200525 /* fall-through */
Petr Machatab5f80ac2012-04-04 01:46:18 +0200526 case plt_fail:
527 return -1;
Petr Machata8eb0d932012-04-17 05:18:18 +0200528 /* fall-through */
Petr Machatab5f80ac2012-04-04 01:46:18 +0200529 case plt_ok:
530 if (libsym != NULL)
531 library_add_symbol(lib, libsym);
532 }
533 }
534 return 0;
535}
536
Petr Machata157cc4d2012-04-04 19:00:34 +0200537/* When -x rules result in request to trace several aliases, we only
538 * want to add such symbol once. The only way that those symbols
539 * differ in is their name, e.g. in glibc you have __GI___libc_free,
540 * __cfree, __free, __libc_free, cfree and free all defined on the
541 * same address. So instead we keep this unique symbol struct for
542 * each address, and replace name in libsym with a shorter variant if
543 * we find it. */
544struct unique_symbol {
545 target_address_t addr;
546 struct library_symbol *libsym;
547};
548
549static int
550unique_symbol_cmp(const void *key, const void *val)
551{
552 const struct unique_symbol *sym_key = key;
553 const struct unique_symbol *sym_val = val;
554 return sym_key->addr != sym_val->addr;
555}
556
Petr Machatada3edbf2012-04-04 02:20:21 +0200557static int
558populate_this_symtab(struct Process *proc, const char *filename,
559 struct ltelf *lte, struct library *lib,
560 Elf_Data *symtab, const char *strtab, size_t size)
561{
Petr Machata157cc4d2012-04-04 19:00:34 +0200562 /* Using sorted array would be arguably better, but this
563 * should be well enough for the number of symbols that we
564 * typically deal with. */
565 size_t num_symbols = 0;
566 struct unique_symbol *symbols = malloc(sizeof(*symbols) * size);
567 if (symbols == NULL) {
Petr Machatacc0e1e42012-04-25 13:42:07 +0200568 fprintf(stderr, "couldn't insert symbols for -x: %s\n",
569 strerror(errno));
Petr Machata157cc4d2012-04-04 19:00:34 +0200570 return -1;
571 }
572
Petr Machata40cc53b2012-04-07 01:25:38 +0200573 GElf_Word secflags[lte->ehdr.e_shnum];
Petr Machatada3edbf2012-04-04 02:20:21 +0200574 size_t i;
Petr Machata40cc53b2012-04-07 01:25:38 +0200575 for (i = 1; i < lte->ehdr.e_shnum; ++i) {
576 Elf_Scn *scn = elf_getscn(lte->elf, i);
577 if (scn == NULL)
578 continue;
579 GElf_Shdr shdr;
580 if (gelf_getshdr(scn, &shdr) == NULL)
581 continue;
582 secflags[i] = shdr.sh_flags;
583 }
584
585 size_t lib_len = strlen(lib->soname);
Petr Machatada3edbf2012-04-04 02:20:21 +0200586 for (i = 0; i < size; ++i) {
587 GElf_Sym sym;
Petr Machata074f68f2012-04-07 01:01:02 +0200588 if (gelf_getsym(symtab, i, &sym) == NULL) {
Petr Machatada3edbf2012-04-04 02:20:21 +0200589 fail:
Petr Machatacc0e1e42012-04-25 13:42:07 +0200590 fprintf(stderr,
591 "couldn't get symbol #%zd from %s: %s\n",
592 i, filename, elf_errmsg(-1));
Petr Machatada3edbf2012-04-04 02:20:21 +0200593 continue;
594 }
595
Petr Machata4de6b6b2012-04-04 14:06:09 +0200596 /* XXX support IFUNC as well. */
597 if (GELF_ST_TYPE(sym.st_info) != STT_FUNC
Petr Machata6c1c0bb2012-05-18 16:49:34 +0200598 || sym.st_value == 0
599 || sym.st_shndx == STN_UNDEF)
Petr Machata4de6b6b2012-04-04 14:06:09 +0200600 continue;
601
Petr Machata2bbeac42012-04-30 20:48:34 +0200602 const char *orig_name = strtab + sym.st_name;
603 const char *version = strchr(orig_name, '@');
604 size_t len = version != NULL ? (assert(version > orig_name),
605 (size_t)(version - orig_name))
606 : strlen(orig_name);
607 char name[len + 1];
608 memcpy(name, orig_name, len);
609 name[len] = 0;
610
Petr Machatada3edbf2012-04-04 02:20:21 +0200611 if (!filter_matches_symbol(options.static_filter, name, lib))
612 continue;
Petr Machatada3edbf2012-04-04 02:20:21 +0200613
Petr Machataea8eb9a2012-04-17 01:32:07 +0200614 target_address_t addr = (target_address_t)
615 (uintptr_t)(sym.st_value + lte->bias);
Petr Machatada3edbf2012-04-04 02:20:21 +0200616 target_address_t naddr;
Petr Machata40cc53b2012-04-07 01:25:38 +0200617
618 /* On arches that support OPD, the value of typical
619 * function symbol will be a pointer to .opd, but some
620 * will point directly to .text. We don't want to
621 * translate those. */
622 if (secflags[sym.st_shndx] & SHF_EXECINSTR) {
623 naddr = addr;
Petr Machatab1492df2012-04-30 21:01:40 +0200624 } else if (arch_translate_address(lte, addr, &naddr) < 0) {
Petr Machatacc0e1e42012-04-25 13:42:07 +0200625 fprintf(stderr,
626 "couldn't translate address of %s@%s: %s\n",
627 name, lib->soname, strerror(errno));
Petr Machatada3edbf2012-04-04 02:20:21 +0200628 continue;
629 }
Petr Machata40cc53b2012-04-07 01:25:38 +0200630
Petr Machata3840f682012-04-06 16:05:41 +0200631 char *full_name;
632 if (lib->type != LT_LIBTYPE_MAIN) {
633 full_name = malloc(strlen(name) + 1 + lib_len + 1);
634 if (full_name == NULL)
635 goto fail;
636 sprintf(full_name, "%s@%s", name, lib->soname);
637 } else {
638 full_name = strdup(name);
639 if (full_name == NULL)
640 goto fail;
641 }
Petr Machata4de6b6b2012-04-04 14:06:09 +0200642
Petr Machata157cc4d2012-04-04 19:00:34 +0200643 /* Look whether we already have a symbol for this
644 * address. If not, add this one. */
645 struct unique_symbol key = { naddr, NULL };
646 struct unique_symbol *unique
647 = lsearch(&key, symbols, &num_symbols,
648 sizeof(*symbols), &unique_symbol_cmp);
Petr Machatada3edbf2012-04-04 02:20:21 +0200649
Petr Machata157cc4d2012-04-04 19:00:34 +0200650 if (unique->libsym == NULL) {
651 struct library_symbol *libsym = malloc(sizeof(*libsym));
Petr Machatae8d90762012-04-15 04:28:31 +0200652 if (libsym == NULL
653 || library_symbol_init(libsym, naddr, full_name,
654 1, LS_TOPLT_NONE) < 0) {
Petr Machata157cc4d2012-04-04 19:00:34 +0200655 --num_symbols;
656 goto fail;
657 }
Petr Machata157cc4d2012-04-04 19:00:34 +0200658 unique->libsym = libsym;
659 unique->addr = naddr;
660
661 } else if (strlen(full_name) < strlen(unique->libsym->name)) {
662 library_symbol_set_name(unique->libsym, full_name, 1);
663
664 } else {
665 free(full_name);
666 }
Petr Machatada3edbf2012-04-04 02:20:21 +0200667 }
Petr Machata157cc4d2012-04-04 19:00:34 +0200668
669 for (i = 0; i < num_symbols; ++i) {
670 assert(symbols[i].libsym != NULL);
671 library_add_symbol(lib, symbols[i].libsym);
672 }
673
674 free(symbols);
675
Petr Machatada3edbf2012-04-04 02:20:21 +0200676 return 0;
677}
678
679static int
680populate_symtab(struct Process *proc, const char *filename,
681 struct ltelf *lte, struct library *lib)
682{
683 if (lte->symtab != NULL && lte->strtab != NULL)
684 return populate_this_symtab(proc, filename, lte, lib,
685 lte->symtab, lte->strtab,
686 lte->symtab_count);
687 else
688 return populate_this_symtab(proc, filename, lte, lib,
689 lte->dynsym, lte->dynstr,
690 lte->dynsym_count);
691}
692
Petr Machatab5f80ac2012-04-04 01:46:18 +0200693int
694ltelf_read_library(struct library *lib, struct Process *proc,
695 const char *filename, GElf_Addr bias)
Petr Machatae84fa002012-02-07 13:43:03 +0100696{
Petr Machata29add4f2012-02-18 16:38:05 +0100697 struct ltelf lte = {};
Petr Machatab120fdf2012-03-21 05:05:46 +0100698 if (do_init_elf(&lte, filename, bias) < 0)
Petr Machatab5f80ac2012-04-04 01:46:18 +0200699 return -1;
Petr Machatae0615ab2012-04-17 05:17:48 +0200700 if (arch_elf_init(&lte, lib) < 0) {
701 fprintf(stderr, "Backend initialization failed.\n");
702 return -1;
703 }
704
Petr Machatae67635d2012-03-21 03:37:39 +0100705 proc->e_machine = lte.ehdr.e_machine;
Joe Damatof0bd98b2010-11-08 15:47:42 -0800706
Petr Machatab5f80ac2012-04-04 01:46:18 +0200707 int status = 0;
Petr Machatafc6ff182012-04-04 13:11:50 +0200708 if (lib == NULL)
709 goto fail;
710
711 /* Note that we set soname and pathname as soon as they are
712 * allocated, so in case of further errors, this get released
713 * when LIB is release, which should happen in the caller when
714 * we return error. */
715
716 if (lib->pathname == NULL) {
717 char *pathname = strdup(filename);
718 if (pathname == NULL)
719 goto fail;
Petr Machataf13afd52012-04-14 02:30:31 +0200720 library_set_pathname(lib, pathname, 1);
Joe Damatof0bd98b2010-11-08 15:47:42 -0800721 }
722
Petr Machata0b55b582012-04-02 00:38:46 +0200723 if (lte.soname != NULL) {
Petr Machatafc6ff182012-04-04 13:11:50 +0200724 char *soname = strdup(lte.soname);
725 if (soname == NULL)
726 goto fail;
727 library_set_soname(lib, soname, 1);
Petr Machata0b55b582012-04-02 00:38:46 +0200728 } else {
Petr Machatafc6ff182012-04-04 13:11:50 +0200729 const char *soname = rindex(lib->pathname, '/') + 1;
730 if (soname == NULL)
731 soname = lib->pathname;
732 library_set_soname(lib, soname, 0);
Petr Machata0b55b582012-04-02 00:38:46 +0200733 }
Joe Damatofa2aefc2010-10-30 19:56:50 -0700734
Petr Machataea8eb9a2012-04-17 01:32:07 +0200735 /* XXX The double cast should be removed when
736 * target_address_t becomes integral type. */
737 target_address_t entry = (target_address_t)(uintptr_t)lte.entry_addr;
Petr Machatab1492df2012-04-30 21:01:40 +0200738 if (arch_translate_address(&lte, entry, &entry) < 0)
Petr Machatab120fdf2012-03-21 05:05:46 +0100739 goto fail;
740
Petr Machataea8eb9a2012-04-17 01:32:07 +0200741 /* XXX The double cast should be removed when
742 * target_address_t becomes integral type. */
743 lib->base = (target_address_t)(uintptr_t)lte.base_addr;
Petr Machatab120fdf2012-03-21 05:05:46 +0100744 lib->entry = entry;
Petr Machataea8eb9a2012-04-17 01:32:07 +0200745 /* XXX The double cast should be removed when
746 * target_address_t becomes integral type. */
747 lib->dyn_addr = (target_address_t)(uintptr_t)lte.dyn_addr;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100748
Petr Machatab5f80ac2012-04-04 01:46:18 +0200749 if (filter_matches_library(options.plt_filter, lib)
750 && populate_plt(proc, filename, &lte, lib) < 0)
751 goto fail;
Joe Damatoe2a8f572010-11-08 15:47:40 -0800752
Petr Machatada3edbf2012-04-04 02:20:21 +0200753 if (filter_matches_library(options.static_filter, lib)
754 && populate_symtab(proc, filename, &lte, lib) < 0)
755 goto fail;
756
Petr Machata2b46cfc2012-02-18 11:17:29 +0100757done:
758 do_close_elf(&lte);
Petr Machatab5f80ac2012-04-04 01:46:18 +0200759 return status;
Petr Machatafc6ff182012-04-04 13:11:50 +0200760
761fail:
762 status = -1;
763 goto done;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100764}
Petr Machatae84fa002012-02-07 13:43:03 +0100765
Petr Machata2b46cfc2012-02-18 11:17:29 +0100766struct library *
767ltelf_read_main_binary(struct Process *proc, const char *path)
768{
Petr Machatab5f80ac2012-04-04 01:46:18 +0200769 struct library *lib = malloc(sizeof(*lib));
770 if (lib == NULL)
771 return NULL;
772 library_init(lib, LT_LIBTYPE_MAIN);
Petr Machatafc6ff182012-04-04 13:11:50 +0200773 library_set_pathname(lib, path, 0);
Petr Machatab5f80ac2012-04-04 01:46:18 +0200774
Petr Machatafc6ff182012-04-04 13:11:50 +0200775 /* There is a race between running the process and reading its
776 * binary for internal consumption. So open the binary from
777 * the /proc filesystem. XXX Note that there is similar race
778 * for libraries, but there we don't have a nice answer like
779 * that. Presumably we could read the DSOs from the process
780 * memory image, but that's not currently done. */
Petr Machata2b46cfc2012-02-18 11:17:29 +0100781 char *fname = pid2name(proc->pid);
Petr Machatab5f80ac2012-04-04 01:46:18 +0200782 if (ltelf_read_library(lib, proc, fname, 0) < 0) {
783 library_destroy(lib);
784 free(lib);
785 return NULL;
Petr Machata0b55b582012-04-02 00:38:46 +0200786 }
Petr Machatab5f80ac2012-04-04 01:46:18 +0200787
Petr Machata2b46cfc2012-02-18 11:17:29 +0100788 return lib;
Juan Cespedes96935a91997-08-09 23:45:39 +0200789}