mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-12-15 09:09:58 +08:00
ELF64: actually generate relative GOT/PLT references correctly
Fix the arithmetic for relative GOT/PLT references. We still can't enable exactitude, because of the assumption that "size" is always the proper adjustment for the offset of the displacement inside the instruction, which is wrong in the case of displacements that are followed by an immediate. This also affects the list file, so it really should be fixed. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
9d8b57d081
commit
d5e7498556
@ -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 - size;
|
||||
addr = *(int64_t *)data;
|
||||
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, R_X86_64_PC16);
|
||||
elf_add_reloc(s, segment, addr-size, 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, size);
|
||||
} else if (type == OUT_REL4ADR) {
|
||||
addr = *(int64_t *)data - size;
|
||||
addr = *(int64_t *)data;
|
||||
if (segment == segto)
|
||||
error(ERR_PANIC, "intra-segment OUT_REL4ADR");
|
||||
if (segment == NO_SEG) {
|
||||
@ -1096,17 +1096,16 @@ static void elf_out(int32_t segto, const void *data,
|
||||
" segment base references");
|
||||
} else {
|
||||
if (wrt == NO_SEG) {
|
||||
elf_add_reloc(s, segment, addr, R_X86_64_PC32);
|
||||
elf_add_reloc(s, segment, addr-size, R_X86_64_PC32);
|
||||
addr = 0;
|
||||
} else if (wrt == elf_plt_sect + 1) {
|
||||
int64_t pcrel = s->len + size;
|
||||
elf_add_gsym_reloc(s, segment, addr+pcrel, pcrel,
|
||||
elf_add_gsym_reloc(s, segment, addr, size,
|
||||
R_X86_64_PLT32, false);
|
||||
addr = 0;
|
||||
} else if (wrt == elf_gotpc_sect + 1 ||
|
||||
wrt == elf_got_sect + 1) {
|
||||
int64_t pcrel = s->len + size;
|
||||
elf_add_gsym_reloc(s, segment, addr+pcrel, pcrel,
|
||||
printf("addr = %ld, pcrel = %ld\n", addr, size);
|
||||
elf_add_gsym_reloc(s, segment, addr, size,
|
||||
R_X86_64_GOTPCREL, false);
|
||||
addr = 0;
|
||||
} else if (wrt == elf_gotoff_sect + 1 ||
|
||||
@ -1120,7 +1119,7 @@ static void elf_out(int32_t segto, const void *data,
|
||||
}
|
||||
elf_sect_writeaddr(s, addr, size);
|
||||
} else if (type == OUT_REL8ADR) {
|
||||
addr = *(int64_t *)data - size;
|
||||
addr = *(int64_t *)data;
|
||||
if (segment == segto)
|
||||
error(ERR_PANIC, "intra-segment OUT_REL8ADR");
|
||||
if (segment == NO_SEG) {
|
||||
@ -1130,12 +1129,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, R_X86_64_PC64);
|
||||
elf_add_reloc(s, segment, addr-size, R_X86_64_PC64);
|
||||
addr = 0;
|
||||
} else if (wrt == elf_gotpc_sect + 1 ||
|
||||
wrt == elf_got_sect + 1) {
|
||||
int64_t pcrel = s->len + size;
|
||||
elf_add_gsym_reloc(s, segment, addr+pcrel, pcrel,
|
||||
elf_add_gsym_reloc(s, segment, addr, size,
|
||||
R_X86_64_GOTPCREL64, false);
|
||||
addr = 0;
|
||||
} else if (wrt == elf_gotoff_sect + 1 ||
|
||||
|
Loading…
Reference in New Issue
Block a user