blob: 983fe519b2e794f0639cfd81845a01e60782710d [file] [log] [blame]
Juan Cespedesd44c6b81998-09-25 14:48:42 +02001#if HAVE_CONFIG_H
Juan Cespedesd914a202004-11-10 00:15:33 +01002# include "config.h"
Juan Cespedesd44c6b81998-09-25 14:48:42 +02003#endif
4
Juan Cespedesd914a202004-11-10 00:15:33 +01005#include <endian.h>
Juan Cespedes96935a91997-08-09 23:45:39 +02006#include <errno.h>
Juan Cespedesd914a202004-11-10 00:15:33 +01007#include <error.h>
Juan Cespedes96935a91997-08-09 23:45:39 +02008#include <fcntl.h>
Juan Cespedesd914a202004-11-10 00:15:33 +01009#include <gelf.h>
10#include <stdint.h>
11#include <stdlib.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020012#include <string.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010013#include <unistd.h>
Juan Cespedes96935a91997-08-09 23:45:39 +020014
Juan Cespedes96935a91997-08-09 23:45:39 +020015#include "ltrace.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010016#include "elf.h"
Juan Cespedescac15c32003-01-31 18:58:58 +010017#include "debug.h"
Ian Wienand9a2ad352006-02-20 22:44:45 +010018#include "options.h"
Juan Cespedes96935a91997-08-09 23:45:39 +020019
Ian Wienand2d45b1a2006-02-20 22:48:07 +010020static void do_init_elf(struct ltelf *lte, const char *filename);
21static void do_close_elf(struct ltelf *lte);
22static void add_library_symbol(GElf_Addr addr, const char *name,
23 struct library_symbol **library_symbolspp,
24 int use_elf_plt2addr, int is_weak);
25static int in_load_libraries(const char *name, struct ltelf *lte);
26static GElf_Addr elf_plt2addr(struct ltelf *ltc, void *addr);
Juan Cespedes1cd999a2001-07-03 00:46:04 +020027
Ian Wienand2d45b1a2006-02-20 22:48:07 +010028extern char *PLTs_initialized_by_here;
Ian Wienand9a2ad352006-02-20 22:44:45 +010029
Ian Wienand2d45b1a2006-02-20 22:48:07 +010030static void do_init_elf(struct ltelf *lte, const char *filename)
Juan Cespedesd914a202004-11-10 00:15:33 +010031{
Ian Wienand2d45b1a2006-02-20 22:48:07 +010032 int i;
33 GElf_Addr relplt_addr = 0;
34 size_t relplt_size = 0;
Juan Cespedes1cd999a2001-07-03 00:46:04 +020035
Ian Wienand2d45b1a2006-02-20 22:48:07 +010036 debug(1, "Reading ELF from %s...", filename);
Juan Cespedes1afec691997-08-23 21:31:46 +020037
Ian Wienand2d45b1a2006-02-20 22:48:07 +010038 memset(lte, 0, sizeof(*lte));
39 lte->fd = open(filename, O_RDONLY);
40 if (lte->fd == -1)
41 error(EXIT_FAILURE, errno, "Can't open \"%s\"", filename);
Juan Cespedes96935a91997-08-09 23:45:39 +020042
Juan Cespedesd914a202004-11-10 00:15:33 +010043#ifdef HAVE_ELF_C_READ_MMAP
Ian Wienand2d45b1a2006-02-20 22:48:07 +010044 lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL);
Juan Cespedes5c3fe062004-06-14 18:08:37 +020045#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010046 lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL);
Juan Cespedes5c3fe062004-06-14 18:08:37 +020047#endif
Juan Cespedes1cd999a2001-07-03 00:46:04 +020048
Ian Wienand2d45b1a2006-02-20 22:48:07 +010049 if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF)
50 error(EXIT_FAILURE, 0, "Can't open ELF file \"%s\"", filename);
Juan Cespedes1cd999a2001-07-03 00:46:04 +020051
Ian Wienand2d45b1a2006-02-20 22:48:07 +010052 if (gelf_getehdr(lte->elf, &lte->ehdr) == NULL)
53 error(EXIT_FAILURE, 0, "Can't read ELF header of \"%s\"",
54 filename);
Juan Cespedes1cd999a2001-07-03 00:46:04 +020055
Ian Wienand2d45b1a2006-02-20 22:48:07 +010056 if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN)
57 error(EXIT_FAILURE, 0,
58 "\"%s\" is not an ELF executable nor shared library",
59 filename);
Juan Cespedes1cd999a2001-07-03 00:46:04 +020060
Ian Wienand2d45b1a2006-02-20 22:48:07 +010061 if ((lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
62 || lte->ehdr.e_machine != LT_ELF_MACHINE)
Juan Cespedesd914a202004-11-10 00:15:33 +010063#ifdef LT_ELF_MACHINE2
Ian Wienand2d45b1a2006-02-20 22:48:07 +010064 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2
65 || lte->ehdr.e_machine != LT_ELF_MACHINE2)
Juan Cespedesd914a202004-11-10 00:15:33 +010066#endif
67#ifdef LT_ELF_MACHINE3
Ian Wienand2d45b1a2006-02-20 22:48:07 +010068 && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3
69 || lte->ehdr.e_machine != LT_ELF_MACHINE3)
Juan Cespedesd914a202004-11-10 00:15:33 +010070#endif
Ian Wienand2d45b1a2006-02-20 22:48:07 +010071 )
72 error(EXIT_FAILURE, 0,
73 "\"%s\" is ELF from incompatible architecture", filename);
Juan Cespedesd914a202004-11-10 00:15:33 +010074
Ian Wienand2d45b1a2006-02-20 22:48:07 +010075 for (i = 1; i < lte->ehdr.e_shnum; ++i) {
76 Elf_Scn *scn;
77 GElf_Shdr shdr;
78 const char *name;
Juan Cespedesd914a202004-11-10 00:15:33 +010079
Ian Wienand2d45b1a2006-02-20 22:48:07 +010080 scn = elf_getscn(lte->elf, i);
81 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
82 error(EXIT_FAILURE, 0,
83 "Couldn't get section header from \"%s\"",
84 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +010085
Ian Wienand2d45b1a2006-02-20 22:48:07 +010086 name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name);
87 if (name == NULL)
88 error(EXIT_FAILURE, 0,
89 "Couldn't get section header from \"%s\"",
90 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +010091
Ian Wienand2d45b1a2006-02-20 22:48:07 +010092 if (shdr.sh_type == SHT_SYMTAB) {
93 Elf_Data *data;
Juan Cespedesd914a202004-11-10 00:15:33 +010094
Ian Wienand2d45b1a2006-02-20 22:48:07 +010095 lte->symtab = elf_getdata(scn, NULL);
96 lte->symtab_count = shdr.sh_size / shdr.sh_entsize;
97 if ((lte->symtab == NULL
98 || elf_getdata(scn, lte->symtab) != NULL)
99 && opt_x != NULL)
100 error(EXIT_FAILURE, 0,
101 "Couldn't get .symtab data from \"%s\"",
102 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100103
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100104 scn = elf_getscn(lte->elf, shdr.sh_link);
105 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
106 error(EXIT_FAILURE, 0,
107 "Couldn't get section header from \"%s\"",
108 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100109
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100110 data = elf_getdata(scn, NULL);
111 if (data == NULL || elf_getdata(scn, data) != NULL
112 || shdr.sh_size != data->d_size || data->d_off)
113 error(EXIT_FAILURE, 0,
114 "Couldn't get .strtab data from \"%s\"",
115 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100116
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100117 lte->strtab = data->d_buf;
118 } else if (shdr.sh_type == SHT_DYNSYM) {
119 Elf_Data *data;
Juan Cespedesd914a202004-11-10 00:15:33 +0100120
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100121 lte->dynsym = elf_getdata(scn, NULL);
122 lte->dynsym_count = shdr.sh_size / shdr.sh_entsize;
123 if (lte->dynsym == NULL
124 || elf_getdata(scn, lte->dynsym) != NULL)
125 error(EXIT_FAILURE, 0,
126 "Couldn't get .dynsym data from \"%s\"",
127 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100128
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100129 scn = elf_getscn(lte->elf, shdr.sh_link);
130 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
131 error(EXIT_FAILURE, 0,
132 "Couldn't get section header from \"%s\"",
133 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100134
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100135 data = elf_getdata(scn, NULL);
136 if (data == NULL || elf_getdata(scn, data) != NULL
137 || shdr.sh_size != data->d_size || data->d_off)
138 error(EXIT_FAILURE, 0,
139 "Couldn't get .dynstr data from \"%s\"",
140 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100141
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100142 lte->dynstr = data->d_buf;
143 } else if (shdr.sh_type == SHT_DYNAMIC) {
144 Elf_Data *data;
145 size_t j;
Juan Cespedesd914a202004-11-10 00:15:33 +0100146
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100147 data = elf_getdata(scn, NULL);
148 if (data == NULL || elf_getdata(scn, data) != NULL)
149 error(EXIT_FAILURE, 0,
150 "Couldn't get .dynamic data from \"%s\"",
151 filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100152
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100153 for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
154 GElf_Dyn dyn;
Juan Cespedesd914a202004-11-10 00:15:33 +0100155
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100156 if (gelf_getdyn(data, j, &dyn) == NULL)
157 error(EXIT_FAILURE, 0,
158 "Couldn't get .dynamic data from \"%s\"",
159 filename);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100160
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100161 if (dyn.d_tag == DT_JMPREL)
162 relplt_addr = dyn.d_un.d_ptr;
163 else if (dyn.d_tag == DT_PLTRELSZ)
164 relplt_size = dyn.d_un.d_val;
165 }
166 } else if (shdr.sh_type == SHT_HASH) {
167 Elf_Data *data;
168 size_t j;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100169
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100170 data = elf_getdata(scn, NULL);
171 if (data == NULL || elf_getdata(scn, data) != NULL
172 || data->d_off || data->d_size != shdr.sh_size)
173 error(EXIT_FAILURE, 0,
174 "Couldn't get .hash data from \"%s\"",
175 filename);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100176
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100177 if (shdr.sh_entsize == 4) {
178 /* Standard conforming ELF. */
179 if (data->d_type != ELF_T_WORD)
180 error(EXIT_FAILURE, 0,
181 "Couldn't get .hash data from \"%s\"",
182 filename);
183 lte->hash = (Elf32_Word *) data->d_buf;
184 } else if (shdr.sh_entsize == 8) {
185 /* Alpha or s390x. */
186 Elf32_Word *dst, *src;
187 size_t hash_count = data->d_size / 8;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100188
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100189 lte->hash = (Elf32_Word *)
190 malloc(hash_count * sizeof(Elf32_Word));
191 if (lte->hash == NULL)
192 error(EXIT_FAILURE, 0,
193 "Couldn't convert .hash section from \"%s\"",
194 filename);
195 lte->hash_malloced = 1;
196 dst = lte->hash;
197 src = (Elf32_Word *) data->d_buf;
198 if ((data->d_type == ELF_T_WORD
199 && __BYTE_ORDER == __BIG_ENDIAN)
200 || (data->d_type == ELF_T_XWORD
201 && lte->ehdr.e_ident[EI_DATA] ==
202 ELFDATA2MSB))
203 ++src;
204 for (j = 0; j < hash_count; ++j, src += 2)
205 *dst++ = *src;
206 } else
207 error(EXIT_FAILURE, 0,
208 "Unknown .hash sh_entsize in \"%s\"",
209 filename);
210 } else if (shdr.sh_type == SHT_PROGBITS
211 || shdr.sh_type == SHT_NOBITS) {
212 if (strcmp(name, ".plt") == 0) {
213 lte->plt_addr = shdr.sh_addr;
214 lte->plt_size = shdr.sh_size;
215 } else if (strcmp(name, ".opd") == 0) {
Paul Gilliam3f1219f2006-04-24 18:25:38 +0200216 lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100217 lte->opd_size = shdr.sh_size;
218 lte->opd = elf_rawdata(scn, NULL);
219 }
220 }
Juan Cespedesd914a202004-11-10 00:15:33 +0100221 }
222
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100223 if (lte->dynsym == NULL || lte->dynstr == NULL)
224 error(EXIT_FAILURE, 0,
225 "Couldn't find .dynsym or .dynstr in \"%s\"", filename);
Juan Cespedesd914a202004-11-10 00:15:33 +0100226
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100227 if (!relplt_addr || !lte->plt_addr) {
228 debug(1, "%s has no PLT relocations", filename);
229 lte->relplt = NULL;
230 lte->relplt_count = 0;
231 } else {
232 for (i = 1; i < lte->ehdr.e_shnum; ++i) {
233 Elf_Scn *scn;
234 GElf_Shdr shdr;
235
236 scn = elf_getscn(lte->elf, i);
237 if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
238 error(EXIT_FAILURE, 0,
239 "Couldn't get section header from \"%s\"",
240 filename);
241 if (shdr.sh_addr == relplt_addr
242 && shdr.sh_size == relplt_size) {
243 lte->relplt = elf_getdata(scn, NULL);
244 lte->relplt_count =
245 shdr.sh_size / shdr.sh_entsize;
246 if (lte->relplt == NULL
247 || elf_getdata(scn, lte->relplt) != NULL)
248 error(EXIT_FAILURE, 0,
249 "Couldn't get .rel*.plt data from \"%s\"",
250 filename);
251 break;
252 }
253 }
254
255 if (i == lte->ehdr.e_shnum)
256 error(EXIT_FAILURE, 0,
257 "Couldn't find .rel*.plt section in \"%s\"",
258 filename);
259
260 debug(1, "%s %zd PLT relocations", filename, lte->relplt_count);
261 }
262}
263
264static void do_close_elf(struct ltelf *lte)
265{
266 if (lte->hash_malloced)
267 free((char *)lte->hash);
268 elf_end(lte->elf);
269 close(lte->fd);
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200270}
271
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100272static void
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100273add_library_symbol(GElf_Addr addr, const char *name,
274 struct library_symbol **library_symbolspp,
275 int use_elf_plt2addr, int is_weak)
Juan Cespedesd914a202004-11-10 00:15:33 +0100276{
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100277 struct library_symbol *s;
278 s = malloc(sizeof(struct library_symbol) + strlen(name) + 1);
279 if (s == NULL)
280 error(EXIT_FAILURE, errno, "add_library_symbol failed");
281
282 s->needs_init = 1;
283 s->is_weak = is_weak;
284 s->static_plt2addr = use_elf_plt2addr;
285 s->next = *library_symbolspp;
286 s->enter_addr = (void *)(uintptr_t) addr;
287 s->brkpnt = NULL;
288 s->name = (char *)(s + 1);
289 strcpy(s->name, name);
290 *library_symbolspp = s;
291
292 debug(2, "addr: %p, symbol: \"%s\"", (void *)(uintptr_t) addr, name);
Juan Cespedesd914a202004-11-10 00:15:33 +0100293}
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200294
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100295static int in_load_libraries(const char *name, struct ltelf *lte)
Juan Cespedesd914a202004-11-10 00:15:33 +0100296{
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100297 size_t i;
298 unsigned long hash;
Juan Cespedesd914a202004-11-10 00:15:33 +0100299
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100300 if (!library_num)
301 return 1;
Juan Cespedesd914a202004-11-10 00:15:33 +0100302
Paul Gilliam3f1219f2006-04-24 18:25:38 +0200303 hash = elf_hash((const unsigned char *)name);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100304 for (i = 1; i <= library_num; ++i) {
305 Elf32_Word nbuckets, symndx;
306 Elf32_Word *buckets, *chain;
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200307
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100308 if (lte[i].hash == NULL)
309 continue;
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200310
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100311 nbuckets = lte[i].hash[0];
312 buckets = &lte[i].hash[2];
313 chain = &lte[i].hash[2 + nbuckets];
314 for (symndx = buckets[hash % nbuckets];
315 symndx != STN_UNDEF; symndx = chain[symndx]) {
316 GElf_Sym sym;
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200317
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100318 if (gelf_getsym(lte[i].dynsym, symndx, &sym) == NULL)
319 error(EXIT_FAILURE, 0,
320 "Couldn't get symbol from .dynsym");
Juan Cespedesd914a202004-11-10 00:15:33 +0100321
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100322 if (sym.st_value != 0
323 && sym.st_shndx != SHN_UNDEF
324 && strcmp(name, lte[i].dynstr + sym.st_name) == 0)
325 return 1;
326 }
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200327 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100328 return 0;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100329}
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200330
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100331static GElf_Addr elf_plt2addr(struct ltelf *lte, void *addr)
Ian Wienand9a2ad352006-02-20 22:44:45 +0100332{
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100333 long base;
334 long offset;
335 GElf_Addr ret_val;
Juan Cespedes1cd999a2001-07-03 00:46:04 +0200336
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100337 if (!lte->opd)
Paul Gilliam3f1219f2006-04-24 18:25:38 +0200338 return (GElf_Addr) (long) addr;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100339
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100340 base = (long)lte->opd->d_buf;
341 offset = (long)addr - (long)lte->opd_addr;
342 if (offset > lte->opd_size)
343 error(EXIT_FAILURE, 0, "static plt not in .opd");
344
345 ret_val = (GElf_Addr) * (long *)(base + offset);
346 return ret_val;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100347}
348
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100349struct library_symbol *read_elf(struct process *proc)
Ian Wienand9a2ad352006-02-20 22:44:45 +0100350{
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100351 struct library_symbol *library_symbols = NULL;
352 struct ltelf lte[MAX_LIBRARY + 1];
353 size_t i;
Paul Gilliam24e643a2006-03-13 18:43:13 +0100354 struct opt_x_t *xptr;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100355 struct library_symbol **lib_tail = NULL;
Paul Gilliam24e643a2006-03-13 18:43:13 +0100356 struct opt_x_t *main_cheat;
357 int exit_out = 0;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100358
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100359 elf_version(EV_CURRENT);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100360
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100361 do_init_elf(lte, proc->filename);
362 proc->e_machine = lte->ehdr.e_machine;
363 for (i = 0; i < library_num; ++i)
364 do_init_elf(&lte[i + 1], library[i]);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100365
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100366 for (i = 0; i < lte->relplt_count; ++i) {
367 GElf_Rel rel;
368 GElf_Rela rela;
369 GElf_Sym sym;
370 GElf_Addr addr;
371 void *ret;
372 const char *name;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100373
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100374 if (lte->relplt->d_type == ELF_T_REL) {
375 ret = gelf_getrel(lte->relplt, i, &rel);
376 rela.r_offset = rel.r_offset;
377 rela.r_info = rel.r_info;
378 rela.r_addend = 0;
379 } else
380 ret = gelf_getrela(lte->relplt, i, &rela);
381
382 if (ret == NULL
383 || ELF64_R_SYM(rela.r_info) >= lte->dynsym_count
384 || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info),
385 &sym) == NULL)
386 error(EXIT_FAILURE, 0,
387 "Couldn't get relocation from \"%s\"",
388 proc->filename);
389
390 if (!sym.st_value && PLTs_initialized_by_here)
391 proc->need_to_reinitialize_breakpoints = 1;
392
393 name = lte->dynstr + sym.st_name;
394 if (in_load_libraries(name, lte)) {
395 addr = arch_plt_sym_val(lte, i, &rela);
396 add_library_symbol(addr, name, &library_symbols, 0,
397 ELF64_ST_BIND(sym.st_info) != 0);
398 if (!lib_tail)
399 lib_tail = &(library_symbols->next);
400 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100401 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100402
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100403 if (proc->need_to_reinitialize_breakpoints) {
404 /* Add "PLTs_initialized_by_here" to opt_x list, if not already there. */
Paul Gilliam2b2507a2006-04-07 18:32:07 +0200405 main_cheat = (struct opt_x_t *)malloc(sizeof(struct opt_x_t));
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100406 if (main_cheat == NULL)
407 error(EXIT_FAILURE, 0, "Couldn allocate memory");
408 main_cheat->next = opt_x;
409 main_cheat->name = PLTs_initialized_by_here;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100410
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100411 for (xptr = opt_x; xptr; xptr = xptr->next)
412 if (strcmp(xptr->name, PLTs_initialized_by_here) == 0
413 && main_cheat) {
414 free(main_cheat);
415 main_cheat = NULL;
416 break;
417 }
418 if (main_cheat)
419 opt_x = main_cheat;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100420 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100421
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100422 for (i = 0; i < lte->symtab_count; ++i) {
423 GElf_Sym sym;
424 GElf_Addr addr;
425 const char *name;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100426
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100427 if (gelf_getsym(lte->symtab, i, &sym) == NULL)
428 error(EXIT_FAILURE, 0,
429 "Couldn't get symbol from \"%s\"",
430 proc->filename);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100431
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100432 name = lte->strtab + sym.st_name;
433 addr = sym.st_value;
434 if (!addr)
435 continue;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100436
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100437 for (xptr = opt_x; xptr; xptr = xptr->next)
438 if (xptr->name && strcmp(xptr->name, name) == 0) {
439 /* FIXME: Should be able to use &library_symbols as above. But
440 when you do, none of the real library symbols cause breaks. */
441 add_library_symbol(elf_plt2addr
Paul Gilliam3f1219f2006-04-24 18:25:38 +0200442 (lte, (void *) (long) addr),
443 name, lib_tail, 1, 0);
Paul Gilliam24e643a2006-03-13 18:43:13 +0100444 xptr->found = 1;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100445 break;
446 }
447 }
448 for (xptr = opt_x; xptr; xptr = xptr->next)
Paul Gilliam24e643a2006-03-13 18:43:13 +0100449 if ( ! xptr->found) {
450 char *badthing = "WARNING";
451 if (E_ENTRY_NAME && strcmp(xptr->name, E_ENTRY_NAME)) {
452 badthing = "ERROR";
453 exit_out = 1;
454 }
455 fprintf (stderr,
456 "%s: Couldn't find symbol \"%s\" in file \"%s\"\n",
457 badthing, xptr->name, proc->filename);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100458 }
Paul Gilliam24e643a2006-03-13 18:43:13 +0100459 if (exit_out) {
460 exit (1);
461 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100462
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100463 for (i = 0; i < library_num + 1; ++i)
464 do_close_elf(&lte[i]);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100465
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100466 return library_symbols;
Juan Cespedes96935a91997-08-09 23:45:39 +0200467}