diff options
| author | Michael Matz <matz@suse.de> | 2016-05-09 23:09:55 +0200 |
|---|---|---|
| committer | Michael Matz <matz@suse.de> | 2016-05-09 23:17:47 +0200 |
| commit | 9645b62a65986738e6b70d748890d73daf40508b (patch) | |
| tree | ade2908d9f65ebd9c16edaba00e1c9e0a40a28bc | |
| parent | 5e47b08dc80281e27f0cd7c15d0d91a2e1c0a636 (diff) | |
| download | tinycc-9645b62a65986738e6b70d748890d73daf40508b.tar.gz tinycc-9645b62a65986738e6b70d748890d73daf40508b.tar.bz2 | |
x86_64: Use addend on relocs
Traditional behaviour on x86-64 is to encode the relocation
addend in r_addend, not in the relocated field (after all,
that's the reason to use RELA relocs to begin with). Our
linker can deal with both, other linkers as well. But using
e.g. the GNU assembler one can detect differences (equivalent
code in the end, but still a difference).
Now there's only a trivial difference in tests/asmtest.S
(having to do with ordering of prefixes).
| -rw-r--r-- | tccelf.c | 2 | ||||
| -rw-r--r-- | x86_64-gen.c | 31 |
2 files changed, 14 insertions, 19 deletions
@@ -927,7 +927,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) qrel->r_offset = rel->r_offset; qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32); /* Use sign extension! */ - qrel->r_addend = (int)read32le(ptr); + qrel->r_addend = (int)read32le(ptr) + rel->r_addend; qrel++; break; } diff --git a/x86_64-gen.c b/x86_64-gen.c index bf983d4..e313a5f 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -256,7 +256,7 @@ ST_FUNC int oad(int c, int s) ST_FUNC void gen_addr32(int r, Sym *sym, int c) { if (r & VT_SYM) - greloc(cur_text_section, sym, ind, R_X86_64_32); + greloca(cur_text_section, sym, ind, R_X86_64_32, c), c=0; gen_le32(c); } @@ -264,7 +264,7 @@ ST_FUNC void gen_addr32(int r, Sym *sym, int c) ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c) { if (r & VT_SYM) - greloc(cur_text_section, sym, ind, R_X86_64_64); + greloca(cur_text_section, sym, ind, R_X86_64_64, c), c=0; gen_le64(c); } @@ -272,7 +272,7 @@ ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c) ST_FUNC void gen_addrpc32(int r, Sym *sym, int c) { if (r & VT_SYM) - greloc(cur_text_section, sym, ind, R_X86_64_PC32); + greloca(cur_text_section, sym, ind, R_X86_64_PC32, c-4), c=4; gen_le32(c-4); } @@ -280,12 +280,7 @@ ST_FUNC void gen_addrpc32(int r, Sym *sym, int c) static void gen_gotpcrel(int r, Sym *sym, int c) { #ifndef TCC_TARGET_PE - Section *sr; - ElfW(Rela) *rel; - greloc(cur_text_section, sym, ind, R_X86_64_GOTPCREL); - sr = cur_text_section->reloc; - rel = (ElfW(Rela) *)(sr->data + sr->data_offset - sizeof(ElfW(Rela))); - rel->r_addend = -4; + greloca(cur_text_section, sym, ind, R_X86_64_GOTPCREL, -4); #else tcc_error("internal error: no GOT on PE: %s %x %x | %02x %02x %02x\n", get_tok_str(sym->v, NULL), c, r, @@ -608,16 +603,16 @@ static void gcall_or_jmp(int is_jmp) if (vtop->r & VT_SYM) { /* relocation case */ #ifdef TCC_TARGET_PE - greloc(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32); + greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4)); #else - greloc(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32); + greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4)); #endif } else { /* put an empty PC32 relocation */ - put_elf_reloc(symtab_section, cur_text_section, - ind + 1, R_X86_64_PC32, 0); + put_elf_reloca(symtab_section, cur_text_section, + ind + 1, R_X86_64_PC32, 0, (int)(vtop->c.i-4)); } - oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */ + oad(0xe8 + is_jmp, 0); /* call/jmp im */ } else { /* otherwise, indirect call */ r = TREG_R11; @@ -637,8 +632,8 @@ static unsigned long func_bound_ind; static void gen_static_call(int v) { Sym *sym = external_global_sym(v, &func_old_type, 0); - oad(0xe8, -4); - greloc(cur_text_section, sym, ind-4, R_X86_64_PC32); + oad(0xe8, 0); + greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4); } /* generate a bounded pointer addition */ @@ -991,8 +986,8 @@ void gfunc_epilog(void) if (v >= 4096) { Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); oad(0xb8, v); /* mov stacksize, %eax */ - oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */ - greloc(cur_text_section, sym, ind-4, R_X86_64_PC32); + oad(0xe8, 0); /* call __chkstk, (does the stackframe too) */ + greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4); o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */ } else { o(0xe5894855); /* push %rbp, mov %rsp, %rbp */ |
