diff --git a/modules/objfmts/elf/Makefile.inc b/modules/objfmts/elf/Makefile.inc index ac48c4cc..e181eb1d 100644 --- a/modules/objfmts/elf/Makefile.inc +++ b/modules/objfmts/elf/Makefile.inc @@ -5,6 +5,9 @@ pkglib_LTLIBRARIES += objfmt_elf.la objfmt_elf_la_SOURCES = modules/objfmts/elf/elf.c objfmt_elf_la_SOURCES += modules/objfmts/elf/elf.h objfmt_elf_la_SOURCES += modules/objfmts/elf/elf-objfmt.c +objfmt_elf_la_SOURCES += modules/objfmts/elf/elf-machine.h +objfmt_elf_la_SOURCES += modules/objfmts/elf/elf-x86-x86.c +objfmt_elf_la_SOURCES += modules/objfmts/elf/elf-x86-amd64.c objfmt_elf_la_LDFLAGS = -module -avoid-version -no-undefined objfmt_elf_la_LIBADD = libyasm.la YASM_MODULES += -dlopen objfmt_elf.la diff --git a/modules/objfmts/elf/elf-machine.h b/modules/objfmts/elf/elf-machine.h new file mode 100644 index 00000000..934235a7 --- /dev/null +++ b/modules/objfmts/elf/elf-machine.h @@ -0,0 +1,85 @@ +/* $Id:$ + * ELF object machine specific format helpers + * + * Copyright (C) 2004 Michael Urman + * + * 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 OTHER 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 OTHER 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. + */ + +#ifndef ELF_MACHINE_H_INCLUDED +#define ELF_MACHINE_H_INCLUDED + +#define YASM_WRITE_32I_L(p, i) do {\ + assert(yasm_intnum_check_size(i, 32, 0, 2)); \ + yasm_intnum_get_sized(i, p, 4, 32, 0, 0, 0, 0); \ + p += 4; } while (0) + +#define YASM_WRITE_64I_L(p, i) do {\ + assert(yasm_intnum_check_size(i, 64, 0, 2)); \ + yasm_intnum_get_sized(i, p, 8, 64, 0, 0, 0, 0); \ + p += 8; } while (0) + +#define YASM_WRITE_64C_L(p, hi, lo) do {\ + YASM_WRITE_32_L(p, lo); \ + YASM_WRITE_32_L(p, hi); } while (0) + +#define YASM_WRITE_64Z_L(p, i) YASM_WRITE_64C_L(p, 0, i) + +typedef int(*func_accepts_size_t)(size_t); +typedef void(*func_write_symtab_entry)(unsigned char *bufp, + elf_symtab_entry *entry, + yasm_intnum *value_intn, + yasm_intnum *size_intn); +typedef void(*func_write_secthead)(unsigned char *bufp, elf_secthead *shead); +typedef void(*func_write_secthead_rel)(unsigned char *bufp, + elf_secthead *shead, + elf_section_index symtab_idx, + elf_section_index sindex); + +typedef unsigned int(*func_map_reloc_info_to_type)(elf_reloc_entry *reloc); +typedef void(*func_write_reloc)(unsigned char *bufp, + elf_reloc_entry *reloc, + unsigned int r_type, + unsigned int r_sym); +typedef void (*func_write_proghead)(unsigned char **bufpp, + elf_offset secthead_addr, + unsigned long secthead_count, + elf_section_index shstrtab_index); + +typedef struct { + const char *arch; + const char *machine; + const unsigned long symtab_entry_size; + const unsigned long symtab_entry_align; + const unsigned long reloc_entry_size; + const unsigned long secthead_size; + const unsigned long proghead_size; + func_accepts_size_t accepts_reloc_size; + func_write_symtab_entry write_symtab_entry; + func_write_secthead write_secthead; + func_write_secthead_rel write_secthead_rel; + func_map_reloc_info_to_type map_reloc_info_to_type; + func_write_reloc write_reloc; + func_write_proghead write_proghead; +} elf_machine_handler; + +#endif /* ELF_MACHINE_H_INCLUDED */ diff --git a/modules/objfmts/elf/elf-x86-amd64.c b/modules/objfmts/elf/elf-x86-amd64.c new file mode 100644 index 00000000..be056153 --- /dev/null +++ b/modules/objfmts/elf/elf-x86-amd64.c @@ -0,0 +1,195 @@ +/* + * ELF object format helpers - x86:amd64 + * + * Copyright (C) 2004 Michael Urman + * + * 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 OTHER 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 OTHER 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 +/*@unused@*/ RCSID("$Id:$"); + +#define YASM_LIB_INTERNAL +#define YASM_EXPR_INTERNAL +#include +#define YASM_OBJFMT_ELF_INTERNAL +#include "elf.h" +#include "elf-machine.h" + +static int +elf_x86_amd64_accepts_reloc_size(size_t val) +{ + return (val&(val-1)) ? 0 : ((val & (8|16|32|64)) != 0); +} + +static void +elf_x86_amd64_write_symtab_entry(unsigned char *bufp, + elf_symtab_entry *entry, + yasm_intnum *value_intn, + yasm_intnum *size_intn) +{ + YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0); + YASM_WRITE_8(bufp, ELF64_ST_INFO(entry->bind, entry->type)); + YASM_WRITE_8(bufp, 0); + if (entry->sect) { + if (yasm_section_is_absolute(entry->sect)) { + YASM_WRITE_16_L(bufp, SHN_ABS); + } else { + elf_secthead *shead = yasm_section_get_data(entry->sect, + &elf_section_data); + if (!shead) + yasm_internal_error( + N_("symbol references section without data")); + YASM_WRITE_16_L(bufp, shead->index); + } + } else { + YASM_WRITE_16_L(bufp, entry->index); + } + YASM_WRITE_64I_L(bufp, value_intn); + YASM_WRITE_64I_L(bufp, size_intn); +} + +static void +elf_x86_amd64_write_secthead(unsigned char *bufp, elf_secthead *shead) +{ + YASM_WRITE_32_L(bufp, shead->name ? shead->name->index : 0); + YASM_WRITE_32_L(bufp, shead->type); + YASM_WRITE_64Z_L(bufp, shead->flags); + YASM_WRITE_64Z_L(bufp, 0); /* vmem address */ + YASM_WRITE_64Z_L(bufp, shead->offset); + YASM_WRITE_64I_L(bufp, shead->size); + + YASM_WRITE_32_L(bufp, shead->link); + YASM_WRITE_32_L(bufp, shead->info); + + if (shead->align) + YASM_WRITE_64I_L(bufp, shead->align); + else + YASM_WRITE_64Z_L(bufp, 0); + YASM_WRITE_64Z_L(bufp, shead->entsize); + +} + +static void +elf_x86_amd64_write_secthead_rel(unsigned char *bufp, + elf_secthead *shead, + elf_section_index symtab_idx, + elf_section_index sindex) +{ + yasm_intnum *nreloc; + yasm_intnum *relocsize; + + YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0); + YASM_WRITE_32_L(bufp, SHT_REL); + YASM_WRITE_64Z_L(bufp, 0); + YASM_WRITE_64Z_L(bufp, 0); + YASM_WRITE_64Z_L(bufp, shead->rel_offset); + + nreloc = yasm_intnum_create_uint(shead->nreloc); + relocsize = yasm_intnum_create_uint(RELOC64_SIZE); + yasm_intnum_calc(relocsize, YASM_EXPR_MUL, nreloc, 0); + YASM_WRITE_64I_L(bufp, relocsize); /* size */ + yasm_intnum_destroy(nreloc); + yasm_intnum_destroy(relocsize); + + YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */ + YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */ + YASM_WRITE_64Z_L(bufp, RELOC64_ALIGN); /* align */ + YASM_WRITE_64Z_L(bufp, RELOC64_SIZE); /* entity size */ +} + +static unsigned int +elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc) +{ + if (reloc->rtype_rel) { + switch (reloc->valsize) { + case 8: return (unsigned char) R_X86_64_PC8; + case 16: return (unsigned char) R_X86_64_PC16; + case 32: return (unsigned char) R_X86_64_PC32; + default: yasm_internal_error(N_("Unsupported relocation size")); + } + } else { + switch (reloc->valsize) { + case 8: return (unsigned char) R_X86_64_8; + case 16: return (unsigned char) R_X86_64_16; + case 32: return (unsigned char) R_X86_64_32; + case 64: return (unsigned char) R_X86_64_64; + default: yasm_internal_error(N_("Unsupported relocation size")); + } + } + return 0; +} + +static void +elf_x86_amd64_write_reloc(unsigned char *bufp, elf_reloc_entry *reloc, + unsigned int r_type, unsigned int r_sym) +{ + YASM_WRITE_64I_L(bufp, reloc->reloc.addr); + /*YASM_WRITE_64_L(bufp, ELF64_R_INFO(r_sym, r_type));*/ + YASM_WRITE_64C_L(bufp, r_sym, r_type); +} + +static void +elf_x86_amd64_write_proghead(unsigned char **bufpp, + elf_offset secthead_addr, + unsigned long secthead_count, + elf_section_index shstrtab_index) +{ + unsigned char *bufp = *bufpp; + unsigned char *buf = bufp-4; + YASM_WRITE_8(bufp, ELFCLASS64); /* elf class */ + YASM_WRITE_8(bufp, ELFDATA2LSB); /* data encoding :: MSB? */ + YASM_WRITE_8(bufp, EV_CURRENT); /* elf version */ + YASM_WRITE_8(bufp, ELFOSABI_SYSV); /* os/abi */ + YASM_WRITE_8(bufp, 0); /* SYSV v3 ABI=0 */ + while (bufp-buf < EI_NIDENT) /* e_ident padding */ + YASM_WRITE_8(bufp, 0); + + YASM_WRITE_16_L(bufp, ET_REL); /* e_type - object file */ + YASM_WRITE_16_L(bufp, EM_X86_64); /* e_machine - or others */ + YASM_WRITE_32_L(bufp, EV_CURRENT); /* elf version */ + YASM_WRITE_64Z_L(bufp, 0); /* e_entry */ + YASM_WRITE_64Z_L(bufp, 0); /* e_phoff */ + YASM_WRITE_64Z_L(bufp, secthead_addr); /* e_shoff secthead off */ + + YASM_WRITE_32_L(bufp, 0); /* e_flags */ + YASM_WRITE_16_L(bufp, EHDR64_SIZE); /* e_ehsize */ + YASM_WRITE_16_L(bufp, 0); /* e_phentsize */ + YASM_WRITE_16_L(bufp, 0); /* e_phnum */ + YASM_WRITE_16_L(bufp, SHDR64_SIZE); /* e_shentsize */ + YASM_WRITE_16_L(bufp, secthead_count); /* e_shnum */ + YASM_WRITE_16_L(bufp, shstrtab_index); /* e_shstrndx */ + *bufpp = bufp; +} + +const elf_machine_handler +elf_machine_handler_x86_amd64 = { + "x86", "amd64", + SYMTAB64_SIZE, SYMTAB64_ALIGN, RELOC64_SIZE, SHDR64_SIZE, EHDR64_SIZE, + elf_x86_amd64_accepts_reloc_size, + elf_x86_amd64_write_symtab_entry, + elf_x86_amd64_write_secthead, + elf_x86_amd64_write_secthead_rel, + elf_x86_amd64_map_reloc_info_to_type, + elf_x86_amd64_write_reloc, + elf_x86_amd64_write_proghead +}; diff --git a/modules/objfmts/elf/elf-x86-x86.c b/modules/objfmts/elf/elf-x86-x86.c new file mode 100644 index 00000000..1e926a8e --- /dev/null +++ b/modules/objfmts/elf/elf-x86-x86.c @@ -0,0 +1,168 @@ +/* + * ELF object format helpers - x86:x86 + * + * Copyright (C) 2004 Michael Urman + * + * 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 OTHER 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 OTHER 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 +/*@unused@*/ RCSID("$Id:$"); + +#define YASM_LIB_INTERNAL +#define YASM_EXPR_INTERNAL +#include +#define YASM_OBJFMT_ELF_INTERNAL +#include "elf.h" +#include "elf-machine.h" + +static int +elf_x86_x86_accepts_reloc_size(size_t val) +{ + return val == 32; +} + +static void +elf_x86_x86_write_symtab_entry(unsigned char *bufp, + elf_symtab_entry *entry, + yasm_intnum *value_intn, + yasm_intnum *size_intn) +{ + YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0); + YASM_WRITE_32I_L(bufp, value_intn); + YASM_WRITE_32I_L(bufp, size_intn); + + YASM_WRITE_8(bufp, ELF32_ST_INFO(entry->bind, entry->type)); + YASM_WRITE_8(bufp, 0); + if (entry->sect) { + if (yasm_section_is_absolute(entry->sect)) { + YASM_WRITE_16_L(bufp, SHN_ABS); + } else { + elf_secthead *shead = yasm_section_get_data(entry->sect, + &elf_section_data); + if (!shead) + yasm_internal_error( + N_("symbol references section without data")); + YASM_WRITE_16_L(bufp, shead->index); + } + } else { + YASM_WRITE_16_L(bufp, entry->index); + } +} + +static void +elf_x86_x86_write_secthead(unsigned char *bufp, elf_secthead *shead) +{ + YASM_WRITE_32_L(bufp, shead->name ? shead->name->index : 0); + YASM_WRITE_32_L(bufp, shead->type); + YASM_WRITE_32_L(bufp, shead->flags); + YASM_WRITE_32_L(bufp, 0); /* vmem address */ + + YASM_WRITE_32_L(bufp, shead->offset); + YASM_WRITE_32I_L(bufp, shead->size); + YASM_WRITE_32_L(bufp, shead->link); + YASM_WRITE_32_L(bufp, shead->info); + + if (shead->align) + YASM_WRITE_32I_L(bufp, shead->align); + else + YASM_WRITE_32_L(bufp, 0); + YASM_WRITE_32_L(bufp, shead->entsize); + +} + +static void +elf_x86_x86_write_secthead_rel(unsigned char *bufp, + elf_secthead *shead, + elf_section_index symtab_idx, + elf_section_index sindex) +{ + YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0); + YASM_WRITE_32_L(bufp, SHT_REL); + YASM_WRITE_32_L(bufp, 0); + YASM_WRITE_32_L(bufp, 0); + + YASM_WRITE_32_L(bufp, shead->rel_offset); + YASM_WRITE_32_L(bufp, RELOC32_SIZE * shead->nreloc);/* size */ + YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */ + YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */ + + YASM_WRITE_32_L(bufp, RELOC32_ALIGN); /* align */ + YASM_WRITE_32_L(bufp, RELOC32_SIZE); /* entity size */ +} + +static unsigned int +elf_x86_x86_map_reloc_info_to_type(elf_reloc_entry *reloc) +{ + return (reloc->rtype_rel ? R_386_PC32 : R_386_32); +} + +static void +elf_x86_x86_write_reloc(unsigned char *bufp, elf_reloc_entry *reloc, + unsigned int r_type, unsigned int r_sym) +{ + YASM_WRITE_32I_L(bufp, reloc->reloc.addr); + YASM_WRITE_32_L(bufp, ELF32_R_INFO((unsigned char)r_sym, (unsigned char)r_type)); +} + +static void +elf_x86_x86_write_proghead(unsigned char **bufpp, + elf_offset secthead_addr, + unsigned long secthead_count, + elf_section_index shstrtab_index) +{ + unsigned char *bufp = *bufpp; + unsigned char *buf = bufp-4; + YASM_WRITE_8(bufp, ELFCLASS32); /* elf class */ + YASM_WRITE_8(bufp, ELFDATA2LSB); /* data encoding :: MSB? */ + YASM_WRITE_8(bufp, EV_CURRENT); /* elf version */ + while (bufp-buf < EI_NIDENT) /* e_ident padding */ + YASM_WRITE_8(bufp, 0); + + YASM_WRITE_16_L(bufp, ET_REL); /* e_type - object file */ + YASM_WRITE_16_L(bufp, EM_386); /* e_machine - or others */ + YASM_WRITE_32_L(bufp, EV_CURRENT); /* elf version */ + YASM_WRITE_32_L(bufp, 0); /* e_entry exection startaddr */ + YASM_WRITE_32_L(bufp, 0); /* e_phoff program header off */ + YASM_WRITE_32_L(bufp, secthead_addr); /* e_shoff section header off */ + YASM_WRITE_32_L(bufp, 0); /* e_flags also by arch */ + YASM_WRITE_16_L(bufp, EHDR32_SIZE); /* e_ehsize */ + YASM_WRITE_16_L(bufp, 0); /* e_phentsize */ + YASM_WRITE_16_L(bufp, 0); /* e_phnum */ + YASM_WRITE_16_L(bufp, SHDR32_SIZE); /* e_shentsize */ + YASM_WRITE_16_L(bufp, secthead_count); /* e_shnum */ + YASM_WRITE_16_L(bufp, shstrtab_index); /* e_shstrndx */ + *bufpp = bufp; +} + +const elf_machine_handler +elf_machine_handler_x86_x86 = { + "x86", "x86", + SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32_SIZE, SHDR32_SIZE, EHDR32_SIZE, + elf_x86_x86_accepts_reloc_size, + elf_x86_x86_write_symtab_entry, + elf_x86_x86_write_secthead, + elf_x86_x86_write_secthead_rel, + elf_x86_x86_map_reloc_info_to_type, + elf_x86_x86_write_reloc, + elf_x86_x86_write_proghead +}; diff --git a/modules/objfmts/elf/elf.c b/modules/objfmts/elf/elf.c index e3a8c7e8..6b4ccd54 100644 --- a/modules/objfmts/elf/elf.c +++ b/modules/objfmts/elf/elf.c @@ -33,22 +33,7 @@ #include #define YASM_OBJFMT_ELF_INTERNAL #include "elf.h" - -#define YASM_WRITE_32I_L(p, i) do {\ - assert(yasm_intnum_check_size(i, 32, 0, 2)); \ - yasm_intnum_get_sized(i, p, 4, 32, 0, 0, 0, 0); \ - p += 4; } while (0) - -#define YASM_WRITE_64I_L(p, i) do {\ - assert(yasm_intnum_check_size(i, 64, 0, 2)); \ - yasm_intnum_get_sized(i, p, 8, 64, 0, 0, 0, 0); \ - p += 8; } while (0) - -#define YASM_WRITE_64C_L(p, hi, lo) do {\ - YASM_WRITE_32_L(p, lo); \ - YASM_WRITE_32_L(p, hi); } while (0) - -#define YASM_WRITE_64Z_L(p, i) YASM_WRITE_64C_L(p, 0, i) +#include "elf-machine.h" static void elf_section_data_destroy(void *data); static void elf_secthead_print(void *data, FILE *f, int indent_level); @@ -66,317 +51,15 @@ const yasm_assoc_data_callback elf_symrec_data = { elf_symtab_entry_print }; -typedef int(*func_accepts_size_t)(size_t); -typedef void(*func_write_symtab_entry)(unsigned char *bufp, - elf_symtab_entry *entry, - yasm_intnum *value_intn, - yasm_intnum *size_intn); -typedef void(*func_write_secthead)(unsigned char *bufp, elf_secthead *shead); -typedef void(*func_write_secthead_rel)(unsigned char *bufp, - elf_secthead *shead, - elf_section_index symtab_idx, - elf_section_index sindex); - -typedef unsigned char(*func_map_reloc_info_to_type)(elf_reloc_entry *reloc); -typedef void(*func_write_reloc)(unsigned char *bufp, - elf_reloc_entry *reloc, - unsigned char r_type, - unsigned char r_sym); -typedef void (*func_write_proghead)(unsigned char **bufpp, - elf_offset secthead_addr, - unsigned long secthead_count, - elf_section_index shstrtab_index); - -typedef struct { - const char *arch; - const char *machine; - const unsigned long symtab_entry_size; - const unsigned long symtab_entry_align; - const unsigned long reloc_entry_size; - const unsigned long secthead_size; - const unsigned long proghead_size; - func_accepts_size_t accepts_reloc_size; - func_write_symtab_entry write_symtab_entry; - func_write_secthead write_secthead; - func_write_secthead_rel write_secthead_rel; - func_map_reloc_info_to_type map_reloc_info_to_type; - func_write_reloc write_reloc; - func_write_proghead write_proghead; -} elf_machine_handler; - -static int elf_accept_32(size_t val) -{ - return val == 32; -} -static int elf_accept_8_16_32_64(size_t val) -{ - return (val&(val-1)) ? 0 : ((val & (8|16|32|64)) != 0); -} - -static void elf_write_symtab_entry_x86(unsigned char *bufp, - elf_symtab_entry *entry, - yasm_intnum *value_intn, - yasm_intnum *size_intn) -{ - YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0); - YASM_WRITE_32I_L(bufp, value_intn); - YASM_WRITE_32I_L(bufp, size_intn); - - YASM_WRITE_8(bufp, ELF32_ST_INFO(entry->bind, entry->type)); - YASM_WRITE_8(bufp, 0); - if (entry->sect) { - if (yasm_section_is_absolute(entry->sect)) { - YASM_WRITE_16_L(bufp, SHN_ABS); - } else { - elf_secthead *shead = yasm_section_get_data(entry->sect, - &elf_section_data); - if (!shead) - yasm_internal_error( - N_("symbol references section without data")); - YASM_WRITE_16_L(bufp, shead->index); - } - } else { - YASM_WRITE_16_L(bufp, entry->index); - } -} - -static void elf_write_symtab_entry_x86_64(unsigned char *bufp, - elf_symtab_entry *entry, - yasm_intnum *value_intn, - yasm_intnum *size_intn) -{ - YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0); - YASM_WRITE_8(bufp, ELF64_ST_INFO(entry->bind, entry->type)); - YASM_WRITE_8(bufp, 0); - if (entry->sect) { - if (yasm_section_is_absolute(entry->sect)) { - YASM_WRITE_16_L(bufp, SHN_ABS); - } else { - elf_secthead *shead = yasm_section_get_data(entry->sect, - &elf_section_data); - if (!shead) - yasm_internal_error( - N_("symbol references section without data")); - YASM_WRITE_16_L(bufp, shead->index); - } - } else { - YASM_WRITE_16_L(bufp, entry->index); - } - YASM_WRITE_64I_L(bufp, value_intn); - YASM_WRITE_64I_L(bufp, size_intn); -} - -static void elf_write_secthead_x86(unsigned char *bufp, elf_secthead *shead) -{ - YASM_WRITE_32_L(bufp, shead->name ? shead->name->index : 0); - YASM_WRITE_32_L(bufp, shead->type); - YASM_WRITE_32_L(bufp, shead->flags); - YASM_WRITE_32_L(bufp, 0); /* vmem address */ - - YASM_WRITE_32_L(bufp, shead->offset); - YASM_WRITE_32I_L(bufp, shead->size); - YASM_WRITE_32_L(bufp, shead->link); - YASM_WRITE_32_L(bufp, shead->info); - - if (shead->align) - YASM_WRITE_32I_L(bufp, shead->align); - else - YASM_WRITE_32_L(bufp, 0); - YASM_WRITE_32_L(bufp, shead->entsize); - -} - -static void elf_write_secthead_x86_64(unsigned char *bufp, elf_secthead *shead) -{ - YASM_WRITE_32_L(bufp, shead->name ? shead->name->index : 0); - YASM_WRITE_32_L(bufp, shead->type); - YASM_WRITE_64Z_L(bufp, shead->flags); - YASM_WRITE_64Z_L(bufp, 0); /* vmem address */ - YASM_WRITE_64Z_L(bufp, shead->offset); - YASM_WRITE_64I_L(bufp, shead->size); - - YASM_WRITE_32_L(bufp, shead->link); - YASM_WRITE_32_L(bufp, shead->info); - - if (shead->align) - YASM_WRITE_64I_L(bufp, shead->align); - else - YASM_WRITE_64Z_L(bufp, 0); - YASM_WRITE_64Z_L(bufp, shead->entsize); - -} - -static void elf_write_secthead_rel_x86(unsigned char *bufp, - elf_secthead *shead, - elf_section_index symtab_idx, - elf_section_index sindex) -{ - YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0); - YASM_WRITE_32_L(bufp, SHT_REL); - YASM_WRITE_32_L(bufp, 0); - YASM_WRITE_32_L(bufp, 0); - - YASM_WRITE_32_L(bufp, shead->rel_offset); - YASM_WRITE_32_L(bufp, RELOC32_SIZE * shead->nreloc);/* size */ - YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */ - YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */ - - YASM_WRITE_32_L(bufp, RELOC32_ALIGN); /* align */ - YASM_WRITE_32_L(bufp, RELOC32_SIZE); /* entity size */ -} - -static void elf_write_secthead_rel_x86_64(unsigned char *bufp, - elf_secthead *shead, - elf_section_index symtab_idx, - elf_section_index sindex) -{ - yasm_intnum *nreloc; - yasm_intnum *relocsize; - - YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0); - YASM_WRITE_32_L(bufp, SHT_REL); - YASM_WRITE_64Z_L(bufp, 0); - YASM_WRITE_64Z_L(bufp, 0); - YASM_WRITE_64Z_L(bufp, shead->rel_offset); - - nreloc = yasm_intnum_create_uint(shead->nreloc); - relocsize = yasm_intnum_create_uint(RELOC64_SIZE); - yasm_intnum_calc(relocsize, YASM_EXPR_MUL, nreloc, 0); - YASM_WRITE_64I_L(bufp, relocsize); /* size */ - yasm_intnum_destroy(nreloc); - yasm_intnum_destroy(relocsize); - - YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */ - YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */ - YASM_WRITE_64Z_L(bufp, RELOC64_ALIGN); /* align */ - YASM_WRITE_64Z_L(bufp, RELOC64_SIZE); /* entity size */ -} - -static unsigned char elf_map_reloc_info_to_type_x86(elf_reloc_entry *reloc) -{ - return (unsigned char)(reloc->rtype_rel ? R_386_PC32 : R_386_32); -} - -static unsigned char elf_map_reloc_info_to_type_x86_64(elf_reloc_entry *reloc) -{ - if (reloc->rtype_rel) { - switch (reloc->valsize) { - case 8: return (unsigned char) R_X86_64_PC8; - case 16: return (unsigned char) R_X86_64_PC16; - case 32: return (unsigned char) R_X86_64_PC32; - default: yasm_internal_error(N_("Unsupported relocation size")); - } - } else { - switch (reloc->valsize) { - case 8: return (unsigned char) R_X86_64_8; - case 16: return (unsigned char) R_X86_64_16; - case 32: return (unsigned char) R_X86_64_32; - case 64: return (unsigned char) R_X86_64_64; - default: yasm_internal_error(N_("Unsupported relocation size")); - } - } - return 0; -} - -static void elf_write_reloc_x86(unsigned char *bufp, elf_reloc_entry *reloc, - unsigned char r_type, unsigned char r_sym) -{ - YASM_WRITE_32I_L(bufp, reloc->reloc.addr); - YASM_WRITE_32_L(bufp, ELF32_R_INFO(r_sym, r_type)); -} - -static void elf_write_reloc_x86_64(unsigned char *bufp, elf_reloc_entry *reloc, - unsigned char r_type, unsigned char r_sym) -{ - YASM_WRITE_64I_L(bufp, reloc->reloc.addr); - /*YASM_WRITE_64_L(bufp, ELF64_R_INFO(r_sym, r_type));*/ - YASM_WRITE_64C_L(bufp, r_sym, r_type); -} +extern elf_machine_handler + elf_machine_handler_x86_x86, + elf_machine_handler_x86_amd64; -static void elf_write_proghead_x86(unsigned char **bufpp, - elf_offset secthead_addr, - unsigned long secthead_count, - elf_section_index shstrtab_index) +static const elf_machine_handler *elf_machine_handlers[] = { - unsigned char *bufp = *bufpp; - unsigned char *buf = bufp-4; - YASM_WRITE_8(bufp, ELFCLASS32); /* elf class */ - YASM_WRITE_8(bufp, ELFDATA2LSB); /* data encoding :: MSB? */ - YASM_WRITE_8(bufp, EV_CURRENT); /* elf version */ - while (bufp-buf < EI_NIDENT) /* e_ident padding */ - YASM_WRITE_8(bufp, 0); - - YASM_WRITE_16_L(bufp, ET_REL); /* e_type - object file */ - YASM_WRITE_16_L(bufp, EM_386); /* e_machine - or others */ - YASM_WRITE_32_L(bufp, EV_CURRENT); /* elf version */ - YASM_WRITE_32_L(bufp, 0); /* e_entry exection startaddr */ - YASM_WRITE_32_L(bufp, 0); /* e_phoff program header off */ - YASM_WRITE_32_L(bufp, secthead_addr); /* e_shoff section header off */ - YASM_WRITE_32_L(bufp, 0); /* e_flags also by arch */ - YASM_WRITE_16_L(bufp, EHDR32_SIZE); /* e_ehsize */ - YASM_WRITE_16_L(bufp, 0); /* e_phentsize */ - YASM_WRITE_16_L(bufp, 0); /* e_phnum */ - YASM_WRITE_16_L(bufp, SHDR32_SIZE); /* e_shentsize */ - YASM_WRITE_16_L(bufp, secthead_count); /* e_shnum */ - YASM_WRITE_16_L(bufp, shstrtab_index); /* e_shstrndx */ - *bufpp = bufp; -} - -static void elf_write_proghead_x86_64(unsigned char **bufpp, - elf_offset secthead_addr, - unsigned long secthead_count, - elf_section_index shstrtab_index) -{ - unsigned char *bufp = *bufpp; - unsigned char *buf = bufp-4; - YASM_WRITE_8(bufp, ELFCLASS64); /* elf class */ - YASM_WRITE_8(bufp, ELFDATA2LSB); /* data encoding :: MSB? */ - YASM_WRITE_8(bufp, EV_CURRENT); /* elf version */ - YASM_WRITE_8(bufp, ELFOSABI_SYSV); /* os/abi */ - YASM_WRITE_8(bufp, 0); /* SYSV v3 ABI=0 */ - while (bufp-buf < EI_NIDENT) /* e_ident padding */ - YASM_WRITE_8(bufp, 0); - - YASM_WRITE_16_L(bufp, ET_REL); /* e_type - object file */ - YASM_WRITE_16_L(bufp, EM_X86_64); /* e_machine - or others */ - YASM_WRITE_32_L(bufp, EV_CURRENT); /* elf version */ - YASM_WRITE_64Z_L(bufp, 0); /* e_entry */ - YASM_WRITE_64Z_L(bufp, 0); /* e_phoff */ - YASM_WRITE_64Z_L(bufp, secthead_addr); /* e_shoff secthead off */ - - YASM_WRITE_32_L(bufp, 0); /* e_flags */ - YASM_WRITE_16_L(bufp, EHDR64_SIZE); /* e_ehsize */ - YASM_WRITE_16_L(bufp, 0); /* e_phentsize */ - YASM_WRITE_16_L(bufp, 0); /* e_phnum */ - YASM_WRITE_16_L(bufp, SHDR64_SIZE); /* e_shentsize */ - YASM_WRITE_16_L(bufp, secthead_count); /* e_shnum */ - YASM_WRITE_16_L(bufp, shstrtab_index); /* e_shstrndx */ - *bufpp = bufp; -} - -static const elf_machine_handler elf_machine_handlers[] = -{ - { "x86", "x86", - SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32_SIZE, SHDR32_SIZE, EHDR32_SIZE, - elf_accept_32, - elf_write_symtab_entry_x86, - elf_write_secthead_x86, - elf_write_secthead_rel_x86, - elf_map_reloc_info_to_type_x86, - elf_write_reloc_x86, - elf_write_proghead_x86 - }, - { "x86", "amd64", - SYMTAB64_SIZE, SYMTAB64_ALIGN, RELOC64_SIZE, SHDR64_SIZE, EHDR64_SIZE, - elf_accept_8_16_32_64, - elf_write_symtab_entry_x86_64, - elf_write_secthead_x86_64, - elf_write_secthead_rel_x86_64, - elf_map_reloc_info_to_type_x86_64, - elf_write_reloc_x86_64, - elf_write_proghead_x86_64 - }, - { NULL } + &elf_machine_handler_x86_x86, + &elf_machine_handler_x86_amd64, + NULL }; static elf_machine_handler const *elf_march; @@ -384,13 +67,17 @@ int elf_set_arch(yasm_arch *arch) { const char *machine = yasm_arch_get_machine(arch); + int i; - /* TODO: support more than x86:x86, x86:amd64 */ - for (elf_march = elf_machine_handlers; elf_march->arch != NULL; elf_march++) + for (i=0, elf_march = elf_machine_handlers[0]; + elf_march != NULL; + elf_march = elf_machine_handlers[++i]) + { if (yasm__strcasecmp(yasm_arch_keyword(arch), elf_march->arch)==0) if (yasm__strcasecmp(machine, elf_march->machine)==0) break; - return elf_march->arch != NULL; + } + return elf_march != NULL; } /* reloc functions */ @@ -935,7 +622,7 @@ elf_secthead_write_relocs_to_file(FILE *f, yasm_section *sect, while (reloc) { yasm_sym_vis vis; - unsigned char r_type=0, r_sym; + unsigned int r_type=0, r_sym; elf_symtab_entry *esym; esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);