#include <stdio.h>; #include <stdlib.h>; #include <unistd.h>; #include <fcntl.h>; #include <elf.h>; #include <stdarg.h>; #include <string.h>;
void die(const char *fmt, ...) { va_list ap;
va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fputc('\n', stderr); exit(1); }
#define PAGE_SIZE 4096
static char shstr[] = "\0" ".symtab\0" ".strtab\0" ".shstrtab\0" ".interp\0" ".hash\0" ".dynsym\0" ".dynstr\0" ".rel.got\0" ".rel.bss\0" ".rel.plt\0" ".init\0" ".plt\0" ".text\0" ".fini\0" ".rodata\0" ".data\0" ".ctors\0" ".dtors\0" ".got\0" ".dynamic\0" ".bss\0" ".comment\0" ".note" ;
char *xget(int fd, int off, int sz) { char *buf;
if (lseek(fd, off, SEEK_SET) < 0) die("Seek error"); buf = (char *)malloc(sz); if (buf == NULL) die("No memory"); if (read(fd, buf, sz) != sz) die("Read error"); return buf; }
void do_elf_checks(Elf32_Ehdr *ehdr) { if (strncmp(ehdr->e_ident, ELFMAG, SELFMAG)) die("File not ELF"); if (ehdr->e_type != ET_CORE) die("ELF type not ET_CORE"); //if (ehdr->e_machine != EM_386 && ehdr->e_machine != EM_486) //die("ELF machine type not EM_386 or EM_486"); if (ehdr->e_version != EV_CURRENT) die("ELF version not current"); }
int main(int argc, char *argv[]) { Elf32_Ehdr ehdr, *core_ehdr; Elf32_Phdr *phdr, *core_phdr, *tmpphdr; Elf32_Shdr shdr; char *core; char *data[2], *core_data[3]; int prog[2], core_prog[3]; int in, out; int i, p; int plen;
if (argc >2) die("usage: %s [core-file]");
if (argc == 2) core = argv[1]; else core = "core.3665"; in = open(core, O_RDONLY); if (in < 0) die("Coudln't open file: %s", core);
if (read(in, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) die("Read error"); do_elf_checks(&ehdr);
if (lseek(in, ehdr.e_phoff, SEEK_SET) < 0) die("Seek error"); phdr = (Elf32_Phdr *)malloc(plen = sizeof(Elf32_Phdr)*ehdr.e_phnum); if (read(in, phdr, plen) != plen) die("Read error");
for (i = 0; i < ehdr.e_phnum; i++) printf("0x%x - 0x%x (%i)\n", phdr[i].p_vaddr, phdr[i].p_vaddr + phdr[i].p_memsz, phdr[i].p_memsz);
/* copy segments (in memory)
prog/data[0] ... text prog/data[1] ... data prog/data[2] ... dynamic */ for (i = 0, p = 0; i < ehdr.e_phnum; i++) { if ( phdr[i].p_vaddr >= 0x8000000 && phdr[i].p_type == PT_LOAD ) { prog[p] = i; if (p == 1) break; ++p; } } if (i == ehdr.e_phnum) die("Couldnt find TEXT/DATA");
for (i = 0; i < 2; i++) data[i] = xget( in, phdr[prog[i]].p_offset, (phdr[prog[i]].p_memsz + 4095) & 4095 );
core_ehdr = (Elf32_Ehdr *)&data[0][0]; core_phdr = (Elf32_Phdr *)&data[0][core_ehdr->e_phoff];
for (i = 0, p = 0; i < core_ehdr->e_phnum; i++) { if (core_phdr[i].p_type == PT_LOAD) { core_prog[p] = i; if (p == 0) { core_data[0] = &data[0][0]; } else { core_data[1] = &data[1][ (core_phdr[i].p_vaddr & 4095) ]; break; } ++p; } } if (i == core_ehdr->e_phnum) die("No TEXT and DATA segment"); for (i = 0; i < core_ehdr->e_phnum; i++) { if (core_phdr[i].p_type == PT_DYNAMIC) { core_prog[2] = i; core_data[2] = &data[1][64]; break; } } if (i == core_ehdr->e_phnum) die("No DYNAMIC segment");
out = open("a.out", O_WRONLY | O_CREAT | O_TRUNC); if (out < 0) die("Coudln't open file: %s", "a.out");
core_ehdr->e_shoff = core_phdr[core_prog[2]].p_offset + core_phdr[core_prog[2]].p_filesz + sizeof(shstr);
/* text data bss dynamic shstrtab */ core_ehdr->e_shnum = 6; core_ehdr->e_shstrndx = 5;
for (i = 0; i < 2; i++) { Elf32_Phdr *p = &core_phdr[core_prog[i]]; int sz = p->p_filesz;
if (lseek(out, p->p_offset, SEEK_SET) < 0) goto cleanup; if (write(out, core_data[i], sz) != sz) goto cleanup; }
if (write(out, shstr, sizeof(shstr)) != sizeof(shstr)) goto cleanup;
memset(&shdr, 0, sizeof(shdr)); if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;
/* text section */ tmpphdr = &core_phdr[core_prog[0]];
shdr.sh_name = 95; shdr.sh_type = SHT_PROGBITS; shdr.sh_addr = tmpphdr->p_vaddr; shdr.sh_offset = 0; shdr.sh_size = tmpphdr->p_filesz; shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; shdr.sh_link = 0; shdr.sh_info = 0; shdr.sh_addralign = 16; shdr.sh_entsize = 0;
if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;
/* data section */ tmpphdr = &core_phdr[core_prog[1]];
shdr.sh_name = 115; shdr.sh_type = SHT_PROGBITS; shdr.sh_addr = tmpphdr->p_vaddr; shdr.sh_offset = tmpphdr->p_offset; shdr.sh_size = tmpphdr->p_filesz; shdr.sh_flags = SHF_ALLOC | SHF_WRITE; shdr.sh_link = 0; shdr.sh_info = 0; shdr.sh_addralign = 4; shdr.sh_entsize = 0;
if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;
/* dynamic section */ for (i = 0; i < core_ehdr->e_phnum; i++) { if (core_phdr[i].p_type == PT_DYNAMIC) { tmpphdr = &core_phdr[i]; break; } }
shdr.sh_name = 140; shdr.sh_type = SHT_PROGBITS; shdr.sh_addr = tmpphdr->p_vaddr; shdr.sh_offset = tmpphdr->p_offset; shdr.sh_size = tmpphdr->p_memsz; shdr.sh_flags = SHF_ALLOC; shdr.sh_link = 0; shdr.sh_info = 0; shdr.sh_addralign = 4; shdr.sh_entsize = 8;
if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;
/* bss section */ shdr.sh_name = 149; shdr.sh_type = SHT_PROGBITS; shdr.sh_addr = tmpphdr->p_vaddr + tmpphdr->p_filesz; shdr.sh_offset = tmpphdr->p_offset + tmpphdr->p_filesz; shdr.sh_size = tmpphdr->p_memsz - tmpphdr->p_filesz; shdr.sh_flags = SHF_ALLOC; shdr.sh_link = 0; shdr.sh_info = 0; shdr.sh_addralign = 1; shdr.sh_entsize = 0;
if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;
/* shstrtab */
shdr.sh_name = 17; shdr.sh_type = SHT_STRTAB; shdr.sh_addr = 0; shdr.sh_offset = core_ehdr->e_shoff - sizeof(shstr); shdr.sh_size = sizeof(shstr); shdr.sh_flags = 0; shdr.sh_link = 0; shdr.sh_info = 0; shdr.sh_addralign = 1; shdr.sh_entsize = 0;
if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;
return 0;
cleanup: unlink("a.out"); die("Error writing file: %s", "a.out"); return 1; /* not reached */ } |
|