* Section analysis pass: find potential code pointers in data. */
| 251 | * Section analysis pass: find potential code pointers in data. |
| 252 | */ |
| 253 | static void CFGSectionAnalysis(const ELF *elf, bool pic, const char *name, |
| 254 | const Elf64_Shdr *shdr, const Instr *Is, size_t size, |
| 255 | const std::set<intptr_t> &tables, Targets &targets) |
| 256 | { |
| 257 | if ((shdr->sh_flags & SHF_EXECINSTR) != 0 || shdr->sh_addr == 0x0) |
| 258 | return; |
| 259 | |
| 260 | const uint8_t *sh_data = getELFData(elf) + shdr->sh_offset; |
| 261 | size_t sh_size = shdr->sh_size; |
| 262 | |
| 263 | if (!pic) |
| 264 | { |
| 265 | switch (shdr->sh_type) |
| 266 | { |
| 267 | case SHT_PROGBITS: case SHT_INIT_ARRAY: case SHT_FINI_ARRAY: |
| 268 | break; |
| 269 | default: |
| 270 | return; |
| 271 | } |
| 272 | |
| 273 | // Scan the data for absolute addresses. |
| 274 | auto bounds = getBounds<intptr_t>(sh_data, sh_data + sh_size); |
| 275 | bool call = true; |
| 276 | for (const intptr_t *p = bounds.first; p < bounds.second; p++) |
| 277 | { |
| 278 | intptr_t table = (intptr_t)shdr->sh_addr + |
| 279 | ((intptr_t)p - (intptr_t)sh_data); |
| 280 | if (tables.find(table) != tables.end()) |
| 281 | call = false; |
| 282 | intptr_t target = *p; |
| 283 | if (target != 0 && findInstr(Is, size, target) >= 0) |
| 284 | { |
| 285 | // "Probably" a jump target. |
| 286 | DEBUG(targets, target, "%s: %p%s", (call? "Data ": "JmpTbl"), |
| 287 | (void *)target, (call? " (F)": "")); |
| 288 | addTarget(target, |
| 289 | TARGET_INDIRECT | (call? TARGET_FUNCTION: 0), targets); |
| 290 | } |
| 291 | else |
| 292 | call = true; |
| 293 | } |
| 294 | return; |
| 295 | } |
| 296 | if (shdr->sh_type == SHT_PROGBITS && (shdr->sh_flags & SHF_WRITE) == 0) |
| 297 | { |
| 298 | // Scan the data for PIC-style jump tables. |
| 299 | // Note: We do this analysis even for non-PIC binaries. This is |
| 300 | // because it is possible that a non-PIC binary was compiled |
| 301 | // with -fPIC. |
| 302 | auto bounds = getBounds<int32_t>(sh_data, sh_data + sh_size); |
| 303 | for (const int32_t *p = bounds.first; p < bounds.second; p++) |
| 304 | { |
| 305 | intptr_t table = (intptr_t)shdr->sh_addr + |
| 306 | ((intptr_t)p - (intptr_t)sh_data); |
| 307 | auto i = tables.find(table); |
| 308 | if (i == tables.end()) |
| 309 | continue; |
| 310 |
no test coverage detected