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