diff options
Diffstat (limited to 'libdwfl/elf-from-memory.c')
-rw-r--r-- | libdwfl/elf-from-memory.c | 81 |
1 files changed, 34 insertions, 47 deletions
diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c index c54c1b99..933ab864 100644 --- a/libdwfl/elf-from-memory.c +++ b/libdwfl/elf-from-memory.c | |||
@@ -223,61 +223,48 @@ elf_from_remote_memory (GElf_Addr ehdr_vma, | |||
223 | bool found_base = false; | 223 | bool found_base = false; |
224 | Elf32_Phdr (*p32)[phnum] = phdrsp; | 224 | Elf32_Phdr (*p32)[phnum] = phdrsp; |
225 | Elf64_Phdr (*p64)[phnum] = phdrsp; | 225 | Elf64_Phdr (*p64)[phnum] = phdrsp; |
226 | switch (ehdr.e32.e_ident[EI_CLASS]) | 226 | |
227 | if (class32) | ||
227 | { | 228 | { |
228 | /* Sanity checks segments and calculates segment_end, | 229 | if (! elf32_xlatetom (&xlateto, &xlatefrom, ehdr.e32.e_ident[EI_DATA])) |
229 | segments_end, segments_end_mem and loadbase (if not | 230 | goto libelf_error; |
230 | found_base yet). Returns true if sanity checking failed, | 231 | } |
231 | false otherwise. */ | 232 | else |
232 | inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset, | 233 | { |
233 | GElf_Xword filesz, GElf_Xword memsz) | 234 | if (! elf64_xlatetom (&xlateto, &xlatefrom, ehdr.e64.e_ident[EI_DATA])) |
234 | { | 235 | goto libelf_error; |
235 | /* Sanity check the segment load aligns with the pagesize. */ | 236 | } |
236 | if (((vaddr - offset) & (pagesize - 1)) != 0) | ||
237 | return true; | ||
238 | 237 | ||
239 | GElf_Off segment_end = ((offset + filesz + pagesize - 1) | 238 | for (uint_fast16_t i = 0; i < phnum; ++i) |
240 | & -pagesize); | 239 | { |
240 | GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type; | ||
241 | 241 | ||
242 | if (segment_end > (GElf_Off) contents_size) | 242 | if (type != PT_LOAD) |
243 | contents_size = segment_end; | 243 | continue; |
244 | 244 | ||
245 | if (!found_base && (offset & -pagesize) == 0) | 245 | GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr; |
246 | { | 246 | GElf_Xword memsz = class32 ? (*p32)[i].p_memsz : (*p64)[i].p_memsz; |
247 | loadbase = ehdr_vma - (vaddr & -pagesize); | 247 | GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset; |
248 | found_base = true; | 248 | GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz; |
249 | } | ||
250 | 249 | ||
251 | segments_end = offset + filesz; | 250 | /* Sanity check the segment load aligns with the pagesize. */ |
252 | segments_end_mem = offset + memsz; | 251 | if (((vaddr - offset) & (pagesize - 1)) != 0) |
253 | return false; | 252 | goto bad_elf; |
254 | } | ||
255 | 253 | ||
256 | case ELFCLASS32: | 254 | GElf_Off segment_end = ((offset + filesz + pagesize - 1) |
257 | if (elf32_xlatetom (&xlateto, &xlatefrom, | 255 | & -pagesize); |
258 | ehdr.e32.e_ident[EI_DATA]) == NULL) | ||
259 | goto libelf_error; | ||
260 | for (uint_fast16_t i = 0; i < phnum; ++i) | ||
261 | if ((*p32)[i].p_type == PT_LOAD) | ||
262 | if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset, | ||
263 | (*p32)[i].p_filesz, (*p32)[i].p_memsz)) | ||
264 | goto bad_elf; | ||
265 | break; | ||
266 | 256 | ||
267 | case ELFCLASS64: | 257 | if (segment_end > (GElf_Off) contents_size) |
268 | if (elf64_xlatetom (&xlateto, &xlatefrom, | 258 | contents_size = segment_end; |
269 | ehdr.e64.e_ident[EI_DATA]) == NULL) | ||
270 | goto libelf_error; | ||
271 | for (uint_fast16_t i = 0; i < phnum; ++i) | ||
272 | if ((*p64)[i].p_type == PT_LOAD) | ||
273 | if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset, | ||
274 | (*p64)[i].p_filesz, (*p64)[i].p_memsz)) | ||
275 | goto bad_elf; | ||
276 | break; | ||
277 | 259 | ||
278 | default: | 260 | if (!found_base && (offset & -pagesize) == 0) |
279 | abort (); | 261 | { |
280 | break; | 262 | loadbase = ehdr_vma - (vaddr & -pagesize); |
263 | found_base = true; | ||
264 | } | ||
265 | |||
266 | segments_end = offset + filesz; | ||
267 | segments_end_mem = offset + memsz; | ||
281 | } | 268 | } |
282 | 269 | ||
283 | /* Trim the last segment so we don't bother with zeros in the last page | 270 | /* Trim the last segment so we don't bother with zeros in the last page |