aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/yasm/modules/objfmts/elf
diff options
context:
space:
mode:
authorsomov <somov@yandex-team.ru>2022-02-10 16:45:47 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:47 +0300
commita5950576e397b1909261050b8c7da16db58f10b1 (patch)
tree7ba7677f6a4c3e19e2cefab34d16df2c8963b4d4 /contrib/tools/yasm/modules/objfmts/elf
parent81eddc8c0b55990194e112b02d127b87d54164a9 (diff)
downloadydb-a5950576e397b1909261050b8c7da16db58f10b1.tar.gz
Restoring authorship annotation for <somov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/yasm/modules/objfmts/elf')
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf-machine.h216
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf-objfmt.c2782
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf-x86-amd64.c512
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf-x86-x32.c502
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf-x86-x86.c484
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf.c1920
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf.h1064
7 files changed, 3740 insertions, 3740 deletions
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf-machine.h b/contrib/tools/yasm/modules/objfmts/elf/elf-machine.h
index ea6cb4ec94..346b4f6f34 100644
--- a/contrib/tools/yasm/modules/objfmts/elf/elf-machine.h
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf-machine.h
@@ -1,108 +1,108 @@
-/*
- * ELF object machine specific format helpers
- *
- * Copyright (C) 2004-2007 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); \
- 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); \
- 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_reloc)(size_t val, yasm_symrec *wrt);
-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 void(*func_handle_reloc_addend)(yasm_intnum *intn,
- elf_reloc_entry *reloc,
- unsigned long offset);
-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);
-
-enum {
- ELF_SSYM_SYM_RELATIVE = 1 << 0,
- ELF_SSYM_CURPOS_ADJUST = 1 << 1,
- ELF_SSYM_THREAD_LOCAL = 1 << 2
-};
-
-typedef struct {
- const char *name; /* should be something like ..name */
- const int sym_rel; /* symbol or section-relative? */
- const unsigned int reloc; /* relocation type */
- const unsigned int size; /* legal data size */
-} elf_machine_ssym;
-
-struct elf_machine_handler {
- const char *arch;
- const char *machine;
- const char *reloc_section_prefix;
- 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_reloc accepts_reloc;
- func_write_symtab_entry write_symtab_entry;
- func_write_secthead write_secthead;
- func_write_secthead_rel write_secthead_rel;
- func_handle_reloc_addend handle_reloc_addend;
- func_map_reloc_info_to_type map_reloc_info_to_type;
- func_write_reloc write_reloc;
- func_write_proghead write_proghead;
-
- elf_machine_ssym *ssyms; /* array of "special" syms */
- const size_t num_ssyms; /* size of array */
-
- const int bits; /* usually 32 or 64 */
-};
-
-#endif /* ELF_MACHINE_H_INCLUDED */
+/*
+ * ELF object machine specific format helpers
+ *
+ * Copyright (C) 2004-2007 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); \
+ 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); \
+ 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_reloc)(size_t val, yasm_symrec *wrt);
+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 void(*func_handle_reloc_addend)(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset);
+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);
+
+enum {
+ ELF_SSYM_SYM_RELATIVE = 1 << 0,
+ ELF_SSYM_CURPOS_ADJUST = 1 << 1,
+ ELF_SSYM_THREAD_LOCAL = 1 << 2
+};
+
+typedef struct {
+ const char *name; /* should be something like ..name */
+ const int sym_rel; /* symbol or section-relative? */
+ const unsigned int reloc; /* relocation type */
+ const unsigned int size; /* legal data size */
+} elf_machine_ssym;
+
+struct elf_machine_handler {
+ const char *arch;
+ const char *machine;
+ const char *reloc_section_prefix;
+ 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_reloc accepts_reloc;
+ func_write_symtab_entry write_symtab_entry;
+ func_write_secthead write_secthead;
+ func_write_secthead_rel write_secthead_rel;
+ func_handle_reloc_addend handle_reloc_addend;
+ func_map_reloc_info_to_type map_reloc_info_to_type;
+ func_write_reloc write_reloc;
+ func_write_proghead write_proghead;
+
+ elf_machine_ssym *ssyms; /* array of "special" syms */
+ const size_t num_ssyms; /* size of array */
+
+ const int bits; /* usually 32 or 64 */
+};
+
+#endif /* ELF_MACHINE_H_INCLUDED */
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf-objfmt.c b/contrib/tools/yasm/modules/objfmts/elf/elf-objfmt.c
index 6874a1689f..e447218ad5 100644
--- a/contrib/tools/yasm/modules/objfmts/elf/elf-objfmt.c
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf-objfmt.c
@@ -1,1403 +1,1403 @@
-/*
- * ELF object format
- *
- * Copyright (C) 2003-2007 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>
-
-/* Notes
- *
- * elf-objfmt uses the "linking" view of an ELF file:
- * ELF header, an optional program header table, several sections,
- * and a section header table
- *
- * The ELF header tells us some overall program information,
- * where to find the PHT (if it exists) with phnum and phentsize,
- * and where to find the SHT with shnum and shentsize
- *
- * The PHT doesn't seem to be generated by NASM for elftest.asm
- *
- * The SHT
- *
- * Each Section is spatially disjoint, and has exactly one SHT entry.
- */
-
-#include <libyasm.h>
-
-#include "elf.h"
-#include "elf-machine.h"
-
-typedef struct yasm_objfmt_elf {
- yasm_objfmt_base objfmt; /* base structure */
-
- elf_symtab_head* elf_symtab; /* symbol table of indexed syms */
- elf_strtab_head* shstrtab; /* section name strtab */
- elf_strtab_head* strtab; /* strtab entries */
-
- elf_strtab_entry *file_strtab_entry;/* .file symbol associated string */
- yasm_symrec *dotdotsym; /* ..sym symbol */
-} yasm_objfmt_elf;
-
-typedef struct {
- yasm_objfmt_elf *objfmt_elf;
- yasm_errwarns *errwarns;
- FILE *f;
- elf_secthead *shead;
- yasm_section *sect;
- yasm_object *object;
- unsigned long sindex;
- yasm_symrec *GOT_sym;
-} elf_objfmt_output_info;
-
-typedef struct {
- yasm_object *object;
- yasm_objfmt_elf *objfmt_elf;
- yasm_errwarns *errwarns;
- int local_names;
-} build_symtab_info;
-
-yasm_objfmt_module yasm_elf_LTX_objfmt;
-yasm_objfmt_module yasm_elf32_LTX_objfmt;
-yasm_objfmt_module yasm_elf64_LTX_objfmt;
-yasm_objfmt_module yasm_elfx32_LTX_objfmt;
-
-
-static elf_symtab_entry *
-elf_objfmt_symtab_append(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym,
- elf_section_index sectidx, elf_symbol_binding bind,
- elf_symbol_type type, elf_symbol_vis vis,
- yasm_expr *size, elf_address *value,
- yasm_object *object)
-{
- elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
-
- if (!entry) {
- /*@only@*/ char *symname = yasm_symrec_get_global_name(sym, object);
- elf_strtab_entry *name =
- elf_strtab_append_str(objfmt_elf->strtab, symname);
- yasm_xfree(symname);
- entry = elf_symtab_entry_create(name, sym);
- yasm_symrec_add_data(sym, &elf_symrec_data, entry);
- }
-
- /* Only append to table if not already appended */
- if (!elf_sym_in_table(entry))
- elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
-
- elf_symtab_set_nonzero(entry, NULL, sectidx, bind, type, size, value);
- elf_sym_set_visibility(entry, vis);
-
- return entry;
-}
-
-static elf_symtab_entry *
-build_extern(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
-{
- yasm_valparamhead *objext_valparams =
- yasm_symrec_get_objext_valparams(sym);
-
- if (objext_valparams) {
- yasm_valparam *vp = yasm_vps_first(objext_valparams);
- for (; vp; vp = yasm_vps_next(vp)) {
- if (yasm_vp_string(vp))
- yasm_error_set(YASM_ERROR_TYPE,
- N_("unrecognized symbol type `%s'"),
- yasm_vp_string(vp));
- }
- }
-
- return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL, 0,
- STV_DEFAULT, NULL, NULL, object);
-}
-
-struct elf_build_global_data {
- yasm_expr *size;
- unsigned long type; /* elf_symbol_type */
- elf_symbol_vis vis;
- unsigned int vis_overrides;
-};
-
-static int
-elf_global_helper_valparam(void *obj, yasm_valparam *vp, unsigned long line,
- void *d)
-
-{
- struct elf_build_global_data *data = (struct elf_build_global_data *)d;
- const char *s;
-
- if (!vp->val && (s = yasm_vp_id(vp))) {
- yasm_error_set(YASM_ERROR_TYPE, N_("unrecognized symbol type `%s'"),
- s);
- return -1;
- } else if (!vp->val && vp->type == YASM_PARAM_EXPR && !data->size) {
- data->size = yasm_expr_copy(vp->param.e);
- return 0;
- } else
- return yasm_dir_helper_valparam_warn(obj, vp, line, d);
-}
-
-static int
-elf_global_helper_vis(void *obj, yasm_valparam *vp, unsigned long line,
- void *d, uintptr_t vis)
-{
- struct elf_build_global_data *data = (struct elf_build_global_data *)d;
- data->vis = vis;
- data->vis_overrides++;
- return 0;
-}
-
-
-static elf_symtab_entry *
-build_global(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
-{
- yasm_valparamhead *objext_valparams =
- yasm_symrec_get_objext_valparams(sym);
-
- struct elf_build_global_data data;
-
- static const yasm_dir_help help[] = {
- { "function", 0, yasm_dir_helper_flag_set,
- offsetof(struct elf_build_global_data, type), STT_FUNC },
- { "data", 0, yasm_dir_helper_flag_set,
- offsetof(struct elf_build_global_data, type), STT_OBJECT },
- { "object", 0, yasm_dir_helper_flag_set,
- offsetof(struct elf_build_global_data, type), STT_OBJECT },
- { "internal", 0, elf_global_helper_vis, 0, STV_INTERNAL },
- { "hidden", 0, elf_global_helper_vis, 0, STV_HIDDEN },
- { "protected", 0, elf_global_helper_vis, 0, STV_PROTECTED },
- };
-
- data.size = NULL;
- data.type = 0;
- data.vis = STV_DEFAULT;
- data.vis_overrides = 0;
-
- if (objext_valparams)
- yasm_dir_helper(sym, yasm_vps_first(objext_valparams),
- yasm_symrec_get_decl_line(sym), help, NELEMS(help),
- &data, elf_global_helper_valparam);
-
- if (data.vis_overrides > 1) {
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("More than one symbol visibility provided; using last"));
- }
-
- return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL,
- data.type, data.vis, data.size, NULL,
- object);
-}
-
-static /*@null@*/ elf_symtab_entry *
-build_common(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
-{
- yasm_expr **size = yasm_symrec_get_common_size(sym);
- yasm_valparamhead *objext_valparams =
- yasm_symrec_get_objext_valparams(sym);
- unsigned long addralign = 0;
-
- if (objext_valparams) {
- yasm_valparam *vp = yasm_vps_first(objext_valparams);
- for (; vp; vp = yasm_vps_next(vp)) {
- if (!vp->val) {
- /*@only@*/ /*@null@*/ yasm_expr *align_expr;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *align_intn;
-
- if (!(align_expr = yasm_vp_expr(vp, object->symtab,
- yasm_symrec_get_def_line(sym)))
- || !(align_intn = yasm_expr_get_intnum(&align_expr, 0))) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("alignment constraint is not an integer"));
- if (align_expr)
- yasm_expr_destroy(align_expr);
- return NULL;
- }
- addralign = yasm_intnum_get_uint(align_intn);
- yasm_expr_destroy(align_expr);
-
- /* Alignments must be a power of two. */
- if (!is_exp2(addralign)) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("alignment constraint is not a power of two"));
- return NULL;
- }
- } else
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("Unrecognized qualifier `%s'"), vp->val);
- }
- }
-
- return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_COMMON, STB_GLOBAL,
- 0, STV_DEFAULT, *size, &addralign, object);
-}
-
-static int
-elf_objfmt_build_symtab(yasm_symrec *sym, /*@null@*/ void *d)
-{
- build_symtab_info *info = (build_symtab_info *)d;
- yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
- yasm_sym_status status = yasm_symrec_get_status(sym);
- elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
- elf_address value=0;
- yasm_section *sect=NULL;
- yasm_bytecode *precbc=NULL;
-
- assert(info != NULL);
-
- if (vis & YASM_SYM_EXTERN) {
- entry = build_extern(info->objfmt_elf, sym, info->object);
- yasm_errwarn_propagate(info->errwarns,
- yasm_symrec_get_decl_line(sym));
- return 0;
- }
-
- if (vis & YASM_SYM_COMMON) {
- entry = build_common(info->objfmt_elf, sym, info->object);
- yasm_errwarn_propagate(info->errwarns,
- yasm_symrec_get_decl_line(sym));
- /* If the COMMON variable was actually defined, fall through. */
- if (!(status & YASM_SYM_DEFINED))
- return 0;
- }
-
- /* Ignore any undefined at this point. */
- if (!(status & YASM_SYM_DEFINED))
- return 0;
-
- if (!yasm_symrec_get_label(sym, &precbc)) {
- if (!yasm_symrec_get_equ(sym) && !yasm_symrec_is_abs(sym))
- return 0;
- precbc = NULL;
- }
-
- if (precbc)
- sect = yasm_bc_get_section(precbc);
-
- if (entry && elf_sym_in_table(entry))
- ;
- else if (vis & YASM_SYM_GLOBAL) {
- entry = build_global(info->objfmt_elf, sym, info->object);
- yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
- } else {
- int is_sect = 0;
-
- /* Locals (except when debugging) do not need to be
- * in the symbol table, unless they're a section.
- */
- if (sect &&
- strcmp(yasm_symrec_get_name(sym), yasm_section_get_name(sect))==0)
- is_sect = 1;
-#if 0
- /* FIXME: to enable this we must have handling in place for special
- * symbols.
- */
- if (!info->local_names && !is_sect)
- return 0;
-#else
- if (yasm_symrec_get_equ(sym) && !yasm_symrec_is_abs(sym))
- return 0;
-#endif
- entry = yasm_symrec_get_data(sym, &elf_symrec_data);
- if (!entry) {
- /*@only@*/ char *symname =
- yasm_symrec_get_global_name(sym, info->object);
- elf_strtab_entry *name = !info->local_names || is_sect ? NULL :
- elf_strtab_append_str(info->objfmt_elf->strtab, symname);
- yasm_xfree(symname);
- entry = elf_symtab_entry_create(name, sym);
- yasm_symrec_add_data(sym, &elf_symrec_data, entry);
- }
-
- if (!elf_sym_in_table(entry))
- elf_symtab_insert_local_sym(info->objfmt_elf->elf_symtab, entry);
-
- elf_symtab_set_nonzero(entry, sect, 0, STB_LOCAL,
- is_sect ? STT_SECTION : 0, NULL, 0);
-
- if (is_sect)
- return 0;
- }
-
- if (precbc)
- value = yasm_bc_next_offset(precbc);
- elf_symtab_set_nonzero(entry, sect, 0, 0, 0, NULL, &value);
-
- return 0;
-}
-
-static yasm_objfmt *
-elf_objfmt_create_common(yasm_object *object, yasm_objfmt_module *module,
- int bits_pref,
- const elf_machine_handler **elf_march_out)
-{
- yasm_objfmt_elf *objfmt_elf = yasm_xmalloc(sizeof(yasm_objfmt_elf));
- yasm_symrec *filesym;
- elf_symtab_entry *entry;
- const elf_machine_handler *elf_march;
-
- objfmt_elf->objfmt.module = module;
- elf_march = elf_set_arch(object->arch, object->symtab, bits_pref);
- if (!elf_march) {
- yasm_xfree(objfmt_elf);
- return NULL;
- }
- if (elf_march_out)
- *elf_march_out = elf_march;
-
- objfmt_elf->shstrtab = elf_strtab_create();
- objfmt_elf->strtab = elf_strtab_create();
- objfmt_elf->elf_symtab = elf_symtab_create();
-
- /* FIXME: misuse of NULL bytecode here; it works, but only barely. */
- filesym = yasm_symtab_define_label(object->symtab, ".file", NULL, 0, 0);
+/*
+ * ELF object format
+ *
+ * Copyright (C) 2003-2007 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>
+
+/* Notes
+ *
+ * elf-objfmt uses the "linking" view of an ELF file:
+ * ELF header, an optional program header table, several sections,
+ * and a section header table
+ *
+ * The ELF header tells us some overall program information,
+ * where to find the PHT (if it exists) with phnum and phentsize,
+ * and where to find the SHT with shnum and shentsize
+ *
+ * The PHT doesn't seem to be generated by NASM for elftest.asm
+ *
+ * The SHT
+ *
+ * Each Section is spatially disjoint, and has exactly one SHT entry.
+ */
+
+#include <libyasm.h>
+
+#include "elf.h"
+#include "elf-machine.h"
+
+typedef struct yasm_objfmt_elf {
+ yasm_objfmt_base objfmt; /* base structure */
+
+ elf_symtab_head* elf_symtab; /* symbol table of indexed syms */
+ elf_strtab_head* shstrtab; /* section name strtab */
+ elf_strtab_head* strtab; /* strtab entries */
+
+ elf_strtab_entry *file_strtab_entry;/* .file symbol associated string */
+ yasm_symrec *dotdotsym; /* ..sym symbol */
+} yasm_objfmt_elf;
+
+typedef struct {
+ yasm_objfmt_elf *objfmt_elf;
+ yasm_errwarns *errwarns;
+ FILE *f;
+ elf_secthead *shead;
+ yasm_section *sect;
+ yasm_object *object;
+ unsigned long sindex;
+ yasm_symrec *GOT_sym;
+} elf_objfmt_output_info;
+
+typedef struct {
+ yasm_object *object;
+ yasm_objfmt_elf *objfmt_elf;
+ yasm_errwarns *errwarns;
+ int local_names;
+} build_symtab_info;
+
+yasm_objfmt_module yasm_elf_LTX_objfmt;
+yasm_objfmt_module yasm_elf32_LTX_objfmt;
+yasm_objfmt_module yasm_elf64_LTX_objfmt;
+yasm_objfmt_module yasm_elfx32_LTX_objfmt;
+
+
+static elf_symtab_entry *
+elf_objfmt_symtab_append(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym,
+ elf_section_index sectidx, elf_symbol_binding bind,
+ elf_symbol_type type, elf_symbol_vis vis,
+ yasm_expr *size, elf_address *value,
+ yasm_object *object)
+{
+ elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+
+ if (!entry) {
+ /*@only@*/ char *symname = yasm_symrec_get_global_name(sym, object);
+ elf_strtab_entry *name =
+ elf_strtab_append_str(objfmt_elf->strtab, symname);
+ yasm_xfree(symname);
+ entry = elf_symtab_entry_create(name, sym);
+ yasm_symrec_add_data(sym, &elf_symrec_data, entry);
+ }
+
+ /* Only append to table if not already appended */
+ if (!elf_sym_in_table(entry))
+ elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
+
+ elf_symtab_set_nonzero(entry, NULL, sectidx, bind, type, size, value);
+ elf_sym_set_visibility(entry, vis);
+
+ return entry;
+}
+
+static elf_symtab_entry *
+build_extern(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
+{
+ yasm_valparamhead *objext_valparams =
+ yasm_symrec_get_objext_valparams(sym);
+
+ if (objext_valparams) {
+ yasm_valparam *vp = yasm_vps_first(objext_valparams);
+ for (; vp; vp = yasm_vps_next(vp)) {
+ if (yasm_vp_string(vp))
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("unrecognized symbol type `%s'"),
+ yasm_vp_string(vp));
+ }
+ }
+
+ return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL, 0,
+ STV_DEFAULT, NULL, NULL, object);
+}
+
+struct elf_build_global_data {
+ yasm_expr *size;
+ unsigned long type; /* elf_symbol_type */
+ elf_symbol_vis vis;
+ unsigned int vis_overrides;
+};
+
+static int
+elf_global_helper_valparam(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d)
+
+{
+ struct elf_build_global_data *data = (struct elf_build_global_data *)d;
+ const char *s;
+
+ if (!vp->val && (s = yasm_vp_id(vp))) {
+ yasm_error_set(YASM_ERROR_TYPE, N_("unrecognized symbol type `%s'"),
+ s);
+ return -1;
+ } else if (!vp->val && vp->type == YASM_PARAM_EXPR && !data->size) {
+ data->size = yasm_expr_copy(vp->param.e);
+ return 0;
+ } else
+ return yasm_dir_helper_valparam_warn(obj, vp, line, d);
+}
+
+static int
+elf_global_helper_vis(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d, uintptr_t vis)
+{
+ struct elf_build_global_data *data = (struct elf_build_global_data *)d;
+ data->vis = vis;
+ data->vis_overrides++;
+ return 0;
+}
+
+
+static elf_symtab_entry *
+build_global(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
+{
+ yasm_valparamhead *objext_valparams =
+ yasm_symrec_get_objext_valparams(sym);
+
+ struct elf_build_global_data data;
+
+ static const yasm_dir_help help[] = {
+ { "function", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_build_global_data, type), STT_FUNC },
+ { "data", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_build_global_data, type), STT_OBJECT },
+ { "object", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_build_global_data, type), STT_OBJECT },
+ { "internal", 0, elf_global_helper_vis, 0, STV_INTERNAL },
+ { "hidden", 0, elf_global_helper_vis, 0, STV_HIDDEN },
+ { "protected", 0, elf_global_helper_vis, 0, STV_PROTECTED },
+ };
+
+ data.size = NULL;
+ data.type = 0;
+ data.vis = STV_DEFAULT;
+ data.vis_overrides = 0;
+
+ if (objext_valparams)
+ yasm_dir_helper(sym, yasm_vps_first(objext_valparams),
+ yasm_symrec_get_decl_line(sym), help, NELEMS(help),
+ &data, elf_global_helper_valparam);
+
+ if (data.vis_overrides > 1) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("More than one symbol visibility provided; using last"));
+ }
+
+ return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL,
+ data.type, data.vis, data.size, NULL,
+ object);
+}
+
+static /*@null@*/ elf_symtab_entry *
+build_common(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
+{
+ yasm_expr **size = yasm_symrec_get_common_size(sym);
+ yasm_valparamhead *objext_valparams =
+ yasm_symrec_get_objext_valparams(sym);
+ unsigned long addralign = 0;
+
+ if (objext_valparams) {
+ yasm_valparam *vp = yasm_vps_first(objext_valparams);
+ for (; vp; vp = yasm_vps_next(vp)) {
+ if (!vp->val) {
+ /*@only@*/ /*@null@*/ yasm_expr *align_expr;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *align_intn;
+
+ if (!(align_expr = yasm_vp_expr(vp, object->symtab,
+ yasm_symrec_get_def_line(sym)))
+ || !(align_intn = yasm_expr_get_intnum(&align_expr, 0))) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("alignment constraint is not an integer"));
+ if (align_expr)
+ yasm_expr_destroy(align_expr);
+ return NULL;
+ }
+ addralign = yasm_intnum_get_uint(align_intn);
+ yasm_expr_destroy(align_expr);
+
+ /* Alignments must be a power of two. */
+ if (!is_exp2(addralign)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("alignment constraint is not a power of two"));
+ return NULL;
+ }
+ } else
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("Unrecognized qualifier `%s'"), vp->val);
+ }
+ }
+
+ return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_COMMON, STB_GLOBAL,
+ 0, STV_DEFAULT, *size, &addralign, object);
+}
+
+static int
+elf_objfmt_build_symtab(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ build_symtab_info *info = (build_symtab_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+ yasm_sym_status status = yasm_symrec_get_status(sym);
+ elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+ elf_address value=0;
+ yasm_section *sect=NULL;
+ yasm_bytecode *precbc=NULL;
+
+ assert(info != NULL);
+
+ if (vis & YASM_SYM_EXTERN) {
+ entry = build_extern(info->objfmt_elf, sym, info->object);
+ yasm_errwarn_propagate(info->errwarns,
+ yasm_symrec_get_decl_line(sym));
+ return 0;
+ }
+
+ if (vis & YASM_SYM_COMMON) {
+ entry = build_common(info->objfmt_elf, sym, info->object);
+ yasm_errwarn_propagate(info->errwarns,
+ yasm_symrec_get_decl_line(sym));
+ /* If the COMMON variable was actually defined, fall through. */
+ if (!(status & YASM_SYM_DEFINED))
+ return 0;
+ }
+
+ /* Ignore any undefined at this point. */
+ if (!(status & YASM_SYM_DEFINED))
+ return 0;
+
+ if (!yasm_symrec_get_label(sym, &precbc)) {
+ if (!yasm_symrec_get_equ(sym) && !yasm_symrec_is_abs(sym))
+ return 0;
+ precbc = NULL;
+ }
+
+ if (precbc)
+ sect = yasm_bc_get_section(precbc);
+
+ if (entry && elf_sym_in_table(entry))
+ ;
+ else if (vis & YASM_SYM_GLOBAL) {
+ entry = build_global(info->objfmt_elf, sym, info->object);
+ yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
+ } else {
+ int is_sect = 0;
+
+ /* Locals (except when debugging) do not need to be
+ * in the symbol table, unless they're a section.
+ */
+ if (sect &&
+ strcmp(yasm_symrec_get_name(sym), yasm_section_get_name(sect))==0)
+ is_sect = 1;
+#if 0
+ /* FIXME: to enable this we must have handling in place for special
+ * symbols.
+ */
+ if (!info->local_names && !is_sect)
+ return 0;
+#else
+ if (yasm_symrec_get_equ(sym) && !yasm_symrec_is_abs(sym))
+ return 0;
+#endif
+ entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+ if (!entry) {
+ /*@only@*/ char *symname =
+ yasm_symrec_get_global_name(sym, info->object);
+ elf_strtab_entry *name = !info->local_names || is_sect ? NULL :
+ elf_strtab_append_str(info->objfmt_elf->strtab, symname);
+ yasm_xfree(symname);
+ entry = elf_symtab_entry_create(name, sym);
+ yasm_symrec_add_data(sym, &elf_symrec_data, entry);
+ }
+
+ if (!elf_sym_in_table(entry))
+ elf_symtab_insert_local_sym(info->objfmt_elf->elf_symtab, entry);
+
+ elf_symtab_set_nonzero(entry, sect, 0, STB_LOCAL,
+ is_sect ? STT_SECTION : 0, NULL, 0);
+
+ if (is_sect)
+ return 0;
+ }
+
+ if (precbc)
+ value = yasm_bc_next_offset(precbc);
+ elf_symtab_set_nonzero(entry, sect, 0, 0, 0, NULL, &value);
+
+ return 0;
+}
+
+static yasm_objfmt *
+elf_objfmt_create_common(yasm_object *object, yasm_objfmt_module *module,
+ int bits_pref,
+ const elf_machine_handler **elf_march_out)
+{
+ yasm_objfmt_elf *objfmt_elf = yasm_xmalloc(sizeof(yasm_objfmt_elf));
+ yasm_symrec *filesym;
+ elf_symtab_entry *entry;
+ const elf_machine_handler *elf_march;
+
+ objfmt_elf->objfmt.module = module;
+ elf_march = elf_set_arch(object->arch, object->symtab, bits_pref);
+ if (!elf_march) {
+ yasm_xfree(objfmt_elf);
+ return NULL;
+ }
+ if (elf_march_out)
+ *elf_march_out = elf_march;
+
+ objfmt_elf->shstrtab = elf_strtab_create();
+ objfmt_elf->strtab = elf_strtab_create();
+ objfmt_elf->elf_symtab = elf_symtab_create();
+
+ /* FIXME: misuse of NULL bytecode here; it works, but only barely. */
+ filesym = yasm_symtab_define_label(object->symtab, ".file", NULL, 0, 0);
if (!object->deb_filename) {
object->deb_filename = yasm_replace_path(
module->replace_map, module->replace_map_size,
object->src_filename, strlen(object->src_filename));
}
- /* Put in current input filename; we'll replace it in output() */
- objfmt_elf->file_strtab_entry =
+ /* Put in current input filename; we'll replace it in output() */
+ objfmt_elf->file_strtab_entry =
elf_strtab_append_str(objfmt_elf->strtab, object->deb_filename);
- entry = elf_symtab_entry_create(objfmt_elf->file_strtab_entry, filesym);
- yasm_symrec_add_data(filesym, &elf_symrec_data, entry);
- elf_symtab_set_nonzero(entry, NULL, SHN_ABS, STB_LOCAL, STT_FILE, NULL,
- NULL);
- elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
-
- /* FIXME: misuse of NULL bytecode */
- objfmt_elf->dotdotsym =
- yasm_symtab_define_label(object->symtab, "..sym", NULL, 0, 0);
-
- return (yasm_objfmt *)objfmt_elf;
-}
-
-static yasm_objfmt *
-elf_objfmt_create(yasm_object *object)
-{
- const elf_machine_handler *elf_march;
- yasm_objfmt *objfmt;
- yasm_objfmt_elf *objfmt_elf;
-
- objfmt = elf_objfmt_create_common(object, &yasm_elf_LTX_objfmt, 0,
- &elf_march);
- if (objfmt) {
- objfmt_elf = (yasm_objfmt_elf *)objfmt;
- /* Figure out which bitness of object format to use */
- if (strcmp (elf_march->machine, "x32") == 0)
- objfmt_elf->objfmt.module = &yasm_elfx32_LTX_objfmt;
- else if (elf_march->bits == 32)
- objfmt_elf->objfmt.module = &yasm_elf32_LTX_objfmt;
- else if (elf_march->bits == 64)
- objfmt_elf->objfmt.module = &yasm_elf64_LTX_objfmt;
- }
- return objfmt;
-}
-
-static yasm_objfmt *
-elf32_objfmt_create(yasm_object *object)
-{
- return elf_objfmt_create_common(object, &yasm_elf32_LTX_objfmt, 32, NULL);
-}
-
-static yasm_objfmt *
-elf64_objfmt_create(yasm_object *object)
-{
- return elf_objfmt_create_common(object, &yasm_elf64_LTX_objfmt, 64, NULL);
-}
-
-static yasm_objfmt *
-elfx32_objfmt_create(yasm_object *object)
-{
- return elf_objfmt_create_common(object, &yasm_elfx32_LTX_objfmt, 32, NULL);
-}
-
-static long
-elf_objfmt_output_align(FILE *f, unsigned int align)
-{
- long pos;
- unsigned long delta;
- if (!is_exp2(align))
- yasm_internal_error("requested alignment not a power of two");
-
- pos = ftell(f);
- if (pos == -1) {
- yasm_error_set(YASM_ERROR_IO,
- N_("could not get file position on output file"));
- return -1;
- }
- delta = align - (pos & (align-1));
- if (delta != align) {
- pos += delta;
- if (fseek(f, pos, SEEK_SET) < 0) {
- yasm_error_set(YASM_ERROR_IO,
- N_("could not set file position on output file"));
- return -1;
- }
- }
- return pos;
-}
-
-static int
-elf_objfmt_output_reloc(yasm_symrec *sym, yasm_bytecode *bc,
- unsigned char *buf, unsigned int destsize,
- unsigned int valsize, int warn, void *d)
-{
- elf_reloc_entry *reloc;
- elf_objfmt_output_info *info = d;
- yasm_intnum *zero;
- int retval;
-
- reloc = elf_reloc_entry_create(sym, NULL,
- yasm_intnum_create_uint(bc->offset), 0, valsize, 0);
- if (reloc == NULL) {
- yasm_error_set(YASM_ERROR_TYPE, N_("elf: invalid relocation size"));
- return 1;
- }
- /* allocate .rel[a] sections on a need-basis */
- elf_secthead_append_reloc(info->sect, info->shead, reloc);
-
- zero = yasm_intnum_create_uint(0);
- elf_handle_reloc_addend(zero, reloc, 0);
- retval = yasm_arch_intnum_tobytes(info->object->arch, zero, buf, destsize,
- valsize, 0, bc, warn);
- yasm_intnum_destroy(zero);
- return retval;
-}
-
-static int
-elf_objfmt_output_value(yasm_value *value, unsigned char *buf,
- unsigned int destsize, unsigned long offset,
- yasm_bytecode *bc, int warn, /*@null@*/ void *d)
-{
- /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
- /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
- unsigned long intn_val;
- /*@null@*/ elf_reloc_entry *reloc = NULL;
- int retval;
- unsigned int valsize = value->size;
-
- if (info == NULL)
- yasm_internal_error("null info struct");
-
- if (value->abs)
- value->abs = yasm_expr_simplify(value->abs, 1);
-
- /* Try to output constant and PC-relative section-local first.
- * Note this does NOT output any value with a SEG, WRT, external,
- * cross-section, or non-PC-relative reference (those are handled below).
- */
- switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
- info->object->arch)) {
- case -1:
- return 1;
- case 0:
- break;
- default:
- return 0;
- }
-
- /* Handle other expressions, with relocation if necessary */
- if (value->seg_of || value->section_rel || value->rshift > 0) {
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("elf: relocation too complex"));
- return 1;
- }
-
- intn_val = 0;
- if (value->rel) {
- yasm_sym_vis vis = yasm_symrec_get_visibility(value->rel);
- /*@dependent@*/ /*@null@*/ yasm_symrec *sym = value->rel;
- /*@dependent@*/ /*@null@*/ yasm_symrec *wrt = value->wrt;
-
- if (wrt == info->objfmt_elf->dotdotsym)
- wrt = NULL;
- else if (wrt && elf_is_wrt_sym_relative(wrt))
- ;
- else if (wrt && elf_is_wrt_pos_adjusted(wrt))
- intn_val = offset + bc->offset;
- else if (vis == YASM_SYM_LOCAL) {
- yasm_bytecode *sym_precbc;
- /* Local symbols need relocation to their section's start, and
- * add in the offset of the bytecode (within the target section)
- * into the abs portion.
- *
- * This is only done if the symbol is relocated against the
- * section instead of the symbol itself.
- */
- if (yasm_symrec_get_label(sym, &sym_precbc)) {
- /* Relocate to section start */
- yasm_section *sym_sect = yasm_bc_get_section(sym_precbc);
- /*@null@*/ elf_secthead *sym_shead;
- sym_shead = yasm_section_get_data(sym_sect, &elf_section_data);
- assert(sym_shead != NULL);
- sym = elf_secthead_get_sym(sym_shead);
-
- intn_val = yasm_bc_next_offset(sym_precbc);
- }
- }
-
- /* For PC-relative, need to add offset of expression within bc. */
- if (value->curpos_rel)
- intn_val += offset;
-
- /* Check for _GLOBAL_OFFSET_TABLE_ symbol reference */
- reloc = elf_reloc_entry_create(sym, wrt,
- yasm_intnum_create_uint(bc->offset + offset), value->curpos_rel,
- valsize, sym == info->GOT_sym);
- if (reloc == NULL) {
- yasm_error_set(YASM_ERROR_TYPE,
- N_("elf: invalid relocation (WRT or size)"));
- return 1;
- }
- /* allocate .rel[a] sections on a need-basis */
- elf_secthead_append_reloc(info->sect, info->shead, reloc);
- }
-
- intn = yasm_intnum_create_uint(intn_val);
-
- if (value->abs) {
- yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
- if (!intn2) {
- yasm_error_set(YASM_ERROR_TOO_COMPLEX,
- N_("elf: relocation too complex"));
- yasm_intnum_destroy(intn);
- return 1;
- }
- yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
- }
-
- if (reloc)
- elf_handle_reloc_addend(intn, reloc, offset);
- retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
- valsize, 0, bc, warn);
- yasm_intnum_destroy(intn);
- return retval;
-}
-
-static int
-elf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
-{
- /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
- unsigned char buf[256];
- /*@null@*/ /*@only@*/ unsigned char *bigbuf;
- unsigned long size = 256;
- int gap;
-
- if (info == NULL)
- yasm_internal_error("null info struct");
-
- bigbuf = yasm_bc_tobytes(bc, buf, &size, &gap, info,
- elf_objfmt_output_value, elf_objfmt_output_reloc);
-
- /* Don't bother doing anything else if size ended up being 0. */
- if (size == 0) {
- if (bigbuf)
- yasm_xfree(bigbuf);
- return 0;
- }
- else {
- yasm_intnum *bcsize = yasm_intnum_create_uint(size);
- elf_secthead_add_size(info->shead, bcsize);
- yasm_intnum_destroy(bcsize);
- }
-
- /* Warn that gaps are converted to 0 and write out the 0's. */
- if (gap) {
- unsigned long left;
- yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
- N_("uninitialized space declared in code/data section: zeroing"));
- /* Write out in chunks */
- memset(buf, 0, 256);
- left = size;
- while (left > 256) {
- fwrite(buf, 256, 1, info->f);
- left -= 256;
- }
- fwrite(buf, left, 1, info->f);
- } else {
- /* Output buf (or bigbuf if non-NULL) to file */
- fwrite(bigbuf ? bigbuf : buf, (size_t)size, 1, info->f);
- }
-
- /* If bigbuf was allocated, free it */
- if (bigbuf)
- yasm_xfree(bigbuf);
-
- return 0;
-}
-
-static int
-elf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
-{
- /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
- /*@dependent@*/ /*@null@*/ elf_secthead *shead;
- long pos;
- char *relname;
- const char *sectname;
-
- if (info == NULL)
- yasm_internal_error("null info struct");
- shead = yasm_section_get_data(sect, &elf_section_data);
- if (shead == NULL)
- yasm_internal_error("no associated data");
-
- if (elf_secthead_get_align(shead) == 0)
- elf_secthead_set_align(shead, yasm_section_get_align(sect));
-
- /* don't output header-only sections */
- if ((elf_secthead_get_type(shead) & SHT_NOBITS) == SHT_NOBITS)
- {
- yasm_bytecode *last = yasm_section_bcs_last(sect);
- if (last) {
- yasm_intnum *sectsize;
- sectsize = yasm_intnum_create_uint(yasm_bc_next_offset(last));
- elf_secthead_add_size(shead, sectsize);
- yasm_intnum_destroy(sectsize);
- }
- elf_secthead_set_index(shead, ++info->sindex);
- return 0;
- }
-
- if ((pos = ftell(info->f)) == -1) {
- yasm_error_set(YASM_ERROR_IO,
- N_("couldn't read position on output stream"));
- yasm_errwarn_propagate(info->errwarns, 0);
- }
- pos = elf_secthead_set_file_offset(shead, pos);
- if (fseek(info->f, pos, SEEK_SET) < 0) {
- yasm_error_set(YASM_ERROR_IO, N_("couldn't seek on output stream"));
- yasm_errwarn_propagate(info->errwarns, 0);
- }
-
- info->sect = sect;
- info->shead = shead;
- yasm_section_bcs_traverse(sect, info->errwarns, info,
- elf_objfmt_output_bytecode);
-
- elf_secthead_set_index(shead, ++info->sindex);
-
- /* No relocations to output? Go on to next section */
- if (elf_secthead_write_relocs_to_file(info->f, sect, shead,
- info->errwarns) == 0)
- return 0;
- elf_secthead_set_rel_index(shead, ++info->sindex);
-
- /* name the relocation section .rel[a].foo */
- sectname = yasm_section_get_name(sect);
- relname = elf_secthead_name_reloc_section(sectname);
- elf_secthead_set_rel_name(shead,
- elf_strtab_append_str(info->objfmt_elf->shstrtab, relname));
- yasm_xfree(relname);
-
- return 0;
-}
-
-static int
-elf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
-{
- /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
- /*@dependent@*/ /*@null@*/ elf_secthead *shead;
-
- if (info == NULL)
- yasm_internal_error("null info struct");
- shead = yasm_section_get_data(sect, &elf_section_data);
- if (shead == NULL)
- yasm_internal_error("no section header attached to section");
-
- if(elf_secthead_write_to_file(info->f, shead, info->sindex+1))
- info->sindex++;
-
- /* output strtab headers here? */
-
- /* relocation entries for .foo are stored in section .rel[a].foo */
- if(elf_secthead_write_rel_to_file(info->f, 3, sect, shead,
- info->sindex+1))
- info->sindex++;
-
- return 0;
-}
-
-static void
-elf_objfmt_output(yasm_object *object, FILE *f, int all_syms,
- yasm_errwarns *errwarns)
-{
- yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
- elf_objfmt_output_info info;
- build_symtab_info buildsym_info;
- long pos;
- unsigned long elf_shead_addr;
- elf_secthead *esdn;
- unsigned long elf_strtab_offset, elf_shstrtab_offset, elf_symtab_offset;
- unsigned long elf_strtab_size, elf_shstrtab_size, elf_symtab_size;
- elf_strtab_entry *elf_strtab_name, *elf_shstrtab_name, *elf_symtab_name;
- unsigned long elf_symtab_nlocal;
-
- info.object = object;
- info.objfmt_elf = objfmt_elf;
- info.errwarns = errwarns;
- info.f = f;
- info.GOT_sym = yasm_symtab_get(object->symtab, "_GLOBAL_OFFSET_TABLE_");
-
+ entry = elf_symtab_entry_create(objfmt_elf->file_strtab_entry, filesym);
+ yasm_symrec_add_data(filesym, &elf_symrec_data, entry);
+ elf_symtab_set_nonzero(entry, NULL, SHN_ABS, STB_LOCAL, STT_FILE, NULL,
+ NULL);
+ elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
+
+ /* FIXME: misuse of NULL bytecode */
+ objfmt_elf->dotdotsym =
+ yasm_symtab_define_label(object->symtab, "..sym", NULL, 0, 0);
+
+ return (yasm_objfmt *)objfmt_elf;
+}
+
+static yasm_objfmt *
+elf_objfmt_create(yasm_object *object)
+{
+ const elf_machine_handler *elf_march;
+ yasm_objfmt *objfmt;
+ yasm_objfmt_elf *objfmt_elf;
+
+ objfmt = elf_objfmt_create_common(object, &yasm_elf_LTX_objfmt, 0,
+ &elf_march);
+ if (objfmt) {
+ objfmt_elf = (yasm_objfmt_elf *)objfmt;
+ /* Figure out which bitness of object format to use */
+ if (strcmp (elf_march->machine, "x32") == 0)
+ objfmt_elf->objfmt.module = &yasm_elfx32_LTX_objfmt;
+ else if (elf_march->bits == 32)
+ objfmt_elf->objfmt.module = &yasm_elf32_LTX_objfmt;
+ else if (elf_march->bits == 64)
+ objfmt_elf->objfmt.module = &yasm_elf64_LTX_objfmt;
+ }
+ return objfmt;
+}
+
+static yasm_objfmt *
+elf32_objfmt_create(yasm_object *object)
+{
+ return elf_objfmt_create_common(object, &yasm_elf32_LTX_objfmt, 32, NULL);
+}
+
+static yasm_objfmt *
+elf64_objfmt_create(yasm_object *object)
+{
+ return elf_objfmt_create_common(object, &yasm_elf64_LTX_objfmt, 64, NULL);
+}
+
+static yasm_objfmt *
+elfx32_objfmt_create(yasm_object *object)
+{
+ return elf_objfmt_create_common(object, &yasm_elfx32_LTX_objfmt, 32, NULL);
+}
+
+static long
+elf_objfmt_output_align(FILE *f, unsigned int align)
+{
+ long pos;
+ unsigned long delta;
+ if (!is_exp2(align))
+ yasm_internal_error("requested alignment not a power of two");
+
+ pos = ftell(f);
+ if (pos == -1) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("could not get file position on output file"));
+ return -1;
+ }
+ delta = align - (pos & (align-1));
+ if (delta != align) {
+ pos += delta;
+ if (fseek(f, pos, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("could not set file position on output file"));
+ return -1;
+ }
+ }
+ return pos;
+}
+
+static int
+elf_objfmt_output_reloc(yasm_symrec *sym, yasm_bytecode *bc,
+ unsigned char *buf, unsigned int destsize,
+ unsigned int valsize, int warn, void *d)
+{
+ elf_reloc_entry *reloc;
+ elf_objfmt_output_info *info = d;
+ yasm_intnum *zero;
+ int retval;
+
+ reloc = elf_reloc_entry_create(sym, NULL,
+ yasm_intnum_create_uint(bc->offset), 0, valsize, 0);
+ if (reloc == NULL) {
+ yasm_error_set(YASM_ERROR_TYPE, N_("elf: invalid relocation size"));
+ return 1;
+ }
+ /* allocate .rel[a] sections on a need-basis */
+ elf_secthead_append_reloc(info->sect, info->shead, reloc);
+
+ zero = yasm_intnum_create_uint(0);
+ elf_handle_reloc_addend(zero, reloc, 0);
+ retval = yasm_arch_intnum_tobytes(info->object->arch, zero, buf, destsize,
+ valsize, 0, bc, warn);
+ yasm_intnum_destroy(zero);
+ return retval;
+}
+
+static int
+elf_objfmt_output_value(yasm_value *value, unsigned char *buf,
+ unsigned int destsize, unsigned long offset,
+ yasm_bytecode *bc, int warn, /*@null@*/ void *d)
+{
+ /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+ unsigned long intn_val;
+ /*@null@*/ elf_reloc_entry *reloc = NULL;
+ int retval;
+ unsigned int valsize = value->size;
+
+ if (info == NULL)
+ yasm_internal_error("null info struct");
+
+ if (value->abs)
+ value->abs = yasm_expr_simplify(value->abs, 1);
+
+ /* Try to output constant and PC-relative section-local first.
+ * Note this does NOT output any value with a SEG, WRT, external,
+ * cross-section, or non-PC-relative reference (those are handled below).
+ */
+ switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
+ info->object->arch)) {
+ case -1:
+ return 1;
+ case 0:
+ break;
+ default:
+ return 0;
+ }
+
+ /* Handle other expressions, with relocation if necessary */
+ if (value->seg_of || value->section_rel || value->rshift > 0) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("elf: relocation too complex"));
+ return 1;
+ }
+
+ intn_val = 0;
+ if (value->rel) {
+ yasm_sym_vis vis = yasm_symrec_get_visibility(value->rel);
+ /*@dependent@*/ /*@null@*/ yasm_symrec *sym = value->rel;
+ /*@dependent@*/ /*@null@*/ yasm_symrec *wrt = value->wrt;
+
+ if (wrt == info->objfmt_elf->dotdotsym)
+ wrt = NULL;
+ else if (wrt && elf_is_wrt_sym_relative(wrt))
+ ;
+ else if (wrt && elf_is_wrt_pos_adjusted(wrt))
+ intn_val = offset + bc->offset;
+ else if (vis == YASM_SYM_LOCAL) {
+ yasm_bytecode *sym_precbc;
+ /* Local symbols need relocation to their section's start, and
+ * add in the offset of the bytecode (within the target section)
+ * into the abs portion.
+ *
+ * This is only done if the symbol is relocated against the
+ * section instead of the symbol itself.
+ */
+ if (yasm_symrec_get_label(sym, &sym_precbc)) {
+ /* Relocate to section start */
+ yasm_section *sym_sect = yasm_bc_get_section(sym_precbc);
+ /*@null@*/ elf_secthead *sym_shead;
+ sym_shead = yasm_section_get_data(sym_sect, &elf_section_data);
+ assert(sym_shead != NULL);
+ sym = elf_secthead_get_sym(sym_shead);
+
+ intn_val = yasm_bc_next_offset(sym_precbc);
+ }
+ }
+
+ /* For PC-relative, need to add offset of expression within bc. */
+ if (value->curpos_rel)
+ intn_val += offset;
+
+ /* Check for _GLOBAL_OFFSET_TABLE_ symbol reference */
+ reloc = elf_reloc_entry_create(sym, wrt,
+ yasm_intnum_create_uint(bc->offset + offset), value->curpos_rel,
+ valsize, sym == info->GOT_sym);
+ if (reloc == NULL) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("elf: invalid relocation (WRT or size)"));
+ return 1;
+ }
+ /* allocate .rel[a] sections on a need-basis */
+ elf_secthead_append_reloc(info->sect, info->shead, reloc);
+ }
+
+ intn = yasm_intnum_create_uint(intn_val);
+
+ if (value->abs) {
+ yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
+ if (!intn2) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("elf: relocation too complex"));
+ yasm_intnum_destroy(intn);
+ return 1;
+ }
+ yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
+ }
+
+ if (reloc)
+ elf_handle_reloc_addend(intn, reloc, offset);
+ retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
+ valsize, 0, bc, warn);
+ yasm_intnum_destroy(intn);
+ return retval;
+}
+
+static int
+elf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+ /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
+ unsigned char buf[256];
+ /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+ unsigned long size = 256;
+ int gap;
+
+ if (info == NULL)
+ yasm_internal_error("null info struct");
+
+ bigbuf = yasm_bc_tobytes(bc, buf, &size, &gap, info,
+ elf_objfmt_output_value, elf_objfmt_output_reloc);
+
+ /* Don't bother doing anything else if size ended up being 0. */
+ if (size == 0) {
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+ return 0;
+ }
+ else {
+ yasm_intnum *bcsize = yasm_intnum_create_uint(size);
+ elf_secthead_add_size(info->shead, bcsize);
+ yasm_intnum_destroy(bcsize);
+ }
+
+ /* Warn that gaps are converted to 0 and write out the 0's. */
+ if (gap) {
+ unsigned long left;
+ yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
+ N_("uninitialized space declared in code/data section: zeroing"));
+ /* Write out in chunks */
+ memset(buf, 0, 256);
+ left = size;
+ while (left > 256) {
+ fwrite(buf, 256, 1, info->f);
+ left -= 256;
+ }
+ fwrite(buf, left, 1, info->f);
+ } else {
+ /* Output buf (or bigbuf if non-NULL) to file */
+ fwrite(bigbuf ? bigbuf : buf, (size_t)size, 1, info->f);
+ }
+
+ /* If bigbuf was allocated, free it */
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+
+ return 0;
+}
+
+static int
+elf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ elf_secthead *shead;
+ long pos;
+ char *relname;
+ const char *sectname;
+
+ if (info == NULL)
+ yasm_internal_error("null info struct");
+ shead = yasm_section_get_data(sect, &elf_section_data);
+ if (shead == NULL)
+ yasm_internal_error("no associated data");
+
+ if (elf_secthead_get_align(shead) == 0)
+ elf_secthead_set_align(shead, yasm_section_get_align(sect));
+
+ /* don't output header-only sections */
+ if ((elf_secthead_get_type(shead) & SHT_NOBITS) == SHT_NOBITS)
+ {
+ yasm_bytecode *last = yasm_section_bcs_last(sect);
+ if (last) {
+ yasm_intnum *sectsize;
+ sectsize = yasm_intnum_create_uint(yasm_bc_next_offset(last));
+ elf_secthead_add_size(shead, sectsize);
+ yasm_intnum_destroy(sectsize);
+ }
+ elf_secthead_set_index(shead, ++info->sindex);
+ return 0;
+ }
+
+ if ((pos = ftell(info->f)) == -1) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("couldn't read position on output stream"));
+ yasm_errwarn_propagate(info->errwarns, 0);
+ }
+ pos = elf_secthead_set_file_offset(shead, pos);
+ if (fseek(info->f, pos, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO, N_("couldn't seek on output stream"));
+ yasm_errwarn_propagate(info->errwarns, 0);
+ }
+
+ info->sect = sect;
+ info->shead = shead;
+ yasm_section_bcs_traverse(sect, info->errwarns, info,
+ elf_objfmt_output_bytecode);
+
+ elf_secthead_set_index(shead, ++info->sindex);
+
+ /* No relocations to output? Go on to next section */
+ if (elf_secthead_write_relocs_to_file(info->f, sect, shead,
+ info->errwarns) == 0)
+ return 0;
+ elf_secthead_set_rel_index(shead, ++info->sindex);
+
+ /* name the relocation section .rel[a].foo */
+ sectname = yasm_section_get_name(sect);
+ relname = elf_secthead_name_reloc_section(sectname);
+ elf_secthead_set_rel_name(shead,
+ elf_strtab_append_str(info->objfmt_elf->shstrtab, relname));
+ yasm_xfree(relname);
+
+ return 0;
+}
+
+static int
+elf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ elf_secthead *shead;
+
+ if (info == NULL)
+ yasm_internal_error("null info struct");
+ shead = yasm_section_get_data(sect, &elf_section_data);
+ if (shead == NULL)
+ yasm_internal_error("no section header attached to section");
+
+ if(elf_secthead_write_to_file(info->f, shead, info->sindex+1))
+ info->sindex++;
+
+ /* output strtab headers here? */
+
+ /* relocation entries for .foo are stored in section .rel[a].foo */
+ if(elf_secthead_write_rel_to_file(info->f, 3, sect, shead,
+ info->sindex+1))
+ info->sindex++;
+
+ return 0;
+}
+
+static void
+elf_objfmt_output(yasm_object *object, FILE *f, int all_syms,
+ yasm_errwarns *errwarns)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ elf_objfmt_output_info info;
+ build_symtab_info buildsym_info;
+ long pos;
+ unsigned long elf_shead_addr;
+ elf_secthead *esdn;
+ unsigned long elf_strtab_offset, elf_shstrtab_offset, elf_symtab_offset;
+ unsigned long elf_strtab_size, elf_shstrtab_size, elf_symtab_size;
+ elf_strtab_entry *elf_strtab_name, *elf_shstrtab_name, *elf_symtab_name;
+ unsigned long elf_symtab_nlocal;
+
+ info.object = object;
+ info.objfmt_elf = objfmt_elf;
+ info.errwarns = errwarns;
+ info.f = f;
+ info.GOT_sym = yasm_symtab_get(object->symtab, "_GLOBAL_OFFSET_TABLE_");
+
if (!object->deb_filename) {
object->deb_filename = yasm_replace_path(
objfmt_elf->objfmt.module->replace_map, objfmt_elf->objfmt.module->replace_map_size,
object->src_filename, strlen(object->src_filename));
}
- /* Update filename strtab */
- elf_strtab_entry_set_str(objfmt_elf->file_strtab_entry,
+ /* Update filename strtab */
+ elf_strtab_entry_set_str(objfmt_elf->file_strtab_entry,
object->deb_filename);
-
- /* Allocate space for Ehdr by seeking forward */
- if (fseek(f, (long)(elf_proghead_get_size()), SEEK_SET) < 0) {
- yasm_error_set(YASM_ERROR_IO, N_("could not seek on output file"));
- yasm_errwarn_propagate(errwarns, 0);
- return;
- }
-
- /* add all (local) syms to symtab because relocation needs a symtab index
- * if all_syms, register them by name. if not, use strtab entry 0 */
- buildsym_info.object = object;
- buildsym_info.objfmt_elf = objfmt_elf;
- buildsym_info.errwarns = errwarns;
- buildsym_info.local_names = all_syms;
- yasm_symtab_traverse(object->symtab, &buildsym_info,
- elf_objfmt_build_symtab);
- elf_symtab_nlocal = elf_symtab_assign_indices(objfmt_elf->elf_symtab);
-
- /* output known sections - includes reloc sections which aren't in yasm's
- * list. Assign indices as we go. */
- info.sindex = 3;
- if (yasm_object_sections_traverse(object, &info,
- elf_objfmt_output_section))
- return;
-
- /* add final sections to the shstrtab */
- elf_strtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".strtab");
- elf_symtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".symtab");
- elf_shstrtab_name = elf_strtab_append_str(objfmt_elf->shstrtab,
- ".shstrtab");
-
- /* output .shstrtab */
- if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
- yasm_errwarn_propagate(errwarns, 0);
- return;
- }
- elf_shstrtab_offset = (unsigned long) pos;
- elf_shstrtab_size = elf_strtab_output_to_file(f, objfmt_elf->shstrtab);
-
- /* output .strtab */
- if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
- yasm_errwarn_propagate(errwarns, 0);
- return;
- }
- elf_strtab_offset = (unsigned long) pos;
- elf_strtab_size = elf_strtab_output_to_file(f, objfmt_elf->strtab);
-
- /* output .symtab - last section so all others have indexes */
- if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
- yasm_errwarn_propagate(errwarns, 0);
- return;
- }
- elf_symtab_offset = (unsigned long) pos;
- elf_symtab_size = elf_symtab_write_to_file(f, objfmt_elf->elf_symtab,
- errwarns);
-
- /* output section header table */
- if ((pos = elf_objfmt_output_align(f, 16)) == -1) {
- yasm_errwarn_propagate(errwarns, 0);
- return;
- }
- elf_shead_addr = (unsigned long) pos;
-
- /* stabs debugging support */
- if (strcmp(yasm_dbgfmt_keyword(object->dbgfmt), "stabs")==0) {
- yasm_section *stabsect = yasm_object_find_general(object, ".stab");
- yasm_section *stabstrsect =
- yasm_object_find_general(object, ".stabstr");
- if (stabsect && stabstrsect) {
- elf_secthead *stab =
- yasm_section_get_data(stabsect, &elf_section_data);
- elf_secthead *stabstr =
- yasm_section_get_data(stabstrsect, &elf_section_data);
- if (stab && stabstr) {
- elf_secthead_set_link(stab, elf_secthead_get_index(stabstr));
- }
- else
- yasm_internal_error(N_("missing .stab or .stabstr section/data"));
- }
- }
-
- /* output dummy section header - 0 */
- info.sindex = 0;
-
- esdn = elf_secthead_create(NULL, SHT_NULL, 0, 0, 0);
- elf_secthead_set_index(esdn, 0);
- elf_secthead_write_to_file(f, esdn, 0);
- elf_secthead_destroy(esdn);
-
- esdn = elf_secthead_create(elf_shstrtab_name, SHT_STRTAB, 0,
- elf_shstrtab_offset, elf_shstrtab_size);
- elf_secthead_set_index(esdn, 1);
- elf_secthead_write_to_file(f, esdn, 1);
- elf_secthead_destroy(esdn);
-
- esdn = elf_secthead_create(elf_strtab_name, SHT_STRTAB, 0,
- elf_strtab_offset, elf_strtab_size);
- elf_secthead_set_index(esdn, 2);
- elf_secthead_write_to_file(f, esdn, 2);
- elf_secthead_destroy(esdn);
-
- esdn = elf_secthead_create(elf_symtab_name, SHT_SYMTAB, 0,
- elf_symtab_offset, elf_symtab_size);
- elf_secthead_set_index(esdn, 3);
- elf_secthead_set_info(esdn, elf_symtab_nlocal);
- elf_secthead_set_link(esdn, 2); /* for .strtab, which is index 2 */
- elf_secthead_write_to_file(f, esdn, 3);
- elf_secthead_destroy(esdn);
-
- info.sindex = 3;
- /* output remaining section headers */
- yasm_object_sections_traverse(object, &info, elf_objfmt_output_secthead);
-
- /* output Ehdr */
- if (fseek(f, 0, SEEK_SET) < 0) {
- yasm_error_set(YASM_ERROR_IO, N_("could not seek on output file"));
- yasm_errwarn_propagate(errwarns, 0);
- return;
- }
-
- elf_proghead_write_to_file(f, elf_shead_addr, info.sindex+1, 1);
-}
-
-static void
-elf_objfmt_destroy(yasm_objfmt *objfmt)
-{
- yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt;
- elf_symtab_destroy(objfmt_elf->elf_symtab);
- elf_strtab_destroy(objfmt_elf->shstrtab);
- elf_strtab_destroy(objfmt_elf->strtab);
- yasm_xfree(objfmt);
-}
-
-static void
-elf_objfmt_init_new_section(yasm_section *sect, unsigned long line)
-{
- yasm_object *object = yasm_section_get_object(sect);
- const char *sectname = yasm_section_get_name(sect);
- yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
- elf_secthead *esd;
- yasm_symrec *sym;
- elf_strtab_entry *name = elf_strtab_append_str(objfmt_elf->shstrtab,
- sectname);
-
- elf_section_type type=SHT_PROGBITS;
- elf_size entsize=0;
-
- if (yasm__strcasecmp(sectname, ".stab")==0) {
- entsize = 12;
- } else if (yasm__strcasecmp(sectname, ".stabstr")==0) {
- type = SHT_STRTAB;
- }
-
- esd = elf_secthead_create(name, type, 0, 0, 0);
- elf_secthead_set_entsize(esd, entsize);
- yasm_section_add_data(sect, &elf_section_data, esd);
- sym = yasm_symtab_define_label(object->symtab, sectname,
- yasm_section_bcs_first(sect), 1, line);
-
- elf_secthead_set_sym(esd, sym);
-}
-
-static yasm_section *
-elf_objfmt_add_default_section(yasm_object *object)
-{
- yasm_section *retval;
- int isnew;
-
- retval = yasm_object_get_general(object, ".text", 16, 1, 0, &isnew, 0);
- if (isnew)
- {
- elf_secthead *esd = yasm_section_get_data(retval, &elf_section_data);
- elf_secthead_set_typeflags(esd, SHT_PROGBITS,
- SHF_ALLOC + SHF_EXECINSTR);
- yasm_section_set_default(retval, 1);
- }
- return retval;
-}
-
-struct elf_section_switch_data {
- /*@only@*/ /*@null@*/ yasm_intnum *align_intn;
- unsigned long flags;
- unsigned long type;
- int gasflags;
- int stdsect;
-};
-
-/* GAS-style flags */
-static int
-elf_helper_gasflags(void *obj, yasm_valparam *vp, unsigned long line, void *d,
- /*@unused@*/ uintptr_t arg)
-{
- struct elf_section_switch_data *data = (struct elf_section_switch_data *)d;
- const char *s = yasm_vp_string(vp);
- size_t i;
-
- if (!s) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("non-string section attribute"));
- return -1;
- }
-
- if (data->stdsect && strlen(s) == 0) {
- data->gasflags = 1;
- return 0;
- }
-
- data->flags = 0;
- for (i=0; i<strlen(s); i++) {
- switch (s[i]) {
- case 'a':
- data->flags |= SHF_ALLOC;
- break;
- case 'w':
- data->flags |= SHF_WRITE;
- break;
- case 'x':
- data->flags |= SHF_EXECINSTR;
- break;
- case 'M':
- data->flags |= SHF_MERGE;
- break;
- case 'S':
- data->flags |= SHF_STRINGS;
- break;
- case 'G':
- data->flags |= SHF_GROUP;
- break;
- case 'T':
- data->flags |= SHF_TLS;
- break;
- default:
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("unrecognized section attribute: `%c'"),
- s[i]);
- }
- }
-
- data->gasflags = 1;
- return 0;
-}
-
-static /*@observer@*/ /*@null@*/ yasm_section *
-elf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
- /*@null@*/ yasm_valparamhead *objext_valparams,
- unsigned long line)
-{
- yasm_valparam *vp;
- yasm_section *retval;
- int isnew;
- unsigned long align = 4;
- int flags_override = 0;
- const char *sectname;
- int resonly = 0;
-
- struct elf_section_switch_data data;
-
- static const yasm_dir_help help[] = {
- { "alloc", 0, yasm_dir_helper_flag_or,
- offsetof(struct elf_section_switch_data, flags), SHF_ALLOC },
- { "exec", 0, yasm_dir_helper_flag_or,
- offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR },
- { "write", 0, yasm_dir_helper_flag_or,
- offsetof(struct elf_section_switch_data, flags), SHF_WRITE },
- { "tls", 0, yasm_dir_helper_flag_or,
- offsetof(struct elf_section_switch_data, flags), SHF_TLS },
- { "progbits", 0, yasm_dir_helper_flag_set,
- offsetof(struct elf_section_switch_data, type), SHT_PROGBITS },
- { "noalloc", 0, yasm_dir_helper_flag_and,
- offsetof(struct elf_section_switch_data, flags), SHF_ALLOC },
- { "noexec", 0, yasm_dir_helper_flag_and,
- offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR },
- { "nowrite", 0, yasm_dir_helper_flag_and,
- offsetof(struct elf_section_switch_data, flags), SHF_WRITE },
- { "notls", 0, yasm_dir_helper_flag_and,
- offsetof(struct elf_section_switch_data, flags), SHF_TLS },
- { "noprogbits", 0, yasm_dir_helper_flag_set,
- offsetof(struct elf_section_switch_data, type), SHT_NOBITS },
- { "nobits", 0, yasm_dir_helper_flag_set,
- offsetof(struct elf_section_switch_data, type), SHT_NOBITS },
- { "gasflags", 1, elf_helper_gasflags, 0, 0 },
- { "align", 1, yasm_dir_helper_intn,
- offsetof(struct elf_section_switch_data, align_intn), 0 }
- };
- /*@only@*/ /*@null@*/ yasm_expr *merge_expr = NULL;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *merge_intn = NULL;
- elf_secthead *esd;
-
- data.align_intn = NULL;
- data.flags = SHF_ALLOC;
- data.type = SHT_PROGBITS;
- data.gasflags = 0;
- data.stdsect = 1;
-
- vp = yasm_vps_first(valparams);
- sectname = yasm_vp_string(vp);
- if (!sectname)
- return NULL;
- vp = yasm_vps_next(vp);
-
- if (strcmp(sectname, ".bss") == 0) {
- data.type = SHT_NOBITS;
- data.flags = SHF_ALLOC + SHF_WRITE;
- resonly = 1;
- } else if (strcmp(sectname, ".data") == 0) {
- data.type = SHT_PROGBITS;
- data.flags = SHF_ALLOC + SHF_WRITE;
- } else if (strcmp(sectname, ".tdata") == 0) {
- data.type = SHT_PROGBITS;
- data.flags = SHF_ALLOC + SHF_WRITE + SHF_TLS;
- } else if (strcmp(sectname, ".rodata") == 0) {
- data.type = SHT_PROGBITS;
- data.flags = SHF_ALLOC;
- } else if (strcmp(sectname, ".text") == 0) {
- align = 16;
- data.type = SHT_PROGBITS;
- data.flags = SHF_ALLOC + SHF_EXECINSTR;
- } else if (strcmp(sectname, ".comment") == 0) {
- align = 0;
- data.type = SHT_PROGBITS;
- data.flags = 0;
- } else {
- /* Default to code */
- align = 1;
- data.stdsect = 0;
- }
-
- flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
- &data, yasm_dir_helper_valparam_warn);
- if (flags_override < 0)
- return NULL; /* error occurred */
-
- if (data.align_intn) {
- align = yasm_intnum_get_uint(data.align_intn);
- yasm_intnum_destroy(data.align_intn);
-
- /* Alignments must be a power of two. */
- if (!is_exp2(align)) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("argument to `%s' is not a power of two"),
- "align");
- return NULL;
- }
- }
-
- /* Handle merge entity size */
- if (data.flags & SHF_MERGE) {
- if (objext_valparams && (vp = yasm_vps_first(objext_valparams))
- && !vp->val) {
- if (!(merge_expr = yasm_vp_expr(vp, object->symtab, line)) ||
- !(merge_intn = yasm_expr_get_intnum(&merge_expr, 0)))
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("invalid merge entity size"));
- } else {
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("entity size for SHF_MERGE not specified"));
- data.flags &= ~SHF_MERGE;
- }
- }
-
- retval = yasm_object_get_general(object, sectname, align,
- (data.flags & SHF_EXECINSTR) != 0,
- resonly, &isnew, line);
-
- esd = yasm_section_get_data(retval, &elf_section_data);
-
- if (isnew || yasm_section_is_default(retval)) {
- yasm_section_set_default(retval, 0);
- elf_secthead_set_typeflags(esd, data.type, data.flags);
- if (merge_intn)
- elf_secthead_set_entsize(esd, yasm_intnum_get_uint(merge_intn));
- yasm_section_set_align(retval, align, line);
- } else if (flags_override && !data.gasflags)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("section flags ignored on section redeclaration"));
- if (merge_expr)
- yasm_expr_destroy(merge_expr);
- return retval;
-}
-
-static /*@observer@*/ /*@null@*/ yasm_symrec *
-elf_objfmt_get_special_sym(yasm_object *object, const char *name,
- const char *parser)
-{
- if (yasm__strcasecmp(name, "sym") == 0) {
- yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
- return objfmt_elf->dotdotsym;
- }
- return elf_get_special_sym(name, parser);
-}
-
-static void
-dir_type(yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
-{
- yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
- yasm_valparam *vp = yasm_vps_first(valparams);
- const char *symname = yasm_vp_id(vp);
- /* Get symbol elf data */
- yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line);
- elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
- /*@null@*/ const char *type;
-
- /* Create entry if necessary */
- if (!entry) {
- entry = elf_symtab_entry_create(
- elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
- yasm_symrec_add_data(sym, &elf_symrec_data, entry);
- }
-
- /* Pull new type from param */
- vp = yasm_vps_next(vp);
- if (vp && !vp->val && (type = yasm_vp_id(vp))) {
- if (yasm__strcasecmp(type, "function") == 0)
- elf_sym_set_type(entry, STT_FUNC);
- else if (yasm__strcasecmp(type, "object") == 0)
- elf_sym_set_type(entry, STT_OBJECT);
- else if (yasm__strcasecmp(type, "tls_object") == 0)
- elf_sym_set_type(entry, STT_TLS);
- else if (yasm__strcasecmp(type, "notype") == 0)
- elf_sym_set_type(entry, STT_NOTYPE);
- else
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("unrecognized symbol type `%s'"), type);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("no type specified"));
-}
-
-static void
-dir_size(yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
-{
- yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
- yasm_valparam *vp = yasm_vps_first(valparams);
- const char *symname = yasm_vp_id(vp);
- /* Get symbol elf data */
- yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line);
- elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
- /*@only@*/ /*@null@*/ yasm_expr *size;
-
- /* Create entry if necessary */
- if (!entry) {
- entry = elf_symtab_entry_create(
- elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
- yasm_symrec_add_data(sym, &elf_symrec_data, entry);
- }
-
- /* Pull new size from param */
- vp = yasm_vps_next(vp);
- if (vp && !vp->val && (size = yasm_vp_expr(vp, object->symtab, line)))
- elf_sym_set_size(entry, size);
- else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("no size specified"));
-}
-
-static void
-dir_weak(yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
-{
- yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
- yasm_valparam *vp = yasm_vps_first(valparams);
- const char *symname = yasm_vp_id(vp);
- yasm_symrec *sym = yasm_symtab_declare(object->symtab, symname,
- YASM_SYM_GLOBAL, line);
- elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK, 0,
- STV_DEFAULT, NULL, NULL, object);
-}
-
-static void
-dir_ident(yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
-{
- yasm_valparamhead sect_vps;
- yasm_datavalhead dvs;
- yasm_section *comment;
- yasm_valparam *vp;
- yasm_valparam *vp2;
-
- /* Accept, but do nothing with empty ident */
- if (!valparams)
- return;
- vp = yasm_vps_first(valparams);
- if (!vp)
- return;
-
- /* Put ident data into .comment section */
- yasm_vps_initialize(&sect_vps);
- vp2 = yasm_vp_create_string(NULL, yasm__xstrdup(".comment"));
- yasm_vps_append(&sect_vps, vp2);
- comment = elf_objfmt_section_switch(object, &sect_vps, NULL, line);
- yasm_vps_delete(&sect_vps);
-
- /* To match GAS output, if the comment section is empty, put an
- * initial 0 byte in the section.
- */
- if (yasm_section_bcs_first(comment) == yasm_section_bcs_last(comment)) {
- yasm_dvs_initialize(&dvs);
- yasm_dvs_append(&dvs, yasm_dv_create_expr(
- yasm_expr_create_ident(
- yasm_expr_int(yasm_intnum_create_uint(0)), line)));
- yasm_section_bcs_append(comment,
- yasm_bc_create_data(&dvs, 1, 0, object->arch, line));
- }
-
- yasm_dvs_initialize(&dvs);
- do {
- const char *s = yasm_vp_string(vp);
- if (!s) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_(".comment requires string parameters"));
- yasm_dvs_delete(&dvs);
- return;
- }
- yasm_dvs_append(&dvs,
- yasm_dv_create_string(yasm__xstrdup(s), strlen(s)));
- } while ((vp = yasm_vps_next(vp)));
-
- yasm_section_bcs_append(comment,
- yasm_bc_create_data(&dvs, 1, 1, object->arch, line));
-}
-
-/* Define valid debug formats to use with this object format */
-static const char *elf_objfmt_dbgfmt_keywords[] = {
- "null",
- "stabs",
- "dwarf2",
- NULL
-};
-
-static const yasm_directive elf_objfmt_directives[] = {
- { ".type", "gas", dir_type, YASM_DIR_ID_REQUIRED },
- { ".size", "gas", dir_size, YASM_DIR_ID_REQUIRED },
- { ".weak", "gas", dir_weak, YASM_DIR_ID_REQUIRED },
- { ".ident", "gas", dir_ident, YASM_DIR_ANY },
- { "type", "nasm", dir_type, YASM_DIR_ID_REQUIRED },
- { "size", "nasm", dir_size, YASM_DIR_ID_REQUIRED },
- { "weak", "nasm", dir_weak, YASM_DIR_ID_REQUIRED },
- { "ident", "nasm", dir_ident, YASM_DIR_ANY },
- { NULL, NULL, NULL, 0 }
-};
-
-static const char *elf_nasm_stdmac[] = {
- "%imacro type 1+.nolist",
- "[type %1]",
- "%endmacro",
- "%imacro size 1+.nolist",
- "[size %1]",
- "%endmacro",
- "%imacro weak 1+.nolist",
- "[weak %1]",
- "%endmacro",
- NULL
-};
-
-static const yasm_stdmac elf_objfmt_stdmacs[] = {
- { "nasm", "nasm", elf_nasm_stdmac },
- { NULL, NULL, NULL }
-};
-
-/* Define objfmt structure -- see objfmt.h for details */
-yasm_objfmt_module yasm_elf_LTX_objfmt = {
- "ELF",
- "elf",
- "o",
- 32,
- 0,
- elf_objfmt_dbgfmt_keywords,
- "null",
- elf_objfmt_directives,
- elf_objfmt_stdmacs,
- elf_objfmt_create,
- elf_objfmt_output,
- elf_objfmt_destroy,
- elf_objfmt_add_default_section,
- elf_objfmt_init_new_section,
- elf_objfmt_section_switch,
- elf_objfmt_get_special_sym
-};
-
-yasm_objfmt_module yasm_elf32_LTX_objfmt = {
- "ELF (32-bit)",
- "elf32",
- "o",
- 32,
- 0,
- elf_objfmt_dbgfmt_keywords,
- "null",
- elf_objfmt_directives,
- elf_objfmt_stdmacs,
- elf32_objfmt_create,
- elf_objfmt_output,
- elf_objfmt_destroy,
- elf_objfmt_add_default_section,
- elf_objfmt_init_new_section,
- elf_objfmt_section_switch,
- elf_objfmt_get_special_sym
-};
-
-yasm_objfmt_module yasm_elf64_LTX_objfmt = {
- "ELF (64-bit)",
- "elf64",
- "o",
- 64,
- 0,
- elf_objfmt_dbgfmt_keywords,
- "null",
- elf_objfmt_directives,
- elf_objfmt_stdmacs,
- elf64_objfmt_create,
- elf_objfmt_output,
- elf_objfmt_destroy,
- elf_objfmt_add_default_section,
- elf_objfmt_init_new_section,
- elf_objfmt_section_switch,
- elf_objfmt_get_special_sym
-};
-
-yasm_objfmt_module yasm_elfx32_LTX_objfmt = {
- "ELF (x32)",
- "elfx32",
- "o",
- 64,
- 0,
- elf_objfmt_dbgfmt_keywords,
- "null",
- elf_objfmt_directives,
- elf_objfmt_stdmacs,
- elfx32_objfmt_create,
- elf_objfmt_output,
- elf_objfmt_destroy,
- elf_objfmt_add_default_section,
- elf_objfmt_init_new_section,
- elf_objfmt_section_switch,
- elf_objfmt_get_special_sym
-};
+
+ /* Allocate space for Ehdr by seeking forward */
+ if (fseek(f, (long)(elf_proghead_get_size()), SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO, N_("could not seek on output file"));
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+
+ /* add all (local) syms to symtab because relocation needs a symtab index
+ * if all_syms, register them by name. if not, use strtab entry 0 */
+ buildsym_info.object = object;
+ buildsym_info.objfmt_elf = objfmt_elf;
+ buildsym_info.errwarns = errwarns;
+ buildsym_info.local_names = all_syms;
+ yasm_symtab_traverse(object->symtab, &buildsym_info,
+ elf_objfmt_build_symtab);
+ elf_symtab_nlocal = elf_symtab_assign_indices(objfmt_elf->elf_symtab);
+
+ /* output known sections - includes reloc sections which aren't in yasm's
+ * list. Assign indices as we go. */
+ info.sindex = 3;
+ if (yasm_object_sections_traverse(object, &info,
+ elf_objfmt_output_section))
+ return;
+
+ /* add final sections to the shstrtab */
+ elf_strtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".strtab");
+ elf_symtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".symtab");
+ elf_shstrtab_name = elf_strtab_append_str(objfmt_elf->shstrtab,
+ ".shstrtab");
+
+ /* output .shstrtab */
+ if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+ elf_shstrtab_offset = (unsigned long) pos;
+ elf_shstrtab_size = elf_strtab_output_to_file(f, objfmt_elf->shstrtab);
+
+ /* output .strtab */
+ if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+ elf_strtab_offset = (unsigned long) pos;
+ elf_strtab_size = elf_strtab_output_to_file(f, objfmt_elf->strtab);
+
+ /* output .symtab - last section so all others have indexes */
+ if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+ elf_symtab_offset = (unsigned long) pos;
+ elf_symtab_size = elf_symtab_write_to_file(f, objfmt_elf->elf_symtab,
+ errwarns);
+
+ /* output section header table */
+ if ((pos = elf_objfmt_output_align(f, 16)) == -1) {
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+ elf_shead_addr = (unsigned long) pos;
+
+ /* stabs debugging support */
+ if (strcmp(yasm_dbgfmt_keyword(object->dbgfmt), "stabs")==0) {
+ yasm_section *stabsect = yasm_object_find_general(object, ".stab");
+ yasm_section *stabstrsect =
+ yasm_object_find_general(object, ".stabstr");
+ if (stabsect && stabstrsect) {
+ elf_secthead *stab =
+ yasm_section_get_data(stabsect, &elf_section_data);
+ elf_secthead *stabstr =
+ yasm_section_get_data(stabstrsect, &elf_section_data);
+ if (stab && stabstr) {
+ elf_secthead_set_link(stab, elf_secthead_get_index(stabstr));
+ }
+ else
+ yasm_internal_error(N_("missing .stab or .stabstr section/data"));
+ }
+ }
+
+ /* output dummy section header - 0 */
+ info.sindex = 0;
+
+ esdn = elf_secthead_create(NULL, SHT_NULL, 0, 0, 0);
+ elf_secthead_set_index(esdn, 0);
+ elf_secthead_write_to_file(f, esdn, 0);
+ elf_secthead_destroy(esdn);
+
+ esdn = elf_secthead_create(elf_shstrtab_name, SHT_STRTAB, 0,
+ elf_shstrtab_offset, elf_shstrtab_size);
+ elf_secthead_set_index(esdn, 1);
+ elf_secthead_write_to_file(f, esdn, 1);
+ elf_secthead_destroy(esdn);
+
+ esdn = elf_secthead_create(elf_strtab_name, SHT_STRTAB, 0,
+ elf_strtab_offset, elf_strtab_size);
+ elf_secthead_set_index(esdn, 2);
+ elf_secthead_write_to_file(f, esdn, 2);
+ elf_secthead_destroy(esdn);
+
+ esdn = elf_secthead_create(elf_symtab_name, SHT_SYMTAB, 0,
+ elf_symtab_offset, elf_symtab_size);
+ elf_secthead_set_index(esdn, 3);
+ elf_secthead_set_info(esdn, elf_symtab_nlocal);
+ elf_secthead_set_link(esdn, 2); /* for .strtab, which is index 2 */
+ elf_secthead_write_to_file(f, esdn, 3);
+ elf_secthead_destroy(esdn);
+
+ info.sindex = 3;
+ /* output remaining section headers */
+ yasm_object_sections_traverse(object, &info, elf_objfmt_output_secthead);
+
+ /* output Ehdr */
+ if (fseek(f, 0, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO, N_("could not seek on output file"));
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+
+ elf_proghead_write_to_file(f, elf_shead_addr, info.sindex+1, 1);
+}
+
+static void
+elf_objfmt_destroy(yasm_objfmt *objfmt)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt;
+ elf_symtab_destroy(objfmt_elf->elf_symtab);
+ elf_strtab_destroy(objfmt_elf->shstrtab);
+ elf_strtab_destroy(objfmt_elf->strtab);
+ yasm_xfree(objfmt);
+}
+
+static void
+elf_objfmt_init_new_section(yasm_section *sect, unsigned long line)
+{
+ yasm_object *object = yasm_section_get_object(sect);
+ const char *sectname = yasm_section_get_name(sect);
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ elf_secthead *esd;
+ yasm_symrec *sym;
+ elf_strtab_entry *name = elf_strtab_append_str(objfmt_elf->shstrtab,
+ sectname);
+
+ elf_section_type type=SHT_PROGBITS;
+ elf_size entsize=0;
+
+ if (yasm__strcasecmp(sectname, ".stab")==0) {
+ entsize = 12;
+ } else if (yasm__strcasecmp(sectname, ".stabstr")==0) {
+ type = SHT_STRTAB;
+ }
+
+ esd = elf_secthead_create(name, type, 0, 0, 0);
+ elf_secthead_set_entsize(esd, entsize);
+ yasm_section_add_data(sect, &elf_section_data, esd);
+ sym = yasm_symtab_define_label(object->symtab, sectname,
+ yasm_section_bcs_first(sect), 1, line);
+
+ elf_secthead_set_sym(esd, sym);
+}
+
+static yasm_section *
+elf_objfmt_add_default_section(yasm_object *object)
+{
+ yasm_section *retval;
+ int isnew;
+
+ retval = yasm_object_get_general(object, ".text", 16, 1, 0, &isnew, 0);
+ if (isnew)
+ {
+ elf_secthead *esd = yasm_section_get_data(retval, &elf_section_data);
+ elf_secthead_set_typeflags(esd, SHT_PROGBITS,
+ SHF_ALLOC + SHF_EXECINSTR);
+ yasm_section_set_default(retval, 1);
+ }
+ return retval;
+}
+
+struct elf_section_switch_data {
+ /*@only@*/ /*@null@*/ yasm_intnum *align_intn;
+ unsigned long flags;
+ unsigned long type;
+ int gasflags;
+ int stdsect;
+};
+
+/* GAS-style flags */
+static int
+elf_helper_gasflags(void *obj, yasm_valparam *vp, unsigned long line, void *d,
+ /*@unused@*/ uintptr_t arg)
+{
+ struct elf_section_switch_data *data = (struct elf_section_switch_data *)d;
+ const char *s = yasm_vp_string(vp);
+ size_t i;
+
+ if (!s) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("non-string section attribute"));
+ return -1;
+ }
+
+ if (data->stdsect && strlen(s) == 0) {
+ data->gasflags = 1;
+ return 0;
+ }
+
+ data->flags = 0;
+ for (i=0; i<strlen(s); i++) {
+ switch (s[i]) {
+ case 'a':
+ data->flags |= SHF_ALLOC;
+ break;
+ case 'w':
+ data->flags |= SHF_WRITE;
+ break;
+ case 'x':
+ data->flags |= SHF_EXECINSTR;
+ break;
+ case 'M':
+ data->flags |= SHF_MERGE;
+ break;
+ case 'S':
+ data->flags |= SHF_STRINGS;
+ break;
+ case 'G':
+ data->flags |= SHF_GROUP;
+ break;
+ case 'T':
+ data->flags |= SHF_TLS;
+ break;
+ default:
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized section attribute: `%c'"),
+ s[i]);
+ }
+ }
+
+ data->gasflags = 1;
+ return 0;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_section *
+elf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ yasm_valparam *vp;
+ yasm_section *retval;
+ int isnew;
+ unsigned long align = 4;
+ int flags_override = 0;
+ const char *sectname;
+ int resonly = 0;
+
+ struct elf_section_switch_data data;
+
+ static const yasm_dir_help help[] = {
+ { "alloc", 0, yasm_dir_helper_flag_or,
+ offsetof(struct elf_section_switch_data, flags), SHF_ALLOC },
+ { "exec", 0, yasm_dir_helper_flag_or,
+ offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR },
+ { "write", 0, yasm_dir_helper_flag_or,
+ offsetof(struct elf_section_switch_data, flags), SHF_WRITE },
+ { "tls", 0, yasm_dir_helper_flag_or,
+ offsetof(struct elf_section_switch_data, flags), SHF_TLS },
+ { "progbits", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_section_switch_data, type), SHT_PROGBITS },
+ { "noalloc", 0, yasm_dir_helper_flag_and,
+ offsetof(struct elf_section_switch_data, flags), SHF_ALLOC },
+ { "noexec", 0, yasm_dir_helper_flag_and,
+ offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR },
+ { "nowrite", 0, yasm_dir_helper_flag_and,
+ offsetof(struct elf_section_switch_data, flags), SHF_WRITE },
+ { "notls", 0, yasm_dir_helper_flag_and,
+ offsetof(struct elf_section_switch_data, flags), SHF_TLS },
+ { "noprogbits", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_section_switch_data, type), SHT_NOBITS },
+ { "nobits", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_section_switch_data, type), SHT_NOBITS },
+ { "gasflags", 1, elf_helper_gasflags, 0, 0 },
+ { "align", 1, yasm_dir_helper_intn,
+ offsetof(struct elf_section_switch_data, align_intn), 0 }
+ };
+ /*@only@*/ /*@null@*/ yasm_expr *merge_expr = NULL;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *merge_intn = NULL;
+ elf_secthead *esd;
+
+ data.align_intn = NULL;
+ data.flags = SHF_ALLOC;
+ data.type = SHT_PROGBITS;
+ data.gasflags = 0;
+ data.stdsect = 1;
+
+ vp = yasm_vps_first(valparams);
+ sectname = yasm_vp_string(vp);
+ if (!sectname)
+ return NULL;
+ vp = yasm_vps_next(vp);
+
+ if (strcmp(sectname, ".bss") == 0) {
+ data.type = SHT_NOBITS;
+ data.flags = SHF_ALLOC + SHF_WRITE;
+ resonly = 1;
+ } else if (strcmp(sectname, ".data") == 0) {
+ data.type = SHT_PROGBITS;
+ data.flags = SHF_ALLOC + SHF_WRITE;
+ } else if (strcmp(sectname, ".tdata") == 0) {
+ data.type = SHT_PROGBITS;
+ data.flags = SHF_ALLOC + SHF_WRITE + SHF_TLS;
+ } else if (strcmp(sectname, ".rodata") == 0) {
+ data.type = SHT_PROGBITS;
+ data.flags = SHF_ALLOC;
+ } else if (strcmp(sectname, ".text") == 0) {
+ align = 16;
+ data.type = SHT_PROGBITS;
+ data.flags = SHF_ALLOC + SHF_EXECINSTR;
+ } else if (strcmp(sectname, ".comment") == 0) {
+ align = 0;
+ data.type = SHT_PROGBITS;
+ data.flags = 0;
+ } else {
+ /* Default to code */
+ align = 1;
+ data.stdsect = 0;
+ }
+
+ flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
+ &data, yasm_dir_helper_valparam_warn);
+ if (flags_override < 0)
+ return NULL; /* error occurred */
+
+ if (data.align_intn) {
+ align = yasm_intnum_get_uint(data.align_intn);
+ yasm_intnum_destroy(data.align_intn);
+
+ /* Alignments must be a power of two. */
+ if (!is_exp2(align)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("argument to `%s' is not a power of two"),
+ "align");
+ return NULL;
+ }
+ }
+
+ /* Handle merge entity size */
+ if (data.flags & SHF_MERGE) {
+ if (objext_valparams && (vp = yasm_vps_first(objext_valparams))
+ && !vp->val) {
+ if (!(merge_expr = yasm_vp_expr(vp, object->symtab, line)) ||
+ !(merge_intn = yasm_expr_get_intnum(&merge_expr, 0)))
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("invalid merge entity size"));
+ } else {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("entity size for SHF_MERGE not specified"));
+ data.flags &= ~SHF_MERGE;
+ }
+ }
+
+ retval = yasm_object_get_general(object, sectname, align,
+ (data.flags & SHF_EXECINSTR) != 0,
+ resonly, &isnew, line);
+
+ esd = yasm_section_get_data(retval, &elf_section_data);
+
+ if (isnew || yasm_section_is_default(retval)) {
+ yasm_section_set_default(retval, 0);
+ elf_secthead_set_typeflags(esd, data.type, data.flags);
+ if (merge_intn)
+ elf_secthead_set_entsize(esd, yasm_intnum_get_uint(merge_intn));
+ yasm_section_set_align(retval, align, line);
+ } else if (flags_override && !data.gasflags)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("section flags ignored on section redeclaration"));
+ if (merge_expr)
+ yasm_expr_destroy(merge_expr);
+ return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+elf_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ if (yasm__strcasecmp(name, "sym") == 0) {
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ return objfmt_elf->dotdotsym;
+ }
+ return elf_get_special_sym(name, parser);
+}
+
+static void
+dir_type(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ const char *symname = yasm_vp_id(vp);
+ /* Get symbol elf data */
+ yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line);
+ elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+ /*@null@*/ const char *type;
+
+ /* Create entry if necessary */
+ if (!entry) {
+ entry = elf_symtab_entry_create(
+ elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
+ yasm_symrec_add_data(sym, &elf_symrec_data, entry);
+ }
+
+ /* Pull new type from param */
+ vp = yasm_vps_next(vp);
+ if (vp && !vp->val && (type = yasm_vp_id(vp))) {
+ if (yasm__strcasecmp(type, "function") == 0)
+ elf_sym_set_type(entry, STT_FUNC);
+ else if (yasm__strcasecmp(type, "object") == 0)
+ elf_sym_set_type(entry, STT_OBJECT);
+ else if (yasm__strcasecmp(type, "tls_object") == 0)
+ elf_sym_set_type(entry, STT_TLS);
+ else if (yasm__strcasecmp(type, "notype") == 0)
+ elf_sym_set_type(entry, STT_NOTYPE);
+ else
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized symbol type `%s'"), type);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("no type specified"));
+}
+
+static void
+dir_size(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ const char *symname = yasm_vp_id(vp);
+ /* Get symbol elf data */
+ yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line);
+ elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+ /*@only@*/ /*@null@*/ yasm_expr *size;
+
+ /* Create entry if necessary */
+ if (!entry) {
+ entry = elf_symtab_entry_create(
+ elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
+ yasm_symrec_add_data(sym, &elf_symrec_data, entry);
+ }
+
+ /* Pull new size from param */
+ vp = yasm_vps_next(vp);
+ if (vp && !vp->val && (size = yasm_vp_expr(vp, object->symtab, line)))
+ elf_sym_set_size(entry, size);
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("no size specified"));
+}
+
+static void
+dir_weak(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ const char *symname = yasm_vp_id(vp);
+ yasm_symrec *sym = yasm_symtab_declare(object->symtab, symname,
+ YASM_SYM_GLOBAL, line);
+ elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK, 0,
+ STV_DEFAULT, NULL, NULL, object);
+}
+
+static void
+dir_ident(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparamhead sect_vps;
+ yasm_datavalhead dvs;
+ yasm_section *comment;
+ yasm_valparam *vp;
+ yasm_valparam *vp2;
+
+ /* Accept, but do nothing with empty ident */
+ if (!valparams)
+ return;
+ vp = yasm_vps_first(valparams);
+ if (!vp)
+ return;
+
+ /* Put ident data into .comment section */
+ yasm_vps_initialize(&sect_vps);
+ vp2 = yasm_vp_create_string(NULL, yasm__xstrdup(".comment"));
+ yasm_vps_append(&sect_vps, vp2);
+ comment = elf_objfmt_section_switch(object, &sect_vps, NULL, line);
+ yasm_vps_delete(&sect_vps);
+
+ /* To match GAS output, if the comment section is empty, put an
+ * initial 0 byte in the section.
+ */
+ if (yasm_section_bcs_first(comment) == yasm_section_bcs_last(comment)) {
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ yasm_expr_create_ident(
+ yasm_expr_int(yasm_intnum_create_uint(0)), line)));
+ yasm_section_bcs_append(comment,
+ yasm_bc_create_data(&dvs, 1, 0, object->arch, line));
+ }
+
+ yasm_dvs_initialize(&dvs);
+ do {
+ const char *s = yasm_vp_string(vp);
+ if (!s) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_(".comment requires string parameters"));
+ yasm_dvs_delete(&dvs);
+ return;
+ }
+ yasm_dvs_append(&dvs,
+ yasm_dv_create_string(yasm__xstrdup(s), strlen(s)));
+ } while ((vp = yasm_vps_next(vp)));
+
+ yasm_section_bcs_append(comment,
+ yasm_bc_create_data(&dvs, 1, 1, object->arch, line));
+}
+
+/* Define valid debug formats to use with this object format */
+static const char *elf_objfmt_dbgfmt_keywords[] = {
+ "null",
+ "stabs",
+ "dwarf2",
+ NULL
+};
+
+static const yasm_directive elf_objfmt_directives[] = {
+ { ".type", "gas", dir_type, YASM_DIR_ID_REQUIRED },
+ { ".size", "gas", dir_size, YASM_DIR_ID_REQUIRED },
+ { ".weak", "gas", dir_weak, YASM_DIR_ID_REQUIRED },
+ { ".ident", "gas", dir_ident, YASM_DIR_ANY },
+ { "type", "nasm", dir_type, YASM_DIR_ID_REQUIRED },
+ { "size", "nasm", dir_size, YASM_DIR_ID_REQUIRED },
+ { "weak", "nasm", dir_weak, YASM_DIR_ID_REQUIRED },
+ { "ident", "nasm", dir_ident, YASM_DIR_ANY },
+ { NULL, NULL, NULL, 0 }
+};
+
+static const char *elf_nasm_stdmac[] = {
+ "%imacro type 1+.nolist",
+ "[type %1]",
+ "%endmacro",
+ "%imacro size 1+.nolist",
+ "[size %1]",
+ "%endmacro",
+ "%imacro weak 1+.nolist",
+ "[weak %1]",
+ "%endmacro",
+ NULL
+};
+
+static const yasm_stdmac elf_objfmt_stdmacs[] = {
+ { "nasm", "nasm", elf_nasm_stdmac },
+ { NULL, NULL, NULL }
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_elf_LTX_objfmt = {
+ "ELF",
+ "elf",
+ "o",
+ 32,
+ 0,
+ elf_objfmt_dbgfmt_keywords,
+ "null",
+ elf_objfmt_directives,
+ elf_objfmt_stdmacs,
+ elf_objfmt_create,
+ elf_objfmt_output,
+ elf_objfmt_destroy,
+ elf_objfmt_add_default_section,
+ elf_objfmt_init_new_section,
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
+};
+
+yasm_objfmt_module yasm_elf32_LTX_objfmt = {
+ "ELF (32-bit)",
+ "elf32",
+ "o",
+ 32,
+ 0,
+ elf_objfmt_dbgfmt_keywords,
+ "null",
+ elf_objfmt_directives,
+ elf_objfmt_stdmacs,
+ elf32_objfmt_create,
+ elf_objfmt_output,
+ elf_objfmt_destroy,
+ elf_objfmt_add_default_section,
+ elf_objfmt_init_new_section,
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
+};
+
+yasm_objfmt_module yasm_elf64_LTX_objfmt = {
+ "ELF (64-bit)",
+ "elf64",
+ "o",
+ 64,
+ 0,
+ elf_objfmt_dbgfmt_keywords,
+ "null",
+ elf_objfmt_directives,
+ elf_objfmt_stdmacs,
+ elf64_objfmt_create,
+ elf_objfmt_output,
+ elf_objfmt_destroy,
+ elf_objfmt_add_default_section,
+ elf_objfmt_init_new_section,
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
+};
+
+yasm_objfmt_module yasm_elfx32_LTX_objfmt = {
+ "ELF (x32)",
+ "elfx32",
+ "o",
+ 64,
+ 0,
+ elf_objfmt_dbgfmt_keywords,
+ "null",
+ elf_objfmt_directives,
+ elf_objfmt_stdmacs,
+ elfx32_objfmt_create,
+ elf_objfmt_output,
+ elf_objfmt_destroy,
+ elf_objfmt_add_default_section,
+ elf_objfmt_init_new_section,
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
+};
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf-x86-amd64.c b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-amd64.c
index 3ba376af03..5384b768ed 100644
--- a/contrib/tools/yasm/modules/objfmts/elf/elf-x86-amd64.c
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-amd64.c
@@ -1,256 +1,256 @@
-/*
- * ELF object format helpers - x86:amd64
- *
- * Copyright (C) 2004-2007 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>
-
-#include <libyasm.h>
-#define YASM_OBJFMT_ELF_INTERNAL
-#include "elf.h"
-#include "elf-machine.h"
-
-static elf_machine_ssym elf_x86_amd64_ssyms[] = {
- {"pltoff", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLTOFF64, 64},
- {"plt", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLT32, 32},
- {"gotplt", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPLT64, 64},
- {"gotoff", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTOFF64, 64},
- {"gotpcrel", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPCREL, 32},
- {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_TLSGD, 32},
- {"tlsld", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_TLSLD, 32},
- {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_GOTTPOFF, 32},
- {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_TPOFF32, 32},
- {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_DTPOFF32, 32},
- {"got", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOT32, 32},
- {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_GOTPC32_TLSDESC, 32},
- {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_TLSDESC_CALL, 32}
-};
-
-static int
-elf_x86_amd64_accepts_reloc(size_t val, yasm_symrec *wrt)
-{
- if (wrt) {
- const elf_machine_ssym *ssym = (elf_machine_ssym *)
- yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
- if (!ssym || val != ssym->size)
- return 0;
- return 1;
- }
- 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, ELF64_ST_OTHER(entry->vis));
- if (entry->sect) {
- 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);
-
- YASM_WRITE_64Z_L(bufp, shead->align);
- 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_RELA);
- 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(RELOC64A_SIZE);
- yasm_intnum_calc(relocsize, YASM_EXPR_MUL, nreloc);
- 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, RELOC64A_SIZE); /* entity size */
-}
-
-static void
-elf_x86_amd64_handle_reloc_addend(yasm_intnum *intn,
- elf_reloc_entry *reloc,
- unsigned long offset)
-{
- /* .rela: copy value out as addend, replace original with 0 */
- reloc->addend = yasm_intnum_copy(intn);
- yasm_intnum_zero(intn);
-}
-
-static unsigned int
-elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc)
-{
- if (reloc->wrt) {
- const elf_machine_ssym *ssym = (elf_machine_ssym *)
- yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
- if (!ssym || reloc->valsize != ssym->size)
- yasm_internal_error(N_("Unsupported WRT"));
-
- /* Force TLS type; this is required by the linker. */
- if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
- elf_symtab_entry *esym;
-
- esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
- if (esym)
- esym->type = STT_TLS;
- }
- /* Map PC-relative GOT to appropriate relocation */
- if (reloc->rtype_rel && ssym->reloc == R_X86_64_GOT32)
- return (unsigned char) R_X86_64_GOTPCREL;
- return (unsigned char) ssym->reloc;
- } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
- return (unsigned char) R_X86_64_GOTPC32;
- } else if (reloc->is_GOT_sym && reloc->valsize == 64) {
- return (unsigned char) R_X86_64_GOTPC64;
- } else 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;
- case 64: return (unsigned char) R_X86_64_PC64;
- 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);
- if (reloc->addend)
- YASM_WRITE_64I_L(bufp, reloc->addend);
- else {
- YASM_WRITE_32_L(bufp, 0);
- YASM_WRITE_32_L(bufp, 0);
- }
-}
-
-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", ".rela",
- SYMTAB64_SIZE, SYMTAB64_ALIGN, RELOC64A_SIZE, SHDR64_SIZE, EHDR64_SIZE,
- elf_x86_amd64_accepts_reloc,
- elf_x86_amd64_write_symtab_entry,
- elf_x86_amd64_write_secthead,
- elf_x86_amd64_write_secthead_rel,
- elf_x86_amd64_handle_reloc_addend,
- elf_x86_amd64_map_reloc_info_to_type,
- elf_x86_amd64_write_reloc,
- elf_x86_amd64_write_proghead,
- elf_x86_amd64_ssyms,
- sizeof(elf_x86_amd64_ssyms)/sizeof(elf_x86_amd64_ssyms[0]),
- 64
-};
+/*
+ * ELF object format helpers - x86:amd64
+ *
+ * Copyright (C) 2004-2007 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>
+
+#include <libyasm.h>
+#define YASM_OBJFMT_ELF_INTERNAL
+#include "elf.h"
+#include "elf-machine.h"
+
+static elf_machine_ssym elf_x86_amd64_ssyms[] = {
+ {"pltoff", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLTOFF64, 64},
+ {"plt", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLT32, 32},
+ {"gotplt", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPLT64, 64},
+ {"gotoff", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTOFF64, 64},
+ {"gotpcrel", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPCREL, 32},
+ {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSGD, 32},
+ {"tlsld", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSLD, 32},
+ {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_GOTTPOFF, 32},
+ {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TPOFF32, 32},
+ {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_DTPOFF32, 32},
+ {"got", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOT32, 32},
+ {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_GOTPC32_TLSDESC, 32},
+ {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSDESC_CALL, 32}
+};
+
+static int
+elf_x86_amd64_accepts_reloc(size_t val, yasm_symrec *wrt)
+{
+ if (wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
+ if (!ssym || val != ssym->size)
+ return 0;
+ return 1;
+ }
+ 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, ELF64_ST_OTHER(entry->vis));
+ if (entry->sect) {
+ 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);
+
+ YASM_WRITE_64Z_L(bufp, shead->align);
+ 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_RELA);
+ 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(RELOC64A_SIZE);
+ yasm_intnum_calc(relocsize, YASM_EXPR_MUL, nreloc);
+ 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, RELOC64A_SIZE); /* entity size */
+}
+
+static void
+elf_x86_amd64_handle_reloc_addend(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset)
+{
+ /* .rela: copy value out as addend, replace original with 0 */
+ reloc->addend = yasm_intnum_copy(intn);
+ yasm_intnum_zero(intn);
+}
+
+static unsigned int
+elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc)
+{
+ if (reloc->wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
+ if (!ssym || reloc->valsize != ssym->size)
+ yasm_internal_error(N_("Unsupported WRT"));
+
+ /* Force TLS type; this is required by the linker. */
+ if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
+ elf_symtab_entry *esym;
+
+ esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
+ if (esym)
+ esym->type = STT_TLS;
+ }
+ /* Map PC-relative GOT to appropriate relocation */
+ if (reloc->rtype_rel && ssym->reloc == R_X86_64_GOT32)
+ return (unsigned char) R_X86_64_GOTPCREL;
+ return (unsigned char) ssym->reloc;
+ } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
+ return (unsigned char) R_X86_64_GOTPC32;
+ } else if (reloc->is_GOT_sym && reloc->valsize == 64) {
+ return (unsigned char) R_X86_64_GOTPC64;
+ } else 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;
+ case 64: return (unsigned char) R_X86_64_PC64;
+ 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);
+ if (reloc->addend)
+ YASM_WRITE_64I_L(bufp, reloc->addend);
+ else {
+ YASM_WRITE_32_L(bufp, 0);
+ YASM_WRITE_32_L(bufp, 0);
+ }
+}
+
+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", ".rela",
+ SYMTAB64_SIZE, SYMTAB64_ALIGN, RELOC64A_SIZE, SHDR64_SIZE, EHDR64_SIZE,
+ elf_x86_amd64_accepts_reloc,
+ elf_x86_amd64_write_symtab_entry,
+ elf_x86_amd64_write_secthead,
+ elf_x86_amd64_write_secthead_rel,
+ elf_x86_amd64_handle_reloc_addend,
+ elf_x86_amd64_map_reloc_info_to_type,
+ elf_x86_amd64_write_reloc,
+ elf_x86_amd64_write_proghead,
+ elf_x86_amd64_ssyms,
+ sizeof(elf_x86_amd64_ssyms)/sizeof(elf_x86_amd64_ssyms[0]),
+ 64
+};
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x32.c b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x32.c
index 40a25a12a7..aad2d10dac 100644
--- a/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x32.c
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x32.c
@@ -1,251 +1,251 @@
-/*
- * ELF object format helpers - x86:x32
- *
- * Copyright (C) 2012 Michael Urman and H.J. Lu
- *
- * 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>
-
-#include <libyasm.h>
-#define YASM_OBJFMT_ELF_INTERNAL
-#include "elf.h"
-#include "elf-machine.h"
-
-static elf_machine_ssym elf_x86_x32_ssyms[] = {
- {"plt", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLT32, 32},
- {"gotpcrel", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPCREL, 32},
- {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_TLSGD, 32},
- {"tlsld", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_TLSLD, 32},
- {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_GOTTPOFF, 32},
- {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_TPOFF32, 32},
- {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_DTPOFF32, 32},
- {"got", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOT32, 32},
- {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_GOTPC32_TLSDESC, 32},
- {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_X86_64_TLSDESC_CALL, 32}
-};
-
-static int
-elf_x86_x32_accepts_reloc(size_t val, yasm_symrec *wrt)
-{
- if (wrt) {
- const elf_machine_ssym *ssym = (elf_machine_ssym *)
- yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
- if (!ssym || val != ssym->size)
- return 0;
- return 1;
- }
- return (val&(val-1)) ? 0 : ((val & (8|16|32)) != 0);
-}
-
-static void
-elf_x86_x32_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, ELF32_ST_OTHER(entry->vis));
- if (entry->sect) {
- 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_x32_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);
-
- YASM_WRITE_32_L(bufp, shead->align);
- YASM_WRITE_32_L(bufp, shead->entsize);
-}
-
-static void
-elf_x86_x32_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_RELA);
- YASM_WRITE_32_L(bufp, 0);
- YASM_WRITE_32_L(bufp, 0);
- YASM_WRITE_32_L(bufp, shead->rel_offset);
-
- nreloc = yasm_intnum_create_uint(shead->nreloc);
- relocsize = yasm_intnum_create_uint(RELOC32A_SIZE);
- yasm_intnum_calc(relocsize, YASM_EXPR_MUL, nreloc);
- YASM_WRITE_32I_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_32_L(bufp, RELOC32_ALIGN); /* align */
- YASM_WRITE_32_L(bufp, RELOC32A_SIZE); /* entity size */
-}
-
-static void
-elf_x86_x32_handle_reloc_addend(yasm_intnum *intn,
- elf_reloc_entry *reloc,
- unsigned long offset)
-{
- /* .rela: copy value out as addend, replace original with 0 */
- reloc->addend = yasm_intnum_copy(intn);
- yasm_intnum_zero(intn);
-}
-
-static unsigned int
-elf_x86_x32_map_reloc_info_to_type(elf_reloc_entry *reloc)
-{
- if (reloc->wrt) {
- const elf_machine_ssym *ssym = (elf_machine_ssym *)
- yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
- if (!ssym || reloc->valsize != ssym->size)
- yasm_internal_error(N_("Unsupported WRT"));
-
- /* Force TLS type; this is required by the linker. */
- if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
- elf_symtab_entry *esym;
-
- esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
- if (esym)
- esym->type = STT_TLS;
- }
- /* Map PC-relative GOT to appropriate relocation */
- if (reloc->rtype_rel && ssym->reloc == R_X86_64_GOT32)
- return (unsigned char) R_X86_64_GOTPCREL;
- return (unsigned char) ssym->reloc;
- } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
- return (unsigned char) R_X86_64_GOTPC32;
- } else if (reloc->is_GOT_sym && reloc->valsize == 64) {
- yasm_internal_error(N_("Unsupported relocation size"));
- } else 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_x32_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 long)r_sym, (unsigned char)r_type));
- if (reloc->addend)
- YASM_WRITE_32I_L(bufp, reloc->addend);
- else {
- YASM_WRITE_32_L(bufp, 0);
- }
-}
-
-static void
-elf_x86_x32_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 */
- 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_32_L(bufp, 0); /* e_entry */
- YASM_WRITE_32_L(bufp, 0); /* e_phoff */
- YASM_WRITE_32_L(bufp, secthead_addr); /* e_shoff secthead off */
-
- YASM_WRITE_32_L(bufp, 0); /* e_flags */
- 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_x32 = {
- "x86", "x32", ".rela",
- SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32A_SIZE, SHDR32_SIZE, EHDR32_SIZE,
- elf_x86_x32_accepts_reloc,
- elf_x86_x32_write_symtab_entry,
- elf_x86_x32_write_secthead,
- elf_x86_x32_write_secthead_rel,
- elf_x86_x32_handle_reloc_addend,
- elf_x86_x32_map_reloc_info_to_type,
- elf_x86_x32_write_reloc,
- elf_x86_x32_write_proghead,
- elf_x86_x32_ssyms,
- sizeof(elf_x86_x32_ssyms)/sizeof(elf_x86_x32_ssyms[0]),
- 32
-};
+/*
+ * ELF object format helpers - x86:x32
+ *
+ * Copyright (C) 2012 Michael Urman and H.J. Lu
+ *
+ * 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>
+
+#include <libyasm.h>
+#define YASM_OBJFMT_ELF_INTERNAL
+#include "elf.h"
+#include "elf-machine.h"
+
+static elf_machine_ssym elf_x86_x32_ssyms[] = {
+ {"plt", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLT32, 32},
+ {"gotpcrel", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPCREL, 32},
+ {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSGD, 32},
+ {"tlsld", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSLD, 32},
+ {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_GOTTPOFF, 32},
+ {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TPOFF32, 32},
+ {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_DTPOFF32, 32},
+ {"got", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOT32, 32},
+ {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_GOTPC32_TLSDESC, 32},
+ {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSDESC_CALL, 32}
+};
+
+static int
+elf_x86_x32_accepts_reloc(size_t val, yasm_symrec *wrt)
+{
+ if (wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
+ if (!ssym || val != ssym->size)
+ return 0;
+ return 1;
+ }
+ return (val&(val-1)) ? 0 : ((val & (8|16|32)) != 0);
+}
+
+static void
+elf_x86_x32_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, ELF32_ST_OTHER(entry->vis));
+ if (entry->sect) {
+ 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_x32_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);
+
+ YASM_WRITE_32_L(bufp, shead->align);
+ YASM_WRITE_32_L(bufp, shead->entsize);
+}
+
+static void
+elf_x86_x32_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_RELA);
+ YASM_WRITE_32_L(bufp, 0);
+ YASM_WRITE_32_L(bufp, 0);
+ YASM_WRITE_32_L(bufp, shead->rel_offset);
+
+ nreloc = yasm_intnum_create_uint(shead->nreloc);
+ relocsize = yasm_intnum_create_uint(RELOC32A_SIZE);
+ yasm_intnum_calc(relocsize, YASM_EXPR_MUL, nreloc);
+ YASM_WRITE_32I_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_32_L(bufp, RELOC32_ALIGN); /* align */
+ YASM_WRITE_32_L(bufp, RELOC32A_SIZE); /* entity size */
+}
+
+static void
+elf_x86_x32_handle_reloc_addend(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset)
+{
+ /* .rela: copy value out as addend, replace original with 0 */
+ reloc->addend = yasm_intnum_copy(intn);
+ yasm_intnum_zero(intn);
+}
+
+static unsigned int
+elf_x86_x32_map_reloc_info_to_type(elf_reloc_entry *reloc)
+{
+ if (reloc->wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
+ if (!ssym || reloc->valsize != ssym->size)
+ yasm_internal_error(N_("Unsupported WRT"));
+
+ /* Force TLS type; this is required by the linker. */
+ if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
+ elf_symtab_entry *esym;
+
+ esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
+ if (esym)
+ esym->type = STT_TLS;
+ }
+ /* Map PC-relative GOT to appropriate relocation */
+ if (reloc->rtype_rel && ssym->reloc == R_X86_64_GOT32)
+ return (unsigned char) R_X86_64_GOTPCREL;
+ return (unsigned char) ssym->reloc;
+ } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
+ return (unsigned char) R_X86_64_GOTPC32;
+ } else if (reloc->is_GOT_sym && reloc->valsize == 64) {
+ yasm_internal_error(N_("Unsupported relocation size"));
+ } else 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_x32_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 long)r_sym, (unsigned char)r_type));
+ if (reloc->addend)
+ YASM_WRITE_32I_L(bufp, reloc->addend);
+ else {
+ YASM_WRITE_32_L(bufp, 0);
+ }
+}
+
+static void
+elf_x86_x32_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 */
+ 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_32_L(bufp, 0); /* e_entry */
+ YASM_WRITE_32_L(bufp, 0); /* e_phoff */
+ YASM_WRITE_32_L(bufp, secthead_addr); /* e_shoff secthead off */
+
+ YASM_WRITE_32_L(bufp, 0); /* e_flags */
+ 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_x32 = {
+ "x86", "x32", ".rela",
+ SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32A_SIZE, SHDR32_SIZE, EHDR32_SIZE,
+ elf_x86_x32_accepts_reloc,
+ elf_x86_x32_write_symtab_entry,
+ elf_x86_x32_write_secthead,
+ elf_x86_x32_write_secthead_rel,
+ elf_x86_x32_handle_reloc_addend,
+ elf_x86_x32_map_reloc_info_to_type,
+ elf_x86_x32_write_reloc,
+ elf_x86_x32_write_proghead,
+ elf_x86_x32_ssyms,
+ sizeof(elf_x86_x32_ssyms)/sizeof(elf_x86_x32_ssyms[0]),
+ 32
+};
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x86.c b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x86.c
index d79ec6eabd..8ebaa87381 100644
--- a/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x86.c
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x86.c
@@ -1,242 +1,242 @@
-/*
- * ELF object format helpers - x86:x86
- *
- * Copyright (C) 2004-2007 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>
-
-#include <libyasm.h>
-#define YASM_OBJFMT_ELF_INTERNAL
-#include "elf.h"
-#include "elf-machine.h"
-
-static elf_machine_ssym elf_x86_x86_ssyms[] = {
- {"plt", ELF_SSYM_SYM_RELATIVE, R_386_PLT32, 32},
- {"gotoff", 0, R_386_GOTOFF, 32},
- /* special one for NASM */
- {"gotpc", ELF_SSYM_CURPOS_ADJUST, R_386_GOTPC, 32},
- {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_386_TLS_GD, 32},
- {"tlsldm", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_386_TLS_LDM, 32},
- {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_386_TLS_IE_32, 32},
- {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_386_TLS_LE_32, 32},
- {"ntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_386_TLS_LE, 32},
- {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_386_TLS_LDO_32, 32},
- {"gotntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_386_TLS_GOTIE, 32},
- {"indntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_386_TLS_IE, 32},
- {"got", ELF_SSYM_SYM_RELATIVE, R_386_GOT32, 32},
- {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_386_TLS_GOTDESC, 32},
- {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
- R_386_TLS_DESC_CALL, 32}
-};
-
-static int
-elf_x86_x86_accepts_reloc(size_t val, yasm_symrec *wrt)
-{
- if (wrt) {
- const elf_machine_ssym *ssym = (elf_machine_ssym *)
- yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
- if (!ssym || val != ssym->size)
- return 0;
- return 1;
- }
- return (val&(val-1)) ? 0 : ((val & (8|16|32)) != 0);
-}
-
-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, ELF32_ST_OTHER(entry->vis));
- if (entry->sect) {
- 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);
-
- YASM_WRITE_32_L(bufp, shead->align);
- 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 void
-elf_x86_x86_handle_reloc_addend(yasm_intnum *intn,
- elf_reloc_entry *reloc,
- unsigned long offset)
-{
- if (!reloc->wrt && reloc->is_GOT_sym && reloc->valsize == 32 && offset != 0)
- {
- yasm_intnum *off_intn = yasm_intnum_create_uint(offset);
- yasm_intnum_calc(intn, YASM_EXPR_ADD, off_intn);
- yasm_intnum_destroy(off_intn);
- }
- return; /* .rel: Leave addend in intn */
-}
-
-static unsigned int
-elf_x86_x86_map_reloc_info_to_type(elf_reloc_entry *reloc)
-{
- if (reloc->wrt) {
- const elf_machine_ssym *ssym = (elf_machine_ssym *)
- yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
- if (!ssym || reloc->valsize != ssym->size)
- yasm_internal_error(N_("Unsupported WRT"));
-
- /* Force TLS type; this is required by the linker. */
- if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
- elf_symtab_entry *esym;
-
- esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
- if (esym)
- esym->type = STT_TLS;
- }
- return (unsigned char) ssym->reloc;
- } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
- return (unsigned char) R_386_GOTPC;
- } else if (reloc->rtype_rel) {
- switch (reloc->valsize) {
- case 8: return (unsigned char) R_386_PC8;
- case 16: return (unsigned char) R_386_PC16;
- case 32: return (unsigned char) R_386_PC32;
- default: yasm_internal_error(N_("Unsupported relocation size"));
- }
- } else {
- switch (reloc->valsize) {
- case 8: return (unsigned char) R_386_8;
- case 16: return (unsigned char) R_386_16;
- case 32: return (unsigned char) R_386_32;
- default: yasm_internal_error(N_("Unsupported relocation size"));
- }
- }
- return 0;
-}
-
-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 long)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", ".rel",
- SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32_SIZE, SHDR32_SIZE, EHDR32_SIZE,
- elf_x86_x86_accepts_reloc,
- elf_x86_x86_write_symtab_entry,
- elf_x86_x86_write_secthead,
- elf_x86_x86_write_secthead_rel,
- elf_x86_x86_handle_reloc_addend,
- elf_x86_x86_map_reloc_info_to_type,
- elf_x86_x86_write_reloc,
- elf_x86_x86_write_proghead,
- elf_x86_x86_ssyms,
- sizeof(elf_x86_x86_ssyms)/sizeof(elf_x86_x86_ssyms[0]),
- 32
-};
+/*
+ * ELF object format helpers - x86:x86
+ *
+ * Copyright (C) 2004-2007 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>
+
+#include <libyasm.h>
+#define YASM_OBJFMT_ELF_INTERNAL
+#include "elf.h"
+#include "elf-machine.h"
+
+static elf_machine_ssym elf_x86_x86_ssyms[] = {
+ {"plt", ELF_SSYM_SYM_RELATIVE, R_386_PLT32, 32},
+ {"gotoff", 0, R_386_GOTOFF, 32},
+ /* special one for NASM */
+ {"gotpc", ELF_SSYM_CURPOS_ADJUST, R_386_GOTPC, 32},
+ {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_GD, 32},
+ {"tlsldm", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_LDM, 32},
+ {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_IE_32, 32},
+ {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_LE_32, 32},
+ {"ntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_LE, 32},
+ {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_LDO_32, 32},
+ {"gotntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_GOTIE, 32},
+ {"indntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_IE, 32},
+ {"got", ELF_SSYM_SYM_RELATIVE, R_386_GOT32, 32},
+ {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_GOTDESC, 32},
+ {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_DESC_CALL, 32}
+};
+
+static int
+elf_x86_x86_accepts_reloc(size_t val, yasm_symrec *wrt)
+{
+ if (wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
+ if (!ssym || val != ssym->size)
+ return 0;
+ return 1;
+ }
+ return (val&(val-1)) ? 0 : ((val & (8|16|32)) != 0);
+}
+
+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, ELF32_ST_OTHER(entry->vis));
+ if (entry->sect) {
+ 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);
+
+ YASM_WRITE_32_L(bufp, shead->align);
+ 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 void
+elf_x86_x86_handle_reloc_addend(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset)
+{
+ if (!reloc->wrt && reloc->is_GOT_sym && reloc->valsize == 32 && offset != 0)
+ {
+ yasm_intnum *off_intn = yasm_intnum_create_uint(offset);
+ yasm_intnum_calc(intn, YASM_EXPR_ADD, off_intn);
+ yasm_intnum_destroy(off_intn);
+ }
+ return; /* .rel: Leave addend in intn */
+}
+
+static unsigned int
+elf_x86_x86_map_reloc_info_to_type(elf_reloc_entry *reloc)
+{
+ if (reloc->wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
+ if (!ssym || reloc->valsize != ssym->size)
+ yasm_internal_error(N_("Unsupported WRT"));
+
+ /* Force TLS type; this is required by the linker. */
+ if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
+ elf_symtab_entry *esym;
+
+ esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
+ if (esym)
+ esym->type = STT_TLS;
+ }
+ return (unsigned char) ssym->reloc;
+ } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
+ return (unsigned char) R_386_GOTPC;
+ } else if (reloc->rtype_rel) {
+ switch (reloc->valsize) {
+ case 8: return (unsigned char) R_386_PC8;
+ case 16: return (unsigned char) R_386_PC16;
+ case 32: return (unsigned char) R_386_PC32;
+ default: yasm_internal_error(N_("Unsupported relocation size"));
+ }
+ } else {
+ switch (reloc->valsize) {
+ case 8: return (unsigned char) R_386_8;
+ case 16: return (unsigned char) R_386_16;
+ case 32: return (unsigned char) R_386_32;
+ default: yasm_internal_error(N_("Unsupported relocation size"));
+ }
+ }
+ return 0;
+}
+
+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 long)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", ".rel",
+ SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32_SIZE, SHDR32_SIZE, EHDR32_SIZE,
+ elf_x86_x86_accepts_reloc,
+ elf_x86_x86_write_symtab_entry,
+ elf_x86_x86_write_secthead,
+ elf_x86_x86_write_secthead_rel,
+ elf_x86_x86_handle_reloc_addend,
+ elf_x86_x86_map_reloc_info_to_type,
+ elf_x86_x86_write_reloc,
+ elf_x86_x86_write_proghead,
+ elf_x86_x86_ssyms,
+ sizeof(elf_x86_x86_ssyms)/sizeof(elf_x86_x86_ssyms[0]),
+ 32
+};
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf.c b/contrib/tools/yasm/modules/objfmts/elf/elf.c
index 2486bba8df..04f3fe661a 100644
--- a/contrib/tools/yasm/modules/objfmts/elf/elf.c
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf.c
@@ -1,960 +1,960 @@
-/*
- * ELF object format helpers
- *
- * Copyright (C) 2003-2007 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>
-
-#include <libyasm.h>
-#define YASM_OBJFMT_ELF_INTERNAL
-#include "elf.h"
-#include "elf-machine.h"
-
-static void elf_section_data_destroy(void *data);
-static void elf_secthead_print(void *data, FILE *f, int indent_level);
-
-const yasm_assoc_data_callback elf_section_data = {
- elf_section_data_destroy,
- elf_secthead_print
-};
-
-static void elf_symrec_data_destroy(/*@only@*/ void *d);
-static void elf_symtab_entry_print(void *data, FILE *f, int indent_level);
-static void elf_ssym_symtab_entry_print(void *data, FILE *f, int indent_level);
-
-const yasm_assoc_data_callback elf_symrec_data = {
- elf_symrec_data_destroy,
- elf_symtab_entry_print
-};
-
-const yasm_assoc_data_callback elf_ssym_symrec_data = {
- elf_symrec_data_destroy,
- elf_ssym_symtab_entry_print
-};
-
-extern elf_machine_handler
- elf_machine_handler_x86_x86,
- elf_machine_handler_x86_amd64,
- elf_machine_handler_x86_x32;
-
-static const elf_machine_handler *elf_machine_handlers[] =
-{
- &elf_machine_handler_x86_x86,
- &elf_machine_handler_x86_amd64,
- &elf_machine_handler_x86_x32,
- NULL
-};
-static const elf_machine_handler elf_null_machine = {0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0};
-static elf_machine_handler const *elf_march = &elf_null_machine;
-static yasm_symrec **elf_ssyms;
-
-const elf_machine_handler *
-elf_set_arch(yasm_arch *arch, yasm_symtab *symtab, int bits_pref)
-{
- const char *machine = yasm_arch_get_machine(arch);
- int i;
-
- 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) {
- if (bits_pref == 0 || bits_pref == elf_march->bits)
- break;
- } else if (bits_pref == elf_march->bits
- && yasm__strcasecmp(machine, "amd64") == 0
- && yasm__strcasecmp(elf_march->machine, "x32") == 0)
- break;
- }
- }
-
- if (elf_march && elf_march->num_ssyms > 0)
- {
- /* Allocate "special" syms */
- elf_ssyms =
- yasm_xmalloc(elf_march->num_ssyms * sizeof(yasm_symrec *));
- for (i=0; (unsigned int)i<elf_march->num_ssyms; i++)
- {
- /* FIXME: misuse of NULL bytecode */
- elf_ssyms[i] = yasm_symtab_define_label(symtab,
- elf_march->ssyms[i].name,
- NULL, 0, 0);
- yasm_symrec_add_data(elf_ssyms[i], &elf_ssym_symrec_data,
- (void*)&elf_march->ssyms[i]);
- }
- }
-
- return elf_march;
-}
-
-yasm_symrec *
-elf_get_special_sym(const char *name, const char *parser)
-{
- int i;
- for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
- if (yasm__strcasecmp(name, elf_march->ssyms[i].name) == 0)
- return elf_ssyms[i];
- }
- return NULL;
-}
-
-/* reloc functions */
-int elf_ssym_has_flag(yasm_symrec *wrt, int flag);
-
-int
-elf_is_wrt_sym_relative(yasm_symrec *wrt)
-{
- return elf_ssym_has_flag(wrt, ELF_SSYM_SYM_RELATIVE);
-}
-
-int
-elf_is_wrt_pos_adjusted(yasm_symrec *wrt)
-{
- return elf_ssym_has_flag(wrt, ELF_SSYM_CURPOS_ADJUST);
-}
-
-int
-elf_ssym_has_flag(yasm_symrec *wrt, int flag)
-{
- int i;
- for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
- if (elf_ssyms[i] == wrt)
- return (elf_march->ssyms[i].sym_rel & flag) != 0;
- }
- return 0;
-}
-
-/* takes ownership of addr */
-elf_reloc_entry *
-elf_reloc_entry_create(yasm_symrec *sym,
- yasm_symrec *wrt,
- yasm_intnum *addr,
- int rel,
- size_t valsize,
- int is_GOT_sym)
-{
- elf_reloc_entry *entry;
-
- if (!elf_march->accepts_reloc)
- yasm_internal_error(N_("Unsupported machine for ELF output"));
-
- if (!elf_march->accepts_reloc(valsize, wrt))
- {
- if (addr)
- yasm_intnum_destroy(addr);
- return NULL;
- }
-
- if (sym == NULL)
- yasm_internal_error("sym is null");
-
- entry = yasm_xmalloc(sizeof(elf_reloc_entry));
- entry->reloc.sym = sym;
- entry->reloc.addr = addr;
- entry->rtype_rel = rel;
- entry->valsize = valsize;
- entry->addend = NULL;
- entry->wrt = wrt;
- entry->is_GOT_sym = is_GOT_sym;
-
- return entry;
-}
-
-void
-elf_reloc_entry_destroy(void *entry)
-{
- if (((elf_reloc_entry*)entry)->addend)
- yasm_intnum_destroy(((elf_reloc_entry*)entry)->addend);
- yasm_xfree(entry);
-}
-
-/* strtab functions */
-elf_strtab_entry *
-elf_strtab_entry_create(const char *str)
-{
- elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry));
- entry->str = yasm__xstrdup(str);
- entry->index = 0;
- return entry;
-}
-
-void
-elf_strtab_entry_set_str(elf_strtab_entry *entry, const char *str)
-{
- elf_strtab_entry *last;
- if (entry->str)
- yasm_xfree(entry->str);
- entry->str = yasm__xstrdup(str);
-
- /* Update all following indices since string length probably changes */
- last = entry;
- entry = STAILQ_NEXT(last, qlink);
- while (entry) {
- entry->index = last->index + (unsigned long)strlen(last->str) + 1;
- last = entry;
- entry = STAILQ_NEXT(last, qlink);
- }
-}
-
-elf_strtab_head *
-elf_strtab_create()
-{
- elf_strtab_head *strtab = yasm_xmalloc(sizeof(elf_strtab_head));
- elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry));
-
- STAILQ_INIT(strtab);
- entry->index = 0;
- entry->str = yasm__xstrdup("");
-
- STAILQ_INSERT_TAIL(strtab, entry, qlink);
- return strtab;
-}
-
-elf_strtab_entry *
-elf_strtab_append_str(elf_strtab_head *strtab, const char *str)
-{
- elf_strtab_entry *last, *entry;
-
- if (strtab == NULL)
- yasm_internal_error("strtab is null");
- if (STAILQ_EMPTY(strtab))
- yasm_internal_error("strtab is missing initial dummy entry");
-
- last = STAILQ_LAST(strtab, elf_strtab_entry, qlink);
-
- entry = elf_strtab_entry_create(str);
- entry->index = last->index + (unsigned long)strlen(last->str) + 1;
-
- STAILQ_INSERT_TAIL(strtab, entry, qlink);
- return entry;
-}
-
-void
-elf_strtab_destroy(elf_strtab_head *strtab)
-{
- elf_strtab_entry *s1, *s2;
-
- if (strtab == NULL)
- yasm_internal_error("strtab is null");
- if (STAILQ_EMPTY(strtab))
- yasm_internal_error("strtab is missing initial dummy entry");
-
- s1 = STAILQ_FIRST(strtab);
- while (s1 != NULL) {
- s2 = STAILQ_NEXT(s1, qlink);
- yasm_xfree(s1->str);
- yasm_xfree(s1);
- s1 = s2;
- }
- yasm_xfree(strtab);
-}
-
-unsigned long
-elf_strtab_output_to_file(FILE *f, elf_strtab_head *strtab)
-{
- unsigned long size = 0;
- elf_strtab_entry *entry;
-
- if (strtab == NULL)
- yasm_internal_error("strtab is null");
-
- /* consider optimizing tables here */
- STAILQ_FOREACH(entry, strtab, qlink) {
- size_t len = 1 + strlen(entry->str);
- fwrite(entry->str, len, 1, f);
- size += (unsigned long)len;
- }
- return size;
-}
-
-
-
-/* symtab functions */
-elf_symtab_entry *
-elf_symtab_entry_create(elf_strtab_entry *name,
- yasm_symrec *sym)
-{
- elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry));
- entry->in_table = 0;
- entry->sym = sym;
- entry->sect = NULL;
- entry->name = name;
- entry->value = 0;
-
- entry->xsize = NULL;
- entry->size = 0;
- entry->index = 0;
- entry->bind = 0;
- entry->type = STT_NOTYPE;
- entry->vis = STV_DEFAULT;
-
- return entry;
-}
-
-static void
-elf_symtab_entry_destroy(elf_symtab_entry *entry)
-{
- if (entry == NULL)
- yasm_internal_error("symtab entry is null");
-
- yasm_xfree(entry);
-}
-
-static void
-elf_symrec_data_destroy(void *data)
-{
- /* do nothing, as this stuff is in the symtab anyway... this speaks of bad
- * design/use or this stuff, i fear */
-
- /* watch for double-free here ... */
- /*elf_symtab_entry_destroy((elf_symtab_entry *)data);*/
-}
-
-static void
-elf_symtab_entry_print(void *data, FILE *f, int indent_level)
-{
- elf_symtab_entry *entry = data;
- if (entry == NULL)
- yasm_internal_error("symtab entry is null");
-
- fprintf(f, "%*sbind=", indent_level, "");
- switch (entry->bind) {
- case STB_LOCAL: fprintf(f, "local\n"); break;
- case STB_GLOBAL: fprintf(f, "global\n"); break;
- case STB_WEAK: fprintf(f, "weak\n"); break;
- default: fprintf(f, "undef\n"); break;
- }
- fprintf(f, "%*stype=", indent_level, "");
- switch (entry->type) {
- case STT_NOTYPE: fprintf(f, "notype\n"); break;
- case STT_OBJECT: fprintf(f, "object\n"); break;
- case STT_FUNC: fprintf(f, "func\n"); break;
- case STT_SECTION: fprintf(f, "section\n");break;
- case STT_FILE: fprintf(f, "file\n"); break;
- default: fprintf(f, "undef\n"); break;
- }
- fprintf(f, "%*ssize=", indent_level, "");
- if (entry->xsize)
- yasm_expr_print(entry->xsize, f);
- else
- fprintf(f, "%ld", entry->size);
- fprintf(f, "\n");
-}
-
-static void
-elf_ssym_symtab_entry_print(void *data, FILE *f, int indent_level)
-{
- /* TODO */
-}
-
-elf_symtab_head *
-elf_symtab_create()
-{
- elf_symtab_head *symtab = yasm_xmalloc(sizeof(elf_symtab_head));
- elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry));
-
- STAILQ_INIT(symtab);
- entry->in_table = 1;
- entry->sym = NULL;
- entry->sect = NULL;
- entry->name = NULL;
- entry->value = 0;
- entry->xsize = NULL;
- entry->size = 0;
- entry->index = SHN_UNDEF;
- entry->bind = STB_LOCAL;
- entry->type = STT_NOTYPE;
- entry->vis = STV_DEFAULT;
- entry->symindex = 0;
- STAILQ_INSERT_TAIL(symtab, entry, qlink);
- return symtab;
-}
-
-void
-elf_symtab_append_entry(elf_symtab_head *symtab, elf_symtab_entry *entry)
-{
- if (symtab == NULL)
- yasm_internal_error("symtab is null");
- if (entry == NULL)
- yasm_internal_error("symtab entry is null");
- if (STAILQ_EMPTY(symtab))
- yasm_internal_error(N_("symtab is missing initial dummy entry"));
-
- STAILQ_INSERT_TAIL(symtab, entry, qlink);
- entry->in_table = 1;
-}
-
-void
-elf_symtab_insert_local_sym(elf_symtab_head *symtab, elf_symtab_entry *entry)
-{
- elf_symtab_entry *after = STAILQ_FIRST(symtab);
- elf_symtab_entry *before = NULL;
-
- while (after && (after->bind == STB_LOCAL)) {
- before = after;
- if (before->type == STT_FILE) break;
- after = STAILQ_NEXT(after, qlink);
- }
- STAILQ_INSERT_AFTER(symtab, before, entry, qlink);
- entry->in_table = 1;
-}
-
-void
-elf_symtab_destroy(elf_symtab_head *symtab)
-{
- elf_symtab_entry *s1, *s2;
-
- if (symtab == NULL)
- yasm_internal_error("symtab is null");
- if (STAILQ_EMPTY(symtab))
- yasm_internal_error(N_("symtab is missing initial dummy entry"));
-
- s1 = STAILQ_FIRST(symtab);
- while (s1 != NULL) {
- s2 = STAILQ_NEXT(s1, qlink);
- elf_symtab_entry_destroy(s1);
- s1 = s2;
- }
- yasm_xfree(symtab);
-}
-
-unsigned long
-elf_symtab_assign_indices(elf_symtab_head *symtab)
-{
- elf_symtab_entry *entry, *prev=NULL;
- unsigned long last_local=0;
-
- if (symtab == NULL)
- yasm_internal_error("symtab is null");
- if (STAILQ_EMPTY(symtab))
- yasm_internal_error(N_("symtab is missing initial dummy entry"));
-
- STAILQ_FOREACH(entry, symtab, qlink) {
- if (prev)
- entry->symindex = prev->symindex + 1;
- if (entry->bind == STB_LOCAL)
- last_local = entry->symindex;
- prev = entry;
- }
- return last_local + 1;
-}
-
-unsigned long
-elf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab,
- yasm_errwarns *errwarns)
-{
- unsigned char buf[SYMTAB_MAXSIZE], *bufp;
- elf_symtab_entry *entry;
- unsigned long size = 0;
-
- if (!symtab)
- yasm_internal_error(N_("symtab is null"));
-
- STAILQ_FOREACH(entry, symtab, qlink) {
-
- yasm_intnum *size_intn=NULL, *value_intn=NULL;
- bufp = buf;
-
- /* get size (if specified); expr overrides stored integer */
- if (entry->xsize) {
- size_intn = yasm_intnum_copy(
- yasm_expr_get_intnum(&entry->xsize, 1));
- if (!size_intn) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("size specifier not an integer expression"));
- yasm_errwarn_propagate(errwarns, entry->xsize->line);
- }
- }
- else
- size_intn = yasm_intnum_create_uint(entry->size);
-
- /* get EQU value for constants */
- if (entry->sym) {
- const yasm_expr *equ_expr_c;
- equ_expr_c = yasm_symrec_get_equ(entry->sym);
-
- if (equ_expr_c != NULL) {
- const yasm_intnum *equ_intn;
- yasm_expr *equ_expr = yasm_expr_copy(equ_expr_c);
- equ_intn = yasm_expr_get_intnum(&equ_expr, 1);
-
- if (equ_intn == NULL) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("EQU value not an integer expression"));
- yasm_errwarn_propagate(errwarns, equ_expr->line);
- } else
- value_intn = yasm_intnum_copy(equ_intn);
- entry->index = SHN_ABS;
- yasm_expr_destroy(equ_expr);
- }
- }
- if (value_intn == NULL)
- value_intn = yasm_intnum_create_uint(entry->value);
-
- /* If symbol is in a TLS section, force its type to TLS. */
- if (entry->sym) {
- yasm_bytecode *precbc;
- yasm_section *sect;
- elf_secthead *shead;
- if (yasm_symrec_get_label(entry->sym, &precbc) &&
- (sect = yasm_bc_get_section(precbc)) &&
- (shead = yasm_section_get_data(sect, &elf_section_data)) &&
- shead->flags & SHF_TLS) {
- entry->type = STT_TLS;
- }
- }
-
- if (!elf_march->write_symtab_entry || !elf_march->symtab_entry_size)
- yasm_internal_error(N_("Unsupported machine for ELF output"));
- elf_march->write_symtab_entry(bufp, entry, value_intn, size_intn);
- fwrite(buf, elf_march->symtab_entry_size, 1, f);
- size += elf_march->symtab_entry_size;
-
- yasm_intnum_destroy(size_intn);
- yasm_intnum_destroy(value_intn);
- }
- return size;
-}
-
-void elf_symtab_set_nonzero(elf_symtab_entry *entry,
- yasm_section *sect,
- elf_section_index sectidx,
- elf_symbol_binding bind,
- elf_symbol_type type,
- yasm_expr *xsize,
- elf_address *value)
-{
- if (!entry)
- yasm_internal_error("NULL entry");
- if (sect) entry->sect = sect;
- if (sectidx) entry->index = sectidx;
- if (bind) entry->bind = bind;
- if (type) entry->type = type;
- if (xsize) entry->xsize = xsize;
- if (value) entry->value = *value;
-}
-
-void
-elf_sym_set_visibility(elf_symtab_entry *entry,
- elf_symbol_vis vis)
-{
- entry->vis = ELF_ST_VISIBILITY(vis);
-}
-
-void
-elf_sym_set_type(elf_symtab_entry *entry,
- elf_symbol_type type)
-{
- entry->type = type;
-}
-
-void
-elf_sym_set_size(elf_symtab_entry *entry,
- struct yasm_expr *size)
-{
- if (entry->xsize)
- yasm_expr_destroy(entry->xsize);
- entry->xsize = size;
-}
-
-int
-elf_sym_in_table(elf_symtab_entry *entry)
-{
- return entry->in_table;
-}
-
-elf_secthead *
-elf_secthead_create(elf_strtab_entry *name,
- elf_section_type type,
- elf_section_flags flags,
- elf_address offset,
- elf_size size)
-{
- elf_secthead *esd = yasm_xmalloc(sizeof(elf_secthead));
-
- esd->type = type;
- esd->flags = flags;
- esd->offset = offset;
- esd->size = yasm_intnum_create_uint(size);
- esd->link = 0;
- esd->info = 0;
- esd->align = 0;
- esd->entsize = 0;
- esd->index = 0;
-
- esd->sym = NULL;
- esd->name = name;
- esd->index = 0;
- esd->rel_name = NULL;
- esd->rel_index = 0;
- esd->rel_offset = 0;
- esd->nreloc = 0;
-
- if (name && (strcmp(name->str, ".symtab") == 0)) {
- if (!elf_march->symtab_entry_size || !elf_march->symtab_entry_align)
- yasm_internal_error(N_("unsupported ELF format"));
- esd->entsize = elf_march->symtab_entry_size;
- esd->align = elf_march->symtab_entry_align;
- }
-
- return esd;
-}
-
-void
-elf_secthead_destroy(elf_secthead *shead)
-{
- if (shead == NULL)
- yasm_internal_error(N_("shead is null"));
-
- yasm_intnum_destroy(shead->size);
-
- yasm_xfree(shead);
-}
-
-static void
-elf_section_data_destroy(void *data)
-{
- elf_secthead_destroy((elf_secthead *)data);
-}
-
-static void
-elf_secthead_print(void *data, FILE *f, int indent_level)
-{
- elf_secthead *sect = data;
- fprintf(f, "%*sname=%s\n", indent_level, "",
- sect->name ? sect->name->str : "<undef>");
- fprintf(f, "%*ssym=\n", indent_level, "");
- yasm_symrec_print(sect->sym, f, indent_level+1);
- fprintf(f, "%*sindex=0x%x\n", indent_level, "", sect->index);
- fprintf(f, "%*sflags=", indent_level, "");
- if (sect->flags & SHF_WRITE)
- fprintf(f, "WRITE ");
- if (sect->flags & SHF_ALLOC)
- fprintf(f, "ALLOC ");
- if (sect->flags & SHF_EXECINSTR)
- fprintf(f, "EXEC ");
- /*if (sect->flags & SHF_MASKPROC)
- fprintf(f, "PROC-SPECIFIC"); */
- fprintf(f, "%*soffset=0x%lx\n", indent_level, "", sect->offset);
- fprintf(f, "%*ssize=0x%lx\n", indent_level, "",
- yasm_intnum_get_uint(sect->size));
- fprintf(f, "%*slink=0x%x\n", indent_level, "", sect->link);
- fprintf(f, "%*salign=%lu\n", indent_level, "", sect->align);
- fprintf(f, "%*snreloc=%ld\n", indent_level, "", sect->nreloc);
-}
-
-unsigned long
-elf_secthead_write_to_file(FILE *f, elf_secthead *shead,
- elf_section_index sindex)
-{
- unsigned char buf[SHDR_MAXSIZE], *bufp = buf;
- shead->index = sindex;
-
- if (shead == NULL)
- yasm_internal_error("shead is null");
-
- if (!elf_march->write_secthead || !elf_march->secthead_size)
- yasm_internal_error(N_("Unsupported machine for ELF output"));
- elf_march->write_secthead(bufp, shead);
- if (fwrite(buf, elf_march->secthead_size, 1, f))
- return elf_march->secthead_size;
- yasm_internal_error(N_("Failed to write an elf section header"));
- return 0;
-}
-
-void
-elf_secthead_append_reloc(yasm_section *sect, elf_secthead *shead,
- elf_reloc_entry *reloc)
-{
- if (sect == NULL)
- yasm_internal_error("sect is null");
- if (shead == NULL)
- yasm_internal_error("shead is null");
- if (reloc == NULL)
- yasm_internal_error("reloc is null");
-
- shead->nreloc++;
- yasm_section_add_reloc(sect, (yasm_reloc *)reloc, elf_reloc_entry_destroy);
-}
-
-char *
-elf_secthead_name_reloc_section(const char *basesect)
-{
- if (!elf_march->reloc_section_prefix)
- {
- yasm_internal_error(N_("Unsupported machine for ELF output"));
- return NULL;
- }
- else
- {
- size_t prepend_length = strlen(elf_march->reloc_section_prefix);
- char *sectname = yasm_xmalloc(prepend_length + strlen(basesect) + 1);
- strcpy(sectname, elf_march->reloc_section_prefix);
- strcat(sectname, basesect);
- return sectname;
- }
-}
-
-void
-elf_handle_reloc_addend(yasm_intnum *intn,
- elf_reloc_entry *reloc,
- unsigned long offset)
-{
- if (!elf_march->handle_reloc_addend)
- yasm_internal_error(N_("Unsupported machine for ELF output"));
- elf_march->handle_reloc_addend(intn, reloc, offset);
-}
-
-unsigned long
-elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab_idx,
- yasm_section *sect, elf_secthead *shead,
- elf_section_index sindex)
-{
- unsigned char buf[SHDR_MAXSIZE], *bufp = buf;
-
- if (shead == NULL)
- yasm_internal_error("shead is null");
-
- if (!yasm_section_relocs_first(sect))
- return 0; /* no relocations, no .rel.* section header */
-
- shead->rel_index = sindex;
-
- if (!elf_march->write_secthead_rel || !elf_march->secthead_size)
- yasm_internal_error(N_("Unsupported machine for ELF output"));
- elf_march->write_secthead_rel(bufp, shead, symtab_idx, sindex);
- if (fwrite(buf, elf_march->secthead_size, 1, f))
- return elf_march->secthead_size;
- yasm_internal_error(N_("Failed to write an elf section header"));
- return 0;
-}
-
-unsigned long
-elf_secthead_write_relocs_to_file(FILE *f, yasm_section *sect,
- elf_secthead *shead, yasm_errwarns *errwarns)
-{
- elf_reloc_entry *reloc;
- unsigned char buf[RELOC_MAXSIZE], *bufp;
- unsigned long size = 0;
- long pos;
-
- if (shead == NULL)
- yasm_internal_error("shead is null");
-
- reloc = (elf_reloc_entry *)yasm_section_relocs_first(sect);
- if (!reloc)
- return 0;
-
- /* first align section to multiple of 4 */
- pos = ftell(f);
- if (pos == -1) {
- yasm_error_set(YASM_ERROR_IO,
- N_("couldn't read position on output stream"));
- yasm_errwarn_propagate(errwarns, 0);
- }
- pos = (pos + 3) & ~3;
- if (fseek(f, pos, SEEK_SET) < 0) {
- yasm_error_set(YASM_ERROR_IO, N_("couldn't seek on output stream"));
- yasm_errwarn_propagate(errwarns, 0);
- }
- shead->rel_offset = (unsigned long)pos;
-
-
- while (reloc) {
- unsigned int r_type=0, r_sym;
- elf_symtab_entry *esym;
-
- esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
- if (esym)
- r_sym = esym->symindex;
- else
- r_sym = STN_UNDEF;
-
- if (!elf_march->map_reloc_info_to_type)
- yasm_internal_error(N_("Unsupported arch/machine for elf output"));
- r_type = elf_march->map_reloc_info_to_type(reloc);
-
- bufp = buf;
- if (!elf_march->write_reloc || !elf_march->reloc_entry_size)
- yasm_internal_error(N_("Unsupported arch/machine for elf output"));
- elf_march->write_reloc(bufp, reloc, r_type, r_sym);
- fwrite(buf, elf_march->reloc_entry_size, 1, f);
- size += elf_march->reloc_entry_size;
-
- reloc = (elf_reloc_entry *)
- yasm_section_reloc_next((yasm_reloc *)reloc);
- }
- return size;
-}
-
-elf_section_type
-elf_secthead_get_type(elf_secthead *shead)
-{
- return shead->type;
-}
-
-void
-elf_secthead_set_typeflags(elf_secthead *shead, elf_section_type type,
- elf_section_flags flags)
-{
- shead->type = type;
- shead->flags = flags;
-}
-
-int
-elf_secthead_is_empty(elf_secthead *shead)
-{
- return yasm_intnum_is_zero(shead->size);
-}
-
-yasm_symrec *
-elf_secthead_get_sym(elf_secthead *shead)
-{
- return shead->sym;
-}
-
-elf_section_index
-elf_secthead_get_index(elf_secthead *shead)
-{
- return shead->index;
-}
-
-unsigned long
-elf_secthead_get_align(const elf_secthead *shead)
-{
- return shead->align;
-}
-
-unsigned long
-elf_secthead_set_align(elf_secthead *shead, unsigned long align)
-{
- return shead->align = align;
-}
-
-elf_section_info
-elf_secthead_set_info(elf_secthead *shead, elf_section_info info)
-{
- return shead->info = info;
-}
-
-elf_section_index
-elf_secthead_set_index(elf_secthead *shead, elf_section_index sectidx)
-{
- return shead->index = sectidx;
-}
-
-elf_section_index
-elf_secthead_set_link(elf_secthead *shead, elf_section_index link)
-{
- return shead->link = link;
-}
-
-elf_section_index
-elf_secthead_set_rel_index(elf_secthead *shead, elf_section_index sectidx)
-{
- return shead->rel_index = sectidx;
-}
-
-elf_strtab_entry *
-elf_secthead_set_rel_name(elf_secthead *shead, elf_strtab_entry *entry)
-{
- return shead->rel_name = entry;
-}
-
-elf_size
-elf_secthead_set_entsize(elf_secthead *shead, elf_size size)
-{
- return shead->entsize = size;
-}
-
-yasm_symrec *
-elf_secthead_set_sym(elf_secthead *shead, yasm_symrec *sym)
-{
- return shead->sym = sym;
-}
-
-void
-elf_secthead_add_size(elf_secthead *shead, yasm_intnum *size)
-{
- if (size) {
- yasm_intnum_calc(shead->size, YASM_EXPR_ADD, size);
- }
-}
-
-long
-elf_secthead_set_file_offset(elf_secthead *shead, long pos)
-{
- unsigned long align = shead->align;
-
- if (align == 0 || align == 1) {
- shead->offset = (unsigned long)pos;
- return pos;
- }
- else if (align & (align - 1))
- yasm_internal_error(
- N_("alignment %d for section `%s' is not a power of 2"));
- /*, align, sect->name->str);*/
-
- shead->offset = (unsigned long)((pos + align - 1) & ~(align - 1));
- return (long)shead->offset;
-}
-
-unsigned long
-elf_proghead_get_size(void)
-{
- if (!elf_march->proghead_size)
- yasm_internal_error(N_("Unsupported ELF format for output"));
- return elf_march->proghead_size;
-}
-
-unsigned long
-elf_proghead_write_to_file(FILE *f,
- elf_offset secthead_addr,
- unsigned long secthead_count,
- elf_section_index shstrtab_index)
-{
- unsigned char buf[EHDR_MAXSIZE], *bufp = buf;
-
- YASM_WRITE_8(bufp, ELFMAG0); /* ELF magic number */
- YASM_WRITE_8(bufp, ELFMAG1);
- YASM_WRITE_8(bufp, ELFMAG2);
- YASM_WRITE_8(bufp, ELFMAG3);
-
- if (!elf_march->write_proghead || !elf_march->proghead_size)
- yasm_internal_error(N_("Unsupported ELF format for output"));
- elf_march->write_proghead(&bufp, secthead_addr, secthead_count, shstrtab_index);
-
- if (((unsigned)(bufp - buf)) != elf_march->proghead_size)
- yasm_internal_error(N_("ELF program header is not proper length"));
-
- if (fwrite(buf, elf_march->proghead_size, 1, f))
- return elf_march->proghead_size;
-
- yasm_internal_error(N_("Failed to write ELF program header"));
- return 0;
-}
+/*
+ * ELF object format helpers
+ *
+ * Copyright (C) 2003-2007 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>
+
+#include <libyasm.h>
+#define YASM_OBJFMT_ELF_INTERNAL
+#include "elf.h"
+#include "elf-machine.h"
+
+static void elf_section_data_destroy(void *data);
+static void elf_secthead_print(void *data, FILE *f, int indent_level);
+
+const yasm_assoc_data_callback elf_section_data = {
+ elf_section_data_destroy,
+ elf_secthead_print
+};
+
+static void elf_symrec_data_destroy(/*@only@*/ void *d);
+static void elf_symtab_entry_print(void *data, FILE *f, int indent_level);
+static void elf_ssym_symtab_entry_print(void *data, FILE *f, int indent_level);
+
+const yasm_assoc_data_callback elf_symrec_data = {
+ elf_symrec_data_destroy,
+ elf_symtab_entry_print
+};
+
+const yasm_assoc_data_callback elf_ssym_symrec_data = {
+ elf_symrec_data_destroy,
+ elf_ssym_symtab_entry_print
+};
+
+extern elf_machine_handler
+ elf_machine_handler_x86_x86,
+ elf_machine_handler_x86_amd64,
+ elf_machine_handler_x86_x32;
+
+static const elf_machine_handler *elf_machine_handlers[] =
+{
+ &elf_machine_handler_x86_x86,
+ &elf_machine_handler_x86_amd64,
+ &elf_machine_handler_x86_x32,
+ NULL
+};
+static const elf_machine_handler elf_null_machine = {0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0};
+static elf_machine_handler const *elf_march = &elf_null_machine;
+static yasm_symrec **elf_ssyms;
+
+const elf_machine_handler *
+elf_set_arch(yasm_arch *arch, yasm_symtab *symtab, int bits_pref)
+{
+ const char *machine = yasm_arch_get_machine(arch);
+ int i;
+
+ 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) {
+ if (bits_pref == 0 || bits_pref == elf_march->bits)
+ break;
+ } else if (bits_pref == elf_march->bits
+ && yasm__strcasecmp(machine, "amd64") == 0
+ && yasm__strcasecmp(elf_march->machine, "x32") == 0)
+ break;
+ }
+ }
+
+ if (elf_march && elf_march->num_ssyms > 0)
+ {
+ /* Allocate "special" syms */
+ elf_ssyms =
+ yasm_xmalloc(elf_march->num_ssyms * sizeof(yasm_symrec *));
+ for (i=0; (unsigned int)i<elf_march->num_ssyms; i++)
+ {
+ /* FIXME: misuse of NULL bytecode */
+ elf_ssyms[i] = yasm_symtab_define_label(symtab,
+ elf_march->ssyms[i].name,
+ NULL, 0, 0);
+ yasm_symrec_add_data(elf_ssyms[i], &elf_ssym_symrec_data,
+ (void*)&elf_march->ssyms[i]);
+ }
+ }
+
+ return elf_march;
+}
+
+yasm_symrec *
+elf_get_special_sym(const char *name, const char *parser)
+{
+ int i;
+ for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
+ if (yasm__strcasecmp(name, elf_march->ssyms[i].name) == 0)
+ return elf_ssyms[i];
+ }
+ return NULL;
+}
+
+/* reloc functions */
+int elf_ssym_has_flag(yasm_symrec *wrt, int flag);
+
+int
+elf_is_wrt_sym_relative(yasm_symrec *wrt)
+{
+ return elf_ssym_has_flag(wrt, ELF_SSYM_SYM_RELATIVE);
+}
+
+int
+elf_is_wrt_pos_adjusted(yasm_symrec *wrt)
+{
+ return elf_ssym_has_flag(wrt, ELF_SSYM_CURPOS_ADJUST);
+}
+
+int
+elf_ssym_has_flag(yasm_symrec *wrt, int flag)
+{
+ int i;
+ for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
+ if (elf_ssyms[i] == wrt)
+ return (elf_march->ssyms[i].sym_rel & flag) != 0;
+ }
+ return 0;
+}
+
+/* takes ownership of addr */
+elf_reloc_entry *
+elf_reloc_entry_create(yasm_symrec *sym,
+ yasm_symrec *wrt,
+ yasm_intnum *addr,
+ int rel,
+ size_t valsize,
+ int is_GOT_sym)
+{
+ elf_reloc_entry *entry;
+
+ if (!elf_march->accepts_reloc)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+
+ if (!elf_march->accepts_reloc(valsize, wrt))
+ {
+ if (addr)
+ yasm_intnum_destroy(addr);
+ return NULL;
+ }
+
+ if (sym == NULL)
+ yasm_internal_error("sym is null");
+
+ entry = yasm_xmalloc(sizeof(elf_reloc_entry));
+ entry->reloc.sym = sym;
+ entry->reloc.addr = addr;
+ entry->rtype_rel = rel;
+ entry->valsize = valsize;
+ entry->addend = NULL;
+ entry->wrt = wrt;
+ entry->is_GOT_sym = is_GOT_sym;
+
+ return entry;
+}
+
+void
+elf_reloc_entry_destroy(void *entry)
+{
+ if (((elf_reloc_entry*)entry)->addend)
+ yasm_intnum_destroy(((elf_reloc_entry*)entry)->addend);
+ yasm_xfree(entry);
+}
+
+/* strtab functions */
+elf_strtab_entry *
+elf_strtab_entry_create(const char *str)
+{
+ elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry));
+ entry->str = yasm__xstrdup(str);
+ entry->index = 0;
+ return entry;
+}
+
+void
+elf_strtab_entry_set_str(elf_strtab_entry *entry, const char *str)
+{
+ elf_strtab_entry *last;
+ if (entry->str)
+ yasm_xfree(entry->str);
+ entry->str = yasm__xstrdup(str);
+
+ /* Update all following indices since string length probably changes */
+ last = entry;
+ entry = STAILQ_NEXT(last, qlink);
+ while (entry) {
+ entry->index = last->index + (unsigned long)strlen(last->str) + 1;
+ last = entry;
+ entry = STAILQ_NEXT(last, qlink);
+ }
+}
+
+elf_strtab_head *
+elf_strtab_create()
+{
+ elf_strtab_head *strtab = yasm_xmalloc(sizeof(elf_strtab_head));
+ elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry));
+
+ STAILQ_INIT(strtab);
+ entry->index = 0;
+ entry->str = yasm__xstrdup("");
+
+ STAILQ_INSERT_TAIL(strtab, entry, qlink);
+ return strtab;
+}
+
+elf_strtab_entry *
+elf_strtab_append_str(elf_strtab_head *strtab, const char *str)
+{
+ elf_strtab_entry *last, *entry;
+
+ if (strtab == NULL)
+ yasm_internal_error("strtab is null");
+ if (STAILQ_EMPTY(strtab))
+ yasm_internal_error("strtab is missing initial dummy entry");
+
+ last = STAILQ_LAST(strtab, elf_strtab_entry, qlink);
+
+ entry = elf_strtab_entry_create(str);
+ entry->index = last->index + (unsigned long)strlen(last->str) + 1;
+
+ STAILQ_INSERT_TAIL(strtab, entry, qlink);
+ return entry;
+}
+
+void
+elf_strtab_destroy(elf_strtab_head *strtab)
+{
+ elf_strtab_entry *s1, *s2;
+
+ if (strtab == NULL)
+ yasm_internal_error("strtab is null");
+ if (STAILQ_EMPTY(strtab))
+ yasm_internal_error("strtab is missing initial dummy entry");
+
+ s1 = STAILQ_FIRST(strtab);
+ while (s1 != NULL) {
+ s2 = STAILQ_NEXT(s1, qlink);
+ yasm_xfree(s1->str);
+ yasm_xfree(s1);
+ s1 = s2;
+ }
+ yasm_xfree(strtab);
+}
+
+unsigned long
+elf_strtab_output_to_file(FILE *f, elf_strtab_head *strtab)
+{
+ unsigned long size = 0;
+ elf_strtab_entry *entry;
+
+ if (strtab == NULL)
+ yasm_internal_error("strtab is null");
+
+ /* consider optimizing tables here */
+ STAILQ_FOREACH(entry, strtab, qlink) {
+ size_t len = 1 + strlen(entry->str);
+ fwrite(entry->str, len, 1, f);
+ size += (unsigned long)len;
+ }
+ return size;
+}
+
+
+
+/* symtab functions */
+elf_symtab_entry *
+elf_symtab_entry_create(elf_strtab_entry *name,
+ yasm_symrec *sym)
+{
+ elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry));
+ entry->in_table = 0;
+ entry->sym = sym;
+ entry->sect = NULL;
+ entry->name = name;
+ entry->value = 0;
+
+ entry->xsize = NULL;
+ entry->size = 0;
+ entry->index = 0;
+ entry->bind = 0;
+ entry->type = STT_NOTYPE;
+ entry->vis = STV_DEFAULT;
+
+ return entry;
+}
+
+static void
+elf_symtab_entry_destroy(elf_symtab_entry *entry)
+{
+ if (entry == NULL)
+ yasm_internal_error("symtab entry is null");
+
+ yasm_xfree(entry);
+}
+
+static void
+elf_symrec_data_destroy(void *data)
+{
+ /* do nothing, as this stuff is in the symtab anyway... this speaks of bad
+ * design/use or this stuff, i fear */
+
+ /* watch for double-free here ... */
+ /*elf_symtab_entry_destroy((elf_symtab_entry *)data);*/
+}
+
+static void
+elf_symtab_entry_print(void *data, FILE *f, int indent_level)
+{
+ elf_symtab_entry *entry = data;
+ if (entry == NULL)
+ yasm_internal_error("symtab entry is null");
+
+ fprintf(f, "%*sbind=", indent_level, "");
+ switch (entry->bind) {
+ case STB_LOCAL: fprintf(f, "local\n"); break;
+ case STB_GLOBAL: fprintf(f, "global\n"); break;
+ case STB_WEAK: fprintf(f, "weak\n"); break;
+ default: fprintf(f, "undef\n"); break;
+ }
+ fprintf(f, "%*stype=", indent_level, "");
+ switch (entry->type) {
+ case STT_NOTYPE: fprintf(f, "notype\n"); break;
+ case STT_OBJECT: fprintf(f, "object\n"); break;
+ case STT_FUNC: fprintf(f, "func\n"); break;
+ case STT_SECTION: fprintf(f, "section\n");break;
+ case STT_FILE: fprintf(f, "file\n"); break;
+ default: fprintf(f, "undef\n"); break;
+ }
+ fprintf(f, "%*ssize=", indent_level, "");
+ if (entry->xsize)
+ yasm_expr_print(entry->xsize, f);
+ else
+ fprintf(f, "%ld", entry->size);
+ fprintf(f, "\n");
+}
+
+static void
+elf_ssym_symtab_entry_print(void *data, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+elf_symtab_head *
+elf_symtab_create()
+{
+ elf_symtab_head *symtab = yasm_xmalloc(sizeof(elf_symtab_head));
+ elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry));
+
+ STAILQ_INIT(symtab);
+ entry->in_table = 1;
+ entry->sym = NULL;
+ entry->sect = NULL;
+ entry->name = NULL;
+ entry->value = 0;
+ entry->xsize = NULL;
+ entry->size = 0;
+ entry->index = SHN_UNDEF;
+ entry->bind = STB_LOCAL;
+ entry->type = STT_NOTYPE;
+ entry->vis = STV_DEFAULT;
+ entry->symindex = 0;
+ STAILQ_INSERT_TAIL(symtab, entry, qlink);
+ return symtab;
+}
+
+void
+elf_symtab_append_entry(elf_symtab_head *symtab, elf_symtab_entry *entry)
+{
+ if (symtab == NULL)
+ yasm_internal_error("symtab is null");
+ if (entry == NULL)
+ yasm_internal_error("symtab entry is null");
+ if (STAILQ_EMPTY(symtab))
+ yasm_internal_error(N_("symtab is missing initial dummy entry"));
+
+ STAILQ_INSERT_TAIL(symtab, entry, qlink);
+ entry->in_table = 1;
+}
+
+void
+elf_symtab_insert_local_sym(elf_symtab_head *symtab, elf_symtab_entry *entry)
+{
+ elf_symtab_entry *after = STAILQ_FIRST(symtab);
+ elf_symtab_entry *before = NULL;
+
+ while (after && (after->bind == STB_LOCAL)) {
+ before = after;
+ if (before->type == STT_FILE) break;
+ after = STAILQ_NEXT(after, qlink);
+ }
+ STAILQ_INSERT_AFTER(symtab, before, entry, qlink);
+ entry->in_table = 1;
+}
+
+void
+elf_symtab_destroy(elf_symtab_head *symtab)
+{
+ elf_symtab_entry *s1, *s2;
+
+ if (symtab == NULL)
+ yasm_internal_error("symtab is null");
+ if (STAILQ_EMPTY(symtab))
+ yasm_internal_error(N_("symtab is missing initial dummy entry"));
+
+ s1 = STAILQ_FIRST(symtab);
+ while (s1 != NULL) {
+ s2 = STAILQ_NEXT(s1, qlink);
+ elf_symtab_entry_destroy(s1);
+ s1 = s2;
+ }
+ yasm_xfree(symtab);
+}
+
+unsigned long
+elf_symtab_assign_indices(elf_symtab_head *symtab)
+{
+ elf_symtab_entry *entry, *prev=NULL;
+ unsigned long last_local=0;
+
+ if (symtab == NULL)
+ yasm_internal_error("symtab is null");
+ if (STAILQ_EMPTY(symtab))
+ yasm_internal_error(N_("symtab is missing initial dummy entry"));
+
+ STAILQ_FOREACH(entry, symtab, qlink) {
+ if (prev)
+ entry->symindex = prev->symindex + 1;
+ if (entry->bind == STB_LOCAL)
+ last_local = entry->symindex;
+ prev = entry;
+ }
+ return last_local + 1;
+}
+
+unsigned long
+elf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab,
+ yasm_errwarns *errwarns)
+{
+ unsigned char buf[SYMTAB_MAXSIZE], *bufp;
+ elf_symtab_entry *entry;
+ unsigned long size = 0;
+
+ if (!symtab)
+ yasm_internal_error(N_("symtab is null"));
+
+ STAILQ_FOREACH(entry, symtab, qlink) {
+
+ yasm_intnum *size_intn=NULL, *value_intn=NULL;
+ bufp = buf;
+
+ /* get size (if specified); expr overrides stored integer */
+ if (entry->xsize) {
+ size_intn = yasm_intnum_copy(
+ yasm_expr_get_intnum(&entry->xsize, 1));
+ if (!size_intn) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("size specifier not an integer expression"));
+ yasm_errwarn_propagate(errwarns, entry->xsize->line);
+ }
+ }
+ else
+ size_intn = yasm_intnum_create_uint(entry->size);
+
+ /* get EQU value for constants */
+ if (entry->sym) {
+ const yasm_expr *equ_expr_c;
+ equ_expr_c = yasm_symrec_get_equ(entry->sym);
+
+ if (equ_expr_c != NULL) {
+ const yasm_intnum *equ_intn;
+ yasm_expr *equ_expr = yasm_expr_copy(equ_expr_c);
+ equ_intn = yasm_expr_get_intnum(&equ_expr, 1);
+
+ if (equ_intn == NULL) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("EQU value not an integer expression"));
+ yasm_errwarn_propagate(errwarns, equ_expr->line);
+ } else
+ value_intn = yasm_intnum_copy(equ_intn);
+ entry->index = SHN_ABS;
+ yasm_expr_destroy(equ_expr);
+ }
+ }
+ if (value_intn == NULL)
+ value_intn = yasm_intnum_create_uint(entry->value);
+
+ /* If symbol is in a TLS section, force its type to TLS. */
+ if (entry->sym) {
+ yasm_bytecode *precbc;
+ yasm_section *sect;
+ elf_secthead *shead;
+ if (yasm_symrec_get_label(entry->sym, &precbc) &&
+ (sect = yasm_bc_get_section(precbc)) &&
+ (shead = yasm_section_get_data(sect, &elf_section_data)) &&
+ shead->flags & SHF_TLS) {
+ entry->type = STT_TLS;
+ }
+ }
+
+ if (!elf_march->write_symtab_entry || !elf_march->symtab_entry_size)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ elf_march->write_symtab_entry(bufp, entry, value_intn, size_intn);
+ fwrite(buf, elf_march->symtab_entry_size, 1, f);
+ size += elf_march->symtab_entry_size;
+
+ yasm_intnum_destroy(size_intn);
+ yasm_intnum_destroy(value_intn);
+ }
+ return size;
+}
+
+void elf_symtab_set_nonzero(elf_symtab_entry *entry,
+ yasm_section *sect,
+ elf_section_index sectidx,
+ elf_symbol_binding bind,
+ elf_symbol_type type,
+ yasm_expr *xsize,
+ elf_address *value)
+{
+ if (!entry)
+ yasm_internal_error("NULL entry");
+ if (sect) entry->sect = sect;
+ if (sectidx) entry->index = sectidx;
+ if (bind) entry->bind = bind;
+ if (type) entry->type = type;
+ if (xsize) entry->xsize = xsize;
+ if (value) entry->value = *value;
+}
+
+void
+elf_sym_set_visibility(elf_symtab_entry *entry,
+ elf_symbol_vis vis)
+{
+ entry->vis = ELF_ST_VISIBILITY(vis);
+}
+
+void
+elf_sym_set_type(elf_symtab_entry *entry,
+ elf_symbol_type type)
+{
+ entry->type = type;
+}
+
+void
+elf_sym_set_size(elf_symtab_entry *entry,
+ struct yasm_expr *size)
+{
+ if (entry->xsize)
+ yasm_expr_destroy(entry->xsize);
+ entry->xsize = size;
+}
+
+int
+elf_sym_in_table(elf_symtab_entry *entry)
+{
+ return entry->in_table;
+}
+
+elf_secthead *
+elf_secthead_create(elf_strtab_entry *name,
+ elf_section_type type,
+ elf_section_flags flags,
+ elf_address offset,
+ elf_size size)
+{
+ elf_secthead *esd = yasm_xmalloc(sizeof(elf_secthead));
+
+ esd->type = type;
+ esd->flags = flags;
+ esd->offset = offset;
+ esd->size = yasm_intnum_create_uint(size);
+ esd->link = 0;
+ esd->info = 0;
+ esd->align = 0;
+ esd->entsize = 0;
+ esd->index = 0;
+
+ esd->sym = NULL;
+ esd->name = name;
+ esd->index = 0;
+ esd->rel_name = NULL;
+ esd->rel_index = 0;
+ esd->rel_offset = 0;
+ esd->nreloc = 0;
+
+ if (name && (strcmp(name->str, ".symtab") == 0)) {
+ if (!elf_march->symtab_entry_size || !elf_march->symtab_entry_align)
+ yasm_internal_error(N_("unsupported ELF format"));
+ esd->entsize = elf_march->symtab_entry_size;
+ esd->align = elf_march->symtab_entry_align;
+ }
+
+ return esd;
+}
+
+void
+elf_secthead_destroy(elf_secthead *shead)
+{
+ if (shead == NULL)
+ yasm_internal_error(N_("shead is null"));
+
+ yasm_intnum_destroy(shead->size);
+
+ yasm_xfree(shead);
+}
+
+static void
+elf_section_data_destroy(void *data)
+{
+ elf_secthead_destroy((elf_secthead *)data);
+}
+
+static void
+elf_secthead_print(void *data, FILE *f, int indent_level)
+{
+ elf_secthead *sect = data;
+ fprintf(f, "%*sname=%s\n", indent_level, "",
+ sect->name ? sect->name->str : "<undef>");
+ fprintf(f, "%*ssym=\n", indent_level, "");
+ yasm_symrec_print(sect->sym, f, indent_level+1);
+ fprintf(f, "%*sindex=0x%x\n", indent_level, "", sect->index);
+ fprintf(f, "%*sflags=", indent_level, "");
+ if (sect->flags & SHF_WRITE)
+ fprintf(f, "WRITE ");
+ if (sect->flags & SHF_ALLOC)
+ fprintf(f, "ALLOC ");
+ if (sect->flags & SHF_EXECINSTR)
+ fprintf(f, "EXEC ");
+ /*if (sect->flags & SHF_MASKPROC)
+ fprintf(f, "PROC-SPECIFIC"); */
+ fprintf(f, "%*soffset=0x%lx\n", indent_level, "", sect->offset);
+ fprintf(f, "%*ssize=0x%lx\n", indent_level, "",
+ yasm_intnum_get_uint(sect->size));
+ fprintf(f, "%*slink=0x%x\n", indent_level, "", sect->link);
+ fprintf(f, "%*salign=%lu\n", indent_level, "", sect->align);
+ fprintf(f, "%*snreloc=%ld\n", indent_level, "", sect->nreloc);
+}
+
+unsigned long
+elf_secthead_write_to_file(FILE *f, elf_secthead *shead,
+ elf_section_index sindex)
+{
+ unsigned char buf[SHDR_MAXSIZE], *bufp = buf;
+ shead->index = sindex;
+
+ if (shead == NULL)
+ yasm_internal_error("shead is null");
+
+ if (!elf_march->write_secthead || !elf_march->secthead_size)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ elf_march->write_secthead(bufp, shead);
+ if (fwrite(buf, elf_march->secthead_size, 1, f))
+ return elf_march->secthead_size;
+ yasm_internal_error(N_("Failed to write an elf section header"));
+ return 0;
+}
+
+void
+elf_secthead_append_reloc(yasm_section *sect, elf_secthead *shead,
+ elf_reloc_entry *reloc)
+{
+ if (sect == NULL)
+ yasm_internal_error("sect is null");
+ if (shead == NULL)
+ yasm_internal_error("shead is null");
+ if (reloc == NULL)
+ yasm_internal_error("reloc is null");
+
+ shead->nreloc++;
+ yasm_section_add_reloc(sect, (yasm_reloc *)reloc, elf_reloc_entry_destroy);
+}
+
+char *
+elf_secthead_name_reloc_section(const char *basesect)
+{
+ if (!elf_march->reloc_section_prefix)
+ {
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ return NULL;
+ }
+ else
+ {
+ size_t prepend_length = strlen(elf_march->reloc_section_prefix);
+ char *sectname = yasm_xmalloc(prepend_length + strlen(basesect) + 1);
+ strcpy(sectname, elf_march->reloc_section_prefix);
+ strcat(sectname, basesect);
+ return sectname;
+ }
+}
+
+void
+elf_handle_reloc_addend(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset)
+{
+ if (!elf_march->handle_reloc_addend)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ elf_march->handle_reloc_addend(intn, reloc, offset);
+}
+
+unsigned long
+elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab_idx,
+ yasm_section *sect, elf_secthead *shead,
+ elf_section_index sindex)
+{
+ unsigned char buf[SHDR_MAXSIZE], *bufp = buf;
+
+ if (shead == NULL)
+ yasm_internal_error("shead is null");
+
+ if (!yasm_section_relocs_first(sect))
+ return 0; /* no relocations, no .rel.* section header */
+
+ shead->rel_index = sindex;
+
+ if (!elf_march->write_secthead_rel || !elf_march->secthead_size)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ elf_march->write_secthead_rel(bufp, shead, symtab_idx, sindex);
+ if (fwrite(buf, elf_march->secthead_size, 1, f))
+ return elf_march->secthead_size;
+ yasm_internal_error(N_("Failed to write an elf section header"));
+ return 0;
+}
+
+unsigned long
+elf_secthead_write_relocs_to_file(FILE *f, yasm_section *sect,
+ elf_secthead *shead, yasm_errwarns *errwarns)
+{
+ elf_reloc_entry *reloc;
+ unsigned char buf[RELOC_MAXSIZE], *bufp;
+ unsigned long size = 0;
+ long pos;
+
+ if (shead == NULL)
+ yasm_internal_error("shead is null");
+
+ reloc = (elf_reloc_entry *)yasm_section_relocs_first(sect);
+ if (!reloc)
+ return 0;
+
+ /* first align section to multiple of 4 */
+ pos = ftell(f);
+ if (pos == -1) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("couldn't read position on output stream"));
+ yasm_errwarn_propagate(errwarns, 0);
+ }
+ pos = (pos + 3) & ~3;
+ if (fseek(f, pos, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO, N_("couldn't seek on output stream"));
+ yasm_errwarn_propagate(errwarns, 0);
+ }
+ shead->rel_offset = (unsigned long)pos;
+
+
+ while (reloc) {
+ unsigned int r_type=0, r_sym;
+ elf_symtab_entry *esym;
+
+ esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
+ if (esym)
+ r_sym = esym->symindex;
+ else
+ r_sym = STN_UNDEF;
+
+ if (!elf_march->map_reloc_info_to_type)
+ yasm_internal_error(N_("Unsupported arch/machine for elf output"));
+ r_type = elf_march->map_reloc_info_to_type(reloc);
+
+ bufp = buf;
+ if (!elf_march->write_reloc || !elf_march->reloc_entry_size)
+ yasm_internal_error(N_("Unsupported arch/machine for elf output"));
+ elf_march->write_reloc(bufp, reloc, r_type, r_sym);
+ fwrite(buf, elf_march->reloc_entry_size, 1, f);
+ size += elf_march->reloc_entry_size;
+
+ reloc = (elf_reloc_entry *)
+ yasm_section_reloc_next((yasm_reloc *)reloc);
+ }
+ return size;
+}
+
+elf_section_type
+elf_secthead_get_type(elf_secthead *shead)
+{
+ return shead->type;
+}
+
+void
+elf_secthead_set_typeflags(elf_secthead *shead, elf_section_type type,
+ elf_section_flags flags)
+{
+ shead->type = type;
+ shead->flags = flags;
+}
+
+int
+elf_secthead_is_empty(elf_secthead *shead)
+{
+ return yasm_intnum_is_zero(shead->size);
+}
+
+yasm_symrec *
+elf_secthead_get_sym(elf_secthead *shead)
+{
+ return shead->sym;
+}
+
+elf_section_index
+elf_secthead_get_index(elf_secthead *shead)
+{
+ return shead->index;
+}
+
+unsigned long
+elf_secthead_get_align(const elf_secthead *shead)
+{
+ return shead->align;
+}
+
+unsigned long
+elf_secthead_set_align(elf_secthead *shead, unsigned long align)
+{
+ return shead->align = align;
+}
+
+elf_section_info
+elf_secthead_set_info(elf_secthead *shead, elf_section_info info)
+{
+ return shead->info = info;
+}
+
+elf_section_index
+elf_secthead_set_index(elf_secthead *shead, elf_section_index sectidx)
+{
+ return shead->index = sectidx;
+}
+
+elf_section_index
+elf_secthead_set_link(elf_secthead *shead, elf_section_index link)
+{
+ return shead->link = link;
+}
+
+elf_section_index
+elf_secthead_set_rel_index(elf_secthead *shead, elf_section_index sectidx)
+{
+ return shead->rel_index = sectidx;
+}
+
+elf_strtab_entry *
+elf_secthead_set_rel_name(elf_secthead *shead, elf_strtab_entry *entry)
+{
+ return shead->rel_name = entry;
+}
+
+elf_size
+elf_secthead_set_entsize(elf_secthead *shead, elf_size size)
+{
+ return shead->entsize = size;
+}
+
+yasm_symrec *
+elf_secthead_set_sym(elf_secthead *shead, yasm_symrec *sym)
+{
+ return shead->sym = sym;
+}
+
+void
+elf_secthead_add_size(elf_secthead *shead, yasm_intnum *size)
+{
+ if (size) {
+ yasm_intnum_calc(shead->size, YASM_EXPR_ADD, size);
+ }
+}
+
+long
+elf_secthead_set_file_offset(elf_secthead *shead, long pos)
+{
+ unsigned long align = shead->align;
+
+ if (align == 0 || align == 1) {
+ shead->offset = (unsigned long)pos;
+ return pos;
+ }
+ else if (align & (align - 1))
+ yasm_internal_error(
+ N_("alignment %d for section `%s' is not a power of 2"));
+ /*, align, sect->name->str);*/
+
+ shead->offset = (unsigned long)((pos + align - 1) & ~(align - 1));
+ return (long)shead->offset;
+}
+
+unsigned long
+elf_proghead_get_size(void)
+{
+ if (!elf_march->proghead_size)
+ yasm_internal_error(N_("Unsupported ELF format for output"));
+ return elf_march->proghead_size;
+}
+
+unsigned long
+elf_proghead_write_to_file(FILE *f,
+ elf_offset secthead_addr,
+ unsigned long secthead_count,
+ elf_section_index shstrtab_index)
+{
+ unsigned char buf[EHDR_MAXSIZE], *bufp = buf;
+
+ YASM_WRITE_8(bufp, ELFMAG0); /* ELF magic number */
+ YASM_WRITE_8(bufp, ELFMAG1);
+ YASM_WRITE_8(bufp, ELFMAG2);
+ YASM_WRITE_8(bufp, ELFMAG3);
+
+ if (!elf_march->write_proghead || !elf_march->proghead_size)
+ yasm_internal_error(N_("Unsupported ELF format for output"));
+ elf_march->write_proghead(&bufp, secthead_addr, secthead_count, shstrtab_index);
+
+ if (((unsigned)(bufp - buf)) != elf_march->proghead_size)
+ yasm_internal_error(N_("ELF program header is not proper length"));
+
+ if (fwrite(buf, elf_march->proghead_size, 1, f))
+ return elf_march->proghead_size;
+
+ yasm_internal_error(N_("Failed to write ELF program header"));
+ return 0;
+}
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf.h b/contrib/tools/yasm/modules/objfmts/elf/elf.h
index fce629ae45..73498477e8 100644
--- a/contrib/tools/yasm/modules/objfmts/elf/elf.h
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf.h
@@ -1,532 +1,532 @@
-/*
- * ELF object format helpers
- *
- * Copyright (C) 2003-2007 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_H_INCLUDED
-#define ELF_H_INCLUDED
-
-typedef struct elf_reloc_entry elf_reloc_entry;
-typedef struct elf_reloc_head elf_reloc_head;
-typedef struct elf_secthead elf_secthead;
-typedef struct elf_strtab_entry elf_strtab_entry;
-typedef struct elf_strtab_head elf_strtab_head;
-typedef struct elf_symtab_entry elf_symtab_entry;
-typedef struct elf_symtab_head elf_symtab_head;
-
-typedef struct elf_machine_handler elf_machine_handler;
-
-typedef unsigned long elf_address;
-typedef unsigned long elf_offset;
-typedef unsigned long elf_size;
-typedef unsigned long elf_section_info;
-
-typedef enum {
- ET_NONE = 0,
- ET_REL = 1, /* Relocatable */
- ET_EXEC = 2, /* Executable */
- ET_DYN = 3, /* Shared object */
- ET_CORE = 4, /* Core */
- ET_LOOS = 0xfe00, /* Environment specific */
- ET_HIOS = 0xfeff,
- ET_LOPROC = 0xff00, /* Processor specific */
- ET_HIPROC = 0xffff
-} elf_file_type;
-
-typedef enum {
- EM_NONE = 0,
- EM_M32 = 1, /* AT&T WE 32100 */
- EM_SPARC = 2, /* SPARC */
- EM_386 = 3, /* Intel 80386 */
- EM_68K = 4, /* Motorola 68000 */
- EM_88K = 5, /* Motorola 88000 */
- EM_860 = 7, /* Intel 80860 */
- EM_MIPS = 8, /* MIPS RS3000 */
-
- EM_S370 = 9, /* IBM System/370 */
- EM_MIPS_RS4_BE = 10, /* MIPS R4000 Big-Endian (dep)*/
- EM_PARISC = 15, /* HPPA */
- EM_SPARC32PLUS = 18, /* SPARC v8plus */
- EM_PPC = 20, /* PowerPC 32-bit */
- EM_PPC64 = 21, /* PowerPC 64-bit */
- EM_ARM = 40, /* ARM */
- EM_SPARCV9 = 43, /* SPARC v9 64-bit */
- EM_IA_64 = 50, /* Intel IA-64 */
- EM_X86_64 = 62, /* AMD x86-64 */
- EM_ALPHA = 0x9026 /* Alpha (no ABI) */
-} elf_machine;
-
-typedef enum {
- ELFMAG0 = 0x7f,
- ELFMAG1 = 0x45,
- ELFMAG2 = 0x4c,
- ELFMAG3 = 0x46
-} elf_magic;
-
-typedef enum {
- EV_NONE = 0, /* invalid */
- EV_CURRENT = 1 /* current */
-} elf_version;
-
-typedef enum {
- EI_MAG0 = 0, /* File id */
- EI_MAG1 = 1,
- EI_MAG2 = 2,
- EI_MAG3 = 3,
- EI_CLASS = 4, /* File class */
- EI_DATA = 5, /* Data encoding */
- EI_VERSION = 6, /* File version */
- EI_OSABI = 7, /* OS and ABI */
- EI_ABIVERSION = 8, /* version of ABI */
-
- EI_PAD = 9, /* Pad to end; start here */
- EI_NIDENT = 16 /* Sizeof e_ident[] */
-} elf_identification_index;
-
-typedef enum {
- ELFOSABI_SYSV = 0, /* System V ABI */
- ELFOSABI_HPUX = 1, /* HP-UX os */
- ELFOSABI_STANDALONE = 255 /* Standalone / embedded app */
-} elf_osabi_index;
-
-typedef enum {
- ELFCLASSNONE = 0, /* invalid */
- ELFCLASS32 = 1, /* 32-bit */
- ELFCLASS64 = 2 /* 64-bit */
-} elf_class;
-
-typedef enum {
- ELFDATANONE = 0,
- ELFDATA2LSB = 1,
- ELFDATA2MSB = 2
-} elf_data_encoding;
-
-/* elf section types - index of semantics */
-typedef enum {
- SHT_NULL = 0, /* inactive section - no associated data */
- SHT_PROGBITS = 1, /* defined by program for its own meaning */
- SHT_SYMTAB = 2, /* symbol table (primarily) for linking */
- SHT_STRTAB = 3, /* string table - symbols need names */
- SHT_RELA = 4, /* relocation entries w/ explicit addends */
- SHT_HASH = 5, /* symbol hash table - for dynamic linking */
- SHT_DYNAMIC = 6, /* information for dynamic linking */
- SHT_NOTE = 7, /* extra data marking the file somehow */
- SHT_NOBITS = 8, /* no stored data, but occupies runtime space */
- SHT_REL = 9, /* relocations entries w/o explicit addends */
- SHT_SHLIB = 10, /* reserved; unspecified semantics */
- SHT_DYNSYM = 11, /* like symtab, but more for dynamic linking */
-
- SHT_LOOS = 0x60000000, /* reserved for environment specific use */
- SHT_HIOS = 0x6fffffff,
- SHT_LOPROC = 0x70000000, /* reserved for processor specific semantics */
- SHT_HIPROC = 0x7fffffff/*,
- SHT_LOUSER = 0x80000000,*/ /* reserved for applications; safe */
- /*SHT_HIUSER = 0xffffffff*/
-} elf_section_type;
-
-/* elf section flags - bitfield of attributes */
-typedef enum {
- SHF_WRITE = 0x1, /* data should be writable at runtime */
- SHF_ALLOC = 0x2, /* occupies memory at runtime */
- SHF_EXECINSTR = 0x4, /* contains machine instructions */
- SHF_MERGE = 0x10, /* data can be merged */
- SHF_STRINGS = 0x20, /* contains 0-terminated strings */
- SHF_GROUP = 0x200, /* member of a section group */
- SHF_TLS = 0x400, /* thread local storage */
- SHF_MASKOS = 0x0f000000/*,*//* environment specific use */
- /*SHF_MASKPROC = 0xf0000000*/ /* bits reserved for processor specific needs */
-} elf_section_flags;
-
-/* elf section index - just the special ones */
-typedef enum {
- SHN_UNDEF = 0, /* undefined symbol; requires other global */
- SHN_LORESERVE = 0xff00, /* reserved for various semantics */
- SHN_LOPROC = 0xff00, /* reserved for processor specific semantics */
- SHN_HIPROC = 0xff1f,
- SHN_LOOS = 0xff20, /* reserved for environment specific use */
- SHN_HIOS = 0xff3f,
- SHN_ABS = 0xfff1, /* associated symbols don't change on reloc */
- SHN_COMMON = 0xfff2, /* associated symbols refer to unallocated */
- SHN_HIRESERVE = 0xffff
-} elf_section_index;
-
-/* elf symbol binding - index of visibility/behavior */
-typedef enum {
- STB_LOCAL = 0, /* invisible outside defining file */
- STB_GLOBAL = 1, /* visible to all combined object files */
- STB_WEAK = 2, /* global but lower precedence */
-
- STB_LOOS = 10, /* Environment specific use */
- STB_HIOS = 12,
- STB_LOPROC = 13, /* reserved for processor specific semantics */
- STB_HIPROC = 15
-} elf_symbol_binding;
-
-/* elf symbol type - index of classifications */
-typedef enum {
- STT_NOTYPE = 0, /* type not specified */
- STT_OBJECT = 1, /* data object such as a variable, array, etc */
- STT_FUNC = 2, /* a function or executable code */
- STT_SECTION = 3, /* a section: often for relocation, STB_LOCAL */
- STT_FILE = 4, /* often source filename: STB_LOCAL, SHN_ABS */
- STT_COMMON = 5, /* Uninitialized common block. */
- STT_TLS = 6, /* TLS object. */
- STT_NUM = 7,
-
- STT_LOOS = 10, /* Environment specific use */
- STT_HIOS = 12,
- STT_LOPROC = 13, /* reserved for processor specific semantics */
- STT_HIPROC = 15
-} elf_symbol_type;
-
-typedef enum {
- STN_UNDEF = 0
-} elf_symbol_index;
-
-/* elf symbol visibility - lower two bits of OTHER field */
-typedef enum {
- STV_DEFAULT = 0, /* Default symbol visibility rules */
- STV_INTERNAL = 1, /* Processor specific hidden class */
- STV_HIDDEN = 2, /* Sym unavailable in other modules */
- STV_PROTECTED = 3 /* Not preemptable, not exported */
-} elf_symbol_vis;
-
-
-/* internal only object definitions */
-#ifdef YASM_OBJFMT_ELF_INTERNAL
-
-#define ELF_VISIBILITY_MASK 0x03
-#define ELF_ST_VISIBILITY(v) ((v) & ELF_VISIBILITY_MASK)
-
-#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
-#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))
-#define ELF32_ST_OTHER(vis) ELF_ST_VISIBILITY(vis)
-
-#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
-#define ELF64_R_INFO(s,t) (((s)<<32) + ((t) & 0xffffffffL))
-#define ELF64_ST_OTHER(vis) ELF_ST_VISIBILITY(vis)
-
-#define EHDR32_SIZE 52
-#define EHDR64_SIZE 64
-#define EHDR_MAXSIZE 64
-
-#define SHDR32_SIZE 40
-#define SHDR64_SIZE 64
-#define SHDR_MAXSIZE 64
-
-#define SYMTAB32_SIZE 16
-#define SYMTAB64_SIZE 24
-#define SYMTAB_MAXSIZE 24
-
-#define SYMTAB32_ALIGN 4
-#define SYMTAB64_ALIGN 8
-
-#define RELOC32_SIZE 8
-#define RELOC32A_SIZE 12
-#define RELOC64_SIZE 16
-#define RELOC64A_SIZE 24
-#define RELOC_MAXSIZE 24
-
-#define RELOC32_ALIGN 4
-#define RELOC64_ALIGN 8
-
-
-/* elf relocation type - index of semantics
- *
- * A = Addend (r_addend for RELA, value at location for REL)
- * B = Base address
- * G = Offset into global offset table (GOT)
- * GOT = Address of the global offset table (GOT)
- * L = Location of procedure linkage table (PLT)
- * P = Location of location being relocated (r_offset)
- * S = Value of symbol
- */
-typedef enum {
- R_386_NONE = 0, /* none */
- R_386_32 = 1, /* word32, S + A */
- R_386_PC32 = 2, /* word32, S + A - P */
- R_386_GOT32 = 3, /* word32, G + A - P */
- R_386_PLT32 = 4, /* word32, L + A - P */
- R_386_COPY = 5, /* none */
- R_386_GLOB_DAT = 6, /* word32, S */
- R_386_JMP_SLOT = 7, /* word32, S */
- R_386_RELATIVE = 8, /* word32, B + A */
- R_386_GOTOFF = 9, /* word32, S + A - GOT */
- R_386_GOTPC = 10, /* word32, GOT + A - P */
- R_386_TLS_TPOFF = 14, /* Negative offset in static TLS block (GNU
- version) */
- R_386_TLS_IE = 15, /* Absolute address of GOT entry for negative
- static TLS block offset */
- R_386_TLS_GOTIE = 16, /* GOT entry for negative static TLS block
- offset */
- R_386_TLS_LE = 17, /* Negative offset relative to static TLS
- (GNU version) */
- R_386_TLS_GD = 18, /* Direct 32 bit for GNU version of GD TLS */
- R_386_TLS_LDM = 19, /* Direct 32 bit for GNU version of LD TLS
- in LE code */
- R_386_16 = 20, /* word16, S + A (GNU extension) */
- R_386_PC16 = 21, /* word16, S + A - P (GNU extension) */
- R_386_8 = 22, /* word8, S + A (GNU extension) */
- R_386_PC8 = 23, /* word8, S + A - P (GNU extension) */
- R_386_TLS_GD_32 = 24, /* Direct 32 bit for GD TLS */
- R_386_TLS_GD_PUSH = 25, /* Tag for pushl in GD TLS code */
- R_386_TLS_GD_CALL = 26, /* Relocation for call to */
- R_386_TLS_GD_POP = 27, /* Tag for popl in GD TLS code */
- R_386_TLS_LDM_32 = 28, /* Direct 32 bit for local dynamic code */
- R_386_TLS_LDM_PUSH = 29, /* Tag for pushl in LDM TLS code */
- R_386_TLS_LDM_CALL = 30, /* Relocation for call to */
- R_386_TLS_LDM_POP = 31, /* Tag for popl in LDM TLS code */
- R_386_TLS_LDO_32 = 32, /* Offset relative to TLS block */
- R_386_TLS_IE_32 = 33, /* GOT entry for static TLS block */
- R_386_TLS_LE_32 = 34, /* Offset relative to static TLS block */
- R_386_TLS_DTPMOD32 = 35, /* ID of module containing symbol */
- R_386_TLS_DTPOFF32 = 36, /* Offset in TLS block */
- R_386_TLS_TPOFF32 = 37, /* Offset in static TLS block */
- R_386_TLS_GOTDESC = 39,
- R_386_TLS_DESC_CALL = 40,
- R_386_TLS_DESC = 41
-} elf_386_relocation_type;
-
-typedef enum {
- R_X86_64_NONE = 0, /* none */
- R_X86_64_64 = 1, /* word64, S + A */
- R_X86_64_PC32 = 2, /* word32, S + A - P */
- R_X86_64_GOT32 = 3, /* word32, G + A */
- R_X86_64_PLT32 = 4, /* word32, L + A - P */
- R_X86_64_COPY = 5, /* none */
- R_X86_64_GLOB_DAT = 6, /* word64, S, set GOT entry to data address */
- R_X86_64_JMP_SLOT = 7, /* word64, S, set GOT entry to code address */
- R_X86_64_RELATIVE = 8, /* word64, B + A */
- R_X86_64_GOTPCREL = 9, /* word32, G + GOT + A - P */
- R_X86_64_32 = 10, /* word32 (zero extend), S + A */
- R_X86_64_32S = 11, /* word32 (sign extend), S + A */
- R_X86_64_16 = 12, /* word16, S + A */
- R_X86_64_PC16 = 13, /* word16, S + A - P */
- R_X86_64_8 = 14, /* word8, S + A */
- R_X86_64_PC8 = 15, /* word8, S + A - P */
- R_X86_64_DPTMOD64 = 16, /* word64, ID of module containing symbol */
- R_X86_64_DTPOFF64 = 17, /* word64, offset in TLS block */
- R_X86_64_TPOFF64 = 18, /* word64, offset in initial TLS block */
- R_X86_64_TLSGD = 19, /* word32, PC-rel offset to GD GOT block */
- R_X86_64_TLSLD = 20, /* word32, PC-rel offset to LD GOT block */
- R_X86_64_DTPOFF32 = 21, /* word32, offset to TLS block */
- R_X86_64_GOTTPOFF = 22, /* word32, PC-rel offset to IE GOT entry */
- R_X86_64_TPOFF32 = 23, /* word32, offset in initial TLS block */
- R_X86_64_PC64 = 24, /* word64, PC relative */
- R_X86_64_GOTOFF64 = 25, /* word64, offset to GOT */
- R_X86_64_GOTPC32 = 26, /* word32, signed pc relative to GOT */
- R_X86_64_GOT64 = 27, /* word64, GOT entry offset */
- R_X86_64_GOTPCREL64 = 28, /* word64, signed pc relative to GOT entry */
- R_X86_64_GOTPC64 = 29, /* word64, signed pc relative to GOT */
- R_X86_64_GOTPLT64 = 30, /* like GOT64, but indicates PLT entry needed */
- R_X86_64_PLTOFF64 = 31, /* word64, GOT relative offset to PLT entry */
- R_X86_64_GOTPC32_TLSDESC = 34, /* GOT offset for TLS descriptor */
- R_X86_64_TLSDESC_CALL = 35, /* Marker for call through TLS descriptor */
- R_X86_64_TLSDESC = 36 /* TLS descriptor */
-} elf_x86_64_relocation_type;
-
-struct elf_secthead {
- elf_section_type type;
- elf_section_flags flags;
- elf_address offset;
- yasm_intnum *size;
- elf_section_index link;
- elf_section_info info; /* see note ESD1 */
- unsigned long align;
- elf_size entsize;
-
- yasm_symrec *sym;
- elf_strtab_entry *name;
- elf_section_index index;
-
- elf_strtab_entry *rel_name;
- elf_section_index rel_index;
- elf_address rel_offset;
- unsigned long nreloc;
-};
-
-/* Note ESD1:
- * for section types SHT_REL, SHT_RELA:
- * link -> index of associated symbol table
- * info -> index of relocated section
- * for section types SHT_SYMTAB, SHT_DYNSYM:
- * link -> index of associated string table
- * info -> 1+index of last "local symbol" (bind == STB_LOCAL)
- * (for section type SHT_DNAMIC:
- * link -> index of string table
- * info -> 0 )
- * (for section type SHT_HASH:
- * link -> index of symbol table to which hash applies
- * info -> 0 )
- * for all others:
- * link -> SHN_UNDEF
- * info -> 0
- */
-
-struct elf_reloc_entry {
- yasm_reloc reloc;
- int rtype_rel;
- size_t valsize;
- yasm_intnum *addend;
- /*@null@*/ yasm_symrec *wrt;
- int is_GOT_sym;
-};
-
-STAILQ_HEAD(elf_strtab_head, elf_strtab_entry);
-struct elf_strtab_entry {
- STAILQ_ENTRY(elf_strtab_entry) qlink;
- unsigned long index;
- char *str;
-};
-
-STAILQ_HEAD(elf_symtab_head, elf_symtab_entry);
-struct elf_symtab_entry {
- STAILQ_ENTRY(elf_symtab_entry) qlink;
- int in_table;
- yasm_symrec *sym;
- yasm_section *sect;
- elf_strtab_entry *name;
- elf_address value;
- /*@dependent@*/ yasm_expr *xsize;
- elf_size size;
- elf_section_index index;
- elf_symbol_binding bind;
- elf_symbol_type type;
- elf_symbol_vis vis;
- elf_symbol_index symindex;
-};
-
-#endif /* defined(YASM_OBJFMT_ELF_INTERNAL) */
-
-extern const yasm_assoc_data_callback elf_section_data;
-extern const yasm_assoc_data_callback elf_symrec_data;
-extern const yasm_assoc_data_callback elf_ssym_symrec_data;
-
-
-const elf_machine_handler *elf_set_arch(struct yasm_arch *arch,
- yasm_symtab *symtab,
- int bits_pref);
-
-yasm_symrec *elf_get_special_sym(const char *name, const char *parser);
-
-/* reloc functions */
-int elf_is_wrt_sym_relative(yasm_symrec *wrt);
-int elf_is_wrt_pos_adjusted(yasm_symrec *wrt);
-elf_reloc_entry *elf_reloc_entry_create(yasm_symrec *sym,
- /*@null@*/ yasm_symrec *wrt,
- yasm_intnum *addr,
- int rel,
- size_t valsize,
- int is_GOT_sym);
-void elf_reloc_entry_destroy(void *entry);
-
-/* strtab functions */
-elf_strtab_entry *elf_strtab_entry_create(const char *str);
-void elf_strtab_entry_set_str(elf_strtab_entry *entry, const char *str);
-elf_strtab_head *elf_strtab_create(void);
-elf_strtab_entry *elf_strtab_append_str(elf_strtab_head *head, const char *str);
-void elf_strtab_destroy(elf_strtab_head *head);
-unsigned long elf_strtab_output_to_file(FILE *f, elf_strtab_head *head);
-
-/* symtab functions */
-elf_symtab_entry *elf_symtab_entry_create(elf_strtab_entry *name,
- struct yasm_symrec *sym);
-elf_symtab_head *elf_symtab_create(void);
-void elf_symtab_append_entry(elf_symtab_head *symtab, elf_symtab_entry *entry);
-void elf_symtab_insert_local_sym(elf_symtab_head *symtab,
- elf_symtab_entry *entry);
-void elf_symtab_destroy(elf_symtab_head *head);
-unsigned long elf_symtab_assign_indices(elf_symtab_head *symtab);
-unsigned long elf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab,
- yasm_errwarns *errwarns);
-void elf_symtab_set_nonzero(elf_symtab_entry *entry,
- struct yasm_section *sect,
- elf_section_index sectidx,
- elf_symbol_binding bind,
- elf_symbol_type type,
- struct yasm_expr *size,
- elf_address *value);
-void elf_sym_set_visibility(elf_symtab_entry *entry,
- elf_symbol_vis vis);
-void elf_sym_set_type(elf_symtab_entry *entry, elf_symbol_type type);
-void elf_sym_set_size(elf_symtab_entry *entry, struct yasm_expr *size);
-int elf_sym_in_table(elf_symtab_entry *entry);
-
-/* section header functions */
-elf_secthead *elf_secthead_create(elf_strtab_entry *name,
- elf_section_type type,
- elf_section_flags flags,
- elf_address offset,
- elf_size size);
-void elf_secthead_destroy(elf_secthead *esd);
-unsigned long elf_secthead_write_to_file(FILE *f, elf_secthead *esd,
- elf_section_index sindex);
-void elf_secthead_append_reloc(yasm_section *sect, elf_secthead *shead,
- elf_reloc_entry *reloc);
-elf_section_type elf_secthead_get_type(elf_secthead *shead);
-void elf_secthead_set_typeflags(elf_secthead *shead, elf_section_type type,
- elf_section_flags flags);
-int elf_secthead_is_empty(elf_secthead *shead);
-struct yasm_symrec *elf_secthead_get_sym(elf_secthead *shead);
-unsigned long elf_secthead_get_align(const elf_secthead *shead);
-unsigned long elf_secthead_set_align(elf_secthead *shead, unsigned long align);
-elf_section_index elf_secthead_get_index(elf_secthead *shead);
-elf_section_info elf_secthead_set_info(elf_secthead *shead,
- elf_section_info info);
-elf_section_index elf_secthead_set_index(elf_secthead *shead,
- elf_section_index sectidx);
-elf_section_index elf_secthead_set_link(elf_secthead *shead,
- elf_section_index link);
-elf_section_index elf_secthead_set_rel_index(elf_secthead *shead,
- elf_section_index sectidx);
-elf_strtab_entry *elf_secthead_set_rel_name(elf_secthead *shead,
- elf_strtab_entry *entry);
-elf_size elf_secthead_set_entsize(elf_secthead *shead, elf_size size);
-struct yasm_symrec *elf_secthead_set_sym(elf_secthead *shead,
- struct yasm_symrec *sym);
-void elf_secthead_add_size(elf_secthead *shead, yasm_intnum *size);
-char *elf_secthead_name_reloc_section(const char *basesect);
-void elf_handle_reloc_addend(yasm_intnum *intn,
- elf_reloc_entry *reloc,
- unsigned long offset);
-unsigned long elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab,
- yasm_section *sect,
- elf_secthead *esd,
- elf_section_index sindex);
-unsigned long elf_secthead_write_relocs_to_file(FILE *f, yasm_section *sect,
- elf_secthead *shead,
- yasm_errwarns *errwarns);
-long elf_secthead_set_file_offset(elf_secthead *shead, long pos);
-
-/* program header function */
-unsigned long
-elf_proghead_get_size(void);
-unsigned long
-elf_proghead_write_to_file(FILE *f,
- elf_offset secthead_addr,
- unsigned long secthead_count,
- elf_section_index shstrtab_index);
-
-#endif /* ELF_H_INCLUDED */
+/*
+ * ELF object format helpers
+ *
+ * Copyright (C) 2003-2007 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_H_INCLUDED
+#define ELF_H_INCLUDED
+
+typedef struct elf_reloc_entry elf_reloc_entry;
+typedef struct elf_reloc_head elf_reloc_head;
+typedef struct elf_secthead elf_secthead;
+typedef struct elf_strtab_entry elf_strtab_entry;
+typedef struct elf_strtab_head elf_strtab_head;
+typedef struct elf_symtab_entry elf_symtab_entry;
+typedef struct elf_symtab_head elf_symtab_head;
+
+typedef struct elf_machine_handler elf_machine_handler;
+
+typedef unsigned long elf_address;
+typedef unsigned long elf_offset;
+typedef unsigned long elf_size;
+typedef unsigned long elf_section_info;
+
+typedef enum {
+ ET_NONE = 0,
+ ET_REL = 1, /* Relocatable */
+ ET_EXEC = 2, /* Executable */
+ ET_DYN = 3, /* Shared object */
+ ET_CORE = 4, /* Core */
+ ET_LOOS = 0xfe00, /* Environment specific */
+ ET_HIOS = 0xfeff,
+ ET_LOPROC = 0xff00, /* Processor specific */
+ ET_HIPROC = 0xffff
+} elf_file_type;
+
+typedef enum {
+ EM_NONE = 0,
+ EM_M32 = 1, /* AT&T WE 32100 */
+ EM_SPARC = 2, /* SPARC */
+ EM_386 = 3, /* Intel 80386 */
+ EM_68K = 4, /* Motorola 68000 */
+ EM_88K = 5, /* Motorola 88000 */
+ EM_860 = 7, /* Intel 80860 */
+ EM_MIPS = 8, /* MIPS RS3000 */
+
+ EM_S370 = 9, /* IBM System/370 */
+ EM_MIPS_RS4_BE = 10, /* MIPS R4000 Big-Endian (dep)*/
+ EM_PARISC = 15, /* HPPA */
+ EM_SPARC32PLUS = 18, /* SPARC v8plus */
+ EM_PPC = 20, /* PowerPC 32-bit */
+ EM_PPC64 = 21, /* PowerPC 64-bit */
+ EM_ARM = 40, /* ARM */
+ EM_SPARCV9 = 43, /* SPARC v9 64-bit */
+ EM_IA_64 = 50, /* Intel IA-64 */
+ EM_X86_64 = 62, /* AMD x86-64 */
+ EM_ALPHA = 0x9026 /* Alpha (no ABI) */
+} elf_machine;
+
+typedef enum {
+ ELFMAG0 = 0x7f,
+ ELFMAG1 = 0x45,
+ ELFMAG2 = 0x4c,
+ ELFMAG3 = 0x46
+} elf_magic;
+
+typedef enum {
+ EV_NONE = 0, /* invalid */
+ EV_CURRENT = 1 /* current */
+} elf_version;
+
+typedef enum {
+ EI_MAG0 = 0, /* File id */
+ EI_MAG1 = 1,
+ EI_MAG2 = 2,
+ EI_MAG3 = 3,
+ EI_CLASS = 4, /* File class */
+ EI_DATA = 5, /* Data encoding */
+ EI_VERSION = 6, /* File version */
+ EI_OSABI = 7, /* OS and ABI */
+ EI_ABIVERSION = 8, /* version of ABI */
+
+ EI_PAD = 9, /* Pad to end; start here */
+ EI_NIDENT = 16 /* Sizeof e_ident[] */
+} elf_identification_index;
+
+typedef enum {
+ ELFOSABI_SYSV = 0, /* System V ABI */
+ ELFOSABI_HPUX = 1, /* HP-UX os */
+ ELFOSABI_STANDALONE = 255 /* Standalone / embedded app */
+} elf_osabi_index;
+
+typedef enum {
+ ELFCLASSNONE = 0, /* invalid */
+ ELFCLASS32 = 1, /* 32-bit */
+ ELFCLASS64 = 2 /* 64-bit */
+} elf_class;
+
+typedef enum {
+ ELFDATANONE = 0,
+ ELFDATA2LSB = 1,
+ ELFDATA2MSB = 2
+} elf_data_encoding;
+
+/* elf section types - index of semantics */
+typedef enum {
+ SHT_NULL = 0, /* inactive section - no associated data */
+ SHT_PROGBITS = 1, /* defined by program for its own meaning */
+ SHT_SYMTAB = 2, /* symbol table (primarily) for linking */
+ SHT_STRTAB = 3, /* string table - symbols need names */
+ SHT_RELA = 4, /* relocation entries w/ explicit addends */
+ SHT_HASH = 5, /* symbol hash table - for dynamic linking */
+ SHT_DYNAMIC = 6, /* information for dynamic linking */
+ SHT_NOTE = 7, /* extra data marking the file somehow */
+ SHT_NOBITS = 8, /* no stored data, but occupies runtime space */
+ SHT_REL = 9, /* relocations entries w/o explicit addends */
+ SHT_SHLIB = 10, /* reserved; unspecified semantics */
+ SHT_DYNSYM = 11, /* like symtab, but more for dynamic linking */
+
+ SHT_LOOS = 0x60000000, /* reserved for environment specific use */
+ SHT_HIOS = 0x6fffffff,
+ SHT_LOPROC = 0x70000000, /* reserved for processor specific semantics */
+ SHT_HIPROC = 0x7fffffff/*,
+ SHT_LOUSER = 0x80000000,*/ /* reserved for applications; safe */
+ /*SHT_HIUSER = 0xffffffff*/
+} elf_section_type;
+
+/* elf section flags - bitfield of attributes */
+typedef enum {
+ SHF_WRITE = 0x1, /* data should be writable at runtime */
+ SHF_ALLOC = 0x2, /* occupies memory at runtime */
+ SHF_EXECINSTR = 0x4, /* contains machine instructions */
+ SHF_MERGE = 0x10, /* data can be merged */
+ SHF_STRINGS = 0x20, /* contains 0-terminated strings */
+ SHF_GROUP = 0x200, /* member of a section group */
+ SHF_TLS = 0x400, /* thread local storage */
+ SHF_MASKOS = 0x0f000000/*,*//* environment specific use */
+ /*SHF_MASKPROC = 0xf0000000*/ /* bits reserved for processor specific needs */
+} elf_section_flags;
+
+/* elf section index - just the special ones */
+typedef enum {
+ SHN_UNDEF = 0, /* undefined symbol; requires other global */
+ SHN_LORESERVE = 0xff00, /* reserved for various semantics */
+ SHN_LOPROC = 0xff00, /* reserved for processor specific semantics */
+ SHN_HIPROC = 0xff1f,
+ SHN_LOOS = 0xff20, /* reserved for environment specific use */
+ SHN_HIOS = 0xff3f,
+ SHN_ABS = 0xfff1, /* associated symbols don't change on reloc */
+ SHN_COMMON = 0xfff2, /* associated symbols refer to unallocated */
+ SHN_HIRESERVE = 0xffff
+} elf_section_index;
+
+/* elf symbol binding - index of visibility/behavior */
+typedef enum {
+ STB_LOCAL = 0, /* invisible outside defining file */
+ STB_GLOBAL = 1, /* visible to all combined object files */
+ STB_WEAK = 2, /* global but lower precedence */
+
+ STB_LOOS = 10, /* Environment specific use */
+ STB_HIOS = 12,
+ STB_LOPROC = 13, /* reserved for processor specific semantics */
+ STB_HIPROC = 15
+} elf_symbol_binding;
+
+/* elf symbol type - index of classifications */
+typedef enum {
+ STT_NOTYPE = 0, /* type not specified */
+ STT_OBJECT = 1, /* data object such as a variable, array, etc */
+ STT_FUNC = 2, /* a function or executable code */
+ STT_SECTION = 3, /* a section: often for relocation, STB_LOCAL */
+ STT_FILE = 4, /* often source filename: STB_LOCAL, SHN_ABS */
+ STT_COMMON = 5, /* Uninitialized common block. */
+ STT_TLS = 6, /* TLS object. */
+ STT_NUM = 7,
+
+ STT_LOOS = 10, /* Environment specific use */
+ STT_HIOS = 12,
+ STT_LOPROC = 13, /* reserved for processor specific semantics */
+ STT_HIPROC = 15
+} elf_symbol_type;
+
+typedef enum {
+ STN_UNDEF = 0
+} elf_symbol_index;
+
+/* elf symbol visibility - lower two bits of OTHER field */
+typedef enum {
+ STV_DEFAULT = 0, /* Default symbol visibility rules */
+ STV_INTERNAL = 1, /* Processor specific hidden class */
+ STV_HIDDEN = 2, /* Sym unavailable in other modules */
+ STV_PROTECTED = 3 /* Not preemptable, not exported */
+} elf_symbol_vis;
+
+
+/* internal only object definitions */
+#ifdef YASM_OBJFMT_ELF_INTERNAL
+
+#define ELF_VISIBILITY_MASK 0x03
+#define ELF_ST_VISIBILITY(v) ((v) & ELF_VISIBILITY_MASK)
+
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))
+#define ELF32_ST_OTHER(vis) ELF_ST_VISIBILITY(vis)
+
+#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+#define ELF64_R_INFO(s,t) (((s)<<32) + ((t) & 0xffffffffL))
+#define ELF64_ST_OTHER(vis) ELF_ST_VISIBILITY(vis)
+
+#define EHDR32_SIZE 52
+#define EHDR64_SIZE 64
+#define EHDR_MAXSIZE 64
+
+#define SHDR32_SIZE 40
+#define SHDR64_SIZE 64
+#define SHDR_MAXSIZE 64
+
+#define SYMTAB32_SIZE 16
+#define SYMTAB64_SIZE 24
+#define SYMTAB_MAXSIZE 24
+
+#define SYMTAB32_ALIGN 4
+#define SYMTAB64_ALIGN 8
+
+#define RELOC32_SIZE 8
+#define RELOC32A_SIZE 12
+#define RELOC64_SIZE 16
+#define RELOC64A_SIZE 24
+#define RELOC_MAXSIZE 24
+
+#define RELOC32_ALIGN 4
+#define RELOC64_ALIGN 8
+
+
+/* elf relocation type - index of semantics
+ *
+ * A = Addend (r_addend for RELA, value at location for REL)
+ * B = Base address
+ * G = Offset into global offset table (GOT)
+ * GOT = Address of the global offset table (GOT)
+ * L = Location of procedure linkage table (PLT)
+ * P = Location of location being relocated (r_offset)
+ * S = Value of symbol
+ */
+typedef enum {
+ R_386_NONE = 0, /* none */
+ R_386_32 = 1, /* word32, S + A */
+ R_386_PC32 = 2, /* word32, S + A - P */
+ R_386_GOT32 = 3, /* word32, G + A - P */
+ R_386_PLT32 = 4, /* word32, L + A - P */
+ R_386_COPY = 5, /* none */
+ R_386_GLOB_DAT = 6, /* word32, S */
+ R_386_JMP_SLOT = 7, /* word32, S */
+ R_386_RELATIVE = 8, /* word32, B + A */
+ R_386_GOTOFF = 9, /* word32, S + A - GOT */
+ R_386_GOTPC = 10, /* word32, GOT + A - P */
+ R_386_TLS_TPOFF = 14, /* Negative offset in static TLS block (GNU
+ version) */
+ R_386_TLS_IE = 15, /* Absolute address of GOT entry for negative
+ static TLS block offset */
+ R_386_TLS_GOTIE = 16, /* GOT entry for negative static TLS block
+ offset */
+ R_386_TLS_LE = 17, /* Negative offset relative to static TLS
+ (GNU version) */
+ R_386_TLS_GD = 18, /* Direct 32 bit for GNU version of GD TLS */
+ R_386_TLS_LDM = 19, /* Direct 32 bit for GNU version of LD TLS
+ in LE code */
+ R_386_16 = 20, /* word16, S + A (GNU extension) */
+ R_386_PC16 = 21, /* word16, S + A - P (GNU extension) */
+ R_386_8 = 22, /* word8, S + A (GNU extension) */
+ R_386_PC8 = 23, /* word8, S + A - P (GNU extension) */
+ R_386_TLS_GD_32 = 24, /* Direct 32 bit for GD TLS */
+ R_386_TLS_GD_PUSH = 25, /* Tag for pushl in GD TLS code */
+ R_386_TLS_GD_CALL = 26, /* Relocation for call to */
+ R_386_TLS_GD_POP = 27, /* Tag for popl in GD TLS code */
+ R_386_TLS_LDM_32 = 28, /* Direct 32 bit for local dynamic code */
+ R_386_TLS_LDM_PUSH = 29, /* Tag for pushl in LDM TLS code */
+ R_386_TLS_LDM_CALL = 30, /* Relocation for call to */
+ R_386_TLS_LDM_POP = 31, /* Tag for popl in LDM TLS code */
+ R_386_TLS_LDO_32 = 32, /* Offset relative to TLS block */
+ R_386_TLS_IE_32 = 33, /* GOT entry for static TLS block */
+ R_386_TLS_LE_32 = 34, /* Offset relative to static TLS block */
+ R_386_TLS_DTPMOD32 = 35, /* ID of module containing symbol */
+ R_386_TLS_DTPOFF32 = 36, /* Offset in TLS block */
+ R_386_TLS_TPOFF32 = 37, /* Offset in static TLS block */
+ R_386_TLS_GOTDESC = 39,
+ R_386_TLS_DESC_CALL = 40,
+ R_386_TLS_DESC = 41
+} elf_386_relocation_type;
+
+typedef enum {
+ R_X86_64_NONE = 0, /* none */
+ R_X86_64_64 = 1, /* word64, S + A */
+ R_X86_64_PC32 = 2, /* word32, S + A - P */
+ R_X86_64_GOT32 = 3, /* word32, G + A */
+ R_X86_64_PLT32 = 4, /* word32, L + A - P */
+ R_X86_64_COPY = 5, /* none */
+ R_X86_64_GLOB_DAT = 6, /* word64, S, set GOT entry to data address */
+ R_X86_64_JMP_SLOT = 7, /* word64, S, set GOT entry to code address */
+ R_X86_64_RELATIVE = 8, /* word64, B + A */
+ R_X86_64_GOTPCREL = 9, /* word32, G + GOT + A - P */
+ R_X86_64_32 = 10, /* word32 (zero extend), S + A */
+ R_X86_64_32S = 11, /* word32 (sign extend), S + A */
+ R_X86_64_16 = 12, /* word16, S + A */
+ R_X86_64_PC16 = 13, /* word16, S + A - P */
+ R_X86_64_8 = 14, /* word8, S + A */
+ R_X86_64_PC8 = 15, /* word8, S + A - P */
+ R_X86_64_DPTMOD64 = 16, /* word64, ID of module containing symbol */
+ R_X86_64_DTPOFF64 = 17, /* word64, offset in TLS block */
+ R_X86_64_TPOFF64 = 18, /* word64, offset in initial TLS block */
+ R_X86_64_TLSGD = 19, /* word32, PC-rel offset to GD GOT block */
+ R_X86_64_TLSLD = 20, /* word32, PC-rel offset to LD GOT block */
+ R_X86_64_DTPOFF32 = 21, /* word32, offset to TLS block */
+ R_X86_64_GOTTPOFF = 22, /* word32, PC-rel offset to IE GOT entry */
+ R_X86_64_TPOFF32 = 23, /* word32, offset in initial TLS block */
+ R_X86_64_PC64 = 24, /* word64, PC relative */
+ R_X86_64_GOTOFF64 = 25, /* word64, offset to GOT */
+ R_X86_64_GOTPC32 = 26, /* word32, signed pc relative to GOT */
+ R_X86_64_GOT64 = 27, /* word64, GOT entry offset */
+ R_X86_64_GOTPCREL64 = 28, /* word64, signed pc relative to GOT entry */
+ R_X86_64_GOTPC64 = 29, /* word64, signed pc relative to GOT */
+ R_X86_64_GOTPLT64 = 30, /* like GOT64, but indicates PLT entry needed */
+ R_X86_64_PLTOFF64 = 31, /* word64, GOT relative offset to PLT entry */
+ R_X86_64_GOTPC32_TLSDESC = 34, /* GOT offset for TLS descriptor */
+ R_X86_64_TLSDESC_CALL = 35, /* Marker for call through TLS descriptor */
+ R_X86_64_TLSDESC = 36 /* TLS descriptor */
+} elf_x86_64_relocation_type;
+
+struct elf_secthead {
+ elf_section_type type;
+ elf_section_flags flags;
+ elf_address offset;
+ yasm_intnum *size;
+ elf_section_index link;
+ elf_section_info info; /* see note ESD1 */
+ unsigned long align;
+ elf_size entsize;
+
+ yasm_symrec *sym;
+ elf_strtab_entry *name;
+ elf_section_index index;
+
+ elf_strtab_entry *rel_name;
+ elf_section_index rel_index;
+ elf_address rel_offset;
+ unsigned long nreloc;
+};
+
+/* Note ESD1:
+ * for section types SHT_REL, SHT_RELA:
+ * link -> index of associated symbol table
+ * info -> index of relocated section
+ * for section types SHT_SYMTAB, SHT_DYNSYM:
+ * link -> index of associated string table
+ * info -> 1+index of last "local symbol" (bind == STB_LOCAL)
+ * (for section type SHT_DNAMIC:
+ * link -> index of string table
+ * info -> 0 )
+ * (for section type SHT_HASH:
+ * link -> index of symbol table to which hash applies
+ * info -> 0 )
+ * for all others:
+ * link -> SHN_UNDEF
+ * info -> 0
+ */
+
+struct elf_reloc_entry {
+ yasm_reloc reloc;
+ int rtype_rel;
+ size_t valsize;
+ yasm_intnum *addend;
+ /*@null@*/ yasm_symrec *wrt;
+ int is_GOT_sym;
+};
+
+STAILQ_HEAD(elf_strtab_head, elf_strtab_entry);
+struct elf_strtab_entry {
+ STAILQ_ENTRY(elf_strtab_entry) qlink;
+ unsigned long index;
+ char *str;
+};
+
+STAILQ_HEAD(elf_symtab_head, elf_symtab_entry);
+struct elf_symtab_entry {
+ STAILQ_ENTRY(elf_symtab_entry) qlink;
+ int in_table;
+ yasm_symrec *sym;
+ yasm_section *sect;
+ elf_strtab_entry *name;
+ elf_address value;
+ /*@dependent@*/ yasm_expr *xsize;
+ elf_size size;
+ elf_section_index index;
+ elf_symbol_binding bind;
+ elf_symbol_type type;
+ elf_symbol_vis vis;
+ elf_symbol_index symindex;
+};
+
+#endif /* defined(YASM_OBJFMT_ELF_INTERNAL) */
+
+extern const yasm_assoc_data_callback elf_section_data;
+extern const yasm_assoc_data_callback elf_symrec_data;
+extern const yasm_assoc_data_callback elf_ssym_symrec_data;
+
+
+const elf_machine_handler *elf_set_arch(struct yasm_arch *arch,
+ yasm_symtab *symtab,
+ int bits_pref);
+
+yasm_symrec *elf_get_special_sym(const char *name, const char *parser);
+
+/* reloc functions */
+int elf_is_wrt_sym_relative(yasm_symrec *wrt);
+int elf_is_wrt_pos_adjusted(yasm_symrec *wrt);
+elf_reloc_entry *elf_reloc_entry_create(yasm_symrec *sym,
+ /*@null@*/ yasm_symrec *wrt,
+ yasm_intnum *addr,
+ int rel,
+ size_t valsize,
+ int is_GOT_sym);
+void elf_reloc_entry_destroy(void *entry);
+
+/* strtab functions */
+elf_strtab_entry *elf_strtab_entry_create(const char *str);
+void elf_strtab_entry_set_str(elf_strtab_entry *entry, const char *str);
+elf_strtab_head *elf_strtab_create(void);
+elf_strtab_entry *elf_strtab_append_str(elf_strtab_head *head, const char *str);
+void elf_strtab_destroy(elf_strtab_head *head);
+unsigned long elf_strtab_output_to_file(FILE *f, elf_strtab_head *head);
+
+/* symtab functions */
+elf_symtab_entry *elf_symtab_entry_create(elf_strtab_entry *name,
+ struct yasm_symrec *sym);
+elf_symtab_head *elf_symtab_create(void);
+void elf_symtab_append_entry(elf_symtab_head *symtab, elf_symtab_entry *entry);
+void elf_symtab_insert_local_sym(elf_symtab_head *symtab,
+ elf_symtab_entry *entry);
+void elf_symtab_destroy(elf_symtab_head *head);
+unsigned long elf_symtab_assign_indices(elf_symtab_head *symtab);
+unsigned long elf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab,
+ yasm_errwarns *errwarns);
+void elf_symtab_set_nonzero(elf_symtab_entry *entry,
+ struct yasm_section *sect,
+ elf_section_index sectidx,
+ elf_symbol_binding bind,
+ elf_symbol_type type,
+ struct yasm_expr *size,
+ elf_address *value);
+void elf_sym_set_visibility(elf_symtab_entry *entry,
+ elf_symbol_vis vis);
+void elf_sym_set_type(elf_symtab_entry *entry, elf_symbol_type type);
+void elf_sym_set_size(elf_symtab_entry *entry, struct yasm_expr *size);
+int elf_sym_in_table(elf_symtab_entry *entry);
+
+/* section header functions */
+elf_secthead *elf_secthead_create(elf_strtab_entry *name,
+ elf_section_type type,
+ elf_section_flags flags,
+ elf_address offset,
+ elf_size size);
+void elf_secthead_destroy(elf_secthead *esd);
+unsigned long elf_secthead_write_to_file(FILE *f, elf_secthead *esd,
+ elf_section_index sindex);
+void elf_secthead_append_reloc(yasm_section *sect, elf_secthead *shead,
+ elf_reloc_entry *reloc);
+elf_section_type elf_secthead_get_type(elf_secthead *shead);
+void elf_secthead_set_typeflags(elf_secthead *shead, elf_section_type type,
+ elf_section_flags flags);
+int elf_secthead_is_empty(elf_secthead *shead);
+struct yasm_symrec *elf_secthead_get_sym(elf_secthead *shead);
+unsigned long elf_secthead_get_align(const elf_secthead *shead);
+unsigned long elf_secthead_set_align(elf_secthead *shead, unsigned long align);
+elf_section_index elf_secthead_get_index(elf_secthead *shead);
+elf_section_info elf_secthead_set_info(elf_secthead *shead,
+ elf_section_info info);
+elf_section_index elf_secthead_set_index(elf_secthead *shead,
+ elf_section_index sectidx);
+elf_section_index elf_secthead_set_link(elf_secthead *shead,
+ elf_section_index link);
+elf_section_index elf_secthead_set_rel_index(elf_secthead *shead,
+ elf_section_index sectidx);
+elf_strtab_entry *elf_secthead_set_rel_name(elf_secthead *shead,
+ elf_strtab_entry *entry);
+elf_size elf_secthead_set_entsize(elf_secthead *shead, elf_size size);
+struct yasm_symrec *elf_secthead_set_sym(elf_secthead *shead,
+ struct yasm_symrec *sym);
+void elf_secthead_add_size(elf_secthead *shead, yasm_intnum *size);
+char *elf_secthead_name_reloc_section(const char *basesect);
+void elf_handle_reloc_addend(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset);
+unsigned long elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab,
+ yasm_section *sect,
+ elf_secthead *esd,
+ elf_section_index sindex);
+unsigned long elf_secthead_write_relocs_to_file(FILE *f, yasm_section *sect,
+ elf_secthead *shead,
+ yasm_errwarns *errwarns);
+long elf_secthead_set_file_offset(elf_secthead *shead, long pos);
+
+/* program header function */
+unsigned long
+elf_proghead_get_size(void);
+unsigned long
+elf_proghead_write_to_file(FILE *f,
+ elf_offset secthead_addr,
+ unsigned long secthead_count,
+ elf_section_index shstrtab_index);
+
+#endif /* ELF_H_INCLUDED */