]> granicus.if.org Git - yasm/commitdiff
Move elf relocation valsize handling to the backend.
authorMichael Urman <mu@tortall.net>
Sat, 2 Aug 2003 21:50:42 +0000 (21:50 -0000)
committerMichael Urman <mu@tortall.net>
Sat, 2 Aug 2003 21:50:42 +0000 (21:50 -0000)
Add elf x86 test case to verify it works properly.
Unsure about elf x86-64 status (relocations segfault my objdump), but
 it's no *worse* than last commit.

svn path=/trunk/yasm/; revision=1029

modules/objfmts/elf/elf-objfmt.c
modules/objfmts/elf/elf.c
modules/objfmts/elf/elf.h
modules/objfmts/elf/tests/Makefile.inc
modules/objfmts/elf/tests/elfreloc-err.asm [new file with mode: 0644]
modules/objfmts/elf/tests/elfreloc-err.errwarn [new file with mode: 0644]

index 3207cd8a093c579490d747d7cf5c43ef4bffc4f6..de10a5bfbee68d859505b96cf1269a1f28d8346a 100644 (file)
@@ -207,12 +207,6 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
        elf_reloc_entry *reloc;
        yasm_sym_vis vis;
 
-       /* XXX: this can't be platform portable */
-       if (valsize != 32) {
-           yasm__error(bc->line, N_("elf: invalid relocation size"));
-           return 1;
-       }
-
        vis = yasm_symrec_get_visibility(sym);
        if (!(vis & (YASM_SYM_COMMON|YASM_SYM_EXTERN)))
        {
@@ -240,7 +234,11 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
            *ep = yasm_expr_simplify(*ep, yasm_common_calc_bc_dist);
        }
 
-       reloc = elf_reloc_entry_new(sym, bc->offset + offset, rel);
+       reloc = elf_reloc_entry_new(sym, bc->offset + offset, rel, valsize);
+       if (reloc == NULL) {
+           yasm__error(bc->line, N_("elf: invalid relocation size"));
+           return 1;
+       }
        /* allocate .rel sections on a need-basis */
        if (elf_secthead_append_reloc(info->shead, reloc))
            elf_objfmt_parse_scnum++;
index d8b7a872d0254bb37aee296a0028d6dfb66e1a79..b071dfb47146faba6b2fa32bed459dabc5ce8d3e 100644 (file)
@@ -76,16 +76,33 @@ elf_set_arch(yasm_arch *arch, const char *machine)
 elf_reloc_entry *
 elf_reloc_entry_new(yasm_symrec *sym,
                    elf_address addr,
-                   int rel)
-{
-    elf_reloc_entry *entry = yasm_xmalloc(sizeof(elf_reloc_entry));
+                   int rel,
+                   size_t valsize)
+{
+    elf_reloc_entry *entry;
+    switch (cur_machine) {
+       case M_X86_32:
+           if (valsize != 32)
+               return NULL;
+           break;
+
+       case M_X86_64:
+           if (valsize != 8 && valsize != 16 && valsize != 32 && valsize != 64)
+               return NULL;
+           break;
+
+       default:
+           yasm_internal_error(N_("Unsupported machine for ELF output"));
+    }
 
+    entry = yasm_xmalloc(sizeof(elf_reloc_entry));
     if (sym == NULL)
        yasm_internal_error("sym is null");
 
     entry->sym = sym;
     entry->addr = addr;
     entry->rtype_rel = rel;
+    entry->valsize = valsize;
 
     return entry;
 }
@@ -433,7 +450,7 @@ elf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab)
 
            case ELF64:
                YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0);
