From fcf2e5981fe5e37e3aee633b414486311e54bc8e Mon Sep 17 00:00:00 2001 From: Shinichiro Hamaji Date: Mon, 13 Apr 2009 03:22:08 +0900 Subject: [PATCH] x86-64: Combine buffers of sections before we call tcc_run(). - Now we can run tcc -run tcc.c successfully, though there are some bugs. - Remove jmp_table and got_table and use text_section for got and plt entries. - Combine buffers in tcc_relocate(). - Use R_X86_64_64 instead of R_X86_64_32 for R_DATA_32 (now the name R_DATA_32 is inappropriate...). --- tcc.c | 71 ++++++++++++++++++++++++++++++++++++++++++++---------------- tccelf.c | 30 +++---------------------- x86_64-gen.c | 2 +- 3 files changed, 56 insertions(+), 47 deletions(-) diff --git a/tcc.c b/tcc.c index 02da926a..1b0b72be 100644 --- a/tcc.c +++ b/tcc.c @@ -542,15 +542,6 @@ struct TCCState { /* output file for preprocessing */ FILE *outfile; - -#ifdef TCC_TARGET_X86_64 - /* buffer to store jump tables used when the output is memory */ - char *jmp_table; - int jmp_table_num; - /* buffer to store got tables used when the output is memory */ - void **got_table; - int got_table_num; -#endif }; /* The current value can be: */ @@ -1315,7 +1306,12 @@ Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) static void free_section(Section *s) { - tcc_free(s->data); +#ifdef TCC_TARGET_X86_64 + /* after tcc_relocate(), some sections share the data buffer. + let's check if the data is allocated not to free the shared buffers */ + if (s->data_allocated) +#endif + tcc_free(s->data); } /* realloc section and set its content to zero */ @@ -10276,6 +10272,51 @@ int tcc_relocate(TCCState *s1) #ifndef TCC_TARGET_PE build_got_entries(s1); #endif + +#ifdef TCC_TARGET_X86_64 + { + /* If the distance of two sections are longer than 32bit, our + program will crash. Let's combine all sections which are + necessary to run the program into a single buffer in the + text section */ + unsigned char *p; + int size; + /* calculate the size of buffers we need */ + size = 0; + for(i = 1; i < s1->nb_sections; i++) { + s = s1->sections[i]; + if (s->sh_flags & SHF_ALLOC) { + size += s->data_offset; + } + } + /* double the size of the buffer for got and plt entries + XXX: calculate exact size for them? */ + section_realloc(text_section, size * 2); + p = text_section->data + text_section->data_offset; + /* we will put got and plt after this offset */ + text_section->data_offset = size; + + for(i = 1; i < s1->nb_sections; i++) { + s = s1->sections[i]; + if (s->sh_flags & SHF_ALLOC) { + if (s != text_section && s->data_offset) { + if (s->sh_type == SHT_NOBITS) { + /* for bss section */ + memset(p, 0, s->data_offset); + } else { + memcpy(p, s->data, s->data_offset); + tcc_free(s->data); + } + s->data = p; + /* we won't free s->data for this section */ + s->data_allocated = 0; + p += s->data_offset; + } + s->sh_addr = (unsigned long)s->data; + } + } + } +#else /* compute relocation address : section are relocated in place. We also alloc the bss space */ for(i = 1; i < s1->nb_sections; i++) { @@ -10286,6 +10327,7 @@ int tcc_relocate(TCCState *s1) s->sh_addr = (unsigned long)s->data; } } +#endif relocate_syms(s1, 1); @@ -10505,11 +10547,6 @@ TCCState *tcc_new(void) /* XXX: currently the PE linker is not ready to support that */ s->leading_underscore = 1; #endif - -#ifdef TCC_TARGET_X86_64 - s->jmp_table = NULL; - s->got_table = NULL; -#endif return s; } @@ -10546,10 +10583,6 @@ void tcc_delete(TCCState *s1) dynarray_reset(&s1->include_paths, &s1->nb_include_paths); dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths); -#ifdef TCC_TARGET_X86_64 - tcc_free(s1->jmp_table); - tcc_free(s1->got_table); -#endif tcc_free(s1); } diff --git a/tccelf.c b/tccelf.c index 56ee75a1..6cf11e2b 100644 --- a/tccelf.c +++ b/tccelf.c @@ -479,22 +479,9 @@ static void relocate_syms(TCCState *s1, int do_resolve) #ifdef TCC_TARGET_X86_64 #define JMP_TABLE_ENTRY_SIZE 14 -#define JMP_TABLE_ENTRY_MAX_NUM 4096 static unsigned long add_jmp_table(TCCState *s1, unsigned long val) { - char *p; - if (!s1->jmp_table) { - int size = JMP_TABLE_ENTRY_SIZE * JMP_TABLE_ENTRY_MAX_NUM; - s1->jmp_table_num = 0; - s1->jmp_table = (char *)tcc_malloc(size); - set_pages_executable(s1->jmp_table, size); - } - if (s1->jmp_table_num == JMP_TABLE_ENTRY_MAX_NUM) { - error("relocating >%d symbols are not supported", - JMP_TABLE_ENTRY_MAX_NUM); - } - p = s1->jmp_table + s1->jmp_table_num * JMP_TABLE_ENTRY_SIZE; - s1->jmp_table_num++; + char *p = (char *)section_ptr_add(text_section, JMP_TABLE_ENTRY_SIZE); /* jmp *0x0(%rip) */ p[0] = 0xff; p[1] = 0x25; @@ -503,21 +490,10 @@ static unsigned long add_jmp_table(TCCState *s1, unsigned long 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++; + unsigned long *p = + (unsigned long *)section_ptr_add(text_section, sizeof(void *)); *p = val; return (unsigned long)p; } diff --git a/x86_64-gen.c b/x86_64-gen.c index 8e393728..1d0d8db6 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -91,7 +91,7 @@ int reg_classes[NB_REGS] = { #define EM_TCC_TARGET EM_X86_64 /* relocation type for 32 bit data relocation */ -#define R_DATA_32 R_X86_64_32 +#define R_DATA_32 R_X86_64_64 #define R_JMP_SLOT R_X86_64_JUMP_SLOT #define R_COPY R_X86_64_COPY -- 2.11.4.GIT