ltrace-elf.c revision 513258cf3063bcdfbd4a7aeb3c9fe3b8484ccdf5
1642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata/*
2642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * This file is part of ltrace.
3642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * Copyright (C) 2006,2010,2011,2012 Petr Machata, Red Hat Inc.
4642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * Copyright (C) 2010 Zachary T Welch, CodeSourcery
5642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * Copyright (C) 2010 Joe Damato
6642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * Copyright (C) 1997,1998,2001,2004,2007,2008,2009 Juan Cespedes
7642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * Copyright (C) 2006 Olaf Hering, SUSE Linux GmbH
8642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
9642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * Copyright (C) 2006 Paul Gilliam, IBM Corporation
10642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * Copyright (C) 2006 Ian Wienand
11642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata *
12642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * This program is free software; you can redistribute it and/or
13642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * modify it under the terms of the GNU General Public License as
14642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * published by the Free Software Foundation; either version 2 of the
15642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * License, or (at your option) any later version.
16642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata *
17642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * This program is distributed in the hope that it will be useful, but
18642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
19642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * General Public License for more details.
21642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata *
22642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * You should have received a copy of the GNU General Public License
23642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * along with this program; if not, write to the Free Software
24642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * 02110-1301 USA
26642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata */
27642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata
28f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato#include "config.h"
29d44c6b8b090b8b7aa9d971d9e0bfd848732a3071Juan Cespedes
30157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata#include <assert.h>
319d878c9d7600d313a2b2c53201569db790ec2c61Andrey Zonov#ifdef	__linux__
32d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#include <endian.h>
339d878c9d7600d313a2b2c53201569db790ec2c61Andrey Zonov#endif
3496935a9fe2af57e089cbd2e32a69caba5b3f2458Juan Cespedes#include <errno.h>
3596935a9fe2af57e089cbd2e32a69caba5b3f2458Juan Cespedes#include <fcntl.h>
36d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#include <gelf.h>
37bfb26c745705a839f1ef5fc45e1b32135b9bc3e7Zachary T Welch#include <inttypes.h>
38157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata#include <search.h>
39d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#include <stdint.h>
40cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata#include <stdio.h>
41d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#include <stdlib.h>
4296935a9fe2af57e089cbd2e32a69caba5b3f2458Juan Cespedes#include <string.h>
43513258cf3063bcdfbd4a7aeb3c9fe3b8484ccdf5Petr Machata#include <strings.h>
445e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes#include <unistd.h>
4596935a9fe2af57e089cbd2e32a69caba5b3f2458Juan Cespedes
46642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata#include "backend.h"
47ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "filter.h"
48ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "library.h"
49ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "ltrace-elf.h"
50ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "proc.h"
51ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "debug.h"
52ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "options.h"
53f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato
54e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#ifndef ARCH_HAVE_LTELF_DATA
55e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machataint
56e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machataarch_elf_init(struct ltelf *lte, struct library *lib)
57e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata{
58e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	return 0;
59e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata}
60c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata
61c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machatavoid
62c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machataarch_elf_destroy(struct ltelf *lte)
63c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata{
64c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata}
65e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#endif
66e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata
676db61f509eb7537ca64873b0c8c1955e2293db9fPetr Machataint
68e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machatadefault_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
691be2291ffdf3a20b0a1702f5705f82617fb91ef6Petr Machata			  const char *a_name, GElf_Rela *rela, size_t ndx,
70e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata			  struct library_symbol **ret)
71e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata{
72e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata	char *name = strdup(a_name);
73e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata	if (name == NULL) {
746db61f509eb7537ca64873b0c8c1955e2293db9fPetr Machata	fail_message:
756db61f509eb7537ca64873b0c8c1955e2293db9fPetr Machata		fprintf(stderr, "Couldn't create symbol for PLT entry: %s\n",
766db61f509eb7537ca64873b0c8c1955e2293db9fPetr Machata			strerror(errno));
77e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata	fail:
78e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata		free(name);
79e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata		return -1;
80e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata	}
81e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata
821be2291ffdf3a20b0a1702f5705f82617fb91ef6Petr Machata	GElf_Addr addr = arch_plt_sym_val(lte, ndx, rela);
83e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata
84e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata	struct library_symbol *libsym = malloc(sizeof(*libsym));
85e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata	if (libsym == NULL)
866db61f509eb7537ca64873b0c8c1955e2293db9fPetr Machata		goto fail_message;
87e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata
88ea8eb9a606096fd072abe104b4239f67883ad39aPetr Machata	/* XXX The double cast should be removed when
89bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	 * arch_addr_t becomes integral type.  */
90bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	arch_addr_t taddr = (arch_addr_t)
91ea8eb9a606096fd072abe104b4239f67883ad39aPetr Machata		(uintptr_t)(addr + lte->bias);
92bb790604dcaa546737417bf7df8587b3096fa6a5Petr Machata
93e8d9076a97f6617868466a99bd18e11e3f6389acPetr Machata	if (library_symbol_init(libsym, taddr, name, 1, LS_TOPLT_EXEC) < 0) {
94e8d9076a97f6617868466a99bd18e11e3f6389acPetr Machata		free(libsym);
95e8d9076a97f6617868466a99bd18e11e3f6389acPetr Machata		goto fail;
96e8d9076a97f6617868466a99bd18e11e3f6389acPetr Machata	}
97e8d9076a97f6617868466a99bd18e11e3f6389acPetr Machata
980fa790473a035a432cb795eace4fe7ae6fd742b8Petr Machata	libsym->next = *ret;
99e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata	*ret = libsym;
100e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata	return 0;
101e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata}
102e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata
103e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata#ifndef ARCH_HAVE_ADD_PLT_ENTRY
104e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machataenum plt_status
105e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machataarch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
1061be2291ffdf3a20b0a1702f5705f82617fb91ef6Petr Machata		       const char *a_name, GElf_Rela *rela, size_t ndx,
107e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata		       struct library_symbol **ret)
108e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata{
109e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata	return plt_default;
110e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata}
111e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata#endif
112e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata
113e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr MachataElf_Data *
114e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machataelf_loaddata(Elf_Scn *scn, GElf_Shdr *shdr)
115fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata{
116fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	Elf_Data *data = elf_getdata(scn, NULL);
117fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	if (data == NULL || elf_getdata(scn, data) != NULL
118fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	    || data->d_off || data->d_size != shdr->sh_size)
119fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		return NULL;
120fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	return data;
121fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata}
122fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
123e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machatastatic int
124ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machataelf_get_section_if(struct ltelf *lte, Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr,
125ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		   int (*predicate)(Elf_Scn *, GElf_Shdr *, void *data),
126ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		   void *data)
127fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata{
128fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	int i;
129fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	for (i = 1; i < lte->ehdr.e_shnum; ++i) {
130fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		Elf_Scn *scn;
131fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		GElf_Shdr shdr;
132fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
133fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		scn = elf_getscn(lte->elf, i);
134fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
135fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata			debug(1, "Couldn't read section or header.");
136e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			return -1;
137fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		}
138ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		if (predicate(scn, &shdr, data)) {
139ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata			*tgt_sec = scn;
140ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata			*tgt_shdr = shdr;
141e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			return 0;
142ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		}
143fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	}
144e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	return -1;
145ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata
146ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata}
147ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata
148ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machatastatic int
149ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machatainside_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data)
150ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata{
151ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	GElf_Addr addr = *(GElf_Addr *)data;
152ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	return addr >= shdr->sh_addr
153ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		&& addr < shdr->sh_addr + shdr->sh_size;
154ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata}
155ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata
156ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machataint
157ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machataelf_get_section_covering(struct ltelf *lte, GElf_Addr addr,
158ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata			 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
159ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata{
160ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	return elf_get_section_if(lte, tgt_sec, tgt_shdr,
161ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata				  &inside_p, &addr);
162ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata}
163ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata
164ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machatastatic int
165ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machatatype_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data)
166ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata{
167ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	GElf_Word type = *(GElf_Word *)data;
168ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	return shdr->sh_type == type;
169ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata}
170ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata
171ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machataint
172ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machataelf_get_section_type(struct ltelf *lte, GElf_Word type,
173ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		     Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
174ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata{
175ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	return elf_get_section_if(lte, tgt_sec, tgt_shdr,
176ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata				  &type_p, &type);
177fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata}
178fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
1795b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machatastruct section_named_data {
1805b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	struct ltelf *lte;
1815b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	const char *name;
1825b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata};
1835b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata
1845b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machatastatic int
1855b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machataname_p(Elf_Scn *scn, GElf_Shdr *shdr, void *d)
1865b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata{
1875b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	struct section_named_data *data = d;
1885b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	const char *name = elf_strptr(data->lte->elf,
1895b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata				      data->lte->ehdr.e_shstrndx,
1905b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata				      shdr->sh_name);
1915b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	return strcmp(name, data->name) == 0;
1925b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata}
1935b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata
1945b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machataint
1955b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machataelf_get_section_named(struct ltelf *lte, const char *name,
1965b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata		     Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
1975b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata{
1985b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	struct section_named_data data = {
1995b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata		.lte = lte,
2005b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata		.name = name,
2015b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	};
2025b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	return elf_get_section_if(lte, tgt_sec, tgt_shdr,
2035b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata				  &name_p, &data);
2045b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata}
2055b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata
206e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machatastatic int
2073a01cd7a2fcf200cedd0770e137a28764f679c3cPetr Machataneed_data(Elf_Data *data, GElf_Xword offset, GElf_Xword size)
208fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata{
209e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	assert(data != NULL);
210e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	if (data->d_size < size || offset > data->d_size - size) {
211a82d32209f276e10dd1f437b38b4b6e5de32b980Petr Machata		debug(1, "Not enough data to read %"PRId64"-byte value"
212a82d32209f276e10dd1f437b38b4b6e5de32b980Petr Machata		      " at offset %"PRId64".", size, offset);
213e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		return -1;
214fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	}
215e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	return 0;
216fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata}
217fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
218e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#define DEF_READER(NAME, SIZE)						\
219e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	int								\
2203a01cd7a2fcf200cedd0770e137a28764f679c3cPetr Machata	NAME(Elf_Data *data, GElf_Xword offset, uint##SIZE##_t *retp)	\
221e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	{								\
222e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		if (!need_data(data, offset, SIZE / 8) < 0)		\
223e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			return -1;					\
224e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata									\
2256d8ccb236ccb4e31c8f2fb1c8b556fb7b055a418Petr Machata		if (data->d_buf == NULL) /* NODATA section */ {		\
2266d8ccb236ccb4e31c8f2fb1c8b556fb7b055a418Petr Machata			*retp = 0;					\
2276d8ccb236ccb4e31c8f2fb1c8b556fb7b055a418Petr Machata			return 0;					\
2286d8ccb236ccb4e31c8f2fb1c8b556fb7b055a418Petr Machata		}							\
2296d8ccb236ccb4e31c8f2fb1c8b556fb7b055a418Petr Machata									\
230e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		union {							\
231e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			uint##SIZE##_t dst;				\
232e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			char buf[0];					\
233e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		} u;							\
234e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		memcpy(u.buf, data->d_buf + offset, sizeof(u.dst));	\
235e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		*retp = u.dst;						\
236e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		return 0;						\
237fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	}
238fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
239e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr MachataDEF_READER(elf_read_u16, 16)
240e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr MachataDEF_READER(elf_read_u32, 32)
241e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr MachataDEF_READER(elf_read_u64, 64)
242fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
243e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#undef DEF_READER
244fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
2451974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machataint
24602bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machataopen_elf(struct ltelf *lte, const char *filename)
24702bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata{
2482d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	lte->fd = open(filename, O_RDONLY);
2492d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (lte->fd == -1)
2501974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata		return 1;
2511cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
25202bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	elf_version(EV_CURRENT);
25302bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata
254d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#ifdef HAVE_ELF_C_READ_MMAP
2552d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL);
256d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#else
2572d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL);
258d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#endif
2591cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
260cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF) {
261cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "\"%s\" is not an ELF file\n", filename);
262cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
263cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
2641cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
265cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (gelf_getehdr(lte->elf, &lte->ehdr) == NULL) {
266cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "can't read ELF header of \"%s\": %s\n",
267cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			filename, elf_errmsg(-1));
268cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
269cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
2701cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
271cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN) {
272cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "\"%s\" is neither an ELF executable"
273cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			" nor a shared library\n", filename);
274cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
275cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
2761cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
277ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	if (1
278ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef LT_ELF_MACHINE
279ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
280ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		|| lte->ehdr.e_machine != LT_ELF_MACHINE)
281ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
282d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#ifdef LT_ELF_MACHINE2
2832d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2
2842d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		|| lte->ehdr.e_machine != LT_ELF_MACHINE2)
285d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#endif
286d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#ifdef LT_ELF_MACHINE3
2872d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3
2882d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		|| lte->ehdr.e_machine != LT_ELF_MACHINE3)
289d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#endif
290cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		) {
291cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr,
292cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			"\"%s\" is ELF from incompatible architecture\n",
293cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			filename);
294cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
295cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
2962d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
29702bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	return 0;
29802bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata}
29902bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata
300cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machatastatic void
301cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machataread_symbol_table(struct ltelf *lte, const char *filename,
302cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		  Elf_Scn *scn, GElf_Shdr *shdr, const char *name,
303cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		  Elf_Data **datap, size_t *countp, const char **strsp)
304cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata{
305cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	*datap = elf_getdata(scn, NULL);
306cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	*countp = shdr->sh_size / shdr->sh_entsize;
307cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if ((*datap == NULL || elf_getdata(scn, *datap) != NULL)
308cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	    && options.static_filter != NULL) {
309cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "Couldn't get data of section"
310cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			" %s from \"%s\": %s\n",
311cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			name, filename, elf_errmsg(-1));
312cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
313cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
314cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata
315cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	scn = elf_getscn(lte->elf, shdr->sh_link);
316cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	GElf_Shdr shdr2;
317cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (scn == NULL || gelf_getshdr(scn, &shdr2) == NULL) {
318cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "Couldn't get header of section"
319cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			" #%d from \"%s\": %s\n",
320cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			shdr2.sh_link, filename, elf_errmsg(-1));
321cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
322cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
323cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata
324cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	Elf_Data *data = elf_getdata(scn, NULL);
325cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (data == NULL || elf_getdata(scn, data) != NULL
326cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	    || shdr2.sh_size != data->d_size || data->d_off) {
327cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "Couldn't get data of section"
328cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			" #%d from \"%s\": %s\n",
329cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			shdr2.sh_link, filename, elf_errmsg(-1));
330cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
331cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
332cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata
333cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	*strsp = data->d_buf;
334cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata}
335cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata
336e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machatastatic int
337da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machatado_init_elf(struct ltelf *lte, const char *filename)
3382b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata{
33902bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	int i;
34002bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	GElf_Addr relplt_addr = 0;
3412b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	GElf_Addr soname_offset = 0;
34202bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata
34302bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename);
34402bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	debug(1, "Reading ELF from %s...", filename);
34502bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata
3462d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	for (i = 1; i < lte->ehdr.e_shnum; ++i) {
3472d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		Elf_Scn *scn;
3482d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		GElf_Shdr shdr;
3492d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		const char *name;
3502d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
3512d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		scn = elf_getscn(lte->elf, i);
352cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
353cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			fprintf(stderr,	"Couldn't get section #%d from"
354cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				" \"%s\": %s\n", i, filename, elf_errmsg(-1));
355cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			exit(EXIT_FAILURE);
356cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		}
3572d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
3582d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name);
359cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		if (name == NULL) {
360cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			fprintf(stderr,	"Couldn't get name of section #%d from"
361cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				" \"%s\": %s\n", i, filename, elf_errmsg(-1));
362cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			exit(EXIT_FAILURE);
363cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		}
3642d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
3652d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		if (shdr.sh_type == SHT_SYMTAB) {
366cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			read_symbol_table(lte, filename,
367cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					  scn, &shdr, name, &lte->symtab,
368cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					  &lte->symtab_count, &lte->strtab);
3692d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
3702d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		} else if (shdr.sh_type == SHT_DYNSYM) {
371cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			read_symbol_table(lte, filename,
372cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					  scn, &shdr, name, &lte->dynsym,
373cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					  &lte->dynsym_count, &lte->dynstr);
3742d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
3752d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		} else if (shdr.sh_type == SHT_DYNAMIC) {
3762d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			Elf_Data *data;
3772d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			size_t j;
3782d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
379da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			lte->dyn_addr = shdr.sh_addr + lte->bias;
38087f4f58320226cd20d317f488c7e6a92a3efa2ddJoe Damato			lte->dyn_sz = shdr.sh_size;
38187f4f58320226cd20d317f488c7e6a92a3efa2ddJoe Damato
3822d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			data = elf_getdata(scn, NULL);
383cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			if (data == NULL || elf_getdata(scn, data) != NULL) {
384cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				fprintf(stderr, "Couldn't get .dynamic data"
385cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					" from \"%s\": %s\n",
386cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					filename, strerror(errno));
387cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				exit(EXIT_FAILURE);
388cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			}
3892d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
3902d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
3912d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				GElf_Dyn dyn;
3922d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
393cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				if (gelf_getdyn(data, j, &dyn) == NULL) {
394cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					fprintf(stderr, "Couldn't get .dynamic"
395cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata						" data from \"%s\": %s\n",
396cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata						filename, strerror(errno));
397cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					exit(EXIT_FAILURE);
398cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				}
3992d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				if (dyn.d_tag == DT_JMPREL)
4002d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand					relplt_addr = dyn.d_un.d_ptr;
4012d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				else if (dyn.d_tag == DT_PLTRELSZ)
402e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata					lte->relplt_size = dyn.d_un.d_val;
403e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata				else if (dyn.d_tag == DT_SONAME)
4042b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata					soname_offset = dyn.d_un.d_val;
4052d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			}
4062d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		} else if (shdr.sh_type == SHT_PROGBITS
4072d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			   || shdr.sh_type == SHT_NOBITS) {
4082d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			if (strcmp(name, ".plt") == 0) {
4092d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				lte->plt_addr = shdr.sh_addr;
4102d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				lte->plt_size = shdr.sh_size;
411e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata				lte->plt_data = elf_loaddata(scn, &shdr);
412e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata				if (lte->plt_data == NULL)
413e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata					fprintf(stderr,
414e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata						"Can't load .plt data\n");
41518c801c3f29081d9de517815df89bc1bbf8e2188Petr Machata				lte->plt_flags = shdr.sh_flags;
416b3f8fef12fccb0914b7b28725f42192c279d31c9Petr Machata			}
417b3f8fef12fccb0914b7b28725f42192c279d31c9Petr Machata#ifdef ARCH_SUPPORTS_OPD
418b3f8fef12fccb0914b7b28725f42192c279d31c9Petr Machata			else if (strcmp(name, ".opd") == 0) {
4193f1219f7803599df8556e7fc096a6a239f9a04fdPaul Gilliam				lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr;
4202d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				lte->opd_size = shdr.sh_size;
4212d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				lte->opd = elf_rawdata(scn, NULL);
4222d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			}
423b3f8fef12fccb0914b7b28725f42192c279d31c9Petr Machata#endif
4242d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		}
4259a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand	}
4269a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand
427cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (lte->dynsym == NULL || lte->dynstr == NULL) {
428cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "Couldn't find .dynsym or .dynstr in \"%s\"\n",
429cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			filename);
430cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
431cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
4322d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
4332d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (!relplt_addr || !lte->plt_addr) {
4342d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		debug(1, "%s has no PLT relocations", filename);
4352d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		lte->relplt = NULL;
4362d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		lte->relplt_count = 0;
437e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	} else if (lte->relplt_size == 0) {
438fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		debug(1, "%s has unknown PLT size", filename);
439fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		lte->relplt = NULL;
440fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		lte->relplt_count = 0;
4412d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	} else {
442fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
4432d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		for (i = 1; i < lte->ehdr.e_shnum; ++i) {
4442d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			Elf_Scn *scn;
4452d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			GElf_Shdr shdr;
4462d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
4472d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			scn = elf_getscn(lte->elf, i);
448cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
449cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				fprintf(stderr, "Couldn't get section header"
450cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					" from \"%s\": %s\n",
451cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					filename, elf_errmsg(-1));
452cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				exit(EXIT_FAILURE);
453cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			}
4542d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			if (shdr.sh_addr == relplt_addr
455e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			    && shdr.sh_size == lte->relplt_size) {
4562d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				lte->relplt = elf_getdata(scn, NULL);
4572d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				lte->relplt_count =
4582d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				    shdr.sh_size / shdr.sh_entsize;
4592d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				if (lte->relplt == NULL
460cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				    || elf_getdata(scn, lte->relplt) != NULL) {
461cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					fprintf(stderr, "Couldn't get .rel*.plt"
462cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata						" data from \"%s\": %s\n",
463cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata						filename, elf_errmsg(-1));
464cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					exit(EXIT_FAILURE);
465cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				}
4662d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				break;
4672d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			}
4682d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		}
4692d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
470cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		if (i == lte->ehdr.e_shnum) {
471cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			fprintf(stderr,
472cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				"Couldn't find .rel*.plt section in \"%s\"\n",
473cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				filename);
474cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			exit(EXIT_FAILURE);
475cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		}
4762d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
4772d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		debug(1, "%s %zd PLT relocations", filename, lte->relplt_count);
4782d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	}
4792b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata
4802b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	if (soname_offset != 0)
4812b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata		lte->soname = lte->dynstr + soname_offset;
4822b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata
4831974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata	return 0;
4841cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes}
4851cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
4867a2bdf8e5bf49d2fbb700981efd1d0a8728340edJoe Damatovoid
487588850f2d73fa03d5c4e59b82acb9c4eb1aaf1c0Petr Machatado_close_elf(struct ltelf *lte)
488588850f2d73fa03d5c4e59b82acb9c4eb1aaf1c0Petr Machata{
489cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "do_close_elf()");
4904d9a91c5c677d6a6b2db21f00385bce5167373c4Petr Machata	arch_elf_destroy(lte);
4912d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	elf_end(lte->elf);
4922d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	close(lte->fd);
4931cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes}
4941cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
495b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesiasint
49635b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesiaself_get_sym_info(struct ltelf *lte, const char *filename,
49735b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias		 size_t sym_index, GElf_Rela *rela, GElf_Sym *sym)
498b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias{
499b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	int i = sym_index;
500b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	GElf_Rel rel;
501b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	void *ret;
502b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias
503b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	if (lte->relplt->d_type == ELF_T_REL) {
504b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias		ret = gelf_getrel(lte->relplt, i, &rel);
505b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias		rela->r_offset = rel.r_offset;
506b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias		rela->r_info = rel.r_info;
507b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias		rela->r_addend = 0;
508b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	} else {
509b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias		ret = gelf_getrela(lte->relplt, i, rela);
510b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	}
511b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias
512b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	if (ret == NULL
513b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	    || ELF64_R_SYM(rela->r_info) >= lte->dynsym_count
514b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	    || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela->r_info),
515b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias			   sym) == NULL) {
516b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias		fprintf(stderr,
517b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias			"Couldn't get relocation from \"%s\": %s\n",
518b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias			filename, elf_errmsg(-1));
519b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias		exit(EXIT_FAILURE);
520b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	}
521b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias
522b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias	return 0;
523b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias}
52435b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias
52535b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias#ifndef ARCH_HAVE_GET_SYMINFO
52635b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesiasint
52735b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesiasarch_get_sym_info(struct ltelf *lte, const char *filename,
52835b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias		  size_t sym_index, GElf_Rela *rela, GElf_Sym *sym)
52935b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias{
53035b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias	return elf_get_sym_info(lte, filename, sym_index, rela, sym);
53135b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias}
532b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias#endif
533b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias
534e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machatastatic void
535e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machatamark_chain_latent(struct library_symbol *libsym)
536e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata{
537e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata	for (; libsym != NULL; libsym = libsym->next) {
538e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata		debug(DEBUG_FUNCTION, "marking %s latent", libsym->name);
539e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata		libsym->latent = 1;
540e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata	}
541e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata}
542e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata
543b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machatastatic int
544b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machatapopulate_plt(struct Process *proc, const char *filename,
545e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata	     struct ltelf *lte, struct library *lib,
546e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata	     int latent_plts)
547b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata{
548b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	size_t i;
549b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	for (i = 0; i < lte->relplt_count; ++i) {
550b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		GElf_Rela rela;
551b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		GElf_Sym sym;
552b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
553b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias		if (arch_get_sym_info(lte, filename, i, &rela, &sym) < 0)
554b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias			continue; /* Skip this entry.  */
555b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
556b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		char const *name = lte->dynstr + sym.st_name;
557b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
558e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata		/* If the symbol wasn't matched, reject it, unless we
559e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata		 * need to keep latent PLT breakpoints for tracing
560e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata		 * exports.  */
561e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata		int matched = filter_matches_symbol(options.plt_filter,
562e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata						    name, lib);
563e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata		if (!matched && !latent_plts)
564b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata			continue;
565b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
566218c5ff26841f5bbd188c42ccbd67422a7a20556Petr Machata		struct library_symbol *libsym = NULL;
567b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		switch (arch_elf_add_plt_entry(proc, lte, name,
568b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata					       &rela, i, &libsym)) {
569b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		case plt_default:
570b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata			if (default_elf_add_plt_entry(proc, lte, name,
571b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata						      &rela, i, &libsym) < 0)
5728eb0d9349614219cec5c3bb164f1376d83988525Petr Machata			/* fall-through */
573b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		case plt_fail:
574b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata				return -1;
5758eb0d9349614219cec5c3bb164f1376d83988525Petr Machata			/* fall-through */
576b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		case plt_ok:
577e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata			if (libsym != NULL) {
578e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata				/* If we are adding those symbols just
579e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata				 * for tracing exports, mark them all
580e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata				 * latent.  */
581e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata				if (!matched)
582e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata					mark_chain_latent(libsym);
583b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata				library_add_symbol(lib, libsym);
584e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata			}
585b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		}
586b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	}
587b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	return 0;
588b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata}
589b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
590157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata/* When -x rules result in request to trace several aliases, we only
591157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * want to add such symbol once.  The only way that those symbols
592157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * differ in is their name, e.g. in glibc you have __GI___libc_free,
593157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * __cfree, __free, __libc_free, cfree and free all defined on the
594157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * same address.  So instead we keep this unique symbol struct for
595157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * each address, and replace name in libsym with a shorter variant if
596157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * we find it.  */
597157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machatastruct unique_symbol {
598bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	arch_addr_t addr;
599157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	struct library_symbol *libsym;
600157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata};
601157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
602157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machatastatic int
603157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machataunique_symbol_cmp(const void *key, const void *val)
604157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata{
605157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	const struct unique_symbol *sym_key = key;
606157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	const struct unique_symbol *sym_val = val;
607157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	return sym_key->addr != sym_val->addr;
608157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata}
609157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
61010bd7a99d384f34c9c510828b722f29a8dc02393Petr Machatastatic enum callback_status
61110bd7a99d384f34c9c510828b722f29a8dc02393Petr Machatasymbol_with_address(struct library_symbol *sym, void *addrptr)
61210bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata{
61310bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata	return sym->enter_addr == *(arch_addr_t *)addrptr
61410bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		? CBS_STOP : CBS_CONT;
61510bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata}
61610bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata
617da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machatastatic int
618da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machatapopulate_this_symtab(struct Process *proc, const char *filename,
619da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		     struct ltelf *lte, struct library *lib,
620013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		     Elf_Data *symtab, const char *strtab, size_t size,
621013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		     struct library_exported_name **names)
622da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata{
623013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	/* If a valid NAMES is passed, we pass in *NAMES a list of
624013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * symbol names that this library exports.  */
625013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	if (names != NULL)
626013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		*names = NULL;
627013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
628157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	/* Using sorted array would be arguably better, but this
629157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	 * should be well enough for the number of symbols that we
630157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	 * typically deal with.  */
631157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	size_t num_symbols = 0;
632157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	struct unique_symbol *symbols = malloc(sizeof(*symbols) * size);
633157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	if (symbols == NULL) {
634cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "couldn't insert symbols for -x: %s\n",
635cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			strerror(errno));
636157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata		return -1;
637157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	}
638157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
63940cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata	GElf_Word secflags[lte->ehdr.e_shnum];
640da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata	size_t i;
64140cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata	for (i = 1; i < lte->ehdr.e_shnum; ++i) {
64240cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		Elf_Scn *scn = elf_getscn(lte->elf, i);
64340cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		if (scn == NULL)
64440cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata			continue;
64540cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		GElf_Shdr shdr;
64640cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		if (gelf_getshdr(scn, &shdr) == NULL)
64740cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata			continue;
64840cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		secflags[i] = shdr.sh_flags;
64940cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata	}
65040cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata
651da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata	for (i = 0; i < size; ++i) {
652da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		GElf_Sym sym;
653074f68fb8f57f93de3d94552a855b296b7a25906Petr Machata		if (gelf_getsym(symtab, i, &sym) == NULL) {
654da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		fail:
655cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			fprintf(stderr,
656cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				"couldn't get symbol #%zd from %s: %s\n",
657cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				i, filename, elf_errmsg(-1));
658da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata			continue;
659da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		}
660da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
6614de6b6b5ca9f7b3bb930663c43a8bf0f322e2bedPetr Machata		/* XXX support IFUNC as well.  */
6624de6b6b5ca9f7b3bb930663c43a8bf0f322e2bedPetr Machata		if (GELF_ST_TYPE(sym.st_info) != STT_FUNC
6636c1c0bb3494f787a5cf544e4d62375ec81af8d99Petr Machata		    || sym.st_value == 0
6646c1c0bb3494f787a5cf544e4d62375ec81af8d99Petr Machata		    || sym.st_shndx == STN_UNDEF)
6654de6b6b5ca9f7b3bb930663c43a8bf0f322e2bedPetr Machata			continue;
6664de6b6b5ca9f7b3bb930663c43a8bf0f322e2bedPetr Machata
667013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		/* Find symbol name and snip version.  */
6682bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		const char *orig_name = strtab + sym.st_name;
6692bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		const char *version = strchr(orig_name, '@');
6702bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		size_t len = version != NULL ? (assert(version > orig_name),
6712bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata						(size_t)(version - orig_name))
6722bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata			: strlen(orig_name);
6732bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		char name[len + 1];
6742bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		memcpy(name, orig_name, len);
6752bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		name[len] = 0;
6762bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata
677013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		/* If we are interested in exports, store this name.  */
678013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		char *name_copy = NULL;
679013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		if (names != NULL) {
680013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			struct library_exported_name *export = NULL;
681013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			name_copy = strdup(name);
682013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
683013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			if (name_copy == NULL
684013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			    || (export = malloc(sizeof(*export))) == NULL) {
685013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				free(name_copy);
686013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				fprintf(stderr, "Couldn't store symbol %s.  "
687013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata					"Tracing may be incomplete.\n", name);
688013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			} else {
689013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				export->name = name_copy;
690013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				export->own_name = 1;
691013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				export->next = *names;
692013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				*names = export;
693013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			}
694013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		}
695013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
696013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		/* If the symbol is not matched, skip it.  We already
697013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		 * stored it to export list above.  */
698da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		if (!filter_matches_symbol(options.static_filter, name, lib))
699da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata			continue;
700da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
701bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata		arch_addr_t addr = (arch_addr_t)
702ea8eb9a606096fd072abe104b4239f67883ad39aPetr Machata			(uintptr_t)(sym.st_value + lte->bias);
703bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata		arch_addr_t naddr;
70440cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata
70540cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		/* On arches that support OPD, the value of typical
70640cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		 * function symbol will be a pointer to .opd, but some
70740cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		 * will point directly to .text.  We don't want to
70840cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		 * translate those.  */
70940cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		if (secflags[sym.st_shndx] & SHF_EXECINSTR) {
71040cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata			naddr = addr;
711b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machata		} else if (arch_translate_address(lte, addr, &naddr) < 0) {
712cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			fprintf(stderr,
713cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				"couldn't translate address of %s@%s: %s\n",
714cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				name, lib->soname, strerror(errno));
715da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata			continue;
716da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		}
71740cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata
7183840f68c3d212d17444efaf1c8557f420622fd13Petr Machata		char *full_name;
719013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		int own_full_name = 1;
7200965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata		if (name_copy == NULL) {
7210965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata			full_name = strdup(name);
7223840f68c3d212d17444efaf1c8557f420622fd13Petr Machata			if (full_name == NULL)
7233840f68c3d212d17444efaf1c8557f420622fd13Petr Machata				goto fail;
7243840f68c3d212d17444efaf1c8557f420622fd13Petr Machata		} else {
7250965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata			full_name = name_copy;
7260965420dfd1f4167609c4b3bbee5dc0277423897Petr Machata			own_full_name = 0;
7273840f68c3d212d17444efaf1c8557f420622fd13Petr Machata		}
7284de6b6b5ca9f7b3bb930663c43a8bf0f322e2bedPetr Machata
729157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata		/* Look whether we already have a symbol for this
730157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata		 * address.  If not, add this one.  */
731157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata		struct unique_symbol key = { naddr, NULL };
732157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata		struct unique_symbol *unique
733157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata			= lsearch(&key, symbols, &num_symbols,
734157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata				  sizeof(*symbols), &unique_symbol_cmp);
735157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
736157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata		if (unique->libsym == NULL) {
737157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata			struct library_symbol *libsym = malloc(sizeof(*libsym));
738e8d9076a97f6617868466a99bd18e11e3f6389acPetr Machata			if (libsym == NULL
739013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			    || library_symbol_init(libsym, naddr,
740013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata						   full_name, own_full_name,
741013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata						   LS_TOPLT_NONE) < 0) {
742157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata				--num_symbols;
743157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata				goto fail;
744157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata			}
745157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata			unique->libsym = libsym;
746157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata			unique->addr = naddr;
747157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
748157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata		} else if (strlen(full_name) < strlen(unique->libsym->name)) {
749013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			library_symbol_set_name(unique->libsym,
750013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata						full_name, own_full_name);
751da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
752013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		} else if (own_full_name) {
753157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata			free(full_name);
754157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata		}
755da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata	}
756157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
75710bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata	/* Now we do the union of this set of unique symbols with
75810bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata	 * what's already in the library.  */
759157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	for (i = 0; i < num_symbols; ++i) {
76010bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		struct library_symbol *this_sym = symbols[i].libsym;
76110bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		assert(this_sym != NULL);
76210bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		struct library_symbol *other
76310bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata			= library_each_symbol(lib, NULL, symbol_with_address,
76410bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata					      &this_sym->enter_addr);
76510bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		if (other != NULL) {
76610bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata			library_symbol_destroy(this_sym);
76710bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata			free(this_sym);
76810bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata			symbols[i].libsym = NULL;
76910bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		}
770157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	}
771157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
77210bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata	for (i = 0; i < num_symbols; ++i)
77310bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		if (symbols[i].libsym != NULL)
77410bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata			library_add_symbol(lib, symbols[i].libsym);
775157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
77610bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata	free(symbols);
777da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata	return 0;
778da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata}
779da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
780da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machatastatic int
781da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machatapopulate_symtab(struct Process *proc, const char *filename,
782013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		struct ltelf *lte, struct library *lib,
783013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		int symtabs, int exports)
784da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata{
785013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	int status;
786013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	if (symtabs && lte->symtab != NULL && lte->strtab != NULL
787013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	    && (status = populate_this_symtab(proc, filename, lte, lib,
788013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata					      lte->symtab, lte->strtab,
789013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata					      lte->symtab_count, NULL)) < 0)
790013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		return status;
791013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
792013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	/* Check whether we want to trace symbols implemented by this
793013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * library (-l).  */
794013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	struct library_exported_name **names = NULL;
795013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	if (exports) {
796013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		debug(DEBUG_FUNCTION, "-l matches %s", lib->soname);
797013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		names = &lib->exported_names;
798013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	}
799013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
800013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	return populate_this_symtab(proc, filename, lte, lib,
801013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				    lte->dynsym, lte->dynstr,
802013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				    lte->dynsym_count, names);
803da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata}
804da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
805da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machatastatic int
806da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machataread_module(struct library *lib, struct Process *proc,
807da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	    const char *filename, GElf_Addr bias, int main)
808e84fa00bdabf20f57d1d02d159aa3fcab4e549fePetr Machata{
80929add4fdf852b10ddd22cac0d1390f6d01577bc2Petr Machata	struct ltelf lte = {};
810da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	if (open_elf(&lte, filename) < 0)
811da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		return -1;
812da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
8131c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	/* XXX When we abstract ABI into a module, this should instead
8141c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 * become something like
8151c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 *
8161c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 *    proc->abi = arch_get_abi(lte.ehdr);
8171c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 *
8181c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 * The code in open_elf needs to be replaced by this logic.
8191c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 * Be warned that libltrace.c calls open_elf as well to
8201c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 * determine whether ABI is supported.  This is to get
8211c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 * reasonable error messages when trying to run 64-bit binary
8221c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 * with 32-bit ltrace.  It is desirable to preserve this.  */
8231c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	proc->e_machine = lte.ehdr.e_machine;
8241c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	proc->e_class = lte.ehdr.e_ident[EI_CLASS];
8251c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	get_arch_dep(proc);
8261c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata
827da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	/* Find out the base address.  For PIE main binaries we look
828da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	 * into auxv, otherwise we scan phdrs.  */
829da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	if (main && lte.ehdr.e_type == ET_DYN) {
830da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		arch_addr_t entry;
831da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		if (process_get_entry(proc, &entry, NULL) < 0) {
832da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			fprintf(stderr, "Couldn't find entry of PIE %s\n",
833da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata				filename);
834da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			return -1;
835da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		}
836b024ca33e3734592a67e41414c2dc02978218501Petr Machata		/* XXX The double cast should be removed when
837b024ca33e3734592a67e41414c2dc02978218501Petr Machata		 * arch_addr_t becomes integral type.  */
838b024ca33e3734592a67e41414c2dc02978218501Petr Machata		lte.entry_addr = (GElf_Addr)(uintptr_t)entry;
839b024ca33e3734592a67e41414c2dc02978218501Petr Machata		lte.bias = (GElf_Addr)(uintptr_t)entry - lte.ehdr.e_entry;
840da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
841da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	} else {
842da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		GElf_Phdr phdr;
843da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		size_t i;
844da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		for (i = 0; gelf_getphdr (lte.elf, i, &phdr) != NULL; ++i) {
845da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			if (phdr.p_type == PT_LOAD) {
846da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata				lte.base_addr = phdr.p_vaddr + bias;
847da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata				break;
848da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			}
849da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		}
850da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
851da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		lte.bias = bias;
852da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		lte.entry_addr = lte.ehdr.e_entry + lte.bias;
853da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
854da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		if (lte.base_addr == 0) {
855da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			fprintf(stderr,
856da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata				"Couldn't determine base address of %s\n",
857da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata				filename);
858da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			return -1;
859da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		}
860da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	}
861da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
862da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	if (do_init_elf(&lte, filename) < 0)
863b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		return -1;
864da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
865e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machata	if (arch_elf_init(&lte, lib) < 0) {
866e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machata		fprintf(stderr, "Backend initialization failed.\n");
867e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machata		return -1;
868e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machata	}
869e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machata
870b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	int status = 0;
871fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	if (lib == NULL)
872fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		goto fail;
873fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata
874fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	/* Note that we set soname and pathname as soon as they are
875fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * allocated, so in case of further errors, this get released
876fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * when LIB is release, which should happen in the caller when
877fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * we return error.  */
878fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata
879fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	if (lib->pathname == NULL) {
880fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		char *pathname = strdup(filename);
881fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		if (pathname == NULL)
882fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata			goto fail;
883f13afd562dfbf9aa563177bfbbd1d9fc8e3cf2a3Petr Machata		library_set_pathname(lib, pathname, 1);
884f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato	}
885f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato
8860b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	if (lte.soname != NULL) {
887fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		char *soname = strdup(lte.soname);
888fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		if (soname == NULL)
889fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata			goto fail;
890fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		library_set_soname(lib, soname, 1);
8910b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	} else {
892fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		const char *soname = rindex(lib->pathname, '/') + 1;
893fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		if (soname == NULL)
894fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata			soname = lib->pathname;
895fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		library_set_soname(lib, soname, 0);
8960b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	}
897fa2aefc32eb4196966a14d1e7def931652f40d46Joe Damato
898ea8eb9a606096fd072abe104b4239f67883ad39aPetr Machata	/* XXX The double cast should be removed when
899bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	 * arch_addr_t becomes integral type.  */
900bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	arch_addr_t entry = (arch_addr_t)(uintptr_t)lte.entry_addr;
901b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machata	if (arch_translate_address(&lte, entry, &entry) < 0)
902b120fdfda45e49d082ab2aa5caadf030f50cb4edPetr Machata		goto fail;
903b120fdfda45e49d082ab2aa5caadf030f50cb4edPetr Machata
904ea8eb9a606096fd072abe104b4239f67883ad39aPetr Machata	/* XXX The double cast should be removed when
905bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	 * arch_addr_t becomes integral type.  */
906bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	lib->base = (arch_addr_t)(uintptr_t)lte.base_addr;
907b120fdfda45e49d082ab2aa5caadf030f50cb4edPetr Machata	lib->entry = entry;
908ea8eb9a606096fd072abe104b4239f67883ad39aPetr Machata	/* XXX The double cast should be removed when
909bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	 * arch_addr_t becomes integral type.  */
910bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	lib->dyn_addr = (arch_addr_t)(uintptr_t)lte.dyn_addr;
911fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
912013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	/* There are two reasons that we need to inspect symbol tables
913013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * or populate PLT entries.  Either the user requested
914013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * corresponding tracing features (respectively -x and -e), or
915013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * they requested tracing exported symbols (-l).
916013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 *
917013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * In the latter case we need to keep even those PLT slots
918013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * that are not requested by -e (but we keep them latent).  We
919013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * also need to inspect .dynsym to find what exports this
920013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * library provide, to turn on existing latent PLT
921013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * entries.  */
922013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
923013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	int plts = filter_matches_library(options.plt_filter, lib);
924013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	if ((plts || options.export_filter != NULL)
925e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata	    && populate_plt(proc, filename, &lte, lib,
926e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata			    options.export_filter != NULL) < 0)
927b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		goto fail;
9282d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
929013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	int exports = filter_matches_library(options.export_filter, lib);
930013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	int symtabs = filter_matches_library(options.static_filter, lib);
931013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	if ((symtabs || exports)
932013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	    && populate_symtab(proc, filename, &lte, lib,
933013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			       symtabs, exports) < 0)
934da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		goto fail;
935da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
9362b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machatadone:
9372b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	do_close_elf(&lte);
938b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	return status;
939fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata
940fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machatafail:
941fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	status = -1;
942fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	goto done;
9432b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata}
9442d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
945da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machataint
946da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machataltelf_read_library(struct library *lib, struct Process *proc,
947da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		   const char *filename, GElf_Addr bias)
948da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata{
949da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	return read_module(lib, proc, filename, bias, 0);
950da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata}
951da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
952da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
9532b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machatastruct library *
9542b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machataltelf_read_main_binary(struct Process *proc, const char *path)
9552b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata{
956b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	struct library *lib = malloc(sizeof(*lib));
957b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	if (lib == NULL)
958b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		return NULL;
959b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	library_init(lib, LT_LIBTYPE_MAIN);
960fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	library_set_pathname(lib, path, 0);
961b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
962fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	/* There is a race between running the process and reading its
963fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * binary for internal consumption.  So open the binary from
964fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * the /proc filesystem.  XXX Note that there is similar race
965fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * for libraries, but there we don't have a nice answer like
966fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * that.  Presumably we could read the DSOs from the process
967fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * memory image, but that's not currently done.  */
9682b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	char *fname = pid2name(proc->pid);
969ef0c74de9320c86ab1f08e5f9c15b031ed36d01fPetr Machata	if (fname == NULL)
970ef0c74de9320c86ab1f08e5f9c15b031ed36d01fPetr Machata		return NULL;
971da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	if (read_module(lib, proc, fname, 0, 1) < 0) {
972b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		library_destroy(lib);
973b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		free(lib);
974b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		return NULL;
9750b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	}
976ef0c74de9320c86ab1f08e5f9c15b031ed36d01fPetr Machata	free(fname);
977b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
9782b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	return lib;
97996935a9fe2af57e089cbd2e32a69caba5b3f2458Juan Cespedes}
980