diff --git a/arm-asm.c b/arm-asm.c index 314ce5c1..45ccab5d 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -2826,7 +2826,7 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, // TODO: Check non-E ABI. // Note: Technically, r13 (sp) is also callee-saved--but that does not matter yet - static uint8_t reg_saved[] = { 4, 5, 6, 7, 8, 9 /* Note: sometimes special reg "sb" */ , 10, 11 }; + static const uint8_t reg_saved[] = { 4, 5, 6, 7, 8, 9 /* Note: sometimes special reg "sb" */ , 10, 11 }; /* mark all used registers */ memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated)); diff --git a/arm-gen.c b/arm-gen.c index bc308c2f..2b2e6261 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -141,7 +141,7 @@ enum { #define USING_GLOBALS #include "tcc.h" -ST_DATA const char *target_machine_defs = +ST_DATA const char * const target_machine_defs = "__arm__\0" "__arm\0" "arm\0" diff --git a/arm64-gen.c b/arm64-gen.c index ca38b3a6..8edbfff6 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -50,7 +50,7 @@ #include "tcc.h" #include -ST_DATA const char *target_machine_defs = +ST_DATA const char * const target_machine_defs = "__aarch64__\0" ; diff --git a/c67-gen.c b/c67-gen.c index 6ebe7181..9490a27f 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -116,7 +116,7 @@ enum { #define USING_GLOBALS #include "tcc.h" -ST_DATA const char *target_machine_defs = +ST_DATA const char * const target_machine_defs = "__C67__\0" ; @@ -371,7 +371,7 @@ int C67_map_D12(char *s) -void C67_asm(char *s, int a, int b, int c) +void C67_asm(const char *s, int a, int b, int c) { BOOL xpath; diff --git a/i386-asm.c b/i386-asm.c index 23e1fbbb..aca6c97e 100644 --- a/i386-asm.c +++ b/i386-asm.c @@ -638,10 +638,12 @@ static void asm_rex(int width64, Operand *ops, int nb_ops, int *op_type, } #endif + static void maybe_print_stats (void) { - static int already = 1; - if (!already) + static int already; + + if (0 && !already) /* print stats about opcodes */ { const struct ASMInstr *pa; @@ -1604,12 +1606,12 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, call-preserved registers, but currently it doesn't matter. */ #ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_PE - static uint8_t reg_saved[] = { 3, 6, 7, 12, 13, 14, 15 }; + static const uint8_t reg_saved[] = { 3, 6, 7, 12, 13, 14, 15 }; #else - static uint8_t reg_saved[] = { 3, 12, 13, 14, 15 }; + static const uint8_t reg_saved[] = { 3, 12, 13, 14, 15 }; #endif #else - static uint8_t reg_saved[] = { 3, 6, 7 }; + static const uint8_t reg_saved[] = { 3, 6, 7 }; #endif /* mark all used registers */ diff --git a/i386-gen.c b/i386-gen.c index 2f32944e..8c245ada 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -81,7 +81,7 @@ enum { #define USING_GLOBALS #include "tcc.h" -ST_DATA const char *target_machine_defs = +ST_DATA const char * const target_machine_defs = "__i386__\0" "__i386\0" ; @@ -372,8 +372,8 @@ static void gcall_or_jmp(int is_jmp) } } -static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX }; -static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; +static const uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX }; +static const uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ @@ -479,7 +479,7 @@ ST_FUNC void gfunc_call(int nb_args) if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || func_call == FUNC_FASTCALLW) { int fastcall_nb_regs; - uint8_t *fastcall_regs_ptr; + const uint8_t *fastcall_regs_ptr; if (func_call == FUNC_FASTCALLW) { fastcall_regs_ptr = fastcallw_regs; fastcall_nb_regs = 2; @@ -519,7 +519,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) CType *func_type = &func_sym->type; int addr, align, size, func_call, fastcall_nb_regs; int param_index, param_addr; - uint8_t *fastcall_regs_ptr; + const uint8_t *fastcall_regs_ptr; Sym *sym; CType *type; diff --git a/libtcc.c b/libtcc.c index 56fe65a1..ec33591a 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1580,7 +1580,7 @@ static const TCCOption tcc_options[] = { static const FlagDef options_W[] = { { 0, 0, "all" }, { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, - { offsetof(TCCState, warn_write_strings), 0, "write-strings" }, + { offsetof(TCCState, warn_write_strings), WD_ALL, "write-strings" }, { offsetof(TCCState, warn_error), 0, "error" }, { offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" }, { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, @@ -1997,8 +1997,12 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time) (double)total_time/1000, (unsigned)total_lines*1000/total_time, (double)total_bytes/1000/total_time); - fprintf(stderr, "* text %d, data %d, bss %d bytes\n", - s1->total_output[0], s1->total_output[1], s1->total_output[2]); + fprintf(stderr, "* text %d, data.rw %d, data.ro %d, bss %d bytes\n", + s1->total_output[0], + s1->total_output[1], + s1->total_output[2], + s1->total_output[3] + ); #ifdef MEM_DEBUG fprintf(stderr, "* %d bytes memory used\n", mem_max_size); #endif diff --git a/riscv64-gen.c b/riscv64-gen.c index 8cbfcb77..54e52bfe 100644 --- a/riscv64-gen.c +++ b/riscv64-gen.c @@ -36,7 +36,7 @@ #include "tcc.h" #include -ST_DATA const char *target_machine_defs = +ST_DATA const char * const target_machine_defs = "__riscv\0" "__riscv_xlen 64\0" "__riscv_flen 64\0" diff --git a/tcc.h b/tcc.h index 81c1fc37..e97e4d0b 100644 --- a/tcc.h +++ b/tcc.h @@ -885,7 +885,7 @@ struct TCCState { Section *plt; /* predefined sections */ - Section *text_section, *data_section, *data_ro_section, *bss_section; + Section *text_section, *data_section, *rodata_section, *bss_section; Section *common_section; Section *cur_text_section; /* current section where function code is generated */ #ifdef CONFIG_TCC_BCHECK @@ -960,7 +960,7 @@ struct TCCState { int total_idents; int total_lines; int total_bytes; - int total_output[3]; + int total_output[4]; /* option -dnum (for general development purposes) */ int g_debug; @@ -1639,7 +1639,7 @@ ST_FUNC void relocate_plt(TCCState *s1); ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val); /* ------------ xxx-gen.c ------------ */ -ST_DATA const char *target_machine_defs; +ST_DATA const char * const target_machine_defs; ST_DATA const int reg_classes[NB_REGS]; ST_FUNC void gsym_addr(int t, int a); @@ -1842,7 +1842,7 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) #define text_section TCC_STATE_VAR(text_section) #define data_section TCC_STATE_VAR(data_section) -#define data_ro_section TCC_STATE_VAR(data_ro_section) +#define rodata_section TCC_STATE_VAR(rodata_section) #define bss_section TCC_STATE_VAR(bss_section) #define common_section TCC_STATE_VAR(common_section) #define cur_text_section TCC_STATE_VAR(cur_text_section) diff --git a/tccelf.c b/tccelf.c index b6ed54e3..c7a8022b 100644 --- a/tccelf.c +++ b/tccelf.c @@ -58,8 +58,12 @@ ST_FUNC void tccelf_new(TCCState *s) /* create standard sections */ text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); +#ifdef TCC_TARGET_PE + rodata_section = new_section(s, ".rdata", SHT_PROGBITS, SHF_ALLOC); +#else /* create ro data section (make ro after relocation done with GNU_RELRO) */ - data_ro_section = new_section(s, ".data.ro", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); + rodata_section = new_section(s, ".data.ro", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); +#endif bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); common_section->sh_num = SHN_COMMON; @@ -206,7 +210,7 @@ ST_FUNC void tccelf_end_file(TCCState *s1) tcc_free(tr); /* record text/data/bss output for -bench info */ - for (i = 0; i < 3; ++i) { + for (i = 0; i < 4; ++i) { s = s1->sections[i + 1]; s1->total_output[i] += s->data_offset - s->sh_offset; } @@ -1255,11 +1259,16 @@ redo: && ELFW(ST_TYPE)(sym->st_info) == STT_FUNC))) goto jmp_slot; } - } else if (!(sym->st_shndx == SHN_ABS + } else if (sym->st_shndx == SHN_ABS) { + if (sym->st_value == 0) /* from tcc_add_btstub() */ + continue; #ifndef TCC_TARGET_ARM - && PTR_SIZE == 8 + if (PTR_SIZE != 8) + continue; #endif - )) + /* from tcc_add_symbol(): on 64 bit platforms these + need to go through .got */ + } else continue; } @@ -1314,7 +1323,7 @@ redo: ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs) { - int shn = sec ? sec->sh_num : offs ? SHN_ABS : SHN_UNDEF; + int shn = sec ? sec->sh_num : offs || !name ? SHN_ABS : SHN_UNDEF; if (sec && offs == -1) offs = sec->data_offset; return set_elf_sym(symtab_section, offs, 0, @@ -1326,7 +1335,7 @@ static void add_init_array_defines(TCCState *s1, const char *section_name) Section *s; addr_t end_offset; char buf[1024]; - s = find_section(s1, section_name); + s = find_section_create(s1, section_name, 0); if (!s) { end_offset = 0; s = data_section; @@ -1407,12 +1416,8 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) put_ptr(s1, stab_section, -1); put_ptr(s1, stab_section->link, 0); section_ptr_add(s, 3 * PTR_SIZE); - /* prog_base */ -#ifndef TCC_TARGET_MACHO - /* XXX this relocation is wrong, it uses sym-index 0 (local,undef) */ - put_elf_reloc(s1->symtab, s, s->data_offset, R_DATA_PTR, 0); -#endif - section_ptr_add(s, PTR_SIZE); + /* prog_base : local nameless symbol with offset 0 at SHN_ABS */ + put_ptr(s1, NULL, 0); n = 2 * PTR_SIZE; #ifdef CONFIG_TCC_BCHECK if (s1->do_bounds_check) { @@ -1421,10 +1426,10 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) } #endif section_ptr_add(s, n); - cstr_new(&cstr); cstr_printf(&cstr, - " extern void __bt_init(),*__rt_info[],__bt_init_dll();" + "extern void __bt_init(),__bt_init_dll();" + "static void *__rt_info[];" "__attribute__((constructor)) static void __bt_init_rt(){"); #ifdef TCC_TARGET_PE if (s1->output_type == TCC_OUTPUT_DLL) @@ -1526,8 +1531,9 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) tcc_add_btstub(s1); } #endif - if (strlen(TCC_LIBTCC1) > 0) + if (TCC_LIBTCC1[0]) tcc_add_support(s1, TCC_LIBTCC1); + #if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD /* add crt end if not memory output */ if (s1->output_type != TCC_OUTPUT_MEMORY) { @@ -1568,7 +1574,9 @@ static void tcc_add_linker_symbols(TCCState *s1) set_global_sym(s1, "__global_pointer$", data_section, 0x800); #endif /* horrible new standard ldscript defines */ +#ifndef TCC_TARGET_PE add_init_array_defines(s1, ".preinit_array"); +#endif add_init_array_defines(s1, ".init_array"); add_init_array_defines(s1, ".fini_array"); /* add start and stop symbols for sections whose name can be @@ -1996,12 +2004,12 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, } else if (s->sh_type == SHT_NOBITS) { if (k != 6) continue; - } else if (s == data_ro_section || + } else if ((s == rodata_section #ifdef CONFIG_TCC_BCHECK - s == bounds_section || - s == lbounds_section || + || s == bounds_section + || s == lbounds_section #endif - 0) { + ) && (s->sh_flags & SHF_WRITE)) { if (k != 4) continue; /* Align next section on page size. @@ -2029,18 +2037,15 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, ph->p_vaddr = addr; ph->p_paddr = ph->p_vaddr; } - if (s == data_ro_section || -#ifdef CONFIG_TCC_BCHECK - s == bounds_section || - s == lbounds_section || -#endif - 0) { + + if (k == 4) { if (roinf->sh_size == 0) { roinf->sh_offset = s->sh_offset; roinf->sh_addr = s->sh_addr; } roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size; } + addr += s->sh_size; if (s->sh_type != SHT_NOBITS) file_offset += s->sh_size; diff --git a/tccgen.c b/tccgen.c index 7cf40fa4..739670c8 100644 --- a/tccgen.c +++ b/tccgen.c @@ -2356,7 +2356,7 @@ ST_FUNC int gv(int rc) (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { /* CPUs usually cannot use float constants, so we store them generically in data segment */ - init_params p = { data_section }; + init_params p = { rodata_section }; unsigned long offset; size = type_size(&vtop->type, &align); if (NODATA_WANTED) @@ -3095,11 +3095,12 @@ static void type_to_str(char *buf, int buf_size, pstrcat(buf, buf_size, "typedef "); if (t & VT_INLINE) pstrcat(buf, buf_size, "inline "); - if (t & VT_VOLATILE) - pstrcat(buf, buf_size, "volatile "); - if (t & VT_CONSTANT) - pstrcat(buf, buf_size, "const "); - + if (bt != VT_PTR) { + if (t & VT_VOLATILE) + pstrcat(buf, buf_size, "volatile "); + if (t & VT_CONSTANT) + pstrcat(buf, buf_size, "const "); + } if (((t & VT_DEFSIGN) && bt == VT_BYTE) || ((t & VT_UNSIGNED) && (bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG) @@ -5932,18 +5933,22 @@ ST_FUNC void unary(void) /* fall thru */ case TOK___FUNC__: { + Section *sec; void *ptr; int len; /* special function name identifier */ len = strlen(funcname) + 1; /* generate char[len] type */ type.t = VT_BYTE; + if (tcc_state->warn_write_strings) + type.t |= VT_CONSTANT; mk_pointer(&type); type.t |= VT_ARRAY; type.ref->c = len; - vpush_ref(&type, data_section, data_section->data_offset, len); + sec = rodata_section; + vpush_ref(&type, sec, sec->data_offset, len); if (!NODATA_WANTED) { - ptr = section_ptr_add(data_section, len); + ptr = section_ptr_add(sec, len); memcpy(ptr, funcname, len); } next(); @@ -5968,6 +5973,7 @@ ST_FUNC void unary(void) mk_pointer(&type); type.t |= VT_ARRAY; memset(&ad, 0, sizeof(AttributeDef)); + ad.section = rodata_section; decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0); break; case '(': @@ -8526,11 +8532,16 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, /* allocate symbol in corresponding section */ sec = ad->section; if (!sec) { - if (type->t & VT_CONSTANT) - sec = data_ro_section; - else if (has_init) + CType *tp = type; + while ((tp->t & (VT_BTYPE|VT_ARRAY)) == (VT_PTR|VT_ARRAY)) + tp = &tp->ref->type; + if (tp->t & VT_CONSTANT) { + sec = rodata_section; + } else if (has_init) { sec = data_section; - else if (tcc_state->nocommon) + /*if (tcc_state->g_debug & 4) + tcc_warning("rw data: %s", get_tok_str(v, 0));*/ + } else if (tcc_state->nocommon) sec = bss_section; } diff --git a/tccmacho.c b/tccmacho.c index ebc5091b..bf6b5f69 100644 --- a/tccmacho.c +++ b/tccmacho.c @@ -259,7 +259,7 @@ static void * add_lc(struct macho *mo, uint32_t cmd, uint32_t cmdsize) return lc; } -static struct segment_command_64 * add_segment(struct macho *mo, char *name) +static struct segment_command_64 * add_segment(struct macho *mo, const char *name) { struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc)); strncpy(sc->segname, name, 16); @@ -272,7 +272,7 @@ static struct segment_command_64 * get_segment(struct macho *mo, int i) return (struct segment_command_64 *) (mo->lc[mo->seg2lc[i]]); } -static int add_section(struct macho *mo, struct segment_command_64 **_seg, char *name) +static int add_section(struct macho *mo, struct segment_command_64 **_seg, const char *name) { struct segment_command_64 *seg = *_seg; int ret = seg->nsects; @@ -525,10 +525,10 @@ static void create_symtab(TCCState *s1, struct macho *mo) } } -struct { +const struct { int seg; uint32_t flags; - char *name; + const char *name; } skinfo[sk_last] = { /*[sk_unknown] =*/ { 0 }, /*[sk_discard] =*/ { 0 }, diff --git a/tccpe.c b/tccpe.c index 70b83ed8..df57f71c 100644 --- a/tccpe.c +++ b/tccpe.c @@ -20,8 +20,8 @@ #include "tcc.h" -#define PE_MERGE_DATA -/* #define PE_PRINT_SECTIONS */ +#define PE_MERGE_DATA 1 +#define PE_PRINT_SECTIONS 0 #ifndef _WIN32 #define stricmp strcasecmp @@ -294,6 +294,7 @@ struct pe_rsrc_reloc { enum { sec_text = 0, + sec_rdata , sec_data , sec_bss , sec_idata , @@ -725,6 +726,8 @@ static int pe_write(struct pe_info *pe) for (i = 0; i < pe->sec_count; ++i) { Section *s; si = pe->sec_info[i]; + if (!si->data_size) + continue; for (s = si->sec; s; s = s->prev) { pe_fpad(&pf, file_offset); pe_fwrite(s->data, s->data_offset, &pf); @@ -1084,6 +1087,7 @@ static int pe_section_class(Section *s) return sec_idata; if (0 == strcmp(name, ".pdata")) return sec_pdata; + return sec_rdata; } else if (type == SHT_NOBITS) { if (flags & SHF_WRITE) return sec_bss; @@ -1106,6 +1110,7 @@ static int pe_assign_addresses (struct pe_info *pe) int *section_order; struct section_info *si; Section *s; + TCCState *s1 = pe->s1; if (PE_DLL == pe->type) pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0); @@ -1113,8 +1118,8 @@ static int pe_assign_addresses (struct pe_info *pe) section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int)); for (o = k = 0 ; k < sec_last; ++k) { - for (i = 1; i < pe->s1->nb_sections; ++i) { - s = pe->s1->sections[i]; + for (i = 1; i < s1->nb_sections; ++i) { + s = s1->sections[i]; if (k == pe_section_class(s)) section_order[o++] = i; } @@ -1125,16 +1130,15 @@ static int pe_assign_addresses (struct pe_info *pe) for (i = 0; i < o; ++i) { k = section_order[i]; - s = pe->s1->sections[k]; + s = s1->sections[k]; c = pe_section_class(s); - if ((c == sec_stab || c == sec_stabstr) && 0 == pe->s1->do_debug) + if ((c == sec_stab || c == sec_stabstr) && 0 == s1->do_debug) continue; -#ifdef PE_MERGE_DATA - if (c == sec_bss) + if (PE_MERGE_DATA && c == sec_bss) c = sec_data; -#endif + if (si && c == si->cls) { /* merge with previous section */ s->sh_addr = addr = ((addr - 1) | (16 - 1)) + 1; @@ -1143,7 +1147,8 @@ static int pe_assign_addresses (struct pe_info *pe) s->sh_addr = addr = pe_virtual_align(pe, addr); } - if (c == sec_data && NULL == pe->thunk) + if (NULL == pe->thunk + && c == (data_section == rodata_section ? sec_data : sec_rdata)) pe->thunk = s; if (s == pe->thunk) { @@ -1192,8 +1197,8 @@ add_section: } tcc_free(section_order); #if 0 - for (i = 1; i < pe->s1->nb_sections; ++i) { - Section *s = pe->s1->sections[i]; + for (i = 1; i < s1->nb_sections; ++i) { + Section *s = s1->sections[i]; int type = s->sh_type; int flags = s->sh_flags; printf("section %-16s %-10s %08x %04x %s,%s,%s\n", @@ -1210,7 +1215,7 @@ add_section: flags & SHF_EXECINSTR ? "exec" : "" ); } - pe->s1->verbose = 2; + s1->verbose = 2; #endif return 0; } @@ -1345,7 +1350,7 @@ static int pe_check_symbols(struct pe_info *pe) } /*----------------------------------------------------------------------------*/ -#ifdef PE_PRINT_SECTIONS +#if PE_PRINT_SECTIONS static void pe_print_section(FILE * f, Section * s) { /* just if you're curious */ @@ -1923,11 +1928,11 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) set_global_sym(s1, start_symbol, NULL, 0); if (0 == s1->nostdlib) { - static const char *libs[] = { + static const char * const libs[] = { "msvcrt", "kernel32", "", "user32", "gdi32", NULL }; - const char **pp, *p; - if (strlen(TCC_LIBTCC1) > 0) + const char * const *pp, *p; + if (TCC_LIBTCC1[0]) tcc_add_support(s1, TCC_LIBTCC1); for (pp = libs; 0 != (p = *pp); ++pp) { if (*p) @@ -2038,8 +2043,9 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) pe_free_imports(&pe); -#ifdef PE_PRINT_SECTIONS - pe_print_sections(s1, "tcc.log"); +#if PE_PRINT_SECTIONS + if (s1->g_debug & 8) + pe_print_sections(s1, "tcc.log"); #endif return ret; } diff --git a/tccpp.c b/tccpp.c index 24de7d90..46c5ece4 100644 --- a/tccpp.c +++ b/tccpp.c @@ -3669,7 +3669,7 @@ ST_INLN void unget_tok(int last_tok) /* ------------------------------------------------------------------------- */ /* init preprocessor */ -static const char *target_os_defs = +static const char * const target_os_defs = #ifdef TCC_TARGET_PE "_WIN32\0" # if PTR_SIZE == 8 diff --git a/tccrun.c b/tccrun.c index 4eeb3f1e..ffb3c685 100644 --- a/tccrun.c +++ b/tccrun.c @@ -55,7 +55,7 @@ static void rt_exit(int code); # include #endif -static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length); +static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length); static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff); #ifdef _WIN64 @@ -94,7 +94,6 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) prx = mmap((char*)ptr + size, size, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_FIXED, fd, 0); if (ptr == MAP_FAILED || prx == MAP_FAILED) tcc_error("tccrun: could not map memory"); - dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)(size*2)); ptr_diff = (char*)prx - (char*)ptr; close(fd); //printf("map %p %p %p\n", ptr, prx, (void*)ptr_diff); @@ -103,6 +102,7 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) ptr = tcc_malloc(size); #endif tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */ + dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size); dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr); return 0; } @@ -111,15 +111,18 @@ ST_FUNC void tcc_run_free(TCCState *s1) { int i; - for (i = 0; i < s1->nb_runtime_mem; ++i) { + for (i = 0; i < s1->nb_runtime_mem; i += 2) { + unsigned size = (unsigned)(addr_t)s1->runtime_mem[i]; + void *ptr = s1->runtime_mem[i+1]; #ifdef HAVE_SELINUX - unsigned size = (unsigned)(addr_t)s1->runtime_mem[i++]; - munmap(s1->runtime_mem[i], size); + munmap(ptr, size * 2); #else + /* unprotect memory to make it usable for malloc again */ + set_pages_executable(s1, 2, ptr, size); #ifdef _WIN64 - win64_del_function_table(*(void**)s1->runtime_mem[i]); + win64_del_function_table(*(void**)ptr); #endif - tcc_free(s1->runtime_mem[i]); + tcc_free(ptr); #endif } tcc_free(s1->runtime_mem); @@ -182,8 +185,9 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) *(void**)p = _rt_error; #ifdef CONFIG_TCC_BCHECK if (s1->do_bounds_check) { + rc->bounds_start = (void*)bounds_section->sh_addr; if ((p = tcc_get_symbol(s1, "__bound_init"))) - ((void(*)(addr_t, int))p)(bounds_section->sh_addr, 1); + ((void(*)(void*,int))p)(rc->bounds_start, 1); } #endif set_exception_handler(); @@ -207,13 +211,20 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) return ret; } -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 +#define DEBUG_RUNMEN 0 + +/* enable rx/ro/rw permissions */ +#define CONFIG_RUNMEM_RO 1 + +#if CONFIG_RUNMEM_RO +# define PAGE_ALIGN PAGESIZE +#elif defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 /* To avoid that x86 processors would reload cached instructions each time when data is written in the near, we need to make sure that code and data do not share the same 64 byte unit */ - #define RUN_SECTION_ALIGNMENT 63 +# define PAGE_ALIGN 64 #else - #define RUN_SECTION_ALIGNMENT 0 +# define PAGE_ALIGN 1 #endif /* relocate code. Return -1 on error, required size if ptr is NULL, @@ -222,6 +233,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) { Section *s; unsigned offset, length, align, max_align, i, k, f; + unsigned n, copy; addr_t mem, addr; if (NULL == ptr) { @@ -241,35 +253,80 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) #ifdef _WIN64 offset += sizeof (void*); /* space for function_table pointer */ #endif - for (k = 0; k < 2; ++k) { - f = 0, addr = k ? mem : mem + ptr_diff; + copy = 0; +redo: + for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */ + n = 0; addr = 0; for(i = 1; i < s1->nb_sections; i++) { + static const char shf[] = { + SHF_ALLOC|SHF_EXECINSTR, SHF_ALLOC, SHF_ALLOC|SHF_WRITE + }; s = s1->sections[i]; - if (0 == (s->sh_flags & SHF_ALLOC)) + if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR))) continue; - if (k != !(s->sh_flags & SHF_EXECINSTR)) + length = s->data_offset; + if (copy) { + 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); + if (NULL == s->data || s->sh_type == SHT_NOBITS) + memset(ptr, 0, length); + else + memcpy(ptr, s->data, length); +#ifdef _WIN64 + if (s == s1->uw_pdata) + *(void**)mem = win64_add_function_table(s1); +#endif + if (s->data) { + tcc_free(s->data); + s->data = NULL; + s->data_allocated = 0; + } + s->data_offset = 0; continue; + } align = s->sh_addralign - 1; - if (++f == 1 && align < RUN_SECTION_ALIGNMENT) - align = RUN_SECTION_ALIGNMENT; + if (++n == 1 && align < (PAGE_ALIGN - 1)) + align = (PAGE_ALIGN - 1); if (max_align < align) max_align = align; + addr = k ? mem : mem + ptr_diff; offset += -(addr + offset) & align; s->sh_addr = mem ? addr + offset : 0; - offset += s->data_offset; -#if 0 + offset += length; +#if DEBUG_RUNMEN if (mem) - printf("%-16s %p len %04x align %2d\n", - s->name, (void*)s->sh_addr, (unsigned)s->data_offset, align + 1); + printf("%d: %-16s %p len %04x align %04x\n", + k, s->name, (void*)s->sh_addr, length, align + 1); #endif } + if (copy) { /* set permissions */ + if (k == 0 && ptr_diff) + continue; /* not with HAVE_SELINUX */ + f = k; +#if !CONFIG_RUNMEM_RO + if (f != 0) + continue; + f = 3; /* change only SHF_EXECINSTR to rwx */ +#endif +#if DEBUG_RUNMEN + printf("protect %d %p %04x\n", f, (void*)addr, n); +#endif + if (n) + set_pages_executable(s1, f, (void*)addr, n); + } } + if (copy) + return 0; + /* relocate symbols */ relocate_syms(s1, s1->symtab, !(s1->nostdlib)); if (s1->nb_errors) return -1; - if (0 == mem) return offset + max_align; @@ -282,55 +339,46 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) relocate_plt(s1); #endif relocate_sections(s1); - - for(i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - if (0 == (s->sh_flags & SHF_ALLOC)) - continue; - length = s->data_offset; - ptr = (void*)s->sh_addr; - if (s->sh_flags & SHF_EXECINSTR) - ptr = (char*)((addr_t)ptr - ptr_diff); - if (NULL == s->data || s->sh_type == SHT_NOBITS) - memset(ptr, 0, length); - else - memcpy(ptr, s->data, length); - /* mark executable sections as executable in memory */ - if (s->sh_flags & SHF_EXECINSTR) - set_pages_executable(s1, (char*)((addr_t)ptr + ptr_diff), length); - } - -#ifdef _WIN64 - *(void**)mem = win64_add_function_table(s1); -#endif - - return 0; + copy = 1; + goto redo; } /* ------------------------------------------------------------- */ /* allow to run code in memory */ -static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length) +static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length) { #ifdef _WIN32 - unsigned long old_protect; - VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect); + static const unsigned char protect[] = { + PAGE_EXECUTE_READ, + PAGE_READONLY, + PAGE_READWRITE, + PAGE_EXECUTE_READWRITE + }; + DWORD old; + VirtualProtect(ptr, length, protect[mode], &old); #else - void __clear_cache(void *beginning, void *end); -# ifndef HAVE_SELINUX + static const unsigned char protect[] = { + PROT_READ | PROT_EXEC, + PROT_READ, + 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, PROT_READ | PROT_WRITE | PROT_EXEC)) + if (mprotect((void *)start, end - start, protect[mode])) tcc_error("mprotect failed: did you mean to configure --with-selinux?"); -# endif + /* XXX: BSD sometimes dump core with bad system call */ -# if (defined(TCC_TARGET_ARM) && \ - !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)) || \ - defined(TCC_TARGET_ARM64) - __clear_cache(ptr, (char *)ptr + length); +# if (TCC_TARGET_ARM && !TARGETOS_BSD) || TCC_TARGET_ARM64 + if (mode == 0 || mode == 3) { + void __clear_cache(void *beginning, void *end); + __clear_cache(ptr, (char *)ptr + length); + } # endif + #endif } diff --git a/tcctools.c b/tcctools.c index 96e5e12e..2df57358 100644 --- a/tcctools.c +++ b/tcctools.c @@ -68,7 +68,7 @@ static int ar_usage(int ret) { ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) { - static ArHdr arhdr = { + static const ArHdr arhdr_init = { "/ ", " ", "0 ", @@ -78,15 +78,8 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) ARFMAG }; - static ArHdr arhdro = { - " ", - " ", - "0 ", - "0 ", - "0 ", - " ", - ARFMAG - }; + ArHdr arhdr = arhdr_init; + ArHdr arhdro = arhdr_init; FILE *fi, *fh = NULL, *fo = NULL; ElfW(Ehdr) *ehdr; @@ -506,9 +499,9 @@ ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int target) /* enable commandline wildcard expansion (tcc -o x.exe *.c) */ #ifdef _WIN32 -int _CRT_glob = 1; +const int _CRT_glob = 1; #ifndef _CRT_glob -int _dowildcard = 1; +const int _dowildcard = 1; #endif #endif diff --git a/tests/tests2/96_nodata_wanted.c b/tests/tests2/96_nodata_wanted.c index 1a4cd334..95938b54 100644 --- a/tests/tests2/96_nodata_wanted.c +++ b/tests/tests2/96_nodata_wanted.c @@ -42,8 +42,8 @@ int main() __label__ ts0, te0, ts1, te1; int tl, dl; - static char ds0 = 0; - static char de0 = 0; + static const char ds0 = 0; + static const char de0 = 0; /* get reference size of empty jmp */ ts0:; if (!SKIP) {} @@ -52,7 +52,7 @@ te0:; tl = -(&&te0 - &&ts0); /* test data and code suppression */ - static char ds1 = 0; + static const char ds1 = 0; ts1:; if (!SKIP) { void *p = (void*)&main; @@ -75,7 +75,7 @@ ts1:; s.x, s.y, s.z, s.a, s.b); } te1:; - static char de1 = 0; + static const char de1 = 0; dl += &de1 - &ds1; tl += &&te1 - &&ts1; diff --git a/x86_64-gen.c b/x86_64-gen.c index f8c56348..95eda80f 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -112,7 +112,7 @@ enum { #include "tcc.h" #include -ST_DATA const char *target_machine_defs = +ST_DATA const char * const target_machine_defs = "__x86_64__\0" "__amd64__\0" ; @@ -575,7 +575,9 @@ void store(int r, SValue *v) #ifndef TCC_TARGET_PE /* we need to access the variable via got */ - if (fr == VT_CONST && (v->r & VT_SYM)) { + if (fr == VT_CONST + && (v->r & VT_SYM) + && !(v->sym->type.t & VT_STATIC)) { /* mov xx(%rip), %r11 */ o(0x1d8b4c); gen_gotpcrel(TREG_R11, v->sym, v->c.i);