summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-10-15 15:23:18 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-10-15 15:23:18 -0700
commitc3cea4843077389dcf8d0cb9fccc20ef653f00ad (patch)
treef6f6e7417c1b1074eb470f6ef66482da0746b74f
parentb048324b9e6ba43b1add7c4dbbab61b1b1297a2d (diff)
downloadnasm-c3cea4843077389dcf8d0cb9fccc20ef653f00ad.tar.gz
ELF64: fix various GOT relocations
Try to make the various GOT relocations do the right thing in ELF64, including erring out when appropriate. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--output/outelf64.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/output/outelf64.c b/output/outelf64.c
index 02f2d07e..b70550f5 100644
--- a/output/outelf64.c
+++ b/output/outelf64.c
@@ -969,6 +969,9 @@ static void elf_out(int32_t segto, const void *data,
} else {
if (wrt == NO_SEG) {
switch ((int)size) {
+ case 1:
+ elf_add_reloc(s, segment, R_X86_64_8);
+ break;
case 2:
elf_add_reloc(s, segment, R_X86_64_16);
break;
@@ -991,14 +994,35 @@ static void elf_out(int32_t segto, const void *data,
addr += s->len;
elf_add_reloc(s, segment, R_X86_64_GOTPC32);
} else if (wrt == elf_gotoff_sect + 1) {
- elf_add_reloc(s, segment, R_X86_64_GOTOFF64);
+ if (size != 8) {
+ error(ERR_NONFATAL, "ELF64 requires ..gotoff "
+ "references to be qword absolute");
+ wrt = NO_SEG;
+ } else {
+ elf_add_reloc(s, segment, R_X86_64_GOTOFF64);
+ }
} else if (wrt == elf_got_sect + 1) {
- addr = elf_add_gsym_reloc(s, segment, addr,
- R_X86_64_GOT32, true);
+ switch ((int)size) {
+ case 4:
+ addr = elf_add_gsym_reloc(s, segment, addr,
+ R_X86_64_GOT32, true);
+ break;
+ case 8:
+ addr = elf_add_gsym_reloc(s, segment, addr,
+ R_X86_64_GOT64, true);
+ break;
+ default:
+ error(ERR_NONFATAL, "invalid ..got reference");
+ wrt = NO_SEG;
+ break;
+ }
} else if (wrt == elf_sym_sect + 1) {
switch ((int)size) {
+ case 1:
+ addr = elf_add_gsym_reloc(s, segment, addr,
+ R_X86_64_8, false);
+ break;
case 2:
- gnu16 = true;
addr = elf_add_gsym_reloc(s, segment, addr,
R_X86_64_16, false);
break;
@@ -1064,12 +1088,14 @@ static void elf_out(int32_t segto, const void *data,
elf_add_reloc(s, segment, R_X86_64_PC32);
} else if (wrt == elf_plt_sect + 1) {
elf_add_reloc(s, segment, R_X86_64_PLT32);
- } else if (wrt == elf_gotpc_sect + 1) {
- elf_add_reloc(s, segment, R_X86_64_GOTPCREL);
- } else if (wrt == elf_gotoff_sect + 1) {
- elf_add_reloc(s, segment, R_X86_64_GOTOFF64);
- } else if (wrt == elf_got_sect + 1) {
+ } else if (wrt == elf_gotpc_sect + 1 ||
+ wrt == elf_got_sect + 1) {
elf_add_reloc(s, segment, R_X86_64_GOTPCREL);
+ } else if (wrt == elf_gotoff_sect + 1 ||
+ wrt == elf_got_sect + 1) {
+ error(ERR_NONFATAL, "ELF64 requires ..gotoff references to be "
+ "qword absolute");
+ wrt = NO_SEG;
} else {
error(ERR_NONFATAL, "ELF64 format does not support this"
" use of WRT");