* Get the offset for an address. */
| 65 | * Get the offset for an address. |
| 66 | */ |
| 67 | static intptr_t addrToOffset(const Elf64_Phdr *phdrs, size_t phnum, |
| 68 | intptr_t addr, bool x = true) |
| 69 | { |
| 70 | if (addr == 0x0) |
| 71 | return INTPTR_MIN; |
| 72 | for (unsigned i = 0; i < phnum; i++) |
| 73 | { |
| 74 | const Elf64_Phdr *phdr = phdrs + i; |
| 75 | switch (phdr->p_type) |
| 76 | { |
| 77 | case PT_LOAD: case PT_GNU_RELRO: |
| 78 | break; |
| 79 | default: |
| 80 | continue; |
| 81 | } |
| 82 | if (x && (phdr->p_flags & PF_X) == 0) |
| 83 | continue; |
| 84 | intptr_t base = (intptr_t)phdr->p_vaddr; |
| 85 | size_t size = (size_t)phdr->p_filesz; |
| 86 | off_t offset = (off_t)phdr->p_offset; |
| 87 | if (addr >= base && addr < base + (ssize_t)size) |
| 88 | return offset + (addr - base); |
| 89 | } |
| 90 | return INTPTR_MIN; |
| 91 | } |
| 92 | |
| 93 | /* |
| 94 | * Target analysis. Find instructions that can be reached by a |