plt.c revision 37d368e49f2d757484252a060d3021de96998e0d
1d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#include <gelf.h> 2a7af00db2231e99a4506e4f5587f9dd00b9d1175Juan Cespedes#include <sys/ptrace.h> 3e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#include <errno.h> 4e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#include <error.h> 5e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#include <inttypes.h> 6e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#include <assert.h> 737d368e49f2d757484252a060d3021de96998e0dPetr Machata#include <string.h> 8e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 9366c2f46d844f040458df9b7e35fc3b8527ed2d3Petr Machata#include "proc.h" 10f728123bd75a65a6a1536e198c3c30719e494e71Juan Cespedes#include "common.h" 11e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#include "library.h" 12e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 1337d368e49f2d757484252a060d3021de96998e0dPetr Machata/* There are two PLT types on 32-bit PPC: old-style, BSS PLT, and 1437d368e49f2d757484252a060d3021de96998e0dPetr Machata * new-style "secure" PLT. We can tell one from the other by the 1537d368e49f2d757484252a060d3021de96998e0dPetr Machata * flags on the .plt section. If it's +X (executable), it's BSS PLT, 1637d368e49f2d757484252a060d3021de96998e0dPetr Machata * otherwise it's secure. 1737d368e49f2d757484252a060d3021de96998e0dPetr Machata * 1837d368e49f2d757484252a060d3021de96998e0dPetr Machata * BSS PLT works the same way as most architectures: the .plt section 1937d368e49f2d757484252a060d3021de96998e0dPetr Machata * contains trampolines and we put breakpoints to those. With secure 2037d368e49f2d757484252a060d3021de96998e0dPetr Machata * PLT, the .plt section doesn't contain instructions but addresses. 2137d368e49f2d757484252a060d3021de96998e0dPetr Machata * The real PLT table is stored in .text. Addresses of those PLT 2237d368e49f2d757484252a060d3021de96998e0dPetr Machata * entries can be computed, and it fact that's what the glink deal 2337d368e49f2d757484252a060d3021de96998e0dPetr Machata * below does. 2437d368e49f2d757484252a060d3021de96998e0dPetr Machata * 2537d368e49f2d757484252a060d3021de96998e0dPetr Machata * If not prelinked, BSS PLT entries in the .plt section contain 2637d368e49f2d757484252a060d3021de96998e0dPetr Machata * zeroes that are overwritten by the dynamic linker during start-up. 2737d368e49f2d757484252a060d3021de96998e0dPetr Machata * For that reason, ltrace realizes those breakpoints only after 2837d368e49f2d757484252a060d3021de96998e0dPetr Machata * .start is hit. 2937d368e49f2d757484252a060d3021de96998e0dPetr Machata * 3037d368e49f2d757484252a060d3021de96998e0dPetr Machata * 64-bit PPC is more involved. Program linker creates for each 3137d368e49f2d757484252a060d3021de96998e0dPetr Machata * library call a _stub_ symbol named xxxxxxxx.plt_call.<callee> 3237d368e49f2d757484252a060d3021de96998e0dPetr Machata * (where xxxxxxxx is a hexadecimal number). That stub does the call 3337d368e49f2d757484252a060d3021de96998e0dPetr Machata * dispatch: it loads an address of a function to call from the 3437d368e49f2d757484252a060d3021de96998e0dPetr Machata * section .plt, and branches. PLT entries themselves are essentially 3537d368e49f2d757484252a060d3021de96998e0dPetr Machata * a curried call to the resolver. When the symbol is resolved, the 3637d368e49f2d757484252a060d3021de96998e0dPetr Machata * resolver updates the value stored in .plt, and the next time 3737d368e49f2d757484252a060d3021de96998e0dPetr Machata * around, the stub calls the library function directly. So we make 3837d368e49f2d757484252a060d3021de96998e0dPetr Machata * at most one trip (none if the binary is prelinked) through each PLT 3937d368e49f2d757484252a060d3021de96998e0dPetr Machata * entry, and correspondingly that is useless as a breakpoint site. 4037d368e49f2d757484252a060d3021de96998e0dPetr Machata * 4137d368e49f2d757484252a060d3021de96998e0dPetr Machata * Note the three confusing terms: stubs (that play the role of PLT 4237d368e49f2d757484252a060d3021de96998e0dPetr Machata * entries), PLT entries, .plt section. 4337d368e49f2d757484252a060d3021de96998e0dPetr Machata * 4437d368e49f2d757484252a060d3021de96998e0dPetr Machata * We first check symbol tables and see if we happen to have stub 4537d368e49f2d757484252a060d3021de96998e0dPetr Machata * symbols available. If yes we just put breakpoints to those, and 4637d368e49f2d757484252a060d3021de96998e0dPetr Machata * treat them as usual breakpoints. The only tricky part is realizing 4737d368e49f2d757484252a060d3021de96998e0dPetr Machata * that there can be more than one breakpoint per symbol. 4837d368e49f2d757484252a060d3021de96998e0dPetr Machata * 4937d368e49f2d757484252a060d3021de96998e0dPetr Machata * The case that we don't have the stub symbols available is harder. 5037d368e49f2d757484252a060d3021de96998e0dPetr Machata * The following scheme uses two kinds of PLT breakpoints: unresolved 5137d368e49f2d757484252a060d3021de96998e0dPetr Machata * and resolved (to some address). When the process starts (or when 5237d368e49f2d757484252a060d3021de96998e0dPetr Machata * we attach), we distribute unresolved PLT breakpoints to the PLT 5337d368e49f2d757484252a060d3021de96998e0dPetr Machata * entries (not stubs). Then we look in .plt, and for each entry 5437d368e49f2d757484252a060d3021de96998e0dPetr Machata * whose value is different than the corresponding PLT entry address, 5537d368e49f2d757484252a060d3021de96998e0dPetr Machata * we assume it was already resolved, and convert the breakpoint to 5637d368e49f2d757484252a060d3021de96998e0dPetr Machata * resolved. We also rewrite the resolved value in .plt back to the 5737d368e49f2d757484252a060d3021de96998e0dPetr Machata * PLT address. 5837d368e49f2d757484252a060d3021de96998e0dPetr Machata * 5937d368e49f2d757484252a060d3021de96998e0dPetr Machata * When a PLT entry hits a resolved breakpoint (which happens because 6037d368e49f2d757484252a060d3021de96998e0dPetr Machata * we put back the unresolved addresses to .plt), we move the 6137d368e49f2d757484252a060d3021de96998e0dPetr Machata * instruction pointer to the corresponding address and continue the 6237d368e49f2d757484252a060d3021de96998e0dPetr Machata * process as if nothing happened. 6337d368e49f2d757484252a060d3021de96998e0dPetr Machata * 6437d368e49f2d757484252a060d3021de96998e0dPetr Machata * When unresolved PLT entry is called for the first time, we need to 6537d368e49f2d757484252a060d3021de96998e0dPetr Machata * catch the new value that the resolver will write to a .plt slot. 6637d368e49f2d757484252a060d3021de96998e0dPetr Machata * We also need to prevent another thread from racing through and 6737d368e49f2d757484252a060d3021de96998e0dPetr Machata * taking the branch without ltrace noticing. So when unresolved PLT 6837d368e49f2d757484252a060d3021de96998e0dPetr Machata * entry hits, we have to stop all threads. We then single-step 6937d368e49f2d757484252a060d3021de96998e0dPetr Machata * through the resolver, until the .plt slot changes. When it does, 7037d368e49f2d757484252a060d3021de96998e0dPetr Machata * we treat it the same way as above: convert the PLT breakpoint to 7137d368e49f2d757484252a060d3021de96998e0dPetr Machata * resolved, and rewrite the .plt value back to PLT address. We then 7237d368e49f2d757484252a060d3021de96998e0dPetr Machata * start all threads again. 7337d368e49f2d757484252a060d3021de96998e0dPetr Machata * 7437d368e49f2d757484252a060d3021de96998e0dPetr Machata * In theory we might find the exact instruction that will update the 7537d368e49f2d757484252a060d3021de96998e0dPetr Machata * .plt slot, and emulate it, updating the PLT breakpoint immediately, 7637d368e49f2d757484252a060d3021de96998e0dPetr Machata * and then just skip it. But that's even messier than the thread 7737d368e49f2d757484252a060d3021de96998e0dPetr Machata * stopping business and single stepping that needs to be done. 7837d368e49f2d757484252a060d3021de96998e0dPetr Machata */ 7937d368e49f2d757484252a060d3021de96998e0dPetr Machata 80e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#define PPC_PLT_STUB_SIZE 16 81e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 82e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machatastatic inline int 834e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machatahost_powerpc64() 84e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata{ 85e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#ifdef __powerpc64__ 86e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return 1; 87e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#else 88e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return 0; 89e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata#endif 90e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata} 91e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 92f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan CespedesGElf_Addr 934e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machataarch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela) 944e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata{ 954e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata if (lte->ehdr.e_machine == EM_PPC && lte->arch.secure_plt) { 964e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata assert(lte->arch.plt_stub_vma != 0); 97e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return lte->arch.plt_stub_vma + PPC_PLT_STUB_SIZE * ndx; 984e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata 994e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata } else if (lte->ehdr.e_machine == EM_PPC) { 100e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return rela->r_offset; 1014e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata 1024e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata } else { 1034e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata assert(lte->ehdr.e_machine == EM_PPC64); 1044e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata fprintf(stderr, "PPC64\n"); 1054e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata abort(); 1064e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata return rela->r_offset; 1074e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata } 108e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata} 109e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 110e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machataint 111e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machataarch_translate_address(struct Process *proc, 112e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata target_address_t addr, target_address_t *ret) 113e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata{ 1144e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata if (host_powerpc64() && proc->e_machine == EM_PPC64) { 115e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0); 116e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata fprintf(stderr, "arch_translate_address %p->%#lx\n", 117e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata addr, l); 118e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata if (l == -1 && errno) { 119e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata error(0, errno, ".opd translation of %p", addr); 120e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return -1; 121e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } 122e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata *ret = (target_address_t)l; 123e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return 0; 124e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } 125e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 126e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata *ret = addr; 127e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return 0; 128d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes} 1299a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand 1302b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata/* XXX Apparently PPC64 doesn't support PLT breakpoints. */ 131f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid * 132a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedessym2addr(Process *proc, struct library_symbol *sym) { 133a841f6592e75d78620ee9e645af22a58c9e3bbf9Olaf Hering void *addr = sym->enter_addr; 13476c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam long pt_ret; 1359a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand 1362d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand debug(3, 0); 1379a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand 13876c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam if (sym->plt_type != LS_TOPLT_POINT) { 13976c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam return addr; 14076c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam } 1419a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand 14276c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam if (proc->pid == 0) { 14376c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam return 0; 14476c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam } 1459a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand 146da9b953284966b8c52de43713ebb5b503756e468Juan Cespedes if (options.debug >= 3) { 14776c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam xinfdump(proc->pid, (void *)(((long)addr-32)&0xfffffff0), 14876c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam sizeof(void*)*8); 14976c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam } 15076c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam 15176c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // On a PowerPC-64 system, a plt is three 64-bit words: the first is the 15276c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // 64-bit address of the routine. Before the PLT has been initialized, 15376c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // this will be 0x0. In fact, the symbol table won't have the plt's 15476c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // address even. Ater the PLT has been initialized, but before it has 15576c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // been resolved, the first word will be the address of the function in 15676c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // the dynamic linker that will reslove the PLT. After the PLT is 15776c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // resolved, this will will be the address of the routine whose symbol 15876c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // is in the symbol table. 15976c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam 16076c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // On a PowerPC-32 system, there are two types of PLTs: secure (new) and 16176c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // non-secure (old). For the secure case, the PLT is simply a pointer 16276c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // and we can treat it much as we do for the PowerPC-64 case. For the 16376c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // non-secure case, the PLT is executable code and we can put the 16476c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // break-point right in the PLT. 16576c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam 16676c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam pt_ret = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0); 16776c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam 1689bc4a9b46340209f774181f7e55ece1c47bd59d6Michael K. Edwards#if SIZEOF_LONG == 8 16976c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam if (proc->mask_32bit) { 17076c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam // Assume big-endian. 17176c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam addr = (void *)((pt_ret >> 32) & 0xffffffff); 17276c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam } else { 17376c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam addr = (void *)pt_ret; 1742d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand } 1759bc4a9b46340209f774181f7e55ece1c47bd59d6Michael K. Edwards#else 1762b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata /* XXX Um, so where exactly are we dealing with the non-secure 1772b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata PLT thing? */ 1789bc4a9b46340209f774181f7e55ece1c47bd59d6Michael K. Edwards addr = (void *)pt_ret; 1799bc4a9b46340209f774181f7e55ece1c47bd59d6Michael K. Edwards#endif 1809a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand 18176c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam return addr; 1829a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand} 183e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 184e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machatastatic GElf_Addr 185e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machataget_glink_vma(struct ltelf *lte, GElf_Addr ppcgot, Elf_Data *plt_data) 186e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata{ 187e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata Elf_Scn *ppcgot_sec = NULL; 188e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata GElf_Shdr ppcgot_shdr; 189e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata if (ppcgot != 0 190e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata && elf_get_section_covering(lte, ppcgot, 191e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata &ppcgot_sec, &ppcgot_shdr) < 0) 192e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata // xxx should be the log out 193e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata fprintf(stderr, 194e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata "DT_PPC_GOT=%#" PRIx64 ", but no such section found.\n", 195e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata ppcgot); 196e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 197e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata if (ppcgot_sec != NULL) { 198e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata Elf_Data *data = elf_loaddata(ppcgot_sec, &ppcgot_shdr); 199e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata if (data == NULL || data->d_size < 8 ) { 200e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata fprintf(stderr, "Couldn't read GOT data.\n"); 201e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } else { 202e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata // where PPCGOT begins in .got 203e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata size_t offset = ppcgot - ppcgot_shdr.sh_addr; 204e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata assert(offset % 4 == 0); 205e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata uint32_t glink_vma; 206e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata if (elf_read_u32(data, offset + 4, &glink_vma) < 0) { 207e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata fprintf(stderr, 208e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata "Couldn't read glink VMA address" 209e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata " at %zd@GOT\n", offset); 210e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return 0; 211e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } 212e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata if (glink_vma != 0) { 213e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata debug(1, "PPC GOT glink_vma address: %#" PRIx32, 214e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata glink_vma); 215e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata fprintf(stderr, "PPC GOT glink_vma " 216e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata "address: %#"PRIx32"\n", glink_vma); 217e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return (GElf_Addr)glink_vma; 218e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } 219e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } 220e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } 221e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 222e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata if (plt_data != NULL) { 223e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata uint32_t glink_vma; 224e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata if (elf_read_u32(plt_data, 0, &glink_vma) < 0) { 225e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata fprintf(stderr, 226e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata "Couldn't read glink VMA address at 0@.plt\n"); 227e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return 0; 228e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } 229e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata debug(1, ".plt glink_vma address: %#" PRIx32, glink_vma); 230e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata fprintf(stderr, ".plt glink_vma address: " 231e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata "%#"PRIx32"\n", glink_vma); 232e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return (GElf_Addr)glink_vma; 233e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } 234e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 235e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return 0; 236e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata} 237e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 238644d669f96c0fe261fe938cecda41938e804c7d9Petr Machatastatic int 239644d669f96c0fe261fe938cecda41938e804c7d9Petr Machataload_ppcgot(struct ltelf *lte, GElf_Addr *ppcgotp) 240e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata{ 241644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata Elf_Scn *scn; 242644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata GElf_Shdr shdr; 243644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0 244644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata || scn == NULL) { 245644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata fail: 246644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata error(0, 0, "Couldn't get SHT_DYNAMIC: %s", 247644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata elf_errmsg(-1)); 248644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata return -1; 249e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } 250644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata 251644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata Elf_Data *data = elf_loaddata(scn, &shdr); 252644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata if (data == NULL) 253644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata goto fail; 254644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata 255644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata size_t j; 256644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) { 257644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata GElf_Dyn dyn; 258644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata if (gelf_getdyn(data, j, &dyn) == NULL) 259644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata goto fail; 260644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata 261644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata if(dyn.d_tag == DT_PPC_GOT) { 262644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata *ppcgotp = dyn.d_un.d_ptr; 263644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata return 0; 264644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata } 265644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata } 266644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata 267644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata return -1; 268e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata} 269e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 270e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machataint 271e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machataarch_elf_init(struct ltelf *lte) 272e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata{ 2734e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata lte->arch.secure_plt = !(lte->lte_flags & LTE_PLT_EXECUTABLE); 2744e2073f64f9db2974d89064dcdc49b2ed7aa9006Petr Machata if (lte->ehdr.e_machine == EM_PPC && lte->arch.secure_plt) { 275644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata GElf_Addr ppcgot; 276644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata if (load_ppcgot(lte, &ppcgot) < 0) { 277644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata fprintf(stderr, "Couldn't find DT_PPC_GOT.\n"); 278644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata return -1; 279644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata } 280644d669f96c0fe261fe938cecda41938e804c7d9Petr Machata GElf_Addr glink_vma = get_glink_vma(lte, ppcgot, lte->plt_data); 281e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 282e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata assert (lte->relplt_size % 12 == 0); 283e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata size_t count = lte->relplt_size / 12; // size of RELA entry 284e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata lte->arch.plt_stub_vma = glink_vma 285e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata - (GElf_Addr)count * PPC_PLT_STUB_SIZE; 286e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata debug(1, "stub_vma is %#" PRIx64, lte->arch.plt_stub_vma); 287e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata } 288e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata 289e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata /* Override the value that we gleaned from flags on the .plt 290e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata * section. The PLT entries are in fact executable, they are 291e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata * just not in .plt. */ 292e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata lte->lte_flags |= LTE_PLT_EXECUTABLE; 29337d368e49f2d757484252a060d3021de96998e0dPetr Machata 29437d368e49f2d757484252a060d3021de96998e0dPetr Machata /* On PPC64, look for stub symbols in symbol table. These are 29537d368e49f2d757484252a060d3021de96998e0dPetr Machata * called: xxxxxxxx.plt_call.callee_name@version+addend. */ 29637d368e49f2d757484252a060d3021de96998e0dPetr Machata if (lte->ehdr.e_machine == EM_PPC64 29737d368e49f2d757484252a060d3021de96998e0dPetr Machata && lte->symtab != NULL && lte->strtab != NULL) { 29837d368e49f2d757484252a060d3021de96998e0dPetr Machata 29937d368e49f2d757484252a060d3021de96998e0dPetr Machata /* N.B. We can't simply skip the symbols that we fail 30037d368e49f2d757484252a060d3021de96998e0dPetr Machata * to read or malloc. There may be more than one stub 30137d368e49f2d757484252a060d3021de96998e0dPetr Machata * per symbol name, and if we failed in one but 30237d368e49f2d757484252a060d3021de96998e0dPetr Machata * succeeded in another, the PLT enabling code would 30337d368e49f2d757484252a060d3021de96998e0dPetr Machata * have no way to tell that something is missing. We 30437d368e49f2d757484252a060d3021de96998e0dPetr Machata * could work around that, of course, but it doesn't 30537d368e49f2d757484252a060d3021de96998e0dPetr Machata * seem worth the trouble. We just fail right away in 30637d368e49f2d757484252a060d3021de96998e0dPetr Machata * face of errors. */ 30737d368e49f2d757484252a060d3021de96998e0dPetr Machata 30837d368e49f2d757484252a060d3021de96998e0dPetr Machata size_t i; 30937d368e49f2d757484252a060d3021de96998e0dPetr Machata for (i = 0; i < lte->symtab_count; ++i) { 31037d368e49f2d757484252a060d3021de96998e0dPetr Machata GElf_Sym sym; 31137d368e49f2d757484252a060d3021de96998e0dPetr Machata if (gelf_getsym(lte->symtab, i, &sym) == NULL) 31237d368e49f2d757484252a060d3021de96998e0dPetr Machata break; 31337d368e49f2d757484252a060d3021de96998e0dPetr Machata 31437d368e49f2d757484252a060d3021de96998e0dPetr Machata const char *name = lte->strtab + sym.st_name; 31537d368e49f2d757484252a060d3021de96998e0dPetr Machata 31637d368e49f2d757484252a060d3021de96998e0dPetr Machata#define STUBN ".plt_call." 31737d368e49f2d757484252a060d3021de96998e0dPetr Machata if ((name = strstr(name, STUBN)) == NULL) 31837d368e49f2d757484252a060d3021de96998e0dPetr Machata continue; 31937d368e49f2d757484252a060d3021de96998e0dPetr Machata name += sizeof(STUBN) - 1; 32037d368e49f2d757484252a060d3021de96998e0dPetr Machata#undef STUBN 32137d368e49f2d757484252a060d3021de96998e0dPetr Machata 32237d368e49f2d757484252a060d3021de96998e0dPetr Machata size_t len; 32337d368e49f2d757484252a060d3021de96998e0dPetr Machata const char *ver = strchr(name, '@'); 32437d368e49f2d757484252a060d3021de96998e0dPetr Machata if (ver != NULL) { 32537d368e49f2d757484252a060d3021de96998e0dPetr Machata len = ver - name; 32637d368e49f2d757484252a060d3021de96998e0dPetr Machata 32737d368e49f2d757484252a060d3021de96998e0dPetr Machata } else { 32837d368e49f2d757484252a060d3021de96998e0dPetr Machata /* If there is "+" at all, check that 32937d368e49f2d757484252a060d3021de96998e0dPetr Machata * the symbol name ends in "+0". */ 33037d368e49f2d757484252a060d3021de96998e0dPetr Machata const char *add = strrchr(name, '+'); 33137d368e49f2d757484252a060d3021de96998e0dPetr Machata if (add != NULL) { 33237d368e49f2d757484252a060d3021de96998e0dPetr Machata assert(strcmp(add, "+0") == 0); 33337d368e49f2d757484252a060d3021de96998e0dPetr Machata len = add - name; 33437d368e49f2d757484252a060d3021de96998e0dPetr Machata } else { 33537d368e49f2d757484252a060d3021de96998e0dPetr Machata len = strlen(name); 33637d368e49f2d757484252a060d3021de96998e0dPetr Machata } 33737d368e49f2d757484252a060d3021de96998e0dPetr Machata } 33837d368e49f2d757484252a060d3021de96998e0dPetr Machata 33937d368e49f2d757484252a060d3021de96998e0dPetr Machata char *sym_name = strndup(name, len); 34037d368e49f2d757484252a060d3021de96998e0dPetr Machata if (sym_name == NULL) { 34137d368e49f2d757484252a060d3021de96998e0dPetr Machata fail: 34237d368e49f2d757484252a060d3021de96998e0dPetr Machata free(sym_name); 34337d368e49f2d757484252a060d3021de96998e0dPetr Machata break; 34437d368e49f2d757484252a060d3021de96998e0dPetr Machata } 34537d368e49f2d757484252a060d3021de96998e0dPetr Machata 34637d368e49f2d757484252a060d3021de96998e0dPetr Machata struct library_symbol *libsym = malloc(sizeof(*libsym)); 34737d368e49f2d757484252a060d3021de96998e0dPetr Machata if (libsym == NULL) 34837d368e49f2d757484252a060d3021de96998e0dPetr Machata goto fail; 34937d368e49f2d757484252a060d3021de96998e0dPetr Machata target_address_t addr 35037d368e49f2d757484252a060d3021de96998e0dPetr Machata = (target_address_t)sym.st_value + lte->bias; 35137d368e49f2d757484252a060d3021de96998e0dPetr Machata library_symbol_init(libsym, addr, sym_name, 1, 35237d368e49f2d757484252a060d3021de96998e0dPetr Machata LS_TOPLT_EXEC); 35337d368e49f2d757484252a060d3021de96998e0dPetr Machata libsym->next = lte->arch.stubs; 35437d368e49f2d757484252a060d3021de96998e0dPetr Machata lte->arch.stubs = libsym; 35537d368e49f2d757484252a060d3021de96998e0dPetr Machata } 35637d368e49f2d757484252a060d3021de96998e0dPetr Machata } 35737d368e49f2d757484252a060d3021de96998e0dPetr Machata 358e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata return 0; 359e67635d6dcecb0f44448a5329d69fd0de74ebabaPetr Machata} 36037d368e49f2d757484252a060d3021de96998e0dPetr Machata 36137d368e49f2d757484252a060d3021de96998e0dPetr Machataenum plt_status 36237d368e49f2d757484252a060d3021de96998e0dPetr Machataarch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte, 36337d368e49f2d757484252a060d3021de96998e0dPetr Machata const char *a_name, GElf_Rela *rela, size_t i, 36437d368e49f2d757484252a060d3021de96998e0dPetr Machata struct library_symbol **ret) 36537d368e49f2d757484252a060d3021de96998e0dPetr Machata{ 36637d368e49f2d757484252a060d3021de96998e0dPetr Machata if (lte->ehdr.e_machine == EM_PPC) 36737d368e49f2d757484252a060d3021de96998e0dPetr Machata return plt_default; 36837d368e49f2d757484252a060d3021de96998e0dPetr Machata 36937d368e49f2d757484252a060d3021de96998e0dPetr Machata /* PPC64. If we have stubs, we return a chain of breakpoint 37037d368e49f2d757484252a060d3021de96998e0dPetr Machata * sites, one for each stub that corresponds to this PLT 37137d368e49f2d757484252a060d3021de96998e0dPetr Machata * entry. */ 37237d368e49f2d757484252a060d3021de96998e0dPetr Machata struct library_symbol *chain = NULL; 37337d368e49f2d757484252a060d3021de96998e0dPetr Machata struct library_symbol **symp; 37437d368e49f2d757484252a060d3021de96998e0dPetr Machata for (symp = <e->arch.stubs; *symp != NULL; ) { 37537d368e49f2d757484252a060d3021de96998e0dPetr Machata struct library_symbol *sym = *symp; 37637d368e49f2d757484252a060d3021de96998e0dPetr Machata if (strcmp(sym->name, a_name) != 0) { 37737d368e49f2d757484252a060d3021de96998e0dPetr Machata symp = &(*symp)->next; 37837d368e49f2d757484252a060d3021de96998e0dPetr Machata continue; 37937d368e49f2d757484252a060d3021de96998e0dPetr Machata } 38037d368e49f2d757484252a060d3021de96998e0dPetr Machata 38137d368e49f2d757484252a060d3021de96998e0dPetr Machata /* Re-chain the symbol from stubs to CHAIN. */ 38237d368e49f2d757484252a060d3021de96998e0dPetr Machata *symp = sym->next; 38337d368e49f2d757484252a060d3021de96998e0dPetr Machata sym->next = chain; 38437d368e49f2d757484252a060d3021de96998e0dPetr Machata chain = sym; 38537d368e49f2d757484252a060d3021de96998e0dPetr Machata } 38637d368e49f2d757484252a060d3021de96998e0dPetr Machata 38737d368e49f2d757484252a060d3021de96998e0dPetr Machata if (chain != NULL) { 38837d368e49f2d757484252a060d3021de96998e0dPetr Machata struct library_symbol *sym; 38937d368e49f2d757484252a060d3021de96998e0dPetr Machata for (sym = chain; sym != NULL; sym = sym->next) 39037d368e49f2d757484252a060d3021de96998e0dPetr Machata fprintf(stderr, "match %s --> %p\n", 39137d368e49f2d757484252a060d3021de96998e0dPetr Machata sym->name, sym->enter_addr); 39237d368e49f2d757484252a060d3021de96998e0dPetr Machata for (sym = lte->arch.stubs; sym != NULL; sym = sym->next) 39337d368e49f2d757484252a060d3021de96998e0dPetr Machata fprintf(stderr, "remains %s --> %p\n", 39437d368e49f2d757484252a060d3021de96998e0dPetr Machata sym->name, sym->enter_addr); 39537d368e49f2d757484252a060d3021de96998e0dPetr Machata 39637d368e49f2d757484252a060d3021de96998e0dPetr Machata *ret = chain; 39737d368e49f2d757484252a060d3021de96998e0dPetr Machata return plt_ok; 39837d368e49f2d757484252a060d3021de96998e0dPetr Machata } 39937d368e49f2d757484252a060d3021de96998e0dPetr Machata 40037d368e49f2d757484252a060d3021de96998e0dPetr Machata fprintf(stderr, "NO STUBS!\n"); 40137d368e49f2d757484252a060d3021de96998e0dPetr Machata abort(); 40237d368e49f2d757484252a060d3021de96998e0dPetr Machata} 40337d368e49f2d757484252a060d3021de96998e0dPetr Machata 4044d9a91c5c677d6a6b2db21f00385bce5167373c4Petr Machatavoid 4054d9a91c5c677d6a6b2db21f00385bce5167373c4Petr Machataarch_elf_destroy(struct ltelf *lte) 4064d9a91c5c677d6a6b2db21f00385bce5167373c4Petr Machata{ 40737d368e49f2d757484252a060d3021de96998e0dPetr Machata struct library_symbol *sym; 40837d368e49f2d757484252a060d3021de96998e0dPetr Machata for (sym = lte->arch.stubs; sym != NULL; ) { 40937d368e49f2d757484252a060d3021de96998e0dPetr Machata struct library_symbol *next = sym->next; 41037d368e49f2d757484252a060d3021de96998e0dPetr Machata library_symbol_destroy(sym); 41137d368e49f2d757484252a060d3021de96998e0dPetr Machata free(sym); 41237d368e49f2d757484252a060d3021de96998e0dPetr Machata sym = next; 41337d368e49f2d757484252a060d3021de96998e0dPetr Machata } 4144d9a91c5c677d6a6b2db21f00385bce5167373c4Petr Machata} 415