diff options
| author | Shinichiro Hamaji <shinichiro.hamaji _at_ gmail.com> | 2009-04-13 00:27:04 +0900 |
|---|---|---|
| committer | grischka <grischka> | 2009-04-18 15:08:01 +0200 |
| commit | 830b7533c99f86203c4fbaf94897679678c3bad0 (patch) | |
| tree | ed583dda98119b1248b857bdd20e22db457de0d5 /tccelf.c | |
| parent | 6c10429aa5e7c65e725ed1989ddb856bbf7283aa (diff) | |
| download | tinycc-830b7533c99f86203c4fbaf94897679678c3bad0.tar.gz tinycc-830b7533c99f86203c4fbaf94897679678c3bad0.tar.bz2 | |
Generate PIC code so that we can create shared objects properly.
- Add got_table in TCCState. This approach is naive and the distance between executable code and GOT can be longer than 32bit.
- Handle R_X86_64_GOTPCREL properly. We use got_table for TCC_OUTPUT_MEMORY case for now.
- Fix load() and store() so that they access global variables via GOT.
Diffstat (limited to 'tccelf.c')
| -rw-r--r-- | tccelf.c | 29 |
1 files changed, 25 insertions, 4 deletions
@@ -502,6 +502,25 @@ static unsigned long add_jmp_table(TCCState *s1, unsigned long val) *(unsigned long *)(p + 6) = val; return (unsigned long)p; } + +#define GOT_TABLE_ENTRY_MAX_NUM 4096 +static unsigned long add_got_table(TCCState *s1, unsigned long val) +{ + unsigned long *p; + if (!s1->got_table) { + int size = sizeof(void *) * GOT_TABLE_ENTRY_MAX_NUM; + s1->got_table_num = 0; + s1->got_table = (char *)tcc_malloc(size); + } + if (s1->got_table_num == GOT_TABLE_ENTRY_MAX_NUM) { + error("relocating >%d symbols are not supported", + GOT_TABLE_ENTRY_MAX_NUM); + } + p = s1->got_table + s1->got_table_num; + s1->got_table_num++; + *p = val; + return (unsigned long)p; +} #endif /* relocate a given section (CPU dependent) */ @@ -727,11 +746,13 @@ static void relocate_section(TCCState *s1, Section *s) *(int *)ptr = val; break; case R_X86_64_GOTPCREL: - *(int *)ptr += s1->got->sh_addr - addr; - /* XXX: is this OK? */ - if (s1->output_type == TCC_OUTPUT_DLL) { - *(int *)ptr += s1->got_offsets[sym_index] - 4; + if (s1->output_type == TCC_OUTPUT_MEMORY) { + val = add_got_table(s1, val - rel->r_addend) + rel->r_addend; + *(int *)ptr += val - addr; + break; } + *(int *)ptr += (s1->got->sh_addr - addr + + s1->got_offsets[sym_index] - 4); break; case R_X86_64_GOTTPOFF: *(int *)ptr += val - s1->got->sh_addr; |
