1 /* 2 * This file is part of ltrace. 3 * Copyright (C) 2012 Petr Machata, Red Hat Inc. 4 * Copyright (C) 2008,2009 Juan Cespedes 5 * Copyright (C) 2006 Ian Wienand 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of the 10 * License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA 21 */ 22 23 #include <errno.h> 24 #include <gelf.h> 25 #include <stdio.h> 26 #include <string.h> 27 #include <sys/ptrace.h> 28 29 #include "proc.h" 30 #include "common.h" 31 #include "library.h" 32 33 /* A bundle is 128 bits. */ 34 #define BUNDLE_SIZE 16 35 36 /* The PLT has 37 * 38 * - 3 bundles as a header 39 * 40 * - The special reserved entry 41 * 42 * - Following that, each PLT entry has it's initial code that the GOT 43 * entry points to. Each PLT entry has one bundle allocated. 44 * 45 * - Following that, each PLT entry has two bundles of actual PLT 46 * code, i.e. load up the address from the GOT and jump to it. This 47 * is the point we want to insert the breakpoint, as this will be 48 * captured every time we jump to the PLT entry in the code. 49 */ 50 51 GElf_Addr 52 arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) 53 { 54 /* Find number of entires by removing header and special 55 * entry, dividing total size by three, since each PLT entry 56 * will have 3 bundles (1 for inital entry and two for the PLT 57 * code). */ 58 int entries = (lte->plt_size - 4 * BUNDLE_SIZE) / (3 * BUNDLE_SIZE); 59 60 /* Now the point we want to break on is the PLT entry after 61 * all the header stuff */ 62 unsigned long addr = 63 lte->plt_addr + (4 * BUNDLE_SIZE) + (BUNDLE_SIZE * entries) + 64 (2 * ndx * BUNDLE_SIZE); 65 debug(3, "Found PLT %zd entry at %lx", ndx, addr); 66 67 return addr; 68 } 69 70 void * 71 sym2addr(struct process *proc, struct library_symbol *sym) 72 { 73 return sym->enter_addr; 74 } 75 76 int 77 arch_translate_address_dyn(struct process *proc, 78 arch_addr_t addr, arch_addr_t *ret) 79 { 80 errno = 0; 81 unsigned long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0); 82 if (l == -1UL && errno) { 83 fprintf(stderr, "dynamic .opd translation of %p: %s\n", 84 addr, strerror(errno)); 85 return -1; 86 } 87 88 /* XXX The double cast should be removed when 89 * arch_addr_t becomes integral type. */ 90 *ret = (arch_addr_t)(uintptr_t)l; 91 return 0; 92 } 93 94 int 95 arch_translate_address(struct ltelf *lte, 96 arch_addr_t addr, arch_addr_t *ret) 97 { 98 *ret = addr; 99 return 0; 100 } 101