1642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata/*
2642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata * This file is part of ltrace.
3aafb00b7d7751049b99cac3953b5021e4f474ac4Petr Machata * Copyright (C) 2006,2010,2011,2012,2013 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>
3997d13666cd84589135ba593fa43a800d098026d0Petr Machata#include <stdbool.h>
40d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#include <stdint.h>
41cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata#include <stdio.h>
42d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#include <stdlib.h>
4396935a9fe2af57e089cbd2e32a69caba5b3f2458Juan Cespedes#include <string.h>
44513258cf3063bcdfbd4a7aeb3c9fe3b8484ccdf5Petr Machata#include <strings.h>
455e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes#include <unistd.h>
4696935a9fe2af57e089cbd2e32a69caba5b3f2458Juan Cespedes
47642626096a694c6af279d25d2b1b2fba5b10ddfbPetr Machata#include "backend.h"
48ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "filter.h"
49ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "library.h"
50ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "ltrace-elf.h"
51ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "proc.h"
52ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "debug.h"
53ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "options.h"
54f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato
55e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#ifndef ARCH_HAVE_LTELF_DATA
56e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machataint
57e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machataarch_elf_init(struct ltelf *lte, struct library *lib)
58e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata{
59e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	return 0;
60e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata}
61c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata
62c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machatavoid
63c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machataarch_elf_destroy(struct ltelf *lte)
64c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata{
65c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata}
66e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#endif
67e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata
6897d13666cd84589135ba593fa43a800d098026d0Petr Machata#ifndef OS_HAVE_ADD_PLT_ENTRY
6997d13666cd84589135ba593fa43a800d098026d0Petr Machataenum plt_status
7097d13666cd84589135ba593fa43a800d098026d0Petr Machataos_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
7197d13666cd84589135ba593fa43a800d098026d0Petr Machata		     const char *a_name, GElf_Rela *rela, size_t ndx,
7297d13666cd84589135ba593fa43a800d098026d0Petr Machata		     struct library_symbol **ret)
73e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata{
7497d13666cd84589135ba593fa43a800d098026d0Petr Machata	return PLT_DEFAULT;
75e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata}
7697d13666cd84589135ba593fa43a800d098026d0Petr Machata#endif
77e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata
78e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata#ifndef ARCH_HAVE_ADD_PLT_ENTRY
79e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machataenum plt_status
80929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
811be2291ffdf3a20b0a1702f5705f82617fb91ef6Petr Machata		       const char *a_name, GElf_Rela *rela, size_t ndx,
82e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata		       struct library_symbol **ret)
83e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata{
84ade3b9798fbc62becbe1b4854f7a2d106498167aPetr Machata	return PLT_DEFAULT;
85e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata}
86e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata#endif
87e6523e69b0230fef8dddbf628e0511a004203eb8Petr Machata
88a186b0e5c469156b9af66e88dca12d208418195cPetr Machata#ifndef OS_HAVE_ADD_FUNC_ENTRY
89a186b0e5c469156b9af66e88dca12d208418195cPetr Machataenum plt_status
90a186b0e5c469156b9af66e88dca12d208418195cPetr Machataos_elf_add_func_entry(struct process *proc, struct ltelf *lte,
91a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		      const GElf_Sym *sym,
92a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		      arch_addr_t addr, const char *name,
93a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		      struct library_symbol **ret)
94a186b0e5c469156b9af66e88dca12d208418195cPetr Machata{
95a186b0e5c469156b9af66e88dca12d208418195cPetr Machata	if (GELF_ST_TYPE(sym->st_info) != STT_FUNC) {
96a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		*ret = NULL;
97a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		return PLT_OK;
98a186b0e5c469156b9af66e88dca12d208418195cPetr Machata	} else {
99a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		return PLT_DEFAULT;
100a186b0e5c469156b9af66e88dca12d208418195cPetr Machata	}
101a186b0e5c469156b9af66e88dca12d208418195cPetr Machata}
102a186b0e5c469156b9af66e88dca12d208418195cPetr Machata#endif
103a186b0e5c469156b9af66e88dca12d208418195cPetr Machata
10497d13666cd84589135ba593fa43a800d098026d0Petr Machata#ifndef ARCH_HAVE_ADD_FUNC_ENTRY
10597d13666cd84589135ba593fa43a800d098026d0Petr Machataenum plt_status
10697d13666cd84589135ba593fa43a800d098026d0Petr Machataarch_elf_add_func_entry(struct process *proc, struct ltelf *lte,
10797d13666cd84589135ba593fa43a800d098026d0Petr Machata			const GElf_Sym *sym,
10897d13666cd84589135ba593fa43a800d098026d0Petr Machata			arch_addr_t addr, const char *name,
10997d13666cd84589135ba593fa43a800d098026d0Petr Machata			struct library_symbol **ret)
11097d13666cd84589135ba593fa43a800d098026d0Petr Machata{
11197d13666cd84589135ba593fa43a800d098026d0Petr Machata	return PLT_DEFAULT;
11297d13666cd84589135ba593fa43a800d098026d0Petr Machata}
11397d13666cd84589135ba593fa43a800d098026d0Petr Machata#endif
11497d13666cd84589135ba593fa43a800d098026d0Petr Machata
115e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr MachataElf_Data *
116e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machataelf_loaddata(Elf_Scn *scn, GElf_Shdr *shdr)
117fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata{
118fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	Elf_Data *data = elf_getdata(scn, NULL);
119fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	if (data == NULL || elf_getdata(scn, data) != NULL
120fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	    || data->d_off || data->d_size != shdr->sh_size)
121fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		return NULL;
122fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	return data;
123fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata}
124fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
125e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machatastatic int
126ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machataelf_get_section_if(struct ltelf *lte, Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr,
127ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		   int (*predicate)(Elf_Scn *, GElf_Shdr *, void *data),
128ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		   void *data)
129fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata{
130fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	int i;
131fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	for (i = 1; i < lte->ehdr.e_shnum; ++i) {
132fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		Elf_Scn *scn;
133fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		GElf_Shdr shdr;
134fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
135fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		scn = elf_getscn(lte->elf, i);
136fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
137fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata			debug(1, "Couldn't read section or header.");
138e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			return -1;
139fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		}
140ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		if (predicate(scn, &shdr, data)) {
141ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata			*tgt_sec = scn;
142ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata			*tgt_shdr = shdr;
143e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			return 0;
144ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		}
145fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	}
146ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata
14799b19eb1bb736d7066026894aa69e70de8a03094Petr Machata	*tgt_sec = NULL;
14899b19eb1bb736d7066026894aa69e70de8a03094Petr Machata	return 0;
149ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata}
150ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata
151ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machatastatic int
152ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machatainside_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data)
153ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata{
154ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	GElf_Addr addr = *(GElf_Addr *)data;
155ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	return addr >= shdr->sh_addr
156ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		&& addr < shdr->sh_addr + shdr->sh_size;
157ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata}
158ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata
159ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machataint
160ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machataelf_get_section_covering(struct ltelf *lte, GElf_Addr addr,
161ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata			 Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
162ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata{
163ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	return elf_get_section_if(lte, tgt_sec, tgt_shdr,
164ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata				  &inside_p, &addr);
165ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata}
166ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata
167ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machatastatic int
168ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machatatype_p(Elf_Scn *scn, GElf_Shdr *shdr, void *data)
169ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata{
170ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	GElf_Word type = *(GElf_Word *)data;
171ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	return shdr->sh_type == type;
172ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata}
173ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata
174ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machataint
175ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machataelf_get_section_type(struct ltelf *lte, GElf_Word type,
176ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata		     Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
177ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata{
178ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata	return elf_get_section_if(lte, tgt_sec, tgt_shdr,
179ffd5aab0bddbbb7c650c2f5c12a48e0298f82516Petr Machata				  &type_p, &type);
180fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata}
181fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
1825b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machatastruct section_named_data {
1835b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	struct ltelf *lte;
1845b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	const char *name;
1855b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata};
1865b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata
1875b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machatastatic int
1885b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machataname_p(Elf_Scn *scn, GElf_Shdr *shdr, void *d)
1895b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata{
1905b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	struct section_named_data *data = d;
1915b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	const char *name = elf_strptr(data->lte->elf,
1925b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata				      data->lte->ehdr.e_shstrndx,
1935b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata				      shdr->sh_name);
1945b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	return strcmp(name, data->name) == 0;
1955b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata}
1965b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata
1975b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machataint
1985b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machataelf_get_section_named(struct ltelf *lte, const char *name,
1995b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata		     Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr)
2005b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata{
2015b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	struct section_named_data data = {
2025b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata		.lte = lte,
2035b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata		.name = name,
2045b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	};
2055b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata	return elf_get_section_if(lte, tgt_sec, tgt_shdr,
2065b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata				  &name_p, &data);
2075b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata}
2085b3e26acd50d74e8b7c007f8b5dfb1a825ef9affPetr Machata
2097a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machatastatic struct elf_each_symbol_t
2107a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machataeach_symbol_in(Elf_Data *symtab, const char *strtab, size_t count,
2117a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	       unsigned i,
2127a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	       enum callback_status (*cb)(GElf_Sym *symbol,
2137a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata					  const char *name, void *data),
2147a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	       void *data)
2157a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata{
2167a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	for (; i < count; ++i) {
2177a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		GElf_Sym sym;
2187a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		if (gelf_getsym(symtab, i, &sym) == NULL)
2197a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata			return (struct elf_each_symbol_t){ i, -2 };
2207a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata
2217a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		switch (cb(&sym, strtab + sym.st_name, data)) {
2227a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		case CBS_FAIL:
2237a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata			return (struct elf_each_symbol_t){ i, -1 };
2247a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		case CBS_STOP:
2257a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata			return (struct elf_each_symbol_t){ i + 1, 0 };
2267a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		case CBS_CONT:
2277a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata			break;
2287a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		}
2297a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	}
2307a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata
2317a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	return (struct elf_each_symbol_t){ 0, 0 };
2327a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata}
2337a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata
2347a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata/* N.B.: gelf_getsym takes integer argument.  Since negative values
2357a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata * are invalid as indices, we can use the extra bit to encode which
2367a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata * symbol table we are looking into.  ltrace currently doesn't handle
2377a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata * more than two symbol tables anyway, nor does it handle the xindex
2387a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata * stuff.  */
2397a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machatastruct elf_each_symbol_t
2407a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machataelf_each_symbol(struct ltelf *lte, unsigned start_after,
2417a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		enum callback_status (*cb)(GElf_Sym *symbol,
2427a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata					   const char *name, void *data),
2437a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		void *data)
2447a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata{
2457a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	unsigned index = start_after == 0 ? 0 : start_after >> 1;
2467a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata
2477a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	/* Go through static symbol table first.  */
2487a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	if ((start_after & 0x1) == 0) {
2497a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		struct elf_each_symbol_t st
2507a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata			= each_symbol_in(lte->symtab, lte->strtab,
2517a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata					 lte->symtab_count, index, cb, data);
2527a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata
2537a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		/* If the iteration stopped prematurely, bail out.  */
2547a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		if (st.restart != 0)
2557a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata			return ((struct elf_each_symbol_t)
2567a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata				{ st.restart << 1, st.status });
2577a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	}
2587a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata
2597a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	struct elf_each_symbol_t st
2607a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		= each_symbol_in(lte->dynsym, lte->dynstr, lte->dynsym_count,
2617a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata				 index, cb, data);
2627a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	if (st.restart != 0)
2637a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata		return ((struct elf_each_symbol_t)
2647a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata			{ st.restart << 1 | 0x1, st.status });
2657a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata
2667a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata	return (struct elf_each_symbol_t){ 0, 0 };
2677a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata}
2687a29f9e7a2bd5849886519eb82e9c043d24c6a40Petr Machata
2695c37171a18bddfbc716d4f3da8b008a844eea4f7Petr Machataint
2705c37171a18bddfbc716d4f3da8b008a844eea4f7Petr Machataelf_can_read_next(Elf_Data *data, GElf_Xword offset, GElf_Xword size)
271fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata{
272e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	assert(data != NULL);
273e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	if (data->d_size < size || offset > data->d_size - size) {
274a82d32209f276e10dd1f437b38b4b6e5de32b980Petr Machata		debug(1, "Not enough data to read %"PRId64"-byte value"
275a82d32209f276e10dd1f437b38b4b6e5de32b980Petr Machata		      " at offset %"PRId64".", size, offset);
2765c37171a18bddfbc716d4f3da8b008a844eea4f7Petr Machata		return 0;
277fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	}
2785c37171a18bddfbc716d4f3da8b008a844eea4f7Petr Machata	return 1;
279fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata}
280fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
281e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#define DEF_READER(NAME, SIZE)						\
282e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	int								\
2833a01cd7a2fcf200cedd0770e137a28764f679c3cPetr Machata	NAME(Elf_Data *data, GElf_Xword offset, uint##SIZE##_t *retp)	\
284e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata	{								\
2855c37171a18bddfbc716d4f3da8b008a844eea4f7Petr Machata		if (!elf_can_read_next(data, offset, SIZE / 8))		\
286e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			return -1;					\
287e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata									\
2886d8ccb236ccb4e31c8f2fb1c8b556fb7b055a418Petr Machata		if (data->d_buf == NULL) /* NODATA section */ {		\
2896d8ccb236ccb4e31c8f2fb1c8b556fb7b055a418Petr Machata			*retp = 0;					\
2906d8ccb236ccb4e31c8f2fb1c8b556fb7b055a418Petr Machata			return 0;					\
2916d8ccb236ccb4e31c8f2fb1c8b556fb7b055a418Petr Machata		}							\
2926d8ccb236ccb4e31c8f2fb1c8b556fb7b055a418Petr Machata									\
293e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		union {							\
294e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			uint##SIZE##_t dst;				\
295e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata			char buf[0];					\
296e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		} u;							\
297e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		memcpy(u.buf, data->d_buf + offset, sizeof(u.dst));	\
298e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		*retp = u.dst;						\
299e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata		return 0;						\
300fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata	}
301fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
3023c636fb789a29cac0c8f7f0982fb17afeee489dcPetr MachataDEF_READER(elf_read_u8, 8)
303e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr MachataDEF_READER(elf_read_u16, 16)
304e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr MachataDEF_READER(elf_read_u32, 32)
305e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr MachataDEF_READER(elf_read_u64, 64)
306fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
307e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#undef DEF_READER
308fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
309439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata#define DEF_READER(NAME, SIZE)						\
310439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata	int								\
311439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata	NAME(Elf_Data *data, GElf_Xword *offset, uint##SIZE##_t *retp)	\
312439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata	{								\
313439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata		int rc = elf_read_u##SIZE(data, *offset, retp);		\
314439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata		if (rc < 0)						\
315439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata			return rc;					\
316439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata		*offset += SIZE / 8;					\
317439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata		return 0;						\
318439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata	}
319439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata
320439ab5bfac8588e52c77e22c96fb397787512d0ePetr MachataDEF_READER(elf_read_next_u8, 8)
321439ab5bfac8588e52c77e22c96fb397787512d0ePetr MachataDEF_READER(elf_read_next_u16, 16)
322439ab5bfac8588e52c77e22c96fb397787512d0ePetr MachataDEF_READER(elf_read_next_u32, 32)
323439ab5bfac8588e52c77e22c96fb397787512d0ePetr MachataDEF_READER(elf_read_next_u64, 64)
324439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata
325439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata#undef DEF_READER
326439ab5bfac8588e52c77e22c96fb397787512d0ePetr Machata
3271974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machataint
328184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machataelf_read_next_uleb128(Elf_Data *data, GElf_Xword *offset, uint64_t *retp)
329184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata{
330184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata	uint64_t result = 0;
331184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata	int shift = 0;
332184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata	int size = 8 * sizeof result;
333184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata
334184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata	while (1) {
335184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata		uint8_t byte;
336184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata		if (elf_read_next_u8(data, offset, &byte) < 0)
337184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata			return -1;
338184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata
339184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata		uint8_t payload = byte & 0x7f;
340184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata		result |= (uint64_t)payload << shift;
341184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata		shift += 7;
342184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata		if (shift > size && byte != 0x1)
343184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata			return -1;
344184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata		if ((byte & 0x80) == 0)
345184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata			break;
346184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata	}
347184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata
348184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata	if (retp != NULL)
349184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata		*retp = result;
350184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata	return 0;
351184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata}
352184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata
353184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machataint
354184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machataelf_read_uleb128(Elf_Data *data, GElf_Xword offset, uint64_t *retp)
355184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata{
356184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata	return elf_read_next_uleb128(data, &offset, retp);
357184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata}
358184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machata
359184779e4e8a42f2e9e7f3cee4bf4eb31e8c84ee4Petr Machataint
360673ff510953b65b844a58478aa434120f457c014Petr Machataltelf_init(struct ltelf *lte, const char *filename)
36102bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata{
362673ff510953b65b844a58478aa434120f457c014Petr Machata	memset(lte, 0, sizeof *lte);
3632d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	lte->fd = open(filename, O_RDONLY);
3642bfea358ea6730980fb6fbbd896bbbf4e58238eePetr Machata	if (lte->fd == -1) {
3652bfea358ea6730980fb6fbbd896bbbf4e58238eePetr Machata		fprintf(stderr, "Can't open %s: %s\n", filename,
3662bfea358ea6730980fb6fbbd896bbbf4e58238eePetr Machata			strerror(errno));
3671974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata		return 1;
3682bfea358ea6730980fb6fbbd896bbbf4e58238eePetr Machata	}
3691cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
37002bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	elf_version(EV_CURRENT);
37102bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata
372d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#ifdef HAVE_ELF_C_READ_MMAP
3732d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	lte->elf = elf_begin(lte->fd, ELF_C_READ_MMAP, NULL);
374d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#else
3752d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	lte->elf = elf_begin(lte->fd, ELF_C_READ, NULL);
376d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#endif
3771cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
378cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (lte->elf == NULL || elf_kind(lte->elf) != ELF_K_ELF) {
379cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "\"%s\" is not an ELF file\n", filename);
380cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
381cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
3821cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
383cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (gelf_getehdr(lte->elf, &lte->ehdr) == NULL) {
384cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "can't read ELF header of \"%s\": %s\n",
385cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			filename, elf_errmsg(-1));
386cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
387cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
3881cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
389cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (lte->ehdr.e_type != ET_EXEC && lte->ehdr.e_type != ET_DYN) {
390cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "\"%s\" is neither an ELF executable"
391cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			" nor a shared library\n", filename);
392cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
393cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
3941cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
395ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	if (1
396ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef LT_ELF_MACHINE
397ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS
398ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		|| lte->ehdr.e_machine != LT_ELF_MACHINE)
399ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
400d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#ifdef LT_ELF_MACHINE2
4012d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS2
4022d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		|| lte->ehdr.e_machine != LT_ELF_MACHINE2)
403d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#endif
404d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#ifdef LT_ELF_MACHINE3
4052d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	    && (lte->ehdr.e_ident[EI_CLASS] != LT_ELFCLASS3
4062d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		|| lte->ehdr.e_machine != LT_ELF_MACHINE3)
407d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#endif
408cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		) {
409cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr,
410cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			"\"%s\" is ELF from incompatible architecture\n",
411cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			filename);
412cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
413cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
4142d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
415673ff510953b65b844a58478aa434120f457c014Petr Machata	VECT_INIT(&lte->plt_relocs, GElf_Rela);
416673ff510953b65b844a58478aa434120f457c014Petr Machata
41702bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	return 0;
41802bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata}
41902bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata
420673ff510953b65b844a58478aa434120f457c014Petr Machatavoid
421673ff510953b65b844a58478aa434120f457c014Petr Machataltelf_destroy(struct ltelf *lte)
422673ff510953b65b844a58478aa434120f457c014Petr Machata{
423673ff510953b65b844a58478aa434120f457c014Petr Machata	debug(DEBUG_FUNCTION, "close_elf()");
424673ff510953b65b844a58478aa434120f457c014Petr Machata	elf_end(lte->elf);
425673ff510953b65b844a58478aa434120f457c014Petr Machata	close(lte->fd);
426673ff510953b65b844a58478aa434120f457c014Petr Machata	VECT_DESTROY(&lte->plt_relocs, GElf_Rela, NULL, NULL);
427673ff510953b65b844a58478aa434120f457c014Petr Machata}
428673ff510953b65b844a58478aa434120f457c014Petr Machata
429cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machatastatic void
430cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machataread_symbol_table(struct ltelf *lte, const char *filename,
431cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		  Elf_Scn *scn, GElf_Shdr *shdr, const char *name,
432cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		  Elf_Data **datap, size_t *countp, const char **strsp)
433cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata{
434cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	*datap = elf_getdata(scn, NULL);
435cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	*countp = shdr->sh_size / shdr->sh_entsize;
436cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if ((*datap == NULL || elf_getdata(scn, *datap) != NULL)
437cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	    && options.static_filter != NULL) {
438cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "Couldn't get data of section"
439cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			" %s from \"%s\": %s\n",
440cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			name, filename, elf_errmsg(-1));
441cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
442cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
443cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata
444cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	scn = elf_getscn(lte->elf, shdr->sh_link);
445cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	GElf_Shdr shdr2;
446cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (scn == NULL || gelf_getshdr(scn, &shdr2) == NULL) {
447cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "Couldn't get header of section"
448cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			" #%d from \"%s\": %s\n",
44902ecb499445a441cd1ceec4cfb00fab59ce0b23bPetr Machata			shdr->sh_link, filename, elf_errmsg(-1));
450cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
451cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
452cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata
453cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	Elf_Data *data = elf_getdata(scn, NULL);
454cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (data == NULL || elf_getdata(scn, data) != NULL
455cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	    || shdr2.sh_size != data->d_size || data->d_off) {
456cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "Couldn't get data of section"
457cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			" #%d from \"%s\": %s\n",
458cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			shdr2.sh_link, filename, elf_errmsg(-1));
459cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
460cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
461cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata
462cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	*strsp = data->d_buf;
463cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata}
464cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata
465e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machatastatic int
466673ff510953b65b844a58478aa434120f457c014Petr Machatarel_to_rela(struct ltelf *lte, const GElf_Rel *rel, GElf_Rela *rela)
467673ff510953b65b844a58478aa434120f457c014Petr Machata{
468673ff510953b65b844a58478aa434120f457c014Petr Machata	rela->r_offset = rel->r_offset;
469673ff510953b65b844a58478aa434120f457c014Petr Machata	rela->r_info = rel->r_info;
470673ff510953b65b844a58478aa434120f457c014Petr Machata
471673ff510953b65b844a58478aa434120f457c014Petr Machata	Elf_Scn *sec;
472673ff510953b65b844a58478aa434120f457c014Petr Machata	GElf_Shdr shdr;
473673ff510953b65b844a58478aa434120f457c014Petr Machata	if (elf_get_section_covering(lte, rel->r_offset, &sec, &shdr) < 0
474673ff510953b65b844a58478aa434120f457c014Petr Machata	    || sec == NULL)
475673ff510953b65b844a58478aa434120f457c014Petr Machata		return -1;
476673ff510953b65b844a58478aa434120f457c014Petr Machata
477673ff510953b65b844a58478aa434120f457c014Petr Machata	Elf_Data *data = elf_loaddata(sec, &shdr);
478673ff510953b65b844a58478aa434120f457c014Petr Machata	if (data == NULL)
479673ff510953b65b844a58478aa434120f457c014Petr Machata		return -1;
480673ff510953b65b844a58478aa434120f457c014Petr Machata
481673ff510953b65b844a58478aa434120f457c014Petr Machata	GElf_Xword offset = rel->r_offset - shdr.sh_addr - data->d_off;
482673ff510953b65b844a58478aa434120f457c014Petr Machata	uint64_t value;
483673ff510953b65b844a58478aa434120f457c014Petr Machata	if (lte->ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
484673ff510953b65b844a58478aa434120f457c014Petr Machata		uint32_t tmp;
485673ff510953b65b844a58478aa434120f457c014Petr Machata		if (elf_read_u32(data, offset, &tmp) < 0)
486673ff510953b65b844a58478aa434120f457c014Petr Machata			return -1;
487673ff510953b65b844a58478aa434120f457c014Petr Machata		value = tmp;
488673ff510953b65b844a58478aa434120f457c014Petr Machata	} else if (elf_read_u64(data, offset, &value) < 0) {
489673ff510953b65b844a58478aa434120f457c014Petr Machata		return -1;
490673ff510953b65b844a58478aa434120f457c014Petr Machata	}
491673ff510953b65b844a58478aa434120f457c014Petr Machata
492673ff510953b65b844a58478aa434120f457c014Petr Machata	rela->r_addend = value;
493673ff510953b65b844a58478aa434120f457c014Petr Machata	return 0;
494673ff510953b65b844a58478aa434120f457c014Petr Machata}
495673ff510953b65b844a58478aa434120f457c014Petr Machata
496673ff510953b65b844a58478aa434120f457c014Petr Machataint
4970ed5399f5cbb2b505a95bcac634c0ad5d7bbd6b8Petr Machataelf_read_relocs(struct ltelf *lte, Elf_Scn *scn, GElf_Shdr *shdr,
4980ed5399f5cbb2b505a95bcac634c0ad5d7bbd6b8Petr Machata		struct vect *rela_vec)
499673ff510953b65b844a58478aa434120f457c014Petr Machata{
500673ff510953b65b844a58478aa434120f457c014Petr Machata	if (vect_reserve_additional(rela_vec, lte->ehdr.e_shnum) < 0)
501673ff510953b65b844a58478aa434120f457c014Petr Machata		return -1;
502673ff510953b65b844a58478aa434120f457c014Petr Machata
503673ff510953b65b844a58478aa434120f457c014Petr Machata	Elf_Data *relplt = elf_loaddata(scn, shdr);
504673ff510953b65b844a58478aa434120f457c014Petr Machata	if (relplt == NULL) {
505673ff510953b65b844a58478aa434120f457c014Petr Machata		fprintf(stderr, "Couldn't load .rel*.plt data.\n");
506673ff510953b65b844a58478aa434120f457c014Petr Machata		return -1;
507673ff510953b65b844a58478aa434120f457c014Petr Machata	}
508673ff510953b65b844a58478aa434120f457c014Petr Machata
509673ff510953b65b844a58478aa434120f457c014Petr Machata	if ((shdr->sh_size % shdr->sh_entsize) != 0) {
510673ff510953b65b844a58478aa434120f457c014Petr Machata		fprintf(stderr, ".rel*.plt size (%" PRIx64 "d) not a multiple "
511673ff510953b65b844a58478aa434120f457c014Petr Machata			"of its sh_entsize (%" PRIx64 "d).\n",
512673ff510953b65b844a58478aa434120f457c014Petr Machata			shdr->sh_size, shdr->sh_entsize);
513673ff510953b65b844a58478aa434120f457c014Petr Machata		return -1;
514673ff510953b65b844a58478aa434120f457c014Petr Machata	}
515673ff510953b65b844a58478aa434120f457c014Petr Machata
516673ff510953b65b844a58478aa434120f457c014Petr Machata	GElf_Xword relplt_count = shdr->sh_size / shdr->sh_entsize;
517673ff510953b65b844a58478aa434120f457c014Petr Machata	GElf_Xword i;
518673ff510953b65b844a58478aa434120f457c014Petr Machata	for (i = 0; i < relplt_count; ++i) {
519673ff510953b65b844a58478aa434120f457c014Petr Machata		GElf_Rela rela;
520673ff510953b65b844a58478aa434120f457c014Petr Machata		if (relplt->d_type == ELF_T_REL) {
521673ff510953b65b844a58478aa434120f457c014Petr Machata			GElf_Rel rel;
522673ff510953b65b844a58478aa434120f457c014Petr Machata			if (gelf_getrel(relplt, i, &rel) == NULL
523673ff510953b65b844a58478aa434120f457c014Petr Machata			    || rel_to_rela(lte, &rel, &rela) < 0)
524673ff510953b65b844a58478aa434120f457c014Petr Machata				return -1;
525673ff510953b65b844a58478aa434120f457c014Petr Machata
526673ff510953b65b844a58478aa434120f457c014Petr Machata		} else if (gelf_getrela(relplt, i, &rela) == NULL) {
527673ff510953b65b844a58478aa434120f457c014Petr Machata			return -1;
528673ff510953b65b844a58478aa434120f457c014Petr Machata		}
529673ff510953b65b844a58478aa434120f457c014Petr Machata
530673ff510953b65b844a58478aa434120f457c014Petr Machata		if (VECT_PUSHBACK(rela_vec, &rela) < 0)
531673ff510953b65b844a58478aa434120f457c014Petr Machata			return -1;
532673ff510953b65b844a58478aa434120f457c014Petr Machata	}
533673ff510953b65b844a58478aa434120f457c014Petr Machata
534673ff510953b65b844a58478aa434120f457c014Petr Machata	return 0;
535673ff510953b65b844a58478aa434120f457c014Petr Machata}
536673ff510953b65b844a58478aa434120f457c014Petr Machata
5374f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machataint
5384f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machataelf_load_dynamic_entry(struct ltelf *lte, int tag, GElf_Addr *valuep)
5394f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata{
5404f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	Elf_Scn *scn;
5414f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	GElf_Shdr shdr;
5424f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
5434f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	    || scn == NULL) {
5444f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	fail:
5454f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata		fprintf(stderr, "Couldn't get SHT_DYNAMIC: %s\n",
5464f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata			elf_errmsg(-1));
5474f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata		return -1;
5484f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	}
5494f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata
5504f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	Elf_Data *data = elf_loaddata(scn, &shdr);
5514f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	if (data == NULL)
5524f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata		goto fail;
5534f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata
5544f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	size_t j;
5554f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
5564f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata		GElf_Dyn dyn;
5574f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata		if (gelf_getdyn(data, j, &dyn) == NULL)
5584f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata			goto fail;
5594f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata
5604f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata		if(dyn.d_tag == tag) {
5614f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata			*valuep = dyn.d_un.d_ptr;
5624f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata			return 0;
5634f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata		}
5644f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	}
5654f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata
5664f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata	return -1;
5674f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata}
5684f2f66e6abc7fedf3a5d04fab7cc00e5f82b37cfPetr Machata
569673ff510953b65b844a58478aa434120f457c014Petr Machatastatic int
570673ff510953b65b844a58478aa434120f457c014Petr Machataltelf_read_elf(struct ltelf *lte, const char *filename)
5712b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata{
57202bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	int i;
57302bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	GElf_Addr relplt_addr = 0;
5742b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	GElf_Addr soname_offset = 0;
575673ff510953b65b844a58478aa434120f457c014Petr Machata	GElf_Xword relplt_size = 0;
57602bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata
577673ff510953b65b844a58478aa434120f457c014Petr Machata	debug(DEBUG_FUNCTION, "ltelf_read_elf(filename=%s)", filename);
57802bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata	debug(1, "Reading ELF from %s...", filename);
57902bd9eca0b439b6950ab72ba64b67181e5bf0fbdPetr Machata
5802d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	for (i = 1; i < lte->ehdr.e_shnum; ++i) {
5812d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		Elf_Scn *scn;
5822d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		GElf_Shdr shdr;
5832d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		const char *name;
5842d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
5852d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		scn = elf_getscn(lte->elf, i);
586cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
587cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			fprintf(stderr,	"Couldn't get section #%d from"
588cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				" \"%s\": %s\n", i, filename, elf_errmsg(-1));
589cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			exit(EXIT_FAILURE);
590cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		}
5912d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
5922d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		name = elf_strptr(lte->elf, lte->ehdr.e_shstrndx, shdr.sh_name);
593cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		if (name == NULL) {
594cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			fprintf(stderr,	"Couldn't get name of section #%d from"
595cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				" \"%s\": %s\n", i, filename, elf_errmsg(-1));
596cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			exit(EXIT_FAILURE);
597cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		}
5982d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
5992d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		if (shdr.sh_type == SHT_SYMTAB) {
600cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			read_symbol_table(lte, filename,
601cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					  scn, &shdr, name, &lte->symtab,
602cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					  &lte->symtab_count, &lte->strtab);
6032d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
6042d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		} else if (shdr.sh_type == SHT_DYNSYM) {
605cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			read_symbol_table(lte, filename,
606cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					  scn, &shdr, name, &lte->dynsym,
607cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					  &lte->dynsym_count, &lte->dynstr);
6082d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
6092d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		} else if (shdr.sh_type == SHT_DYNAMIC) {
6102d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			Elf_Data *data;
6112d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			size_t j;
6122d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
613da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			lte->dyn_addr = shdr.sh_addr + lte->bias;
61487f4f58320226cd20d317f488c7e6a92a3efa2ddJoe Damato			lte->dyn_sz = shdr.sh_size;
61587f4f58320226cd20d317f488c7e6a92a3efa2ddJoe Damato
6162d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			data = elf_getdata(scn, NULL);
617cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			if (data == NULL || elf_getdata(scn, data) != NULL) {
618cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				fprintf(stderr, "Couldn't get .dynamic data"
619cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					" from \"%s\": %s\n",
620cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					filename, strerror(errno));
621cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				exit(EXIT_FAILURE);
622cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			}
6232d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
6242d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
6252d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				GElf_Dyn dyn;
6262d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
627cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				if (gelf_getdyn(data, j, &dyn) == NULL) {
628cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					fprintf(stderr, "Couldn't get .dynamic"
629cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata						" data from \"%s\": %s\n",
630cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata						filename, strerror(errno));
631cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					exit(EXIT_FAILURE);
632cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				}
6332d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				if (dyn.d_tag == DT_JMPREL)
6342d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand					relplt_addr = dyn.d_un.d_ptr;
6352d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				else if (dyn.d_tag == DT_PLTRELSZ)
636673ff510953b65b844a58478aa434120f457c014Petr Machata					relplt_size = dyn.d_un.d_val;
637e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata				else if (dyn.d_tag == DT_SONAME)
6382b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata					soname_offset = dyn.d_un.d_val;
6392d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			}
6402d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		} else if (shdr.sh_type == SHT_PROGBITS
6412d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			   || shdr.sh_type == SHT_NOBITS) {
6422d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			if (strcmp(name, ".plt") == 0) {
6432d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				lte->plt_addr = shdr.sh_addr;
6442d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				lte->plt_size = shdr.sh_size;
645e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata				lte->plt_data = elf_loaddata(scn, &shdr);
646e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata				if (lte->plt_data == NULL)
647e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata					fprintf(stderr,
648e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata						"Can't load .plt data\n");
64918c801c3f29081d9de517815df89bc1bbf8e2188Petr Machata				lte->plt_flags = shdr.sh_flags;
650b3f8fef12fccb0914b7b28725f42192c279d31c9Petr Machata			}
651b3f8fef12fccb0914b7b28725f42192c279d31c9Petr Machata#ifdef ARCH_SUPPORTS_OPD
652b3f8fef12fccb0914b7b28725f42192c279d31c9Petr Machata			else if (strcmp(name, ".opd") == 0) {
6533f1219f7803599df8556e7fc096a6a239f9a04fdPaul Gilliam				lte->opd_addr = (GElf_Addr *) (long) shdr.sh_addr;
6542d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				lte->opd_size = shdr.sh_size;
6552d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				lte->opd = elf_rawdata(scn, NULL);
6562d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			}
657b3f8fef12fccb0914b7b28725f42192c279d31c9Petr Machata#endif
6582d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		}
6599a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand	}
6609a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand
661cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	if (lte->dynsym == NULL || lte->dynstr == NULL) {
662cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "Couldn't find .dynsym or .dynstr in \"%s\"\n",
663cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			filename);
664cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		exit(EXIT_FAILURE);
665cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	}
6662d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
6672d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (!relplt_addr || !lte->plt_addr) {
6682d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		debug(1, "%s has no PLT relocations", filename);
669673ff510953b65b844a58478aa434120f457c014Petr Machata	} else if (relplt_size == 0) {
670fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata		debug(1, "%s has unknown PLT size", filename);
6712d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	} else {
6722d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		for (i = 1; i < lte->ehdr.e_shnum; ++i) {
6732d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			Elf_Scn *scn;
6742d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			GElf_Shdr shdr;
6752d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
6762d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			scn = elf_getscn(lte->elf, i);
677cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
678cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				fprintf(stderr, "Couldn't get section header"
679cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					" from \"%s\": %s\n",
680cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					filename, elf_errmsg(-1));
681cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				exit(EXIT_FAILURE);
682cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			}
6832d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			if (shdr.sh_addr == relplt_addr
684673ff510953b65b844a58478aa434120f457c014Petr Machata			    && shdr.sh_size == relplt_size) {
6850ed5399f5cbb2b505a95bcac634c0ad5d7bbd6b8Petr Machata				if (elf_read_relocs(lte, scn, &shdr,
6860ed5399f5cbb2b505a95bcac634c0ad5d7bbd6b8Petr Machata						    &lte->plt_relocs) < 0) {
687cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					fprintf(stderr, "Couldn't get .rel*.plt"
688cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata						" data from \"%s\": %s\n",
689cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata						filename, elf_errmsg(-1));
690cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata					exit(EXIT_FAILURE);
691cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				}
6922d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				break;
6932d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			}
6942d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		}
6952d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
696cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		if (i == lte->ehdr.e_shnum) {
697cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			fprintf(stderr,
698cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				"Couldn't find .rel*.plt section in \"%s\"\n",
699cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				filename);
700cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			exit(EXIT_FAILURE);
701cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		}
7022d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	}
703673ff510953b65b844a58478aa434120f457c014Petr Machata	debug(1, "%s %zd PLT relocations", filename,
704673ff510953b65b844a58478aa434120f457c014Petr Machata	      vect_size(&lte->plt_relocs));
7052b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata
7062b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	if (soname_offset != 0)
7072b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata		lte->soname = lte->dynstr + soname_offset;
7082b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata
7091974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata	return 0;
7101cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes}
7111cd999a32728f41208dc30f38a125d7bb7063625Juan Cespedes
71235b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias#ifndef ARCH_HAVE_GET_SYMINFO
71335b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesiasint
71435b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesiasarch_get_sym_info(struct ltelf *lte, const char *filename,
71535b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias		  size_t sym_index, GElf_Rela *rela, GElf_Sym *sym)
71635b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias{
717673ff510953b65b844a58478aa434120f457c014Petr Machata	return gelf_getsym(lte->dynsym,
718673ff510953b65b844a58478aa434120f457c014Petr Machata			   ELF64_R_SYM(rela->r_info), sym) != NULL ? 0 : -1;
71935b5be786822d87f694dab8b267f9c6df8bfb278Edgar E. Iglesias}
720b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias#endif
721b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias
72297d13666cd84589135ba593fa43a800d098026d0Petr Machataint
72397d13666cd84589135ba593fa43a800d098026d0Petr Machatadefault_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
72497d13666cd84589135ba593fa43a800d098026d0Petr Machata			  const char *a_name, GElf_Rela *rela, size_t ndx,
72597d13666cd84589135ba593fa43a800d098026d0Petr Machata			  struct library_symbol **ret)
72697d13666cd84589135ba593fa43a800d098026d0Petr Machata{
72797d13666cd84589135ba593fa43a800d098026d0Petr Machata	char *name = strdup(a_name);
72897d13666cd84589135ba593fa43a800d098026d0Petr Machata	if (name == NULL) {
72997d13666cd84589135ba593fa43a800d098026d0Petr Machata	fail_message:
73097d13666cd84589135ba593fa43a800d098026d0Petr Machata		fprintf(stderr, "Couldn't create symbol for PLT entry: %s\n",
73197d13666cd84589135ba593fa43a800d098026d0Petr Machata			strerror(errno));
73297d13666cd84589135ba593fa43a800d098026d0Petr Machata	fail:
73397d13666cd84589135ba593fa43a800d098026d0Petr Machata		free(name);
73497d13666cd84589135ba593fa43a800d098026d0Petr Machata		return -1;
73597d13666cd84589135ba593fa43a800d098026d0Petr Machata	}
73697d13666cd84589135ba593fa43a800d098026d0Petr Machata
73797d13666cd84589135ba593fa43a800d098026d0Petr Machata	GElf_Addr addr = arch_plt_sym_val(lte, ndx, rela);
73897d13666cd84589135ba593fa43a800d098026d0Petr Machata
73997d13666cd84589135ba593fa43a800d098026d0Petr Machata	struct library_symbol *libsym = malloc(sizeof(*libsym));
74097d13666cd84589135ba593fa43a800d098026d0Petr Machata	if (libsym == NULL)
74197d13666cd84589135ba593fa43a800d098026d0Petr Machata		goto fail_message;
74297d13666cd84589135ba593fa43a800d098026d0Petr Machata
74397d13666cd84589135ba593fa43a800d098026d0Petr Machata	/* XXX The double cast should be removed when
74497d13666cd84589135ba593fa43a800d098026d0Petr Machata	 * arch_addr_t becomes integral type.  */
74597d13666cd84589135ba593fa43a800d098026d0Petr Machata	arch_addr_t taddr = (arch_addr_t)
74697d13666cd84589135ba593fa43a800d098026d0Petr Machata		(uintptr_t)(addr + lte->bias);
74797d13666cd84589135ba593fa43a800d098026d0Petr Machata
74897d13666cd84589135ba593fa43a800d098026d0Petr Machata	if (library_symbol_init(libsym, taddr, name, 1, LS_TOPLT_EXEC) < 0) {
74997d13666cd84589135ba593fa43a800d098026d0Petr Machata		free(libsym);
75097d13666cd84589135ba593fa43a800d098026d0Petr Machata		goto fail;
75197d13666cd84589135ba593fa43a800d098026d0Petr Machata	}
75297d13666cd84589135ba593fa43a800d098026d0Petr Machata
75397d13666cd84589135ba593fa43a800d098026d0Petr Machata	libsym->next = *ret;
75497d13666cd84589135ba593fa43a800d098026d0Petr Machata	*ret = libsym;
75597d13666cd84589135ba593fa43a800d098026d0Petr Machata	return 0;
75697d13666cd84589135ba593fa43a800d098026d0Petr Machata}
75797d13666cd84589135ba593fa43a800d098026d0Petr Machata
75897d13666cd84589135ba593fa43a800d098026d0Petr Machataint
75997d13666cd84589135ba593fa43a800d098026d0Petr Machataelf_add_plt_entry(struct process *proc, struct ltelf *lte,
76097d13666cd84589135ba593fa43a800d098026d0Petr Machata		  const char *name, GElf_Rela *rela, size_t idx,
76197d13666cd84589135ba593fa43a800d098026d0Petr Machata		  struct library_symbol **ret)
76297d13666cd84589135ba593fa43a800d098026d0Petr Machata{
76397d13666cd84589135ba593fa43a800d098026d0Petr Machata	enum plt_status plts
76497d13666cd84589135ba593fa43a800d098026d0Petr Machata		= arch_elf_add_plt_entry(proc, lte, name, rela, idx, ret);
76597d13666cd84589135ba593fa43a800d098026d0Petr Machata
76697d13666cd84589135ba593fa43a800d098026d0Petr Machata	if (plts == PLT_DEFAULT)
76797d13666cd84589135ba593fa43a800d098026d0Petr Machata		plts = os_elf_add_plt_entry(proc, lte, name, rela, idx, ret);
76897d13666cd84589135ba593fa43a800d098026d0Petr Machata
76997d13666cd84589135ba593fa43a800d098026d0Petr Machata	switch (plts) {
77097d13666cd84589135ba593fa43a800d098026d0Petr Machata	case PLT_DEFAULT:
77197d13666cd84589135ba593fa43a800d098026d0Petr Machata		return default_elf_add_plt_entry(proc, lte, name,
77297d13666cd84589135ba593fa43a800d098026d0Petr Machata						 rela, idx, ret);
77397d13666cd84589135ba593fa43a800d098026d0Petr Machata	case PLT_FAIL:
77497d13666cd84589135ba593fa43a800d098026d0Petr Machata		return -1;
77597d13666cd84589135ba593fa43a800d098026d0Petr Machata	case PLT_OK:
77697d13666cd84589135ba593fa43a800d098026d0Petr Machata		return 0;
77797d13666cd84589135ba593fa43a800d098026d0Petr Machata	}
77897d13666cd84589135ba593fa43a800d098026d0Petr Machata
77997d13666cd84589135ba593fa43a800d098026d0Petr Machata	assert(! "Invalid return from X_elf_add_plt_entry!");
78097d13666cd84589135ba593fa43a800d098026d0Petr Machata	abort();
78197d13666cd84589135ba593fa43a800d098026d0Petr Machata}
78297d13666cd84589135ba593fa43a800d098026d0Petr Machata
783e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machatastatic void
784e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machatamark_chain_latent(struct library_symbol *libsym)
785e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata{
786e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata	for (; libsym != NULL; libsym = libsym->next) {
787e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata		debug(DEBUG_FUNCTION, "marking %s latent", libsym->name);
788e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata		libsym->latent = 1;
789e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata	}
790e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata}
791e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata
792b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machatastatic void
793b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machatafilter_symbol_chain(struct filter *filter,
794b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata		    struct library_symbol **libsymp, struct library *lib)
795b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata{
796b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata	assert(libsymp != NULL);
797b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata	struct library_symbol **ptr = libsymp;
798b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata	while (*ptr != NULL) {
799b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata		if (filter_matches_symbol(filter, (*ptr)->name, lib)) {
800b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata			ptr = &(*ptr)->next;
801b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata		} else {
802b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata			struct library_symbol *sym = *ptr;
803b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata			*ptr = (*ptr)->next;
804b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata			library_symbol_destroy(sym);
805b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata			free(sym);
806b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata		}
807b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata	}
808b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata}
809b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata
810b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machatastatic int
811929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatapopulate_plt(struct process *proc, const char *filename,
81297d13666cd84589135ba593fa43a800d098026d0Petr Machata	     struct ltelf *lte, struct library *lib)
813b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata{
81497d13666cd84589135ba593fa43a800d098026d0Petr Machata	const bool latent_plts = options.export_filter != NULL;
81597d13666cd84589135ba593fa43a800d098026d0Petr Machata	const size_t count = vect_size(&lte->plt_relocs);
81697d13666cd84589135ba593fa43a800d098026d0Petr Machata
817b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	size_t i;
818673ff510953b65b844a58478aa434120f457c014Petr Machata	for (i = 0; i < count; ++i) {
819673ff510953b65b844a58478aa434120f457c014Petr Machata		GElf_Rela *rela = VECT_ELEMENT(&lte->plt_relocs, GElf_Rela, i);
820b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		GElf_Sym sym;
821b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
822673ff510953b65b844a58478aa434120f457c014Petr Machata		switch (arch_get_sym_info(lte, filename, i, rela, &sym)) {
823552d75e2a226782cc9ecf966e6e343af8f51031fPetr Machata		default:
824552d75e2a226782cc9ecf966e6e343af8f51031fPetr Machata			fprintf(stderr,
825552d75e2a226782cc9ecf966e6e343af8f51031fPetr Machata				"Couldn't get relocation for symbol #%zd"
826552d75e2a226782cc9ecf966e6e343af8f51031fPetr Machata				" from \"%s\": %s\n",
827552d75e2a226782cc9ecf966e6e343af8f51031fPetr Machata				i, filename, elf_errmsg(-1));
828552d75e2a226782cc9ecf966e6e343af8f51031fPetr Machata			/* Fall through.  */
829552d75e2a226782cc9ecf966e6e343af8f51031fPetr Machata		case 1:
830b5920d12ceb3dec3d359d8b2972fd22a30c72a66Edgar E. Iglesias			continue; /* Skip this entry.  */
831552d75e2a226782cc9ecf966e6e343af8f51031fPetr Machata		case 0:
832552d75e2a226782cc9ecf966e6e343af8f51031fPetr Machata			break;
833552d75e2a226782cc9ecf966e6e343af8f51031fPetr Machata		}
834b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
835b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		char const *name = lte->dynstr + sym.st_name;
836e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata		int matched = filter_matches_symbol(options.plt_filter,
837e80caced59a9f0cdd7b70a5ad3b0e4103a477f2bPetr Machata						    name, lib);
838b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
839218c5ff26841f5bbd188c42ccbd67422a7a20556Petr Machata		struct library_symbol *libsym = NULL;
84097d13666cd84589135ba593fa43a800d098026d0Petr Machata		if (elf_add_plt_entry(proc, lte, name, rela, i, &libsym) < 0)
841a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			return -1;
842b420a226cd2fc5d6028adcaf236c512a1f1fb437Petr Machata
84397d13666cd84589135ba593fa43a800d098026d0Petr Machata		/* If we didn't match the PLT entry, filter the chain
84497d13666cd84589135ba593fa43a800d098026d0Petr Machata		 * to only include the matching symbols (but include
84597d13666cd84589135ba593fa43a800d098026d0Petr Machata		 * all if we are adding latent symbols) to allow
84697d13666cd84589135ba593fa43a800d098026d0Petr Machata		 * backends to override the PLT symbol's name.  */
84797d13666cd84589135ba593fa43a800d098026d0Petr Machata
84897d13666cd84589135ba593fa43a800d098026d0Petr Machata		if (! matched && ! latent_plts)
84997d13666cd84589135ba593fa43a800d098026d0Petr Machata			filter_symbol_chain(options.plt_filter, &libsym, lib);
85097d13666cd84589135ba593fa43a800d098026d0Petr Machata
85197d13666cd84589135ba593fa43a800d098026d0Petr Machata		if (libsym != NULL) {
85297d13666cd84589135ba593fa43a800d098026d0Petr Machata			/* If we are adding those symbols just for
85397d13666cd84589135ba593fa43a800d098026d0Petr Machata			 * tracing exports, mark them all latent.  */
85497d13666cd84589135ba593fa43a800d098026d0Petr Machata			if (! matched && latent_plts)
85597d13666cd84589135ba593fa43a800d098026d0Petr Machata				mark_chain_latent(libsym);
85697d13666cd84589135ba593fa43a800d098026d0Petr Machata			library_add_symbol(lib, libsym);
857b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		}
858b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	}
859b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	return 0;
860b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata}
861b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
86297d13666cd84589135ba593fa43a800d098026d0Petr Machatastatic void
86397d13666cd84589135ba593fa43a800d098026d0Petr Machatadelete_symbol_chain(struct library_symbol *libsym)
86497d13666cd84589135ba593fa43a800d098026d0Petr Machata{
86597d13666cd84589135ba593fa43a800d098026d0Petr Machata	while (libsym != NULL) {
86697d13666cd84589135ba593fa43a800d098026d0Petr Machata		struct library_symbol *tmp = libsym->next;
86797d13666cd84589135ba593fa43a800d098026d0Petr Machata		library_symbol_destroy(libsym);
86897d13666cd84589135ba593fa43a800d098026d0Petr Machata		free(libsym);
86997d13666cd84589135ba593fa43a800d098026d0Petr Machata		libsym = tmp;
87097d13666cd84589135ba593fa43a800d098026d0Petr Machata	}
87197d13666cd84589135ba593fa43a800d098026d0Petr Machata}
87297d13666cd84589135ba593fa43a800d098026d0Petr Machata
873157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata/* When -x rules result in request to trace several aliases, we only
874157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * want to add such symbol once.  The only way that those symbols
875157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * differ in is their name, e.g. in glibc you have __GI___libc_free,
876157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * __cfree, __free, __libc_free, cfree and free all defined on the
877157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * same address.  So instead we keep this unique symbol struct for
878157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * each address, and replace name in libsym with a shorter variant if
879157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata * we find it.  */
880157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machatastruct unique_symbol {
881bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	arch_addr_t addr;
882157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	struct library_symbol *libsym;
883157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata};
884157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
885157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machatastatic int
886157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machataunique_symbol_cmp(const void *key, const void *val)
887157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata{
888157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	const struct unique_symbol *sym_key = key;
889157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	const struct unique_symbol *sym_val = val;
890157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	return sym_key->addr != sym_val->addr;
891157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata}
892157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
89310bd7a99d384f34c9c510828b722f29a8dc02393Petr Machatastatic enum callback_status
89410bd7a99d384f34c9c510828b722f29a8dc02393Petr Machatasymbol_with_address(struct library_symbol *sym, void *addrptr)
89510bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata{
89610bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata	return sym->enter_addr == *(arch_addr_t *)addrptr
89710bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		? CBS_STOP : CBS_CONT;
89810bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata}
89910bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata
900da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machatastatic int
901929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatapopulate_this_symtab(struct process *proc, const char *filename,
902da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		     struct ltelf *lte, struct library *lib,
9031187af0639449c3c6da03d827f93d2c2181a06f5Petr Machata		     Elf_Data *symtab, const char *strtab, size_t count,
904013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		     struct library_exported_name **names)
905da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata{
906013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	/* If a valid NAMES is passed, we pass in *NAMES a list of
907013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * symbol names that this library exports.  */
908013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	if (names != NULL)
909013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		*names = NULL;
910013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
911157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	/* Using sorted array would be arguably better, but this
912157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	 * should be well enough for the number of symbols that we
913157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	 * typically deal with.  */
914157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	size_t num_symbols = 0;
9151187af0639449c3c6da03d827f93d2c2181a06f5Petr Machata	struct unique_symbol *symbols = malloc(sizeof(*symbols) * count);
916157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	if (symbols == NULL) {
917cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata		fprintf(stderr, "couldn't insert symbols for -x: %s\n",
918cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			strerror(errno));
919157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata		return -1;
920157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	}
921157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
92240cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata	GElf_Word secflags[lte->ehdr.e_shnum];
923da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata	size_t i;
92440cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata	for (i = 1; i < lte->ehdr.e_shnum; ++i) {
92540cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		Elf_Scn *scn = elf_getscn(lte->elf, i);
92640cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		GElf_Shdr shdr;
927aeb549016d8f536ca007ff0943f9583389dff121Petr Machata		if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL)
928aeb549016d8f536ca007ff0943f9583389dff121Petr Machata			secflags[i] = 0;
929aeb549016d8f536ca007ff0943f9583389dff121Petr Machata		else
930aeb549016d8f536ca007ff0943f9583389dff121Petr Machata			secflags[i] = shdr.sh_flags;
93140cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata	}
93240cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata
9331187af0639449c3c6da03d827f93d2c2181a06f5Petr Machata	for (i = 0; i < count; ++i) {
934da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		GElf_Sym sym;
935074f68fb8f57f93de3d94552a855b296b7a25906Petr Machata		if (gelf_getsym(symtab, i, &sym) == NULL) {
936cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			fprintf(stderr,
937cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				"couldn't get symbol #%zd from %s: %s\n",
938cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				i, filename, elf_errmsg(-1));
939da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata			continue;
940da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		}
941da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
942a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		if (sym.st_value == 0 || sym.st_shndx == STN_UNDEF
943a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		    /* Also ignore any special values besides direct
944a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		     * section references.  */
945a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		    || sym.st_shndx >= lte->ehdr.e_shnum)
9464de6b6b5ca9f7b3bb930663c43a8bf0f322e2bedPetr Machata			continue;
9474de6b6b5ca9f7b3bb930663c43a8bf0f322e2bedPetr Machata
948013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		/* Find symbol name and snip version.  */
9492bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		const char *orig_name = strtab + sym.st_name;
9502bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		const char *version = strchr(orig_name, '@');
9512bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		size_t len = version != NULL ? (assert(version > orig_name),
9522bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata						(size_t)(version - orig_name))
9532bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata			: strlen(orig_name);
9542bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		char name[len + 1];
9552bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		memcpy(name, orig_name, len);
9562bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata		name[len] = 0;
9572bbeac4df26c6ecb7793fb2e764195cba88471faPetr Machata
958013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		/* If we are interested in exports, store this name.  */
959013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		if (names != NULL) {
960a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			struct library_exported_name *export
961a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				= malloc(sizeof *export);
962a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			char *name_copy = strdup(name);
963013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
964a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			if (name_copy == NULL || export == NULL) {
965013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				free(name_copy);
966a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				free(export);
967013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				fprintf(stderr, "Couldn't store symbol %s.  "
968013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata					"Tracing may be incomplete.\n", name);
969013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			} else {
970013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				export->name = name_copy;
971013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				export->own_name = 1;
972013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				export->next = *names;
973013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				*names = export;
974013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			}
975013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		}
976013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
977013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		/* If the symbol is not matched, skip it.  We already
978013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		 * stored it to export list above.  */
979da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		if (!filter_matches_symbol(options.static_filter, name, lib))
980da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata			continue;
981da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
982bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata		arch_addr_t addr = (arch_addr_t)
983ea8eb9a606096fd072abe104b4239f67883ad39aPetr Machata			(uintptr_t)(sym.st_value + lte->bias);
984bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata		arch_addr_t naddr;
98540cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata
98640cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		/* On arches that support OPD, the value of typical
98740cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		 * function symbol will be a pointer to .opd, but some
98840cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		 * will point directly to .text.  We don't want to
98940cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		 * translate those.  */
99040cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata		if (secflags[sym.st_shndx] & SHF_EXECINSTR) {
99140cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata			naddr = addr;
992b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machata		} else if (arch_translate_address(lte, addr, &naddr) < 0) {
993cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata			fprintf(stderr,
994cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				"couldn't translate address of %s@%s: %s\n",
995cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata				name, lib->soname, strerror(errno));
996da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata			continue;
997da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		}
99840cc53b8a944aabfd42e64bf71815252652d7f77Petr Machata
999a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		char *full_name = strdup(name);
1000a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		if (full_name == NULL) {
1001a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			fprintf(stderr, "couldn't copy name of %s@%s: %s\n",
1002a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				name, lib->soname, strerror(errno));
1003a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			continue;
10043840f68c3d212d17444efaf1c8557f420622fd13Petr Machata		}
10054de6b6b5ca9f7b3bb930663c43a8bf0f322e2bedPetr Machata
1006a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		struct library_symbol *libsym = NULL;
100797d13666cd84589135ba593fa43a800d098026d0Petr Machata		enum plt_status plts
100897d13666cd84589135ba593fa43a800d098026d0Petr Machata			= arch_elf_add_func_entry(proc, lte, &sym,
100997d13666cd84589135ba593fa43a800d098026d0Petr Machata						  naddr, full_name, &libsym);
101097d13666cd84589135ba593fa43a800d098026d0Petr Machata		if (plts == PLT_DEFAULT)
101197d13666cd84589135ba593fa43a800d098026d0Petr Machata			plts = os_elf_add_func_entry(proc, lte, &sym,
101297d13666cd84589135ba593fa43a800d098026d0Petr Machata						     naddr, full_name, &libsym);
101397d13666cd84589135ba593fa43a800d098026d0Petr Machata
101497d13666cd84589135ba593fa43a800d098026d0Petr Machata		switch (plts) {
1015a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		case PLT_DEFAULT:;
1016a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			/* Put the default symbol to the chain.  */
1017a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			struct library_symbol *tmp = malloc(sizeof *tmp);
1018a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			if (tmp == NULL
1019a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			    || library_symbol_init(tmp, naddr, full_name, 1,
1020013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata						   LS_TOPLT_NONE) < 0) {
1021a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				free(tmp);
1022a186b0e5c469156b9af66e88dca12d208418195cPetr Machata
1023a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				/* Either add the whole bunch, or none
1024a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				 * of it.  Note that for PLT_FAIL we
1025a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				 * don't do this--it's the callee's
1026a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				 * job to clean up after itself before
1027a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				 * it bails out.  */
1028a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				delete_symbol_chain(libsym);
1029a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				libsym = NULL;
1030a186b0e5c469156b9af66e88dca12d208418195cPetr Machata
1031a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		case PLT_FAIL:
1032a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				fprintf(stderr, "Couldn't add symbol %s@%s "
1033a186b0e5c469156b9af66e88dca12d208418195cPetr Machata					"for tracing.\n", name, lib->soname);
1034a186b0e5c469156b9af66e88dca12d208418195cPetr Machata
1035a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				break;
1036157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata			}
1037157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
1038a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			full_name = NULL;
1039a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			tmp->next = libsym;
1040a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			libsym = tmp;
1041a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			break;
1042da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
1043a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		case PLT_OK:
1044a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			break;
1045a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		}
1046a186b0e5c469156b9af66e88dca12d208418195cPetr Machata
1047a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		free(full_name);
1048a186b0e5c469156b9af66e88dca12d208418195cPetr Machata
1049a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		struct library_symbol *tmp;
1050a186b0e5c469156b9af66e88dca12d208418195cPetr Machata		for (tmp = libsym; tmp != NULL; ) {
1051a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			/* Look whether we already have a symbol for
1052a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			 * this address.  If not, add this one.  If
1053a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			 * yes, look if we should pick the new symbol
1054a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			 * name.  */
1055a186b0e5c469156b9af66e88dca12d208418195cPetr Machata
1056a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			struct unique_symbol key = { tmp->enter_addr, NULL };
1057a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			struct unique_symbol *unique
1058a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				= lsearch(&key, symbols, &num_symbols,
1059a186b0e5c469156b9af66e88dca12d208418195cPetr Machata					  sizeof *symbols, &unique_symbol_cmp);
1060a186b0e5c469156b9af66e88dca12d208418195cPetr Machata
1061a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			if (unique->libsym == NULL) {
1062a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				unique->libsym = tmp;
1063a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				unique->addr = tmp->enter_addr;
1064a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				tmp = tmp->next;
106597d13666cd84589135ba593fa43a800d098026d0Petr Machata				unique->libsym->next = NULL;
1066a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			} else {
1067a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				if (strlen(tmp->name)
1068a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				    < strlen(unique->libsym->name)) {
1069a186b0e5c469156b9af66e88dca12d208418195cPetr Machata					library_symbol_set_name
1070a186b0e5c469156b9af66e88dca12d208418195cPetr Machata						(unique->libsym, tmp->name, 1);
1071a186b0e5c469156b9af66e88dca12d208418195cPetr Machata					tmp->name = NULL;
1072a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				}
1073a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				struct library_symbol *next = tmp->next;
1074a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				library_symbol_destroy(tmp);
1075a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				free(tmp);
1076a186b0e5c469156b9af66e88dca12d208418195cPetr Machata				tmp = next;
1077a186b0e5c469156b9af66e88dca12d208418195cPetr Machata			}
1078157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata		}
1079da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata	}
1080157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
108110bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata	/* Now we do the union of this set of unique symbols with
108210bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata	 * what's already in the library.  */
1083157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	for (i = 0; i < num_symbols; ++i) {
108410bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		struct library_symbol *this_sym = symbols[i].libsym;
108510bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		assert(this_sym != NULL);
108610bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		struct library_symbol *other
108710bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata			= library_each_symbol(lib, NULL, symbol_with_address,
108810bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata					      &this_sym->enter_addr);
108910bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		if (other != NULL) {
109010bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata			library_symbol_destroy(this_sym);
109110bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata			free(this_sym);
109210bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata			symbols[i].libsym = NULL;
109310bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		}
1094157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata	}
1095157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
109610bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata	for (i = 0; i < num_symbols; ++i)
109710bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata		if (symbols[i].libsym != NULL)
109810bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata			library_add_symbol(lib, symbols[i].libsym);
1099157cc4d6ee93f35e3aa65edcf57f369ae4e4677cPetr Machata
110010bd7a99d384f34c9c510828b722f29a8dc02393Petr Machata	free(symbols);
1101da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata	return 0;
1102da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata}
1103da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
1104da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machatastatic int
1105929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatapopulate_symtab(struct process *proc, const char *filename,
1106013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		struct ltelf *lte, struct library *lib,
1107013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		int symtabs, int exports)
1108da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata{
1109013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	int status;
1110013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	if (symtabs && lte->symtab != NULL && lte->strtab != NULL
1111013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	    && (status = populate_this_symtab(proc, filename, lte, lib,
1112013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata					      lte->symtab, lte->strtab,
1113013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata					      lte->symtab_count, NULL)) < 0)
1114013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		return status;
1115013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
1116013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	/* Check whether we want to trace symbols implemented by this
1117013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * library (-l).  */
1118013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	struct library_exported_name **names = NULL;
1119013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	if (exports) {
1120013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		debug(DEBUG_FUNCTION, "-l matches %s", lib->soname);
1121013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata		names = &lib->exported_names;
1122013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	}
1123013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
1124013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	return populate_this_symtab(proc, filename, lte, lib,
1125013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				    lte->dynsym, lte->dynstr,
1126013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata				    lte->dynsym_count, names);
1127da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata}
1128da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
1129da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machatastatic int
1130929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataread_module(struct library *lib, struct process *proc,
1131da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	    const char *filename, GElf_Addr bias, int main)
1132e84fa00bdabf20f57d1d02d159aa3fcab4e549fePetr Machata{
1133673ff510953b65b844a58478aa434120f457c014Petr Machata	struct ltelf lte;
1134673ff510953b65b844a58478aa434120f457c014Petr Machata	if (ltelf_init(&lte, filename) < 0)
1135da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		return -1;
1136da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
11371c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	/* XXX When we abstract ABI into a module, this should instead
11381c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 * become something like
11391c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 *
11401c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 *    proc->abi = arch_get_abi(lte.ehdr);
11411c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 *
1142673ff510953b65b844a58478aa434120f457c014Petr Machata	 * The code in ltelf_init needs to be replaced by this logic.
1143673ff510953b65b844a58478aa434120f457c014Petr Machata	 * Be warned that libltrace.c calls ltelf_init as well to
11441c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 * determine whether ABI is supported.  This is to get
11451c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 * reasonable error messages when trying to run 64-bit binary
11461c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	 * with 32-bit ltrace.  It is desirable to preserve this.  */
11471c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	proc->e_machine = lte.ehdr.e_machine;
11481c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	proc->e_class = lte.ehdr.e_ident[EI_CLASS];
11491c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	get_arch_dep(proc);
11501c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata
1151da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	/* Find out the base address.  For PIE main binaries we look
1152da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	 * into auxv, otherwise we scan phdrs.  */
1153da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	if (main && lte.ehdr.e_type == ET_DYN) {
1154da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		arch_addr_t entry;
1155da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		if (process_get_entry(proc, &entry, NULL) < 0) {
1156da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			fprintf(stderr, "Couldn't find entry of PIE %s\n",
1157da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata				filename);
1158673ff510953b65b844a58478aa434120f457c014Petr Machata		fail:
1159673ff510953b65b844a58478aa434120f457c014Petr Machata			ltelf_destroy(&lte);
1160da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			return -1;
1161da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		}
1162b024ca33e3734592a67e41414c2dc02978218501Petr Machata		/* XXX The double cast should be removed when
1163b024ca33e3734592a67e41414c2dc02978218501Petr Machata		 * arch_addr_t becomes integral type.  */
1164b024ca33e3734592a67e41414c2dc02978218501Petr Machata		lte.entry_addr = (GElf_Addr)(uintptr_t)entry;
1165b024ca33e3734592a67e41414c2dc02978218501Petr Machata		lte.bias = (GElf_Addr)(uintptr_t)entry - lte.ehdr.e_entry;
1166da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
1167da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	} else {
1168da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		GElf_Phdr phdr;
1169da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		size_t i;
1170da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		for (i = 0; gelf_getphdr (lte.elf, i, &phdr) != NULL; ++i) {
1171da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			if (phdr.p_type == PT_LOAD) {
1172da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata				lte.base_addr = phdr.p_vaddr + bias;
1173da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata				break;
1174da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			}
1175da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		}
1176da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
1177da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		lte.bias = bias;
1178da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		lte.entry_addr = lte.ehdr.e_entry + lte.bias;
1179da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
1180da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		if (lte.base_addr == 0) {
1181da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata			fprintf(stderr,
1182da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata				"Couldn't determine base address of %s\n",
1183da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata				filename);
1184673ff510953b65b844a58478aa434120f457c014Petr Machata			goto fail;
1185da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		}
1186da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	}
1187da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
1188673ff510953b65b844a58478aa434120f457c014Petr Machata	if (ltelf_read_elf(&lte, filename) < 0)
1189673ff510953b65b844a58478aa434120f457c014Petr Machata		goto fail;
1190da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
1191e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machata	if (arch_elf_init(&lte, lib) < 0) {
1192e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machata		fprintf(stderr, "Backend initialization failed.\n");
1193673ff510953b65b844a58478aa434120f457c014Petr Machata		goto fail;
1194e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machata	}
1195e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machata
1196fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	if (lib == NULL)
1197fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		goto fail;
1198fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata
1199fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	/* Note that we set soname and pathname as soon as they are
1200fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * allocated, so in case of further errors, this get released
1201f0d248aab596acd802668990793413180bb21f79Petr Machata	 * when LIB is released, which should happen in the caller
1202f0d248aab596acd802668990793413180bb21f79Petr Machata	 * when we return error.  */
1203fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata
1204fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	if (lib->pathname == NULL) {
1205fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		char *pathname = strdup(filename);
1206fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		if (pathname == NULL)
1207fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata			goto fail;
1208f13afd562dfbf9aa563177bfbbd1d9fc8e3cf2a3Petr Machata		library_set_pathname(lib, pathname, 1);
1209f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato	}
1210f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato
12110b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	if (lte.soname != NULL) {
1212fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		char *soname = strdup(lte.soname);
1213fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		if (soname == NULL)
1214fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata			goto fail;
1215fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		library_set_soname(lib, soname, 1);
12160b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	} else {
1217aafb00b7d7751049b99cac3953b5021e4f474ac4Petr Machata		const char *soname = rindex(lib->pathname, '/');
1218aafb00b7d7751049b99cac3953b5021e4f474ac4Petr Machata		if (soname != NULL)
1219aafb00b7d7751049b99cac3953b5021e4f474ac4Petr Machata			soname += 1;
1220aafb00b7d7751049b99cac3953b5021e4f474ac4Petr Machata		else
1221fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata			soname = lib->pathname;
1222fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata		library_set_soname(lib, soname, 0);
12230b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	}
1224fa2aefc32eb4196966a14d1e7def931652f40d46Joe Damato
1225ea8eb9a606096fd072abe104b4239f67883ad39aPetr Machata	/* XXX The double cast should be removed when
1226bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	 * arch_addr_t becomes integral type.  */
1227bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	arch_addr_t entry = (arch_addr_t)(uintptr_t)lte.entry_addr;
1228b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machata	if (arch_translate_address(&lte, entry, &entry) < 0)
1229b120fdfda45e49d082ab2aa5caadf030f50cb4edPetr Machata		goto fail;
1230b120fdfda45e49d082ab2aa5caadf030f50cb4edPetr Machata
1231ea8eb9a606096fd072abe104b4239f67883ad39aPetr Machata	/* XXX The double cast should be removed when
1232bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	 * arch_addr_t becomes integral type.  */
1233bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	lib->base = (arch_addr_t)(uintptr_t)lte.base_addr;
1234b120fdfda45e49d082ab2aa5caadf030f50cb4edPetr Machata	lib->entry = entry;
1235ea8eb9a606096fd072abe104b4239f67883ad39aPetr Machata	/* XXX The double cast should be removed when
1236bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	 * arch_addr_t becomes integral type.  */
1237bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	lib->dyn_addr = (arch_addr_t)(uintptr_t)lte.dyn_addr;
1238fe1c171b8988a4e9a882b11291faf9d3fa09e944Petr Machata
1239013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	/* There are two reasons that we need to inspect symbol tables
1240013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * or populate PLT entries.  Either the user requested
1241013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * corresponding tracing features (respectively -x and -e), or
1242013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * they requested tracing exported symbols (-l).
1243013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 *
1244013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * In the latter case we need to keep even those PLT slots
1245013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * that are not requested by -e (but we keep them latent).  We
1246013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * also need to inspect .dynsym to find what exports this
1247013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * library provide, to turn on existing latent PLT
1248013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	 * entries.  */
1249013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata
1250013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	int plts = filter_matches_library(options.plt_filter, lib);
1251013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	if ((plts || options.export_filter != NULL)
125297d13666cd84589135ba593fa43a800d098026d0Petr Machata	    && populate_plt(proc, filename, &lte, lib) < 0)
1253b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		goto fail;
12542d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
1255013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	int exports = filter_matches_library(options.export_filter, lib);
1256013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	int symtabs = filter_matches_library(options.static_filter, lib);
1257013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	if ((symtabs || exports)
1258013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata	    && populate_symtab(proc, filename, &lte, lib,
1259013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata			       symtabs, exports) < 0)
1260da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata		goto fail;
1261da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata
1262673ff510953b65b844a58478aa434120f457c014Petr Machata	arch_elf_destroy(&lte);
1263673ff510953b65b844a58478aa434120f457c014Petr Machata	ltelf_destroy(&lte);
1264673ff510953b65b844a58478aa434120f457c014Petr Machata	return 0;
12652b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata}
12662d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
1267da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machataint
1268929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataltelf_read_library(struct library *lib, struct process *proc,
1269da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata		   const char *filename, GElf_Addr bias)
1270da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata{
1271da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata	return read_module(lib, proc, filename, bias, 0);
1272da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata}
1273da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
1274da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata
12752b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machatastruct library *
1276929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataltelf_read_main_binary(struct process *proc, const char *path)
12772b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata{
1278b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata	struct library *lib = malloc(sizeof(*lib));
12797287166e8fd5949ffcf8eb1f3d378b5ea538915ePetr Machata	if (lib == NULL || library_init(lib, LT_LIBTYPE_MAIN) < 0) {
12807287166e8fd5949ffcf8eb1f3d378b5ea538915ePetr Machata		free(lib);
1281b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		return NULL;
12827287166e8fd5949ffcf8eb1f3d378b5ea538915ePetr Machata	}
1283fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	library_set_pathname(lib, path, 0);
1284b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
1285fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	/* There is a race between running the process and reading its
1286fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * binary for internal consumption.  So open the binary from
1287fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * the /proc filesystem.  XXX Note that there is similar race
1288fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * for libraries, but there we don't have a nice answer like
1289fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * that.  Presumably we could read the DSOs from the process
1290fc6ff18285b81c7c3f248be3667e8c74c2910cd8Petr Machata	 * memory image, but that's not currently done.  */
12912b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	char *fname = pid2name(proc->pid);
1292f0d248aab596acd802668990793413180bb21f79Petr Machata	if (fname == NULL
1293f0d248aab596acd802668990793413180bb21f79Petr Machata	    || read_module(lib, proc, fname, 0, 1) < 0) {
1294b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		library_destroy(lib);
1295b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		free(lib);
1296f0d248aab596acd802668990793413180bb21f79Petr Machata		lib = NULL;
12970b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	}
1298b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata
1299f0d248aab596acd802668990793413180bb21f79Petr Machata	free(fname);
13002b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	return lib;
130196935a9fe2af57e089cbd2e32a69caba5b3f2458Juan Cespedes}
1302