* Code analysis pass: find all probable code targets. */
| 106 | * Code analysis pass: find all probable code targets. |
| 107 | */ |
| 108 | static void CFGCodeAnalysis(const ELF *elf, bool pic, const Instr *Is, |
| 109 | size_t size, std::set<intptr_t> &tables, Targets &targets) |
| 110 | { |
| 111 | // STEP (1): Calculate a rough-cut of the targets: |
| 112 | intptr_t next = INTPTR_MIN; |
| 113 | for (size_t i = 0; i < size; i++) |
| 114 | { |
| 115 | InstrInfo I0, *I = &I0; |
| 116 | getInstrInfo(elf, Is + i, I); |
| 117 | if (next != I->address) |
| 118 | { |
| 119 | // [HEURISTIC] This is the first instruction after a "gap" in the |
| 120 | // executable code. Thus, something probably jumps here, so is |
| 121 | // considered a jump target. |
| 122 | DEBUG(targets, I->address, "Entry : %p", (void *)I->address); |
| 123 | addTarget(I->address, TARGET_ENTRY, targets); |
| 124 | } |
| 125 | next = I->address + I->size; |
| 126 | |
| 127 | intptr_t target = INTPTR_MIN; |
| 128 | bool call = false; |
| 129 | switch (I->mnemonic) |
| 130 | { |
| 131 | case MNEMONIC_MOV: case MNEMONIC_PUSH: |
| 132 | if (pic || I->op[0].type != OPTYPE_IMM) |
| 133 | continue; |
| 134 | |
| 135 | // [HEURISTIC] This instruction may be moving a jump target |
| 136 | // into another location for later use. Thus, we consider the |
| 137 | // immediate value to be a target if it happens to point to a |
| 138 | // valid instruction. |
| 139 | // |
| 140 | // [HEURISTIC] The target is assumed to be a function. |
| 141 | target = (intptr_t)I->op[0].imm; |
| 142 | if (findInstr(Is, size, target) >= 0) |
| 143 | { |
| 144 | DEBUG(targets, target, "Load : %p", (void *)target); |
| 145 | addTarget(target, TARGET_INDIRECT | TARGET_FUNCTION, |
| 146 | targets); |
| 147 | } |
| 148 | continue; |
| 149 | |
| 150 | case MNEMONIC_LEA: |
| 151 | if (I->op[0].type != OPTYPE_MEM || |
| 152 | I->op[0].mem.base != REGISTER_RIP) |
| 153 | continue; |
| 154 | |
| 155 | // [HEURISTIC] Similar to the "mov" case but for PIC. |
| 156 | target = (intptr_t)I->address + (intptr_t)I->size + |
| 157 | (intptr_t)I->op[0].mem.disp; |
| 158 | if (findInstr(Is, size, target) >= 0) |
| 159 | { |
| 160 | DEBUG(targets, target, "Load : %p", (void *)target); |
| 161 | addTarget(target, TARGET_INDIRECT | TARGET_FUNCTION, |
| 162 | targets); |
| 163 | } |
| 164 | else |
| 165 | { |
no test coverage detected