libtcc.c: add -Wwrite-strings to -Wall tccgen.c: ro float-consts, string-consts, ro arrays if base type is tccpe.c: merge IAT with rodata tccrun.c: mprotect rodata accordingly. free section data after copy x86_64.c: do not use got for static data. tcc -bench: show data.rw/ro Probably STB_LOCAL should never get to put_got_entry(), and currently it doesn't seem to happen (See "Hack Alarm" there) Other files: use more ro-data in tinycc
Unified · Split
| @@ -2826,7 +2826,7 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, · 2825 unmodified lines | |||
| 2826 | 2826 | ||
| 2827 | // TODO: Check non-E ABI. | 2827 | // TODO: Check non-E ABI. |
| 2828 | // Note: Technically, r13 (sp) is also callee-saved--but that does not matter yet | 2828 | // Note: Technically, r13 (sp) is also callee-saved--but that does not matter yet |
| 2829 | static uint8_t reg_saved[] = { 4, 5, 6, 7, 8, 9 /* Note: sometimes special reg "sb" */ , 10, 11 }; | 2829 | static const uint8_t reg_saved[] = { 4, 5, 6, 7, 8, 9 /* Note: sometimes special reg "sb" */ , 10, 11 }; |
| 2830 | 2830 | ||
| 2831 | /* mark all used registers */ | 2831 | /* mark all used registers */ |
| 2832 | memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated)); | 2832 | memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated)); |
| @@ -141,7 +141,7 @@ enum { · 140 unmodified lines | |||
| 141 | #define USING_GLOBALS | 141 | #define USING_GLOBALS |
| 142 | #include "tcc.h" | 142 | #include "tcc.h" |
| 143 | 143 | ||
| 144 | ST_DATA const char *target_machine_defs = | 144 | ST_DATA const char * const target_machine_defs = |
| 145 | "__arm__\0" | 145 | "__arm__\0" |
| 146 | "__arm\0" | 146 | "__arm\0" |
| 147 | "arm\0" | 147 | "arm\0" |
| @@ -50,7 +50,7 @@ · 49 unmodified lines | |||
| 50 | #include "tcc.h" | 50 | #include "tcc.h" |
| 51 | #include <assert.h> | 51 | #include <assert.h> |
| 52 | 52 | ||
| 53 | ST_DATA const char *target_machine_defs = | 53 | ST_DATA const char * const target_machine_defs = |
| 54 | "__aarch64__\0" | 54 | "__aarch64__\0" |
| 55 | ; | 55 | ; |
| 56 | 56 | ||
| @@ -116,7 +116,7 @@ enum { · 115 unmodified lines | |||
| 116 | #define USING_GLOBALS | 116 | #define USING_GLOBALS |
| 117 | #include "tcc.h" | 117 | #include "tcc.h" |
| 118 | 118 | ||
| 119 | ST_DATA const char *target_machine_defs = | 119 | ST_DATA const char * const target_machine_defs = |
| 120 | "__C67__\0" | 120 | "__C67__\0" |
| 121 | ; | 121 | ; |
| 122 | 122 | ||
| @@ -371,7 +371,7 @@ int C67_map_D12(char *s) · 248 unmodified lines | |||
| 371 | 371 | ||
| 372 | 372 | ||
| 373 | 373 | ||
| 374 | void C67_asm(char *s, int a, int b, int c) | 374 | void C67_asm(const char *s, int a, int b, int c) |
| 375 | { | 375 | { |
| 376 | BOOL xpath; | 376 | BOOL xpath; |
| 377 | 377 | ||
| @@ -638,10 +638,12 @@ static void asm_rex(int width64, Operand *ops, int nb_ops, int *op_type, · 637 unmodified lines | |||
| 638 | } | 638 | } |
| 639 | #endif | 639 | #endif |
| 640 | 640 | ||
| 641 | |||
| 641 | static void maybe_print_stats (void) | 642 | static void maybe_print_stats (void) |
| 642 | { | 643 | { |
| 643 | static int already = 1; | 644 | static int already; |
| 644 | if (!already) | 645 | |
| 646 | if (0 && !already) | ||
| 645 | /* print stats about opcodes */ | 647 | /* print stats about opcodes */ |
| 646 | { | 648 | { |
| 647 | const struct ASMInstr *pa; | 649 | const struct ASMInstr *pa; |
| @@ -1604,12 +1606,12 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, · 956 unmodified lines | |||
| 1604 | call-preserved registers, but currently it doesn't matter. */ | 1606 | call-preserved registers, but currently it doesn't matter. */ |
| 1605 | #ifdef TCC_TARGET_X86_64 | 1607 | #ifdef TCC_TARGET_X86_64 |
| 1606 | #ifdef TCC_TARGET_PE | 1608 | #ifdef TCC_TARGET_PE |
| 1607 | static uint8_t reg_saved[] = { 3, 6, 7, 12, 13, 14, 15 }; | 1609 | static const uint8_t reg_saved[] = { 3, 6, 7, 12, 13, 14, 15 }; |
| 1608 | #else | 1610 | #else |
| 1609 | static uint8_t reg_saved[] = { 3, 12, 13, 14, 15 }; | 1611 | static const uint8_t reg_saved[] = { 3, 12, 13, 14, 15 }; |
| 1610 | #endif | 1612 | #endif |
| 1611 | #else | 1613 | #else |
| 1612 | static uint8_t reg_saved[] = { 3, 6, 7 }; | 1614 | static const uint8_t reg_saved[] = { 3, 6, 7 }; |
| 1613 | #endif | 1615 | #endif |
| 1614 | 1616 | ||
| 1615 | /* mark all used registers */ | 1617 | /* mark all used registers */ |
| @@ -81,7 +81,7 @@ enum { · 80 unmodified lines | |||
| 81 | #define USING_GLOBALS | 81 | #define USING_GLOBALS |
| 82 | #include "tcc.h" | 82 | #include "tcc.h" |
| 83 | 83 | ||
| 84 | ST_DATA const char *target_machine_defs = | 84 | ST_DATA const char * const target_machine_defs = |
| 85 | "__i386__\0" | 85 | "__i386__\0" |
| 86 | "__i386\0" | 86 | "__i386\0" |
| 87 | ; | 87 | ; |
| @@ -372,8 +372,8 @@ static void gcall_or_jmp(int is_jmp) · 284 unmodified lines | |||
| 372 | } | 372 | } |
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX }; | 375 | static const uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX }; |
| 376 | static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; | 376 | static const uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; |
| 377 | 377 | ||
| 378 | /* Return the number of registers needed to return the struct, or 0 if | 378 | /* Return the number of registers needed to return the struct, or 0 if |
| 379 | returning via struct pointer. */ | 379 | returning via struct pointer. */ |
| @@ -479,7 +479,7 @@ ST_FUNC void gfunc_call(int nb_args) · 99 unmodified lines | |||
| 479 | if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || | 479 | if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || |
| 480 | func_call == FUNC_FASTCALLW) { | 480 | func_call == FUNC_FASTCALLW) { |
| 481 | int fastcall_nb_regs; | 481 | int fastcall_nb_regs; |
| 482 | uint8_t *fastcall_regs_ptr; | 482 | const uint8_t *fastcall_regs_ptr; |
| 483 | if (func_call == FUNC_FASTCALLW) { | 483 | if (func_call == FUNC_FASTCALLW) { |
| 484 | fastcall_regs_ptr = fastcallw_regs; | 484 | fastcall_regs_ptr = fastcallw_regs; |
| 485 | fastcall_nb_regs = 2; | 485 | fastcall_nb_regs = 2; |
| @@ -519,7 +519,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 33 unmodified lines | |||
| 519 | CType *func_type = &func_sym->type; | 519 | CType *func_type = &func_sym->type; |
| 520 | int addr, align, size, func_call, fastcall_nb_regs; | 520 | int addr, align, size, func_call, fastcall_nb_regs; |
| 521 | int param_index, param_addr; | 521 | int param_index, param_addr; |
| 522 | uint8_t *fastcall_regs_ptr; | 522 | const uint8_t *fastcall_regs_ptr; |
| 523 | Sym *sym; | 523 | Sym *sym; |
| 524 | CType *type; | 524 | CType *type; |
| 525 | 525 | ||
| @@ -1580,7 +1580,7 @@ static const TCCOption tcc_options[] = { · 1579 unmodified lines | |||
| 1580 | static const FlagDef options_W[] = { | 1580 | static const FlagDef options_W[] = { |
| 1581 | { 0, 0, "all" }, | 1581 | { 0, 0, "all" }, |
| 1582 | { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, | 1582 | { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, |
| 1583 | { offsetof(TCCState, warn_write_strings), 0, "write-strings" }, | 1583 | { offsetof(TCCState, warn_write_strings), WD_ALL, "write-strings" }, |
| 1584 | { offsetof(TCCState, warn_error), 0, "error" }, | 1584 | { offsetof(TCCState, warn_error), 0, "error" }, |
| 1585 | { offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" }, | 1585 | { offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" }, |
| 1586 | { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, | 1586 | { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, |
| @@ -1997,8 +1997,12 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time) · 410 unmodified lines | |||
| 1997 | (double)total_time/1000, | 1997 | (double)total_time/1000, |
| 1998 | (unsigned)total_lines*1000/total_time, | 1998 | (unsigned)total_lines*1000/total_time, |
| 1999 | (double)total_bytes/1000/total_time); | 1999 | (double)total_bytes/1000/total_time); |
| 2000 | fprintf(stderr, "* text %d, data %d, bss %d bytes\n", | 2000 | fprintf(stderr, "* text %d, data.rw %d, data.ro %d, bss %d bytes\n", |
| 2001 | s1->total_output[0], s1->total_output[1], s1->total_output[2]); | 2001 | s1->total_output[0], |
| 2002 | s1->total_output[1], | ||
| 2003 | s1->total_output[2], | ||
| 2004 | s1->total_output[3] | ||
| 2005 | ); | ||
| 2002 | #ifdef MEM_DEBUG | 2006 | #ifdef MEM_DEBUG |
| 2003 | fprintf(stderr, "* %d bytes memory used\n", mem_max_size); | 2007 | fprintf(stderr, "* %d bytes memory used\n", mem_max_size); |
| 2004 | #endif | 2008 | #endif |
| @@ -36,7 +36,7 @@ · 35 unmodified lines | |||
| 36 | #include "tcc.h" | 36 | #include "tcc.h" |
| 37 | #include <assert.h> | 37 | #include <assert.h> |
| 38 | 38 | ||
| 39 | ST_DATA const char *target_machine_defs = | 39 | ST_DATA const char * const target_machine_defs = |
| 40 | "__riscv\0" | 40 | "__riscv\0" |
| 41 | "__riscv_xlen 64\0" | 41 | "__riscv_xlen 64\0" |
| 42 | "__riscv_flen 64\0" | 42 | "__riscv_flen 64\0" |
| @@ -885,7 +885,7 @@ struct TCCState { · 884 unmodified lines | |||
| 885 | Section *plt; | 885 | Section *plt; |
| 886 | 886 | ||
| 887 | /* predefined sections */ | 887 | /* predefined sections */ |
| 888 | Section *text_section, *data_section, *data_ro_section, *bss_section; | 888 | Section *text_section, *data_section, *rodata_section, *bss_section; |
| 889 | Section *common_section; | 889 | Section *common_section; |
| 890 | Section *cur_text_section; /* current section where function code is generated */ | 890 | Section *cur_text_section; /* current section where function code is generated */ |
| 891 | #ifdef CONFIG_TCC_BCHECK | 891 | #ifdef CONFIG_TCC_BCHECK |
| @@ -960,7 +960,7 @@ struct TCCState { · 68 unmodified lines | |||
| 960 | int total_idents; | 960 | int total_idents; |
| 961 | int total_lines; | 961 | int total_lines; |
| 962 | int total_bytes; | 962 | int total_bytes; |
| 963 | int total_output[3]; | 963 | int total_output[4]; |
| 964 | 964 | ||
| 965 | /* option -dnum (for general development purposes) */ | 965 | /* option -dnum (for general development purposes) */ |
| 966 | int g_debug; | 966 | int g_debug; |
| @@ -1639,7 +1639,7 @@ ST_FUNC void relocate_plt(TCCState *s1); · 672 unmodified lines | |||
| 1639 | ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val); | 1639 | ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val); |
| 1640 | 1640 | ||
| 1641 | /* ------------ xxx-gen.c ------------ */ | 1641 | /* ------------ xxx-gen.c ------------ */ |
| 1642 | ST_DATA const char *target_machine_defs; | 1642 | ST_DATA const char * const target_machine_defs; |
| 1643 | ST_DATA const int reg_classes[NB_REGS]; | 1643 | ST_DATA const int reg_classes[NB_REGS]; |
| 1644 | 1644 | ||
| 1645 | ST_FUNC void gsym_addr(int t, int a); | 1645 | 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) · 196 unmodified lines | |||
| 1842 | 1842 | ||
| 1843 | #define text_section TCC_STATE_VAR(text_section) | 1843 | #define text_section TCC_STATE_VAR(text_section) |
| 1844 | #define data_section TCC_STATE_VAR(data_section) | 1844 | #define data_section TCC_STATE_VAR(data_section) |
| 1845 | #define data_ro_section TCC_STATE_VAR(data_ro_section) | 1845 | #define rodata_section TCC_STATE_VAR(rodata_section) |
| 1846 | #define bss_section TCC_STATE_VAR(bss_section) | 1846 | #define bss_section TCC_STATE_VAR(bss_section) |
| 1847 | #define common_section TCC_STATE_VAR(common_section) | 1847 | #define common_section TCC_STATE_VAR(common_section) |
| 1848 | #define cur_text_section TCC_STATE_VAR(cur_text_section) | 1848 | #define cur_text_section TCC_STATE_VAR(cur_text_section) |
| @@ -58,8 +58,12 @@ ST_FUNC void tccelf_new(TCCState *s) · 57 unmodified lines | |||
| 58 | /* create standard sections */ | 58 | /* create standard sections */ |
| 59 | text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); | 59 | text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); |
| 60 | data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); | 60 | data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| 61 | #ifdef TCC_TARGET_PE | ||
| 62 | rodata_section = new_section(s, ".rdata", SHT_PROGBITS, SHF_ALLOC); | ||
| 63 | #else | ||
| 61 | /* create ro data section (make ro after relocation done with GNU_RELRO) */ | 64 | /* create ro data section (make ro after relocation done with GNU_RELRO) */ |
| 62 | data_ro_section = new_section(s, ".data.ro", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); | 65 | rodata_section = new_section(s, ".data.ro", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| 66 | #endif | ||
| 63 | bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); | 67 | bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); |
| 64 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); | 68 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); |
| 65 | common_section->sh_num = SHN_COMMON; | 69 | common_section->sh_num = SHN_COMMON; |
| @@ -206,7 +210,7 @@ ST_FUNC void tccelf_end_file(TCCState *s1) · 140 unmodified lines | |||
| 206 | tcc_free(tr); | 210 | tcc_free(tr); |
| 207 | 211 | ||
| 208 | /* record text/data/bss output for -bench info */ | 212 | /* record text/data/bss output for -bench info */ |
| 209 | for (i = 0; i < 3; ++i) { | 213 | for (i = 0; i < 4; ++i) { |
| 210 | s = s1->sections[i + 1]; | 214 | s = s1->sections[i + 1]; |
| 211 | s1->total_output[i] += s->data_offset - s->sh_offset; | 215 | s1->total_output[i] += s->data_offset - s->sh_offset; |
| 212 | } | 216 | } |
| @@ -1255,11 +1259,16 @@ redo: · 1042 unmodified lines | |||
| 1255 | && ELFW(ST_TYPE)(sym->st_info) == STT_FUNC))) | 1259 | && ELFW(ST_TYPE)(sym->st_info) == STT_FUNC))) |
| 1256 | goto jmp_slot; | 1260 | goto jmp_slot; |
| 1257 | } | 1261 | } |
| 1258 | } else if (!(sym->st_shndx == SHN_ABS | 1262 | } else if (sym->st_shndx == SHN_ABS) { |
| 1263 | if (sym->st_value == 0) /* from tcc_add_btstub() */ | ||
| 1264 | continue; | ||
| 1259 | #ifndef TCC_TARGET_ARM | 1265 | #ifndef TCC_TARGET_ARM |
| 1260 | && PTR_SIZE == 8 | 1266 | if (PTR_SIZE != 8) |
| 1267 | continue; | ||
| 1261 | #endif | 1268 | #endif |
| 1262 | )) | 1269 | /* from tcc_add_symbol(): on 64 bit platforms these |
| 1270 | need to go through .got */ | ||
| 1271 | } else | ||
| 1263 | continue; | 1272 | continue; |
| 1264 | } | 1273 | } |
| 1265 | 1274 | ||
| @@ -1314,7 +1323,7 @@ redo: · 48 unmodified lines | |||
| 1314 | 1323 | ||
| 1315 | ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs) | 1324 | ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs) |
| 1316 | { | 1325 | { |
| 1317 | int shn = sec ? sec->sh_num : offs ? SHN_ABS : SHN_UNDEF; | 1326 | int shn = sec ? sec->sh_num : offs || !name ? SHN_ABS : SHN_UNDEF; |
| 1318 | if (sec && offs == -1) | 1327 | if (sec && offs == -1) |
| 1319 | offs = sec->data_offset; | 1328 | offs = sec->data_offset; |
| 1320 | return set_elf_sym(symtab_section, offs, 0, | 1329 | return set_elf_sym(symtab_section, offs, 0, |
| @@ -1326,7 +1335,7 @@ static void add_init_array_defines(TCCState *s1, const char *section_name) · 5 unmodified lines | |||
| 1326 | Section *s; | 1335 | Section *s; |
| 1327 | addr_t end_offset; | 1336 | addr_t end_offset; |
| 1328 | char buf[1024]; | 1337 | char buf[1024]; |
| 1329 | s = find_section(s1, section_name); | 1338 | s = find_section_create(s1, section_name, 0); |
| 1330 | if (!s) { | 1339 | if (!s) { |
| 1331 | end_offset = 0; | 1340 | end_offset = 0; |
| 1332 | s = data_section; | 1341 | s = data_section; |
| @@ -1407,12 +1416,8 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) · 74 unmodified lines | |||
| 1407 | put_ptr(s1, stab_section, -1); | 1416 | put_ptr(s1, stab_section, -1); |
| 1408 | put_ptr(s1, stab_section->link, 0); | 1417 | put_ptr(s1, stab_section->link, 0); |
| 1409 | section_ptr_add(s, 3 * PTR_SIZE); | 1418 | section_ptr_add(s, 3 * PTR_SIZE); |
| 1410 | /* prog_base */ | 1419 | /* prog_base : local nameless symbol with offset 0 at SHN_ABS */ |
| 1411 | #ifndef TCC_TARGET_MACHO | 1420 | put_ptr(s1, NULL, 0); |
| 1412 | /* XXX this relocation is wrong, it uses sym-index 0 (local,undef) */ | ||
| 1413 | put_elf_reloc(s1->symtab, s, s->data_offset, R_DATA_PTR, 0); | ||
| 1414 | #endif | ||
| 1415 | section_ptr_add(s, PTR_SIZE); | ||
| 1416 | n = 2 * PTR_SIZE; | 1421 | n = 2 * PTR_SIZE; |
| 1417 | #ifdef CONFIG_TCC_BCHECK | 1422 | #ifdef CONFIG_TCC_BCHECK |
| 1418 | if (s1->do_bounds_check) { | 1423 | if (s1->do_bounds_check) { |
| @@ -1421,10 +1426,10 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) · 2 unmodified lines | |||
| 1421 | } | 1426 | } |
| 1422 | #endif | 1427 | #endif |
| 1423 | section_ptr_add(s, n); | 1428 | section_ptr_add(s, n); |
| 1424 | |||
| 1425 | cstr_new(&cstr); | 1429 | cstr_new(&cstr); |
| 1426 | cstr_printf(&cstr, | 1430 | cstr_printf(&cstr, |
| 1427 | " extern void __bt_init(),*__rt_info[],__bt_init_dll();" | 1431 | "extern void __bt_init(),__bt_init_dll();" |
| 1432 | "static void *__rt_info[];" | ||
| 1428 | "__attribute__((constructor)) static void __bt_init_rt(){"); | 1433 | "__attribute__((constructor)) static void __bt_init_rt(){"); |
| 1429 | #ifdef TCC_TARGET_PE | 1434 | #ifdef TCC_TARGET_PE |
| 1430 | if (s1->output_type == TCC_OUTPUT_DLL) | 1435 | if (s1->output_type == TCC_OUTPUT_DLL) |
| @@ -1526,8 +1531,9 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 95 unmodified lines | |||
| 1526 | tcc_add_btstub(s1); | 1531 | tcc_add_btstub(s1); |
| 1527 | } | 1532 | } |
| 1528 | #endif | 1533 | #endif |
| 1529 | if (strlen(TCC_LIBTCC1) > 0) | 1534 | if (TCC_LIBTCC1[0]) |
| 1530 | tcc_add_support(s1, TCC_LIBTCC1); | 1535 | tcc_add_support(s1, TCC_LIBTCC1); |
| 1536 | |||
| 1531 | #if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD | 1537 | #if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD |
| 1532 | /* add crt end if not memory output */ | 1538 | /* add crt end if not memory output */ |
| 1533 | if (s1->output_type != TCC_OUTPUT_MEMORY) { | 1539 | if (s1->output_type != TCC_OUTPUT_MEMORY) { |
| @@ -1568,7 +1574,9 @@ static void tcc_add_linker_symbols(TCCState *s1) · 34 unmodified lines | |||
| 1568 | set_global_sym(s1, "__global_pointer$", data_section, 0x800); | 1574 | set_global_sym(s1, "__global_pointer$", data_section, 0x800); |
| 1569 | #endif | 1575 | #endif |
| 1570 | /* horrible new standard ldscript defines */ | 1576 | /* horrible new standard ldscript defines */ |
| 1577 | #ifndef TCC_TARGET_PE | ||
| 1571 | add_init_array_defines(s1, ".preinit_array"); | 1578 | add_init_array_defines(s1, ".preinit_array"); |
| 1579 | #endif | ||
| 1572 | add_init_array_defines(s1, ".init_array"); | 1580 | add_init_array_defines(s1, ".init_array"); |
| 1573 | add_init_array_defines(s1, ".fini_array"); | 1581 | add_init_array_defines(s1, ".fini_array"); |
| 1574 | /* add start and stop symbols for sections whose name can be | 1582 | /* add start and stop symbols for sections whose name can be |
| @@ -1996,12 +2004,12 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 421 unmodified lines | |||
| 1996 | } else if (s->sh_type == SHT_NOBITS) { | 2004 | } else if (s->sh_type == SHT_NOBITS) { |
| 1997 | if (k != 6) | 2005 | if (k != 6) |
| 1998 | continue; | 2006 | continue; |
| 1999 | } else if (s == data_ro_section || | 2007 | } else if ((s == rodata_section |
| 2000 | #ifdef CONFIG_TCC_BCHECK | 2008 | #ifdef CONFIG_TCC_BCHECK |
| 2001 | s == bounds_section || | 2009 | || s == bounds_section |
| 2002 | s == lbounds_section || | 2010 | || s == lbounds_section |
| 2003 | #endif | 2011 | #endif |
| 2004 | 0) { | 2012 | ) && (s->sh_flags & SHF_WRITE)) { |
| 2005 | if (k != 4) | 2013 | if (k != 4) |
| 2006 | continue; | 2014 | continue; |
| 2007 | /* Align next section on page size. | 2015 | /* Align next section on page size. |
| @@ -2029,18 +2037,15 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 21 unmodified lines | |||
| 2029 | ph->p_vaddr = addr; | 2037 | ph->p_vaddr = addr; |
| 2030 | ph->p_paddr = ph->p_vaddr; | 2038 | ph->p_paddr = ph->p_vaddr; |
| 2031 | } | 2039 | } |
| 2032 | if (s == data_ro_section || | 2040 | |
| 2033 | #ifdef CONFIG_TCC_BCHECK | 2041 | if (k == 4) { |
| 2034 | s == bounds_section || | ||
| 2035 | s == lbounds_section || | ||
| 2036 | #endif | ||
| 2037 | 0) { | ||
| 2038 | if (roinf->sh_size == 0) { | 2042 | if (roinf->sh_size == 0) { |
| 2039 | roinf->sh_offset = s->sh_offset; | 2043 | roinf->sh_offset = s->sh_offset; |
| 2040 | roinf->sh_addr = s->sh_addr; | 2044 | roinf->sh_addr = s->sh_addr; |
| 2041 | } | 2045 | } |
| 2042 | roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size; | 2046 | roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size; |
| 2043 | } | 2047 | } |
| 2048 | |||
| 2044 | addr += s->sh_size; | 2049 | addr += s->sh_size; |
| 2045 | if (s->sh_type != SHT_NOBITS) | 2050 | if (s->sh_type != SHT_NOBITS) |
| 2046 | file_offset += s->sh_size; | 2051 | file_offset += s->sh_size; |
| @@ -2356,7 +2356,7 @@ ST_FUNC int gv(int rc) · 2355 unmodified lines | |||
| 2356 | (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { | 2356 | (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { |
| 2357 | /* CPUs usually cannot use float constants, so we store them | 2357 | /* CPUs usually cannot use float constants, so we store them |
| 2358 | generically in data segment */ | 2358 | generically in data segment */ |
| 2359 | init_params p = { data_section }; | 2359 | init_params p = { rodata_section }; |
| 2360 | unsigned long offset; | 2360 | unsigned long offset; |
| 2361 | size = type_size(&vtop->type, &align); | 2361 | size = type_size(&vtop->type, &align); |
| 2362 | if (NODATA_WANTED) | 2362 | if (NODATA_WANTED) |
| @@ -3095,11 +3095,12 @@ static void type_to_str(char *buf, int buf_size, · 732 unmodified lines | |||
| 3095 | pstrcat(buf, buf_size, "typedef "); | 3095 | pstrcat(buf, buf_size, "typedef "); |
| 3096 | if (t & VT_INLINE) | 3096 | if (t & VT_INLINE) |
| 3097 | pstrcat(buf, buf_size, "inline "); | 3097 | pstrcat(buf, buf_size, "inline "); |
| 3098 | if (t & VT_VOLATILE) | 3098 | if (bt != VT_PTR) { |
| 3099 | pstrcat(buf, buf_size, "volatile "); | 3099 | if (t & VT_VOLATILE) |
| 3100 | if (t & VT_CONSTANT) | 3100 | pstrcat(buf, buf_size, "volatile "); |
| 3101 | pstrcat(buf, buf_size, "const "); | 3101 | if (t & VT_CONSTANT) |
| 3102 | 3102 | pstrcat(buf, buf_size, "const "); | |
| 3103 | } | ||
| 3103 | if (((t & VT_DEFSIGN) && bt == VT_BYTE) | 3104 | if (((t & VT_DEFSIGN) && bt == VT_BYTE) |
| 3104 | || ((t & VT_UNSIGNED) | 3105 | || ((t & VT_UNSIGNED) |
| 3105 | && (bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG) | 3106 | && (bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG) |
| @@ -5932,18 +5933,22 @@ ST_FUNC void unary(void) · 2826 unmodified lines | |||
| 5932 | /* fall thru */ | 5933 | /* fall thru */ |
| 5933 | case TOK___FUNC__: | 5934 | case TOK___FUNC__: |
| 5934 | { | 5935 | { |
| 5936 | Section *sec; | ||
| 5935 | void *ptr; | 5937 | void *ptr; |
| 5936 | int len; | 5938 | int len; |
| 5937 | /* special function name identifier */ | 5939 | /* special function name identifier */ |
| 5938 | len = strlen(funcname) + 1; | 5940 | len = strlen(funcname) + 1; |
| 5939 | /* generate char[len] type */ | 5941 | /* generate char[len] type */ |
| 5940 | type.t = VT_BYTE; | 5942 | type.t = VT_BYTE; |
| 5943 | if (tcc_state->warn_write_strings) | ||
| 5944 | type.t |= VT_CONSTANT; | ||
| 5941 | mk_pointer(&type); | 5945 | mk_pointer(&type); |
| 5942 | type.t |= VT_ARRAY; | 5946 | type.t |= VT_ARRAY; |
| 5943 | type.ref->c = len; | 5947 | type.ref->c = len; |
| 5944 | vpush_ref(&type, data_section, data_section->data_offset, len); | 5948 | sec = rodata_section; |
| 5949 | vpush_ref(&type, sec, sec->data_offset, len); | ||
| 5945 | if (!NODATA_WANTED) { | 5950 | if (!NODATA_WANTED) { |
| 5946 | ptr = section_ptr_add(data_section, len); | 5951 | ptr = section_ptr_add(sec, len); |
| 5947 | memcpy(ptr, funcname, len); | 5952 | memcpy(ptr, funcname, len); |
| 5948 | } | 5953 | } |
| 5949 | next(); | 5954 | next(); |
| @@ -5968,6 +5973,7 @@ ST_FUNC void unary(void) · 18 unmodified lines | |||
| 5968 | mk_pointer(&type); | 5973 | mk_pointer(&type); |
| 5969 | type.t |= VT_ARRAY; | 5974 | type.t |= VT_ARRAY; |
| 5970 | memset(&ad, 0, sizeof(AttributeDef)); | 5975 | memset(&ad, 0, sizeof(AttributeDef)); |
| 5976 | ad.section = rodata_section; | ||
| 5971 | decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0); | 5977 | decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0); |
| 5972 | break; | 5978 | break; |
| 5973 | case '(': | 5979 | case '(': |
| @@ -8526,11 +8532,16 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 2552 unmodified lines | |||
| 8526 | /* allocate symbol in corresponding section */ | 8532 | /* allocate symbol in corresponding section */ |
| 8527 | sec = ad->section; | 8533 | sec = ad->section; |
| 8528 | if (!sec) { | 8534 | if (!sec) { |
| 8529 | if (type->t & VT_CONSTANT) | 8535 | CType *tp = type; |
| 8530 | sec = data_ro_section; | 8536 | while ((tp->t & (VT_BTYPE|VT_ARRAY)) == (VT_PTR|VT_ARRAY)) |
| 8531 | else if (has_init) | 8537 | tp = &tp->ref->type; |
| 8538 | if (tp->t & VT_CONSTANT) { | ||
| 8539 | sec = rodata_section; | ||
| 8540 | } else if (has_init) { | ||
| 8532 | sec = data_section; | 8541 | sec = data_section; |
| 8533 | else if (tcc_state->nocommon) | 8542 | /*if (tcc_state->g_debug & 4) |
| 8543 | tcc_warning("rw data: %s", get_tok_str(v, 0));*/ | ||
| 8544 | } else if (tcc_state->nocommon) | ||
| 8534 | sec = bss_section; | 8545 | sec = bss_section; |
| 8535 | } | 8546 | } |
| 8536 | 8547 | ||
| @@ -259,7 +259,7 @@ static void * add_lc(struct macho *mo, uint32_t cmd, uint32_t cmdsize) · 258 unmodified lines | |||
| 259 | return lc; | 259 | return lc; |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | static struct segment_command_64 * add_segment(struct macho *mo, char *name) | 262 | static struct segment_command_64 * add_segment(struct macho *mo, const char *name) |
| 263 | { | 263 | { |
| 264 | struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc)); | 264 | struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc)); |
| 265 | strncpy(sc->segname, name, 16); | 265 | strncpy(sc->segname, name, 16); |
| @@ -272,7 +272,7 @@ static struct segment_command_64 * get_segment(struct macho *mo, int i) · 6 unmodified lines | |||
| 272 | return (struct segment_command_64 *) (mo->lc[mo->seg2lc[i]]); | 272 | return (struct segment_command_64 *) (mo->lc[mo->seg2lc[i]]); |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | static int add_section(struct macho *mo, struct segment_command_64 **_seg, char *name) | 275 | static int add_section(struct macho *mo, struct segment_command_64 **_seg, const char *name) |
| 276 | { | 276 | { |
| 277 | struct segment_command_64 *seg = *_seg; | 277 | struct segment_command_64 *seg = *_seg; |
| 278 | int ret = seg->nsects; | 278 | int ret = seg->nsects; |
| @@ -525,10 +525,10 @@ static void create_symtab(TCCState *s1, struct macho *mo) · 246 unmodified lines | |||
| 525 | } | 525 | } |
| 526 | } | 526 | } |
| 527 | 527 | ||
| 528 | struct { | 528 | const struct { |
| 529 | int seg; | 529 | int seg; |
| 530 | uint32_t flags; | 530 | uint32_t flags; |
| 531 | char *name; | 531 | const char *name; |
| 532 | } skinfo[sk_last] = { | 532 | } skinfo[sk_last] = { |
| 533 | /*[sk_unknown] =*/ { 0 }, | 533 | /*[sk_unknown] =*/ { 0 }, |
| 534 | /*[sk_discard] =*/ { 0 }, | 534 | /*[sk_discard] =*/ { 0 }, |
| @@ -20,8 +20,8 @@ · 19 unmodified lines | |||
| 20 | 20 | ||
| 21 | #include "tcc.h" | 21 | #include "tcc.h" |
| 22 | 22 | ||
| 23 | #define PE_MERGE_DATA | 23 | #define PE_MERGE_DATA 1 |
| 24 | /* #define PE_PRINT_SECTIONS */ | 24 | #define PE_PRINT_SECTIONS 0 |
| 25 | 25 | ||
| 26 | #ifndef _WIN32 | 26 | #ifndef _WIN32 |
| 27 | #define stricmp strcasecmp | 27 | #define stricmp strcasecmp |
| @@ -294,6 +294,7 @@ struct pe_rsrc_reloc { · 266 unmodified lines | |||
| 294 | 294 | ||
| 295 | enum { | 295 | enum { |
| 296 | sec_text = 0, | 296 | sec_text = 0, |
| 297 | sec_rdata , | ||
| 297 | sec_data , | 298 | sec_data , |
| 298 | sec_bss , | 299 | sec_bss , |
| 299 | sec_idata , | 300 | sec_idata , |
| @@ -725,6 +726,8 @@ static int pe_write(struct pe_info *pe) · 425 unmodified lines | |||
| 725 | for (i = 0; i < pe->sec_count; ++i) { | 726 | for (i = 0; i < pe->sec_count; ++i) { |
| 726 | Section *s; | 727 | Section *s; |
| 727 | si = pe->sec_info[i]; | 728 | si = pe->sec_info[i]; |
| 729 | if (!si->data_size) | ||
| 730 | continue; | ||
| 728 | for (s = si->sec; s; s = s->prev) { | 731 | for (s = si->sec; s; s = s->prev) { |
| 729 | pe_fpad(&pf, file_offset); | 732 | pe_fpad(&pf, file_offset); |
| 730 | pe_fwrite(s->data, s->data_offset, &pf); | 733 | pe_fwrite(s->data, s->data_offset, &pf); |
| @@ -1084,6 +1087,7 @@ static int pe_section_class(Section *s) · 353 unmodified lines | |||
| 1084 | return sec_idata; | 1087 | return sec_idata; |
| 1085 | if (0 == strcmp(name, ".pdata")) | 1088 | if (0 == strcmp(name, ".pdata")) |
| 1086 | return sec_pdata; | 1089 | return sec_pdata; |
| 1090 | return sec_rdata; | ||
| 1087 | } else if (type == SHT_NOBITS) { | 1091 | } else if (type == SHT_NOBITS) { |
| 1088 | if (flags & SHF_WRITE) | 1092 | if (flags & SHF_WRITE) |
| 1089 | return sec_bss; | 1093 | return sec_bss; |
| @@ -1106,6 +1110,7 @@ static int pe_assign_addresses (struct pe_info *pe) · 16 unmodified lines | |||
| 1106 | int *section_order; | 1110 | int *section_order; |
| 1107 | struct section_info *si; | 1111 | struct section_info *si; |
| 1108 | Section *s; | 1112 | Section *s; |
| 1113 | TCCState *s1 = pe->s1; | ||
| 1109 | 1114 | ||
| 1110 | if (PE_DLL == pe->type) | 1115 | if (PE_DLL == pe->type) |
| 1111 | pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0); | 1116 | pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0); |
| @@ -1113,8 +1118,8 @@ static int pe_assign_addresses (struct pe_info *pe) · 1 unmodified line | |||
| 1113 | 1118 | ||
| 1114 | section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int)); | 1119 | section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int)); |
| 1115 | for (o = k = 0 ; k < sec_last; ++k) { | 1120 | for (o = k = 0 ; k < sec_last; ++k) { |
| 1116 | for (i = 1; i < pe->s1->nb_sections; ++i) { | 1121 | for (i = 1; i < s1->nb_sections; ++i) { |
| 1117 | s = pe->s1->sections[i]; | 1122 | s = s1->sections[i]; |
| 1118 | if (k == pe_section_class(s)) | 1123 | if (k == pe_section_class(s)) |
| 1119 | section_order[o++] = i; | 1124 | section_order[o++] = i; |
| 1120 | } | 1125 | } |
| @@ -1125,16 +1130,15 @@ static int pe_assign_addresses (struct pe_info *pe) · 4 unmodified lines | |||
| 1125 | 1130 | ||
| 1126 | for (i = 0; i < o; ++i) { | 1131 | for (i = 0; i < o; ++i) { |
| 1127 | k = section_order[i]; | 1132 | k = section_order[i]; |
| 1128 | s = pe->s1->sections[k]; | 1133 | s = s1->sections[k]; |
| 1129 | c = pe_section_class(s); | 1134 | c = pe_section_class(s); |
| 1130 | 1135 | ||
| 1131 | if ((c == sec_stab || c == sec_stabstr) && 0 == pe->s1->do_debug) | 1136 | if ((c == sec_stab || c == sec_stabstr) && 0 == s1->do_debug) |
| 1132 | continue; | 1137 | continue; |
| 1133 | 1138 | ||
| 1134 | #ifdef PE_MERGE_DATA | 1139 | if (PE_MERGE_DATA && c == sec_bss) |
| 1135 | if (c == sec_bss) | ||
| 1136 | c = sec_data; | 1140 | c = sec_data; |
| 1137 | #endif | 1141 | |
| 1138 | if (si && c == si->cls) { | 1142 | if (si && c == si->cls) { |
| 1139 | /* merge with previous section */ | 1143 | /* merge with previous section */ |
| 1140 | s->sh_addr = addr = ((addr - 1) | (16 - 1)) + 1; | 1144 | s->sh_addr = addr = ((addr - 1) | (16 - 1)) + 1; |
| @@ -1143,7 +1147,8 @@ static int pe_assign_addresses (struct pe_info *pe) · 2 unmodified lines | |||
| 1143 | s->sh_addr = addr = pe_virtual_align(pe, addr); | 1147 | s->sh_addr = addr = pe_virtual_align(pe, addr); |
| 1144 | } | 1148 | } |
| 1145 | 1149 | ||
| 1146 | if (c == sec_data && NULL == pe->thunk) | 1150 | if (NULL == pe->thunk |
| 1151 | && c == (data_section == rodata_section ? sec_data : sec_rdata)) | ||
| 1147 | pe->thunk = s; | 1152 | pe->thunk = s; |
| 1148 | 1153 | ||
| 1149 | if (s == pe->thunk) { | 1154 | if (s == pe->thunk) { |
| @@ -1192,8 +1197,8 @@ add_section: · 42 unmodified lines | |||
| 1192 | } | 1197 | } |
| 1193 | tcc_free(section_order); | 1198 | tcc_free(section_order); |
| 1194 | #if 0 | 1199 | #if 0 |
| 1195 | for (i = 1; i < pe->s1->nb_sections; ++i) { | 1200 | for (i = 1; i < s1->nb_sections; ++i) { |
| 1196 | Section *s = pe->s1->sections[i]; | 1201 | Section *s = s1->sections[i]; |
| 1197 | int type = s->sh_type; | 1202 | int type = s->sh_type; |
| 1198 | int flags = s->sh_flags; | 1203 | int flags = s->sh_flags; |
| 1199 | printf("section %-16s %-10s %08x %04x %s,%s,%s\n", | 1204 | printf("section %-16s %-10s %08x %04x %s,%s,%s\n", |
| @@ -1210,7 +1215,7 @@ add_section: · 10 unmodified lines | |||
| 1210 | flags & SHF_EXECINSTR ? "exec" : "" | 1215 | flags & SHF_EXECINSTR ? "exec" : "" |
| 1211 | ); | 1216 | ); |
| 1212 | } | 1217 | } |
| 1213 | pe->s1->verbose = 2; | 1218 | s1->verbose = 2; |
| 1214 | #endif | 1219 | #endif |
| 1215 | return 0; | 1220 | return 0; |
| 1216 | } | 1221 | } |
| @@ -1345,7 +1350,7 @@ static int pe_check_symbols(struct pe_info *pe) · 128 unmodified lines | |||
| 1345 | } | 1350 | } |
| 1346 | 1351 | ||
| 1347 | /*----------------------------------------------------------------------------*/ | 1352 | /*----------------------------------------------------------------------------*/ |
| 1348 | #ifdef PE_PRINT_SECTIONS | 1353 | #if PE_PRINT_SECTIONS |
| 1349 | static void pe_print_section(FILE * f, Section * s) | 1354 | static void pe_print_section(FILE * f, Section * s) |
| 1350 | { | 1355 | { |
| 1351 | /* just if you're curious */ | 1356 | /* just if you're curious */ |
| @@ -1923,11 +1928,11 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 571 unmodified lines | |||
| 1923 | set_global_sym(s1, start_symbol, NULL, 0); | 1928 | set_global_sym(s1, start_symbol, NULL, 0); |
| 1924 | 1929 | ||
| 1925 | if (0 == s1->nostdlib) { | 1930 | if (0 == s1->nostdlib) { |
| 1926 | static const char *libs[] = { | 1931 | static const char * const libs[] = { |
| 1927 | "msvcrt", "kernel32", "", "user32", "gdi32", NULL | 1932 | "msvcrt", "kernel32", "", "user32", "gdi32", NULL |
| 1928 | }; | 1933 | }; |
| 1929 | const char **pp, *p; | 1934 | const char * const *pp, *p; |
| 1930 | if (strlen(TCC_LIBTCC1) > 0) | 1935 | if (TCC_LIBTCC1[0]) |
| 1931 | tcc_add_support(s1, TCC_LIBTCC1); | 1936 | tcc_add_support(s1, TCC_LIBTCC1); |
| 1932 | for (pp = libs; 0 != (p = *pp); ++pp) { | 1937 | for (pp = libs; 0 != (p = *pp); ++pp) { |
| 1933 | if (*p) | 1938 | if (*p) |
| @@ -2038,8 +2043,9 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) · 104 unmodified lines | |||
| 2038 | 2043 | ||
| 2039 | pe_free_imports(&pe); | 2044 | pe_free_imports(&pe); |
| 2040 | 2045 | ||
| 2041 | #ifdef PE_PRINT_SECTIONS | 2046 | #if PE_PRINT_SECTIONS |
| 2042 | pe_print_sections(s1, "tcc.log"); | 2047 | if (s1->g_debug & 8) |
| 2048 | pe_print_sections(s1, "tcc.log"); | ||
| 2043 | #endif | 2049 | #endif |
| 2044 | return ret; | 2050 | return ret; |
| 2045 | } | 2051 | } |
| @@ -3669,7 +3669,7 @@ ST_INLN void unget_tok(int last_tok) · 3668 unmodified lines | |||
| 3669 | /* ------------------------------------------------------------------------- */ | 3669 | /* ------------------------------------------------------------------------- */ |
| 3670 | /* init preprocessor */ | 3670 | /* init preprocessor */ |
| 3671 | 3671 | ||
| 3672 | static const char *target_os_defs = | 3672 | static const char * const target_os_defs = |
| 3673 | #ifdef TCC_TARGET_PE | 3673 | #ifdef TCC_TARGET_PE |
| 3674 | "_WIN32\0" | 3674 | "_WIN32\0" |
| 3675 | # if PTR_SIZE == 8 | 3675 | # if PTR_SIZE == 8 |
| @@ -55,7 +55,7 @@ static void rt_exit(int code); · 54 unmodified lines | |||
| 55 | # include <sys/mman.h> | 55 | # include <sys/mman.h> |
| 56 | #endif | 56 | #endif |
| 57 | 57 | ||
| 58 | static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length); | 58 | static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length); |
| 59 | static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff); | 59 | static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff); |
| 60 | 60 | ||
| 61 | #ifdef _WIN64 | 61 | #ifdef _WIN64 |
| @@ -94,7 +94,6 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) · 32 unmodified lines | |||
| 94 | prx = mmap((char*)ptr + size, size, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_FIXED, fd, 0); | 94 | prx = mmap((char*)ptr + size, size, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_FIXED, fd, 0); |
| 95 | if (ptr == MAP_FAILED || prx == MAP_FAILED) | 95 | if (ptr == MAP_FAILED || prx == MAP_FAILED) |
| 96 | tcc_error("tccrun: could not map memory"); | 96 | tcc_error("tccrun: could not map memory"); |
| 97 | dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)(size*2)); | ||
| 98 | ptr_diff = (char*)prx - (char*)ptr; | 97 | ptr_diff = (char*)prx - (char*)ptr; |
| 99 | close(fd); | 98 | close(fd); |
| 100 | //printf("map %p %p %p\n", ptr, prx, (void*)ptr_diff); | 99 | //printf("map %p %p %p\n", ptr, prx, (void*)ptr_diff); |
| @@ -103,6 +102,7 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) · 2 unmodified lines | |||
| 103 | ptr = tcc_malloc(size); | 102 | ptr = tcc_malloc(size); |
| 104 | #endif | 103 | #endif |
| 105 | tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */ | 104 | tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */ |
| 105 | dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size); | ||
| 106 | dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr); | 106 | dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr); |
| 107 | return 0; | 107 | return 0; |
| 108 | } | 108 | } |
| @@ -111,15 +111,18 @@ ST_FUNC void tcc_run_free(TCCState *s1) · 2 unmodified lines | |||
| 111 | { | 111 | { |
| 112 | int i; | 112 | int i; |
| 113 | 113 | ||
| 114 | for (i = 0; i < s1->nb_runtime_mem; ++i) { | 114 | for (i = 0; i < s1->nb_runtime_mem; i += 2) { |
| 115 | unsigned size = (unsigned)(addr_t)s1->runtime_mem[i]; | ||
| 116 | void *ptr = s1->runtime_mem[i+1]; | ||
| 115 | #ifdef HAVE_SELINUX | 117 | #ifdef HAVE_SELINUX |
| 116 | unsigned size = (unsigned)(addr_t)s1->runtime_mem[i++]; | 118 | munmap(ptr, size * 2); |
| 117 | munmap(s1->runtime_mem[i], size); | ||
| 118 | #else | 119 | #else |
| 120 | /* unprotect memory to make it usable for malloc again */ | ||
| 121 | set_pages_executable(s1, 2, ptr, size); | ||
| 119 | #ifdef _WIN64 | 122 | #ifdef _WIN64 |
| 120 | win64_del_function_table(*(void**)s1->runtime_mem[i]); | 123 | win64_del_function_table(*(void**)ptr); |
| 121 | #endif | 124 | #endif |
| 122 | tcc_free(s1->runtime_mem[i]); | 125 | tcc_free(ptr); |
| 123 | #endif | 126 | #endif |
| 124 | } | 127 | } |
| 125 | tcc_free(s1->runtime_mem); | 128 | tcc_free(s1->runtime_mem); |
| @@ -182,8 +185,9 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 56 unmodified lines | |||
| 182 | *(void**)p = _rt_error; | 185 | *(void**)p = _rt_error; |
| 183 | #ifdef CONFIG_TCC_BCHECK | 186 | #ifdef CONFIG_TCC_BCHECK |
| 184 | if (s1->do_bounds_check) { | 187 | if (s1->do_bounds_check) { |
| 188 | rc->bounds_start = (void*)bounds_section->sh_addr; | ||
| 185 | if ((p = tcc_get_symbol(s1, "__bound_init"))) | 189 | if ((p = tcc_get_symbol(s1, "__bound_init"))) |
| 186 | ((void(*)(addr_t, int))p)(bounds_section->sh_addr, 1); | 190 | ((void(*)(void*,int))p)(rc->bounds_start, 1); |
| 187 | } | 191 | } |
| 188 | #endif | 192 | #endif |
| 189 | set_exception_handler(); | 193 | set_exception_handler(); |
| @@ -207,13 +211,20 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 17 unmodified lines | |||
| 207 | return ret; | 211 | return ret; |
| 208 | } | 212 | } |
| 209 | 213 | ||
| 210 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | 214 | #define DEBUG_RUNMEN 0 |
| 215 | |||
| 216 | /* enable rx/ro/rw permissions */ | ||
| 217 | #define CONFIG_RUNMEM_RO 1 | ||
| 218 | |||
| 219 | #if CONFIG_RUNMEM_RO | ||
| 220 | # define PAGE_ALIGN PAGESIZE | ||
| 221 | #elif defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | ||
| 211 | /* To avoid that x86 processors would reload cached instructions | 222 | /* To avoid that x86 processors would reload cached instructions |
| 212 | each time when data is written in the near, we need to make | 223 | each time when data is written in the near, we need to make |
| 213 | sure that code and data do not share the same 64 byte unit */ | 224 | sure that code and data do not share the same 64 byte unit */ |
| 214 | #define RUN_SECTION_ALIGNMENT 63 | 225 | # define PAGE_ALIGN 64 |
| 215 | #else | 226 | #else |
| 216 | #define RUN_SECTION_ALIGNMENT 0 | 227 | # define PAGE_ALIGN 1 |
| 217 | #endif | 228 | #endif |
| 218 | 229 | ||
| 219 | /* relocate code. Return -1 on error, required size if ptr is NULL, | 230 | /* 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) · 2 unmodified lines | |||
| 222 | { | 233 | { |
| 223 | Section *s; | 234 | Section *s; |
| 224 | unsigned offset, length, align, max_align, i, k, f; | 235 | unsigned offset, length, align, max_align, i, k, f; |
| 236 | unsigned n, copy; | ||
| 225 | addr_t mem, addr; | 237 | addr_t mem, addr; |
| 226 | 238 | ||
| 227 | if (NULL == ptr) { | 239 | if (NULL == ptr) { |
| @@ -241,35 +253,80 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) · 13 unmodified lines | |||
| 241 | #ifdef _WIN64 | 253 | #ifdef _WIN64 |
| 242 | offset += sizeof (void*); /* space for function_table pointer */ | 254 | offset += sizeof (void*); /* space for function_table pointer */ |
| 243 | #endif | 255 | #endif |
| 244 | for (k = 0; k < 2; ++k) { | 256 | copy = 0; |
| 245 | f = 0, addr = k ? mem : mem + ptr_diff; | 257 | redo: |
| 258 | for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */ | ||
| 259 | n = 0; addr = 0; | ||
| 246 | for(i = 1; i < s1->nb_sections; i++) { | 260 | for(i = 1; i < s1->nb_sections; i++) { |
| 261 | static const char shf[] = { | ||
| 262 | SHF_ALLOC|SHF_EXECINSTR, SHF_ALLOC, SHF_ALLOC|SHF_WRITE | ||
| 263 | }; | ||
| 247 | s = s1->sections[i]; | 264 | s = s1->sections[i]; |
| 248 | if (0 == (s->sh_flags & SHF_ALLOC)) | 265 | if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR))) |
| 249 | continue; | 266 | continue; |
| 250 | if (k != !(s->sh_flags & SHF_EXECINSTR)) | 267 | length = s->data_offset; |
| 268 | if (copy) { | ||
| 269 | if (addr == 0) | ||
| 270 | addr = s->sh_addr; | ||
| 271 | n = (s->sh_addr - addr) + length; | ||
| 272 | ptr = (void*)s->sh_addr; | ||
| 273 | if (k == 0) | ||
| 274 | ptr = (void*)(s->sh_addr - ptr_diff); | ||
| 275 | if (NULL == s->data || s->sh_type == SHT_NOBITS) | ||
| 276 | memset(ptr, 0, length); | ||
| 277 | else | ||
| 278 | memcpy(ptr, s->data, length); | ||
| 279 | #ifdef _WIN64 | ||
| 280 | if (s == s1->uw_pdata) | ||
| 281 | *(void**)mem = win64_add_function_table(s1); | ||
| 282 | #endif | ||
| 283 | if (s->data) { | ||
| 284 | tcc_free(s->data); | ||
| 285 | s->data = NULL; | ||
| 286 | s->data_allocated = 0; | ||
| 287 | } | ||
| 288 | s->data_offset = 0; | ||
| 251 | continue; | 289 | continue; |
| 290 | } | ||
| 252 | align = s->sh_addralign - 1; | 291 | align = s->sh_addralign - 1; |
| 253 | if (++f == 1 && align < RUN_SECTION_ALIGNMENT) | 292 | if (++n == 1 && align < (PAGE_ALIGN - 1)) |
| 254 | align = RUN_SECTION_ALIGNMENT; | 293 | align = (PAGE_ALIGN - 1); |
| 255 | if (max_align < align) | 294 | if (max_align < align) |
| 256 | max_align = align; | 295 | max_align = align; |
| 296 | addr = k ? mem : mem + ptr_diff; | ||
| 257 | offset += -(addr + offset) & align; | 297 | offset += -(addr + offset) & align; |
| 258 | s->sh_addr = mem ? addr + offset : 0; | 298 | s->sh_addr = mem ? addr + offset : 0; |
| 259 | offset += s->data_offset; | 299 | offset += length; |
| 260 | #if 0 | 300 | #if DEBUG_RUNMEN |
| 261 | if (mem) | 301 | if (mem) |
| 262 | printf("%-16s %p len %04x align %2d\n", | 302 | printf("%d: %-16s %p len %04x align %04x\n", |
| 263 | s->name, (void*)s->sh_addr, (unsigned)s->data_offset, align + 1); | 303 | k, s->name, (void*)s->sh_addr, length, align + 1); |
| 304 | #endif | ||
| 305 | } | ||
| 306 | if (copy) { /* set permissions */ | ||
| 307 | if (k == 0 && ptr_diff) | ||
| 308 | continue; /* not with HAVE_SELINUX */ | ||
| 309 | f = k; | ||
| 310 | #if !CONFIG_RUNMEM_RO | ||
| 311 | if (f != 0) | ||
| 312 | continue; | ||
| 313 | f = 3; /* change only SHF_EXECINSTR to rwx */ | ||
| 314 | #endif | ||
| 315 | #if DEBUG_RUNMEN | ||
| 316 | printf("protect %d %p %04x\n", f, (void*)addr, n); | ||
| 264 | #endif | 317 | #endif |
| 318 | if (n) | ||
| 319 | set_pages_executable(s1, f, (void*)addr, n); | ||
| 265 | } | 320 | } |
| 266 | } | 321 | } |
| 267 | 322 | ||
| 323 | if (copy) | ||
| 324 | return 0; | ||
| 325 | |||
| 268 | /* relocate symbols */ | 326 | /* relocate symbols */ |
| 269 | relocate_syms(s1, s1->symtab, !(s1->nostdlib)); | 327 | relocate_syms(s1, s1->symtab, !(s1->nostdlib)); |
| 270 | if (s1->nb_errors) | 328 | if (s1->nb_errors) |
| 271 | return -1; | 329 | return -1; |
| 272 | |||
| 273 | if (0 == mem) | 330 | if (0 == mem) |
| 274 | return offset + max_align; | 331 | return offset + max_align; |
| 275 | 332 | ||
| @@ -282,55 +339,46 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) · 6 unmodified lines | |||
| 282 | relocate_plt(s1); | 339 | relocate_plt(s1); |
| 283 | #endif | 340 | #endif |
| 284 | relocate_sections(s1); | 341 | relocate_sections(s1); |
| 285 | 342 | copy = 1; | |
| 286 | for(i = 1; i < s1->nb_sections; i++) { | 343 | goto redo; |
| 287 | s = s1->sections[i]; | ||
| 288 | if (0 == (s->sh_flags & SHF_ALLOC)) | ||
| 289 | continue; | ||
| 290 | length = s->data_offset; | ||
| 291 | ptr = (void*)s->sh_addr; | ||
| 292 | if (s->sh_flags & SHF_EXECINSTR) | ||
| 293 | ptr = (char*)((addr_t)ptr - ptr_diff); | ||
| 294 | if (NULL == s->data || s->sh_type == SHT_NOBITS) | ||
| 295 | memset(ptr, 0, length); | ||
| 296 | else | ||
| 297 | memcpy(ptr, s->data, length); | ||
| 298 | /* mark executable sections as executable in memory */ | ||
| 299 | if (s->sh_flags & SHF_EXECINSTR) | ||
| 300 | set_pages_executable(s1, (char*)((addr_t)ptr + ptr_diff), length); | ||
| 301 | } | ||
| 302 | |||
| 303 | #ifdef _WIN64 | ||
| 304 | *(void**)mem = win64_add_function_table(s1); | ||
| 305 | #endif | ||
| 306 | |||
| 307 | return 0; | ||
| 308 | } | 344 | } |
| 309 | 345 | ||
| 310 | /* ------------------------------------------------------------- */ | 346 | /* ------------------------------------------------------------- */ |
| 311 | /* allow to run code in memory */ | 347 | /* allow to run code in memory */ |
| 312 | 348 | ||
| 313 | static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length) | 349 | static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length) |
| 314 | { | 350 | { |
| 315 | #ifdef _WIN32 | 351 | #ifdef _WIN32 |
| 316 | unsigned long old_protect; | 352 | static const unsigned char protect[] = { |
| 317 | VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect); | 353 | PAGE_EXECUTE_READ, |
| 354 | PAGE_READONLY, | ||
| 355 | PAGE_READWRITE, | ||
| 356 | PAGE_EXECUTE_READWRITE | ||
| 357 | }; | ||
| 358 | DWORD old; | ||
| 359 | VirtualProtect(ptr, length, protect[mode], &old); | ||
| 318 | #else | 360 | #else |
| 319 | void __clear_cache(void *beginning, void *end); | 361 | static const unsigned char protect[] = { |
| 320 | # ifndef HAVE_SELINUX | 362 | PROT_READ | PROT_EXEC, |
| 363 | PROT_READ, | ||
| 364 | PROT_READ | PROT_WRITE, | ||
| 365 | PROT_READ | PROT_WRITE | PROT_EXEC | ||
| 366 | }; | ||
| 321 | addr_t start, end; | 367 | addr_t start, end; |
| 322 | start = (addr_t)ptr & ~(PAGESIZE - 1); | 368 | start = (addr_t)ptr & ~(PAGESIZE - 1); |
| 323 | end = (addr_t)ptr + length; | 369 | end = (addr_t)ptr + length; |
| 324 | end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); | 370 | end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); |
| 325 | if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC)) | 371 | if (mprotect((void *)start, end - start, protect[mode])) |
| 326 | tcc_error("mprotect failed: did you mean to configure --with-selinux?"); | 372 | tcc_error("mprotect failed: did you mean to configure --with-selinux?"); |
| 327 | # endif | 373 | |
| 328 | /* XXX: BSD sometimes dump core with bad system call */ | 374 | /* XXX: BSD sometimes dump core with bad system call */ |
| 329 | # if (defined(TCC_TARGET_ARM) && \ | 375 | # if (TCC_TARGET_ARM && !TARGETOS_BSD) || TCC_TARGET_ARM64 |
| 330 | !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)) || \ | 376 | if (mode == 0 || mode == 3) { |
| 331 | defined(TCC_TARGET_ARM64) | 377 | void __clear_cache(void *beginning, void *end); |
| 332 | __clear_cache(ptr, (char *)ptr + length); | 378 | __clear_cache(ptr, (char *)ptr + length); |
| 379 | } | ||
| 333 | # endif | 380 | # endif |
| 381 | |||
| 334 | #endif | 382 | #endif |
| 335 | } | 383 | } |
| 336 | 384 | ||
| @@ -68,7 +68,7 @@ static int ar_usage(int ret) { · 67 unmodified lines | |||
| 68 | 68 | ||
| 69 | ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) | 69 | ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) |
| 70 | { | 70 | { |
| 71 | static ArHdr arhdr = { | 71 | static const ArHdr arhdr_init = { |
| 72 | "/ ", | 72 | "/ ", |
| 73 | " ", | 73 | " ", |
| 74 | "0 ", | 74 | "0 ", |
| @@ -78,15 +78,8 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) · 3 unmodified lines | |||
| 78 | ARFMAG | 78 | ARFMAG |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | static ArHdr arhdro = { | 81 | ArHdr arhdr = arhdr_init; |
| 82 | " ", | 82 | ArHdr arhdro = arhdr_init; |
| 83 | " ", | ||
| 84 | "0 ", | ||
| 85 | "0 ", | ||
| 86 | "0 ", | ||
| 87 | " ", | ||
| 88 | ARFMAG | ||
| 89 | }; | ||
| 90 | 83 | ||
| 91 | FILE *fi, *fh = NULL, *fo = NULL; | 84 | FILE *fi, *fh = NULL, *fo = NULL; |
| 92 | ElfW(Ehdr) *ehdr; | 85 | ElfW(Ehdr) *ehdr; |
| @@ -506,9 +499,9 @@ ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int target) · 413 unmodified lines | |||
| 506 | /* enable commandline wildcard expansion (tcc -o x.exe *.c) */ | 499 | /* enable commandline wildcard expansion (tcc -o x.exe *.c) */ |
| 507 | 500 | ||
| 508 | #ifdef _WIN32 | 501 | #ifdef _WIN32 |
| 509 | int _CRT_glob = 1; | 502 | const int _CRT_glob = 1; |
| 510 | #ifndef _CRT_glob | 503 | #ifndef _CRT_glob |
| 511 | int _dowildcard = 1; | 504 | const int _dowildcard = 1; |
| 512 | #endif | 505 | #endif |
| 513 | #endif | 506 | #endif |
| 514 | 507 | ||
| @@ -42,8 +42,8 @@ int main() · 41 unmodified lines | |||
| 42 | __label__ ts0, te0, ts1, te1; | 42 | __label__ ts0, te0, ts1, te1; |
| 43 | int tl, dl; | 43 | int tl, dl; |
| 44 | 44 | ||
| 45 | static char ds0 = 0; | 45 | static const char ds0 = 0; |
| 46 | static char de0 = 0; | 46 | static const char de0 = 0; |
| 47 | /* get reference size of empty jmp */ | 47 | /* get reference size of empty jmp */ |
| 48 | ts0:; | 48 | ts0:; |
| 49 | if (!SKIP) {} | 49 | if (!SKIP) {} |
| @@ -52,7 +52,7 @@ te0:; · 2 unmodified lines | |||
| 52 | tl = -(&&te0 - &&ts0); | 52 | tl = -(&&te0 - &&ts0); |
| 53 | 53 | ||
| 54 | /* test data and code suppression */ | 54 | /* test data and code suppression */ |
| 55 | static char ds1 = 0; | 55 | static const char ds1 = 0; |
| 56 | ts1:; | 56 | ts1:; |
| 57 | if (!SKIP) { | 57 | if (!SKIP) { |
| 58 | void *p = (void*)&main; | 58 | void *p = (void*)&main; |
| @@ -75,7 +75,7 @@ ts1:; · 16 unmodified lines | |||
| 75 | s.x, s.y, s.z, s.a, s.b); | 75 | s.x, s.y, s.z, s.a, s.b); |
| 76 | } | 76 | } |
| 77 | te1:; | 77 | te1:; |
| 78 | static char de1 = 0; | 78 | static const char de1 = 0; |
| 79 | 79 | ||
| 80 | dl += &de1 - &ds1; | 80 | dl += &de1 - &ds1; |
| 81 | tl += &&te1 - &&ts1; | 81 | tl += &&te1 - &&ts1; |
| @@ -112,7 +112,7 @@ enum { · 111 unmodified lines | |||
| 112 | #include "tcc.h" | 112 | #include "tcc.h" |
| 113 | #include <assert.h> | 113 | #include <assert.h> |
| 114 | 114 | ||
| 115 | ST_DATA const char *target_machine_defs = | 115 | ST_DATA const char * const target_machine_defs = |
| 116 | "__x86_64__\0" | 116 | "__x86_64__\0" |
| 117 | "__amd64__\0" | 117 | "__amd64__\0" |
| 118 | ; | 118 | ; |
| @@ -575,7 +575,9 @@ void store(int r, SValue *v) · 456 unmodified lines | |||
| 575 | 575 | ||
| 576 | #ifndef TCC_TARGET_PE | 576 | #ifndef TCC_TARGET_PE |
| 577 | /* we need to access the variable via got */ | 577 | /* we need to access the variable via got */ |
| 578 | if (fr == VT_CONST && (v->r & VT_SYM)) { | 578 | if (fr == VT_CONST |
| 579 | && (v->r & VT_SYM) | ||
| 580 | && !(v->sym->type.t & VT_STATIC)) { | ||
| 579 | /* mov xx(%rip), %r11 */ | 581 | /* mov xx(%rip), %r11 */ |
| 580 | o(0x1d8b4c); | 582 | o(0x1d8b4c); |
| 581 | gen_gotpcrel(TREG_R11, v->sym, v->c.i); | 583 | gen_gotpcrel(TREG_R11, v->sym, v->c.i); |