mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50:07 +08:00
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:
parent
86c850fc58
commit
738606dbd5
10
libtcc.c
10
libtcc.c
@ -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' */
|
||||
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;
|
||||
if (sym) {
|
||||
@ -545,7 +546,12 @@ ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)
|
||||
c = sym->c;
|
||||
}
|
||||
/* 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
2
tcc.h
@ -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_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 greloca(Section *s, Sym *sym, unsigned long offset, int type, unsigned long addend);
|
||||
|
||||
ST_INLN void sym_free(Sym *sym);
|
||||
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 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_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_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index);
|
||||
|
15
tccelf.c
15
tccelf.c
@ -269,8 +269,8 @@ ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
|
||||
}
|
||||
|
||||
/* put relocation */
|
||||
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)
|
||||
{
|
||||
char buf[256];
|
||||
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_info = ELFW(R_INFO)(symbol, type);
|
||||
#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
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
|
||||
|
32
tccgen.c
32
tccgen.c
@ -5201,19 +5201,35 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
|
||||
case VT_LLONG:
|
||||
*(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
|
||||
break;
|
||||
case VT_PTR:
|
||||
if (vtop->r & VT_SYM) {
|
||||
case VT_PTR: {
|
||||
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);
|
||||
}
|
||||
*(addr_t *)ptr |= (vtop->c.ptr_offset & bit_mask) << bit_pos;
|
||||
*(addr_t *)ptr |= val;
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
*(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
|
||||
*(int *)ptr |= val;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
} else {
|
||||
vset(&dtype, VT_LOCAL|VT_LVAL, c);
|
||||
|
Loading…
Reference in New Issue
Block a user