ELF64: once again, fix generation of "naked" OUT_REL*ADR
authorH. Peter Anvin <hpa@zytor.com>
Sat, 18 Oct 2008 18:29:11 +0000 (11:29 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Sat, 18 Oct 2008 18:29:11 +0000 (11:29 -0700)
It is unclear if we will ever see any "naked" (absolute bytes)
OUT_REL*ADR coming from the assembler, but if we do, we should
generate them correctly.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
output/outelf64.c

index dcb1675..74a8ed5 100644 (file)
@@ -1067,7 +1067,7 @@ static void elf_out(int32_t segto, const void *data,
        }
        elf_sect_writeaddr(s, addr, size);
     } else if (type == OUT_REL2ADR) {
-       addr = *(int64_t *)data;
+       addr = *(int64_t *)data - size;
         if (segment == segto)
             error(ERR_PANIC, "intra-segment OUT_REL2ADR");
         if (segment == NO_SEG) {
@@ -1077,7 +1077,7 @@ static void elf_out(int32_t segto, const void *data,
                   " segment base references");
         } else {
             if (wrt == NO_SEG) {
-                elf_add_reloc(s, segment, addr-size, R_X86_64_PC16);
+                elf_add_reloc(s, segment, addr, R_X86_64_PC16);
                addr = 0;
             } else {
                 error(ERR_NONFATAL,
@@ -1086,7 +1086,7 @@ static void elf_out(int32_t segto, const void *data,
         }
        elf_sect_writeaddr(s, addr, 2);
     } else if (type == OUT_REL4ADR) {
-       addr = *(int64_t *)data;
+       addr = *(int64_t *)data - size;
         if (segment == segto)
             error(ERR_PANIC, "intra-segment OUT_REL4ADR");
         if (segment == NO_SEG) {
@@ -1096,16 +1096,15 @@ static void elf_out(int32_t segto, const void *data,
                   " segment base references");
         } else {
             if (wrt == NO_SEG) {
-                elf_add_reloc(s, segment, addr-size, R_X86_64_PC32);
+                elf_add_reloc(s, segment, addr, R_X86_64_PC32);
                addr = 0;
             } else if (wrt == elf_plt_sect + 1) {
-                elf_add_gsym_reloc(s, segment, addr, size,
+                elf_add_gsym_reloc(s, segment, addr+size, size,
                                   R_X86_64_PLT32, true);
                addr = 0;
             } else if (wrt == elf_gotpc_sect + 1 ||
                       wrt == elf_got_sect + 1) {
-               printf("addr = %ld, pcrel = %ld\n", addr, size);
-                elf_add_gsym_reloc(s, segment, addr, size,
+                elf_add_gsym_reloc(s, segment, addr+size, size,
                                   R_X86_64_GOTPCREL, true);
                addr = 0;
             } else if (wrt == elf_gotoff_sect + 1 ||
@@ -1119,7 +1118,7 @@ static void elf_out(int32_t segto, const void *data,
         }
        elf_sect_writeaddr(s, addr, 4);
     } else if (type == OUT_REL8ADR) {
-       addr = *(int64_t *)data;
+       addr = *(int64_t *)data - size;
         if (segment == segto)
             error(ERR_PANIC, "intra-segment OUT_REL8ADR");
         if (segment == NO_SEG) {
@@ -1129,11 +1128,11 @@ static void elf_out(int32_t segto, const void *data,
                   " segment base references");
         } else {
             if (wrt == NO_SEG) {
-                elf_add_reloc(s, segment, addr-size, R_X86_64_PC64);
+                elf_add_reloc(s, segment, addr, R_X86_64_PC64);
                addr = 0;
             } else if (wrt == elf_gotpc_sect + 1 ||
                       wrt == elf_got_sect + 1) {
-                elf_add_gsym_reloc(s, segment, addr, size,
+                elf_add_gsym_reloc(s, segment, addr+size, size,
                                   R_X86_64_GOTPCREL64, true);
                addr = 0;
             } else if (wrt == elf_gotoff_sect + 1 ||