diff options
Diffstat (limited to 'ext/libelf/gelf_ehdr.c')
-rw-r--r-- | ext/libelf/gelf_ehdr.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/ext/libelf/gelf_ehdr.c b/ext/libelf/gelf_ehdr.c new file mode 100644 index 000000000..c410f4a15 --- /dev/null +++ b/ext/libelf/gelf_ehdr.c @@ -0,0 +1,164 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <limits.h> + +#include <assert.h> +#include "gelf.h" +#include "libelf.h" +#include <string.h> + +#include "_libelf.h" + +Elf32_Ehdr * +elf32_getehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS32, 0)); +} + +Elf64_Ehdr * +elf64_getehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS64, 0)); +} + +GElf_Ehdr * +gelf_getehdr(Elf *e, GElf_Ehdr *d) +{ + int ec; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + + if (d == NULL || e == NULL || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL) + return (NULL); + + (void) memcpy(d->e_ident, eh32->e_ident, sizeof(eh32->e_ident)); + d->e_type = eh32->e_type; + d->e_machine = eh32->e_machine; + d->e_version = eh32->e_version; + d->e_entry = eh32->e_entry; + d->e_phoff = eh32->e_phoff; + d->e_shoff = eh32->e_shoff; + d->e_flags = eh32->e_flags; + d->e_ehsize = eh32->e_ehsize; + d->e_phentsize = eh32->e_phentsize; + d->e_phnum = eh32->e_phnum; + d->e_shentsize = eh32->e_shentsize; + d->e_shnum = eh32->e_shnum; + d->e_shstrndx = eh32->e_shstrndx; + + return (d); + } + + assert(ec == ELFCLASS64); + + if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL) + return (NULL); + *d = *eh64; + + return (d); +} + +Elf32_Ehdr * +elf32_newehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS32, 1)); +} + +Elf64_Ehdr * +elf64_newehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS64, 1)); +} + +void * +gelf_newehdr(Elf *e, int ec) +{ + if (e != NULL && + (ec == ELFCLASS32 || ec == ELFCLASS64)) + return (_libelf_ehdr(e, ec, 1)); + + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); +} + +int +gelf_update_ehdr(Elf *e, GElf_Ehdr *s) +{ + int ec; + void *ehdr; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + + if (s== NULL || e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (e->e_cmd == ELF_C_READ) { + LIBELF_SET_ERROR(MODE, 0); + return (0); + } + + if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + if (ec == ELFCLASS64) { + eh64 = (Elf64_Ehdr *) ehdr; + *eh64 = *s; + return (1); + } + + eh32 = (Elf32_Ehdr *) ehdr; + + (void) memcpy(eh32->e_ident, s->e_ident, sizeof(eh32->e_ident)); + + eh32->e_type = s->e_type; + eh32->e_machine = s->e_machine; + eh32->e_version = s->e_version; + LIBELF_COPY_U32(eh32, s, e_entry); + LIBELF_COPY_U32(eh32, s, e_phoff); + LIBELF_COPY_U32(eh32, s, e_shoff); + eh32->e_flags = s->e_flags; + eh32->e_ehsize = s->e_ehsize; + eh32->e_phentsize = s->e_phentsize; + eh32->e_phnum = s->e_phnum; + eh32->e_shentsize = s->e_shentsize; + eh32->e_shnum = s->e_shnum; + eh32->e_shstrndx = s->e_shstrndx; + + (void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY); + + return (1); +} |