1e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata/* 2e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This file is part of ltrace. 31e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata * Copyright (C) 2013 Petr Machata, Red Hat Inc. 4e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2004,2008,2009 Juan Cespedes 5e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 6e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is free software; you can redistribute it and/or 7e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * modify it under the terms of the GNU General Public License as 8e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * published by the Free Software Foundation; either version 2 of the 9e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * License, or (at your option) any later version. 10e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 11e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is distributed in the hope that it will be useful, but 12e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of 13e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * General Public License for more details. 15e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 16e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * You should have received a copy of the GNU General Public License 17e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * along with this program; if not, write to the Free Software 18e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 19e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 02110-1301 USA 20e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata */ 21e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata 22d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes#include <gelf.h> 231e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata#include <stdbool.h> 241e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata 25366c2f46d844f040458df9b7e35fc3b8527ed2d3Petr Machata#include "proc.h" 26f728123bd75a65a6a1536e198c3c30719e494e71Juan Cespedes#include "common.h" 272b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata#include "library.h" 281e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata#include "trace.h" 29d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes 307b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machatastatic GElf_Addr 317b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machatax86_plt_offset(uint32_t i) 327b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata{ 337b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata /* Skip the first PLT entry, which contains a stub to call the 347b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * resolver. */ 357b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata return (i + 1) * 16; 367b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata} 377b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 38f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan CespedesGElf_Addr 391e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machataarch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela) 40929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{ 417b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata uint32_t i = *VECT_ELEMENT(<e->arch.plt_map, uint32_t, ndx); 427b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata return x86_plt_offset(i) + lte->plt_addr; 439a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand} 449a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand 45f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid * 46929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatasym2addr(struct process *proc, struct library_symbol *sym) 47929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{ 4876c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam return sym->enter_addr; 49d914a206a11cc1011a45f00674b1e16988fae77fJuan Cespedes} 501e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata 511e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machataenum plt_status 521e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machataarch_elf_add_plt_entry(struct process *proc, struct ltelf *lte, 531e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata const char *a_name, GElf_Rela *rela, size_t ndx, 541e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata struct library_symbol **ret) 551e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata{ 561e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata bool irelative = false; 571e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata if (lte->ehdr.e_machine == EM_X86_64) { 581e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata#ifdef R_X86_64_IRELATIVE 591e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata irelative = GELF_R_TYPE(rela->r_info) == R_X86_64_IRELATIVE; 601e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata#endif 611e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata } else { 621e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata assert(lte->ehdr.e_machine == EM_386); 631e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata#ifdef R_386_IRELATIVE 641e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata irelative = GELF_R_TYPE(rela->r_info) == R_386_IRELATIVE; 651e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata#endif 661e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata } 671e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata 681e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata if (irelative) 691e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata return linux_elf_add_plt_entry_irelative(proc, lte, rela, 701e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata ndx, ret); 711e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata 721e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata return PLT_DEFAULT; 731e4b8c8d93606721c8728c6cacb8c9921353049bPetr Machata} 747b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 757b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machataint 767b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machataarch_elf_init(struct ltelf *lte, struct library *lib) 777b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata{ 787b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata VECT_INIT(<e->arch.plt_map, unsigned int); 797b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 807b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata /* IRELATIVE slots may make the whole situation a fair deal 817b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * more complex. On x86{,_64}, the PLT slots are not 827b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * presented in the order of the corresponding relocations, 837b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * but in the order it which these symbols are in the symbol 847b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * table. That's static symbol table, which may be stripped 857b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * off, not dynsym--that doesn't contain IFUNC symbols at all. 867b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * So we have to decode each PLT entry to figure out what 877b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * entry it corresponds to. We need to interpret the PLT 887b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * table to figure this out. 897b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 907b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * On i386, the PLT entry format is as follows: 917b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 927b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 8048300: ff 25 0c a0 04 08 jmp *0x804a00c 937b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 8048306: 68 20 00 00 00 push $0x20 947b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 804830b: e9 e0 ff ff ff jmp 80482f0 <_init+0x30> 957b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 967b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * For PIE binaries it is the following: 977b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 987b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 410: ff a3 10 00 00 00 jmp *0x10(%ebx) 997b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 416: 68 00 00 00 00 push $0x0 1007b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 41b: e9 d0 ff ff ff jmp 3f0 <_init+0x30> 1017b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 1027b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * On x86_64, it is: 1037b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 1047b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 400420: ff 25 f2 0b 20 00 jmpq *0x200bf2(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18> 1057b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 400426: 68 00 00 00 00 pushq $0x0 1067b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 40042b: e9 e0 ff ff ff jmpq 400410 <_init+0x18> 1077b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 1087b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * On i386, the argument to push is an offset of relocation to 1097b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * use. The first PLT slot has an offset of 0x0, the second 1107b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * 0x8, etc. On x86_64, it's directly the index that we are 1117b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * looking for. 1127b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata */ 1137b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 1147b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata /* Here we scan the PLT table and initialize a map of 1157b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata * relocation->slot number in lte->arch.plt_map. */ 1167b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 1177b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata size_t i; 1187b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata for (i = 0; i < vect_size(<e->plt_relocs); ++i) { 1197b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 1207b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata GElf_Addr offset = x86_plt_offset(i); 1217b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata uint32_t reloc_arg = 0; 1227b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 1237b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata uint8_t byte; 1247b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0 1257b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata || byte != 0xff 1267b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata || elf_read_next_u8(lte->plt_data, &offset, &byte) < 0 1277b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata || (byte != 0xa3 && byte != 0x25)) 1287b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata goto next; 1297b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 1307b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata /* Skip immediate argument in the instruction. */ 1317b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata offset += 4; 1327b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 1337b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata if (elf_read_next_u8(lte->plt_data, &offset, &byte) < 0 1347b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata || byte != 0x68 1357b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata || elf_read_next_u32(lte->plt_data, 1367b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata &offset, &reloc_arg) < 0) { 1377b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata reloc_arg = 0; 1387b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata goto next; 1397b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata } 1407b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 1417b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata if (lte->ehdr.e_machine == EM_386) { 1427b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata if (reloc_arg % 8 != 0) { 1437b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata reloc_arg = 0; 1447b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata goto next; 1457b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata } 1467b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata reloc_arg /= 8; 1477b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata } 1487b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 1497b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata next: 1507b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata if (VECT_PUSHBACK(<e->arch.plt_map, &reloc_arg) < 0) { 1517b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata arch_elf_destroy(lte); 1527b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata return -1; 1537b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata } 1547b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata } 1557b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 1567b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata return 0; 1577b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata} 1587b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata 1597b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machatavoid 1607b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machataarch_elf_destroy(struct ltelf *lte) 1617b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata{ 1627b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata VECT_DESTROY(<e->arch.plt_map, uint32_t, NULL, NULL); 1637b0088dbf6861987f13ad1e0740d633069fdb9d7Petr Machata} 164