summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-10-18 11:29:11 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-10-18 11:29:11 -0700
commit21da3006b5bdbe002eaa849b1fb3af2bb10d367d (patch)
treeef61f5359389a35c6293399bacb4dc58c7d8b0e5
parenta36864413829ed1ff19cb7b0936beda1080fdf72 (diff)
downloadnasm-21da3006b5bdbe002eaa849b1fb3af2bb10d367d.tar.gz
ELF64: once again, fix generation of "naked" OUT_REL*ADR
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>
-rw-r--r--output/outelf64.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/output/outelf64.c b/output/outelf64.c
index dcb16756..74a8ed5e 100644
--- a/output/outelf64.c
+++ b/output/outelf64.c
@@ -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 ||