]> granicus.if.org Git - yasm/commitdiff
Fix #114: Incorrect ELF32 ..gotpc address calculation.
authorPeter Johnson <peter@tortall.net>
Sat, 15 Sep 2007 06:40:27 +0000 (06:40 -0000)
committerPeter Johnson <peter@tortall.net>
Sat, 15 Sep 2007 06:40:27 +0000 (06:40 -0000)
Reported by: Loren Merritt
Fix by: mu@

We already had a testcase for this, but it had an incorrect "golden" result.

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

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/elfso.hex

index 562e098c685670a353083f30fd4f0585e30688b5..f2bb8db76e3edd74c2b97c27d3c7d9b64ac35d51 100644 (file)
@@ -69,6 +69,11 @@ typedef void (*func_write_proghead)(unsigned char **bufpp,
                                     unsigned long secthead_count,
                                     elf_section_index shstrtab_index);
 
+enum {
+    ELF_SSYM_SYM_RELATIVE = 1 << 0,
+    ELF_SSYM_CURPOS_ADJUST = 1 << 1
+};
+
 typedef struct {
     const char *name;       /* should be something like ..name */
     const int sym_rel;      /* symbol or section-relative? */
index 664d135157e0808c1d5d8ad0e631f075bd453017..5ec17b7c49f0ed6fab62f4aa0f1a6736452f5cb9 100644 (file)
@@ -514,6 +514,8 @@ elf_objfmt_output_value(yasm_value *value, unsigned char *buf,
             wrt = NULL;
         else if (wrt && elf_is_wrt_sym_relative(wrt))
             ;
+        else if (wrt && elf_is_wrt_pos_adjusted(wrt))
+            intn_val = offset + bc->offset;
         else if (vis == YASM_SYM_LOCAL) {
             yasm_bytecode *sym_precbc;
             /* Local symbols need relocation to their section's start, and
index ce0cdda18fe05eeb2a3f982a0b394ae5b4fbecae..4bc53b21b94642ec76601e8228c55a2d1b826ccd 100644 (file)
@@ -209,8 +209,8 @@ elf_x86_amd64_write_proghead(unsigned char **bufpp,
 }
 
 static elf_machine_ssym elf_x86_amd64_ssyms[] = {
-    {"..gotpcrel", 1},
-    {"..got", 1},
+    {"..gotpcrel", ELF_SSYM_SYM_RELATIVE},
+    {"..got", ELF_SSYM_SYM_RELATIVE},
     {"..plt", 0}
 };
 
index 827c861e476c486beb65ed14196f5842f231b137..67a23d0a70ced30a08fcc34f343c21de088255f7 100644 (file)
@@ -194,9 +194,9 @@ elf_x86_x86_write_proghead(unsigned char **bufpp,
 }
 
 static elf_machine_ssym elf_x86_x86_ssyms[] = {
-    {"..gotpc", 0},
+    {"..gotpc", ELF_SSYM_CURPOS_ADJUST},
     {"..gotoff", 0},
-    {"..got", 1},
+    {"..got", ELF_SSYM_SYM_RELATIVE},
     {"..plt", 0}
 };
 
index f187b9e7e72009135fcd33db16b2fe1ed7d666bc..87ee9828959a3a3c9e7e7bc08dd0b1d254e5cc81 100644 (file)
@@ -99,13 +99,27 @@ elf_set_arch(yasm_arch *arch, yasm_symtab *symtab, int bits_pref)
 }
 
 /* reloc functions */
+int elf_ssym_has_flag(yasm_symrec *wrt, int flag);
+
 int
 elf_is_wrt_sym_relative(yasm_symrec *wrt)
+{
+    return elf_ssym_has_flag(wrt, ELF_SSYM_SYM_RELATIVE);
+}
+
+int
+elf_is_wrt_pos_adjusted(yasm_symrec *wrt)
+{
+    return elf_ssym_has_flag(wrt, ELF_SSYM_CURPOS_ADJUST);
+}
+
+int
+elf_ssym_has_flag(yasm_symrec *wrt, int flag)
 {
     int i;
     for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
         if (elf_ssyms[i] == wrt)
-            return elf_march->ssyms[i].sym_rel;
+            return (elf_march->ssyms[i].sym_rel & flag) != 0;
     }
     return 0;
 }
index b876a75e702914b6d812c599232e2448e8662eaf..954e052e39bdeb4a708f028cc37b3e44d2b80dc8 100644 (file)
@@ -412,6 +412,7 @@ const elf_machine_handler *elf_set_arch(struct yasm_arch *arch,
 
 /* reloc functions */
 int elf_is_wrt_sym_relative(yasm_symrec *wrt);
+int elf_is_wrt_pos_adjusted(yasm_symrec *wrt);
 elf_reloc_entry *elf_reloc_entry_create(yasm_symrec *sym,
                                         /*@null@*/ yasm_symrec *wrt,
                                         yasm_intnum *addr,
index 9d99c0f8e99710506f1861387dd7f744110ba0c2..206cce9c6d446e39328707da0b977f9978eeb0d6 100644 (file)
@@ -88,10 +88,10 @@ e8
 5b 
 81 
 c3 
-e9 
-ff 
-ff 
-ff 
+03 
+00 
+00 
+00 
 8b 
 83 
 00