From: Michael Urman Date: Mon, 11 Oct 2004 03:47:28 +0000 (-0000) Subject: Enable machine specific handling of relocation section type, since amd64 X-Git-Tag: v0.4.0~11 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9974f8f4eb877748cb6540ff49aea9f93327751e;p=yasm Enable machine specific handling of relocation section type, since amd64 should use .rela.* instead of .rel.* sections, of type SHT_RELA instead of SHT_REL. * elf.h, elf.c: update calls to backend, passing relocations further in. * elf-machine.h, elf-x86-amd64.c, elf-x86-x86.c: add support for setting relocation section name, type, and update amd64 to write RELA records. Also when creating a relocation and writing a value to the file, have it handled here to keep REL vs RELA distinctions hidden from elf.c. * elf-rip.hex: update output to match new section type and data output. svn path=/trunk/yasm/; revision=1160 --- diff --git a/modules/objfmts/elf/elf-machine.h b/modules/objfmts/elf/elf-machine.h index 934235a7..edc3f10f 100644 --- a/modules/objfmts/elf/elf-machine.h +++ b/modules/objfmts/elf/elf-machine.h @@ -55,6 +55,8 @@ typedef void(*func_write_secthead_rel)(unsigned char *bufp, 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, @@ -68,6 +70,7 @@ typedef void (*func_write_proghead)(unsigned char **bufpp, 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; @@ -77,6 +80,7 @@ typedef struct { 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; diff --git a/modules/objfmts/elf/elf-objfmt.c b/modules/objfmts/elf/elf-objfmt.c index 1d12c5ba..78861b61 100644 --- a/modules/objfmts/elf/elf-objfmt.c +++ b/modules/objfmts/elf/elf-objfmt.c @@ -208,7 +208,7 @@ elf_objfmt_output_reloc(yasm_symrec *sym, yasm_bytecode *bc, { 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, @@ -217,10 +217,12 @@ elf_objfmt_output_reloc(yasm_symrec *sym, yasm_bytecode *bc, 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); @@ -235,9 +237,10 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize, /*@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"); @@ -257,7 +260,6 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize, /* 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); @@ -294,12 +296,14 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize, 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, @@ -466,14 +470,11 @@ elf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d) 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; @@ -500,7 +501,7 @@ elf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d) /* 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++; diff --git a/modules/objfmts/elf/elf-x86-amd64.c b/modules/objfmts/elf/elf-x86-amd64.c index be056153..56121ba6 100644 --- a/modules/objfmts/elf/elf-x86-amd64.c +++ b/modules/objfmts/elf/elf-x86-amd64.c @@ -99,13 +99,13 @@ elf_x86_amd64_write_secthead_rel(unsigned char *bufp, 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); @@ -114,7 +114,15 @@ elf_x86_amd64_write_secthead_rel(unsigned char *bufp, 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 @@ -146,6 +154,7 @@ elf_x86_amd64_write_reloc(unsigned char *bufp, elf_reloc_entry *reloc, 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 @@ -183,12 +192,13 @@ elf_x86_amd64_write_proghead(unsigned char **bufpp, 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 diff --git a/modules/objfmts/elf/elf-x86-x86.c b/modules/objfmts/elf/elf-x86-x86.c index 1e926a8e..dd0e08aa 100644 --- a/modules/objfmts/elf/elf-x86-x86.c +++ b/modules/objfmts/elf/elf-x86-x86.c @@ -110,6 +110,12 @@ elf_x86_x86_write_secthead_rel(unsigned char *bufp, 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) { @@ -156,12 +162,13 @@ elf_x86_x86_write_proghead(unsigned char **bufpp, 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 diff --git a/modules/objfmts/elf/elf.c b/modules/objfmts/elf/elf.c index 6b4ccd54..7d63be49 100644 --- a/modules/objfmts/elf/elf.c +++ b/modules/objfmts/elf/elf.c @@ -61,7 +61,8 @@ static const elf_machine_handler *elf_machine_handlers[] = &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) @@ -100,18 +101,27 @@ elf_reloc_entry_create(yasm_symrec *sym, 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) @@ -565,11 +575,37 @@ elf_secthead_append_reloc(yasm_section *sect, elf_secthead *shead, 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, diff --git a/modules/objfmts/elf/elf.h b/modules/objfmts/elf/elf.h index 55fa8db4..c3cacd29 100644 --- a/modules/objfmts/elf/elf.h +++ b/modules/objfmts/elf/elf.h @@ -222,8 +222,10 @@ typedef enum { #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 @@ -305,6 +307,7 @@ struct elf_reloc_entry { yasm_reloc reloc; int rtype_rel; size_t valsize; + yasm_intnum *addend; }; STAILQ_HEAD(elf_strtab_head, elf_strtab_entry); @@ -342,6 +345,7 @@ elf_reloc_entry *elf_reloc_entry_create(yasm_symrec *sym, 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); @@ -403,6 +407,8 @@ 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 elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab, yasm_section *sect, elf_secthead *esd, diff --git a/modules/objfmts/elf/tests/amd64/elf-rip.hex b/modules/objfmts/elf/tests/amd64/elf-rip.hex index 416e4150..9e68a15d 100644 --- a/modules/objfmts/elf/tests/amd64/elf-rip.hex +++ b/modules/objfmts/elf/tests/amd64/elf-rip.hex @@ -38,7 +38,7 @@ 00 00 00 -30 +40 01 00 00 @@ -82,12 +82,12 @@ 00 8b 05 -fc +fa ff ff ff e8 -fc +fb ff ff ff @@ -110,6 +110,14 @@ ff 00 00 00 +00 +00 +00 +00 +00 +00 +00 +00 14 00 00 @@ -126,6 +134,14 @@ ff 00 00 00 +02 +00 +00 +00 +00 +00 +00 +00 19 00 00 @@ -142,6 +158,14 @@ ff 00 00 00 +01 +00 +00 +00 +00 +00 +00 +00 00 2e 74 @@ -153,6 +177,7 @@ ff 72 65 6c +61 2e 74 65 @@ -186,7 +211,6 @@ ff 62 00 00 -00 2d 00 73 @@ -358,15 +382,7 @@ ff 00 00 00 -00 -00 -00 -00 -00 -00 -00 -00 -21 +22 00 00 00 @@ -390,7 +406,7 @@ ff 00 00 00 -90 +a8 00 00 00 @@ -398,7 +414,7 @@ ff 00 00 00 -2b +2c 00 00 00 @@ -430,7 +446,7 @@ ff 00 00 00 -11 +12 00 00 00 @@ -454,7 +470,7 @@ ff 00 00 00 -bc +d4 00 00 00 @@ -494,7 +510,7 @@ bc 00 00 00 -19 +1a 00 00 00 @@ -518,7 +534,7 @@ bc 00 00 00 -c4 +dc 00 00 00 @@ -626,7 +642,7 @@ c4 00 00 00 -09 +04 00 00 00 @@ -654,7 +670,7 @@ c4 00 00 00 -30 +48 00 00 00 @@ -678,7 +694,7 @@ c4 00 00 00 -10 +18 00 00 00