From 42395a19128b7db756721a55e4630ece82cb315b Mon Sep 17 00:00:00 2001 From: grischka Date: Thu, 29 Feb 2024 20:20:39 +0100 Subject: [PATCH] tccrun: PAGEALIGN'ed mprotect the un-mprotect() after run was severly off the limits. Also in tcc.c:main: do not confuse errors with non-zero results from tcc_run() --- configure | 1 + tcc.c | 27 +++++++++--------- tcc.h | 11 ++------ tccrun.c | 74 +++++++++++++++++++++++++++----------------------- tests/Makefile | 2 +- 5 files changed, 58 insertions(+), 57 deletions(-) diff --git a/configure b/configure index 6522195d..e7735a4e 100755 --- a/configure +++ b/configure @@ -518,6 +518,7 @@ fcho "Doc directory " "$docdir" fcho "Target root prefix " "$sysroot" fcho "/usr/include dir " "$tcc_usrinclude" echo "Source path $source_path" +echo "Build OS $(uname -m -s)" echo "C compiler $cc ($gcc_major.$gcc_minor)" echo "Target OS $targetos" echo "CPU $cpu" diff --git a/tcc.c b/tcc.c index f5cd1d8e..263beba9 100644 --- a/tcc.c +++ b/tcc.c @@ -359,20 +359,18 @@ redo: } /* compile or add each files or library */ - first_file = NULL, ret = 0; + first_file = NULL; do { struct filespec *f = s->files[n]; s->filetype = f->type; if (f->type & AFF_TYPE_LIB) { - if (tcc_add_library_err(s, f->name) < 0) - ret = 1; + ret = tcc_add_library_err(s, f->name); } else { if (1 == s->verbose) printf("-> %s\n", f->name); if (!first_file) first_file = f->name; - if (tcc_add_file(s, f->name) < 0) - ret = 1; + ret = tcc_add_file(s, f->name); } done = ret || ++n >= s->nb_files; } while (!done && (s->output_type != TCC_OUTPUT_OBJ || s->option_r)); @@ -393,21 +391,24 @@ redo: if (!s->outfile) s->outfile = default_outputfile(s, first_file); if (!s->just_deps && tcc_output_file(s, s->outfile)) - ret = 1; + ; else if (s->gen_deps) - ret = gen_makedeps(s, s->outfile, s->deps_outfile); + gen_makedeps(s, s->outfile, s->deps_outfile); } } - if (done && 0 == t && 0 == ret && s->do_bench) + done = 1; + if (t) + done = 0; /* run more tests with -dt -run */ + else if (s->nb_errors) + ret = 1; + else if (n < s->nb_files) + done = 0; /* compile more files with -c */ + else if (s->do_bench) tcc_print_stats(s, end_time - start_time); - tcc_delete(s); if (!done) - goto redo; /* compile more files with -c */ - if (t) - goto redo; /* run more tests with -dt -run */ - + goto redo; if (ppfp && ppfp != stdout) fclose(ppfp); return ret; diff --git a/tcc.h b/tcc.h index 4200f357..77200e92 100644 --- a/tcc.h +++ b/tcc.h @@ -92,14 +92,6 @@ extern long double strtold (const char *__nptr, char **__endptr); # undef CONFIG_TCC_STATIC #endif -#ifndef PAGESIZE -# ifdef _SC_PAGESIZE -# define PAGESIZE sysconf(_SC_PAGESIZE) -# else -# define PAGESIZE 4096 -# endif -#endif - #ifndef O_BINARY # define O_BINARY 0 #endif @@ -995,7 +987,8 @@ struct TCCState { #ifdef TCC_IS_NATIVE const char *run_main; /* entry for tcc_run() */ - void *run_ptr; /* ptr to runtime_memory */ + void *run_mem; /* runtime_memory */ + void *run_ptr; /* ptr to runtime_memory (aligned) */ unsigned run_size; /* size of runtime_memory */ #ifdef _WIN64 void *run_function_table; /* unwind data */ diff --git a/tccrun.c b/tccrun.c index b27ccc59..03e752aa 100644 --- a/tccrun.c +++ b/tccrun.c @@ -91,6 +91,19 @@ static void *win64_add_function_table(TCCState *s1); static void win64_del_function_table(void *); #endif +#if !defined PAGESIZE +# if defined _SC_PAGESIZE +# define PAGESIZE sysconf(_SC_PAGESIZE) +# elif defined __APPLE__ +# include +# define PAGESIZE getpagesize() +# else +# define PAGESIZE 4096 +# endif +#endif + +#define PAGEALIGN(n) ((addr_t)n + (-(addr_t)n & (PAGESIZE-1))) + #if !_WIN32 && !__APPLE__ //#define HAVE_SELINUX 1 #endif @@ -116,7 +129,8 @@ static int rt_mem(TCCState *s1, int size) ptr_diff = (char*)prw - (char*)ptr; /* = size; */ //printf("map %p %p %p\n", ptr, prw, (void*)ptr_diff); #else - ptr = tcc_malloc(size += PAGESIZE); /* one extra page to align malloc memory */ + s1->run_mem = tcc_malloc(size + PAGESIZE); /* one extra page to align malloc memory */ + ptr = (void*)PAGEALIGN(s1->run_mem); #endif s1->run_ptr = ptr; s1->run_size = size; @@ -181,7 +195,7 @@ ST_FUNC void tcc_run_free(TCCState *s1) # ifdef _WIN64 win64_del_function_table(s1->run_function_table); # endif - tcc_free(ptr); + tcc_free(s1->run_mem); #endif } @@ -214,11 +228,11 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) top_sym = "main"; } if (tcc_relocate(s1) < 0) - return 1; + return -1; prog_main = (void*)get_sym_addr(s1, s1->run_main, 1, 1); if ((addr_t)-1 == (addr_t)prog_main) - return 1; + return -1; errno = 0; /* clean errno value */ fflush(stdout); fflush(stderr); @@ -274,12 +288,9 @@ static void cleanup_sections(TCCState *s1) /* ------------------------------------------------------------- */ /* 0 = .text rwx other rw */ /* 1 = .text rx .rdata r .data/.bss rw */ + #ifndef CONFIG_RUNMEM_RO -# ifdef _WIN32 -# define CONFIG_RUNMEM_RO 0 -# else -# define CONFIG_RUNMEM_RO 1 -# endif +# define CONFIG_RUNMEM_RO 0 #endif /* relocate code. Return -1 on error, required size if ptr is NULL, @@ -304,14 +315,11 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff) offset = copy = 0; mem = (addr_t)ptr; redo: - if (s1->verbose == 2 && copy) { + if (s1->verbose == 2 && copy) printf(&"-----------------------------------------------------\n"[PTR_SIZE*2 - 8]); - if (1 == copy) - printf("memory %p len %05x\n", ptr, s1->run_size); - } if (s1->nb_errors) return -1; - if (copy == 2) + if (copy == 3) return 0; for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */ @@ -324,14 +332,16 @@ redo: if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR))) continue; length = s->data_offset; - + if (copy == 2) { + if (addr == 0) + addr = s->sh_addr; + n = (s->sh_addr - addr) + length; + continue; + } if (copy) { /* final step: copy section data to memory */ if (s1->verbose == 2) printf("%d: %-16s %p len %05x align %04x\n", k, s->name, (void*)s->sh_addr, length, s->sh_addralign); - if (addr == 0) - addr = s->sh_addr; - n = (s->sh_addr - addr) + length; ptr = (void*)s->sh_addr; if (k == 0) ptr = (void*)(s->sh_addr + ptr_diff); @@ -339,10 +349,6 @@ redo: memset(ptr, 0, length); else memcpy(ptr, s->data, length); -#ifdef _WIN64 - if (s == s1->uw_pdata) - s1->run_function_table = win64_add_function_table(s1); -#endif continue; } @@ -360,13 +366,12 @@ redo: align = PAGESIZE; } s->sh_addralign = align; - addr = k ? mem + ptr_diff : mem; offset += -(addr + offset) & (align - 1); s->sh_addr = mem ? addr + offset : 0; offset += length; } - if (copy) { /* set permissions */ + if (copy == 2) { /* set permissions */ if (n == 0) /* no data */ continue; #ifdef HAVE_SELINUX @@ -379,10 +384,10 @@ redo: continue; f = 3; /* change only SHF_EXECINSTR to rwx */ } - n = (n + PAGESIZE-1) & ~(PAGESIZE-1); + n = PAGEALIGN(n); if (s1->verbose == 2) { printf("protect %3s %p len %05x\n", - &"rx\0r \0rw\0rwx"[f*3], (void*)addr, (unsigned)n); + &"rx\0ro\0rw\0rwx"[f*3], (void*)addr, (unsigned)n); } if (protect_pages((void*)addr, n, f) < 0) return tcc_error_noabort( @@ -391,9 +396,15 @@ redo: } if (0 == mem) - return (offset + (PAGESIZE-1)) & ~(PAGESIZE-1); + return PAGEALIGN(offset); if (++copy == 2) { + goto redo; + } + if (copy == 3) { +#ifdef _WIN64 + s1->run_function_table = win64_add_function_table(s1); +#endif /* remove local symbols and free sections except symtab */ cleanup_symbols(s1); cleanup_sections(s1); @@ -427,7 +438,6 @@ static int protect_pages(void *ptr, unsigned long length, int mode) DWORD old; if (!VirtualProtect(ptr, length, protect[mode], &old)) return -1; - return 0; #else static const unsigned char protect[] = { PROT_READ | PROT_EXEC, @@ -435,11 +445,7 @@ static int protect_pages(void *ptr, unsigned long length, int mode) PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE | PROT_EXEC }; - addr_t start, end; - start = (addr_t)ptr & ~(PAGESIZE - 1); - end = (addr_t)ptr + length; - end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); - if (mprotect((void *)start, end - start, protect[mode])) + if (mprotect(ptr, length, protect[mode])) return -1; /* XXX: BSD sometimes dump core with bad system call */ # if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64 @@ -448,8 +454,8 @@ static int protect_pages(void *ptr, unsigned long length, int mode) __clear_cache(ptr, (char *)ptr + length); } # endif - return 0; #endif + return 0; } #ifdef _WIN64 diff --git a/tests/Makefile b/tests/Makefile index 3906bf5a..c89e2988 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -207,7 +207,7 @@ tccb: $(TCC) -b $(TOPSRC)/tcc.c $(TCCFLAGS) $(NATIVE_DEFINES) -o tccb1.exe mv tccb1.exe tccb2.exe ./tccb2.exe -b $(TOPSRC)/tcc.c $(TCCFLAGS) $(NATIVE_DEFINES) -o tccb1.exe - cmp -s tccb1.exe tccb2.exe && echo "Exe Bound-Rest OK" + cmp -s tccb1.exe tccb2.exe && echo "Exe Bound-Test OK" # speed test