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, <e->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(<e->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(<e->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, <e->symtab, 602cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata <e->symtab_count, <e->strtab); 6032d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand 6042d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand } else if (shdr.sh_type == SHT_DYNSYM) { 605cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata read_symbol_table(lte, filename, 606cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata scn, &shdr, name, <e->dynsym, 607cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata <e->dynsym_count, <e->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 <e->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(<e->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(<e->plt_relocs); 81697d13666cd84589135ba593fa43a800d098026d0Petr Machata 817b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata size_t i; 818673ff510953b65b844a58478aa434120f457c014Petr Machata for (i = 0; i < count; ++i) { 819673ff510953b65b844a58478aa434120f457c014Petr Machata GElf_Rela *rela = VECT_ELEMENT(<e->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(<e, 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(<e); 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(<e, filename) < 0) 1189673ff510953b65b844a58478aa434120f457c014Petr Machata goto fail; 1190da69ed0785ff0a9790f8edadb73fe21013aa118bPetr Machata 1191e0615ab04b1bd376aae61c62d77fa6bda219f326Petr Machata if (arch_elf_init(<e, 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(<e, 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, <e, 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, <e, lib, 1259013ef5b78915cd24324fe28e68ae38de9249cb4ePetr Machata symtabs, exports) < 0) 1260da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata goto fail; 1261da3edbf059fe6c6d010b47ac50876783b4ed49cePetr Machata 1262673ff510953b65b844a58478aa434120f457c014Petr Machata arch_elf_destroy(<e); 1263673ff510953b65b844a58478aa434120f457c014Petr Machata ltelf_destroy(<e); 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