3 #include <libelfu/libelfu.h>
5 int elfu_eCheck(Elf *e)
9 GElf_Phdr *phdrs = NULL;
10 GElf_Shdr *shdrs = NULL;
11 size_t i, j, numPhdr, numShdr;
16 elfclass = gelf_getclass(e);
17 if (elfclass == ELFCLASSNONE) {
18 ELFU_WARNELF("getclass");
22 if (!gelf_getehdr(e, &ehdr)) {
23 ELFU_WARNELF("gelf_getehdr");
27 if (elf_getphdrnum(e, &numPhdr)) {
28 ELFU_WARNELF("elf_getphdrnum");
32 if (elf_getshdrnum(e, &numShdr)) {
33 ELFU_WARNELF("elf_getshdrnum");
39 phdrs = malloc(numPhdr * sizeof(GElf_Phdr));
41 ELFU_WARN("elfu_eCheck: malloc() failed for phdrs.\n");
45 /* Attempt to load all PHDRs at once to catch any errors early */
46 for (i = 0; i < numPhdr; i++) {
48 if (gelf_getphdr(e, i, &phdr) != &phdr) {
49 ELFU_WARN("gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1));
56 /* Check that LOAD PHDR memory ranges do not overlap, and that others
57 * are either fully contained in a LOAD range, or not at all. */
58 for (i = 0; i < numPhdr; i++) {
59 if (phdrs[i].p_type != PT_LOAD) {
63 for (j = 0; j < numPhdr; j++) {
64 if (j == i || phdrs[j].p_type != PT_LOAD) {
68 if (OVERLAPPING(phdrs[i].p_vaddr, phdrs[i].p_memsz,
69 phdrs[j].p_vaddr, phdrs[j].p_memsz)) {
70 if (phdrs[j].p_type == PT_LOAD) {
71 ELFU_WARN("elfu_eCheck: Found LOAD PHDRs that overlap in memory.\n");
73 } else if (!FULLY_OVERLAPPING(phdrs[i].p_vaddr, phdrs[i].p_memsz,
74 phdrs[j].p_vaddr, phdrs[j].p_memsz)) {
75 ELFU_WARN("elfu_eCheck: PHDRs %d and %d partially overlap in memory.\n", i, j);
85 /* SHDRs should not overlap with PHDRs. */
86 if (OVERLAPPING(ehdr.e_shoff, numShdr * ehdr.e_shentsize,
87 ehdr.e_phoff, numPhdr * ehdr.e_phentsize)) {
88 ELFU_WARN("elfu_eCheck: SHDRs overlap with PHDRs.\n");
92 shdrs = malloc(numShdr * sizeof(GElf_Shdr));
94 ELFU_WARN("elfu_eCheck: malloc() failed for shdrs.\n");
98 /* Attempt to load all SHDRs at once to catch any errors early */
99 for (i = 1; i < numShdr; i++) {
103 scn = elf_getscn(e, i);
105 ELFU_WARN("elf_getscn() failed for #%d: %s\n", i, elf_errmsg(-1));
108 if (gelf_getshdr(scn, &shdr) != &shdr) {
109 ELFU_WARNELF("gelf_getshdr");
117 /* Check that Section memory ranges do not overlap.
118 * NB: Section 0 is reserved and thus ignored. */
119 for (i = 1; i < numShdr; i++) {
120 /* Section should not overlap with EHDR. */
121 if (shdrs[i].sh_offset == 0) {
122 ELFU_WARN("elfu_eCheck: Section %d overlaps with EHDR.\n", i);
126 /* Section should not overlap with PHDRs. */
127 if (OVERLAPPING(shdrs[i].sh_offset, SCNFILESIZE(&shdrs[i]),
128 ehdr.e_phoff, numPhdr * ehdr.e_phentsize)) {
129 ELFU_WARN("elfu_eCheck: Section %d overlaps with PHDR.\n", i);
133 /* Section should not overlap with SHDRs. */
134 if (OVERLAPPING(shdrs[i].sh_offset, SCNFILESIZE(&shdrs[i]),
135 ehdr.e_shoff, numShdr * ehdr.e_shentsize)) {
136 ELFU_WARN("elfu_eCheck: Section %d overlaps with SHDRs.\n", i);
140 for (j = 1; j < numShdr; j++) {
145 /* Sections must not overlap in memory. */
146 if (shdrs[i].sh_addr != 0
147 && shdrs[j].sh_addr != 0
148 && OVERLAPPING(shdrs[i].sh_addr, shdrs[i].sh_size,
149 shdrs[j].sh_addr, shdrs[j].sh_size)) {
150 ELFU_WARN("elfu_eCheck: Sections %d and %d overlap in memory.\n", i, j);
154 /* Sections must not overlap in file. */
155 if (OVERLAPPING(shdrs[i].sh_offset, SCNFILESIZE(&shdrs[i]),
156 shdrs[j].sh_offset, SCNFILESIZE(&shdrs[j]))) {
157 ELFU_WARN("elfu_eCheck: Sections %d and %d overlap in file.\n", i, j);
162 /* Section addr/offset should match parent PHDR.
163 * Find parent PHDR: */
164 for (j = 0; j < numPhdr; j++) {
165 if (PHDR_CONTAINS_SCN_IN_MEMORY(&phdrs[j], &shdrs[i])) {
166 GElf_Off shoff = phdrs[j].p_offset + (shdrs[i].sh_addr - phdrs[j].p_vaddr);
168 if (shdrs[i].sh_offset != shoff
169 || !PHDR_CONTAINS_SCN_IN_FILE(&phdrs[j], &shdrs[i])) {
170 ELFU_WARN("elfu_eCheck: Memory/file offsets/sizes are not congruent for SHDR %d, PHDR %d.\n", i, j);
176 /* sh_link members should not point to sections out of range. */
177 if (shdrs[i].sh_link >= numShdr) {
178 ELFU_WARN("elfu_eCheck: Bogus sh_link in SHDR %d.\n", i);
194 ELFU_WARN("elfu_eCheck: Errors found.\n");