MCPcopy Create free account
hub / github.com/GJDuck/e9patch / replaceInitFini

Function replaceInitFini

src/e9patch/e9elf.cpp:398–443  ·  view source on GitHub ↗

* Replace an init/fini function. */

Source from the content-addressed store, hash-verified

396 * Replace an init/fini function.
397 */
398intptr_t replaceInitFini(Binary *B, Elf64_Dyn *dyn_fn,
399 const Elf64_Dyn *dyn_fn_array, size_t dyn_fn_arraysz,
400 const Elf64_Dyn *dyn_rela, size_t dyn_relasz, intptr_t entry)
401{
402 uint8_t *data = B->patched.bytes;
403 if (dyn_fn != nullptr)
404 {
405 intptr_t old = (intptr_t)dyn_fn->d_un.d_ptr;
406 dyn_fn->d_un.d_ptr = (Elf64_Addr)entry;
407 return old;
408 }
409 else if (dyn_fn_array != nullptr && dyn_fn_arraysz > 0)
410 {
411 intptr_t ptr = (intptr_t)dyn_fn_array->d_un.d_ptr;
412 intptr_t offset = addrToOffset(B, ptr, ptr);
413 if (offset < 0)
414 return INTPTR_MIN;
415 Elf64_Addr *fns = (Elf64_Addr *)(data + offset);
416 intptr_t old = (intptr_t)fns[0];
417 fns[0] = (Elf64_Addr)entry;
418 if (dyn_rela != nullptr && dyn_relasz > 0)
419 {
420 // fns[0] may be subject to a relocation:
421 intptr_t rela_ptr = (intptr_t)dyn_rela->d_un.d_ptr;
422 intptr_t rela_offset = addrToOffset(B, rela_ptr,
423 rela_ptr + dyn_relasz);
424 if (rela_offset < 0)
425 return old;
426 size_t rela_size = dyn_relasz / sizeof(Elf64_Rela);
427 Elf64_Rela *rela = (Elf64_Rela *)(B->patched.bytes + rela_offset);
428 for (size_t i = 0; i < rela_size; i++)
429 {
430 if (ELF64_R_TYPE(rela[i].r_info) != R_X86_64_RELATIVE)
431 continue;
432 if ((intptr_t)rela[i].r_offset == ptr)
433 {
434 old = rela[i].r_addend;
435 rela[i].r_addend = (Elf64_Addr)entry;
436 break;
437 }
438 }
439 }
440 return old;
441 }
442 return INTPTR_MIN;
443}
444
445/*
446 * Emit the (modified) ELF binary.

Callers 1

emitElfFunction · 0.85

Calls 1

addrToOffsetFunction · 0.70

Tested by

no test coverage detected