aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShinichiro Hamaji <shinichiro.hamaji _at_ gmail.com>2009-04-13 03:22:08 +0900
committergrischka <grischka>2009-04-18 15:08:01 +0200
commitfcf2e5981fe5e37e3aee633b414486311e54bc8e (patch)
treec6d2a56070f03622b184654bb2b37dc58a038ea8
parent830b7533c99f86203c4fbaf94897679678c3bad0 (diff)
downloadtinycc-fcf2e5981fe5e37e3aee633b414486311e54bc8e.tar.gz
tinycc-fcf2e5981fe5e37e3aee633b414486311e54bc8e.tar.bz2
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...).
-rw-r--r--tcc.c71
-rw-r--r--tccelf.c30
-rw-r--r--x86_64-gen.c2
3 files changed, 56 insertions, 47 deletions
diff --git a/tcc.c b/tcc.c
index 02da926..1b0b72b 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 56ee75a..6cf11e2 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 8e39372..1d0d8db 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