-/* XXX */      YASM_WRITE_8(bufp, ELF32_ST_INFO(entry->bind, entry->type));
+               YASM_WRITE_8(bufp, ELF64_ST_INFO(entry->bind, entry->type));
                YASM_WRITE_8(bufp, 0);
                if (entry->sect) {
                    elf_secthead *shead = yasm_section_get_of_data(entry->sect);
@@ -749,8 +766,40 @@ elf_secthead_write_relocs_to_file(FILE *f, elf_secthead *shead)
                break;
 
            case M_X86_64:
-               r_type = (unsigned char)
-                   (reloc->rtype_rel ? R_X86_64_PC32 : R_X86_64_64);
+               if (reloc->rtype_rel) {
+                   switch (reloc->valsize) {
+                       case 8:
+                           r_type = (unsigned char) R_X86_64_PC8;
+                           break;
+                       case 16:
+                           r_type = (unsigned char) R_X86_64_PC16;
+                           break;
+                       case 32:
+                           r_type = (unsigned char) R_X86_64_PC32;
+                           break;
+                       default:
+                           yasm_internal_error(
+                               N_("Unsupported relocation size"));
+                   }
+               } else {
+                   switch (reloc->valsize) {
+                       case 8:
+                           r_type = (unsigned char) R_X86_64_8;
+                           break;
+                       case 16:
+                           r_type = (unsigned char) R_X86_64_16;
+                           break;
+                       case 32:
+                           r_type = (unsigned char) R_X86_64_32;
+                           break;
+                       case 64:
+                           r_type = (unsigned char) R_X86_64_64;
+                           break;
+                       default:
+                           yasm_internal_error(
+                               N_("Unsupported relocation size"));
+                   }
+               }
                break;
 
            default:
index 47376c8fc46f8e397492a87cd9649d26279eddb3..887ac3da1b34e33a1aea38541e5fa8b498af72bf 100644 (file)
@@ -203,6 +203,7 @@ typedef enum {
 #define ELF32_ST_INFO(bind, type)      (((bind) << 4) + ((type) & 0xf))
 #define ELF32_R_INFO(s,t)              (((s)<<8)+(unsigned char)(t))
 
+#define ELF64_ST_INFO(bind, type)      (((bind) << 4) + ((type) & 0xf))
 #define ELF64_R_INFO(s,t)              (((s)<<32) + ((t) & 0xffffffffL))
 
 #define EHDR32_SIZE 52
@@ -302,6 +303,7 @@ struct elf_reloc_entry {
     elf_address                 addr;
     yasm_symrec                *sym;
     int                         rtype_rel;
+    size_t              valsize;
 };
 
 STAILQ_HEAD(elf_strtab_head, elf_strtab_entry);
@@ -335,7 +337,8 @@ int elf_set_arch(struct yasm_arch *arch, const char *machine);
 /* reloc functions */
 elf_reloc_entry *elf_reloc_entry_new(yasm_symrec *sym,
                                     elf_address addr,
-                                    int rel);
+                                    int rel,
+                                    size_t valsize);
 void elf_reloc_entry_delete(elf_reloc_entry *entry);
 elf_reloc_head *elf_relocs_new(void);
 void elf_reloc_delete(elf_reloc_head *head);
index 0dc899f998636fb9a095fdd88b609e24b928754f..a4ec39e905bfe02911e705ecf09ad383bbce7e64 100644 (file)
@@ -19,3 +19,5 @@ EXTRA_DIST += modules/objfmts/elf/tests/elfreloc.hex
 EXTRA_DIST += modules/objfmts/elf/tests/elfglobal.asm
 EXTRA_DIST += modules/objfmts/elf/tests/elfglobal.errwarn
 EXTRA_DIST += modules/objfmts/elf/tests/elfglobal.hex
+EXTRA_DIST += modules/objfmts/elf/tests/elfreloc-err.asm
+EXTRA_DIST += modules/objfmts/elf/tests/elfreloc-err.errwarn
diff --git a/modules/objfmts/elf/tests/elfreloc-err.asm b/modules/objfmts/elf/tests/elfreloc-err.asm
new file mode 100644 (file)
index 0000000..9158fb4
--- /dev/null
@@ -0,0 +1,4 @@
+EXTERN variable
+       mov     eax, variable
+       mov     ax, variable
+       mov     al, variable
diff --git a/modules/objfmts/elf/tests/elfreloc-err.errwarn b/modules/objfmts/elf/tests/elfreloc-err.errwarn
new file mode 100644 (file)
index 0000000..45779b8
--- /dev/null
@@ -0,0 +1,2 @@
+-:3: elf: invalid relocation size
+-:4: elf: invalid relocation size