summaryrefslogtreecommitdiff
path: root/output
diff options
context:
space:
mode:
authorH. Peter Anvin (Intel) <hpa@zytor.com>2019-04-24 11:14:43 -0700
committerH. Peter Anvin (Intel) <hpa@zytor.com>2019-04-24 11:14:43 -0700
commit9bb55bd1276822565f111f0bb347024b7e08df5b (patch)
tree4582a8ab5ea1dbbe5fc60484fc9518a426b29797 /output
parent982186a1a3139763f2aa2710b32236009f64270d (diff)
parent8b262474424c0f6912b22bbf7452f26bfa4d1235 (diff)
downloadnasm-9bb55bd1276822565f111f0bb347024b7e08df5b.tar.gz
Merge branch 'evalmacro'
Resolved Conflicts: asm/preproc.c output/elf.h output/outelf.c output/outelf.h version Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Diffstat (limited to 'output')
-rw-r--r--output/elf.h63
-rw-r--r--output/outelf.c1369
-rw-r--r--output/outelf.h54
3 files changed, 827 insertions, 659 deletions
diff --git a/output/elf.h b/output/elf.h
index b0aa67e9..8b83c5c2 100644
--- a/output/elf.h
+++ b/output/elf.h
@@ -148,23 +148,27 @@
#define PF_R 0x4
/* Section header types */
-#define SHT_NULL 0
-#define SHT_PROGBITS 1
-#define SHT_SYMTAB 2
-#define SHT_STRTAB 3
-#define SHT_RELA 4
-#define SHT_HASH 5
-#define SHT_DYNAMIC 6
-#define SHT_NOTE 7
-#define SHT_NOBITS 8
-#define SHT_REL 9
-#define SHT_SHLIB 10
-#define SHT_DYNSYM 11
-#define SHT_NUM 12
-#define SHT_LOPROC 0x70000000
-#define SHT_HIPROC 0x7fffffff
-#define SHT_LOUSER 0x80000000
-#define SHT_HIUSER 0xffffffff
+#define SHT_NULL 0
+#define SHT_PROGBITS 1
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+#define SHT_RELA 4
+#define SHT_HASH 5
+#define SHT_DYNAMIC 6
+#define SHT_NOTE 7
+#define SHT_NOBITS 8
+#define SHT_REL 9
+#define SHT_SHLIB 10
+#define SHT_DYNSYM 11
+#define SHT_INIT_ARRAY 14
+#define SHT_FINI_ARRAY 15
+#define SHT_PREINIT_ARRAY 16
+#define SHT_GROUP 17
+#define SHT_SYMTAB_SHNDX 18
+#define SHT_LOPROC 0x70000000
+#define SHT_HIPROC 0x7fffffff
+#define SHT_LOUSER 0x80000000
+#define SHT_HIUSER 0xffffffff
/* Section header flags */
#define SHF_WRITE (1 << 0) /* Writable */
@@ -179,13 +183,24 @@
#define SHF_TLS (1 << 10) /* Section hold thread-local data */
/* Special section numbers */
-#define SHN_UNDEF 0
-#define SHN_LORESERVE 0xff00
-#define SHN_LOPROC 0xff00
-#define SHN_HIPROC 0xff1f
-#define SHN_ABS 0xfff1
-#define SHN_COMMON 0xfff2
-#define SHN_HIRESERVE 0xffff
+#define SHN_UNDEF 0x0000
+#define SHN_LORESERVE 0xff00
+#define SHN_LOPROC 0xff00
+#define SHN_HIPROC 0xff1f
+#define SHN_ABS 0xfff1
+#define SHN_COMMON 0xfff2
+#define SHN_XINDEX 0xffff
+#define SHN_HIRESERVE 0xffff
+
+/* Same, but signed/sign-extended */
+#define XSHN_UNDEF ((int16_t)SHN_UNDEF)
+#define XSHN_LORESERVE ((int16_t)SHN_LORESERVE)
+#define XSHN_LOPROC ((int16_t)SHN_LOPROC)
+#define XSHN_HIPROC ((int16_t)SHN_HIPROC)
+#define XSHN_ABS ((int16_t)SHN_ABS)
+#define XSHN_COMMON ((int16_t)SHN_COMMON)
+#define XSHN_XINDEX ((int16_t)SHN_XINDEX)
+#define XSHN_HIRESERVE ((int16_t)SHN_HIRESERVE)
/* Section align flag */
#define SHA_ANY 1 /* No alignment constraint */
diff --git a/output/outelf.c b/output/outelf.c
index bacecbc6..c176689d 100644
--- a/output/outelf.c
+++ b/output/outelf.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
- *
- * Copyright 1996-2017 The NASM Authors - All Rights Reserved
+ *
+ * Copyright 1996-2019 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -14,7 +14,7 @@
* 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 COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -48,6 +48,7 @@
#include "outform.h"
#include "outlib.h"
#include "rbtree.h"
+#include "hashtbl.h"
#include "ver.h"
#include "dwarf.h"
@@ -72,9 +73,14 @@ static int32_t def_seg;
static struct RAA *bsym;
+static struct SAA *symtab, *symtab_shndx;
+
static struct SAA *strs;
static uint32_t strslen;
+static struct RAA *section_by_index;
+static struct hash_table section_by_name;
+
static struct elf_symbol *fwds;
static char elf_module[FILENAME_MAX];
@@ -95,12 +101,16 @@ static int64_t elf_foffs;
static void elf_write(void);
static void elf_sect_write(struct elf_section *, const void *, size_t);
static void elf_sect_writeaddr(struct elf_section *, int64_t, size_t);
-static void elf_section_header(int, int, uint64_t, void *, bool, uint64_t, int, int,
- int, int);
+static void elf_section_header(int name, int type, uint64_t flags,
+ void *data, bool is_saa, uint64_t datalen,
+ int link, int info,
+ uint64_t align, uint64_t entsize);
static void elf_write_sections(void);
-static struct SAA *elf_build_symtab(int32_t *, int32_t *);
-static struct SAA *elf_build_reltab(uint64_t *, struct elf_reloc *);
-static void add_sectname(const char *, const char *);
+static size_t elf_build_symtab(void);
+static int add_sectname(const char *, const char *);
+
+/* First debugging section index */
+static int sec_debug;
struct erel {
int offset;
@@ -174,9 +184,33 @@ static void dwarf_cleanup(void);
static void dwarf_findfile(const char *);
static void dwarf_findsect(const int);
-static bool is_elf64(void);
-static bool is_elf32(void);
-static bool is_elfx32(void);
+struct elf_format_info {
+ size_t word; /* Word size (4 or 8) */
+ size_t ehdr_size; /* Size of the ELF header */
+ size_t shdr_size; /* Size of a section header */
+ size_t sym_size; /* Size of a symbol */
+ size_t rel_size; /* Size of a reltype relocation */
+ size_t rela_size; /* Size of a RELA relocation */
+ char relpfx[8]; /* Relocation section prefix */
+ uint32_t reltype; /* Relocation section type */
+ uint16_t e_machine; /* Header e_machine field */
+ uint8_t ei_class; /* ELFCLASS32 or ELFCLASS64 */
+ bool elf64; /* 64-bit ELF */
+
+ /* Write a symbol */
+ void (*elf_sym)(const struct elf_symbol *);
+
+ /* Build a relocation table */
+ struct SAA *(*elf_build_reltab)(const struct elf_reloc *);
+};
+static const struct elf_format_info *efmt;
+
+static void elf32_sym(const struct elf_symbol *sym);
+static void elf64_sym(const struct elf_symbol *sym);
+
+static struct SAA *elf32_build_reltab(const struct elf_reloc *r);
+static struct SAA *elfx32_build_reltab(const struct elf_reloc *r);
+static struct SAA *elf64_build_reltab(const struct elf_reloc *r);
static bool dfmt_is_stabs(void);
static bool dfmt_is_dwarf(void);
@@ -192,26 +226,66 @@ static int32_t elf_sym_sect, elf_gottpoff_sect, elf_tlsie_sect;
uint8_t elf_osabi = 0; /* Default OSABI = 0 (System V or Linux) */
uint8_t elf_abiver = 0; /* Current ABI version */
-const struct elf_known_section elf_known_sections[] = {
- { ".text", SHT_PROGBITS, SHF_ALLOC|SHF_EXECINSTR, 16 },
- { ".rodata", SHT_PROGBITS, SHF_ALLOC, 4 },
- { ".lrodata", SHT_PROGBITS, SHF_ALLOC, 4 },
- { ".data", SHT_PROGBITS, SHF_ALLOC|SHF_WRITE, 4 },
- { ".ldata", SHT_PROGBITS, SHF_ALLOC|SHF_WRITE, 4 },
- { ".bss", SHT_NOBITS, SHF_ALLOC|SHF_WRITE, 4 },
- { ".lbss", SHT_NOBITS, SHF_ALLOC|SHF_WRITE, 4 },
- { ".tdata", SHT_PROGBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS, 4 },
- { ".tbss", SHT_NOBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS, 4 },
- { ".comment", SHT_PROGBITS, 0, 1 },
- { NULL, SHT_PROGBITS, SHF_ALLOC, 1 } /* default */
+/* Known sections with nonstandard defaults. -n means n*pointer size. */
+struct elf_known_section {
+ const char *name; /* Name of section */
+ int type; /* Section type (SHT_) */
+ uint32_t flags; /* Section flags (SHF_) */
+ int align; /* Section alignment */
+ int entsize; /* Entry size, if applicable */
};
+static const struct elf_known_section elf_known_sections[] = {
+ { ".text", SHT_PROGBITS, SHF_ALLOC|SHF_EXECINSTR, 16, 0 },
+ { ".rodata", SHT_PROGBITS, SHF_ALLOC, 4, 0 },
+ { ".lrodata", SHT_PROGBITS, SHF_ALLOC, 4, 0 },
+ { ".data", SHT_PROGBITS, SHF_ALLOC|SHF_WRITE, 4, 0 },
+ { ".ldata", SHT_PROGBITS, SHF_ALLOC|SHF_WRITE, 4, 0 },
+ { ".bss", SHT_NOBITS, SHF_ALLOC|SHF_WRITE, 4, 0 },
+ { ".lbss", SHT_NOBITS, SHF_ALLOC|SHF_WRITE, 4, 0 },
+ { ".tdata", SHT_PROGBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS, 4, 0 },
+ { ".tbss", SHT_NOBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS, 4, 0 },
+ { ".comment", SHT_PROGBITS, 0, 1, 0 },
+ { ".preinit_array", SHT_PREINIT_ARRAY, SHF_ALLOC, -1, -1 },
+ { ".init_array", SHT_INIT_ARRAY, SHF_ALLOC, -1, -1 },
+ { ".fini_array", SHT_FINI_ARRAY, SHF_ALLOC, -1, -1 },
+ { ".note", SHT_NOTE, 0, 4, 0 },
+ { NULL /*default*/, SHT_PROGBITS, SHF_ALLOC, 1, 0 }
+};
+
+struct size_unit {
+ char name[8];
+ int bytes;
+ int align;
+};
+static const struct size_unit size_units[] =
+{
+ { "byte", 1, 1 },
+ { "word", 2, 2 },
+ { "dword", 4, 4 },
+ { "qword", 8, 8 },
+ { "tword", 10, 2 },
+ { "tbyte", 10, 2 },
+ { "oword", 16, 16 },
+ { "xword", 16, 16 },
+ { "yword", 32, 32 },
+ { "zword", 64, 64 },
+ { "pointer", -1, -1 },
+ { "", 0, 0 }
+};
+
+static inline size_t to_bytes(int val)
+{
+ return (val >= 0) ? (size_t)val : -val * efmt->word;
+}
+
/* parse section attributes */
-static void elf_section_attrib(char *name, char *attr,
- uint32_t *flags_and, uint32_t *flags_or,
- uint64_t *align, int *type)
+static void elf_section_attrib(char *name, char *attr, uint32_t *flags_and, uint32_t *flags_or,
+ uint64_t *alignp, uint64_t *entsize, int *type)
{
char *opt, *val, *next;
+ uint64_t align = 0;
+ uint64_t xalign = 0;
opt = nasm_skip_spaces(attr);
if (!opt || !*opt)
@@ -222,13 +296,14 @@ static void elf_section_attrib(char *name, char *attr,
if (!val) {
nasm_nonfatal("section align without value specified");
} else {
- *align = atoi(val);
- if (*align == 0) {
- *align = SHA_ANY;
- } else if (!is_power2(*align)) {
- nasm_nonfatal("section alignment %"PRId64" is not a power of two",
- *align);
- *align = SHA_ANY;
+ bool err;
+ uint64_t a = readnum(val, &err);
+ if (a && !is_power2(a)) {
+ nasm_error(ERR_NONFATAL,
+ "section alignment %"PRId64" is not a power of two",
+ a);
+ } else if (a > align) {
+ align = a;
}
}
} else if (!nasm_stricmp(opt, "alloc")) {
@@ -246,22 +321,92 @@ static void elf_section_attrib(char *name, char *attr,
} else if (!nasm_stricmp(opt, "write")) {
*flags_and |= SHF_WRITE;
*flags_or |= SHF_WRITE;
+ } else if (!nasm_stricmp(opt, "nowrite") ||
+ !nasm_stricmp(opt, "readonly")) {
+ *flags_and |= SHF_WRITE;
+ *flags_or &= ~SHF_WRITE;
} else if (!nasm_stricmp(opt, "tls")) {
*flags_and |= SHF_TLS;
*flags_or |= SHF_TLS;
- } else if (!nasm_stricmp(opt, "nowrite")) {
- *flags_and |= SHF_WRITE;
- *flags_or &= ~SHF_WRITE;
+ } else if (!nasm_stricmp(opt, "notls")) {
+ *flags_and |= SHF_TLS;
+ *flags_or &= ~SHF_TLS;
+ } else if (!nasm_stricmp(opt, "merge")) {
+ *flags_and |= SHF_MERGE;
+ *flags_or |= SHF_MERGE;
+ } else if (!nasm_stricmp(opt, "nomerge")) {
+ *flags_and |= SHF_MERGE;
+ *flags_or &= ~SHF_MERGE;
+ } else if (!nasm_stricmp(opt, "strings")) {
+ *flags_and |= SHF_STRINGS;
+ *flags_or |= SHF_STRINGS;
+ } else if (!nasm_stricmp(opt, "nostrings")) {
+ *flags_and |= SHF_STRINGS;
+ *flags_or &= ~SHF_STRINGS;
} else if (!nasm_stricmp(opt, "progbits")) {
*type = SHT_PROGBITS;
} else if (!nasm_stricmp(opt, "nobits")) {
*type = SHT_NOBITS;
+ } else if (!nasm_stricmp(opt, "note")) {
+ *type = SHT_NOTE;
+ } else if (!nasm_stricmp(opt, "preinit_array")) {
+ *type = SHT_PREINIT_ARRAY;
+ } else if (!nasm_stricmp(opt, "init_array")) {
+ *type = SHT_INIT_ARRAY;
+ } else if (!nasm_stricmp(opt, "fini_array")) {
+ *type = SHT_FINI_ARRAY;
} else {
- nasm_warn(WARN_OTHER, "unknown section attribute '%s' ignored on"
- " declaration of section `%s'", opt, name);
- }
+ uint64_t mult;
+ size_t l;
+ const char *a = strchr(opt, '*');
+ bool err;
+ const struct size_unit *su;
+
+ if (a) {
+ l = a - opt - 1;
+ mult = readnum(a+1, &err);
+ } else {
+ l = strlen(opt);
+ mult = 1;
+ }
+
+ for (su = size_units; su->bytes; su++) {
+ if (!nasm_strnicmp(opt, su->name, l))
+ break;
+ }
+
+ if (su->bytes) {
+ *entsize = to_bytes(su->bytes) * mult;
+ xalign = to_bytes(su->align);
+ } else {
+ /* Unknown attribute */
+ nasm_warn(WARN_OTHER,
+ "unknown section attribute '%s' ignored on"
+ " declaration of section `%s'", opt, name);
+ }
+ }
opt = next;
}
+
+ switch (*type) {
+ case SHT_PREINIT_ARRAY:
+ case SHT_INIT_ARRAY:
+ case SHT_FINI_ARRAY:
+ if (!xalign)
+ xalign = efmt->word;
+ if (!*entsize)
+ *entsize = efmt->word;
+ break;
+ default:
+ break;
+ }
+
+ if (!align)
+ align = xalign;
+ if (!align)
+ align = SHA_ANY;
+
+ *alignp = align;
}
static enum directive_result
@@ -308,8 +453,81 @@ elf_directive(enum directive directive, char *value)
}
}
+static void elf_init(void);
+
+static void elf32_init(void)
+{
+ static const struct elf_format_info ef_elf32 = {
+ 4,
+ sizeof(Elf32_Ehdr),
+ sizeof(Elf32_Shdr),
+ sizeof(Elf32_Sym),
+ sizeof(Elf32_Rel),
+ sizeof(Elf32_Rela),
+ ".rel",
+ SHT_REL,
+ EM_386,
+ ELFCLASS32,
+ false,
+
+ elf32_sym,
+ elf32_build_reltab
+ };
+ efmt = &ef_elf32;
+ elf_init();
+}
+
+static void elfx32_init(void)
+{
+ static const struct elf_format_info ef_elfx32 = {
+ 4,
+ sizeof(Elf32_Ehdr),
+ sizeof(Elf32_Shdr),
+ sizeof(Elf32_Sym),
+ sizeof(Elf32_Rela),
+ sizeof(Elf32_Rela),
+ ".rela",
+ SHT_RELA,
+ EM_X86_64,
+ ELFCLASS32,
+ false,
+
+ elf32_sym,
+ elfx32_build_reltab
+ };
+ efmt = &ef_elfx32;
+ elf_init();
+}
+
+static void elf64_init(void)
+{
+ static const struct elf_format_info ef_elf64 = {
+ 8,
+ sizeof(Elf64_Ehdr),
+ sizeof(Elf64_Shdr),
+ sizeof(Elf64_Sym),
+ sizeof(Elf64_Rela),
+ sizeof(Elf64_Rela),
+ ".rela",
+ SHT_RELA,
+ EM_X86_64,
+ ELFCLASS64,
+ true,
+
+ elf64_sym,
+ elf64_build_reltab
+ };
+ efmt = &ef_elf64;
+ elf_init();
+}
+
static void elf_init(void)
{
+ static const char * const reserved_sections[] = {
+ ".shstrtab", ".strtab", ".symtab", ".symtab_shndx", NULL
+ };
+ const char * const *p;
+
strlcpy(elf_module, inname, sizeof(elf_module));
sects = NULL;
nsects = sectlen = 0;
@@ -322,15 +540,26 @@ static void elf_init(void)
strslen = 2 + strlen(elf_module);
shstrtab = NULL;
shstrtablen = shstrtabsize = 0;;
- add_sectname("", "");
+ add_sectname("", ""); /* SHN_UNDEF */
fwds = NULL;
+ section_by_index = raa_init();
+
+ /*
+ * Add reserved section names to the section hash, with NULL
+ * as the data pointer
+ */
+ for (p = reserved_sections; *p; p++) {
+ struct hash_insert hi;
+ hash_find(&section_by_name, *p, &hi);
+ hash_add(&hi, *p, NULL);
+ }
+
/*
* FIXME: tlsie is Elf32 only and
* gottpoff is Elfx32|64 only.
*/
-
elf_gotpc_sect = seg_alloc();
backend_label("..gotpc", elf_gotpc_sect + 1, 0L);
elf_gotoff_sect = seg_alloc();
@@ -358,7 +587,7 @@ static void elf_cleanup(void)
for (i = 0; i < nsects; i++) {
if (sects[i]->type != SHT_NOBITS)
saa_free(sects[i]->data);
- if (sects[i]->head)
+ if (sects[i]->rel)
saa_free(sects[i]->rel);
while (sects[i]->head) {
r = sects[i]->head;
@@ -366,6 +595,8 @@ static void elf_cleanup(void)
nasm_free(r);
}
}
+ hash_free(&section_by_name);
+ raa_free(section_by_index);
nasm_free(sects);
saa_free(syms);
raa_free(bsym);
@@ -373,18 +604,31 @@ static void elf_cleanup(void)
dfmt->cleanup();
}
-/* add entry to the elf .shstrtab section */
-static void add_sectname(const char *firsthalf, const char *secondhalf)
+/*
+ * Add entry to the elf .shstrtab section and increment nsections.
+ * Returns the section index for this new section.
+ *
+ * IMPORTANT: this needs to match the order the section headers are
+ * emitted.
+ */
+static int add_sectname(const char *firsthalf, const char *secondhalf)
{
- int len = strlen(firsthalf) + strlen(secondhalf);
- while (shstrtablen + len + 1 > shstrtabsize)
+ int l1 = strlen(firsthalf);
+ int l2 = strlen(secondhalf);
+
+ while (shstrtablen + l1 + l2 + 1 > shstrtabsize)
shstrtab = nasm_realloc(shstrtab, (shstrtabsize += SHSTR_DELTA));
- strcpy(shstrtab + shstrtablen, firsthalf);
- strcat(shstrtab + shstrtablen, secondhalf);
- shstrtablen += len + 1;
+
+ memcpy(shstrtab + shstrtablen, firsthalf, l1);
+ shstrtablen += l1;
+ memcpy(shstrtab + shstrtablen, secondhalf, l2+1);
+ shstrtablen += l2 + 1;
+
+ return nsections++;
}
-static int elf_make_section(char *name, int type, int flags, int align)
+static struct elf_section *
+elf_make_section(char *name, int type, int flags, uint64_t align)
{
struct elf_section *s;
@@ -397,26 +641,29 @@ static int elf_make_section(char *name, int type, int flags, int align)
s->index = def_seg;
else
s->index = seg_alloc();
- add_sectname("", name);
s->name = nasm_strdup(name);
s->type = type;
s->flags = flags;
s->align = align;
+ s->shndx = add_sectname("", name);
if (nsects >= sectlen)
sects = nasm_realloc(sects, (sectlen += SECT_DELTA) * sizeof(*sects));
sects[nsects++] = s;
- return nsects - 1;
+ return s;
}
static int32_t elf_section_names(char *name, int *bits)
{
char *p;
uint32_t flags, flags_and, flags_or;
- uint64_t align;
- int type, i;
+ uint64_t align, entsize;
+ void **hp;
+ struct elf_section *s;
+ struct hash_insert hi;
+ int type;
if (!name) {
*bits = ofmt->maxbits;
@@ -426,23 +673,18 @@ static int32_t elf_section_names(char *name, int *bits)
p = nasm_skip_word(name);
if (*p)
*p++ = '\0';
- flags_and = flags_or = type = align = 0;
+ flags_and = flags_or = type = align = entsize = 0;
- elf_section_attrib(name, p, &flags_and,
- &flags_or, &align, &type);
+ elf_section_attrib(name, p, &flags_and, &flags_or, &align, &entsize, &type);
- if (!strcmp(name, ".shstrtab") ||
- !strcmp(name, ".symtab") ||
- !strcmp(name, ".strtab")) {
- nasm_nonfatal("attempt to redefine reserved section"
- "name `%s'", name);
- return NO_SEG;
- }
-
- for (i = 0; i < nsects; i++)
- if (!strcmp(name, sects[i]->name))
- break;
- if (i == nsects) {
+ hp = hash_find(&section_by_name, name, &hi);
+ if (hp) {
+ s = *hp;
+ if (!s) {
+ nasm_nonfatal("attempt to redefine reserved section name `%s'", name);
+ return NO_SEG;
+ }
+ } else {
const struct elf_known_section *ks = elf_known_sections;
while (ks->name) {
@@ -452,20 +694,37 @@ static int32_t elf_section_names(char *name, int *bits)
}
type = type ? type : ks->type;
- align = align ? align : ks->align;
+ if (!align)
+ align = to_bytes(ks->align);
+ if (!entsize)
+ entsize = to_bytes(ks->entsize);
flags = (ks->flags & ~flags_and) | flags_or;
- i = elf_make_section(name, type, flags, align);
- } else if (sects[i]->pass_last_seen == pass_count()) {
- if ((type && sects[i]->type != type)
- || (align && sects[i]->align != align)
- || (flags_and && ((sects[i]->flags & flags_and) != flags_or)))
- nasm_warn(WARN_OTHER|ERR_PASS1, "incompatible section attributes ignored on"
- " redeclaration of section `%s'", name);
+ s = elf_make_section(name, type, flags, align);
+ hash_add(&hi, s->name, s);
+ section_by_index = raa_write_ptr(section_by_index, s->index >> 1, s);
+ }
+
+ if ((type && s->type != type)
+ || ((s->flags & flags_and) != flags_or)
+ || (entsize && s->entsize && entsize != s->entsize)) {
+ nasm_warn(WARN_OTHER, "incompatible section attributes ignored on"
+ " redeclaration of section `%s'", name);
+ }
+
+ if (align > s->align)
+ s->align = align;
+
+ if (entsize && !s->entsize)
+ s->entsize = entsize;
+
+ if ((flags_or & SHF_MERGE) && s->entsize == 0) {
+ if (!(s->flags & SHF_STRINGS))
+ nasm_nonfatal("section attribute merge specified without an entry size or `strings'");
+ s->entsize = 1;
}
- sects[i]->pass_last_seen = pass_count();
- return sects[i]->index;
+ return s->index;
}
static void elf_deflabel(char *name, int32_t segment, int64_t offset,
@@ -541,28 +800,25 @@ static void elf_deflabel(char *name, int32_t segment, int64_t offset,
sym->other = STV_DEFAULT;
sym->size = 0;
if (segment == NO_SEG)
- sym->section = SHN_ABS;
+ sym->section = XSHN_ABS;
else {
- int i;
- sym->section = SHN_UNDEF;
+ const struct elf_section *s;
+ sym->section = XSHN_UNDEF;
if (segment == def_seg) {
/* we have to be sure at least text section is there */
int tempint;
if (segment != elf_section_names(".text", &tempint))
nasm_panic("strange segment conditions in ELF driver");
}
- for (i = 0; i < nsects; i++) {
- if (segment == sects[i]->index) {
- sym->section = i + 1;
- break;
- }
- }
+ s = raa_read_ptr(section_by_index, segment >> 1);
+ if (s)
+ sym->section = s->shndx;
}
if (is_global == 2) {
sym->size = offset;
sym->symv.key = 0;
- sym->section = SHN_COMMON;
+ sym->section = XSHN_COMMON;
/*
* We have a common variable. Check the special text to see
* if it's a valid number and power of two; if so, store it
@@ -580,7 +836,7 @@ static void elf_deflabel(char *name, int32_t segment, int64_t offset,
}
special_used = true;
} else
- sym->symv.key = (sym->section == SHN_UNDEF ? 0 : offset);
+ sym->symv.key = (sym->section == XSHN_UNDEF ? 0 : offset);
if (sym->type == SYM_GLOBAL) {
/*
@@ -593,9 +849,9 @@ static void elf_deflabel(char *name, int32_t segment, int64_t offset,
* To avoid such a crash, such requests are silently discarded.
* This may not be the best solution.
*/
- if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON) {
+ if (sym->section == XSHN_UNDEF || sym->section == XSHN_COMMON) {
bsym = raa_write(bsym, segment, nglobs);
- } else if (sym->section != SHN_ABS) {
+ } else if (sym->section != XSHN_ABS) {
/*
* This is a global symbol; so we must add it to the rbtree
* of global symbols in its section.
@@ -697,11 +953,11 @@ static void elf_add_reloc(struct elf_section *sect, int32_t segment,
r->offset = offset;
if (segment != NO_SEG) {
- int i;
- for (i = 0; i < nsects; i++)
- if (segment == sects[i]->index)
- r->symbol = i + 2;
- if (!r->symbol)
+ const struct elf_section *s;
+ s = raa_read_ptr(section_by_index, segment >> 1);
+ if (s)
+ r->symbol = s->shndx + 1;
+ else
r->symbol = GLOBAL_TEMP_BASE + raa_read(bsym, segment);
}
r->type = type;
@@ -739,7 +995,6 @@ static int64_t elf_add_gsym_reloc(struct elf_section *sect,
struct elf_section *s;
struct elf_symbol *sym;
struct rbtree *srb;
- int i;
/*
* First look up the segment/offset pair and find a global
@@ -748,13 +1003,7 @@ static int64_t elf_add_gsym_reloc(struct elf_section *sect,
* doing a normal elf_add_reloc after first sanity-checking
* that the offset from the symbol is zero.
*/
- s = NULL;
- for (i = 0; i < nsects; i++)
- if (segment == sects[i]->index) {
- s = sects[i];
- break;
- }
-
+ s = raa_read_ptr(section_by_index, segment >> 1);
if (!s) {
if (exact && offset)
nasm_nonfatal("invalid access to an external symbol");
@@ -791,28 +1040,29 @@ static void elf32_out(int32_t segto, const void *data,
struct elf_section *s;
int64_t addr;
int reltype, bytes;
- int i;
static struct symlininfo sinfo;
- s = NULL;
- for (i = 0; i < nsects; i++)
- if (segto == sects[i]->index) {
- s = sects[i];
- break;
- }
+ /*
+ * handle absolute-assembly (structure definitions)
+ */
+ if (segto == NO_SEG) {
+ if (type != OUT_RESERVE)
+ nasm_nonfatal("attempt to assemble code in [ABSOLUTE] space");
+ return;
+ }
+
+ s = raa_read_ptr(section_by_index, segto >> 1);
if (!s) {
int tempint; /* ignored */
if (segto != elf_section_names(".text", &tempint))
nasm_panic("strange segment conditions in ELF driver");
- else {
+ else
s = sects[nsects - 1];
- i = nsects - 1;
- }
}
/* again some stabs debugging stuff */
sinfo.offset = s->len;
- sinfo.section = i;
+ sinfo.section = s->shndx;
sinfo.segto = segto;
sinfo.name = s->name;
dfmt->debug_output(TY_DEBUGSYMLIN, &sinfo);
@@ -827,7 +1077,7 @@ static void elf32_out(int32_t segto, const void *data,
switch (type) {
case OUT_RESERVE:
- if (s->type == SHT_PROGBITS) {
+ if (s->type != SHT_NOBITS) {
nasm_warn(WARN_ZEROING, "uninitialized space declared in"
" non-BSS section `%s': zeroing", s->name);
elf_sect_write(s, NULL, size);
@@ -851,7 +1101,7 @@ static void elf32_out(int32_t segto, const void *data,
" segment base references");
} else {
if (wrt == NO_SEG) {
- /*
+ /*
* The if() is a hack to deal with compilers which
* don't handle switch() statements with 64-bit
* expressions.
@@ -1002,28 +1252,29 @@ static void elf64_out(int32_t segto, const void *data,
struct elf_section *s;
int64_t addr;
int reltype, bytes;
- int i;
static struct symlininfo sinfo;
- s = NULL;
- for (i = 0; i < nsects; i++)
- if (segto == sects[i]->index) {
- s = sects[i];
- break;
- }
+ /*
+ * handle absolute-assembly (structure definitions)
+ */
+ if (segto == NO_SEG) {
+ if (type != OUT_RESERVE)
+ nasm_nonfatal("attempt to assemble code in [ABSOLUTE] space");
+ return;
+ }
+
+ s = raa_read_ptr(section_by_index, segto >> 1);
if (!s) {
int tempint; /* ignored */
if (segto != elf_section_names(".text", &tempint))
nasm_panic("strange segment conditions in ELF driver");
- else {
+ else
s = sects[nsects - 1];
- i = nsects - 1;
- }
}
/* again some stabs debugging stuff */
sinfo.offset = s->len;
- sinfo.section = i;
+ sinfo.section = s->shndx;
sinfo.segto = segto;
sinfo.name = s->name;
dfmt->debug_output(TY_DEBUGSYMLIN, &sinfo);
@@ -1038,7 +1289,7 @@ static void elf64_out(int32_t segto, const void *data,
switch (type) {
case OUT_RESERVE:
- if (s->type == SHT_PROGBITS) {
+ if (s->type != SHT_NOBITS) {
nasm_warn(WARN_ZEROING, "uninitialized space declared in"
" non-BSS section `%s': zeroing", s->name);
elf_sect_write(s, NULL, size);
@@ -1280,28 +1531,29 @@ static void elfx32_out(int32_t segto, const void *data,
struct elf_section *s;
int64_t addr;
int reltype, bytes;
- int i;
static struct symlininfo sinfo;
- s = NULL;
- for (i = 0; i < nsects; i++)
- if (segto == sects[i]->index) {
- s = sects[i];
- break;
- }
+ /*
+ * handle absolute-assembly (structure definitions)
+ */
+ if (segto == NO_SEG) {
+ if (type != OUT_RESERVE)
+ nasm_nonfatal("attempt to assemble code in [ABSOLUTE] space");
+ return;
+ }
+
+ s = raa_read_ptr(section_by_index, segto >> 1);
if (!s) {
int tempint; /* ignored */
if (segto != elf_section_names(".text", &tempint))
nasm_panic("strange segment conditions in ELF driver");
- else {
+ else
s = sects[nsects - 1];
- i = nsects - 1;
- }
}
/* again some stabs debugging stuff */
sinfo.offset = s->len;
- sinfo.section = i;
+ sinfo.section = s->shndx;
sinfo.segto = segto;
sinfo.name = s->name;
dfmt->debug_output(TY_DEBUGSYMLIN, &sinfo);
@@ -1316,7 +1568,7 @@ static void elfx32_out(int32_t segto, const void *data,
switch (type) {
case OUT_RESERVE:
- if (s->type == SHT_PROGBITS) {
+ if (s->type != SHT_NOBITS) {
nasm_warn(WARN_ZEROING, "uninitialized space declared in"
" non-BSS section `%s': zeroing", s->name);
elf_sect_write(s, NULL, size);
@@ -1512,51 +1764,53 @@ rel12adr:
}
}
+/*
+ * Section index/count with a specified overflow value (usually SHN_INDEX,
+ * but 0 for e_shnum.
+ */
+static inline uint16_t elf_shndx(int section, uint16_t overflow)
+{
+ return cpu_to_le16(section < (int)SHN_LORESERVE ? section : overflow);
+}
+
+struct ehdr_common {
+ uint8_t e_ident[EI_NIDENT];
+ uint16_t e_type;
+ uint16_t e_machine;
+ uint32_t e_version;
+};
+
+union ehdr {
+ Elf32_Ehdr ehdr32;
+ Elf64_Ehdr ehdr64;
+ struct ehdr_common com;
+};
+
static void elf_write(void)
{
int align;
char *p;
int i;
-
- struct SAA *symtab;
- int32_t symtablen, symtablocal;
+ size_t symtablocal;
+ int sec_shstrtab, sec_symtab, sec_strtab;
+ union ehdr ehdr;
/*
- * Work out how many sections we will have. We have SHN_UNDEF,
- * then the flexible user sections, then the fixed sections
- * `.shstrtab', `.symtab' and `.strtab', then optionally
- * relocation sections for the user sections.
+ * Add any sections we don't already have:
+ * rel/rela sections for the user sections, debug sections, and
+ * the ELF special sections.
*/
- nsections = sec_numspecial + 1;
- if (dfmt_is_stabs())
- nsections += 3;
- else if (dfmt_is_dwarf())
- nsections += 10;
-
- add_sectname("", ".shstrtab");
- add_sectname("", ".symtab");
- add_sectname("", ".strtab");
- for (i = 0; i < nsects; i++) {
- nsections++; /* for the section itself */
- if (sects[i]->head) {
- nsections++; /* for its relocations */
- add_sectname(is_elf32() ? ".rel" : ".rela", sects[i]->name);
- }
- }
+ sec_debug = nsections;
if (dfmt_is_stabs()) {
/* in case the debug information is wanted, just add these three sections... */
add_sectname("", ".stab");
add_sectname("", ".stabstr");
- add_sectname(is_elf32() ? ".rel" : ".rela", ".stab");
+ add_sectname(efmt->relpfx, ".stab");
} else if (dfmt_is_dwarf()) {
/* the dwarf debug standard specifies the following ten sections,
not all of which are currently implemented,
although all of them are defined. */
-#define debug_aranges (int64_t) (nsections-10)
-#define debug_info (int64_t) (nsections-7)
-#define debug_abbrev (int64_t) (nsections-5)
-#define debug_line (int64_t) (nsections-4)
add_sectname("", ".debug_aranges");
add_sectname(".rela", ".debug_aranges");
add_sectname("", ".debug_pubnames");
@@ -1569,145 +1823,84 @@ static void elf_write(void)
add_sectname("", ".debug_loc");
}
+ sec_shstrtab = add_sectname("", ".shstrtab");
+ sec_symtab = add_sectname("", ".symtab");
+ sec_strtab = add_sectname("", ".strtab");
+
/*
- * Output the ELF header.
+ * Build the symbol table and relocation tables.
*/
- if (is_elf32() || is_elfx32()) {
- Elf32_Ehdr ehdr;
-
- nasm_zero(ehdr.e_ident);
- memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
- ehdr.e_ident[EI_CLASS] = ELFCLASS32;
- ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
- ehdr.e_ident[EI_VERSION] = EV_CURRENT;
- ehdr.e_ident[EI_OSABI] = elf_osabi;
- ehdr.e_ident[EI_ABIVERSION] = elf_abiver;
-
- ehdr.e_type = cpu_to_le16(ET_REL);
- ehdr.e_machine = cpu_to_le16(is_elf32() ? EM_386 : EM_X86_64);
- ehdr.e_version = cpu_to_le16(EV_CURRENT);
- ehdr.e_entry = 0;
- ehdr.e_phoff = 0;
- ehdr.e_shoff = sizeof(Elf64_Ehdr);
- ehdr.e_flags = 0;
- ehdr.e_ehsize = cpu_to_le16(sizeof(Elf32_Ehdr));
- ehdr.e_phentsize = 0;
- ehdr.e_phnum = 0;
- ehdr.e_shentsize = cpu_to_le16(sizeof(Elf32_Shdr));
- ehdr.e_shnum = cpu_to_le16(nsections);
- ehdr.e_shstrndx = cpu_to_le16(sec_shstrtab);
-
- nasm_write(&ehdr, sizeof(ehdr), ofile);
- fwritezero(sizeof(Elf64_Ehdr) - sizeof(Elf32_Ehdr), ofile);
- } else {
- Elf64_Ehdr ehdr;
+ symtablocal = elf_build_symtab();
- nasm_assert(is_elf64());
+ /* Do we need an .symtab_shndx section? */
+ if (symtab_shndx)
+ add_sectname("", ".symtab_shndx");
- nasm_zero(ehdr.e_ident);
- memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
- ehdr.e_ident[EI_CLASS] = ELFCLASS64;
- ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
- ehdr.e_ident[EI_VERSION] = EV_CURRENT;
- ehdr.e_ident[EI_OSABI] = elf_osabi;
- ehdr.e_ident[EI_ABIVERSION] = elf_abiver;
-
- ehdr.e_type = cpu_to_le16(ET_REL);
- ehdr.e_machine = cpu_to_le16(EM_X86_64);
- ehdr.e_version = cpu_to_le16(EV_CURRENT);
- ehdr.e_entry = 0;
- ehdr.e_phoff = 0;
- ehdr.e_shoff = sizeof(Elf64_Ehdr);
- ehdr.e_flags = 0;
- ehdr.e_ehsize = cpu_to_le16(sizeof(Elf64_Ehdr));
- ehdr.e_phentsize = 0;
- ehdr.e_phnum = 0;
- ehdr.e_shentsize = cpu_to_le16(sizeof(Elf64_Shdr));
- ehdr.e_shnum = cpu_to_le16(nsections);
- ehdr.e_shstrndx = cpu_to_le16(sec_shstrtab);
-
- nasm_write(&ehdr, sizeof(ehdr), ofile);
+ for (i = 0; i < nsects; i++) {
+ if (sects[i]->head) {
+ add_sectname(efmt->relpfx, sects[i]->name);
+ sects[i]->rel = efmt->elf_build_reltab(sects[i]->head);
+ }
}
/*
- * Build the symbol table and relocation tables.
+ * Output the ELF header.
*/
- symtab = elf_build_symtab(&symtablen, &symtablocal);
- for (i = 0; i < nsects; i++)
- if (sects[i]->head)
- sects[i]->rel = elf_build_reltab(&sects[i]->rellen,
- sects[i]->head);
+ nasm_zero(ehdr);
+
+ /* These fields are in the same place for 32 and 64 bits */
+ memcpy(&ehdr.com.e_ident[EI_MAG0], ELFMAG, SELFMAG);
+ ehdr.com.e_ident[EI_CLASS] = efmt->ei_class;
+ ehdr.com.e_ident[EI_DATA] = ELFDATA2LSB;
+ ehdr.com.e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr.com.e_ident[EI_OSABI] = elf_osabi;
+ ehdr.com.e_ident[EI_ABIVERSION] = elf_abiver;
+ ehdr.com.e_type = cpu_to_le16(ET_REL);
+ ehdr.com.e_machine = cpu_to_le16(efmt->e_machine);
+ ehdr.com.e_version = cpu_to_le16(EV_CURRENT);
+
+ if (!efmt->elf64) {
+ ehdr.ehdr32.e_shoff = cpu_to_le32(sizeof ehdr);
+ ehdr.ehdr32.e_ehsize = cpu_to_le16(sizeof(Elf32_Ehdr));
+ ehdr.ehdr32.e_shentsize = cpu_to_le16(sizeof(Elf32_Shdr));
+ ehdr.ehdr32.e_shnum = elf_shndx(nsections, 0);
+ ehdr.ehdr32.e_shstrndx = elf_shndx(sec_shstrtab, SHN_XINDEX);
+ } else {
+ ehdr.ehdr64.e_shoff = cpu_to_le64(sizeof ehdr);
+ ehdr.ehdr64.e_ehsize = cpu_to_le16(sizeof(Elf64_Ehdr));
+ ehdr.ehdr64.e_shentsize = cpu_to_le16(sizeof(Elf64_Shdr));
+ ehdr.ehdr64.e_shnum = elf_shndx(nsections, 0);
+ ehdr.ehdr64.e_shstrndx = elf_shndx(sec_shstrtab, SHN_XINDEX);
+ }
+
+ nasm_write(&ehdr, sizeof(ehdr), ofile);
+ elf_foffs = sizeof ehdr + efmt->shdr_size * nsections;
/*
* Now output the section header table.
*/
-
- elf_foffs = sizeof(Elf64_Ehdr) + (is_elf64() ? sizeof(Elf64_Shdr): sizeof(Elf32_Shdr)) * nsections;
align = ALIGN(elf_foffs, SEC_FILEALIGN) - elf_foffs;
elf_foffs += align;
elf_nsect = 0;
elf_sects = nasm_malloc(sizeof(*elf_sects) * nsections);
/* SHN_UNDEF */
- elf_section_header(0, SHT_NULL, 0, NULL, false, 0, SHN_UNDEF, 0, 0, 0);
+ elf_section_header(0, SHT_NULL, 0, NULL, false,
+ nsections > (int)SHN_LORESERVE ? nsections : 0,
+ sec_shstrtab >= (int)SHN_LORESERVE ? sec_shstrtab : 0,
+ 0, 0, 0);
p = shstrtab + 1;
/* The normal sections */
for (i = 0; i < nsects; i++) {
elf_section_header(p - shstrtab, sects[i]->type, sects[i]->flags,
- (sects[i]->type == SHT_PROGBITS ?
- sects[i]->data : NULL), true,
- sects[i]->len, 0, 0, sects[i]->align, 0);
+ sects[i]->data, true,
+ sects[i]->len, 0, 0,
+ sects[i]->align, sects[i]->entsize);
p += strlen(p) + 1;
}
- /* .shstrtab */
- elf_section_header(p - shstrtab, SHT_STRTAB, 0, shstrtab, false,
- shstrtablen, 0, 0, 1, 0);
- p += strlen(p) + 1;
-
- /* .symtab */
- if (is_elf64())
- elf_section_header(p - shstrtab, SHT_SYMTAB, 0, symtab, true,
- symtablen, sec_strtab, symtablocal, 8, 24);
- else
- elf_section_header(p - shstrtab, SHT_SYMTAB, 0, symtab, true,
- symtablen, sec_strtab, symtablocal, 4, 16);
- p += strlen(p) + 1;
-
- /* .strtab */
- elf_section_header(p - shstrtab, SHT_STRTAB, 0, strs, true,
- strslen, 0, 0, 1, 0);
- p += strlen(p) + 1;
-
- /* The relocation sections */
- if (is_elf32()) {
- for (i = 0; i < nsects; i++) {
- if (sects[i]->head) {
- elf_section_header(p - shstrtab, SHT_REL, 0, sects[i]->rel, true,
- sects[i]->rellen, sec_symtab, i + 1, 4, 8);
- p += strlen(p) + 1;
- }
- }
- } else if (is_elfx32()) {
- for (i = 0; i < nsects; i++) {
- if (sects[i]->head) {
- elf_section_header(p - shstrtab, SHT_RELA, 0, sects[i]->rel, true,
- sects[i]->rellen, sec_symtab, i + 1, 4, 12);
- p += strlen(p) + 1;
- }
- }
- } else {
- nasm_assert(is_elf64());
- for (i = 0; i < nsects; i++) {
- if (sects[i]->head) {
- elf_section_header(p - shstrtab, SHT_RELA, 0, sects[i]->rel, true,
- sects[i]->rellen, sec_symtab, i + 1, 8, 24);
- p += strlen(p) + 1;
- }
- }
- }
-
+ /* The debugging sections */
if (dfmt_is_stabs()) {
/* for debugging information, create the last three sections
which are the .stab , .stabstr and .rel.stab sections respectively */
@@ -1717,7 +1910,7 @@ static void elf_write(void)
if (stabbuf && stabstrbuf && stabrelbuf) {
elf_section_header(p - shstrtab, SHT_PROGBITS, 0, stabbuf, false,
- stablen, sec_stabstr, 0, 4, 12);
+ stablen, sec_stabstr, 0, 4, 12);
p += strlen(p) + 1;
elf_section_header(p - shstrtab, SHT_STRTAB, 0, stabstrbuf, false,
@@ -1725,67 +1918,99 @@ static void elf_write(void)
p += strlen(p) + 1;
/* link -> symtable info -> section to refer to */
- if (is_elf32()) {
- elf_section_header(p - shstrtab, SHT_REL, 0, stabrelbuf, false,
- stabrellen, sec_symtab, sec_stab, 4, 8);
- } else {
- elf_section_header(p - shstrtab, SHT_RELA, 0, stabrelbuf, false,
- stabrellen, sec_symtab, sec_stab, 4, is_elf64() ? 24 : 12);
- }
+ elf_section_header(p - shstrtab, efmt->reltype, 0,
+ stabrelbuf, false, stabrellen,
+ sec_symtab, sec_stab,
+ efmt->word, efmt->rel_size);
p += strlen(p) + 1;
}
} else if (dfmt_is_dwarf()) {
- /* for dwarf debugging information, create the ten dwarf sections */
+ /* for dwarf debugging information, create the ten dwarf sections */
- /* this function call creates the dwarf sections in memory */
- if (dwarf_fsect)
- dwarf_generate();
+ /* this function call creates the dwarf sections in memory */
+ if (dwarf_fsect)
+ dwarf_generate();
- elf_section_header(p - shstrtab, SHT_PROGBITS, 0, arangesbuf, false,
- arangeslen, 0, 0, 1, 0);
- p += strlen(p) + 1;
+ elf_section_header(p - shstrtab, SHT_PROGBITS, 0, arangesbuf, false,
+ arangeslen, 0, 0, 1, 0);
+ p += strlen(p) + 1;
- elf_section_header(p - shstrtab, SHT_RELA, 0, arangesrelbuf, false,
- arangesrellen, sec_symtab,
- is_elf64() ? debug_aranges : sec_debug_aranges,
- 1, is_elf64() ? 24 : 12);
- p += strlen(p) + 1;
+ elf_section_header(p - shstrtab, SHT_RELA, 0, arangesrelbuf, false,
+ arangesrellen, sec_symtab,
+ sec_debug_aranges,
+ efmt->word, efmt->rela_size);
+ p += strlen(p) + 1;
- elf_section_header(p - shstrtab, SHT_PROGBITS, 0, pubnamesbuf,
- false, pubnameslen, 0, 0, 1, 0);
- p += strlen(p) + 1;
+ elf_section_header(p - shstrtab, SHT_PROGBITS, 0, pubnamesbuf,
+ false, pubnameslen, 0, 0, 1, 0);
+ p += strlen(p) + 1;
- elf_section_header(p - shstrtab, SHT_PROGBITS, 0, infobuf, false,
- infolen, 0, 0, 1, 0);
- p += strlen(p) + 1;
+ elf_section_header(p - shstrtab, SHT_PROGBITS, 0, infobuf, false,
+ infolen, 0, 0, 1, 0);
+ p += strlen(p) + 1;
- elf_section_header(p - shstrtab, SHT_RELA, 0, inforelbuf, false,
- inforellen, sec_symtab,
- is_elf64() ? debug_info : sec_debug_info,
- 1, is_elf64() ? 24 : 12);
- p += strlen(p) + 1;
+ elf_section_header(p - shstrtab, SHT_RELA, 0, inforelbuf, false,
+ inforellen, sec_symtab,
+ sec_debug_info,
+ efmt->word, efmt->rela_size);
+ p += strlen(p) + 1;
- elf_section_header(p - shstrtab, SHT_PROGBITS, 0, abbrevbuf, false,
- abbrevlen, 0, 0, 1, 0);
- p += strlen(p) + 1;
+ elf_section_header(p - shstrtab, SHT_PROGBITS, 0, abbrevbuf, false,
+ abbrevlen, 0, 0, 1, 0);
+ p += strlen(p) + 1;
- elf_section_header(p - shstrtab, SHT_PROGBITS, 0, linebuf, false,
- linelen, 0, 0, 1, 0);
- p += strlen(p) + 1;
+ elf_section_header(p - shstrtab, SHT_PROGBITS, 0, linebuf, false,
+ linelen, 0, 0, 1, 0);
+ p += strlen(p) + 1;
- elf_section_header(p - shstrtab, SHT_RELA, 0, linerelbuf, false,
- linerellen, sec_symtab,
- is_elf64() ? debug_line : sec_debug_line,
- 1, is_elf64() ? 24 : 12);
- p += strlen(p) + 1;
+ elf_section_header(p - shstrtab, SHT_RELA, 0, linerelbuf, false,
+ linerellen, sec_symtab,
+ sec_debug_line,
+ efmt->word, efmt->rela_size);
+ p += strlen(p) + 1;
- elf_section_header(p - shstrtab, SHT_PROGBITS, 0, framebuf, false,
- framelen, 0, 0, 8, 0);
- p += strlen(p) + 1;
+ elf_section_header(p - shstrtab, SHT_PROGBITS, 0, framebuf, false,
+ framelen, 0, 0, 8, 0);
+ p += strlen(p) + 1;
+
+ elf_section_header(p - shstrtab, SHT_PROGBITS, 0, locbuf, false,
+ loclen, 0, 0, 1, 0);
+ p += strlen(p) + 1;
+ }
- elf_section_header(p - shstrtab, SHT_PROGBITS, 0, locbuf, false,
- loclen, 0, 0, 1, 0);
+ /* .shstrtab */
+ elf_section_header(p - shstrtab, SHT_STRTAB, 0, shstrtab, false,
+ shstrtablen, 0, 0, 1, 0);
+ p += strlen(p) + 1;
+
+ /* .symtab */
+ elf_section_header(p - shstrtab, SHT_SYMTAB, 0, symtab, true,
+ symtab->datalen, sec_strtab, symtablocal,
+ efmt->word, efmt->sym_size);
+ p += strlen(p) + 1;
+
+ /* .strtab */
+ elf_section_header(p - shstrtab, SHT_STRTAB, 0, strs, true,
+ strslen, 0, 0, 1, 0);
+ p += strlen(p) + 1
+;
+ /* .symtab_shndx */
+ if (symtab_shndx) {
+ elf_section_header(p - shstrtab, SHT_SYMTAB_SHNDX, 0,
+ symtab_shndx, true, symtab_shndx->datalen,
+ sec_symtab, 0, 1, 0);
+ p += strlen(p) + 1;
+ }
+
+ /* The relocation sections */
+ for (i = 0; i < nsects; i++) {
+ if (sects[i]->rel) {
+ elf_section_header(p - shstrtab, efmt->reltype, 0,
+ sects[i]->rel, true, sects[i]->rel->datalen,
+ sec_symtab, sects[i]->shndx,
+ efmt->word, efmt->rel_size);
p += strlen(p) + 1;
+ }
}
fwritezero(align, ofile);
@@ -1796,241 +2021,189 @@ static void elf_write(void)
nasm_free(elf_sects);
saa_free(symtab);
+ if (symtab_shndx)
+ saa_free(symtab_shndx);
}
-static struct SAA *elf_build_symtab(int32_t *len, int32_t *local)
+static size_t nsyms;
+
+static void elf_sym(const struct elf_symbol *sym)
{
- struct SAA *s = saa_init(1L);
- struct elf_symbol *sym;
- int i;
+ int shndx = sym->section;
+
+ /*
+ * Careful here. This relies on sym->section being signed; for
+ * special section indicies this value needs to be cast to
+ * (int16_t) so that it sign-extends, however, here SHN_LORESERVE
+ * is used as an unsigned constant.
+ */
+ if (shndx >= (int)SHN_LORESERVE) {
+ if (unlikely(!symtab_shndx)) {
+ /* Create symtab_shndx and fill previous entries with zero */
+ symtab_shndx = saa_init(1);
+ saa_wbytes(symtab_shndx, NULL, nsyms << 2);
+ }
+ } else {
+ shndx = 0; /* Section index table always write zero */
+ }
+
+ if (symtab_shndx)
+ saa_write32(symtab_shndx, shndx);
+
+ efmt->elf_sym(sym);
+ nsyms++;
+}
+
+static void elf32_sym(const struct elf_symbol *sym)
+{
+ Elf32_Sym sym32;
+
+ sym32.st_name = cpu_to_le32(sym->strpos);
+ sym32.st_value = cpu_to_le32(sym->symv.key);
+ sym32.st_size = cpu_to_le32(sym->size);
+ sym32.st_info = sym->type;
+ sym32.st_other = sym->other;
+ sym32.st_shndx = elf_shndx(sym->section, SHN_XINDEX);
+ saa_wbytes(symtab, &sym32, sizeof sym32);
+}
+
+static void elf64_sym(const struct elf_symbol *sym)
+{
+ Elf64_Sym sym64;
+
+ sym64.st_name = cpu_to_le32(sym->strpos);
+ sym64.st_value = cpu_to_le64(sym->symv.key);
+ sym64.st_size = cpu_to_le64(sym->size);
+ sym64.st_info = sym->type;
+ sym64.st_other = sym->other;
+ sym64.st_shndx = elf_shndx(sym->section, SHN_XINDEX);
+ saa_wbytes(symtab, &sym64, sizeof sym64);
+}
- size_t usize = is_elf64() ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
- union {
- Elf32_Sym sym32;
- Elf64_Sym sym64;
- } u;
+static size_t elf_build_symtab(void)
+{
+ struct elf_symbol *sym, xsym;
+ size_t nlocal;
+ int i;
- *len = *local = 0;
+ symtab = saa_init(1);
+ symtab_shndx = NULL;
/*
* Zero symbol first as required by spec.
*/
- saa_wbytes(s, NULL, usize);
- *len += usize;
- (*local)++;
+ nasm_zero(xsym);
+ elf_sym(&xsym);
/*
* Next, an entry for the file name.
*/
- if (is_elf64()) {
- u.sym64.st_name = cpu_to_le32(1);
- u.sym64.st_info = ELF64_ST_INFO(STB_LOCAL, STT_FILE);
- u.sym64.st_other = 0;
- u.sym64.st_shndx = cpu_to_le16(SHN_ABS);
- u.sym64.st_value = 0;
- u.sym64.st_size = 0;
- } else {
- u.sym32.st_name = cpu_to_le32(1);
- u.sym32.st_value = 0;
- u.sym32.st_size = 0;
- u.sym32.st_info = ELF32_ST_INFO(STB_LOCAL, STT_FILE);
- u.sym32.st_other = 0;
- u.sym32.st_shndx = cpu_to_le16(SHN_ABS);
- }
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
-
+ nasm_zero(xsym);
+ xsym.strpos = 1;
+ xsym.type = ELF32_ST_INFO(STB_LOCAL, STT_FILE);
+ xsym.section = XSHN_ABS;
+ elf_sym(&xsym);
/*
* Now some standard symbols defining the segments, for relocation
* purposes.
*/
- if (is_elf64()) {
- u.sym64.st_name = 0;
- u.sym64.st_other = 0;
- u.sym64.st_value = 0;
- u.sym64.st_size = 0;
- for (i = 1; i <= nsects; i++) {
- u.sym64.st_info = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
- u.sym64.st_shndx = cpu_to_le16(i);
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
- }
- } else {
- u.sym32.st_name = 0;
- u.sym32.st_value = 0;
- u.sym32.st_size = 0;
- u.sym32.st_other = 0;
- for (i = 1; i <= nsects; i++) {
- u.sym32.st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
- u.sym32.st_shndx = cpu_to_le16(i);
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
- }
+ nasm_zero(xsym);
+ for (i = 1; i <= nsects; i++) {
+ xsym.type = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
+ xsym.section = i;
+ elf_sym(&xsym);
+ }
+
+ /*
+ * dwarf needs symbols for debug sections
+ * which are relocation targets.
+ */
+ if (dfmt_is_dwarf()) {
+ dwarf_infosym = nsyms;
+ xsym.section = sec_debug_info;
+ elf_sym(&xsym);
+
+ dwarf_abbrevsym = nsyms;
+ xsym.section = sec_debug_abbrev;
+ elf_sym(&xsym);
+
+ dwarf_linesym = nsyms;
+ xsym.section = sec_debug_line;
+ elf_sym(&xsym);
}
/*
* Now the other local symbols.
*/
saa_rewind(syms);
- if (is_elf64()) {
- while ((sym = saa_rstruct(syms))) {
- if (sym->type & SYM_GLOBAL)
- continue;
- u.sym64.st_name = cpu_to_le32(sym->strpos);
- u.sym64.st_info = sym->type;
- u.sym64.st_other = sym->other;
- u.sym64.st_shndx = cpu_to_le16(sym->section);
- u.sym64.st_value = cpu_to_le64(sym->symv.key);
- u.sym64.st_size = cpu_to_le64(sym->size);
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
- }
- /*
- * dwarf needs symbols for debug sections
- * which are relocation targets.
- */
- if (dfmt_is_dwarf()) {
- dwarf_infosym = *local;
- u.sym64.st_name = 0;
- u.sym64.st_info = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
- u.sym64.st_other = 0;
- u.sym64.st_shndx = cpu_to_le16(debug_info);
- u.sym64.st_value = 0;
- u.sym64.st_size = 0;
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
- dwarf_abbrevsym = *local;
- u.sym64.st_name = 0;
- u.sym64.st_info = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
- u.sym64.st_other = 0;
- u.sym64.st_shndx = cpu_to_le16(debug_abbrev);
- u.sym64.st_value = 0;
- u.sym64.st_size = 0;
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
- dwarf_linesym = *local;
- u.sym64.st_name = 0;
- u.sym64.st_info = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
- u.sym64.st_other = 0;
- u.sym64.st_shndx = cpu_to_le16(debug_line);
- u.sym64.st_value = 0;
- u.sym64.st_size = 0;
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
- }
- } else {
- while ((sym = saa_rstruct(syms))) {
- if (sym->type & SYM_GLOBAL)
- continue;
- u.sym32.st_name = cpu_to_le32(sym->strpos);
- u.sym32.st_value = cpu_to_le32(sym->symv.key);
- u.sym32.st_size = cpu_to_le32(sym->size);
- u.sym32.st_info = sym->type;
- u.sym32.st_other = sym->other;
- u.sym32.st_shndx = cpu_to_le16(sym->section);
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
- }
- /*
- * dwarf needs symbols for debug sections
- * which are relocation targets.
- */
- if (dfmt_is_dwarf()) {
- dwarf_infosym = *local;
- u.sym32.st_name = 0;
- u.sym32.st_value = 0;
- u.sym32.st_size = 0;
- u.sym32.st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
- u.sym32.st_other = 0;
- u.sym32.st_shndx = cpu_to_le16(sec_debug_info);
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
- dwarf_abbrevsym = *local;
- u.sym32.st_name = 0;
- u.sym32.st_value = 0;
- u.sym32.st_size = 0;
- u.sym32.st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
- u.sym32.st_other = 0;
- u.sym32.st_shndx = cpu_to_le16(sec_debug_abbrev);
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
- dwarf_linesym = *local;
- u.sym32.st_name = 0;
- u.sym32.st_value = 0;
- u.sym32.st_size = 0;
- u.sym32.st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
- u.sym32.st_other = 0;
- u.sym32.st_shndx = cpu_to_le16(sec_debug_line);
- saa_wbytes(s, &u, usize);
- *len += usize;
- (*local)++;
- }
+ while ((sym = saa_rstruct(syms))) {
+ if (sym->type & SYM_GLOBAL)
+ continue;
+
+ elf_sym(sym);
}
+ nlocal = nsyms;
+
/*
* Now the global symbols.
*/
saa_rewind(syms);
- if (is_elf64()) {
- while ((sym = saa_rstruct(syms))) {
- if (!(sym->type & SYM_GLOBAL))
- continue;
- u.sym64.st_name = cpu_to_le32(sym->strpos);
- u.sym64.st_info = sym->type;
- u.sym64.st_other = sym->other;
- u.sym64.st_shndx = cpu_to_le16(sym->section);
- u.sym64.st_value = cpu_to_le64(sym->symv.key);
- u.sym64.st_size = cpu_to_le64(sym->size);
- saa_wbytes(s, &u, usize);
- *len += usize;
- }
- } else {
- while ((sym = saa_rstruct(syms))) {
- if (!(sym->type & SYM_GLOBAL))
- continue;
- u.sym32.st_name = cpu_to_le32(sym->strpos);
- u.sym32.st_value = cpu_to_le32(sym->symv.key);
- u.sym32.st_size = cpu_to_le32(sym->size);
- u.sym32.st_info = sym->type;
- u.sym32.st_other = sym->other;
- u.sym32.st_shndx = cpu_to_le16(sym->section);
- saa_wbytes(s, &u, usize);
- *len += usize;
- }
+ while ((sym = saa_rstruct(syms))) {
+ if (!(sym->type & SYM_GLOBAL))
+ continue;
+
+ elf_sym(sym);
}
- return s;
+ return nlocal;
}
-static struct SAA *elf_build_reltab(uint64_t *len, struct elf_reloc *r)
+static struct SAA *elf32_build_reltab(const struct elf_reloc *r)
{
struct SAA *s;
int32_t global_offset;
+ Elf32_Rel rel32;
- size_t usize = is_elf64() ? sizeof(Elf64_Rela) :
- (is_elfx32() ? sizeof(Elf32_Rela) : sizeof(Elf32_Rel));
- union {
- Elf32_Rel rel32;
- Elf32_Rela rela32;
- Elf64_Rela rela64;
- } u;
+ if (!r)
+ return NULL;
+
+ s = saa_init(1L);
+
+ /*
+ * How to onvert from a global placeholder to a real symbol index;
+ * the +2 refers to the two special entries, the null entry and
+ * the filename entry.
+ */
+ global_offset = -GLOBAL_TEMP_BASE + nsects + nlocals + ndebugs + 2;
+
+ while (r) {
+ int32_t sym = r->symbol;
+
+ if (sym >= GLOBAL_TEMP_BASE)
+ sym += global_offset;
+
+ rel32.r_offset = cpu_to_le32(r->address);
+ rel32.r_info = cpu_to_le32(ELF32_R_INFO(sym, r->type));
+ saa_wbytes(s, &rel32, sizeof rel32);
+
+ r = r->next;
+ }
+
+ return s;
+}
+
+static struct SAA *elfx32_build_reltab(const struct elf_reloc *r)
+{
+ struct SAA *s;
+ int32_t global_offset;
+ Elf32_Rela rela32;
if (!r)
return NULL;
s = saa_init(1L);
- *len = 0;
/*
* How to onvert from a global placeholder to a real symbol index;
@@ -2039,51 +2212,53 @@ static struct SAA *elf_build_reltab(uint64_t *len, struct elf_reloc *r)
*/
global_offset = -GLOBAL_TEMP_BASE + nsects + nlocals + ndebugs + 2;
- if (is_elf32()) {
- while (r) {
- int32_t sym = r->symbol;
+ while (r) {
+ int32_t sym = r->symbol;
- if (sym >= GLOBAL_TEMP_BASE)
- sym += global_offset;
+ if (sym >= GLOBAL_TEMP_BASE)
+ sym += global_offset;
- u.rel32.r_offset = cpu_to_le32(r->address);
- u.rel32.r_info = cpu_to_le32(ELF32_R_INFO(sym, r->type));
- saa_wbytes(s, &u, usize);
- *len += usize;
+ rela32.r_offset = cpu_to_le32(r->address);
+ rela32.r_info = cpu_to_le32(ELF32_R_INFO(sym, r->type));
+ rela32.r_addend = cpu_to_le32(r->offset);
+ saa_wbytes(s, &rela32, sizeof rela32);
- r = r->next;
- }
- } else if (is_elfx32()) {
- while (r) {
- int32_t sym = r->symbol;
+ r = r->next;
+ }
- if (sym >= GLOBAL_TEMP_BASE)
- sym += global_offset;
+ return s;
+}
- u.rela32.r_offset = cpu_to_le32(r->address);
- u.rela32.r_info = cpu_to_le32(ELF32_R_INFO(sym, r->type));
- u.rela32.r_addend = cpu_to_le32(r->offset);
- saa_wbytes(s, &u, usize);
- *len += usize;
+static struct SAA *elf64_build_reltab(const struct elf_reloc *r)
+{
+ struct SAA *s;
+ int32_t global_offset;
+ Elf64_Rela rela64;
- r = r->next;
- }
- } else {
- nasm_assert(is_elf64());
- while (r) {
- int32_t sym = r->symbol;
+ if (!r)
+ return NULL;
+
+ s = saa_init(1L);
+
+ /*
+ * How to onvert from a global placeholder to a real symbol index;
+ * the +2 refers to the two special entries, the null entry and
+ * the filename entry.
+ */
+ global_offset = -GLOBAL_TEMP_BASE + nsects + nlocals + ndebugs + 2;
- if (sym >= GLOBAL_TEMP_BASE)
- sym += global_offset;
+ while (r) {
+ int32_t sym = r->symbol;
- u.rela64.r_offset = cpu_to_le64(r->address);
- u.rela64.r_info = cpu_to_le64(ELF64_R_INFO(sym, r->type));
- u.rela64.r_addend = cpu_to_le64(r->offset);
- saa_wbytes(s, &u, usize);
- *len += usize;
+ if (sym >= GLOBAL_TEMP_BASE)
+ sym += global_offset;
- r = r->next;
- }
+ rela64.r_offset = cpu_to_le64(r->address);
+ rela64.r_info = cpu_to_le64(ELF64_R_INFO(sym, r->type));
+ rela64.r_addend = cpu_to_le64(r->offset);
+ saa_wbytes(s, &rela64, sizeof rela64);
+
+ r = r->next;
}
return s;
@@ -2091,49 +2266,49 @@ static struct SAA *elf_build_reltab(uint64_t *len, struct elf_reloc *r)
static void elf_section_header(int name, int type, uint64_t flags,
void *data, bool is_saa, uint64_t datalen,
- int link, int info, int align, int eltsize)
+ int link, int info,
+ uint64_t align, uint64_t entsize)
{
- union {
- Elf32_Shdr shdr32;
- Elf64_Shdr shdr64;
- } shdr;
-
elf_sects[elf_nsect].data = data;
elf_sects[elf_nsect].len = datalen;
elf_sects[elf_nsect].is_saa = is_saa;
elf_nsect++;
- if (is_elf32() || is_elfx32()) {
- shdr.shdr32.sh_name = cpu_to_le32(name);
- shdr.shdr32.sh_type = cpu_to_le32(type);
- shdr.shdr32.sh_flags = cpu_to_le32(flags);
- shdr.shdr32.sh_addr = 0;
- shdr.shdr32.sh_offset = cpu_to_le32(type == SHT_NULL ? 0 : elf_foffs);
- shdr.shdr32.sh_size = cpu_to_le32(datalen);
+ if (!efmt->elf64) {
+ Elf32_Shdr shdr;
+
+ shdr.sh_name = cpu_to_le32(name);
+ shdr.sh_type = cpu_to_le32(type);
+ shdr.sh_flags = cpu_to_le32(flags);
+ shdr.sh_addr = 0;
+ shdr.sh_offset = cpu_to_le32(type == SHT_NULL ? 0 : elf_foffs);
+ shdr.sh_size = cpu_to_le32(datalen);
if (data)
elf_foffs += ALIGN(datalen, SEC_FILEALIGN);
- shdr.shdr32.sh_link = cpu_to_le32(link);
- shdr.shdr32.sh_info = cpu_to_le32(info);
- shdr.shdr32.sh_addralign = cpu_to_le32(align);
- shdr.shdr32.sh_entsize = cpu_to_le32(eltsize);
- } else {
- nasm_assert(is_elf64());
+ shdr.sh_link = cpu_to_le32(link);
+ shdr.sh_info = cpu_to_le32(info);
+ shdr.sh_addralign = cpu_to_le32(align);
+ shdr.sh_entsize = cpu_to_le32(entsize);
- shdr.shdr64.sh_name = cpu_to_le32(name);
- shdr.shdr64.sh_type = cpu_to_le32(type);
- shdr.shdr64.sh_flags = cpu_to_le64(flags);
- shdr.shdr64.sh_addr = 0;
- shdr.shdr64.sh_offset = cpu_to_le64(type == SHT_NULL ? 0 : elf_foffs);
- shdr.shdr64.sh_size = cpu_to_le32(datalen);
+ nasm_write(&shdr, sizeof shdr, ofile);
+ } else {
+ Elf64_Shdr shdr;
+
+ shdr.sh_name = cpu_to_le32(name);
+ shdr.sh_type = cpu_to_le32(type);
+ shdr.sh_flags = cpu_to_le64(flags);
+ shdr.sh_addr = 0;
+ shdr.sh_offset = cpu_to_le64(type == SHT_NULL ? 0 : elf_foffs);
+ shdr.sh_size = cpu_to_le64(datalen);
if (data)
elf_foffs += ALIGN(datalen, SEC_FILEALIGN);
- shdr.shdr64.sh_link = cpu_to_le32(link);
- shdr.shdr64.sh_info = cpu_to_le32(info);
- shdr.shdr64.sh_addralign = cpu_to_le64(align);
- shdr.shdr64.sh_entsize = cpu_to_le64(eltsize);
- }
+ shdr.sh_link = cpu_to_le32(link);
+ shdr.sh_info = cpu_to_le32(info);
+ shdr.sh_addralign = cpu_to_le64(align);
+ shdr.sh_entsize = cpu_to_le64(entsize);
- nasm_write(&shdr, is_elf64() ? sizeof(shdr.shdr64) : sizeof(shdr.shdr32), ofile);
+ nasm_write(&shdr, sizeof shdr, ofile);
+ }
}
static void elf_write_sections(void)
@@ -2166,15 +2341,9 @@ static void elf_sect_writeaddr(struct elf_section *sect, int64_t data, size_t le
static void elf_sectalign(int32_t seg, unsigned int value)
{
- struct elf_section *s = NULL;
- int i;
+ struct elf_section *s;
- for (i = 0; i < nsects; i++) {
- if (sects[i]->index == seg) {
- s = sects[i];
- break;
- }
- }
+ s = raa_read_ptr(section_by_index, seg >> 1);
if (!s || !is_power2(value))
return;
@@ -2230,7 +2399,7 @@ const struct ofmt of_elf32 = {
elf32_debugs_arr,
&elf32_df_stabs,
elf_stdmac,
- elf_init,
+ elf32_init,
null_reset,
nasm_do_legacy_output,
elf32_out,
@@ -2282,7 +2451,7 @@ const struct ofmt of_elf64 = {
elf64_debugs_arr,
&elf64_df_stabs,
elf_stdmac,
- elf_init,
+ elf64_init,
null_reset,
nasm_do_legacy_output,
elf64_out,
@@ -2334,7 +2503,7 @@ const struct ofmt of_elfx32 = {
elfx32_debugs_arr,
&elfx32_df_stabs,
elf_stdmac,
- elf_init,
+ elfx32_init,
null_reset,
nasm_do_legacy_output,
elfx32_out,
diff --git a/output/outelf.h b/output/outelf.h
index 0801eaf8..f5ccfe1c 100644
--- a/output/outelf.h
+++ b/output/outelf.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2019 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -53,31 +53,14 @@
/* this stuff is needed for the dwarf/stabs debugging format */
#define TY_DEBUGSYMLIN 0x40 /* internal call to debug_out */
-/* Known sections with nonstandard defaults */
-struct elf_known_section {
- const char *name; /* Name of section */
- int type; /* Section type (SHT_) */
- uint32_t flags; /* Section flags (SHF_) */
- uint32_t align; /* Section alignment */
-};
-extern const struct elf_known_section elf_known_sections[];
-
-/*
- * Special ELF sections (after the real sections but before debugging ones)
- */
-#define sec_shstrtab (nsects + 1)
-#define sec_symtab (nsects + 2)
-#define sec_strtab (nsects + 3)
-#define sec_numspecial 3
-
/*
- * Debugging ELF sections (last in the file)
+ * Debugging ELF sections (section indicies starting with sec_debug)
*/
/* stabs */
-#define sec_stab (nsections-3)
-#define sec_stabstr (nsections-2)
-#define sec_rel_stab (nsections-1)
+#define sec_stab (sec_debug + 0)
+#define sec_stabstr (sec_debug + 1)
+#define sec_rel_stab (sec_debug + 2)
/* stabs symbol table format */
struct stabentry {
@@ -89,16 +72,16 @@ struct stabentry {
};
/* dwarf */
-#define sec_debug_aranges (nsections-10)
-#define sec_rela_debug_aranges (nsections-9)
-#define sec_debug_pubnames (nsections-8)
-#define sec_debug_info (nsections-7)
-#define sec_rela_debug_info (nsections-6)
-#define sec_debug_abbrev (nsections-5)
-#define sec_debug_line (nsections-4)
-#define sec_rela_debug_line (nsections-3)
-#define sec_debug_frame (nsections-2)
-#define sec_debug_loc (nsections-1)
+#define sec_debug_aranges (sec_debug + 0)
+#define sec_rela_debug_aranges (sec_debug + 1)
+#define sec_debug_pubnames (sec_debug + 2)
+#define sec_debug_info (sec_debug + 3)
+#define sec_rela_debug_info (sec_debug + 4)
+#define sec_debug_abbrev (sec_debug + 5)
+#define sec_debug_line (sec_debug + 6)
+#define sec_rela_debug_line (sec_debug + 7)
+#define sec_debug_frame (sec_debug + 8)
+#define sec_debug_loc (sec_debug + 9)
extern uint8_t elf_osabi;
extern uint8_t elf_abiver;
@@ -137,14 +120,15 @@ struct elf_section {
uint64_t len;
uint64_t size;
uint64_t nrelocs;
- int32_t index;
- int type; /* SHT_PROGBITS or SHT_NOBITS */
+ int32_t index; /* NASM index or NO_SEG if internal */
+ int shndx; /* ELF index */
+ int type; /* SHT_* */
uint64_t align; /* alignment: power of two */
uint64_t flags; /* section flags */
int64_t pass_last_seen;
+ uint64_t entsize; /* entry size */
char *name;
struct SAA *rel;
- uint64_t rellen;
struct elf_reloc *head;
struct elf_reloc **tail;
struct rbtree *gsyms; /* global symbols in section */