mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-10 06:50:10 +08:00
alternative int tcc_relocate(TCCState *s1, void *ptr);
This commit is contained in:
parent
9a8b2912ed
commit
795f67428e
7
libtcc.h
7
libtcc.h
@ -84,9 +84,10 @@ int tcc_output_file(TCCState *s, const char *filename);
|
|||||||
tcc_relocate() before. */
|
tcc_relocate() before. */
|
||||||
int tcc_run(TCCState *s, int argc, char **argv);
|
int tcc_run(TCCState *s, int argc, char **argv);
|
||||||
|
|
||||||
/* do all relocations (needed before using tcc_get_symbol()). Return
|
/* copy code into memory passed in by the caller and do all relocations
|
||||||
non zero if link error. */
|
(needed before using tcc_get_symbol()).
|
||||||
int tcc_relocate(TCCState *s);
|
returns -1 on error and required size if ptr is NULL */
|
||||||
|
int tcc_relocate(TCCState *s1, void *ptr);
|
||||||
|
|
||||||
/* return symbol value. return 0 if OK, -1 if symbol not found */
|
/* return symbol value. return 0 if OK, -1 if symbol not found */
|
||||||
int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name);
|
int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name);
|
||||||
|
@ -36,6 +36,8 @@ int main(int argc, char **argv)
|
|||||||
TCCState *s;
|
TCCState *s;
|
||||||
int (*func)(int);
|
int (*func)(int);
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
|
void *mem;
|
||||||
|
int size;
|
||||||
|
|
||||||
s = tcc_new();
|
s = tcc_new();
|
||||||
if (!s) {
|
if (!s) {
|
||||||
@ -53,13 +55,25 @@ int main(int argc, char **argv)
|
|||||||
with tcc_add_dll(() and using its symbols directly. */
|
with tcc_add_dll(() and using its symbols directly. */
|
||||||
tcc_add_symbol(s, "add", (unsigned long)&add);
|
tcc_add_symbol(s, "add", (unsigned long)&add);
|
||||||
|
|
||||||
tcc_relocate(s);
|
/* get needed size of the code */
|
||||||
|
size = tcc_relocate(s, NULL);
|
||||||
|
if (size == -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* allocate memory and copy the code into it */
|
||||||
|
mem = malloc(size);
|
||||||
|
tcc_relocate(s, mem);
|
||||||
|
|
||||||
|
/* get entry symbol */
|
||||||
tcc_get_symbol(s, &val, "foo");
|
tcc_get_symbol(s, &val, "foo");
|
||||||
func = (void *)val;
|
func = (void *)val;
|
||||||
|
|
||||||
|
/* delete the state */
|
||||||
|
tcc_delete(s);
|
||||||
|
|
||||||
|
/* run the code */
|
||||||
func(32);
|
func(32);
|
||||||
|
|
||||||
tcc_delete(s);
|
free(mem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
129
tcc.c
129
tcc.c
@ -542,6 +542,9 @@ struct TCCState {
|
|||||||
|
|
||||||
/* output file for preprocessing */
|
/* output file for preprocessing */
|
||||||
FILE *outfile;
|
FILE *outfile;
|
||||||
|
|
||||||
|
/* for tcc_relocate */
|
||||||
|
int runtime_added;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The current value can be: */
|
/* The current value can be: */
|
||||||
@ -10277,88 +10280,61 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* do all relocations (needed before using tcc_get_symbol()) */
|
/* copy code into memory passed in by the caller and do all relocations
|
||||||
int tcc_relocate(TCCState *s1)
|
(needed before using tcc_get_symbol()).
|
||||||
|
returns -1 on error and required size if ptr is NULL */
|
||||||
|
int tcc_relocate(TCCState *s1, void *ptr)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
|
unsigned long offset, length, mem;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
s1->nb_errors = 0;
|
s1->nb_errors = 0;
|
||||||
|
|
||||||
|
if (0 == s1->runtime_added) {
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
pe_add_runtime(s1);
|
pe_add_runtime(s1);
|
||||||
|
relocate_common_syms();
|
||||||
|
tcc_add_linker_symbols(s1);
|
||||||
#else
|
#else
|
||||||
tcc_add_runtime(s1);
|
tcc_add_runtime(s1);
|
||||||
|
relocate_common_syms();
|
||||||
|
tcc_add_linker_symbols(s1);
|
||||||
|
build_got_entries(s1);
|
||||||
#endif
|
#endif
|
||||||
|
s1->runtime_added = 1;
|
||||||
relocate_common_syms();
|
|
||||||
|
|
||||||
tcc_add_linker_symbols(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
|
offset = 0;
|
||||||
also alloc the bss space */
|
mem = (unsigned long)ptr;
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
s = s1->sections[i];
|
s = s1->sections[i];
|
||||||
if (s->sh_flags & SHF_ALLOC) {
|
if (0 == (s->sh_flags & SHF_ALLOC))
|
||||||
|
continue;
|
||||||
|
length = s->data_offset;
|
||||||
|
if (0 == mem) {
|
||||||
|
s->sh_addr = 0;
|
||||||
|
} else if (1 == mem) {
|
||||||
|
/* section are relocated in place.
|
||||||
|
We also alloc the bss space */
|
||||||
if (s->sh_type == SHT_NOBITS)
|
if (s->sh_type == SHT_NOBITS)
|
||||||
s->data = tcc_mallocz(s->data_offset);
|
s->data = tcc_malloc(length);
|
||||||
s->sh_addr = (unsigned long)s->data;
|
s->sh_addr = (unsigned long)s->data;
|
||||||
|
} else {
|
||||||
|
/* sections are relocated to new memory */
|
||||||
|
s->sh_addr = (mem + offset + 15) & ~15;
|
||||||
}
|
}
|
||||||
|
offset = (offset + length + 15) & ~15;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
/* relocate symbols */
|
||||||
relocate_syms(s1, 1);
|
relocate_syms(s1, 1);
|
||||||
|
if (s1->nb_errors)
|
||||||
if (s1->nb_errors != 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (0 == mem)
|
||||||
|
return offset + 15;
|
||||||
|
|
||||||
/* relocate each section */
|
/* relocate each section */
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
s = s1->sections[i];
|
s = s1->sections[i];
|
||||||
@ -10366,12 +10342,20 @@ int tcc_relocate(TCCState *s1)
|
|||||||
relocate_section(s1, s);
|
relocate_section(s1, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mark executable sections as executable in memory */
|
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
s = s1->sections[i];
|
s = s1->sections[i];
|
||||||
if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
|
if (0 == (s->sh_flags & SHF_ALLOC))
|
||||||
(SHF_ALLOC | SHF_EXECINSTR))
|
continue;
|
||||||
set_pages_executable(s->data, s->data_offset);
|
length = s->data_offset;
|
||||||
|
// printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
|
||||||
|
ptr = (void*)s->sh_addr;
|
||||||
|
if (NULL == s->data || s->sh_type == SHT_NOBITS)
|
||||||
|
memset(ptr, 0, length);
|
||||||
|
else if (ptr != s->data)
|
||||||
|
memcpy(ptr, s->data, length);
|
||||||
|
/* mark executable sections as executable in memory */
|
||||||
|
if (s->sh_flags & SHF_EXECINSTR)
|
||||||
|
set_pages_executable(ptr, length);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -10380,9 +10364,14 @@ int tcc_relocate(TCCState *s1)
|
|||||||
int tcc_run(TCCState *s1, int argc, char **argv)
|
int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
{
|
{
|
||||||
int (*prog_main)(int, char **);
|
int (*prog_main)(int, char **);
|
||||||
|
void *ptr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (tcc_relocate(s1) < 0)
|
ret = tcc_relocate(s1, NULL);
|
||||||
|
if (ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
ptr = tcc_malloc(ret);
|
||||||
|
tcc_relocate(s1, ptr);
|
||||||
|
|
||||||
prog_main = tcc_get_symbol_err(s1, "main");
|
prog_main = tcc_get_symbol_err(s1, "main");
|
||||||
|
|
||||||
@ -10417,7 +10406,9 @@ int tcc_run(TCCState *s1, int argc, char **argv)
|
|||||||
bound_init();
|
bound_init();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return (*prog_main)(argc, argv);
|
ret = (*prog_main)(argc, argv);
|
||||||
|
tcc_free(ptr);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcc_memstats(void)
|
void tcc_memstats(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user