mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-06 03:18:41 +08:00
Add pic/pie support to i386
Some checks failed
build and test / test-x86_64-linux (push) Has been cancelled
build and test / test-x86_64-osx (push) Has been cancelled
build and test / test-aarch64-osx (push) Has been cancelled
build and test / test-x86_64-win32 (push) Has been cancelled
build and test / test-i386-win32 (push) Has been cancelled
build and test / test-armv7-linux (push) Has been cancelled
build and test / test-aarch64-linux (push) Has been cancelled
build and test / test-riscv64-linux (push) Has been cancelled
Some checks failed
build and test / test-x86_64-linux (push) Has been cancelled
build and test / test-x86_64-osx (push) Has been cancelled
build and test / test-aarch64-osx (push) Has been cancelled
build and test / test-x86_64-win32 (push) Has been cancelled
build and test / test-i386-win32 (push) Has been cancelled
build and test / test-armv7-linux (push) Has been cancelled
build and test / test-aarch64-linux (push) Has been cancelled
build and test / test-riscv64-linux (push) Has been cancelled
Some targets (netbsd) require that code is compiled with -fPIE. i386-gen.c: Lot of changes to load/store code i386-link.c: Set PCRELATIVE_DLLPLT depending on configuration tccelf.c: Change some relocations and add get_pc_thunk.o Makefile lib/Makefile lib/get_pc_thunk.S: Add new file get_pc_thunk.o
This commit is contained in:
parent
5ce2c4b454
commit
9a7edb20d3
2
Makefile
2
Makefile
@ -372,7 +372,7 @@ IR = $(IM) mkdir -p $2 && cp -r $1/. $2
|
|||||||
IM = @echo "-> $2 : $1" ;
|
IM = @echo "-> $2 : $1" ;
|
||||||
BINCHECK = $(if $(wildcard $(PROGS) *-tcc$(EXESUF)),,@echo "Makefile: nothing found to install" && exit 1)
|
BINCHECK = $(if $(wildcard $(PROGS) *-tcc$(EXESUF)),,@echo "Makefile: nothing found to install" && exit 1)
|
||||||
|
|
||||||
EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o
|
EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o get_pc_thunk.o
|
||||||
|
|
||||||
# install progs & libs
|
# install progs & libs
|
||||||
install-unx:
|
install-unx:
|
||||||
|
|||||||
314
i386-gen.c
314
i386-gen.c
@ -47,9 +47,13 @@ enum {
|
|||||||
TREG_EDX,
|
TREG_EDX,
|
||||||
TREG_EBX,
|
TREG_EBX,
|
||||||
TREG_ST0,
|
TREG_ST0,
|
||||||
TREG_ESP = 4
|
TREG_ESP = 4,
|
||||||
|
|
||||||
|
TREG_MEM = 0x20
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define REG_VALUE(reg) ((reg) & 7)
|
||||||
|
|
||||||
/* return registers for function */
|
/* return registers for function */
|
||||||
#define REG_IRET TREG_EAX /* single word int return register */
|
#define REG_IRET TREG_EAX /* single word int return register */
|
||||||
#define REG_IRE2 TREG_EDX /* second word return register (for long long) */
|
#define REG_IRE2 TREG_EDX /* second word return register (for long long) */
|
||||||
@ -88,6 +92,14 @@ ST_DATA const char * const target_machine_defs =
|
|||||||
|
|
||||||
/* define to 1/0 to [not] have EBX as 4th register */
|
/* define to 1/0 to [not] have EBX as 4th register */
|
||||||
#define USE_EBX 0
|
#define USE_EBX 0
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
#if USE_EBX > 0
|
||||||
|
#error only USE_EBX or GOT_EBX can be set
|
||||||
|
#endif
|
||||||
|
#define GOT_EBX 1
|
||||||
|
#else
|
||||||
|
#define GOT_EBX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
ST_DATA const int reg_classes[NB_REGS] = {
|
ST_DATA const int reg_classes[NB_REGS] = {
|
||||||
/* eax */ RC_INT | RC_EAX,
|
/* eax */ RC_INT | RC_EAX,
|
||||||
@ -171,6 +183,56 @@ ST_FUNC void gen_fill_nops(int bytes)
|
|||||||
g(0x90);
|
g(0x90);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
static void get_pc_thunk(int r, int add)
|
||||||
|
{
|
||||||
|
static const char *pc_thunk_name[] = {
|
||||||
|
"__x86.get_pc_thunk.ax",
|
||||||
|
"__x86.get_pc_thunk.cx",
|
||||||
|
"__x86.get_pc_thunk.dx",
|
||||||
|
"__x86.get_pc_thunk.bx"
|
||||||
|
};
|
||||||
|
int pc_thunk;
|
||||||
|
|
||||||
|
if (nocode_wanted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
r = REG_VALUE(r);
|
||||||
|
pc_thunk = set_elf_sym(tcc_state->symtab, 0, 0,
|
||||||
|
ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC),
|
||||||
|
ELFW(ST_VISIBILITY)(STV_HIDDEN),
|
||||||
|
SHN_UNDEF, pc_thunk_name[r]);
|
||||||
|
oad(0xe8, -4); /* call __x86.get_pc_thunk.rx */
|
||||||
|
put_elf_reloc(symtab_section, cur_text_section, ind - 4,
|
||||||
|
R_386_PC32, pc_thunk);
|
||||||
|
|
||||||
|
if (add) {
|
||||||
|
Sym label = {0};
|
||||||
|
|
||||||
|
label.type.t = VT_VOID | VT_STATIC;
|
||||||
|
put_extern_sym(&label, cur_text_section, ind, 0);
|
||||||
|
if (r == 0)
|
||||||
|
oad(0x05, 1); /* add _GLOBAL_OFFSET_TABLE_, %eax */
|
||||||
|
else
|
||||||
|
oad(0xc081 + r * 0x100, 2); /* add _GLOBAL_OFFSET_TABLE_, %erx */
|
||||||
|
greloc(cur_text_section, &label, ind - 4, R_386_GOTPC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC void gen_gotpcrel(int r, Sym *sym, int c)
|
||||||
|
{
|
||||||
|
greloc(cur_text_section, sym, ind, R_386_GOT32X);
|
||||||
|
gen_le32(0);
|
||||||
|
if (c) {
|
||||||
|
r = REG_VALUE(r);
|
||||||
|
if (r == 0)
|
||||||
|
oad(0x05, c);
|
||||||
|
else
|
||||||
|
oad(0xc081 + r * 0x100, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* generate jmp to a label */
|
/* generate jmp to a label */
|
||||||
#define gjmp2(instr,lbl) oad(instr,lbl)
|
#define gjmp2(instr,lbl) oad(instr,lbl)
|
||||||
|
|
||||||
@ -191,14 +253,40 @@ ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
|
|||||||
|
|
||||||
/* generate a modrm reference. 'op_reg' contains the additional 3
|
/* generate a modrm reference. 'op_reg' contains the additional 3
|
||||||
opcode bits */
|
opcode bits */
|
||||||
static void gen_modrm(int op_reg, int r, Sym *sym, int c)
|
static void gen_modrm(int opc, int op_reg, int r, Sym *sym, int c)
|
||||||
{
|
{
|
||||||
op_reg = op_reg << 3;
|
#if defined CONFIG_TCC_PIC
|
||||||
|
int is_got = (op_reg & TREG_MEM) && !(sym->type.t & VT_STATIC);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
op_reg = REG_VALUE(op_reg) << 3;
|
||||||
if ((r & VT_VALMASK) == VT_CONST) {
|
if ((r & VT_VALMASK) == VT_CONST) {
|
||||||
/* constant memory reference */
|
/* constant memory reference */
|
||||||
o(0x05 | op_reg);
|
#if defined CONFIG_TCC_PIC
|
||||||
gen_addr32(r, sym, c);
|
if (r & VT_SYM) {
|
||||||
|
get_pc_thunk(TREG_EBX, is_got);
|
||||||
|
o(opc);
|
||||||
|
o(0x83 | op_reg);
|
||||||
|
if (is_got)
|
||||||
|
gen_gotpcrel(r, sym, c);
|
||||||
|
else {
|
||||||
|
int off = 6;
|
||||||
|
|
||||||
|
off += opc & 0xff00 ? 1 : 0;
|
||||||
|
off += opc & 0xff0000 ? 1 : 0;
|
||||||
|
off += opc & 0xff000000 ? 1 : 0;
|
||||||
|
gen_addrpc32(r, sym, c + off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
o(opc);
|
||||||
|
o(0x05 | op_reg);
|
||||||
|
gen_addr32(r, sym, c);
|
||||||
|
}
|
||||||
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||||
|
o(opc);
|
||||||
/* currently, we use only ebp as base */
|
/* currently, we use only ebp as base */
|
||||||
if (c == (char)c) {
|
if (c == (char)c) {
|
||||||
/* short reference */
|
/* short reference */
|
||||||
@ -207,7 +295,16 @@ static void gen_modrm(int op_reg, int r, Sym *sym, int c)
|
|||||||
} else {
|
} else {
|
||||||
oad(0x85 | op_reg, c);
|
oad(0x85 | op_reg, c);
|
||||||
}
|
}
|
||||||
|
} else if ((r & VT_VALMASK) >= TREG_MEM) {
|
||||||
|
o(opc);
|
||||||
|
if (c) {
|
||||||
|
g(0x80 | op_reg | REG_VALUE(r));
|
||||||
|
gen_le32(c);
|
||||||
|
} else {
|
||||||
|
g(0x00 | op_reg | REG_VALUE(r));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
o(opc);
|
||||||
g(0x00 | op_reg | (r & VT_VALMASK));
|
g(0x00 | op_reg | (r & VT_VALMASK));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,7 +312,7 @@ static void gen_modrm(int op_reg, int r, Sym *sym, int c)
|
|||||||
/* load 'r' from value 'sv' */
|
/* load 'r' from value 'sv' */
|
||||||
ST_FUNC void load(int r, SValue *sv)
|
ST_FUNC void load(int r, SValue *sv)
|
||||||
{
|
{
|
||||||
int v, t, ft, fc, fr;
|
int v, t, ft, fc, fr, opc;
|
||||||
SValue v1;
|
SValue v1;
|
||||||
|
|
||||||
fr = sv->r;
|
fr = sv->r;
|
||||||
@ -224,6 +321,25 @@ ST_FUNC void load(int r, SValue *sv)
|
|||||||
|
|
||||||
ft &= ~(VT_VOLATILE | VT_CONSTANT);
|
ft &= ~(VT_VOLATILE | VT_CONSTANT);
|
||||||
|
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
/* we use indirect access via got */
|
||||||
|
if ((fr & VT_VALMASK) == VT_CONST && (fr & VT_SYM) &&
|
||||||
|
(fr & VT_LVAL) && !(sv->sym->type.t & VT_STATIC)) {
|
||||||
|
/* use the result register as a temporal register */
|
||||||
|
int tr = r | TREG_MEM;
|
||||||
|
if (is_float(ft)) {
|
||||||
|
/* we cannot use float registers as a temporal register */
|
||||||
|
tr = get_reg(RC_INT) | TREG_MEM;
|
||||||
|
}
|
||||||
|
gen_modrm(0x8b, tr, fr, sv->sym, 0);
|
||||||
|
|
||||||
|
/* load from the temporal register */
|
||||||
|
fr = tr | VT_LVAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
v = fr & VT_VALMASK;
|
v = fr & VT_VALMASK;
|
||||||
if (fr & VT_LVAL) {
|
if (fr & VT_LVAL) {
|
||||||
if (v == VT_LLOCAL) {
|
if (v == VT_LLOCAL) {
|
||||||
@ -237,34 +353,51 @@ ST_FUNC void load(int r, SValue *sv)
|
|||||||
load(fr, &v1);
|
load(fr, &v1);
|
||||||
}
|
}
|
||||||
if ((ft & VT_BTYPE) == VT_FLOAT) {
|
if ((ft & VT_BTYPE) == VT_FLOAT) {
|
||||||
o(0xd9); /* flds */
|
opc = 0xd9; /* flds */
|
||||||
r = 0;
|
r = 0;
|
||||||
} else if ((ft & VT_BTYPE) == VT_DOUBLE) {
|
} else if ((ft & VT_BTYPE) == VT_DOUBLE) {
|
||||||
o(0xdd); /* fldl */
|
opc = 0xdd; /* fldl */
|
||||||
r = 0;
|
r = 0;
|
||||||
} else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
|
} else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
|
||||||
o(0xdb); /* fldt */
|
opc = 0xdb; /* fldt */
|
||||||
r = 5;
|
r = 5;
|
||||||
} else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) {
|
} else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) {
|
||||||
o(0xbe0f); /* movsbl */
|
opc = 0xbe0f; /* movsbl */
|
||||||
} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
|
} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
|
||||||
o(0xb60f); /* movzbl */
|
opc = 0xb60f; /* movzbl */
|
||||||
} else if ((ft & VT_TYPE) == VT_SHORT) {
|
} else if ((ft & VT_TYPE) == VT_SHORT) {
|
||||||
o(0xbf0f); /* movswl */
|
opc = 0xbf0f; /* movswl */
|
||||||
} else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
|
} else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
|
||||||
o(0xb70f); /* movzwl */
|
opc = 0xb70f; /* movzwl */
|
||||||
} else {
|
} else {
|
||||||
o(0x8b); /* movl */
|
opc = 0x8b; /* movl */
|
||||||
}
|
}
|
||||||
gen_modrm(r, fr, sv->sym, fc);
|
gen_modrm(opc, r, fr, sv->sym, fc);
|
||||||
} else {
|
} else {
|
||||||
if (v == VT_CONST) {
|
if (v == VT_CONST) {
|
||||||
o(0xb8 + r); /* mov $xx, r */
|
#if defined CONFIG_TCC_PIC
|
||||||
gen_addr32(fr, sv->sym, fc);
|
if (fr & VT_SYM) {
|
||||||
|
if (sv->sym->type.t & VT_STATIC) {
|
||||||
|
get_pc_thunk(r, 0);
|
||||||
|
o(0x808d | REG_VALUE(r) * 0x900); /* lea $xx(r), r */
|
||||||
|
gen_addrpc32(fr, sv->sym, fc + 6);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
get_pc_thunk(r, 1);
|
||||||
|
o(0x808b | REG_VALUE(r) * 0x900); /* mov $xx(r), r */
|
||||||
|
gen_gotpcrel(r, sv->sym, fc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
o(0xb8 + r); /* mov $xx, r */
|
||||||
|
gen_addr32(fr, sv->sym, fc);
|
||||||
|
}
|
||||||
} else if (v == VT_LOCAL) {
|
} else if (v == VT_LOCAL) {
|
||||||
if (fc) {
|
if (fc) {
|
||||||
o(0x8d); /* lea xxx(%ebp), r */
|
/* lea xxx(%ebp), r */
|
||||||
gen_modrm(r, VT_LOCAL, sv->sym, fc);
|
gen_modrm(0x8d, r, VT_LOCAL, sv->sym, fc);
|
||||||
} else {
|
} else {
|
||||||
o(0x89);
|
o(0x89);
|
||||||
o(0xe8 + r); /* mov %ebp, r */
|
o(0xe8 + r); /* mov %ebp, r */
|
||||||
@ -290,39 +423,58 @@ ST_FUNC void load(int r, SValue *sv)
|
|||||||
/* store register 'r' in lvalue 'v' */
|
/* store register 'r' in lvalue 'v' */
|
||||||
ST_FUNC void store(int r, SValue *v)
|
ST_FUNC void store(int r, SValue *v)
|
||||||
{
|
{
|
||||||
int fr, bt, ft, fc;
|
int fr, bt, ft, fc, opc, pic = 0;
|
||||||
|
|
||||||
ft = v->type.t;
|
ft = v->type.t;
|
||||||
fc = v->c.i;
|
fc = v->c.i;
|
||||||
fr = v->r & VT_VALMASK;
|
fr = v->r & VT_VALMASK;
|
||||||
ft &= ~(VT_VOLATILE | VT_CONSTANT);
|
ft &= ~(VT_VOLATILE | VT_CONSTANT);
|
||||||
bt = ft & VT_BTYPE;
|
bt = ft & VT_BTYPE;
|
||||||
|
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
/* we need to access the variable via got */
|
||||||
|
if (fr == VT_CONST
|
||||||
|
&& (v->r & VT_SYM)
|
||||||
|
&& !(v->sym->type.t & VT_STATIC)) {
|
||||||
|
get_pc_thunk(TREG_EBX, 1);
|
||||||
|
o(0x9b8b); /* mov xx(%ebx),%ebx */
|
||||||
|
gen_gotpcrel(TREG_EBX, v->sym, v->c.i);
|
||||||
|
pic = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* XXX: incorrect if float reg to reg */
|
/* XXX: incorrect if float reg to reg */
|
||||||
if (bt == VT_FLOAT) {
|
if (bt == VT_FLOAT) {
|
||||||
o(0xd9); /* fsts */
|
opc = 0xd9; /* fsts */
|
||||||
r = 2;
|
r = 2;
|
||||||
} else if (bt == VT_DOUBLE) {
|
} else if (bt == VT_DOUBLE) {
|
||||||
o(0xdd); /* fstpl */
|
opc = 0xdd; /* fstpl */
|
||||||
r = 2;
|
r = 2;
|
||||||
} else if (bt == VT_LDOUBLE) {
|
} else if (bt == VT_LDOUBLE) {
|
||||||
o(0xc0d9); /* fld %st(0) */
|
opc = 0xdbc0d9; /* fld %st(0), fstpt */
|
||||||
o(0xdb); /* fstpt */
|
|
||||||
r = 7;
|
r = 7;
|
||||||
} else {
|
} else if (bt == VT_SHORT)
|
||||||
if (bt == VT_SHORT)
|
opc = 0x8966;
|
||||||
o(0x66);
|
else if (bt == VT_BYTE || bt == VT_BOOL)
|
||||||
if (bt == VT_BYTE || bt == VT_BOOL)
|
opc = 0x88;
|
||||||
o(0x88);
|
else
|
||||||
else
|
opc = 0x89;
|
||||||
o(0x89);
|
if (pic) {
|
||||||
|
o(opc);
|
||||||
|
o(3 + (r << 3));
|
||||||
}
|
}
|
||||||
if (fr == VT_CONST ||
|
else if (fr == VT_CONST ||
|
||||||
fr == VT_LOCAL ||
|
fr == VT_LOCAL ||
|
||||||
(v->r & VT_LVAL)) {
|
(v->r & VT_LVAL)) {
|
||||||
gen_modrm(r, v->r, v->sym, fc);
|
gen_modrm(opc, r, v->r, v->sym, fc);
|
||||||
} else if (fr != r) {
|
} else if (fr != r) {
|
||||||
|
o(opc);
|
||||||
o(0xc0 + fr + r * 8); /* mov r, fr */
|
o(0xc0 + fr + r * 8); /* mov r, fr */
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
tcc_error("store problem");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gadd_sp(int val)
|
static void gadd_sp(int val)
|
||||||
@ -341,8 +493,14 @@ static void gen_static_call(int v)
|
|||||||
Sym *sym;
|
Sym *sym;
|
||||||
|
|
||||||
sym = external_helper_sym(v);
|
sym = external_helper_sym(v);
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
get_pc_thunk(TREG_EBX, 1);
|
||||||
oad(0xe8, -4);
|
oad(0xe8, -4);
|
||||||
greloc(cur_text_section, sym, ind-4, R_386_PC32);
|
greloc(cur_text_section, sym, ind - 4, R_386_PLT32);
|
||||||
|
#else
|
||||||
|
oad(0xe8, -4);
|
||||||
|
greloc(cur_text_section, sym, ind - 4, R_386_PC32);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -352,8 +510,20 @@ static void gcall_or_jmp(int is_jmp)
|
|||||||
int r;
|
int r;
|
||||||
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) {
|
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) {
|
||||||
/* constant and relocation case */
|
/* constant and relocation case */
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
if (vtop->sym->type.t & VT_STATIC) {
|
||||||
|
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
|
||||||
|
greloc(cur_text_section, vtop->sym, ind - 4, R_386_PC32);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
get_pc_thunk(TREG_EBX, 1);
|
||||||
|
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
|
||||||
|
greloc(cur_text_section, vtop->sym, ind - 4, R_386_PLT32);
|
||||||
|
}
|
||||||
|
#else
|
||||||
greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32);
|
greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32);
|
||||||
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
|
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* otherwise, indirect call */
|
/* otherwise, indirect call */
|
||||||
r = gv(RC_INT);
|
r = gv(RC_INT);
|
||||||
@ -507,7 +677,7 @@ ST_FUNC void gfunc_call(int nb_args)
|
|||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
#define FUNC_PROLOG_SIZE (10 + USE_EBX)
|
#define FUNC_PROLOG_SIZE (10 + USE_EBX)
|
||||||
#else
|
#else
|
||||||
#define FUNC_PROLOG_SIZE (9 + USE_EBX)
|
#define FUNC_PROLOG_SIZE (9 + (USE_EBX || GOT_EBX))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* generate function prolog of type 't' */
|
/* generate function prolog of type 't' */
|
||||||
@ -571,8 +741,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
|||||||
if (param_index < fastcall_nb_regs) {
|
if (param_index < fastcall_nb_regs) {
|
||||||
/* save FASTCALL register */
|
/* save FASTCALL register */
|
||||||
loc -= 4;
|
loc -= 4;
|
||||||
o(0x89); /* movl */
|
/* movl */
|
||||||
gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc);
|
gen_modrm(0x89, fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc);
|
||||||
param_addr = loc;
|
param_addr = loc;
|
||||||
} else {
|
} else {
|
||||||
param_addr = addr;
|
param_addr = addr;
|
||||||
@ -610,9 +780,9 @@ ST_FUNC void gfunc_epilog(void)
|
|||||||
v = (-loc + 3) & -4;
|
v = (-loc + 3) & -4;
|
||||||
|
|
||||||
#if USE_EBX
|
#if USE_EBX
|
||||||
o(0x8b);
|
gen_modrm(0x8b, TREG_EBX, VT_LOCAL, NULL, -(v+4));
|
||||||
gen_modrm(TREG_EBX, VT_LOCAL, NULL, -(v+4));
|
|
||||||
#endif
|
#endif
|
||||||
|
o(0x5b * GOT_EBX); /* pop ebx */
|
||||||
|
|
||||||
o(0xc9); /* leave */
|
o(0xc9); /* leave */
|
||||||
if (func_ret_sub == 0) {
|
if (func_ret_sub == 0) {
|
||||||
@ -638,7 +808,7 @@ ST_FUNC void gfunc_epilog(void)
|
|||||||
o(0x90); /* adjust to FUNC_PROLOG_SIZE */
|
o(0x90); /* adjust to FUNC_PROLOG_SIZE */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
o(0x53 * USE_EBX); /* push ebx */
|
o(0x53 * (USE_EBX || GOT_EBX)); /* push ebx */
|
||||||
ind = saved_ind;
|
ind = saved_ind;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -942,11 +1112,8 @@ ST_FUNC void gen_opf(int op)
|
|||||||
fc = 0;
|
fc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ft & VT_BTYPE) == VT_DOUBLE)
|
gen_modrm((ft & VT_BTYPE) == VT_DOUBLE ? 0xdc : 0xd8,
|
||||||
o(0xdc);
|
a, r, vtop->sym, fc);
|
||||||
else
|
|
||||||
o(0xd8);
|
|
||||||
gen_modrm(a, r, vtop->sym, fc);
|
|
||||||
}
|
}
|
||||||
vtop--;
|
vtop--;
|
||||||
}
|
}
|
||||||
@ -1025,13 +1192,26 @@ ST_FUNC void gen_cvt_csti(int t)
|
|||||||
/* increment tcov counter */
|
/* increment tcov counter */
|
||||||
ST_FUNC void gen_increment_tcov (SValue *sv)
|
ST_FUNC void gen_increment_tcov (SValue *sv)
|
||||||
{
|
{
|
||||||
o(0x0583); /* addl $1, xxx */
|
int indir, rel, add1, add2;
|
||||||
greloc(cur_text_section, sv->sym, ind, R_386_32);
|
#if defined CONFIG_TCC_PIC
|
||||||
gen_le32(0);
|
get_pc_thunk(TREG_EBX, 0);
|
||||||
|
indir = 0x8300;
|
||||||
|
rel = R_386_PC32;
|
||||||
|
add1 = 2;
|
||||||
|
add2 = 13;
|
||||||
|
#else
|
||||||
|
indir = 0x0500;
|
||||||
|
rel = R_386_32;
|
||||||
|
add1 = 0;
|
||||||
|
add2 = 4;
|
||||||
|
#endif
|
||||||
|
o(0x0083 + indir); /* addl $1, xxx(%ebx) */
|
||||||
|
greloc(cur_text_section, sv->sym, ind, rel);
|
||||||
|
gen_le32(add1);
|
||||||
o(1);
|
o(1);
|
||||||
o(0x1583); /* addcl $0, xxx */
|
o(0x1083 + indir); /* adcl $0, xxx(%ebx) */
|
||||||
greloc(cur_text_section, sv->sym, ind, R_386_32);
|
greloc(cur_text_section, sv->sym, ind, rel);
|
||||||
gen_le32(4);
|
gen_le32(add2);
|
||||||
g(0);
|
g(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1051,8 +1231,16 @@ static void gen_bounds_prolog(void)
|
|||||||
func_bound_offset = lbounds_section->data_offset;
|
func_bound_offset = lbounds_section->data_offset;
|
||||||
func_bound_ind = ind;
|
func_bound_ind = ind;
|
||||||
func_bound_add_epilog = 0;
|
func_bound_add_epilog = 0;
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
oad(0xb8, 0); /* call to pc_thunk function */
|
||||||
|
oad(0x808d, 0); /* lea lbound section pointer */
|
||||||
|
oad(0xb8, 0); /* call to pc_thunk function */
|
||||||
|
oad(0xc381, 0); /* add _GLOBAL_OFFSET_TABLE_ */
|
||||||
|
oad(0xb8, 0); /* call to function */
|
||||||
|
#else
|
||||||
oad(0xb8, 0); /* lbound section pointer */
|
oad(0xb8, 0); /* lbound section pointer */
|
||||||
oad(0xb8, 0); /* call to function */
|
oad(0xb8, 0); /* call to function */
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_bounds_epilog(void)
|
static void gen_bounds_epilog(void)
|
||||||
@ -1076,16 +1264,30 @@ static void gen_bounds_epilog(void)
|
|||||||
if (offset_modified) {
|
if (offset_modified) {
|
||||||
saved_ind = ind;
|
saved_ind = ind;
|
||||||
ind = func_bound_ind;
|
ind = func_bound_ind;
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
get_pc_thunk(TREG_EAX, 0);
|
||||||
|
o(0x808d | TREG_EAX * 0x900); /* lea $xx(r), r */
|
||||||
|
greloc(cur_text_section, sym_data, ind, R_386_PC32);
|
||||||
|
gen_le32(2);
|
||||||
|
#else
|
||||||
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
|
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
|
||||||
ind = ind + 5;
|
ind = ind + 5;
|
||||||
|
#endif
|
||||||
gen_static_call(TOK___bound_local_new);
|
gen_static_call(TOK___bound_local_new);
|
||||||
ind = saved_ind;
|
ind = saved_ind;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate bound check local freeing */
|
/* generate bound check local freeing */
|
||||||
o(0x5250); /* save returned value, if any */
|
o(0x5250); /* save returned value, if any */
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
get_pc_thunk(TREG_EAX, 0);
|
||||||
|
o(0x808d | TREG_EAX * 0x900); /* lea $xx(r), r */
|
||||||
|
greloc(cur_text_section, sym_data, ind, R_386_PC32);
|
||||||
|
gen_le32(2);
|
||||||
|
#else
|
||||||
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
|
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
|
||||||
oad(0xb8, 0); /* mov %eax, xxx */
|
oad(0xb8, 0); /* mov %eax, xxx */
|
||||||
|
#endif
|
||||||
gen_static_call(TOK___bound_local_delete);
|
gen_static_call(TOK___bound_local_delete);
|
||||||
o(0x585a); /* restore returned value, if any */
|
o(0x585a); /* restore returned value, if any */
|
||||||
}
|
}
|
||||||
@ -1094,14 +1296,12 @@ static void gen_bounds_epilog(void)
|
|||||||
/* Save the stack pointer onto the stack */
|
/* Save the stack pointer onto the stack */
|
||||||
ST_FUNC void gen_vla_sp_save(int addr) {
|
ST_FUNC void gen_vla_sp_save(int addr) {
|
||||||
/* mov %esp,addr(%ebp)*/
|
/* mov %esp,addr(%ebp)*/
|
||||||
o(0x89);
|
gen_modrm(0x89, TREG_ESP, VT_LOCAL, NULL, addr);
|
||||||
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore the SP from a location on the stack */
|
/* Restore the SP from a location on the stack */
|
||||||
ST_FUNC void gen_vla_sp_restore(int addr) {
|
ST_FUNC void gen_vla_sp_restore(int addr) {
|
||||||
o(0x8b);
|
gen_modrm(0x8b, TREG_ESP, VT_LOCAL, NULL, addr);
|
||||||
gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subtract from the stack pointer, and push the resulting value onto the stack */
|
/* Subtract from the stack pointer, and push the resulting value onto the stack */
|
||||||
|
|||||||
@ -15,7 +15,11 @@
|
|||||||
#define ELF_START_ADDR 0x08048000
|
#define ELF_START_ADDR 0x08048000
|
||||||
#define ELF_PAGE_SIZE 0x1000
|
#define ELF_PAGE_SIZE 0x1000
|
||||||
|
|
||||||
|
#if defined CONFIG_TCC_PIC
|
||||||
|
#define PCRELATIVE_DLLPLT 1
|
||||||
|
#else
|
||||||
#define PCRELATIVE_DLLPLT 0
|
#define PCRELATIVE_DLLPLT 0
|
||||||
|
#endif
|
||||||
#define RELOCATE_DLLPLT 1
|
#define RELOCATE_DLLPLT 1
|
||||||
|
|
||||||
#else /* !TARGET_DEFS_ONLY */
|
#else /* !TARGET_DEFS_ONLY */
|
||||||
|
|||||||
@ -35,7 +35,7 @@ endif
|
|||||||
|
|
||||||
XFLAGS += -I$(TOP)
|
XFLAGS += -I$(TOP)
|
||||||
|
|
||||||
I386_O = libtcc1.o $(COMMON_O)
|
I386_O = libtcc1.o get_pc_thunk.o $(COMMON_O)
|
||||||
X86_64_O = libtcc1.o $(COMMON_O)
|
X86_64_O = libtcc1.o $(COMMON_O)
|
||||||
ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O)
|
ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O)
|
||||||
ARM64_O = lib-arm64.o $(COMMON_O)
|
ARM64_O = lib-arm64.o $(COMMON_O)
|
||||||
@ -56,7 +56,7 @@ $(Cbt)WIN_O += bt-dll.o
|
|||||||
$(Cbc)COMMON_O += bcheck.o
|
$(Cbc)COMMON_O += bcheck.o
|
||||||
|
|
||||||
# not in libtcc1.a
|
# not in libtcc1.a
|
||||||
EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o
|
EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o get_pc_thunk.o
|
||||||
|
|
||||||
OBJ-i386 = $(I386_O) $(LIN_O)
|
OBJ-i386 = $(I386_O) $(LIN_O)
|
||||||
OBJ-x86_64 = $(X86_64_O) $(LIN_O)
|
OBJ-x86_64 = $(X86_64_O) $(LIN_O)
|
||||||
@ -90,6 +90,9 @@ $(X)%.o : %.c $(TCC)
|
|||||||
$(X)%.o : %.S $(TCC)
|
$(X)%.o : %.S $(TCC)
|
||||||
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
||||||
|
|
||||||
|
$(TOP)/%.o : %.S $(TCC)
|
||||||
|
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
||||||
|
|
||||||
$(TOP)/%.o : %.c $(TCC)
|
$(TOP)/%.o : %.c $(TCC)
|
||||||
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
$S$(XCC) -c $< -o $@ $(XFLAGS)
|
||||||
|
|
||||||
|
|||||||
39
lib/get_pc_thunk.S
Normal file
39
lib/get_pc_thunk.S
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* ---------------------------------------------- */
|
||||||
|
/* get_pc_thunk.S */
|
||||||
|
|
||||||
|
#ifdef __leading_underscore
|
||||||
|
# define _(s) _##s
|
||||||
|
#else
|
||||||
|
# define _(s) s
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
.text
|
||||||
|
|
||||||
|
.globl _(__x86.get_pc_thunk.ax)
|
||||||
|
.hidden _(__x86.get_pc_thunk.ax)
|
||||||
|
_(__x86.get_pc_thunk.ax):
|
||||||
|
mov (%esp),%eax
|
||||||
|
ret
|
||||||
|
.size _(__x86.get_pc_thunk.ax), .-_(__x86.get_pc_thunk.ax)
|
||||||
|
|
||||||
|
.globl _(__x86.get_pc_thunk.bx)
|
||||||
|
.hidden _(__x86.get_pc_thunk.bx)
|
||||||
|
_(__x86.get_pc_thunk.bx):
|
||||||
|
mov (%esp),%ebx
|
||||||
|
ret
|
||||||
|
.size _(__x86.get_pc_thunk.bx), .-_(__x86.get_pc_thunk.bx)
|
||||||
|
|
||||||
|
.globl _(__x86.get_pc_thunk.cx)
|
||||||
|
.hidden _(__x86.get_pc_thunk.cx)
|
||||||
|
_(__x86.get_pc_thunk.cx):
|
||||||
|
mov (%esp),%ecx
|
||||||
|
ret
|
||||||
|
.size _(__x86.get_pc_thunk.cx), .-_(__x86.get_pc_thunk.cx)
|
||||||
|
|
||||||
|
.globl _(__x86.get_pc_thunk.dx)
|
||||||
|
.hidden _(__x86.get_pc_thunk.dx)
|
||||||
|
_(__x86.get_pc_thunk.dx):
|
||||||
|
mov (%esp),%edx
|
||||||
|
ret
|
||||||
|
.size _(__x86.get_pc_thunk.dx), .-_(__x86.get_pc_thunk.dx)
|
||||||
26
tccelf.c
26
tccelf.c
@ -1237,6 +1237,17 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
|||||||
break;
|
break;
|
||||||
#if defined(TCC_TARGET_I386)
|
#if defined(TCC_TARGET_I386)
|
||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
|
{
|
||||||
|
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
/* Hidden defined symbols can and must be resolved locally.
|
||||||
|
We're misusing a PLT32 reloc for this, as that's always
|
||||||
|
resolved to its address even in shared libs. */
|
||||||
|
if (sym->st_shndx != SHN_UNDEF &&
|
||||||
|
ELFW(ST_VISIBILITY)(sym->st_other) == STV_HIDDEN) {
|
||||||
|
rel->r_info = ELFW(R_INFO)(sym_index, R_386_PLT32);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
#elif defined(TCC_TARGET_X86_64)
|
#elif defined(TCC_TARGET_X86_64)
|
||||||
case R_X86_64_PC32:
|
case R_X86_64_PC32:
|
||||||
{
|
{
|
||||||
@ -1455,6 +1466,18 @@ redo:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_I386
|
||||||
|
if ((type == R_386_PLT32 || type == R_386_PC32) &&
|
||||||
|
sym->st_shndx != SHN_UNDEF &&
|
||||||
|
(ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT ||
|
||||||
|
ELFW(ST_BIND)(sym->st_info) == STB_LOCAL ||
|
||||||
|
s1->output_type & TCC_OUTPUT_EXE)) {
|
||||||
|
if (pass != 0)
|
||||||
|
continue;
|
||||||
|
rel->r_info = ELFW(R_INFO)(sym_index, R_386_PC32);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
if ((type == R_X86_64_PLT32 || type == R_X86_64_PC32) &&
|
if ((type == R_X86_64_PLT32 || type == R_X86_64_PC32) &&
|
||||||
sym->st_shndx != SHN_UNDEF &&
|
sym->st_shndx != SHN_UNDEF &&
|
||||||
@ -1817,6 +1840,9 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
|||||||
tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
|
tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if defined CONFIG_TCC_PIC && defined TCC_TARGET_I386
|
||||||
|
tcc_add_support(s1, "get_pc_thunk.o");
|
||||||
|
#endif
|
||||||
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
|
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
|
||||||
tcc_add_library(s1, "gcc_s"); // unwind code
|
tcc_add_library(s1, "gcc_s"); // unwind code
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user