elf_section_index symtab_idx,
elf_section_index sindex);
+typedef void(*func_handle_reloc_addend)(yasm_intnum *intn,
+ elf_reloc_entry *reloc);
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,
typedef struct {
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;
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_reloc_entry *reloc;
elf_objfmt_output_info *info = d;
- yasm_intnum *zero = yasm_intnum_create_uint(0);
+ yasm_intnum *zero;
int retval;
reloc = elf_reloc_entry_create(sym,
yasm__error(bc->line, N_("elf: invalid relocation size"));
return 1;
}
- /* allocate .rel sections on a need-basis */
+ /* allocate .rel[a] sections on a need-basis */
if (elf_secthead_append_reloc(info->sect, info->shead, reloc))
info->objfmt_elf->parse_scnum++;
+ zero = yasm_intnum_create_uint(0);
+ elf_handle_reloc_addend(zero, reloc);
retval = yasm_arch_intnum_tobytes(info->objfmt_elf->arch, zero, buf,
destsize, valsize, 0, bc, rel, warn,
bc->line);
/*@null@*/ void *d)
{
/*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
/*@dependent@*/ /*@null@*/ const yasm_floatnum *flt;
/*@dependent@*/ /*@null@*/ yasm_symrec *sym;
+ /*@null@*/ elf_reloc_entry *reloc = NULL;
if (info == NULL)
yasm_internal_error("null info struct");
/* Handle integer expressions, with relocation if necessary */
sym = yasm_expr_extract_symrec(ep, 1, yasm_common_calc_bc_dist);
if (sym) {
- elf_reloc_entry *reloc;
yasm_sym_vis vis;
vis = yasm_symrec_get_visibility(sym);
yasm__error(bc->line, N_("elf: invalid relocation size"));
return 1;
}
- /* allocate .rel sections on a need-basis */
+ /* allocate .rel[a] sections on a need-basis */
if (elf_secthead_append_reloc(info->sect, info->shead, reloc))
info->objfmt_elf->parse_scnum++;
}
intn = yasm_expr_get_intnum(ep, NULL);
+ if (intn && reloc)
+ elf_handle_reloc_addend(intn, reloc);
if (intn)
return yasm_arch_intnum_tobytes(info->objfmt_elf->arch, intn, buf,
destsize, valsize, shift, bc, rel,
return 0;
elf_secthead_set_rel_index(shead, ++info->sindex);
- /* name the relocation section .rel.foo */
+ /* name the relocation section .rel[a].foo */
sectname = yasm_section_get_name(sect);
- relname = yasm_xmalloc(strlen(sectname)+5);
- strcpy(relname, ".rel");
- strcat(relname, sectname);
+ relname = elf_secthead_name_reloc_section(sectname);
elf_secthead_set_rel_name(shead,
- elf_strtab_append_str(info->objfmt_elf->shstrtab,
- relname));
+ elf_strtab_append_str(info->objfmt_elf->shstrtab, relname));
yasm_xfree(relname);
return 0;
/* output strtab headers here? */
- /* relocation entries for .foo are stored in section .rel.foo */
+ /* 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++;
yasm_intnum *relocsize;
YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0);
- YASM_WRITE_32_L(bufp, SHT_REL);
+ YASM_WRITE_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(RELOC64_SIZE);
+ relocsize = yasm_intnum_create_uint(RELOC64A_SIZE);
yasm_intnum_calc(relocsize, YASM_EXPR_MUL, nreloc, 0);
YASM_WRITE_64I_L(bufp, relocsize); /* size */
yasm_intnum_destroy(nreloc);
YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */
YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */
YASM_WRITE_64Z_L(bufp, RELOC64_ALIGN); /* align */
- YASM_WRITE_64Z_L(bufp, RELOC64_SIZE); /* entity size */
+ YASM_WRITE_64Z_L(bufp, RELOC64A_SIZE); /* entity size */
+}
+
+static void
+elf_x86_amd64_handle_reloc_addend(yasm_intnum *intn, elf_reloc_entry *reloc)
+{
+ /* .rela: copy value out as addend, replace original with 0 */
+ reloc->addend = yasm_intnum_copy(intn);
+ yasm_intnum_zero(intn);
}
static unsigned int
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);
+ YASM_WRITE_64I_L(bufp, reloc->addend);
}
static void
const elf_machine_handler
elf_machine_handler_x86_amd64 = {
- "x86", "amd64",
- SYMTAB64_SIZE, SYMTAB64_ALIGN, RELOC64_SIZE, SHDR64_SIZE, EHDR64_SIZE,
+ "x86", "amd64", ".rela",
+ SYMTAB64_SIZE, SYMTAB64_ALIGN, RELOC64A_SIZE, SHDR64_SIZE, EHDR64_SIZE,
elf_x86_amd64_accepts_reloc_size,
elf_x86_amd64_write_symtab_entry,
elf_x86_amd64_write_secthead,
elf_x86_amd64_write_secthead_rel,
+ elf_x86_amd64_handle_reloc_addend,
elf_x86_amd64_map_reloc_info_to_type,
elf_x86_amd64_write_reloc,
elf_x86_amd64_write_proghead
YASM_WRITE_32_L(bufp, RELOC32_SIZE); /* entity size */
}
+static void
+elf_x86_x86_handle_reloc_addend(yasm_intnum *intn, elf_reloc_entry *reloc)
+{
+ return; /* .rel: Leave addend in intn */
+}
+
static unsigned int
elf_x86_x86_map_reloc_info_to_type(elf_reloc_entry *reloc)
{
const elf_machine_handler
elf_machine_handler_x86_x86 = {
- "x86", "x86",
+ "x86", "x86", ".rel",
SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32_SIZE, SHDR32_SIZE, EHDR32_SIZE,
elf_x86_x86_accepts_reloc_size,
elf_x86_x86_write_symtab_entry,
elf_x86_x86_write_secthead,
elf_x86_x86_write_secthead_rel,
+ elf_x86_x86_handle_reloc_addend,
elf_x86_x86_map_reloc_info_to_type,
elf_x86_x86_write_reloc,
elf_x86_x86_write_proghead
&elf_machine_handler_x86_amd64,
NULL
};
-static elf_machine_handler const *elf_march;
+static const elf_machine_handler elf_null_machine = {0};
+static elf_machine_handler const *elf_march = &elf_null_machine;
int
elf_set_arch(yasm_arch *arch)
return NULL;
}
- entry = yasm_xmalloc(sizeof(elf_reloc_entry));
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;
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)
yasm_internal_error("reloc is null");
shead->nreloc++;
- yasm_section_add_reloc(sect, (yasm_reloc *)reloc, yasm_xfree);
+ yasm_section_add_reloc(sect, (yasm_reloc *)reloc, elf_reloc_entry_destroy);
return new_sect;
}
+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
+ {
+ int 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)
+{
+ if (!elf_march->handle_reloc_addend)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ elf_march->handle_reloc_addend(intn, reloc);
+}
+
unsigned long
elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab_idx,
yasm_section *sect, elf_secthead *shead,
#define SYMTAB64_ALIGN 8
#define RELOC32_SIZE 8
+#define RELOC32A_SIZE 12
#define RELOC64_SIZE 16
-#define RELOC_MAXSIZE 16
+#define RELOC64A_SIZE 24
+#define RELOC_MAXSIZE 24
#define RELOC32_ALIGN 4
#define RELOC64_ALIGN 8
yasm_reloc reloc;
int rtype_rel;
size_t valsize;
+ yasm_intnum *addend;
};
STAILQ_HEAD(elf_strtab_head, elf_strtab_entry);
yasm_intnum *addr,
int rel,
size_t valsize);
+void elf_reloc_entry_destroy(void *entry);
/* strtab functions */
elf_strtab_entry *elf_strtab_entry_create(const char *str);
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 elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab,
yasm_section *sect,
elf_secthead *esd,
00
00
00
-30
+40
01
00
00
00
8b
05
-fc
+fa
ff
ff
ff
e8
-fc
+fb
ff
ff
ff
00
00
00
+00
+00
+00
+00
+00
+00
+00
+00
14
00
00
00
00
00
+02
+00
+00
+00
+00
+00
+00
+00
19
00
00
00
00
00
+01
+00
+00
+00
+00
+00
+00
+00
00
2e
74
72
65
6c
+61
2e
74
65
62
00
00
-00
2d
00
73
00
00
00
-00
-00
-00
-00
-00
-00
-00
-00
-21
+22
00
00
00
00
00
00
-90
+a8
00
00
00
00
00
00
-2b
+2c
00
00
00
00
00
00
-11
+12
00
00
00
00
00
00
-bc
+d4
00
00
00
00
00
00
-19
+1a
00
00
00
00
00
00
-c4
+dc
00
00
00
00
00
00
-09
+04
00
00
00
00
00
00
-30
+48
00
00
00
00
00
00
-10
+18
00
00
00