Use RELA relocations properly for R_DATA_PTR on x86_64.

libtcc.c: Add greloca, a generalisation of greloc that takes an addend.
tcc.h: Add greloca and put_elf_reloca.
tccelf.c: Add put_elf_reloca, a generalisation of put_elf_reloc.
tccgen.c: On x86_64, use greloca instead of greloc in init_putv.
This commit is contained in:
Edmund Grimley Evans 2015-02-21 21:29:03 +00:00
parent 86c850fc58
commit 738606dbd5
4 changed files with 46 additions and 13 deletions

View File

@ -536,7 +536,8 @@ ST_FUNC void put_extern_sym(Sym *sym, Section *section,
} }
/* add a new relocation entry to symbol 'sym' in section 's' */ /* add a new relocation entry to symbol 'sym' in section 's' */
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type) ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type,
unsigned long addend)
{ {
int c = 0; int c = 0;
if (sym) { if (sym) {
@ -545,7 +546,12 @@ ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)
c = sym->c; c = sym->c;
} }
/* now we can add ELF relocation info */ /* now we can add ELF relocation info */
put_elf_reloc(symtab_section, s, offset, type, c); put_elf_reloca(symtab_section, s, offset, type, c, addend);
}
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)
{
greloca(s, sym, offset, type, 0);
} }
/********************************************************/ /********************************************************/

2
tcc.h
View File

@ -1074,6 +1074,7 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name);
ST_FUNC void put_extern_sym2(Sym *sym, Section *section, addr_t value, unsigned long size, int can_add_underscore); ST_FUNC void put_extern_sym2(Sym *sym, Section *section, addr_t value, unsigned long size, int can_add_underscore);
ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size); ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type); ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);
ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, unsigned long addend);
ST_INLN void sym_free(Sym *sym); ST_INLN void sym_free(Sym *sym);
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c); ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c);
@ -1261,6 +1262,7 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info,
ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int sh_num, const char *name); ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int sh_num, const char *name);
ST_FUNC int find_elf_sym(Section *s, const char *name); ST_FUNC int find_elf_sym(Section *s, const char *name);
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol); ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);
ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, unsigned long addend);
ST_FUNC void put_stabs(const char *str, int type, int other, int desc, unsigned long value); ST_FUNC void put_stabs(const char *str, int type, int other, int desc, unsigned long value);
ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index); ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index);

View File

@ -269,8 +269,8 @@ ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
} }
/* put relocation */ /* put relocation */
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
int type, int symbol) int type, int symbol, unsigned long addend)
{ {
char buf[256]; char buf[256];
Section *sr; Section *sr;
@ -292,10 +292,19 @@ ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
rel->r_offset = offset; rel->r_offset = offset;
rel->r_info = ELFW(R_INFO)(symbol, type); rel->r_info = ELFW(R_INFO)(symbol, type);
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
rel->r_addend = 0; rel->r_addend = addend;
#else
if (addend)
tcc_error("non-zero addend on REL architecture");
#endif #endif
} }
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
int type, int symbol)
{
put_elf_reloca(symtab, s, offset, type, symbol, 0);
}
/* put stab debug information */ /* put stab debug information */
ST_FUNC void put_stabs(const char *str, int type, int other, int desc, ST_FUNC void put_stabs(const char *str, int type, int other, int desc,

View File

@ -5201,19 +5201,35 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
case VT_LLONG: case VT_LLONG:
*(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos; *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
break; break;
case VT_PTR: case VT_PTR: {
if (vtop->r & VT_SYM) { addr_t val = (vtop->c.ptr_offset & bit_mask) << bit_pos;
#ifdef TCC_TARGET_X86_64
if (vtop->r & VT_SYM)
greloca(sec, vtop->sym, c, R_DATA_PTR, val);
else
*(addr_t *)ptr |= val;
#else
if (vtop->r & VT_SYM)
greloc(sec, vtop->sym, c, R_DATA_PTR); greloc(sec, vtop->sym, c, R_DATA_PTR);
} *(addr_t *)ptr |= val;
*(addr_t *)ptr |= (vtop->c.ptr_offset & bit_mask) << bit_pos; #endif
break; break;
default: }
if (vtop->r & VT_SYM) { default: {
int val = (vtop->c.i & bit_mask) << bit_pos;
#ifdef TCC_TARGET_X86_64
if (vtop->r & VT_SYM)
greloca(sec, vtop->sym, c, R_DATA_PTR, val);
else
*(int *)ptr |= val;
#else
if (vtop->r & VT_SYM)
greloc(sec, vtop->sym, c, R_DATA_PTR); greloc(sec, vtop->sym, c, R_DATA_PTR);
} *(int *)ptr |= val;
*(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos; #endif
break; break;
} }
}
vtop--; vtop--;
} else { } else {
vset(&dtype, VT_LOCAL|VT_LVAL, c); vset(&dtype, VT_LOCAL|VT_LVAL, c);