* Parse the ELF file & reserve any occupied address space. */
| 79 | * Parse the ELF file & reserve any occupied address space. |
| 80 | */ |
| 81 | bool parseElf(Binary *B) |
| 82 | { |
| 83 | const char *filename = B->filename; |
| 84 | uint8_t *data = B->patched.bytes; |
| 85 | size_t size = B->size; |
| 86 | Mode mode = B->mode; |
| 87 | ElfInfo &info = B->elf; |
| 88 | |
| 89 | if (size < sizeof(Elf64_Ehdr)) |
| 90 | error("failed to parse ELF EHDR from file \"%s\"; file is too small", |
| 91 | filename); |
| 92 | Elf64_Ehdr *ehdr = (Elf64_Ehdr *)data; |
| 93 | |
| 94 | if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || |
| 95 | ehdr->e_ident[EI_MAG1] != ELFMAG1 || |
| 96 | ehdr->e_ident[EI_MAG2] != ELFMAG2 || |
| 97 | ehdr->e_ident[EI_MAG3] != ELFMAG3) |
| 98 | error("failed to parse ELF file \"%s\"; invalid magic number", |
| 99 | filename); |
| 100 | if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) |
| 101 | error("failed to parse ELF file \"%s\"; file is not 64bit", |
| 102 | filename); |
| 103 | if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) |
| 104 | error("failed to parse ELF file \"%s\"; file is not little endian", |
| 105 | filename); |
| 106 | if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) |
| 107 | error("failed to parse ELF file \"%s\"; invalid version", |
| 108 | filename); |
| 109 | if (ehdr->e_machine != EM_X86_64) |
| 110 | error("failed to parse ELF file \"%s\"; file is not x86_64", |
| 111 | filename); |
| 112 | if (ehdr->e_phoff < sizeof(Elf64_Ehdr) || ehdr->e_phoff >= size) |
| 113 | error("failed to parse ELF file \"%s\"; invalid program header " |
| 114 | "offset", filename); |
| 115 | if (ehdr->e_phnum > PN_XNUM) |
| 116 | error("failed to parse ELF file \"%s\"; too many program headers", |
| 117 | filename); |
| 118 | if (ehdr->e_phoff + ehdr->e_phnum * sizeof(Elf64_Phdr) > size) |
| 119 | error("failed to parse ELF file \"%s\"; invalid program headers", |
| 120 | filename); |
| 121 | |
| 122 | bool pic = false, pie = false; |
| 123 | switch (ehdr->e_type) |
| 124 | { |
| 125 | case ET_EXEC: |
| 126 | { |
| 127 | if (mode == MODE_ELF_DSO) |
| 128 | error("failed to parse ELF file \"%s\": file is an " |
| 129 | "executable and not a shared object", filename); |
| 130 | if (!reserve(B, 0x0, 0x10000)) |
| 131 | error("failed to reserve low-address range"); |
| 132 | break; |
| 133 | } |
| 134 | case ET_DYN: |
| 135 | pic = true; |
| 136 | pie = (mode == MODE_ELF_EXE); |
| 137 | break; |
| 138 | default: |
no test coverage detected