#include #include #include #include void elfu_copySegments1(Elf *eo, Elf *ei) { size_t i, n; if (elf_getphdrnum(ei, &n)) { fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1)); } if (!gelf_newphdr(eo, n)) { fprintf(stderr, "gelf_newphdr() failed: %s\n", elf_errmsg(-1)); } for (i = 0; i < n; i++) { GElf_Phdr phdr, phdrOut; if (gelf_getphdr(ei, i, &phdr) != &phdr) { fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1)); break; } if (gelf_getphdr(eo, i, &phdrOut) != &phdrOut) { fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1)); break; } phdrOut.p_type = phdr.p_type; /* p_offset */ phdrOut.p_vaddr = phdr.p_vaddr; phdrOut.p_paddr = phdr.p_paddr; /* p_filesz */ /* p_memsz */ phdrOut.p_flags = phdr.p_flags; phdrOut.p_align = phdr.p_align; if (!gelf_update_phdr (eo, i, &phdrOut)) { fprintf(stderr, "gelf_update_ehdr() failed: %s\n", elf_errmsg(-1)); } } /* Tell libelf that phdrs have changed */ elf_flagphdr(eo, ELF_C_SET, ELF_F_DIRTY); } void elfu_copySegments2(Elf *eo, Elf *ei) { size_t i, n; if (elf_getphdrnum(ei, &n)) { fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1)); } for (i = 0; i < n; i++) { GElf_Phdr phdr, phdrOut; if (gelf_getphdr(ei, i, &phdr) != &phdr) { fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1)); break; } if (gelf_getphdr(eo, i, &phdrOut) != &phdrOut) { fprintf(stderr, "gelf_getphdr() failed for #%d: %s\n", i, elf_errmsg(-1)); break; } /* Start of segment */ if (phdr.p_type == PT_PHDR) { /* Skip PHDR entries and fix them up later */ } else if (phdr.p_offset == 0) { /* The text segment usually loads the whole ELF header */ phdrOut.p_offset = 0; } else { /* Try to guess the start of the segment */ Elf_Scn *scn, *scnOut; GElf_Shdr shdr, shdrOut; scn = elfu_firstSectionInSegment(ei, &phdr); if (!scn) { fprintf(stderr, "elfu_firstSectionInSegment() failed for segment #%d\n", i); continue; } if (gelf_getshdr(scn, &shdr) != &shdr) { fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1)); } if (phdr.p_offset < shdr.sh_offset) { fprintf(stderr, "elfu_copySegments2: Segment #%d starts before first contained section.\n", i); } scnOut = elf_getscn(eo, elf_ndxscn(scn)); if (!scnOut) { fprintf(stderr, "elf_getscn() failed: %s\n", elf_errmsg(-1)); } if (gelf_getshdr(scnOut, &shdrOut) != &shdrOut) { fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1)); } phdrOut.p_offset = shdrOut.sh_offset; } /* File length of segment */ if (phdr.p_type == PT_PHDR) { /* Skip PHDR entries and fix them up later */ } else if (phdr.p_memsz == 0) { phdrOut.p_filesz = 0; phdrOut.p_memsz = 0; } else { /* Try to guess the end of the segment */ Elf_Scn *scn, *scnOut; GElf_Shdr shdr, shdrOut; scn = elfu_lastSectionInSegment(ei, &phdr); if (!scn) { fprintf(stderr, "elfu_lastSectionInSegment() failed for segment #%d\n", i); continue; } if (gelf_getshdr(scn, &shdr) != &shdr) { fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1)); } if (phdr.p_offset + phdr.p_filesz > shdr.sh_offset + shdr.sh_size) { fprintf(stderr, "elfu_copySegments2: Segment #%d ends after last contained section.\n", i); } scnOut = elf_getscn(eo, elf_ndxscn(scn)); if (!scnOut) { fprintf(stderr, "elf_getscn() failed: %s\n", elf_errmsg(-1)); } if (gelf_getshdr(scnOut, &shdrOut) != &shdrOut) { fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1)); } phdrOut.p_filesz = shdrOut.sh_offset - phdrOut.p_offset; if (shdrOut.sh_type != SHT_NOBITS) { phdrOut.p_filesz += shdrOut.sh_size; } phdrOut.p_memsz = shdrOut.sh_offset - phdrOut.p_offset + shdrOut.sh_size; } if (!gelf_update_phdr (eo, i, &phdrOut)) { fprintf(stderr, "gelf_update_ehdr() failed: %s\n", elf_errmsg(-1)); } } /* Tell libelf that phdrs have changed */ elf_flagphdr(eo, ELF_C_SET, ELF_F_DIRTY); }