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.
Unified · Split
| @@ -536,7 +536,8 @@ ST_FUNC void put_extern_sym(Sym *sym, Section *section, · 535 unmodified lines | ||
| 536 | 536 | } |
| 537 | 537 | |
| 538 | 538 | /* add a new relocation entry to symbol 'sym' in section 's' */ |
| 539 | −ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type) | |
| 539 | +ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, | |
| 540 | + unsigned long addend) | |
| 540 | 541 | { |
| 541 | 542 | int c = 0; |
| 542 | 543 | if (sym) { |
| @@ -545,7 +546,12 @@ ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type) · 2 unmodified lines | ||
| 545 | 546 | c = sym->c; |
| 546 | 547 | } |
| 547 | 548 | /* now we can add ELF relocation info */ |
| 548 | − put_elf_reloc(symtab_section, s, offset, type, c); | |
| 549 | + put_elf_reloca(symtab_section, s, offset, type, c, addend); | |
| 550 | +} | |
| 551 | + | |
| 552 | +ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type) | |
| 553 | +{ | |
| 554 | + greloca(s, sym, offset, type, 0); | |
| 549 | 555 | } |
| 550 | 556 | |
| 551 | 557 | /********************************************************/ |
| @@ -1074,6 +1074,7 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name); · 1073 unmodified lines | ||
| 1074 | 1074 | ST_FUNC void put_extern_sym2(Sym *sym, Section *section, addr_t value, unsigned long size, int can_add_underscore); |
| 1075 | 1075 | ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size); |
| 1076 | 1076 | ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type); |
| 1077 | +ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, unsigned long addend); | |
| 1077 | 1078 | |
| 1078 | 1079 | ST_INLN void sym_free(Sym *sym); |
| 1079 | 1080 | 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, · 181 unmodified lines | ||
| 1261 | 1262 | ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int sh_num, const char *name); |
| 1262 | 1263 | ST_FUNC int find_elf_sym(Section *s, const char *name); |
| 1263 | 1264 | ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol); |
| 1265 | +ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, unsigned long addend); | |
| 1264 | 1266 | |
| 1265 | 1267 | ST_FUNC void put_stabs(const char *str, int type, int other, int desc, unsigned long value); |
| 1266 | 1268 | ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index); |
| @@ -269,8 +269,8 @@ ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size, · 268 unmodified lines | ||
| 269 | 269 | } |
| 270 | 270 | |
| 271 | 271 | /* put relocation */ |
| 272 | −ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, | |
| 273 | − int type, int symbol) | |
| 272 | +ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, | |
| 273 | + int type, int symbol, unsigned long addend) | |
| 274 | 274 | { |
| 275 | 275 | char buf[256]; |
| 276 | 276 | Section *sr; |
| @@ -292,10 +292,19 @@ ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, · 15 unmodified lines | ||
| 292 | 292 | rel->r_offset = offset; |
| 293 | 293 | rel->r_info = ELFW(R_INFO)(symbol, type); |
| 294 | 294 | #ifdef TCC_TARGET_X86_64 |
| 295 | − rel->r_addend = 0; | |
| 295 | + rel->r_addend = addend; | |
| 296 | +#else | |
| 297 | + if (addend) | |
| 298 | + tcc_error("non-zero addend on REL architecture"); | |
| 296 | 299 | #endif |
| 297 | 300 | } |
| 298 | 301 | |
| 302 | +ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, | |
| 303 | + int type, int symbol) | |
| 304 | +{ | |
| 305 | + put_elf_reloca(symtab, s, offset, type, symbol, 0); | |
| 306 | +} | |
| 307 | + | |
| 299 | 308 | /* put stab debug information */ |
| 300 | 309 | |
| 301 | 310 | ST_FUNC void put_stabs(const char *str, int type, int other, int desc, |
| @@ -5201,19 +5201,35 @@ static void init_putv(CType *type, Section *sec, unsigned long c, · 5200 unmodified lines | ||
| 5201 | 5201 | case VT_LLONG: |
| 5202 | 5202 | *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos; |
| 5203 | 5203 | break; |
| 5204 | − case VT_PTR: | |
| 5205 | − if (vtop->r & VT_SYM) { | |
| 5204 | + case VT_PTR: { | |
| 5205 | + addr_t val = (vtop->c.ptr_offset & bit_mask) << bit_pos; | |
| 5206 | +#ifdef TCC_TARGET_X86_64 | |
| 5207 | + if (vtop->r & VT_SYM) | |
| 5208 | + greloca(sec, vtop->sym, c, R_DATA_PTR, val); | |
| 5209 | + else | |
| 5210 | + *(addr_t *)ptr |= val; | |
| 5211 | +#else | |
| 5212 | + if (vtop->r & VT_SYM) | |
| 5206 | 5213 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
| 5207 | − } | |
| 5208 | − *(addr_t *)ptr |= (vtop->c.ptr_offset & bit_mask) << bit_pos; | |
| 5214 | + *(addr_t *)ptr |= val; | |
| 5215 | +#endif | |
| 5209 | 5216 | break; |
| 5210 | − default: | |
| 5211 | − if (vtop->r & VT_SYM) { | |
| 5217 | + } | |
| 5218 | + default: { | |
| 5219 | + int val = (vtop->c.i & bit_mask) << bit_pos; | |
| 5220 | +#ifdef TCC_TARGET_X86_64 | |
| 5221 | + if (vtop->r & VT_SYM) | |
| 5222 | + greloca(sec, vtop->sym, c, R_DATA_PTR, val); | |
| 5223 | + else | |
| 5224 | + *(int *)ptr |= val; | |
| 5225 | +#else | |
| 5226 | + if (vtop->r & VT_SYM) | |
| 5212 | 5227 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
| 5213 | − } | |
| 5214 | − *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos; | |
| 5228 | + *(int *)ptr |= val; | |
| 5229 | +#endif | |
| 5215 | 5230 | break; |
| 5216 | 5231 | } |
| 5232 | + } | |
| 5217 | 5233 | vtop--; |
| 5218 | 5234 | } else { |
| 5219 | 5235 | vset(&dtype, VT_LOCAL|VT_LVAL, c); |