]> granicus.if.org Git - yasm/commitdiff
Phase 2 of 2 cleanup to elf's internal structure.
authorMichael Urman <mu@tortall.net>
Sun, 10 Oct 2004 19:25:23 +0000 (19:25 -0000)
committerMichael Urman <mu@tortall.net>
Sun, 10 Oct 2004 19:25:23 +0000 (19:25 -0000)
Move and rename functions for cleanliness.

New files:
elf-machine.h - machine-specific interface, and helper macros
elf-x86-x86   - support specific standard ia32
elf-x86-amd64 - support specific to amd64

Modified files:
elf.c         - update the machine structure traversal for external structures
Makefile.inc  - support the new files

svn path=/trunk/yasm/; revision=1156

modules/objfmts/elf/Makefile.inc
modules/objfmts/elf/elf-machine.h [new file with mode: 0644]
modules/objfmts/elf/elf-x86-amd64.c [new file with mode: 0644]
modules/objfmts/elf/elf-x86-x86.c [new file with mode: 0644]
modules/objfmts/elf/elf.c

index ac48c4cc29a98274016ec241573f791f3120ccc0..e181eb1d1ccaf6ab4a572a63cf2a9fea5e81b9a3 100644 (file)
@@ -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 (file)
index 0000000..934235a
--- /dev/null
@@ -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 (file)
index 0000000..be05615
--- /dev/null
@@ -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 <util.h>
+/*@unused@*/ RCSID("$Id:$");
+
+#define YASM_LIB_INTERNAL
+#define YASM_EXPR_INTERNAL
+#include <libyasm.h>
+#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 (file)
index 0000000..1e926a8
--- /dev/null
@@ -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 <util.h>
+/*@unused@*/ RCSID("$Id:$");
+
+#define YASM_LIB_INTERNAL
+#define YASM_EXPR_INTERNAL
+#include <libyasm.h>
+#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
+};
index e3a8c7e835bc58ca878c6a5779fde6ab0585021a..6b4ccd54541f6794a9e5b2e6a7c2720904db41a4 100644 (file)
 #include <libyasm.h>
 #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);