mirror of
https://github.com/mirror/tinycc.git
synced 2025-03-02 08:20:06 +08:00
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...).
This commit is contained in:
parent
830b7533c9
commit
fcf2e5981f
71
tcc.c
71
tcc.c
@ -542,15 +542,6 @@ struct TCCState {
|
|||||||
|
|
||||||
/* output file for preprocessing */
|
/* output file for preprocessing */
|
||||||
FILE *outfile;
|
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: */
|
/* 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)
|
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 */
|
/* realloc section and set its content to zero */
|
||||||
@ -10276,6 +10272,51 @@ int tcc_relocate(TCCState *s1)
|
|||||||
#ifndef TCC_TARGET_PE
|
#ifndef TCC_TARGET_PE
|
||||||
build_got_entries(s1);
|
build_got_entries(s1);
|
||||||
#endif
|
#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
|
/* compute relocation address : section are relocated in place. We
|
||||||
also alloc the bss space */
|
also alloc the bss space */
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
@ -10286,6 +10327,7 @@ int tcc_relocate(TCCState *s1)
|
|||||||
s->sh_addr = (unsigned long)s->data;
|
s->sh_addr = (unsigned long)s->data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
relocate_syms(s1, 1);
|
relocate_syms(s1, 1);
|
||||||
|
|
||||||
@ -10505,11 +10547,6 @@ TCCState *tcc_new(void)
|
|||||||
/* XXX: currently the PE linker is not ready to support that */
|
/* XXX: currently the PE linker is not ready to support that */
|
||||||
s->leading_underscore = 1;
|
s->leading_underscore = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
s->jmp_table = NULL;
|
|
||||||
s->got_table = NULL;
|
|
||||||
#endif
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10546,10 +10583,6 @@ void tcc_delete(TCCState *s1)
|
|||||||
dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
|
dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
|
||||||
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_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);
|
tcc_free(s1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
tccelf.c
30
tccelf.c
@ -479,22 +479,9 @@ static void relocate_syms(TCCState *s1, int do_resolve)
|
|||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
#define JMP_TABLE_ENTRY_SIZE 14
|
#define JMP_TABLE_ENTRY_SIZE 14
|
||||||
#define JMP_TABLE_ENTRY_MAX_NUM 4096
|
|
||||||
static unsigned long add_jmp_table(TCCState *s1, unsigned long val)
|
static unsigned long add_jmp_table(TCCState *s1, unsigned long val)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p = (char *)section_ptr_add(text_section, JMP_TABLE_ENTRY_SIZE);
|
||||||
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++;
|
|
||||||
/* jmp *0x0(%rip) */
|
/* jmp *0x0(%rip) */
|
||||||
p[0] = 0xff;
|
p[0] = 0xff;
|
||||||
p[1] = 0x25;
|
p[1] = 0x25;
|
||||||
@ -503,21 +490,10 @@ static unsigned long add_jmp_table(TCCState *s1, unsigned long val)
|
|||||||
return (unsigned long)p;
|
return (unsigned long)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GOT_TABLE_ENTRY_MAX_NUM 4096
|
|
||||||
static unsigned long add_got_table(TCCState *s1, unsigned long val)
|
static unsigned long add_got_table(TCCState *s1, unsigned long val)
|
||||||
{
|
{
|
||||||
unsigned long *p;
|
unsigned long *p =
|
||||||
if (!s1->got_table) {
|
(unsigned long *)section_ptr_add(text_section, sizeof(void *));
|
||||||
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;
|
*p = val;
|
||||||
return (unsigned long)p;
|
return (unsigned long)p;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ int reg_classes[NB_REGS] = {
|
|||||||
#define EM_TCC_TARGET EM_X86_64
|
#define EM_TCC_TARGET EM_X86_64
|
||||||
|
|
||||||
/* relocation type for 32 bit data relocation */
|
/* 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_JMP_SLOT R_X86_64_JUMP_SLOT
|
||||||
#define R_COPY R_X86_64_COPY
|
#define R_COPY R_X86_64_COPY
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user