From 66665f1c62163546617a42617db485ed6d5e214f Mon Sep 17 00:00:00 2001 From: norly Date: Sun, 10 Feb 2013 18:39:15 +0000 Subject: [PATCH] Model to ELF (writing) support, copy functionality --- include/libelfu/model.h | 2 + include/options.h | 2 +- src/main.c | 24 ++++++--- src/model/toFile.c | 115 ++++++++++++++++++++++++++++++++++++++++ src/options.c | 6 ++- 5 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 src/model/toFile.c diff --git a/include/libelfu/model.h b/include/libelfu/model.h index 05f31ca..aaf754f 100644 --- a/include/libelfu/model.h +++ b/include/libelfu/model.h @@ -47,4 +47,6 @@ ElfuPhdr* elfu_modelFromPhdr(GElf_Phdr *phdr); ElfuScn* elfu_modelFromSection(Elf_Scn *scn); ElfuElf* elfu_modelFromElf(Elf *e); +void elfu_modelToElf(ElfuElf *me, Elf *e); + #endif diff --git a/include/options.h b/include/options.h index ddd44be..c43c811 100644 --- a/include/options.h +++ b/include/options.h @@ -8,7 +8,7 @@ typedef struct { int printHeader; int printSegments; int printSections; - int model; + int copy; } CLIOpts; diff --git a/src/main.c b/src/main.c index 87b47ef..bd6d294 100644 --- a/src/main.c +++ b/src/main.c @@ -59,14 +59,26 @@ int main(int argc, char **argv) } - /* Generate a memory model of the file */ - if (opts.model) { - ElfuElf *me; + /* Copy the input ELF to the output file */ + if (!opts.fnOutput) { + if (opts.copy) { + fprintf(stderr, "Error: Missing output file name for requested operation.\n"); + } + } else { + if (opts.copy) { + ElfuElf *me; + + me = elfu_modelFromElf(hIn.e); + + if (me) { + printf("Model successfully loaded.\n"); - me = elfu_modelFromElf(hIn.e); + elfu_modelToElf(me, hOut.e); - if (me) { - printf("Model successfully loaded.\n"); + printf("Model converted to ELF, ready to be written.\n"); + } else { + printf("Failed to load model.\n"); + } } } diff --git a/src/model/toFile.c b/src/model/toFile.c new file mode 100644 index 0000000..294cfe4 --- /dev/null +++ b/src/model/toFile.c @@ -0,0 +1,115 @@ +#include +#include + +#include +#include + +#include + + + +static void elfu_modelToPhdrs(ElfuElf *me, Elf *e) +{ + ElfuPhdr *mp; + size_t i; + + /* Count PHDRs */ + i = 0; + for (mp = me->phdrList.cqh_first; + mp != (void *)&me->phdrList; + mp = mp->elem.cqe_next) { + i++; + } + + if (!gelf_newphdr(e, i)) { + fprintf(stderr, "gelf_newphdr() failed: %s\n", elf_errmsg(-1)); + } + + /* Copy PHDRs */ + i = 0; + for (mp = me->phdrList.cqh_first; + mp != (void *)&me->phdrList; + mp = mp->elem.cqe_next) { + if (!gelf_update_phdr (e, i, &mp->phdr)) { + fprintf(stderr, "gelf_update_phdr() failed: %s\n", elf_errmsg(-1)); + } + + i++; + } +} + + + +static void elfu_modelToSection(ElfuScn *ms, Elf *e) +{ + Elf_Scn *scnOut; + + scnOut = elf_newscn(e); + if (!scnOut) { + fprintf(stderr, "elf_newscn() failed: %s\n", elf_errmsg(-1)); + return; + } + + + /* SHDR */ + if (!gelf_update_shdr(scnOut, &ms->shdr)) { + fprintf(stderr, "gelf_update_shdr() failed: %s\n", elf_errmsg(-1)); + } + + + /* Data */ + ElfuData *md; + for (md = ms->dataList.cqh_first; + md != (void *)&ms->dataList; + md = md->elem.cqe_next) { + Elf_Data *dataOut = elf_newdata(scnOut); + if (!dataOut) { + fprintf(stderr, "elf_newdata() failed: %s\n", elf_errmsg(-1)); + } + + dataOut->d_align = md->data.d_align; + dataOut->d_buf = md->data.d_buf; + dataOut->d_off = md->data.d_off; + dataOut->d_type = md->data.d_type; + dataOut->d_size = md->data.d_size; + dataOut->d_version = md->data.d_version; + } +} + + + + + +void elfu_modelToElf(ElfuElf *me, Elf *e) +{ + ElfuScn *ms; + + /* We control the ELF file's layout now. */ + /* tired's libelf also offers ELF_F_LAYOUT_OVERLAP for overlapping sections. */ + elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT); + + + /* EHDR */ + if (!gelf_newehdr(e, me->elfclass)) { + fprintf(stderr, "gelf_newehdr() failed: %s\n", elf_errmsg(-1)); + } + + if (!gelf_update_ehdr(e, &me->ehdr)) { + fprintf(stderr, "gelf_update_ehdr() failed: %s\n", elf_errmsg(-1)); + } + + + /* Sections */ + for (ms = me->scnList.cqh_first; + ms != (void *)&me->scnList; + ms = ms->elem.cqe_next) { + elfu_modelToSection(ms, e); + } + + + /* PHDRs */ + elfu_modelToPhdrs(me, e); + + + elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY); +} diff --git a/src/options.c b/src/options.c index 42637f0..3975bad 100644 --- a/src/options.c +++ b/src/options.c @@ -17,6 +17,8 @@ static void printUsage(char *progname) " --print-header Print ELF header\n" " --print-segments Print program headers\n" " --print-sections Print sections\n" + "\n" + " --copy Copy input to output\n" "\n"); } @@ -34,7 +36,7 @@ void parseOptions(CLIOpts *opts, int argc, char **argv) {"print-header", 0, 0, 10001}, {"print-segments", 0, 0, 10002}, {"print-sections", 0, 0, 10003}, - {"model", 0, 0, 10004}, + {"copy", 0, 0, 10004}, {NULL, 0, NULL, 0} }; @@ -57,7 +59,7 @@ void parseOptions(CLIOpts *opts, int argc, char **argv) opts->printSections = 1; break; case 10004: - opts->model = 1; + opts->copy = 1; break; case '?': default: -- 2.30.2