diff options
author | norly <ny-git@enpas.org> | 2013-02-10 18:39:15 +0000 |
---|---|---|
committer | norly <ny-git@enpas.org> | 2013-02-11 01:24:36 +0000 |
commit | 66665f1c62163546617a42617db485ed6d5e214f (patch) | |
tree | 06d41236e3845f07873405a1803cda197212fab6 /src/model/toFile.c | |
parent | feb8656ebe8c24137b179e1fc347c4fd3bf4bcd4 (diff) |
Model to ELF (writing) support, copy functionality
Diffstat (limited to 'src/model/toFile.c')
-rw-r--r-- | src/model/toFile.c | 115 |
1 files changed, 115 insertions, 0 deletions
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 <stdio.h> +#include <stdlib.h> + +#include <libelf.h> +#include <gelf.h> + +#include <libelfu/libelfu.h> + + + +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); +} |