Typos
[centaur.git] / src / model / expandNobits.c
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include <gelf.h>
7 #include <libelfu/libelfu.h>
8
9
10 void elfu_mExpandNobits(ElfuElf *me, GElf_Off off)
11 {
12   ElfuScn *ms;
13   ElfuPhdr *mp;
14   GElf_Xword expansionSize;
15
16   assert(me);
17
18   expansionSize = 0;
19
20   /* Find the maximum amount we need to expand by. Check PHDRs first */
21   CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
22     GElf_Off off2 = mp->phdr.p_offset;
23     GElf_Off end2 = mp->phdr.p_offset + mp->phdr.p_filesz;
24     if (end2 == off) {
25       GElf_Xword size2 = mp->phdr.p_memsz - mp->phdr.p_filesz;
26       if (size2 > expansionSize) {
27         expansionSize = size2;
28       }
29     } else if (end2 > off) {
30       if (off2 < off) {
31         /*
32          * Found a PHDR whose file contents overlaps with the section
33          * to be filled. This means that it relies on the NOBITS area
34          * being actually 0 bytes, and the expansion would ruin it.
35          */
36         fprintf(stderr, "mExpandNobits: Found PHDR spanning expansion offset. Aborting.\n");
37         return;
38       }
39     } else {
40       // end2 < off, and the PHDR is unaffected.
41       continue;
42     }
43   }
44
45   /* Now check SHDRs */
46   CIRCLEQ_FOREACH(ms, &me->scnList, elem) {
47     if (ms->shdr.sh_offset == off) {
48       if (ms->shdr.sh_type == SHT_NOBITS) {
49         if (ms->shdr.sh_size > expansionSize) {
50           expansionSize = ms->shdr.sh_size;
51         }
52       }
53     }
54   }
55
56
57
58   /* Expand! */
59
60
61   /* Move all following PHDR offsets further down the file. */
62   CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
63     GElf_Off off2 = mp->phdr.p_offset;
64     GElf_Off end2 = mp->phdr.p_offset + mp->phdr.p_filesz;
65
66     if (off2 >= off) {
67       mp->phdr.p_offset += expansionSize;
68     } else {
69       if (end2 == off) {
70         /* This PHDR now has corresponding bytes in the file for every
71          * byte in memory. */
72         mp->phdr.p_filesz = mp->phdr.p_memsz;
73       }
74     }
75   }
76
77   /* Move the following sections */
78   CIRCLEQ_FOREACH(ms, &me->scnList, elem) {
79     if (ms->shdr.sh_offset >= off) {
80       if (ms->shdr.sh_offset > off
81           || ms->shdr.sh_type != SHT_NOBITS) {
82         ms->shdr.sh_offset += expansionSize;
83       }
84     }
85   }
86
87   /* Move SHDR/PHDR tables */
88   if (me->ehdr.e_shoff >= off) {
89     me->ehdr.e_shoff += expansionSize;
90   }
91
92   if (me->ehdr.e_phoff >= off) {
93     me->ehdr.e_phoff += expansionSize;
94   }
95
96
97   /* Convert any NOBITS at off to PROGBITS */
98   CIRCLEQ_FOREACH(ms, &me->scnList, elem) {
99     if (ms->shdr.sh_offset == off) {
100       if (ms->shdr.sh_type == SHT_NOBITS) {
101         ms->data.d_buf = malloc(ms->shdr.sh_size);
102         memset(ms->data.d_buf, '\0', ms->shdr.sh_size);
103         if (!ms->data.d_buf) {
104           fprintf(stderr, "mExpandNobits: Could not allocate %jd bytes for NOBITS expansion.\n", ms->shdr.sh_size);
105         }
106
107         ms->data.d_align = 1;
108         ms->data.d_off  = 0;
109         ms->data.d_type = ELF_T_BYTE;
110         ms->data.d_size = ms->shdr.sh_size;
111         ms->data.d_version = elf_version(EV_NONE);
112
113         ms->shdr.sh_type = SHT_PROGBITS;
114       }
115     }
116   }
117 }