mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-05 02:48:40 +08:00
tccelf: use rodata_section, use more rodata in tcc itself
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
This commit is contained in:
parent
02795106e1
commit
72f1dea537
@ -2826,7 +2826,7 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
|||||||
|
|
||||||
// TODO: Check non-E ABI.
|
// TODO: Check non-E ABI.
|
||||||
// Note: Technically, r13 (sp) is also callee-saved--but that does not matter yet
|
// 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 */
|
/* mark all used registers */
|
||||||
memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
|
memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
|
||||||
|
|||||||
@ -141,7 +141,7 @@ enum {
|
|||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
ST_DATA const char *target_machine_defs =
|
ST_DATA const char * const target_machine_defs =
|
||||||
"__arm__\0"
|
"__arm__\0"
|
||||||
"__arm\0"
|
"__arm\0"
|
||||||
"arm\0"
|
"arm\0"
|
||||||
|
|||||||
@ -50,7 +50,7 @@
|
|||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
ST_DATA const char *target_machine_defs =
|
ST_DATA const char * const target_machine_defs =
|
||||||
"__aarch64__\0"
|
"__aarch64__\0"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@ -116,7 +116,7 @@ enum {
|
|||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
ST_DATA const char *target_machine_defs =
|
ST_DATA const char * const target_machine_defs =
|
||||||
"__C67__\0"
|
"__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;
|
BOOL xpath;
|
||||||
|
|
||||||
|
|||||||
12
i386-asm.c
12
i386-asm.c
@ -638,10 +638,12 @@ static void asm_rex(int width64, Operand *ops, int nb_ops, int *op_type,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void maybe_print_stats (void)
|
static void maybe_print_stats (void)
|
||||||
{
|
{
|
||||||
static int already = 1;
|
static int already;
|
||||||
if (!already)
|
|
||||||
|
if (0 && !already)
|
||||||
/* print stats about opcodes */
|
/* print stats about opcodes */
|
||||||
{
|
{
|
||||||
const struct ASMInstr *pa;
|
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. */
|
call-preserved registers, but currently it doesn't matter. */
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
#ifdef TCC_TARGET_PE
|
#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
|
#else
|
||||||
static uint8_t reg_saved[] = { 3, 12, 13, 14, 15 };
|
static const uint8_t reg_saved[] = { 3, 12, 13, 14, 15 };
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
static uint8_t reg_saved[] = { 3, 6, 7 };
|
static const uint8_t reg_saved[] = { 3, 6, 7 };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* mark all used registers */
|
/* mark all used registers */
|
||||||
|
|||||||
10
i386-gen.c
10
i386-gen.c
@ -81,7 +81,7 @@ enum {
|
|||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
ST_DATA const char *target_machine_defs =
|
ST_DATA const char * const target_machine_defs =
|
||||||
"__i386__\0"
|
"__i386__\0"
|
||||||
"__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 const 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 fastcallw_regs[2] = { TREG_ECX, TREG_EDX };
|
||||||
|
|
||||||
/* Return the number of registers needed to return the struct, or 0 if
|
/* Return the number of registers needed to return the struct, or 0 if
|
||||||
returning via struct pointer. */
|
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) ||
|
if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
|
||||||
func_call == FUNC_FASTCALLW) {
|
func_call == FUNC_FASTCALLW) {
|
||||||
int fastcall_nb_regs;
|
int fastcall_nb_regs;
|
||||||
uint8_t *fastcall_regs_ptr;
|
const uint8_t *fastcall_regs_ptr;
|
||||||
if (func_call == FUNC_FASTCALLW) {
|
if (func_call == FUNC_FASTCALLW) {
|
||||||
fastcall_regs_ptr = fastcallw_regs;
|
fastcall_regs_ptr = fastcallw_regs;
|
||||||
fastcall_nb_regs = 2;
|
fastcall_nb_regs = 2;
|
||||||
@ -519,7 +519,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
|||||||
CType *func_type = &func_sym->type;
|
CType *func_type = &func_sym->type;
|
||||||
int addr, align, size, func_call, fastcall_nb_regs;
|
int addr, align, size, func_call, fastcall_nb_regs;
|
||||||
int param_index, param_addr;
|
int param_index, param_addr;
|
||||||
uint8_t *fastcall_regs_ptr;
|
const uint8_t *fastcall_regs_ptr;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
CType *type;
|
CType *type;
|
||||||
|
|
||||||
|
|||||||
10
libtcc.c
10
libtcc.c
@ -1580,7 +1580,7 @@ static const TCCOption tcc_options[] = {
|
|||||||
static const FlagDef options_W[] = {
|
static const FlagDef options_W[] = {
|
||||||
{ 0, 0, "all" },
|
{ 0, 0, "all" },
|
||||||
{ offsetof(TCCState, warn_unsupported), 0, "unsupported" },
|
{ 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_error), 0, "error" },
|
||||||
{ offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" },
|
{ offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" },
|
||||||
{ offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
|
{ 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,
|
(double)total_time/1000,
|
||||||
(unsigned)total_lines*1000/total_time,
|
(unsigned)total_lines*1000/total_time,
|
||||||
(double)total_bytes/1000/total_time);
|
(double)total_bytes/1000/total_time);
|
||||||
fprintf(stderr, "* text %d, data %d, bss %d bytes\n",
|
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[0],
|
||||||
|
s1->total_output[1],
|
||||||
|
s1->total_output[2],
|
||||||
|
s1->total_output[3]
|
||||||
|
);
|
||||||
#ifdef MEM_DEBUG
|
#ifdef MEM_DEBUG
|
||||||
fprintf(stderr, "* %d bytes memory used\n", mem_max_size);
|
fprintf(stderr, "* %d bytes memory used\n", mem_max_size);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
ST_DATA const char *target_machine_defs =
|
ST_DATA const char * const target_machine_defs =
|
||||||
"__riscv\0"
|
"__riscv\0"
|
||||||
"__riscv_xlen 64\0"
|
"__riscv_xlen 64\0"
|
||||||
"__riscv_flen 64\0"
|
"__riscv_flen 64\0"
|
||||||
|
|||||||
8
tcc.h
8
tcc.h
@ -885,7 +885,7 @@ struct TCCState {
|
|||||||
Section *plt;
|
Section *plt;
|
||||||
|
|
||||||
/* predefined sections */
|
/* 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 *common_section;
|
||||||
Section *cur_text_section; /* current section where function code is generated */
|
Section *cur_text_section; /* current section where function code is generated */
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
@ -960,7 +960,7 @@ struct TCCState {
|
|||||||
int total_idents;
|
int total_idents;
|
||||||
int total_lines;
|
int total_lines;
|
||||||
int total_bytes;
|
int total_bytes;
|
||||||
int total_output[3];
|
int total_output[4];
|
||||||
|
|
||||||
/* option -dnum (for general development purposes) */
|
/* option -dnum (for general development purposes) */
|
||||||
int g_debug;
|
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);
|
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
|
||||||
|
|
||||||
/* ------------ xxx-gen.c ------------ */
|
/* ------------ 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_DATA const int reg_classes[NB_REGS];
|
||||||
|
|
||||||
ST_FUNC void gsym_addr(int t, int a);
|
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 text_section TCC_STATE_VAR(text_section)
|
||||||
#define data_section TCC_STATE_VAR(data_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 bss_section TCC_STATE_VAR(bss_section)
|
||||||
#define common_section TCC_STATE_VAR(common_section)
|
#define common_section TCC_STATE_VAR(common_section)
|
||||||
#define cur_text_section TCC_STATE_VAR(cur_text_section)
|
#define cur_text_section TCC_STATE_VAR(cur_text_section)
|
||||||
|
|||||||
57
tccelf.c
57
tccelf.c
@ -58,8 +58,12 @@ ST_FUNC void tccelf_new(TCCState *s)
|
|||||||
/* create standard sections */
|
/* create standard sections */
|
||||||
text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
|
text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
|
||||||
data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
|
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) */
|
/* 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);
|
bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
|
||||||
common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
|
common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
|
||||||
common_section->sh_num = SHN_COMMON;
|
common_section->sh_num = SHN_COMMON;
|
||||||
@ -206,7 +210,7 @@ ST_FUNC void tccelf_end_file(TCCState *s1)
|
|||||||
tcc_free(tr);
|
tcc_free(tr);
|
||||||
|
|
||||||
/* record text/data/bss output for -bench info */
|
/* 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];
|
s = s1->sections[i + 1];
|
||||||
s1->total_output[i] += s->data_offset - s->sh_offset;
|
s1->total_output[i] += s->data_offset - s->sh_offset;
|
||||||
}
|
}
|
||||||
@ -1255,11 +1259,16 @@ redo:
|
|||||||
&& ELFW(ST_TYPE)(sym->st_info) == STT_FUNC)))
|
&& ELFW(ST_TYPE)(sym->st_info) == STT_FUNC)))
|
||||||
goto jmp_slot;
|
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
|
#ifndef TCC_TARGET_ARM
|
||||||
&& PTR_SIZE == 8
|
if (PTR_SIZE != 8)
|
||||||
|
continue;
|
||||||
#endif
|
#endif
|
||||||
))
|
/* from tcc_add_symbol(): on 64 bit platforms these
|
||||||
|
need to go through .got */
|
||||||
|
} else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1314,7 +1323,7 @@ redo:
|
|||||||
|
|
||||||
ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs)
|
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)
|
if (sec && offs == -1)
|
||||||
offs = sec->data_offset;
|
offs = sec->data_offset;
|
||||||
return set_elf_sym(symtab_section, offs, 0,
|
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;
|
Section *s;
|
||||||
addr_t end_offset;
|
addr_t end_offset;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
s = find_section(s1, section_name);
|
s = find_section_create(s1, section_name, 0);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
end_offset = 0;
|
end_offset = 0;
|
||||||
s = data_section;
|
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, -1);
|
||||||
put_ptr(s1, stab_section->link, 0);
|
put_ptr(s1, stab_section->link, 0);
|
||||||
section_ptr_add(s, 3 * PTR_SIZE);
|
section_ptr_add(s, 3 * PTR_SIZE);
|
||||||
/* prog_base */
|
/* prog_base : local nameless symbol with offset 0 at SHN_ABS */
|
||||||
#ifndef TCC_TARGET_MACHO
|
put_ptr(s1, NULL, 0);
|
||||||
/* 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);
|
|
||||||
n = 2 * PTR_SIZE;
|
n = 2 * PTR_SIZE;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (s1->do_bounds_check) {
|
if (s1->do_bounds_check) {
|
||||||
@ -1421,10 +1426,10 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
section_ptr_add(s, n);
|
section_ptr_add(s, n);
|
||||||
|
|
||||||
cstr_new(&cstr);
|
cstr_new(&cstr);
|
||||||
cstr_printf(&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(){");
|
"__attribute__((constructor)) static void __bt_init_rt(){");
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||||
@ -1526,8 +1531,9 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
|||||||
tcc_add_btstub(s1);
|
tcc_add_btstub(s1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (strlen(TCC_LIBTCC1) > 0)
|
if (TCC_LIBTCC1[0])
|
||||||
tcc_add_support(s1, TCC_LIBTCC1);
|
tcc_add_support(s1, TCC_LIBTCC1);
|
||||||
|
|
||||||
#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
|
#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
|
||||||
/* add crt end if not memory output */
|
/* add crt end if not memory output */
|
||||||
if (s1->output_type != TCC_OUTPUT_MEMORY) {
|
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);
|
set_global_sym(s1, "__global_pointer$", data_section, 0x800);
|
||||||
#endif
|
#endif
|
||||||
/* horrible new standard ldscript defines */
|
/* horrible new standard ldscript defines */
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
add_init_array_defines(s1, ".preinit_array");
|
add_init_array_defines(s1, ".preinit_array");
|
||||||
|
#endif
|
||||||
add_init_array_defines(s1, ".init_array");
|
add_init_array_defines(s1, ".init_array");
|
||||||
add_init_array_defines(s1, ".fini_array");
|
add_init_array_defines(s1, ".fini_array");
|
||||||
/* add start and stop symbols for sections whose name can be
|
/* 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) {
|
} else if (s->sh_type == SHT_NOBITS) {
|
||||||
if (k != 6)
|
if (k != 6)
|
||||||
continue;
|
continue;
|
||||||
} else if (s == data_ro_section ||
|
} else if ((s == rodata_section
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
s == bounds_section ||
|
|| s == bounds_section
|
||||||
s == lbounds_section ||
|
|| s == lbounds_section
|
||||||
#endif
|
#endif
|
||||||
0) {
|
) && (s->sh_flags & SHF_WRITE)) {
|
||||||
if (k != 4)
|
if (k != 4)
|
||||||
continue;
|
continue;
|
||||||
/* Align next section on page size.
|
/* 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_vaddr = addr;
|
||||||
ph->p_paddr = ph->p_vaddr;
|
ph->p_paddr = ph->p_vaddr;
|
||||||
}
|
}
|
||||||
if (s == data_ro_section ||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
if (k == 4) {
|
||||||
s == bounds_section ||
|
|
||||||
s == lbounds_section ||
|
|
||||||
#endif
|
|
||||||
0) {
|
|
||||||
if (roinf->sh_size == 0) {
|
if (roinf->sh_size == 0) {
|
||||||
roinf->sh_offset = s->sh_offset;
|
roinf->sh_offset = s->sh_offset;
|
||||||
roinf->sh_addr = s->sh_addr;
|
roinf->sh_addr = s->sh_addr;
|
||||||
}
|
}
|
||||||
roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size;
|
roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr += s->sh_size;
|
addr += s->sh_size;
|
||||||
if (s->sh_type != SHT_NOBITS)
|
if (s->sh_type != SHT_NOBITS)
|
||||||
file_offset += s->sh_size;
|
file_offset += s->sh_size;
|
||||||
|
|||||||
35
tccgen.c
35
tccgen.c
@ -2356,7 +2356,7 @@ ST_FUNC int gv(int rc)
|
|||||||
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||||
/* CPUs usually cannot use float constants, so we store them
|
/* CPUs usually cannot use float constants, so we store them
|
||||||
generically in data segment */
|
generically in data segment */
|
||||||
init_params p = { data_section };
|
init_params p = { rodata_section };
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
size = type_size(&vtop->type, &align);
|
size = type_size(&vtop->type, &align);
|
||||||
if (NODATA_WANTED)
|
if (NODATA_WANTED)
|
||||||
@ -3095,11 +3095,12 @@ static void type_to_str(char *buf, int buf_size,
|
|||||||
pstrcat(buf, buf_size, "typedef ");
|
pstrcat(buf, buf_size, "typedef ");
|
||||||
if (t & VT_INLINE)
|
if (t & VT_INLINE)
|
||||||
pstrcat(buf, buf_size, "inline ");
|
pstrcat(buf, buf_size, "inline ");
|
||||||
if (t & VT_VOLATILE)
|
if (bt != VT_PTR) {
|
||||||
pstrcat(buf, buf_size, "volatile ");
|
if (t & VT_VOLATILE)
|
||||||
if (t & VT_CONSTANT)
|
pstrcat(buf, buf_size, "volatile ");
|
||||||
pstrcat(buf, buf_size, "const ");
|
if (t & VT_CONSTANT)
|
||||||
|
pstrcat(buf, buf_size, "const ");
|
||||||
|
}
|
||||||
if (((t & VT_DEFSIGN) && bt == VT_BYTE)
|
if (((t & VT_DEFSIGN) && bt == VT_BYTE)
|
||||||
|| ((t & VT_UNSIGNED)
|
|| ((t & VT_UNSIGNED)
|
||||||
&& (bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG)
|
&& (bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG)
|
||||||
@ -5932,18 +5933,22 @@ ST_FUNC void unary(void)
|
|||||||
/* fall thru */
|
/* fall thru */
|
||||||
case TOK___FUNC__:
|
case TOK___FUNC__:
|
||||||
{
|
{
|
||||||
|
Section *sec;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
int len;
|
int len;
|
||||||
/* special function name identifier */
|
/* special function name identifier */
|
||||||
len = strlen(funcname) + 1;
|
len = strlen(funcname) + 1;
|
||||||
/* generate char[len] type */
|
/* generate char[len] type */
|
||||||
type.t = VT_BYTE;
|
type.t = VT_BYTE;
|
||||||
|
if (tcc_state->warn_write_strings)
|
||||||
|
type.t |= VT_CONSTANT;
|
||||||
mk_pointer(&type);
|
mk_pointer(&type);
|
||||||
type.t |= VT_ARRAY;
|
type.t |= VT_ARRAY;
|
||||||
type.ref->c = len;
|
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) {
|
if (!NODATA_WANTED) {
|
||||||
ptr = section_ptr_add(data_section, len);
|
ptr = section_ptr_add(sec, len);
|
||||||
memcpy(ptr, funcname, len);
|
memcpy(ptr, funcname, len);
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
@ -5968,6 +5973,7 @@ ST_FUNC void unary(void)
|
|||||||
mk_pointer(&type);
|
mk_pointer(&type);
|
||||||
type.t |= VT_ARRAY;
|
type.t |= VT_ARRAY;
|
||||||
memset(&ad, 0, sizeof(AttributeDef));
|
memset(&ad, 0, sizeof(AttributeDef));
|
||||||
|
ad.section = rodata_section;
|
||||||
decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
|
decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
|
||||||
break;
|
break;
|
||||||
case '(':
|
case '(':
|
||||||
@ -8526,11 +8532,16 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||||||
/* allocate symbol in corresponding section */
|
/* allocate symbol in corresponding section */
|
||||||
sec = ad->section;
|
sec = ad->section;
|
||||||
if (!sec) {
|
if (!sec) {
|
||||||
if (type->t & VT_CONSTANT)
|
CType *tp = type;
|
||||||
sec = data_ro_section;
|
while ((tp->t & (VT_BTYPE|VT_ARRAY)) == (VT_PTR|VT_ARRAY))
|
||||||
else if (has_init)
|
tp = &tp->ref->type;
|
||||||
|
if (tp->t & VT_CONSTANT) {
|
||||||
|
sec = rodata_section;
|
||||||
|
} else if (has_init) {
|
||||||
sec = data_section;
|
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;
|
sec = bss_section;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -259,7 +259,7 @@ static void * add_lc(struct macho *mo, uint32_t cmd, uint32_t cmdsize)
|
|||||||
return lc;
|
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));
|
struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc));
|
||||||
strncpy(sc->segname, name, 16);
|
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]]);
|
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;
|
struct segment_command_64 *seg = *_seg;
|
||||||
int ret = seg->nsects;
|
int ret = seg->nsects;
|
||||||
@ -525,10 +525,10 @@ static void create_symtab(TCCState *s1, struct macho *mo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct {
|
const struct {
|
||||||
int seg;
|
int seg;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
char *name;
|
const char *name;
|
||||||
} skinfo[sk_last] = {
|
} skinfo[sk_last] = {
|
||||||
/*[sk_unknown] =*/ { 0 },
|
/*[sk_unknown] =*/ { 0 },
|
||||||
/*[sk_discard] =*/ { 0 },
|
/*[sk_discard] =*/ { 0 },
|
||||||
|
|||||||
44
tccpe.c
44
tccpe.c
@ -20,8 +20,8 @@
|
|||||||
|
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
#define PE_MERGE_DATA
|
#define PE_MERGE_DATA 1
|
||||||
/* #define PE_PRINT_SECTIONS */
|
#define PE_PRINT_SECTIONS 0
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#define stricmp strcasecmp
|
#define stricmp strcasecmp
|
||||||
@ -294,6 +294,7 @@ struct pe_rsrc_reloc {
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
sec_text = 0,
|
sec_text = 0,
|
||||||
|
sec_rdata ,
|
||||||
sec_data ,
|
sec_data ,
|
||||||
sec_bss ,
|
sec_bss ,
|
||||||
sec_idata ,
|
sec_idata ,
|
||||||
@ -725,6 +726,8 @@ static int pe_write(struct pe_info *pe)
|
|||||||
for (i = 0; i < pe->sec_count; ++i) {
|
for (i = 0; i < pe->sec_count; ++i) {
|
||||||
Section *s;
|
Section *s;
|
||||||
si = pe->sec_info[i];
|
si = pe->sec_info[i];
|
||||||
|
if (!si->data_size)
|
||||||
|
continue;
|
||||||
for (s = si->sec; s; s = s->prev) {
|
for (s = si->sec; s; s = s->prev) {
|
||||||
pe_fpad(&pf, file_offset);
|
pe_fpad(&pf, file_offset);
|
||||||
pe_fwrite(s->data, s->data_offset, &pf);
|
pe_fwrite(s->data, s->data_offset, &pf);
|
||||||
@ -1084,6 +1087,7 @@ static int pe_section_class(Section *s)
|
|||||||
return sec_idata;
|
return sec_idata;
|
||||||
if (0 == strcmp(name, ".pdata"))
|
if (0 == strcmp(name, ".pdata"))
|
||||||
return sec_pdata;
|
return sec_pdata;
|
||||||
|
return sec_rdata;
|
||||||
} else if (type == SHT_NOBITS) {
|
} else if (type == SHT_NOBITS) {
|
||||||
if (flags & SHF_WRITE)
|
if (flags & SHF_WRITE)
|
||||||
return sec_bss;
|
return sec_bss;
|
||||||
@ -1106,6 +1110,7 @@ static int pe_assign_addresses (struct pe_info *pe)
|
|||||||
int *section_order;
|
int *section_order;
|
||||||
struct section_info *si;
|
struct section_info *si;
|
||||||
Section *s;
|
Section *s;
|
||||||
|
TCCState *s1 = pe->s1;
|
||||||
|
|
||||||
if (PE_DLL == pe->type)
|
if (PE_DLL == pe->type)
|
||||||
pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);
|
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));
|
section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));
|
||||||
for (o = k = 0 ; k < sec_last; ++k) {
|
for (o = k = 0 ; k < sec_last; ++k) {
|
||||||
for (i = 1; i < pe->s1->nb_sections; ++i) {
|
for (i = 1; i < s1->nb_sections; ++i) {
|
||||||
s = pe->s1->sections[i];
|
s = s1->sections[i];
|
||||||
if (k == pe_section_class(s))
|
if (k == pe_section_class(s))
|
||||||
section_order[o++] = i;
|
section_order[o++] = i;
|
||||||
}
|
}
|
||||||
@ -1125,16 +1130,15 @@ static int pe_assign_addresses (struct pe_info *pe)
|
|||||||
|
|
||||||
for (i = 0; i < o; ++i) {
|
for (i = 0; i < o; ++i) {
|
||||||
k = section_order[i];
|
k = section_order[i];
|
||||||
s = pe->s1->sections[k];
|
s = s1->sections[k];
|
||||||
c = pe_section_class(s);
|
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;
|
continue;
|
||||||
|
|
||||||
#ifdef PE_MERGE_DATA
|
if (PE_MERGE_DATA && c == sec_bss)
|
||||||
if (c == sec_bss)
|
|
||||||
c = sec_data;
|
c = sec_data;
|
||||||
#endif
|
|
||||||
if (si && c == si->cls) {
|
if (si && c == si->cls) {
|
||||||
/* merge with previous section */
|
/* merge with previous section */
|
||||||
s->sh_addr = addr = ((addr - 1) | (16 - 1)) + 1;
|
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);
|
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;
|
pe->thunk = s;
|
||||||
|
|
||||||
if (s == pe->thunk) {
|
if (s == pe->thunk) {
|
||||||
@ -1192,8 +1197,8 @@ add_section:
|
|||||||
}
|
}
|
||||||
tcc_free(section_order);
|
tcc_free(section_order);
|
||||||
#if 0
|
#if 0
|
||||||
for (i = 1; i < pe->s1->nb_sections; ++i) {
|
for (i = 1; i < s1->nb_sections; ++i) {
|
||||||
Section *s = pe->s1->sections[i];
|
Section *s = s1->sections[i];
|
||||||
int type = s->sh_type;
|
int type = s->sh_type;
|
||||||
int flags = s->sh_flags;
|
int flags = s->sh_flags;
|
||||||
printf("section %-16s %-10s %08x %04x %s,%s,%s\n",
|
printf("section %-16s %-10s %08x %04x %s,%s,%s\n",
|
||||||
@ -1210,7 +1215,7 @@ add_section:
|
|||||||
flags & SHF_EXECINSTR ? "exec" : ""
|
flags & SHF_EXECINSTR ? "exec" : ""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
pe->s1->verbose = 2;
|
s1->verbose = 2;
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
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)
|
static void pe_print_section(FILE * f, Section * s)
|
||||||
{
|
{
|
||||||
/* just if you're curious */
|
/* 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);
|
set_global_sym(s1, start_symbol, NULL, 0);
|
||||||
|
|
||||||
if (0 == s1->nostdlib) {
|
if (0 == s1->nostdlib) {
|
||||||
static const char *libs[] = {
|
static const char * const libs[] = {
|
||||||
"msvcrt", "kernel32", "", "user32", "gdi32", NULL
|
"msvcrt", "kernel32", "", "user32", "gdi32", NULL
|
||||||
};
|
};
|
||||||
const char **pp, *p;
|
const char * const *pp, *p;
|
||||||
if (strlen(TCC_LIBTCC1) > 0)
|
if (TCC_LIBTCC1[0])
|
||||||
tcc_add_support(s1, TCC_LIBTCC1);
|
tcc_add_support(s1, TCC_LIBTCC1);
|
||||||
for (pp = libs; 0 != (p = *pp); ++pp) {
|
for (pp = libs; 0 != (p = *pp); ++pp) {
|
||||||
if (*p)
|
if (*p)
|
||||||
@ -2038,8 +2043,9 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
|||||||
|
|
||||||
pe_free_imports(&pe);
|
pe_free_imports(&pe);
|
||||||
|
|
||||||
#ifdef PE_PRINT_SECTIONS
|
#if PE_PRINT_SECTIONS
|
||||||
pe_print_sections(s1, "tcc.log");
|
if (s1->g_debug & 8)
|
||||||
|
pe_print_sections(s1, "tcc.log");
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
2
tccpp.c
2
tccpp.c
@ -3669,7 +3669,7 @@ ST_INLN void unget_tok(int last_tok)
|
|||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/* init preprocessor */
|
/* init preprocessor */
|
||||||
|
|
||||||
static const char *target_os_defs =
|
static const char * const target_os_defs =
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
"_WIN32\0"
|
"_WIN32\0"
|
||||||
# if PTR_SIZE == 8
|
# if PTR_SIZE == 8
|
||||||
|
|||||||
160
tccrun.c
160
tccrun.c
@ -55,7 +55,7 @@ static void rt_exit(int code);
|
|||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
#endif
|
#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);
|
static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff);
|
||||||
|
|
||||||
#ifdef _WIN64
|
#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);
|
prx = mmap((char*)ptr + size, size, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_FIXED, fd, 0);
|
||||||
if (ptr == MAP_FAILED || prx == MAP_FAILED)
|
if (ptr == MAP_FAILED || prx == MAP_FAILED)
|
||||||
tcc_error("tccrun: could not map memory");
|
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;
|
ptr_diff = (char*)prx - (char*)ptr;
|
||||||
close(fd);
|
close(fd);
|
||||||
//printf("map %p %p %p\n", ptr, prx, (void*)ptr_diff);
|
//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);
|
ptr = tcc_malloc(size);
|
||||||
#endif
|
#endif
|
||||||
tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */
|
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);
|
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -111,15 +111,18 @@ ST_FUNC void tcc_run_free(TCCState *s1)
|
|||||||
{
|
{
|
||||||
int i;
|
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
|
#ifdef HAVE_SELINUX
|
||||||
unsigned size = (unsigned)(addr_t)s1->runtime_mem[i++];
|
munmap(ptr, size * 2);
|
||||||
munmap(s1->runtime_mem[i], size);
|
|
||||||
#else
|
#else
|
||||||
|
/* unprotect memory to make it usable for malloc again */
|
||||||
|
set_pages_executable(s1, 2, ptr, size);
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
win64_del_function_table(*(void**)s1->runtime_mem[i]);
|
win64_del_function_table(*(void**)ptr);
|
||||||
#endif
|
#endif
|
||||||
tcc_free(s1->runtime_mem[i]);
|
tcc_free(ptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
tcc_free(s1->runtime_mem);
|
tcc_free(s1->runtime_mem);
|
||||||
@ -182,8 +185,9 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
|||||||
*(void**)p = _rt_error;
|
*(void**)p = _rt_error;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (s1->do_bounds_check) {
|
if (s1->do_bounds_check) {
|
||||||
|
rc->bounds_start = (void*)bounds_section->sh_addr;
|
||||||
if ((p = tcc_get_symbol(s1, "__bound_init")))
|
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
|
#endif
|
||||||
set_exception_handler();
|
set_exception_handler();
|
||||||
@ -207,13 +211,20 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
|||||||
return ret;
|
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
|
/* To avoid that x86 processors would reload cached instructions
|
||||||
each time when data is written in the near, we need to make
|
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 */
|
sure that code and data do not share the same 64 byte unit */
|
||||||
#define RUN_SECTION_ALIGNMENT 63
|
# define PAGE_ALIGN 64
|
||||||
#else
|
#else
|
||||||
#define RUN_SECTION_ALIGNMENT 0
|
# define PAGE_ALIGN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* relocate code. Return -1 on error, required size if ptr is NULL,
|
/* 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;
|
Section *s;
|
||||||
unsigned offset, length, align, max_align, i, k, f;
|
unsigned offset, length, align, max_align, i, k, f;
|
||||||
|
unsigned n, copy;
|
||||||
addr_t mem, addr;
|
addr_t mem, addr;
|
||||||
|
|
||||||
if (NULL == ptr) {
|
if (NULL == ptr) {
|
||||||
@ -241,35 +253,80 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
|
|||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
offset += sizeof (void*); /* space for function_table pointer */
|
offset += sizeof (void*); /* space for function_table pointer */
|
||||||
#endif
|
#endif
|
||||||
for (k = 0; k < 2; ++k) {
|
copy = 0;
|
||||||
f = 0, addr = k ? mem : mem + ptr_diff;
|
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++) {
|
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];
|
s = s1->sections[i];
|
||||||
if (0 == (s->sh_flags & SHF_ALLOC))
|
if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR)))
|
||||||
continue;
|
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;
|
continue;
|
||||||
|
}
|
||||||
align = s->sh_addralign - 1;
|
align = s->sh_addralign - 1;
|
||||||
if (++f == 1 && align < RUN_SECTION_ALIGNMENT)
|
if (++n == 1 && align < (PAGE_ALIGN - 1))
|
||||||
align = RUN_SECTION_ALIGNMENT;
|
align = (PAGE_ALIGN - 1);
|
||||||
if (max_align < align)
|
if (max_align < align)
|
||||||
max_align = align;
|
max_align = align;
|
||||||
|
addr = k ? mem : mem + ptr_diff;
|
||||||
offset += -(addr + offset) & align;
|
offset += -(addr + offset) & align;
|
||||||
s->sh_addr = mem ? addr + offset : 0;
|
s->sh_addr = mem ? addr + offset : 0;
|
||||||
offset += s->data_offset;
|
offset += length;
|
||||||
#if 0
|
#if DEBUG_RUNMEN
|
||||||
if (mem)
|
if (mem)
|
||||||
printf("%-16s %p len %04x align %2d\n",
|
printf("%d: %-16s %p len %04x align %04x\n",
|
||||||
s->name, (void*)s->sh_addr, (unsigned)s->data_offset, align + 1);
|
k, s->name, (void*)s->sh_addr, length, align + 1);
|
||||||
#endif
|
#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 symbols */
|
||||||
relocate_syms(s1, s1->symtab, !(s1->nostdlib));
|
relocate_syms(s1, s1->symtab, !(s1->nostdlib));
|
||||||
if (s1->nb_errors)
|
if (s1->nb_errors)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (0 == mem)
|
if (0 == mem)
|
||||||
return offset + max_align;
|
return offset + max_align;
|
||||||
|
|
||||||
@ -282,55 +339,46 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
|
|||||||
relocate_plt(s1);
|
relocate_plt(s1);
|
||||||
#endif
|
#endif
|
||||||
relocate_sections(s1);
|
relocate_sections(s1);
|
||||||
|
copy = 1;
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
goto redo;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
/* allow to run code in memory */
|
/* 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
|
#ifdef _WIN32
|
||||||
unsigned long old_protect;
|
static const unsigned char protect[] = {
|
||||||
VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
|
PAGE_EXECUTE_READ,
|
||||||
|
PAGE_READONLY,
|
||||||
|
PAGE_READWRITE,
|
||||||
|
PAGE_EXECUTE_READWRITE
|
||||||
|
};
|
||||||
|
DWORD old;
|
||||||
|
VirtualProtect(ptr, length, protect[mode], &old);
|
||||||
#else
|
#else
|
||||||
void __clear_cache(void *beginning, void *end);
|
static const unsigned char protect[] = {
|
||||||
# ifndef HAVE_SELINUX
|
PROT_READ | PROT_EXEC,
|
||||||
|
PROT_READ,
|
||||||
|
PROT_READ | PROT_WRITE,
|
||||||
|
PROT_READ | PROT_WRITE | PROT_EXEC
|
||||||
|
};
|
||||||
addr_t start, end;
|
addr_t start, end;
|
||||||
start = (addr_t)ptr & ~(PAGESIZE - 1);
|
start = (addr_t)ptr & ~(PAGESIZE - 1);
|
||||||
end = (addr_t)ptr + length;
|
end = (addr_t)ptr + length;
|
||||||
end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
|
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?");
|
tcc_error("mprotect failed: did you mean to configure --with-selinux?");
|
||||||
# endif
|
|
||||||
/* XXX: BSD sometimes dump core with bad system call */
|
/* XXX: BSD sometimes dump core with bad system call */
|
||||||
# if (defined(TCC_TARGET_ARM) && \
|
# if (TCC_TARGET_ARM && !TARGETOS_BSD) || TCC_TARGET_ARM64
|
||||||
!defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)) || \
|
if (mode == 0 || mode == 3) {
|
||||||
defined(TCC_TARGET_ARM64)
|
void __clear_cache(void *beginning, void *end);
|
||||||
__clear_cache(ptr, (char *)ptr + length);
|
__clear_cache(ptr, (char *)ptr + length);
|
||||||
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
17
tcctools.c
17
tcctools.c
@ -68,7 +68,7 @@ static int ar_usage(int ret) {
|
|||||||
|
|
||||||
ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
||||||
{
|
{
|
||||||
static ArHdr arhdr = {
|
static const ArHdr arhdr_init = {
|
||||||
"/ ",
|
"/ ",
|
||||||
" ",
|
" ",
|
||||||
"0 ",
|
"0 ",
|
||||||
@ -78,15 +78,8 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
ARFMAG
|
ARFMAG
|
||||||
};
|
};
|
||||||
|
|
||||||
static ArHdr arhdro = {
|
ArHdr arhdr = arhdr_init;
|
||||||
" ",
|
ArHdr arhdro = arhdr_init;
|
||||||
" ",
|
|
||||||
"0 ",
|
|
||||||
"0 ",
|
|
||||||
"0 ",
|
|
||||||
" ",
|
|
||||||
ARFMAG
|
|
||||||
};
|
|
||||||
|
|
||||||
FILE *fi, *fh = NULL, *fo = NULL;
|
FILE *fi, *fh = NULL, *fo = NULL;
|
||||||
ElfW(Ehdr) *ehdr;
|
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) */
|
/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
int _CRT_glob = 1;
|
const int _CRT_glob = 1;
|
||||||
#ifndef _CRT_glob
|
#ifndef _CRT_glob
|
||||||
int _dowildcard = 1;
|
const int _dowildcard = 1;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -42,8 +42,8 @@ int main()
|
|||||||
__label__ ts0, te0, ts1, te1;
|
__label__ ts0, te0, ts1, te1;
|
||||||
int tl, dl;
|
int tl, dl;
|
||||||
|
|
||||||
static char ds0 = 0;
|
static const char ds0 = 0;
|
||||||
static char de0 = 0;
|
static const char de0 = 0;
|
||||||
/* get reference size of empty jmp */
|
/* get reference size of empty jmp */
|
||||||
ts0:;
|
ts0:;
|
||||||
if (!SKIP) {}
|
if (!SKIP) {}
|
||||||
@ -52,7 +52,7 @@ te0:;
|
|||||||
tl = -(&&te0 - &&ts0);
|
tl = -(&&te0 - &&ts0);
|
||||||
|
|
||||||
/* test data and code suppression */
|
/* test data and code suppression */
|
||||||
static char ds1 = 0;
|
static const char ds1 = 0;
|
||||||
ts1:;
|
ts1:;
|
||||||
if (!SKIP) {
|
if (!SKIP) {
|
||||||
void *p = (void*)&main;
|
void *p = (void*)&main;
|
||||||
@ -75,7 +75,7 @@ ts1:;
|
|||||||
s.x, s.y, s.z, s.a, s.b);
|
s.x, s.y, s.z, s.a, s.b);
|
||||||
}
|
}
|
||||||
te1:;
|
te1:;
|
||||||
static char de1 = 0;
|
static const char de1 = 0;
|
||||||
|
|
||||||
dl += &de1 - &ds1;
|
dl += &de1 - &ds1;
|
||||||
tl += &&te1 - &&ts1;
|
tl += &&te1 - &&ts1;
|
||||||
|
|||||||
@ -112,7 +112,7 @@ enum {
|
|||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
ST_DATA const char *target_machine_defs =
|
ST_DATA const char * const target_machine_defs =
|
||||||
"__x86_64__\0"
|
"__x86_64__\0"
|
||||||
"__amd64__\0"
|
"__amd64__\0"
|
||||||
;
|
;
|
||||||
@ -575,7 +575,9 @@ void store(int r, SValue *v)
|
|||||||
|
|
||||||
#ifndef TCC_TARGET_PE
|
#ifndef TCC_TARGET_PE
|
||||||
/* we need to access the variable via got */
|
/* 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 */
|
/* mov xx(%rip), %r11 */
|
||||||
o(0x1d8b4c);
|
o(0x1d8b4c);
|
||||||
gen_gotpcrel(TREG_R11, v->sym, v->c.i);
|
gen_gotpcrel(TREG_R11, v->sym, v->c.i);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user