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 | /* add a new relocation entry to symbol 'sym' in section 's' */ | 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 | int c = 0; | 542 | int c = 0; |
| 542 | if (sym) { | 543 | if (sym) { |
| @@ -545,7 +546,12 @@ ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type) · 2 unmodified lines | |||
| 545 | c = sym->c; | 546 | c = sym->c; |
| 546 | } | 547 | } |
| 547 | /* now we can add ELF relocation info */ | 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 | ST_FUNC void put_extern_sym2(Sym *sym, Section *section, addr_t value, unsigned long size, int can_add_underscore); | 1074 | ST_FUNC void put_extern_sym2(Sym *sym, Section *section, addr_t value, unsigned long size, int can_add_underscore); |
| 1075 | ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size); | 1075 | ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size); |
| 1076 | ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type); | 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 | ST_INLN void sym_free(Sym *sym); | 1079 | ST_INLN void sym_free(Sym *sym); |
| 1079 | ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c); | 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 | 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 | 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 | ST_FUNC int find_elf_sym(Section *s, const char *name); | 1263 | ST_FUNC int find_elf_sym(Section *s, const char *name); |
| 1263 | ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol); | 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 | ST_FUNC void put_stabs(const char *str, int type, int other, int desc, unsigned long value); | 1267 | ST_FUNC void put_stabs(const char *str, int type, int other, int desc, unsigned long value); |
| 1266 | ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index); | 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 | /* put relocation */ | 271 | /* put relocation */ |
| 272 | ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, | 272 | ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, |
| 273 | int type, int symbol) | 273 | int type, int symbol, unsigned long addend) |
| 274 | { | 274 | { |
| 275 | char buf[256]; | 275 | char buf[256]; |
| 276 | Section *sr; | 276 | Section *sr; |
| @@ -292,10 +292,19 @@ ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, · 15 unmodified lines | |||
| 292 | rel->r_offset = offset; | 292 | rel->r_offset = offset; |
| 293 | rel->r_info = ELFW(R_INFO)(symbol, type); | 293 | rel->r_info = ELFW(R_INFO)(symbol, type); |
| 294 | #ifdef TCC_TARGET_X86_64 | 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 | #endif | 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 | /* put stab debug information */ | 308 | /* put stab debug information */ |
| 300 | 309 | ||
| 301 | ST_FUNC void put_stabs(const char *str, int type, int other, int desc, | 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 | case VT_LLONG: | 5201 | case VT_LLONG: |
| 5202 | *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos; | 5202 | *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos; |
| 5203 | break; | 5203 | break; |
| 5204 | case VT_PTR: | 5204 | case VT_PTR: { |
| 5205 | if (vtop->r & VT_SYM) { | 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 | greloc(sec, vtop->sym, c, R_DATA_PTR); | 5213 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
| 5207 | } | 5214 | *(addr_t *)ptr |= val; |
| 5208 | *(addr_t *)ptr |= (vtop->c.ptr_offset & bit_mask) << bit_pos; | 5215 | #endif |
| 5209 | break; | 5216 | break; |
| 5210 | default: | 5217 | } |
| 5211 | if (vtop->r & VT_SYM) { | 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 | greloc(sec, vtop->sym, c, R_DATA_PTR); | 5227 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
| 5213 | } | 5228 | *(int *)ptr |= val; |
| 5214 | *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos; | 5229 | #endif |
| 5215 | break; | 5230 | break; |
| 5216 | } | 5231 | } |
| 5232 | } | ||
| 5217 | vtop--; | 5233 | vtop--; |
| 5218 | } else { | 5234 | } else { |
| 5219 | vset(&dtype, VT_LOCAL|VT_LVAL, c); | 5235 | vset(&dtype, VT_LOCAL|VT_LVAL, c); |