4 #include <libelfu/libelfu.h>
9 * Insert space at a given position in the file by moving everything
10 * after it towards the end of the file, and everything before it
11 * towards lower memory regions where it is mapped.
13 * off must not be in the middle of any data structure, such as
14 * PHDRs, SHDRs, or sections. Behaviour is undefined if it is.
16 * PHDRs will be patched such that everything AFTER off is mapped to
17 * the same address in memory, and everything BEFORE it is shifted to
18 * lower addresses, making space for the new data in-between.
20 GElf_Xword elfu_mInsertBefore(ElfuElf *me, GElf_Off off, GElf_Xword size)
27 // TODO: Take p_align into account
29 /* Move SHDRs and PHDRs */
30 if (me->ehdr.e_shoff >= off) {
31 me->ehdr.e_shoff += size;
34 if (me->ehdr.e_phoff >= off) {
35 me->ehdr.e_phoff += size;
38 /* Patch PHDRs to include new data */
39 CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
40 GElf_Off end = mp->phdr.p_offset + mp->phdr.p_filesz;
42 if (mp->phdr.p_offset >= off) {
43 /* Insertion before PHDR's content, so it's just shifted */
44 mp->phdr.p_offset += size;
46 /* mp->phdr.p_offset < off */
49 /* Mark this as a modified area */
51 /* Insertion in the middle of PHDR, so let it span the new data */
52 mp->phdr.p_filesz += size;
53 mp->phdr.p_memsz += size;
54 mp->phdr.p_vaddr -= size;
55 mp->phdr.p_paddr -= size;
57 /* Insertion after PHDR's content, so it may need to be
58 remapped. This will happen in a second pass.
64 /* For each LOAD header, find clashing headers that need to be
65 remapped to lower memory areas.
67 CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
68 if (mp->phdr.p_type == PT_LOAD) {
71 CIRCLEQ_FOREACH(mp2, &me->phdrList, elem) {
72 if (mp2->phdr.p_type != PT_LOAD
73 && mp2->phdr.p_offset + mp2->phdr.p_filesz <= off) {
74 /* The PHDR ends in the file before the injection site */
75 GElf_Off vend1 = mp->phdr.p_vaddr + mp->phdr.p_memsz;
76 GElf_Off pend1 = mp->phdr.p_paddr + mp->phdr.p_memsz;
77 GElf_Off vend2 = mp2->phdr.p_vaddr + mp2->phdr.p_memsz;
78 GElf_Off pend2 = mp2->phdr.p_paddr + mp2->phdr.p_memsz;
80 /* If mp and mp2 now overlap in memory */
81 if ((mp2->phdr.p_vaddr < vend1 && vend2 > mp->phdr.p_vaddr)
82 || (mp2->phdr.p_paddr < pend1 && pend2 > mp->phdr.p_paddr)) {
83 /* Move mp2 down in memory, as mp has been resized.
84 Maintaining the relative offset between them is the best
85 guess at maintaining consistency.
87 mp2->phdr.p_vaddr -= size;
88 mp2->phdr.p_paddr -= size;
95 /* Move the sections themselves */
96 CIRCLEQ_FOREACH(ms, &me->scnList, elem) {
97 if (ms->shdr.sh_offset >= off) {
98 ms->shdr.sh_offset += size;
100 /* sh_offset < off */
102 /* If this was in a LOAD segment, it has been adjusted there
103 and this synchronises it.
104 If not, it doesn't matter anyway.
106 ms->shdr.sh_addr -= size;