* Parse the Procedure Linkage Table (PLT). */
| 809 | * Parse the Procedure Linkage Table (PLT). |
| 810 | */ |
| 811 | static void parsePLT(const uint8_t *data, const Elf64_Shdr *shdr_plt, |
| 812 | const Elf64_Shdr *shdr_rela_plt, const Elf64_Sym *dynsym_tab, |
| 813 | size_t dynsym_num, const char *dynstr_tab, size_t dynstr_len, |
| 814 | size_t plt_entry_sz, PLTInfo &plt) |
| 815 | { |
| 816 | intptr_t plt_addr = (intptr_t)shdr_plt->sh_addr; |
| 817 | size_t plt_size = (size_t)shdr_plt->sh_size; |
| 818 | const uint8_t *plt_data = data + shdr_plt->sh_offset; |
| 819 | plt_size -= plt_size % plt_entry_sz; |
| 820 | std::map<intptr_t, intptr_t> entries; |
| 821 | for (size_t i = 0; i < plt_size; i += plt_entry_sz) |
| 822 | { |
| 823 | // Parse PLT entry: |
| 824 | const uint8_t *plt_entry = plt_data + i; |
| 825 | size_t j = 0; |
| 826 | if (plt_entry[j] == 0xF3 && plt_entry[j+1] == 0x0F && |
| 827 | plt_entry[j+2] == 0x1E && plt_entry[j+3] == 0xFA) |
| 828 | j += 4; // skip endbr64 |
| 829 | if (plt_entry[j] == 0xF2) |
| 830 | j++; // skip bnd prefix |
| 831 | if (plt_entry[j] == 0xFF && plt_entry[j+1] == 0x25) |
| 832 | { |
| 833 | // jmp *offset(%rip) |
| 834 | intptr_t offset = *(const uint32_t *)(plt_entry + j + 2); |
| 835 | intptr_t addr = plt_addr + i + j + /*sizeof(jmpq)=*/6 + offset; |
| 836 | entries.insert({addr, plt_addr + i}); |
| 837 | } |
| 838 | } |
| 839 | |
| 840 | const Elf64_Rela *rela_tab = |
| 841 | (const Elf64_Rela *)(data + shdr_rela_plt->sh_offset); |
| 842 | size_t rela_num = shdr_rela_plt->sh_size / sizeof(Elf64_Rela); |
| 843 | for (size_t i = 0; i < rela_num; i++) |
| 844 | { |
| 845 | const Elf64_Rela *rela = rela_tab + i; |
| 846 | auto k = entries.find(rela->r_offset); |
| 847 | if (k == entries.end()) |
| 848 | continue; |
| 849 | size_t idx = (size_t)ELF64_R_SYM(rela->r_info); |
| 850 | if (idx >= dynsym_num) |
| 851 | continue; |
| 852 | const Elf64_Sym *sym = dynsym_tab + idx; |
| 853 | const char *name = parseName(dynstr_tab, dynstr_len, sym->st_name); |
| 854 | if (name == nullptr || sym->st_shndx != SHN_UNDEF || |
| 855 | ELF64_ST_TYPE(sym->st_info) != STT_FUNC) |
| 856 | continue; |
| 857 | plt.insert({name, k->second}); |
| 858 | } |
| 859 | } |
| 860 | |
| 861 | /* |
| 862 | * Parse a symbol table. |