]> granicus.if.org Git - yasm/commitdiff
Enable machine specific handling of relocation section type, since amd64
authorMichael Urman <mu@tortall.net>
Mon, 11 Oct 2004 03:47:28 +0000 (03:47 -0000)
committerMichael Urman <mu@tortall.net>
Mon, 11 Oct 2004 03:47:28 +0000 (03:47 -0000)
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

modules/objfmts/elf/elf-machine.h
modules/objfmts/elf/elf-objfmt.c
modules/objfmts/elf/elf-x86-amd64.c
modules/objfmts/elf/elf-x86-x86.c
modules/objfmts/elf/elf.c
modules/objfmts/elf/elf.h
modules/objfmts/elf/tests/amd64/elf-rip.hex

index 934235a7e02f494f6a0879fe380965cec4ce3fa1..edc3f10f03b9b11a4d956e78dae146395acc77bc 100644 (file)
@@ -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;
index 1d12c5bab8e6d430d7d11a2da1adfaf9b7d8f8bb..78861b61517f59a00efacb518365f8ca20ea716c 100644 (file)
@@ -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++;
index be05615366c44b7b0fec8a79650ec682e63a7826..56121ba6bec7d11fe6d1d3dcec6e2e87a635f268 100644 (file)
@@ -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
index 1e926a8e338871bda9647f4f5fe001dd05561edf..dd0e08aaf68198e487ceca340892f38ae0800f53 100644 (file)
@@ -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
index 6b4ccd54541f6794a9e5b2e6a7c2720904db41a4..7d63be490e0eae38f25670fbb672079ed2a5a8ee 100644 (file)
@@ -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,
index 55fa8db44673afb417d56ce926670520f578cade..c3cacd2941ab13c551e2466b4702e8c51e4cdf88 100644 (file)
@@ -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,
index 416e4150e1507602bc85361b3721a9021967be4c..9e68a15d08ae187a4a64e762e8a2db31143eda51 100644 (file)
@@ -38,7 +38,7 @@
 00 
 00 
 00 
-3
+4
 01 
 00 
 00 
 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