mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50:07 +08:00
Move almost all global variables to TCCState, actually all tests pass on Ubuntu 18.04 x86_64
This commit is contained in:
parent
ca11849ebb
commit
af686a796b
64
arm-link.c
64
arm-link.c
@ -107,9 +107,9 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TCC_TARGET_PE
|
#ifndef TCC_TARGET_PE
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
Section *plt = s1->plt;
|
Section *plt = S->plt;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
unsigned plt_offset;
|
unsigned plt_offset;
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
/* empty PLT: create PLT0 entry that push address of call site and
|
/* empty PLT: create PLT0 entry that push address of call site and
|
||||||
jump to ld.so resolution routine (GOT + 8) */
|
jump to ld.so resolution routine (GOT + 8) */
|
||||||
if (plt->data_offset == 0) {
|
if (plt->data_offset == 0) {
|
||||||
p = section_ptr_add(plt, 20);
|
p = section_ptr_add(S, plt, 20);
|
||||||
write32le(p, 0xe52de004); /* push {lr} */
|
write32le(p, 0xe52de004); /* push {lr} */
|
||||||
write32le(p+4, 0xe59fe004); /* ldr lr, [pc, #4] */
|
write32le(p+4, 0xe59fe004); /* ldr lr, [pc, #4] */
|
||||||
write32le(p+8, 0xe08fe00e); /* add lr, pc, lr */
|
write32le(p+8, 0xe08fe00e); /* add lr, pc, lr */
|
||||||
@ -129,11 +129,11 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
plt_offset = plt->data_offset;
|
plt_offset = plt->data_offset;
|
||||||
|
|
||||||
if (attr->plt_thumb_stub) {
|
if (attr->plt_thumb_stub) {
|
||||||
p = section_ptr_add(plt, 4);
|
p = section_ptr_add(S, plt, 4);
|
||||||
write32le(p, 0x4778); /* bx pc */
|
write32le(p, 0x4778); /* bx pc */
|
||||||
write32le(p+2, 0x46c0); /* nop */
|
write32le(p+2, 0x46c0); /* nop */
|
||||||
}
|
}
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(S, plt, 16);
|
||||||
/* save GOT offset for relocate_plt */
|
/* save GOT offset for relocate_plt */
|
||||||
write32le(p + 4, got_offset);
|
write32le(p + 4, got_offset);
|
||||||
return plt_offset;
|
return plt_offset;
|
||||||
@ -141,22 +141,22 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
|
|
||||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||||
address for PLT and GOT are known (see fill_program_header) */
|
address for PLT and GOT are known (see fill_program_header) */
|
||||||
ST_FUNC void relocate_plt(TCCState *s1)
|
ST_FUNC void relocate_plt(TCCState *S)
|
||||||
{
|
{
|
||||||
uint8_t *p, *p_end;
|
uint8_t *p, *p_end;
|
||||||
|
|
||||||
if (!s1->plt)
|
if (!S->plt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p = s1->plt->data;
|
p = S->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
p_end = p + S->plt->data_offset;
|
||||||
|
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
int x = s1->got->sh_addr - s1->plt->sh_addr - 12;
|
int x = S->got->sh_addr - S->plt->sh_addr - 12;
|
||||||
write32le(s1->plt->data + 16, x - 4);
|
write32le(S->plt->data + 16, x - 4);
|
||||||
p += 20;
|
p += 20;
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4;
|
unsigned off = x + read32le(p + 4) + (S->plt->data - p) + 4;
|
||||||
if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
|
if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
|
||||||
p += 4;
|
p += 4;
|
||||||
write32le(p, 0xe28fc200 | ((off >> 28) & 0xf)); // add ip, pc, #0xN0000000
|
write32le(p, 0xe28fc200 | ((off >> 28) & 0xf)); // add ip, pc, #0xN0000000
|
||||||
@ -167,17 +167,17 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->plt->reloc) {
|
if (S->plt->reloc) {
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
p = s1->got->data;
|
p = S->got->data;
|
||||||
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
write32le(p + rel->r_offset, s1->plt->sh_addr);
|
write32le(p + rel->r_offset, S->plt->sh_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
{
|
{
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int sym_index, esym_index;
|
int sym_index, esym_index;
|
||||||
@ -212,7 +212,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
h = x & 2;
|
h = x & 2;
|
||||||
th_ko = (x & 3) && (!blx_avail || !is_call);
|
th_ko = (x & 3) && (!blx_avail || !is_call);
|
||||||
if (th_ko || x >= 0x2000000 || x < -0x2000000)
|
if (th_ko || x >= 0x2000000 || x < -0x2000000)
|
||||||
tcc_error("can't relocate value at %x,%d",addr, type);
|
tcc_error(S, "can't relocate value at %x,%d",addr, type);
|
||||||
x >>= 2;
|
x >>= 2;
|
||||||
x &= 0xffffff;
|
x &= 0xffffff;
|
||||||
/* Only reached if blx is avail and it is a call */
|
/* Only reached if blx is avail and it is a call */
|
||||||
@ -255,7 +255,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
|
|
||||||
/* Relocation infos */
|
/* Relocation infos */
|
||||||
to_thumb = val & 1;
|
to_thumb = val & 1;
|
||||||
plt = s1->plt;
|
plt = S->plt;
|
||||||
to_plt = (val >= plt->sh_addr) &&
|
to_plt = (val >= plt->sh_addr) &&
|
||||||
(val < plt->sh_addr + plt->data_offset);
|
(val < plt->sh_addr + plt->data_offset);
|
||||||
is_call = (type == R_ARM_THM_PC22);
|
is_call = (type == R_ARM_THM_PC22);
|
||||||
@ -267,10 +267,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
Section *text;
|
Section *text;
|
||||||
|
|
||||||
name = (char *) symtab_section->link->data + sym->st_name;
|
name = (char *) symtab_section->link->data + sym->st_name;
|
||||||
text = s1->sections[sym->st_shndx];
|
text = S->sections[sym->st_shndx];
|
||||||
/* Modify reloc to target a thumb stub to switch to ARM */
|
/* Modify reloc to target a thumb stub to switch to ARM */
|
||||||
snprintf(buf, sizeof(buf), "%s_from_thumb", name);
|
snprintf(buf, sizeof(buf), "%s_from_thumb", name);
|
||||||
index = put_elf_sym(symtab_section,
|
index = put_elf_sym(S, symtab_section,
|
||||||
text->data_offset + 1,
|
text->data_offset + 1,
|
||||||
sym->st_size, sym->st_info, 0,
|
sym->st_size, sym->st_info, 0,
|
||||||
sym->st_shndx, buf);
|
sym->st_shndx, buf);
|
||||||
@ -281,7 +281,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
put_elf_reloc(symtab_section, text,
|
put_elf_reloc(symtab_section, text,
|
||||||
text->data_offset + 4, R_ARM_JUMP24,
|
text->data_offset + 4, R_ARM_JUMP24,
|
||||||
sym_index);
|
sym_index);
|
||||||
p = section_ptr_add(text, 8);
|
p = section_ptr_add(S, text, 8);
|
||||||
write32le(p, 0x4778); /* bx pc */
|
write32le(p, 0x4778); /* bx pc */
|
||||||
write32le(p+2, 0x46c0); /* nop */
|
write32le(p+2, 0x46c0); /* nop */
|
||||||
write32le(p+4, 0xeafffffe); /* b $sym */
|
write32le(p+4, 0xeafffffe); /* b $sym */
|
||||||
@ -301,7 +301,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
- instruction must be a call (bl) or a jump to PLT */
|
- instruction must be a call (bl) or a jump to PLT */
|
||||||
if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
|
if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
|
||||||
if (to_thumb || (val & 2) || (!is_call && !to_plt))
|
if (to_thumb || (val & 2) || (!is_call && !to_plt))
|
||||||
tcc_error("can't relocate value at %x,%d",addr, type);
|
tcc_error(S, "can't relocate value at %x,%d",addr, type);
|
||||||
|
|
||||||
/* Compute and store final offset */
|
/* Compute and store final offset */
|
||||||
s = (x >> 24) & 1;
|
s = (x >> 24) & 1;
|
||||||
@ -372,14 +372,14 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
x = (x * 2) / 2;
|
x = (x * 2) / 2;
|
||||||
x += val - addr;
|
x += val - addr;
|
||||||
if((x^(x>>1))&0x40000000)
|
if((x^(x>>1))&0x40000000)
|
||||||
tcc_error("can't relocate value at %x,%d",addr, type);
|
tcc_error(S, "can't relocate value at %x,%d",addr, type);
|
||||||
(*(int *)ptr) |= x & 0x7fffffff;
|
(*(int *)ptr) |= x & 0x7fffffff;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case R_ARM_ABS32:
|
case R_ARM_ABS32:
|
||||||
case R_ARM_TARGET1:
|
case R_ARM_TARGET1:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_ARM_ABS32);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_ARM_ABS32);
|
||||||
@ -396,19 +396,19 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
*(int *)ptr += val - addr;
|
*(int *)ptr += val - addr;
|
||||||
return;
|
return;
|
||||||
case R_ARM_GOTPC:
|
case R_ARM_GOTPC:
|
||||||
*(int *)ptr += s1->got->sh_addr - addr;
|
*(int *)ptr += S->got->sh_addr - addr;
|
||||||
return;
|
return;
|
||||||
case R_ARM_GOTOFF:
|
case R_ARM_GOTOFF:
|
||||||
*(int *)ptr += val - s1->got->sh_addr;
|
*(int *)ptr += val - S->got->sh_addr;
|
||||||
return;
|
return;
|
||||||
case R_ARM_GOT32:
|
case R_ARM_GOT32:
|
||||||
/* we load the got offset */
|
/* we load the got offset */
|
||||||
*(int *)ptr += get_sym_attr(s1, sym_index, 0)->got_offset;
|
*(int *)ptr += get_sym_attr(S, sym_index, 0)->got_offset;
|
||||||
return;
|
return;
|
||||||
case R_ARM_GOT_PREL:
|
case R_ARM_GOT_PREL:
|
||||||
/* we load the pc relative got offset */
|
/* we load the pc relative got offset */
|
||||||
*(int *)ptr += s1->got->sh_addr +
|
*(int *)ptr += S->got->sh_addr +
|
||||||
get_sym_attr(s1, sym_index, 0)->got_offset -
|
get_sym_attr(S, sym_index, 0)->got_offset -
|
||||||
addr;
|
addr;
|
||||||
return;
|
return;
|
||||||
case R_ARM_COPY:
|
case R_ARM_COPY:
|
||||||
@ -428,7 +428,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
return;
|
return;
|
||||||
case R_ARM_RELATIVE:
|
case R_ARM_RELATIVE:
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
add32le(ptr, val - s1->pe_imagebase);
|
add32le(ptr, val - S->pe_imagebase);
|
||||||
#endif
|
#endif
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
return;
|
return;
|
||||||
|
26
arm64-asm.c
26
arm64-asm.c
@ -9,9 +9,9 @@
|
|||||||
#define CONFIG_TCC_ASM
|
#define CONFIG_TCC_ASM
|
||||||
#define NB_ASM_REGS 16
|
#define NB_ASM_REGS 16
|
||||||
|
|
||||||
ST_FUNC void g(int c);
|
ST_FUNC void g(TCCState* S, int c);
|
||||||
ST_FUNC void gen_le16(int c);
|
ST_FUNC void gen_le16(TCCState* S, int c);
|
||||||
ST_FUNC void gen_le32(int c);
|
ST_FUNC void gen_le32(TCCState* S, int c);
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
#else
|
#else
|
||||||
@ -25,7 +25,7 @@ static void asm_error(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: make it faster ? */
|
/* XXX: make it faster ? */
|
||||||
ST_FUNC void g(int c)
|
ST_FUNC void g(TCCState* S, int c)
|
||||||
{
|
{
|
||||||
int ind1;
|
int ind1;
|
||||||
if (nocode_wanted)
|
if (nocode_wanted)
|
||||||
@ -37,24 +37,24 @@ ST_FUNC void g(int c)
|
|||||||
ind = ind1;
|
ind = ind1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_le16 (int i)
|
ST_FUNC void gen_le16 (TCCState* S, int i)
|
||||||
{
|
{
|
||||||
g(i);
|
g(S, i);
|
||||||
g(i>>8);
|
g(S, i>>8);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_le32 (int i)
|
ST_FUNC void gen_le32 (TCCState* S, int i)
|
||||||
{
|
{
|
||||||
gen_le16(i);
|
gen_le16(S, i);
|
||||||
gen_le16(i>>16);
|
gen_le16(S, i>>16);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_expr32(ExprValue *pe)
|
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
|
||||||
{
|
{
|
||||||
gen_le32(pe->v);
|
gen_le32(S, pe->v);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
ST_FUNC void asm_opcode(TCCState *S, int opcode)
|
||||||
{
|
{
|
||||||
asm_error();
|
asm_error();
|
||||||
}
|
}
|
||||||
|
1286
arm64-gen.c
1286
arm64-gen.c
File diff suppressed because it is too large
Load Diff
64
arm64-link.c
64
arm64-link.c
@ -90,18 +90,18 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
Section *plt = s1->plt;
|
Section *plt = S->plt;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
unsigned plt_offset;
|
unsigned plt_offset;
|
||||||
|
|
||||||
if (plt->data_offset == 0) {
|
if (plt->data_offset == 0) {
|
||||||
section_ptr_add(plt, 32);
|
section_ptr_add(S, plt, 32);
|
||||||
}
|
}
|
||||||
plt_offset = plt->data_offset;
|
plt_offset = plt->data_offset;
|
||||||
|
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(S, plt, 16);
|
||||||
write32le(p, got_offset);
|
write32le(p, got_offset);
|
||||||
write32le(p + 4, (uint64_t) got_offset >> 32);
|
write32le(p + 4, (uint64_t) got_offset >> 32);
|
||||||
return plt_offset;
|
return plt_offset;
|
||||||
@ -109,22 +109,22 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
|
|
||||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||||
address for PLT and GOT are known (see fill_program_header) */
|
address for PLT and GOT are known (see fill_program_header) */
|
||||||
ST_FUNC void relocate_plt(TCCState *s1)
|
ST_FUNC void relocate_plt(TCCState *S)
|
||||||
{
|
{
|
||||||
uint8_t *p, *p_end;
|
uint8_t *p, *p_end;
|
||||||
|
|
||||||
if (!s1->plt)
|
if (!S->plt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p = s1->plt->data;
|
p = S->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
p_end = p + S->plt->data_offset;
|
||||||
|
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
uint64_t plt = s1->plt->sh_addr;
|
uint64_t plt = S->plt->sh_addr;
|
||||||
uint64_t got = s1->got->sh_addr + 16;
|
uint64_t got = S->got->sh_addr + 16;
|
||||||
uint64_t off = (got >> 12) - (plt >> 12);
|
uint64_t off = (got >> 12) - (plt >> 12);
|
||||||
if ((off + ((uint32_t)1 << 20)) >> 21)
|
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||||
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
|
tcc_error(S, "Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
|
||||||
write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
|
write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
|
||||||
write32le(p + 4, (0x90000010 | // adrp x16,...
|
write32le(p + 4, (0x90000010 | // adrp x16,...
|
||||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||||
@ -137,13 +137,13 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
write32le(p + 24, 0xd503201f); // nop
|
write32le(p + 24, 0xd503201f); // nop
|
||||||
write32le(p + 28, 0xd503201f); // nop
|
write32le(p + 28, 0xd503201f); // nop
|
||||||
p += 32;
|
p += 32;
|
||||||
got = s1->got->sh_addr;
|
got = S->got->sh_addr;
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
uint64_t pc = plt + (p - s1->plt->data);
|
uint64_t pc = plt + (p - S->plt->data);
|
||||||
uint64_t addr = got + read64le(p);
|
uint64_t addr = got + read64le(p);
|
||||||
uint64_t off = (addr >> 12) - (pc >> 12);
|
uint64_t off = (addr >> 12) - (pc >> 12);
|
||||||
if ((off + ((uint32_t)1 << 20)) >> 21)
|
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||||
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
|
tcc_error(S, "Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
|
||||||
write32le(p, (0x90000010 | // adrp x16,...
|
write32le(p, (0x90000010 | // adrp x16,...
|
||||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||||
write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
|
write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
|
||||||
@ -155,16 +155,16 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->plt->reloc) {
|
if (S->plt->reloc) {
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
p = s1->got->data;
|
p = S->got->data;
|
||||||
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
write64le(p + rel->r_offset, s1->plt->sh_addr);
|
write64le(p + rel->r_offset, S->plt->sh_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
{
|
{
|
||||||
int sym_index = ELFW(R_SYM)(rel->r_info), esym_index;
|
int sym_index = ELFW(R_SYM)(rel->r_info), esym_index;
|
||||||
#ifdef DEBUG_RELOC
|
#ifdef DEBUG_RELOC
|
||||||
@ -173,8 +173,8 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case R_AARCH64_ABS64:
|
case R_AARCH64_ABS64:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_AARCH64_ABS64);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_AARCH64_ABS64);
|
||||||
@ -190,7 +190,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
add64le(ptr, val);
|
add64le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_AARCH64_ABS32:
|
case R_AARCH64_ABS32:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
/* XXX: this logic may depend on TCC's codegen
|
/* XXX: this logic may depend on TCC's codegen
|
||||||
now TCC uses R_AARCH64_RELATIVE even for a 64bit pointer */
|
now TCC uses R_AARCH64_RELATIVE even for a 64bit pointer */
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
@ -202,9 +202,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
add32le(ptr, val);
|
add32le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_AARCH64_PREL32:
|
case R_AARCH64_PREL32:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
/* DLL relocation */
|
/* DLL relocation */
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_AARCH64_PREL32);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_AARCH64_PREL32);
|
||||||
@ -235,7 +235,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
case R_AARCH64_ADR_PREL_PG_HI21: {
|
case R_AARCH64_ADR_PREL_PG_HI21: {
|
||||||
uint64_t off = (val >> 12) - (addr >> 12);
|
uint64_t off = (val >> 12) - (addr >> 12);
|
||||||
if ((off + ((uint64_t)1 << 20)) >> 21)
|
if ((off + ((uint64_t)1 << 20)) >> 21)
|
||||||
tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
|
tcc_error(S, "R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
|
||||||
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
|
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
|
||||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||||
return;
|
return;
|
||||||
@ -268,7 +268,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
(char *) symtab_section->link->data + sym->st_name);
|
(char *) symtab_section->link->data + sym->st_name);
|
||||||
#endif
|
#endif
|
||||||
if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
|
if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
|
||||||
tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed"
|
tcc_error(S, "R_AARCH64_(JUMP|CALL)26 relocation failed"
|
||||||
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
write32le(ptr, (0x14000000 |
|
write32le(ptr, (0x14000000 |
|
||||||
(uint32_t)(type == R_AARCH64_CALL26) << 31 |
|
(uint32_t)(type == R_AARCH64_CALL26) << 31 |
|
||||||
@ -276,10 +276,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
return;
|
return;
|
||||||
case R_AARCH64_ADR_GOT_PAGE: {
|
case R_AARCH64_ADR_GOT_PAGE: {
|
||||||
uint64_t off =
|
uint64_t off =
|
||||||
(((s1->got->sh_addr +
|
(((S->got->sh_addr +
|
||||||
get_sym_attr(s1, sym_index, 0)->got_offset) >> 12) - (addr >> 12));
|
get_sym_attr(S, sym_index, 0)->got_offset) >> 12) - (addr >> 12));
|
||||||
if ((off + ((uint64_t)1 << 20)) >> 21)
|
if ((off + ((uint64_t)1 << 20)) >> 21)
|
||||||
tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
|
tcc_error(S, "R_AARCH64_ADR_GOT_PAGE relocation failed");
|
||||||
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
|
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
|
||||||
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
(off & 0x1ffffc) << 3 | (off & 3) << 29));
|
||||||
return;
|
return;
|
||||||
@ -287,8 +287,8 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
case R_AARCH64_LD64_GOT_LO12_NC:
|
case R_AARCH64_LD64_GOT_LO12_NC:
|
||||||
write32le(ptr,
|
write32le(ptr,
|
||||||
((read32le(ptr) & 0xfff803ff) |
|
((read32le(ptr) & 0xfff803ff) |
|
||||||
((s1->got->sh_addr +
|
((S->got->sh_addr +
|
||||||
get_sym_attr(s1, sym_index, 0)->got_offset) & 0xff8) << 7));
|
get_sym_attr(S, sym_index, 0)->got_offset) & 0xff8) << 7));
|
||||||
return;
|
return;
|
||||||
case R_AARCH64_COPY:
|
case R_AARCH64_COPY:
|
||||||
return;
|
return;
|
||||||
@ -304,7 +304,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
return;
|
return;
|
||||||
case R_AARCH64_RELATIVE:
|
case R_AARCH64_RELATIVE:
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
add32le(ptr, val - s1->pe_imagebase);
|
add32le(ptr, val - S->pe_imagebase);
|
||||||
#endif
|
#endif
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
return;
|
return;
|
||||||
|
14
c67-link.c
14
c67-link.c
@ -65,23 +65,23 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
tcc_error("C67 got not implemented");
|
tcc_error(S, "C67 got not implemented");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||||
address for PLT and GOT are known (see fill_program_header) */
|
address for PLT and GOT are known (see fill_program_header) */
|
||||||
ST_FUNC void relocate_plt(TCCState *s1)
|
ST_FUNC void relocate_plt(TCCState *S)
|
||||||
{
|
{
|
||||||
uint8_t *p, *p_end;
|
uint8_t *p, *p_end;
|
||||||
|
|
||||||
if (!s1->plt)
|
if (!S->plt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p = s1->plt->data;
|
p = S->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
p_end = p + S->plt->data_offset;
|
||||||
|
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
/* XXX: TODO */
|
/* XXX: TODO */
|
||||||
@ -91,7 +91,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
{
|
{
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case R_C60_32:
|
case R_C60_32:
|
||||||
|
374
i386-asm.c
374
i386-asm.c
@ -253,10 +253,10 @@ static const uint16_t op0_codes[] = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int get_reg_shift(TCCState *s1)
|
static inline int get_reg_shift(TCCState *S)
|
||||||
{
|
{
|
||||||
int shift, v;
|
int shift, v;
|
||||||
v = asm_int_expr(s1);
|
v = asm_int_expr(S);
|
||||||
switch(v) {
|
switch(v) {
|
||||||
case 1:
|
case 1:
|
||||||
shift = 0;
|
shift = 0;
|
||||||
@ -271,7 +271,7 @@ static inline int get_reg_shift(TCCState *s1)
|
|||||||
shift = 3;
|
shift = 3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
expect("1, 2, 4 or 8 constant");
|
expect(S, "1, 2, 4 or 8 constant");
|
||||||
shift = 0;
|
shift = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -279,11 +279,11 @@ static inline int get_reg_shift(TCCState *s1)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
static int asm_parse_numeric_reg(int t, unsigned int *type)
|
static int asm_parse_numeric_reg(TCCState *S, int t, unsigned int *type)
|
||||||
{
|
{
|
||||||
int reg = -1;
|
int reg = -1;
|
||||||
if (t >= TOK_IDENT && t < tok_ident) {
|
if (t >= TOK_IDENT && t < S->tccpp_tok_ident) {
|
||||||
const char *s = table_ident[t - TOK_IDENT]->str;
|
const char *s = S->tccpp_table_ident[t - TOK_IDENT]->str;
|
||||||
char c;
|
char c;
|
||||||
*type = OP_REG64;
|
*type = OP_REG64;
|
||||||
if (*s == 'c') {
|
if (*s == 'c') {
|
||||||
@ -318,51 +318,51 @@ static int asm_parse_numeric_reg(int t, unsigned int *type)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int asm_parse_reg(unsigned int *type)
|
static int asm_parse_reg(TCCState* S, unsigned int *type)
|
||||||
{
|
{
|
||||||
int reg = 0;
|
int reg = 0;
|
||||||
*type = 0;
|
*type = 0;
|
||||||
if (tok != '%')
|
if (S->tccpp_tok != '%')
|
||||||
goto error_32;
|
goto error_32;
|
||||||
next();
|
next(S);
|
||||||
if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
|
if (S->tccpp_tok >= TOK_ASM_eax && S->tccpp_tok <= TOK_ASM_edi) {
|
||||||
reg = tok - TOK_ASM_eax;
|
reg = S->tccpp_tok - TOK_ASM_eax;
|
||||||
*type = OP_REG32;
|
*type = OP_REG32;
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
} else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) {
|
} else if (S->tccpp_tok >= TOK_ASM_rax && S->tccpp_tok <= TOK_ASM_rdi) {
|
||||||
reg = tok - TOK_ASM_rax;
|
reg = S->tccpp_tok - TOK_ASM_rax;
|
||||||
*type = OP_REG64;
|
*type = OP_REG64;
|
||||||
} else if (tok == TOK_ASM_rip) {
|
} else if (S->tccpp_tok == TOK_ASM_rip) {
|
||||||
reg = -2; /* Probably should use different escape code. */
|
reg = -2; /* Probably should use different escape code. */
|
||||||
*type = OP_REG64;
|
*type = OP_REG64;
|
||||||
} else if ((reg = asm_parse_numeric_reg(tok, type)) >= 0
|
} else if ((reg = asm_parse_numeric_reg(S, S->tccpp_tok, type)) >= 0
|
||||||
&& (*type == OP_REG32 || *type == OP_REG64)) {
|
&& (*type == OP_REG32 || *type == OP_REG64)) {
|
||||||
;
|
;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
error_32:
|
error_32:
|
||||||
expect("register");
|
expect(S, "register");
|
||||||
}
|
}
|
||||||
next();
|
next(S);
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_operand(TCCState *s1, Operand *op)
|
static void parse_operand(TCCState *S, Operand *op)
|
||||||
{
|
{
|
||||||
ExprValue e;
|
ExprValue e;
|
||||||
int reg, indir;
|
int reg, indir;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
indir = 0;
|
indir = 0;
|
||||||
if (tok == '*') {
|
if (S->tccpp_tok == '*') {
|
||||||
next();
|
next(S);
|
||||||
indir = OP_INDIR;
|
indir = OP_INDIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok == '%') {
|
if (S->tccpp_tok == '%') {
|
||||||
next();
|
next(S);
|
||||||
if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
|
if (S->tccpp_tok >= TOK_ASM_al && S->tccpp_tok <= TOK_ASM_db7) {
|
||||||
reg = tok - TOK_ASM_al;
|
reg = S->tccpp_tok - TOK_ASM_al;
|
||||||
op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
|
op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
|
||||||
op->reg = reg & 7;
|
op->reg = reg & 7;
|
||||||
if ((op->type & OP_REG) && op->reg == TREG_XAX)
|
if ((op->type & OP_REG) && op->reg == TREG_XAX)
|
||||||
@ -371,48 +371,48 @@ static void parse_operand(TCCState *s1, Operand *op)
|
|||||||
op->type |= OP_CL;
|
op->type |= OP_CL;
|
||||||
else if (op->type == OP_REG16 && op->reg == TREG_XDX)
|
else if (op->type == OP_REG16 && op->reg == TREG_XDX)
|
||||||
op->type |= OP_DX;
|
op->type |= OP_DX;
|
||||||
} else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
|
} else if (S->tccpp_tok >= TOK_ASM_dr0 && S->tccpp_tok <= TOK_ASM_dr7) {
|
||||||
op->type = OP_DB;
|
op->type = OP_DB;
|
||||||
op->reg = tok - TOK_ASM_dr0;
|
op->reg = S->tccpp_tok - TOK_ASM_dr0;
|
||||||
} else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
|
} else if (S->tccpp_tok >= TOK_ASM_es && S->tccpp_tok <= TOK_ASM_gs) {
|
||||||
op->type = OP_SEG;
|
op->type = OP_SEG;
|
||||||
op->reg = tok - TOK_ASM_es;
|
op->reg = S->tccpp_tok - TOK_ASM_es;
|
||||||
} else if (tok == TOK_ASM_st) {
|
} else if (S->tccpp_tok == TOK_ASM_st) {
|
||||||
op->type = OP_ST;
|
op->type = OP_ST;
|
||||||
op->reg = 0;
|
op->reg = 0;
|
||||||
next();
|
next(S);
|
||||||
if (tok == '(') {
|
if (S->tccpp_tok == '(') {
|
||||||
next();
|
next(S);
|
||||||
if (tok != TOK_PPNUM)
|
if (S->tccpp_tok != TOK_PPNUM)
|
||||||
goto reg_error;
|
goto reg_error;
|
||||||
p = tokc.str.data;
|
p = S->tccpp_tokc.str.data;
|
||||||
reg = p[0] - '0';
|
reg = p[0] - '0';
|
||||||
if ((unsigned)reg >= 8 || p[1] != '\0')
|
if ((unsigned)reg >= 8 || p[1] != '\0')
|
||||||
goto reg_error;
|
goto reg_error;
|
||||||
op->reg = reg;
|
op->reg = reg;
|
||||||
next();
|
next(S);
|
||||||
skip(')');
|
skip(S, ')');
|
||||||
}
|
}
|
||||||
if (op->reg == 0)
|
if (op->reg == 0)
|
||||||
op->type |= OP_ST0;
|
op->type |= OP_ST0;
|
||||||
goto no_skip;
|
goto no_skip;
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
} else if (tok >= TOK_ASM_spl && tok <= TOK_ASM_dil) {
|
} else if (S->tccpp_tok >= TOK_ASM_spl && S->tccpp_tok <= TOK_ASM_dil) {
|
||||||
op->type = OP_REG8 | OP_REG8_LOW;
|
op->type = OP_REG8 | OP_REG8_LOW;
|
||||||
op->reg = 4 + tok - TOK_ASM_spl;
|
op->reg = 4 + S->tccpp_tok - TOK_ASM_spl;
|
||||||
} else if ((op->reg = asm_parse_numeric_reg(tok, &op->type)) >= 0) {
|
} else if ((op->reg = asm_parse_numeric_reg(S, S->tccpp_tok, &op->type)) >= 0) {
|
||||||
;
|
;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
reg_error:
|
reg_error:
|
||||||
tcc_error("unknown register %%%s", get_tok_str(tok, &tokc));
|
tcc_error(S, "unknown register %%%s", get_tok_str(S, S->tccpp_tok, &S->tccpp_tokc));
|
||||||
}
|
}
|
||||||
next();
|
next(S);
|
||||||
no_skip: ;
|
no_skip: ;
|
||||||
} else if (tok == '$') {
|
} else if (S->tccpp_tok == '$') {
|
||||||
/* constant value */
|
/* constant value */
|
||||||
next();
|
next(S);
|
||||||
asm_expr(s1, &e);
|
asm_expr(S, &e);
|
||||||
op->type = OP_IM32;
|
op->type = OP_IM32;
|
||||||
op->e = e;
|
op->e = e;
|
||||||
if (!op->e.sym) {
|
if (!op->e.sym) {
|
||||||
@ -433,45 +433,45 @@ static void parse_operand(TCCState *s1, Operand *op)
|
|||||||
op->reg = -1;
|
op->reg = -1;
|
||||||
op->reg2 = -1;
|
op->reg2 = -1;
|
||||||
op->shift = 0;
|
op->shift = 0;
|
||||||
if (tok != '(') {
|
if (S->tccpp_tok != '(') {
|
||||||
asm_expr(s1, &e);
|
asm_expr(S, &e);
|
||||||
op->e = e;
|
op->e = e;
|
||||||
} else {
|
} else {
|
||||||
next();
|
next(S);
|
||||||
if (tok == '%') {
|
if (S->tccpp_tok == '%') {
|
||||||
unget_tok('(');
|
unget_tok(S, '(');
|
||||||
op->e.v = 0;
|
op->e.v = 0;
|
||||||
op->e.sym = NULL;
|
op->e.sym = NULL;
|
||||||
} else {
|
} else {
|
||||||
/* bracketed offset expression */
|
/* bracketed offset expression */
|
||||||
asm_expr(s1, &e);
|
asm_expr(S, &e);
|
||||||
if (tok != ')')
|
if (S->tccpp_tok != ')')
|
||||||
expect(")");
|
expect(S, ")");
|
||||||
next();
|
next(S);
|
||||||
op->e.v = e.v;
|
op->e.v = e.v;
|
||||||
op->e.sym = e.sym;
|
op->e.sym = e.sym;
|
||||||
}
|
}
|
||||||
op->e.pcrel = 0;
|
op->e.pcrel = 0;
|
||||||
}
|
}
|
||||||
if (tok == '(') {
|
if (S->tccpp_tok == '(') {
|
||||||
unsigned int type = 0;
|
unsigned int type = 0;
|
||||||
next();
|
next(S);
|
||||||
if (tok != ',') {
|
if (S->tccpp_tok != ',') {
|
||||||
op->reg = asm_parse_reg(&type);
|
op->reg = asm_parse_reg(S, &type);
|
||||||
}
|
}
|
||||||
if (tok == ',') {
|
if (S->tccpp_tok == ',') {
|
||||||
next();
|
next(S);
|
||||||
if (tok != ',') {
|
if (S->tccpp_tok != ',') {
|
||||||
op->reg2 = asm_parse_reg(&type);
|
op->reg2 = asm_parse_reg(S, &type);
|
||||||
}
|
}
|
||||||
if (tok == ',') {
|
if (S->tccpp_tok == ',') {
|
||||||
next();
|
next(S);
|
||||||
op->shift = get_reg_shift(s1);
|
op->shift = get_reg_shift(S);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type & OP_REG32)
|
if (type & OP_REG32)
|
||||||
op->type |= OP_EA32;
|
op->type |= OP_EA32;
|
||||||
skip(')');
|
skip(S, ')');
|
||||||
}
|
}
|
||||||
if (op->reg == -1 && op->reg2 == -1)
|
if (op->reg == -1 && op->reg2 == -1)
|
||||||
op->type |= OP_ADDR;
|
op->type |= OP_ADDR;
|
||||||
@ -480,65 +480,65 @@ static void parse_operand(TCCState *s1, Operand *op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: unify with C code output ? */
|
/* XXX: unify with C code output ? */
|
||||||
ST_FUNC void gen_expr32(ExprValue *pe)
|
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
|
||||||
{
|
{
|
||||||
if (pe->pcrel)
|
if (pe->pcrel)
|
||||||
/* If PC-relative, always set VT_SYM, even without symbol,
|
/* If PC-relative, always set VT_SYM, even without symbol,
|
||||||
so as to force a relocation to be emitted. */
|
so as to force a relocation to be emitted. */
|
||||||
gen_addrpc32(VT_SYM, pe->sym, pe->v);
|
gen_addrpc32(S, VT_SYM, pe->sym, pe->v);
|
||||||
else
|
else
|
||||||
gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
gen_addr32(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
ST_FUNC void gen_expr64(ExprValue *pe)
|
ST_FUNC void gen_expr64(TCCState* S, ExprValue *pe)
|
||||||
{
|
{
|
||||||
gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
gen_addr64(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* XXX: unify with C code output ? */
|
/* XXX: unify with C code output ? */
|
||||||
static void gen_disp32(ExprValue *pe)
|
static void gen_disp32(TCCState* S, ExprValue *pe)
|
||||||
{
|
{
|
||||||
Sym *sym = pe->sym;
|
Sym *sym = pe->sym;
|
||||||
ElfSym *esym = elfsym(sym);
|
ElfSym *esym = elfsym(S, sym);
|
||||||
if (esym && esym->st_shndx == cur_text_section->sh_num) {
|
if (esym && esym->st_shndx == cur_text_section->sh_num) {
|
||||||
/* same section: we can output an absolute value. Note
|
/* same section: we can output an absolute value. Note
|
||||||
that the TCC compiler behaves differently here because
|
that the TCC compiler behaves differently here because
|
||||||
it always outputs a relocation to ease (future) code
|
it always outputs a relocation to ease (future) code
|
||||||
elimination in the linker */
|
elimination in the linker */
|
||||||
gen_le32(pe->v + esym->st_value - ind - 4);
|
gen_le32(S, pe->v + esym->st_value - S->tccgen_ind - 4);
|
||||||
} else {
|
} else {
|
||||||
if (sym && sym->type.t == VT_VOID) {
|
if (sym && sym->type.t == VT_VOID) {
|
||||||
sym->type.t = VT_FUNC;
|
sym->type.t = VT_FUNC;
|
||||||
sym->type.ref = NULL;
|
sym->type.ref = NULL;
|
||||||
}
|
}
|
||||||
gen_addrpc32(VT_SYM, sym, pe->v);
|
gen_addrpc32(S, VT_SYM, sym, pe->v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate the modrm operand */
|
/* generate the modrm operand */
|
||||||
static inline int asm_modrm(int reg, Operand *op)
|
static inline int asm_modrm(TCCState* S, int reg, Operand *op)
|
||||||
{
|
{
|
||||||
int mod, reg1, reg2, sib_reg1;
|
int mod, reg1, reg2, sib_reg1;
|
||||||
|
|
||||||
if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
|
if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
|
||||||
g(0xc0 + (reg << 3) + op->reg);
|
g(S, 0xc0 + (reg << 3) + op->reg);
|
||||||
} else if (op->reg == -1 && op->reg2 == -1) {
|
} else if (op->reg == -1 && op->reg2 == -1) {
|
||||||
/* displacement only */
|
/* displacement only */
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
g(0x04 + (reg << 3));
|
g(S, 0x04 + (reg << 3));
|
||||||
g(0x25);
|
g(S, 0x25);
|
||||||
#else
|
#else
|
||||||
g(0x05 + (reg << 3));
|
g(S, 0x05 + (reg << 3));
|
||||||
#endif
|
#endif
|
||||||
gen_expr32(&op->e);
|
gen_expr32(S, &op->e);
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
} else if (op->reg == -2) {
|
} else if (op->reg == -2) {
|
||||||
ExprValue *pe = &op->e;
|
ExprValue *pe = &op->e;
|
||||||
g(0x05 + (reg << 3));
|
g(S, 0x05 + (reg << 3));
|
||||||
gen_addrpc32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
gen_addrpc32(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||||
return ind;
|
return S->tccgen_ind;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
sib_reg1 = op->reg;
|
sib_reg1 = op->reg;
|
||||||
@ -557,19 +557,19 @@ static inline int asm_modrm(int reg, Operand *op)
|
|||||||
reg1 = op->reg;
|
reg1 = op->reg;
|
||||||
if (op->reg2 != -1)
|
if (op->reg2 != -1)
|
||||||
reg1 = 4;
|
reg1 = 4;
|
||||||
g(mod + (reg << 3) + reg1);
|
g(S, mod + (reg << 3) + reg1);
|
||||||
if (reg1 == 4) {
|
if (reg1 == 4) {
|
||||||
/* add sib byte */
|
/* add sib byte */
|
||||||
reg2 = op->reg2;
|
reg2 = op->reg2;
|
||||||
if (reg2 == -1)
|
if (reg2 == -1)
|
||||||
reg2 = 4; /* indicate no index */
|
reg2 = 4; /* indicate no index */
|
||||||
g((op->shift << 6) + (reg2 << 3) + sib_reg1);
|
g(S, (op->shift << 6) + (reg2 << 3) + sib_reg1);
|
||||||
}
|
}
|
||||||
/* add offset */
|
/* add offset */
|
||||||
if (mod == 0x40) {
|
if (mod == 0x40) {
|
||||||
g(op->e.v);
|
g(S, op->e.v);
|
||||||
} else if (mod == 0x80 || op->reg == -1) {
|
} else if (mod == 0x80 || op->reg == -1) {
|
||||||
gen_expr32(&op->e);
|
gen_expr32(S, &op->e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -581,7 +581,7 @@ static inline int asm_modrm(int reg, Operand *op)
|
|||||||
#define REX_X 0x42
|
#define REX_X 0x42
|
||||||
#define REX_B 0x41
|
#define REX_B 0x41
|
||||||
|
|
||||||
static void asm_rex(int width64, Operand *ops, int nb_ops, int *op_type,
|
static void asm_rex(TCCState* S, int width64, Operand *ops, int nb_ops, int *op_type,
|
||||||
int regi, int rmi)
|
int regi, int rmi)
|
||||||
{
|
{
|
||||||
unsigned char rex = width64 ? 0x48 : 0;
|
unsigned char rex = width64 ? 0x48 : 0;
|
||||||
@ -631,9 +631,9 @@ static void asm_rex(int width64, Operand *ops, int nb_ops, int *op_type,
|
|||||||
}
|
}
|
||||||
if (rex) {
|
if (rex) {
|
||||||
if (saw_high_8bit)
|
if (saw_high_8bit)
|
||||||
tcc_error("can't encode register %%%ch when REX prefix is required",
|
tcc_error(S, "can't encode register %%%ch when REX prefix is required",
|
||||||
"acdb"[saw_high_8bit-4]);
|
"acdb"[saw_high_8bit-4]);
|
||||||
g(rex);
|
g(S, rex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -679,7 +679,7 @@ static void maybe_print_stats (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
ST_FUNC void asm_opcode(TCCState *S, int opcode)
|
||||||
{
|
{
|
||||||
const ASMInstr *pa;
|
const ASMInstr *pa;
|
||||||
int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc;
|
int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc;
|
||||||
@ -697,7 +697,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
|||||||
/* force synthetic ';' after prefix instruction, so we can handle */
|
/* force synthetic ';' after prefix instruction, so we can handle */
|
||||||
/* one-line things like "rep stosb" instead of only "rep\nstosb" */
|
/* one-line things like "rep stosb" instead of only "rep\nstosb" */
|
||||||
if (opcode >= TOK_ASM_wait && opcode <= TOK_ASM_repnz)
|
if (opcode >= TOK_ASM_wait && opcode <= TOK_ASM_repnz)
|
||||||
unget_tok(';');
|
unget_tok(S, ';');
|
||||||
|
|
||||||
/* get operands */
|
/* get operands */
|
||||||
pop = ops;
|
pop = ops;
|
||||||
@ -705,27 +705,27 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
|||||||
seg_prefix = 0;
|
seg_prefix = 0;
|
||||||
alltypes = 0;
|
alltypes = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (tok == ';' || tok == TOK_LINEFEED)
|
if (S->tccpp_tok == ';' || S->tccpp_tok == TOK_LINEFEED)
|
||||||
break;
|
break;
|
||||||
if (nb_ops >= MAX_OPERANDS) {
|
if (nb_ops >= MAX_OPERANDS) {
|
||||||
tcc_error("incorrect number of operands");
|
tcc_error(S, "incorrect number of operands");
|
||||||
}
|
}
|
||||||
parse_operand(s1, pop);
|
parse_operand(S, pop);
|
||||||
if (tok == ':') {
|
if (S->tccpp_tok == ':') {
|
||||||
if (pop->type != OP_SEG || seg_prefix)
|
if (pop->type != OP_SEG || seg_prefix)
|
||||||
tcc_error("incorrect prefix");
|
tcc_error(S, "incorrect prefix");
|
||||||
seg_prefix = segment_prefixes[pop->reg];
|
seg_prefix = segment_prefixes[pop->reg];
|
||||||
next();
|
next(S);
|
||||||
parse_operand(s1, pop);
|
parse_operand(S, pop);
|
||||||
if (!(pop->type & OP_EA)) {
|
if (!(pop->type & OP_EA)) {
|
||||||
tcc_error("segment prefix must be followed by memory reference");
|
tcc_error(S, "segment prefix must be followed by memory reference");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pop++;
|
pop++;
|
||||||
nb_ops++;
|
nb_ops++;
|
||||||
if (tok != ',')
|
if (S->tccpp_tok != ',')
|
||||||
break;
|
break;
|
||||||
next();
|
next(S);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = 0; /* avoid warning */
|
s = 0; /* avoid warning */
|
||||||
@ -842,23 +842,23 @@ again:
|
|||||||
int b;
|
int b;
|
||||||
b = op0_codes[opcode - TOK_ASM_first];
|
b = op0_codes[opcode - TOK_ASM_first];
|
||||||
if (b & 0xff00)
|
if (b & 0xff00)
|
||||||
g(b >> 8);
|
g(S, b >> 8);
|
||||||
g(b);
|
g(S, b);
|
||||||
return;
|
return;
|
||||||
} else if (opcode <= TOK_ASM_alllast) {
|
} else if (opcode <= TOK_ASM_alllast) {
|
||||||
tcc_error("bad operand with opcode '%s'",
|
tcc_error(S, "bad operand with opcode '%s'",
|
||||||
get_tok_str(opcode, NULL));
|
get_tok_str(S, opcode, NULL));
|
||||||
} else {
|
} else {
|
||||||
/* Special case for cmovcc, we accept size suffixes but ignore
|
/* Special case for cmovcc, we accept size suffixes but ignore
|
||||||
them, but we don't want them to blow up our tables. */
|
them, but we don't want them to blow up our tables. */
|
||||||
TokenSym *ts = table_ident[opcode - TOK_IDENT];
|
TokenSym *ts = S->tccpp_table_ident[opcode - TOK_IDENT];
|
||||||
if (ts->len >= 6
|
if (ts->len >= 6
|
||||||
&& strchr("wlq", ts->str[ts->len-1])
|
&& strchr("wlq", ts->str[ts->len-1])
|
||||||
&& !memcmp(ts->str, "cmov", 4)) {
|
&& !memcmp(ts->str, "cmov", 4)) {
|
||||||
opcode = tok_alloc(ts->str, ts->len-1)->tok;
|
opcode = tok_alloc(S, ts->str, ts->len-1)->tok;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
tcc_error("unknown opcode '%s'", ts->str);
|
tcc_error(S, "unknown opcode '%s'", ts->str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
|
/* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
|
||||||
@ -886,7 +886,7 @@ again:
|
|||||||
(ops[0].type & OP_EA))
|
(ops[0].type & OP_EA))
|
||||||
s = NBWLX - 2;
|
s = NBWLX - 2;
|
||||||
else
|
else
|
||||||
tcc_error("cannot infer opcode suffix");
|
tcc_error(S, "cannot infer opcode suffix");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -894,7 +894,7 @@ again:
|
|||||||
/* Generate addr32 prefix if needed */
|
/* Generate addr32 prefix if needed */
|
||||||
for(i = 0; i < nb_ops; i++) {
|
for(i = 0; i < nb_ops; i++) {
|
||||||
if (ops[i].type & OP_EA32) {
|
if (ops[i].type & OP_EA32) {
|
||||||
g(0x67);
|
g(S, 0x67);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -913,7 +913,7 @@ again:
|
|||||||
p66 = 1;
|
p66 = 1;
|
||||||
}
|
}
|
||||||
if (p66)
|
if (p66)
|
||||||
g(0x66);
|
g(S, 0x66);
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
rex64 = 0;
|
rex64 = 0;
|
||||||
if (pa->instr_type & OPC_48)
|
if (pa->instr_type & OPC_48)
|
||||||
@ -943,9 +943,9 @@ again:
|
|||||||
|
|
||||||
/* now generates the operation */
|
/* now generates the operation */
|
||||||
if (OPCT_IS(pa->instr_type, OPC_FWAIT))
|
if (OPCT_IS(pa->instr_type, OPC_FWAIT))
|
||||||
g(0x9b);
|
g(S, 0x9b);
|
||||||
if (seg_prefix)
|
if (seg_prefix)
|
||||||
g(seg_prefix);
|
g(S, seg_prefix);
|
||||||
|
|
||||||
v = pa->opcode;
|
v = pa->opcode;
|
||||||
if (pa->instr_type & OPC_0F)
|
if (pa->instr_type & OPC_0F)
|
||||||
@ -998,7 +998,7 @@ again:
|
|||||||
goto modrm_found;
|
goto modrm_found;
|
||||||
}
|
}
|
||||||
#ifdef ASM_DEBUG
|
#ifdef ASM_DEBUG
|
||||||
tcc_error("bad op table");
|
tcc_error(S, "bad op table");
|
||||||
#endif
|
#endif
|
||||||
modrm_found:
|
modrm_found:
|
||||||
modrm_index = i;
|
modrm_index = i;
|
||||||
@ -1014,7 +1014,7 @@ again:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
asm_rex (rex64, ops, nb_ops, op_type, modreg_index, modrm_index);
|
asm_rex (S, rex64, ops, nb_ops, op_type, modreg_index, modrm_index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (pa->instr_type & OPC_REG) {
|
if (pa->instr_type & OPC_REG) {
|
||||||
@ -1035,10 +1035,10 @@ again:
|
|||||||
int jmp_disp;
|
int jmp_disp;
|
||||||
|
|
||||||
/* see if we can really generate the jump with a byte offset */
|
/* see if we can really generate the jump with a byte offset */
|
||||||
esym = elfsym(ops[0].e.sym);
|
esym = elfsym(S, ops[0].e.sym);
|
||||||
if (!esym || esym->st_shndx != cur_text_section->sh_num)
|
if (!esym || esym->st_shndx != cur_text_section->sh_num)
|
||||||
goto no_short_jump;
|
goto no_short_jump;
|
||||||
jmp_disp = ops[0].e.v + esym->st_value - ind - 2 - (v >= 0xff);
|
jmp_disp = ops[0].e.v + esym->st_value - S->tccgen_ind - 2 - (v >= 0xff);
|
||||||
if (jmp_disp == (int8_t)jmp_disp) {
|
if (jmp_disp == (int8_t)jmp_disp) {
|
||||||
/* OK to generate jump */
|
/* OK to generate jump */
|
||||||
ops[0].e.sym = 0;
|
ops[0].e.sym = 0;
|
||||||
@ -1053,18 +1053,18 @@ again:
|
|||||||
else if (v == 0x70) /* jcc */
|
else if (v == 0x70) /* jcc */
|
||||||
v += 0x0f10;
|
v += 0x0f10;
|
||||||
else
|
else
|
||||||
tcc_error("invalid displacement");
|
tcc_error(S, "invalid displacement");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (OPCT_IS(pa->instr_type, OPC_TEST))
|
if (OPCT_IS(pa->instr_type, OPC_TEST))
|
||||||
v += test_bits[opcode - pa->sym];
|
v += test_bits[opcode - pa->sym];
|
||||||
op1 = v >> 16;
|
op1 = v >> 16;
|
||||||
if (op1)
|
if (op1)
|
||||||
g(op1);
|
g(S, op1);
|
||||||
op1 = (v >> 8) & 0xff;
|
op1 = (v >> 8) & 0xff;
|
||||||
if (op1)
|
if (op1)
|
||||||
g(op1);
|
g(S, op1);
|
||||||
g(v);
|
g(S, v);
|
||||||
|
|
||||||
if (OPCT_IS(pa->instr_type, OPC_SHIFT)) {
|
if (OPCT_IS(pa->instr_type, OPC_SHIFT)) {
|
||||||
reg = (opcode - pa->sym) / NBWLX;
|
reg = (opcode - pa->sym) / NBWLX;
|
||||||
@ -1084,7 +1084,7 @@ again:
|
|||||||
used instead of group */
|
used instead of group */
|
||||||
if (modreg_index >= 0)
|
if (modreg_index >= 0)
|
||||||
reg = ops[modreg_index].reg;
|
reg = ops[modreg_index].reg;
|
||||||
pc = asm_modrm(reg, &ops[modrm_index]);
|
pc = asm_modrm(S, reg, &ops[modrm_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* emit constants */
|
/* emit constants */
|
||||||
@ -1092,10 +1092,10 @@ again:
|
|||||||
if (!(pa->instr_type & OPC_0F)
|
if (!(pa->instr_type & OPC_0F)
|
||||||
&& (pa->opcode == 0x9a || pa->opcode == 0xea)) {
|
&& (pa->opcode == 0x9a || pa->opcode == 0xea)) {
|
||||||
/* ljmp or lcall kludge */
|
/* ljmp or lcall kludge */
|
||||||
gen_expr32(&ops[1].e);
|
gen_expr32(S, &ops[1].e);
|
||||||
if (ops[0].e.sym)
|
if (ops[0].e.sym)
|
||||||
tcc_error("cannot relocate");
|
tcc_error(S, "cannot relocate");
|
||||||
gen_le16(ops[0].e.v);
|
gen_le16(S, ops[0].e.v);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1116,32 +1116,32 @@ again:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((v & (OP_IM8 | OP_IM8S | OP_IM16)) && ops[i].e.sym)
|
if ((v & (OP_IM8 | OP_IM8S | OP_IM16)) && ops[i].e.sym)
|
||||||
tcc_error("cannot relocate");
|
tcc_error(S, "cannot relocate");
|
||||||
|
|
||||||
if (v & (OP_IM8 | OP_IM8S)) {
|
if (v & (OP_IM8 | OP_IM8S)) {
|
||||||
g(ops[i].e.v);
|
g(S, ops[i].e.v);
|
||||||
} else if (v & OP_IM16) {
|
} else if (v & OP_IM16) {
|
||||||
gen_le16(ops[i].e.v);
|
gen_le16(S, ops[i].e.v);
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
} else if (v & OP_IM64) {
|
} else if (v & OP_IM64) {
|
||||||
gen_expr64(&ops[i].e);
|
gen_expr64(S, &ops[i].e);
|
||||||
#endif
|
#endif
|
||||||
} else if (pa->op_type[i] == OPT_DISP || pa->op_type[i] == OPT_DISP8) {
|
} else if (pa->op_type[i] == OPT_DISP || pa->op_type[i] == OPT_DISP8) {
|
||||||
gen_disp32(&ops[i].e);
|
gen_disp32(S, &ops[i].e);
|
||||||
} else {
|
} else {
|
||||||
gen_expr32(&ops[i].e);
|
gen_expr32(S, &ops[i].e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* after immediate operands, adjust pc-relative address */
|
/* after immediate operands, adjust pc-relative address */
|
||||||
if (pc)
|
if (pc)
|
||||||
add32le(cur_text_section->data + pc - 4, pc - ind);
|
add32le(cur_text_section->data + pc - 4, pc - S->tccgen_ind);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the constraint priority (we allocate first the lowest
|
/* return the constraint priority (we allocate first the lowest
|
||||||
numbered constraints) */
|
numbered constraints) */
|
||||||
static inline int constraint_priority(const char *str)
|
static inline int constraint_priority(TCCState* S, const char *str)
|
||||||
{
|
{
|
||||||
int priority, c, pr;
|
int priority, c, pr;
|
||||||
|
|
||||||
@ -1182,7 +1182,7 @@ static inline int constraint_priority(const char *str)
|
|||||||
pr = 4;
|
pr = 4;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcc_error("unknown constraint '%c'", c);
|
tcc_error(S, "unknown constraint '%c'", c);
|
||||||
pr = 0;
|
pr = 0;
|
||||||
}
|
}
|
||||||
if (pr > priority)
|
if (pr > priority)
|
||||||
@ -1200,19 +1200,19 @@ static const char *skip_constraint_modifiers(const char *p)
|
|||||||
|
|
||||||
/* If T (a token) is of the form "%reg" returns the register
|
/* If T (a token) is of the form "%reg" returns the register
|
||||||
number and type, otherwise return -1. */
|
number and type, otherwise return -1. */
|
||||||
ST_FUNC int asm_parse_regvar (int t)
|
ST_FUNC int asm_parse_regvar (TCCState* S, int t)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
Operand op;
|
Operand op;
|
||||||
if (t < TOK_IDENT || (t & SYM_FIELD))
|
if (t < TOK_IDENT || (t & SYM_FIELD))
|
||||||
return -1;
|
return -1;
|
||||||
s = table_ident[t - TOK_IDENT]->str;
|
s = S->tccpp_table_ident[t - TOK_IDENT]->str;
|
||||||
if (s[0] != '%')
|
if (s[0] != '%')
|
||||||
return -1;
|
return -1;
|
||||||
t = tok_alloc_const(s + 1);
|
t = tok_alloc_const(S, s + 1);
|
||||||
unget_tok(t);
|
unget_tok(S, t);
|
||||||
unget_tok('%');
|
unget_tok(S, '%');
|
||||||
parse_operand(tcc_state, &op);
|
parse_operand(S, &op);
|
||||||
/* Accept only integer regs for now. */
|
/* Accept only integer regs for now. */
|
||||||
if (op.type & OP_REG)
|
if (op.type & OP_REG)
|
||||||
return op.reg;
|
return op.reg;
|
||||||
@ -1225,7 +1225,7 @@ ST_FUNC int asm_parse_regvar (int t)
|
|||||||
|
|
||||||
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
|
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
|
||||||
|
|
||||||
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
|
||||||
int nb_operands, int nb_outputs,
|
int nb_operands, int nb_outputs,
|
||||||
const uint8_t *clobber_regs,
|
const uint8_t *clobber_regs,
|
||||||
int *pout_reg)
|
int *pout_reg)
|
||||||
@ -1253,13 +1253,13 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
str = skip_constraint_modifiers(str);
|
str = skip_constraint_modifiers(str);
|
||||||
if (isnum(*str) || *str == '[') {
|
if (isnum(*str) || *str == '[') {
|
||||||
/* this is a reference to another constraint */
|
/* this is a reference to another constraint */
|
||||||
k = find_constraint(operands, nb_operands, str, NULL);
|
k = find_constraint(S, operands, nb_operands, str, NULL);
|
||||||
if ((unsigned)k >= i || i < nb_outputs)
|
if ((unsigned)k >= i || i < nb_outputs)
|
||||||
tcc_error("invalid reference in constraint %d ('%s')",
|
tcc_error(S, "invalid reference in constraint %d ('%s')",
|
||||||
i, str);
|
i, str);
|
||||||
op->ref_index = k;
|
op->ref_index = k;
|
||||||
if (operands[k].input_index >= 0)
|
if (operands[k].input_index >= 0)
|
||||||
tcc_error("cannot reference twice the same operand");
|
tcc_error(S, "cannot reference twice the same operand");
|
||||||
operands[k].input_index = i;
|
operands[k].input_index = i;
|
||||||
op->priority = 5;
|
op->priority = 5;
|
||||||
} else if ((op->vt->r & VT_VALMASK) == VT_LOCAL
|
} else if ((op->vt->r & VT_VALMASK) == VT_LOCAL
|
||||||
@ -1268,7 +1268,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
op->priority = 1;
|
op->priority = 1;
|
||||||
op->reg = reg;
|
op->reg = reg;
|
||||||
} else {
|
} else {
|
||||||
op->priority = constraint_priority(str);
|
op->priority = constraint_priority(S, str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1316,7 +1316,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
}
|
}
|
||||||
if (op->reg >= 0) {
|
if (op->reg >= 0) {
|
||||||
if (is_reg_allocated(op->reg))
|
if (is_reg_allocated(op->reg))
|
||||||
tcc_error("asm regvar requests register that's taken already");
|
tcc_error(S, "asm regvar requests register that's taken already");
|
||||||
reg = op->reg;
|
reg = op->reg;
|
||||||
goto reg_found;
|
goto reg_found;
|
||||||
}
|
}
|
||||||
@ -1330,7 +1330,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
/* FALL THRU */
|
/* FALL THRU */
|
||||||
case '&':
|
case '&':
|
||||||
if (j >= nb_outputs)
|
if (j >= nb_outputs)
|
||||||
tcc_error("'%c' modifier can only be applied to outputs", c);
|
tcc_error(S, "'%c' modifier can only be applied to outputs", c);
|
||||||
reg_mask = REG_IN_MASK | REG_OUT_MASK;
|
reg_mask = REG_IN_MASK | REG_OUT_MASK;
|
||||||
goto try_next;
|
goto try_next;
|
||||||
case 'A':
|
case 'A':
|
||||||
@ -1424,7 +1424,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcc_error("asm constraint %d ('%s') could not be satisfied",
|
tcc_error(S, "asm constraint %d ('%s') could not be satisfied",
|
||||||
j, op->constraint);
|
j, op->constraint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1447,7 +1447,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
if (!(regs_allocated[reg] & REG_OUT_MASK))
|
if (!(regs_allocated[reg] & REG_OUT_MASK))
|
||||||
goto reg_found2;
|
goto reg_found2;
|
||||||
}
|
}
|
||||||
tcc_error("could not find free output register for reloading");
|
tcc_error(S, "could not find free output register for reloading");
|
||||||
reg_found2:
|
reg_found2:
|
||||||
*pout_reg = reg;
|
*pout_reg = reg;
|
||||||
break;
|
break;
|
||||||
@ -1461,7 +1461,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
op = &operands[j];
|
op = &operands[j];
|
||||||
printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",
|
printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",
|
||||||
j,
|
j,
|
||||||
op->id ? get_tok_str(op->id, NULL) : "",
|
op->id ? get_tok_str(S, op->id, NULL) : "",
|
||||||
op->constraint,
|
op->constraint,
|
||||||
op->vt->r,
|
op->vt->r,
|
||||||
op->reg);
|
op->reg);
|
||||||
@ -1471,7 +1471,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void subst_asm_operand(CString *add_str,
|
ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str,
|
||||||
SValue *sv, int modifier)
|
SValue *sv, int modifier)
|
||||||
{
|
{
|
||||||
int r, reg, size, val;
|
int r, reg, size, val;
|
||||||
@ -1481,33 +1481,33 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
|||||||
if ((r & VT_VALMASK) == VT_CONST) {
|
if ((r & VT_VALMASK) == VT_CONST) {
|
||||||
if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n' &&
|
if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n' &&
|
||||||
modifier != 'P')
|
modifier != 'P')
|
||||||
cstr_ccat(add_str, '$');
|
cstr_ccat(S, add_str, '$');
|
||||||
if (r & VT_SYM) {
|
if (r & VT_SYM) {
|
||||||
const char *name = get_tok_str(sv->sym->v, NULL);
|
const char *name = get_tok_str(S, sv->sym->v, NULL);
|
||||||
if (sv->sym->v >= SYM_FIRST_ANOM) {
|
if (sv->sym->v >= SYM_FIRST_ANOM) {
|
||||||
/* In case of anonymous symbols ("L.42", used
|
/* In case of anonymous symbols ("L.42", used
|
||||||
for static data labels) we can't find them
|
for static data labels) we can't find them
|
||||||
in the C symbol table when later looking up
|
in the C symbol table when later looking up
|
||||||
this name. So enter them now into the asm label
|
this name. So enter them now into the asm label
|
||||||
list when we still know the symbol. */
|
list when we still know the symbol. */
|
||||||
get_asm_sym(tok_alloc_const(name), sv->sym);
|
get_asm_sym(S, tok_alloc_const(S, name), sv->sym);
|
||||||
}
|
}
|
||||||
if (tcc_state->leading_underscore)
|
if (S->leading_underscore)
|
||||||
cstr_ccat(add_str, '_');
|
cstr_ccat(S, add_str, '_');
|
||||||
cstr_cat(add_str, name, -1);
|
cstr_cat(S, add_str, name, -1);
|
||||||
if ((uint32_t)sv->c.i == 0)
|
if ((uint32_t)sv->c.i == 0)
|
||||||
goto no_offset;
|
goto no_offset;
|
||||||
cstr_ccat(add_str, '+');
|
cstr_ccat(S, add_str, '+');
|
||||||
}
|
}
|
||||||
val = sv->c.i;
|
val = sv->c.i;
|
||||||
if (modifier == 'n')
|
if (modifier == 'n')
|
||||||
val = -val;
|
val = -val;
|
||||||
snprintf(buf, sizeof(buf), "%d", (int)sv->c.i);
|
snprintf(buf, sizeof(buf), "%d", (int)sv->c.i);
|
||||||
cstr_cat(add_str, buf, -1);
|
cstr_cat(S, add_str, buf, -1);
|
||||||
no_offset:;
|
no_offset:;
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
if (r & VT_LVAL)
|
if (r & VT_LVAL)
|
||||||
cstr_cat(add_str, "(%rip)", -1);
|
cstr_cat(S, add_str, "(%rip)", -1);
|
||||||
#endif
|
#endif
|
||||||
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
@ -1515,24 +1515,24 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
|||||||
#else
|
#else
|
||||||
snprintf(buf, sizeof(buf), "%d(%%ebp)", (int)sv->c.i);
|
snprintf(buf, sizeof(buf), "%d(%%ebp)", (int)sv->c.i);
|
||||||
#endif
|
#endif
|
||||||
cstr_cat(add_str, buf, -1);
|
cstr_cat(S, add_str, buf, -1);
|
||||||
} else if (r & VT_LVAL) {
|
} else if (r & VT_LVAL) {
|
||||||
reg = r & VT_VALMASK;
|
reg = r & VT_VALMASK;
|
||||||
if (reg >= VT_CONST)
|
if (reg >= VT_CONST)
|
||||||
tcc_internal_error("");
|
tcc_internal_error(S, "");
|
||||||
snprintf(buf, sizeof(buf), "(%%%s)",
|
snprintf(buf, sizeof(buf), "(%%%s)",
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
get_tok_str(TOK_ASM_rax + reg, NULL)
|
get_tok_str(S, TOK_ASM_rax + reg, NULL)
|
||||||
#else
|
#else
|
||||||
get_tok_str(TOK_ASM_eax + reg, NULL)
|
get_tok_str(S, TOK_ASM_eax + reg, NULL)
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
cstr_cat(add_str, buf, -1);
|
cstr_cat(S, add_str, buf, -1);
|
||||||
} else {
|
} else {
|
||||||
/* register case */
|
/* register case */
|
||||||
reg = r & VT_VALMASK;
|
reg = r & VT_VALMASK;
|
||||||
if (reg >= VT_CONST)
|
if (reg >= VT_CONST)
|
||||||
tcc_internal_error("");
|
tcc_internal_error(S, "");
|
||||||
|
|
||||||
/* choose register operand size */
|
/* choose register operand size */
|
||||||
if ((sv->type.t & VT_BTYPE) == VT_BYTE ||
|
if ((sv->type.t & VT_BTYPE) == VT_BYTE ||
|
||||||
@ -1552,11 +1552,11 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
|||||||
|
|
||||||
if (modifier == 'b') {
|
if (modifier == 'b') {
|
||||||
if (reg >= 4)
|
if (reg >= 4)
|
||||||
tcc_error("cannot use byte register");
|
tcc_error(S, "cannot use byte register");
|
||||||
size = 1;
|
size = 1;
|
||||||
} else if (modifier == 'h') {
|
} else if (modifier == 'h') {
|
||||||
if (reg >= 4)
|
if (reg >= 4)
|
||||||
tcc_error("cannot use byte register");
|
tcc_error(S, "cannot use byte register");
|
||||||
size = -1;
|
size = -1;
|
||||||
} else if (modifier == 'w') {
|
} else if (modifier == 'w') {
|
||||||
size = 2;
|
size = 2;
|
||||||
@ -1587,13 +1587,13 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
|
snprintf(buf, sizeof(buf), "%%%s", get_tok_str(S, reg, NULL));
|
||||||
cstr_cat(add_str, buf, -1);
|
cstr_cat(S, add_str, buf, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate prolog and epilog code for asm statement */
|
/* generate prolog and epilog code for asm statement */
|
||||||
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands,
|
||||||
int nb_outputs, int is_output,
|
int nb_outputs, int is_output,
|
||||||
uint8_t *clobber_regs,
|
uint8_t *clobber_regs,
|
||||||
int out_reg)
|
int out_reg)
|
||||||
@ -1627,8 +1627,8 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
|||||||
reg = reg_saved[i];
|
reg = reg_saved[i];
|
||||||
if (regs_allocated[reg]) {
|
if (regs_allocated[reg]) {
|
||||||
if (reg >= 8)
|
if (reg >= 8)
|
||||||
g(0x41), reg-=8;
|
g(S, 0x41), reg-=8;
|
||||||
g(0x50 + reg);
|
g(S, 0x50 + reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1644,15 +1644,15 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
|||||||
sv = *op->vt;
|
sv = *op->vt;
|
||||||
sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
|
sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
|
||||||
sv.type.t = VT_PTR;
|
sv.type.t = VT_PTR;
|
||||||
load(op->reg, &sv);
|
load(S, op->reg, &sv);
|
||||||
} else if (i >= nb_outputs || op->is_rw) {
|
} else if (i >= nb_outputs || op->is_rw) {
|
||||||
/* load value in register */
|
/* load value in register */
|
||||||
load(op->reg, op->vt);
|
load(S, op->reg, op->vt);
|
||||||
if (op->is_llong) {
|
if (op->is_llong) {
|
||||||
SValue sv;
|
SValue sv;
|
||||||
sv = *op->vt;
|
sv = *op->vt;
|
||||||
sv.c.i += 4;
|
sv.c.i += 4;
|
||||||
load(TREG_XDX, &sv);
|
load(S, TREG_XDX, &sv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1668,19 +1668,19 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
|||||||
sv = *op->vt;
|
sv = *op->vt;
|
||||||
sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
|
sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
|
||||||
sv.type.t = VT_PTR;
|
sv.type.t = VT_PTR;
|
||||||
load(out_reg, &sv);
|
load(S, out_reg, &sv);
|
||||||
|
|
||||||
sv = *op->vt;
|
sv = *op->vt;
|
||||||
sv.r = (sv.r & ~VT_VALMASK) | out_reg;
|
sv.r = (sv.r & ~VT_VALMASK) | out_reg;
|
||||||
store(op->reg, &sv);
|
store(S, op->reg, &sv);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
store(op->reg, op->vt);
|
store(S, op->reg, op->vt);
|
||||||
if (op->is_llong) {
|
if (op->is_llong) {
|
||||||
SValue sv;
|
SValue sv;
|
||||||
sv = *op->vt;
|
sv = *op->vt;
|
||||||
sv.c.i += 4;
|
sv.c.i += 4;
|
||||||
store(TREG_XDX, &sv);
|
store(S, TREG_XDX, &sv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1690,14 +1690,14 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
|||||||
reg = reg_saved[i];
|
reg = reg_saved[i];
|
||||||
if (regs_allocated[reg]) {
|
if (regs_allocated[reg]) {
|
||||||
if (reg >= 8)
|
if (reg >= 8)
|
||||||
g(0x41), reg-=8;
|
g(S, 0x41), reg-=8;
|
||||||
g(0x58 + reg);
|
g(S, 0x58 + reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str)
|
||||||
{
|
{
|
||||||
int reg;
|
int reg;
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
@ -1708,7 +1708,7 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
|||||||
!strcmp(str, "cc") ||
|
!strcmp(str, "cc") ||
|
||||||
!strcmp(str, "flags"))
|
!strcmp(str, "flags"))
|
||||||
return;
|
return;
|
||||||
reg = tok_alloc_const(str);
|
reg = tok_alloc_const(S, str);
|
||||||
if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
|
if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
|
||||||
reg -= TOK_ASM_eax;
|
reg -= TOK_ASM_eax;
|
||||||
} else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
|
} else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
|
||||||
@ -1716,11 +1716,11 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
|||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
} else if (reg >= TOK_ASM_rax && reg <= TOK_ASM_rdi) {
|
} else if (reg >= TOK_ASM_rax && reg <= TOK_ASM_rdi) {
|
||||||
reg -= TOK_ASM_rax;
|
reg -= TOK_ASM_rax;
|
||||||
} else if ((reg = asm_parse_numeric_reg(reg, &type)) >= 0) {
|
} else if ((reg = asm_parse_numeric_reg(S, reg, &type)) >= 0) {
|
||||||
;
|
;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
tcc_error("invalid clobber register '%s'", str);
|
tcc_error(S, "invalid clobber register '%s'", str);
|
||||||
}
|
}
|
||||||
clobber_regs[reg] = 1;
|
clobber_regs[reg] = 1;
|
||||||
}
|
}
|
||||||
|
733
i386-gen.c
733
i386-gen.c
File diff suppressed because it is too large
Load Diff
68
i386-link.c
68
i386-link.c
@ -91,15 +91,15 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
Section *plt = s1->plt;
|
Section *plt = S->plt;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
int modrm;
|
int modrm;
|
||||||
unsigned plt_offset, relofs;
|
unsigned plt_offset, relofs;
|
||||||
|
|
||||||
/* on i386 if we build a DLL, we add a %ebx offset */
|
/* on i386 if we build a DLL, we add a %ebx offset */
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
if (S->output_type == TCC_OUTPUT_DLL)
|
||||||
modrm = 0xa3;
|
modrm = 0xa3;
|
||||||
else
|
else
|
||||||
modrm = 0x25;
|
modrm = 0x25;
|
||||||
@ -108,7 +108,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
|
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
|
||||||
(GOT + 2 * PTR_SIZE) */
|
(GOT + 2 * PTR_SIZE) */
|
||||||
if (plt->data_offset == 0) {
|
if (plt->data_offset == 0) {
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(S, plt, 16);
|
||||||
p[0] = 0xff; /* pushl got + PTR_SIZE */
|
p[0] = 0xff; /* pushl got + PTR_SIZE */
|
||||||
p[1] = modrm + 0x10;
|
p[1] = modrm + 0x10;
|
||||||
write32le(p + 2, PTR_SIZE);
|
write32le(p + 2, PTR_SIZE);
|
||||||
@ -121,10 +121,10 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
/* The PLT slot refers to the relocation entry it needs via offset.
|
/* The PLT slot refers to the relocation entry it needs via offset.
|
||||||
The reloc entry is created below, so its offset is the current
|
The reloc entry is created below, so its offset is the current
|
||||||
data_offset */
|
data_offset */
|
||||||
relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
|
relofs = S->plt->reloc ? S->plt->reloc->data_offset : 0;
|
||||||
|
|
||||||
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(S, plt, 16);
|
||||||
p[0] = 0xff; /* jmp *(got + x) */
|
p[0] = 0xff; /* jmp *(got + x) */
|
||||||
p[1] = modrm;
|
p[1] = modrm;
|
||||||
write32le(p + 2, got_offset);
|
write32le(p + 2, got_offset);
|
||||||
@ -137,31 +137,31 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
|
|
||||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||||
address for PLT and GOT are known (see fill_program_header) */
|
address for PLT and GOT are known (see fill_program_header) */
|
||||||
ST_FUNC void relocate_plt(TCCState *s1)
|
ST_FUNC void relocate_plt(TCCState *S)
|
||||||
{
|
{
|
||||||
uint8_t *p, *p_end;
|
uint8_t *p, *p_end;
|
||||||
|
|
||||||
if (!s1->plt)
|
if (!S->plt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p = s1->plt->data;
|
p = S->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
p_end = p + S->plt->data_offset;
|
||||||
|
|
||||||
if (s1->output_type != TCC_OUTPUT_DLL && p < p_end) {
|
if (S->output_type != TCC_OUTPUT_DLL && p < p_end) {
|
||||||
add32le(p + 2, s1->got->sh_addr);
|
add32le(p + 2, S->got->sh_addr);
|
||||||
add32le(p + 8, s1->got->sh_addr);
|
add32le(p + 8, S->got->sh_addr);
|
||||||
p += 16;
|
p += 16;
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
add32le(p + 2, s1->got->sh_addr);
|
add32le(p + 2, S->got->sh_addr);
|
||||||
p += 16;
|
p += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->plt->reloc) {
|
if (S->plt->reloc) {
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
int x = s1->plt->sh_addr + 16 + 6;
|
int x = S->plt->sh_addr + 16 + 6;
|
||||||
p = s1->got->data;
|
p = S->got->data;
|
||||||
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
write32le(p + rel->r_offset, x);
|
write32le(p + rel->r_offset, x);
|
||||||
x += 16;
|
x += 16;
|
||||||
}
|
}
|
||||||
@ -169,7 +169,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
{
|
{
|
||||||
int sym_index, esym_index;
|
int sym_index, esym_index;
|
||||||
|
|
||||||
@ -177,8 +177,8 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
|
||||||
@ -192,9 +192,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
add32le(ptr, val);
|
add32le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
/* DLL relocation */
|
/* DLL relocation */
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
|
||||||
@ -212,31 +212,31 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
write32le(ptr, val);
|
write32le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_386_GOTPC:
|
case R_386_GOTPC:
|
||||||
add32le(ptr, s1->got->sh_addr - addr);
|
add32le(ptr, S->got->sh_addr - addr);
|
||||||
return;
|
return;
|
||||||
case R_386_GOTOFF:
|
case R_386_GOTOFF:
|
||||||
add32le(ptr, val - s1->got->sh_addr);
|
add32le(ptr, val - S->got->sh_addr);
|
||||||
return;
|
return;
|
||||||
case R_386_GOT32:
|
case R_386_GOT32:
|
||||||
case R_386_GOT32X:
|
case R_386_GOT32X:
|
||||||
/* we load the got offset */
|
/* we load the got offset */
|
||||||
add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
|
add32le(ptr, get_sym_attr(S, sym_index, 0)->got_offset);
|
||||||
return;
|
return;
|
||||||
case R_386_16:
|
case R_386_16:
|
||||||
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
|
if (S->output_format != TCC_OUTPUT_FORMAT_BINARY) {
|
||||||
output_file:
|
output_file:
|
||||||
tcc_error("can only produce 16-bit binary files");
|
tcc_error(S, "can only produce 16-bit binary files");
|
||||||
}
|
}
|
||||||
write16le(ptr, read16le(ptr) + val);
|
write16le(ptr, read16le(ptr) + val);
|
||||||
return;
|
return;
|
||||||
case R_386_PC16:
|
case R_386_PC16:
|
||||||
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
|
if (S->output_format != TCC_OUTPUT_FORMAT_BINARY)
|
||||||
goto output_file;
|
goto output_file;
|
||||||
write16le(ptr, read16le(ptr) + val - addr);
|
write16le(ptr, read16le(ptr) + val - addr);
|
||||||
return;
|
return;
|
||||||
case R_386_RELATIVE:
|
case R_386_RELATIVE:
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
add32le(ptr, val - s1->pe_imagebase);
|
add32le(ptr, val - S->pe_imagebase);
|
||||||
#endif
|
#endif
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
return;
|
return;
|
||||||
@ -267,12 +267,12 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
memcpy(ptr-3, replace, sizeof(replace));
|
memcpy(ptr-3, replace, sizeof(replace));
|
||||||
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
|
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
sec = s1->sections[sym->st_shndx];
|
sec = S->sections[sym->st_shndx];
|
||||||
x = sym->st_value - sec->sh_addr - sec->data_offset;
|
x = sym->st_value - sec->sh_addr - sec->data_offset;
|
||||||
add32le(ptr + 5, -x);
|
add32le(ptr + 5, -x);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tcc_error("unexpected R_386_TLS_GD pattern");
|
tcc_error(S, "unexpected R_386_TLS_GD pattern");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case R_386_TLS_LDM:
|
case R_386_TLS_LDM:
|
||||||
@ -295,7 +295,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
|
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tcc_error("unexpected R_386_TLS_LDM pattern");
|
tcc_error(S, "unexpected R_386_TLS_LDM pattern");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case R_386_TLS_LDO_32:
|
case R_386_TLS_LDO_32:
|
||||||
@ -306,7 +306,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
int32_t x;
|
int32_t x;
|
||||||
|
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
sec = s1->sections[sym->st_shndx];
|
sec = S->sections[sym->st_shndx];
|
||||||
x = val - sec->sh_addr - sec->data_offset;
|
x = val - sec->sh_addr - sec->data_offset;
|
||||||
add32le(ptr, x);
|
add32le(ptr, x);
|
||||||
}
|
}
|
||||||
|
93
libtcc.h
93
libtcc.h
@ -15,56 +15,95 @@ typedef struct TCCState TCCState;
|
|||||||
|
|
||||||
typedef void (*TCCErrorFunc)(void *opaque, const char *msg);
|
typedef void (*TCCErrorFunc)(void *opaque, const char *msg);
|
||||||
|
|
||||||
|
#ifndef _OFF_T_DEFINED
|
||||||
|
#define _OFF_T_DEFINED
|
||||||
|
#ifndef _OFF_T_
|
||||||
|
#define _OFF_T_
|
||||||
|
typedef long _off_t;
|
||||||
|
#ifndef _SIZE_T_
|
||||||
|
#define _SIZE_T_
|
||||||
|
typedef unsigned long size_t;
|
||||||
|
#endif
|
||||||
|
#if !defined(NO_OLDNAMES) || defined(_POSIX)
|
||||||
|
typedef long off_t;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct vio_module_t;
|
||||||
|
|
||||||
|
typedef struct vio_fd {
|
||||||
|
int fd;
|
||||||
|
void *vio_udata;
|
||||||
|
struct vio_module_t *vio_module;
|
||||||
|
} vio_fd;
|
||||||
|
|
||||||
|
#define CALL_VIO_OPEN_FIRST 0x01
|
||||||
|
#define CALL_VIO_OPEN_LAST 0x02
|
||||||
|
|
||||||
|
typedef struct vio_module_t {
|
||||||
|
void *user_data;
|
||||||
|
struct TCCState *S;
|
||||||
|
int call_vio_open_flags; /*CALL_VIO_OPEN_FIRST, CALL_VIO_OPEN_LAST, one or both */
|
||||||
|
int (*vio_open)(vio_fd *fd, const char *fn, int oflag) ;
|
||||||
|
off_t (*vio_lseek)(vio_fd fd, off_t offset, int whence);
|
||||||
|
size_t (*vio_read)(vio_fd fd, void *buf, size_t bytes);
|
||||||
|
int (*vio_close)(vio_fd *fd);
|
||||||
|
} vio_module_t;
|
||||||
|
|
||||||
/* create a new TCC compilation context */
|
/* create a new TCC compilation context */
|
||||||
LIBTCCAPI TCCState *tcc_new(void);
|
LIBTCCAPI TCCState *tcc_new(void);
|
||||||
|
|
||||||
/* free a TCC compilation context */
|
/* free a TCC compilation context */
|
||||||
LIBTCCAPI void tcc_delete(TCCState *s);
|
LIBTCCAPI void tcc_delete(TCCState *S);
|
||||||
|
|
||||||
/* set CONFIG_TCCDIR at runtime */
|
/* set CONFIG_TCCDIR at runtime */
|
||||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
LIBTCCAPI void tcc_set_lib_path(TCCState *S, const char *path);
|
||||||
|
|
||||||
/* set error/warning display callback */
|
/* set error/warning display callback */
|
||||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func);
|
LIBTCCAPI void tcc_set_error_func(TCCState *S, void *error_opaque, TCCErrorFunc error_func);
|
||||||
|
|
||||||
/* return error/warning callback */
|
/* return error/warning callback */
|
||||||
LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s);
|
LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *S);
|
||||||
|
|
||||||
/* return error/warning callback opaque pointer */
|
/* return error/warning callback opaque pointer */
|
||||||
LIBTCCAPI void *tcc_get_error_opaque(TCCState *s);
|
LIBTCCAPI void *tcc_get_error_opaque(TCCState *S);
|
||||||
|
|
||||||
/* set options as from command line (multiple supported) */
|
/* set options as from command line (multiple supported) */
|
||||||
LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);
|
LIBTCCAPI void tcc_set_options(TCCState *S, const char *str);
|
||||||
|
|
||||||
|
/* set virtual io module */
|
||||||
|
LIBTCCAPI void tcc_set_vio_module(TCCState *S, vio_module_t *vio_module);
|
||||||
|
|
||||||
/*****************************/
|
/*****************************/
|
||||||
/* preprocessor */
|
/* preprocessor */
|
||||||
|
|
||||||
/* add include path */
|
/* add include path */
|
||||||
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);
|
LIBTCCAPI int tcc_add_include_path(TCCState *S, const char *pathname);
|
||||||
|
|
||||||
/* add in system include path */
|
/* add in system include path */
|
||||||
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
|
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *S, const char *pathname);
|
||||||
|
|
||||||
/* define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val" */
|
/* define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val" */
|
||||||
LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
|
LIBTCCAPI void tcc_define_symbol(TCCState *S, const char *sym, const char *value);
|
||||||
|
|
||||||
/* undefine preprocess symbol 'sym' */
|
/* undefine preprocess symbol 'sym' */
|
||||||
LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
|
LIBTCCAPI void tcc_undefine_symbol(TCCState *S, const char *sym);
|
||||||
|
|
||||||
/*****************************/
|
/*****************************/
|
||||||
/* compiling */
|
/* compiling */
|
||||||
|
|
||||||
/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
|
/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
|
||||||
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
|
LIBTCCAPI int tcc_add_file(TCCState *S, const char *filename);
|
||||||
|
|
||||||
/* compile a string containing a C source. Return -1 if error. */
|
/* compile a string containing a C source. Return -1 if error. */
|
||||||
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
|
LIBTCCAPI int tcc_compile_string(TCCState *S, const char *buf);
|
||||||
|
|
||||||
/*****************************/
|
/*****************************/
|
||||||
/* linking commands */
|
/* linking commands */
|
||||||
|
|
||||||
/* set output type. MUST BE CALLED before any compilation */
|
/* set output type. MUST BE CALLED before any compilation */
|
||||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
|
LIBTCCAPI int tcc_set_output_type(TCCState *S, int output_type);
|
||||||
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory (default) */
|
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory (default) */
|
||||||
#define TCC_OUTPUT_EXE 2 /* executable file */
|
#define TCC_OUTPUT_EXE 2 /* executable file */
|
||||||
#define TCC_OUTPUT_DLL 3 /* dynamic library */
|
#define TCC_OUTPUT_DLL 3 /* dynamic library */
|
||||||
@ -72,24 +111,24 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
|
|||||||
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */
|
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */
|
||||||
|
|
||||||
/* equivalent to -Lpath option */
|
/* equivalent to -Lpath option */
|
||||||
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
|
LIBTCCAPI int tcc_add_library_path(TCCState *S, const char *pathname);
|
||||||
|
|
||||||
/* the library name is the same as the argument of the '-l' option */
|
/* the library name is the same as the argument of the '-l' option */
|
||||||
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);
|
LIBTCCAPI int tcc_add_library(TCCState *S, const char *libraryname);
|
||||||
|
|
||||||
/* add a symbol to the compiled program */
|
/* add a symbol to the compiled program */
|
||||||
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val);
|
LIBTCCAPI int tcc_add_symbol(TCCState *S, const char *name, const void *val);
|
||||||
|
|
||||||
/* output an executable, library or object file. DO NOT call
|
/* output an executable, library or object file. DO NOT call
|
||||||
tcc_relocate() before. */
|
tcc_relocate() before. */
|
||||||
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
|
LIBTCCAPI int tcc_output_file(TCCState *S, const char *filename);
|
||||||
|
|
||||||
/* link and run main() function and return its value. DO NOT call
|
/* link and run main() function and return its value. DO NOT call
|
||||||
tcc_relocate() before. */
|
tcc_relocate() before. */
|
||||||
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
|
LIBTCCAPI int tcc_run(TCCState *S, int argc, char **argv);
|
||||||
|
|
||||||
/* do all relocations (needed before using tcc_get_symbol()) */
|
/* do all relocations (needed before using tcc_get_symbol()) */
|
||||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
|
LIBTCCAPI int tcc_relocate(TCCState *S, void *ptr);
|
||||||
/* possible values for 'ptr':
|
/* possible values for 'ptr':
|
||||||
- TCC_RELOCATE_AUTO : Allocate and manage memory internally
|
- TCC_RELOCATE_AUTO : Allocate and manage memory internally
|
||||||
- NULL : return required memory size for the step below
|
- NULL : return required memory size for the step below
|
||||||
@ -98,12 +137,24 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
|
|||||||
#define TCC_RELOCATE_AUTO (void*)1
|
#define TCC_RELOCATE_AUTO (void*)1
|
||||||
|
|
||||||
/* return symbol value or NULL if not found */
|
/* return symbol value or NULL if not found */
|
||||||
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
|
LIBTCCAPI void *tcc_get_symbol(TCCState *S, const char *name);
|
||||||
|
|
||||||
/* return symbol value or NULL if not found */
|
/* return symbol value or NULL if not found */
|
||||||
LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
|
LIBTCCAPI void tcc_list_symbols(TCCState *S, void *ctx,
|
||||||
void (*symbol_cb)(void *ctx, const char *name, const void *val));
|
void (*symbol_cb)(void *ctx, const char *name, const void *val));
|
||||||
|
|
||||||
|
typedef int (*tcc_cmpfun)(const void *, const void *, void *);
|
||||||
|
LIBTCCAPI void tcc_qsort_s(void *base, size_t nel, size_t width, tcc_cmpfun cmp, void *ctx);
|
||||||
|
|
||||||
|
enum { /*need better names for some of then*/
|
||||||
|
TCC_OPTION_d_BI = 1,
|
||||||
|
TCC_OPTION_d_D = 3,
|
||||||
|
TCC_OPTION_d_4 = 4,
|
||||||
|
TCC_OPTION_d_M = 7,
|
||||||
|
TCC_OPTION_d_t = 16,
|
||||||
|
TCC_OPTION_d_32 = 32,
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
374
riscv64-asm.c
374
riscv64-asm.c
@ -9,9 +9,9 @@
|
|||||||
#define CONFIG_TCC_ASM
|
#define CONFIG_TCC_ASM
|
||||||
#define NB_ASM_REGS 32
|
#define NB_ASM_REGS 32
|
||||||
|
|
||||||
ST_FUNC void g(int c);
|
ST_FUNC void g(TCCState* S, int c);
|
||||||
ST_FUNC void gen_le16(int c);
|
ST_FUNC void gen_le16(TCCState* S, int c);
|
||||||
ST_FUNC void gen_le32(int c);
|
ST_FUNC void gen_le32(TCCState* S, int c);
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
#else
|
#else
|
||||||
@ -20,85 +20,85 @@ ST_FUNC void gen_le32(int c);
|
|||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
/* XXX: make it faster ? */
|
/* XXX: make it faster ? */
|
||||||
ST_FUNC void g(int c)
|
ST_FUNC void g(TCCState* S, int c)
|
||||||
{
|
{
|
||||||
int ind1;
|
int ind1;
|
||||||
if (nocode_wanted)
|
if (S->tccgen_nocode_wanted)
|
||||||
return;
|
return;
|
||||||
ind1 = ind + 1;
|
ind1 = S->tccgen_ind + 1;
|
||||||
if (ind1 > cur_text_section->data_allocated)
|
if (ind1 > cur_text_section->data_allocated)
|
||||||
section_realloc(cur_text_section, ind1);
|
section_realloc(S, cur_text_section, ind1);
|
||||||
cur_text_section->data[ind] = c;
|
cur_text_section->data[S->tccgen_ind] = c;
|
||||||
ind = ind1;
|
S->tccgen_ind = ind1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_le16 (int i)
|
ST_FUNC void gen_le16 (TCCState* S, int i)
|
||||||
{
|
{
|
||||||
g(i);
|
g(S, i);
|
||||||
g(i>>8);
|
g(S, i>>8);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_le32 (int i)
|
ST_FUNC void gen_le32 (TCCState* S, int i)
|
||||||
{
|
{
|
||||||
int ind1;
|
int ind1;
|
||||||
if (nocode_wanted)
|
if (S->tccgen_nocode_wanted)
|
||||||
return;
|
return;
|
||||||
ind1 = ind + 4;
|
ind1 = S->tccgen_ind + 4;
|
||||||
if (ind1 > cur_text_section->data_allocated)
|
if (ind1 > cur_text_section->data_allocated)
|
||||||
section_realloc(cur_text_section, ind1);
|
section_realloc(S, cur_text_section, ind1);
|
||||||
cur_text_section->data[ind++] = i & 0xFF;
|
cur_text_section->data[S->tccgen_ind++] = i & 0xFF;
|
||||||
cur_text_section->data[ind++] = (i >> 8) & 0xFF;
|
cur_text_section->data[S->tccgen_ind++] = (i >> 8) & 0xFF;
|
||||||
cur_text_section->data[ind++] = (i >> 16) & 0xFF;
|
cur_text_section->data[S->tccgen_ind++] = (i >> 16) & 0xFF;
|
||||||
cur_text_section->data[ind++] = (i >> 24) & 0xFF;
|
cur_text_section->data[S->tccgen_ind++] = (i >> 24) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_expr32(ExprValue *pe)
|
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
|
||||||
{
|
{
|
||||||
gen_le32(pe->v);
|
gen_le32(S, pe->v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_opcode(uint32_t opcode) {
|
static void asm_emit_opcode(TCCState* S, uint32_t opcode) {
|
||||||
gen_le32(opcode);
|
gen_le32(S, opcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_nullary_opcode(TCCState *s1, int token)
|
static void asm_nullary_opcode(TCCState *S, int token)
|
||||||
{
|
{
|
||||||
switch (token) {
|
switch (token) {
|
||||||
// Sync instructions
|
// Sync instructions
|
||||||
|
|
||||||
case TOK_ASM_fence: // I
|
case TOK_ASM_fence: // I
|
||||||
asm_emit_opcode((0x3 << 2) | 3 | (0 << 12));
|
asm_emit_opcode(S, (0x3 << 2) | 3 | (0 << 12));
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_fence_i: // I
|
case TOK_ASM_fence_i: // I
|
||||||
asm_emit_opcode((0x3 << 2) | 3| (1 << 12));
|
asm_emit_opcode(S, (0x3 << 2) | 3| (1 << 12));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// System calls
|
// System calls
|
||||||
|
|
||||||
case TOK_ASM_scall: // I (pseudo)
|
case TOK_ASM_scall: // I (pseudo)
|
||||||
asm_emit_opcode((0x1C << 2) | 3 | (0 << 12));
|
asm_emit_opcode(S, (0x1C << 2) | 3 | (0 << 12));
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sbreak: // I (pseudo)
|
case TOK_ASM_sbreak: // I (pseudo)
|
||||||
asm_emit_opcode((0x1C << 2) | 3 | (0 << 12) | (1 << 20));
|
asm_emit_opcode(S, (0x1C << 2) | 3 | (0 << 12) | (1 << 20));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Privileged Instructions
|
// Privileged Instructions
|
||||||
|
|
||||||
case TOK_ASM_ecall:
|
case TOK_ASM_ecall:
|
||||||
asm_emit_opcode((0x1C << 2) | 3 | (0 << 20));
|
asm_emit_opcode(S, (0x1C << 2) | 3 | (0 << 20));
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_ebreak:
|
case TOK_ASM_ebreak:
|
||||||
asm_emit_opcode((0x1C << 2) | 3 | (1 << 20));
|
asm_emit_opcode(S, (0x1C << 2) | 3 | (1 << 20));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
||||||
case TOK_ASM_wfi:
|
case TOK_ASM_wfi:
|
||||||
asm_emit_opcode((0x1C << 2) | 3 | (0x105 << 20));
|
asm_emit_opcode(S, (0x1C << 2) | 3 | (0x105 << 20));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
expect("nullary instruction");
|
expect(S, "nullary instruction");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,30 +121,30 @@ typedef struct Operand {
|
|||||||
} Operand;
|
} Operand;
|
||||||
|
|
||||||
/* Parse a text containing operand and store the result in OP */
|
/* Parse a text containing operand and store the result in OP */
|
||||||
static void parse_operand(TCCState *s1, Operand *op)
|
static void parse_operand(TCCState *S, Operand *op)
|
||||||
{
|
{
|
||||||
ExprValue e;
|
ExprValue e;
|
||||||
int8_t reg;
|
int8_t reg;
|
||||||
|
|
||||||
op->type = 0;
|
op->type = 0;
|
||||||
|
|
||||||
if ((reg = asm_parse_regvar(tok)) != -1) {
|
if ((reg = asm_parse_regvar(S, S->tccpp_tok)) != -1) {
|
||||||
next(); // skip register name
|
next(S); // skip register name
|
||||||
op->type = OP_REG;
|
op->type = OP_REG;
|
||||||
op->reg = (uint8_t) reg;
|
op->reg = (uint8_t) reg;
|
||||||
return;
|
return;
|
||||||
} else if (tok == '$') {
|
} else if (S->tccpp_tok == '$') {
|
||||||
/* constant value */
|
/* constant value */
|
||||||
next(); // skip '#' or '$'
|
next(S); // skip '#' or '$'
|
||||||
}
|
}
|
||||||
asm_expr(s1, &e);
|
asm_expr(S, &e);
|
||||||
op->type = OP_IM32;
|
op->type = OP_IM32;
|
||||||
op->e = e;
|
op->e = e;
|
||||||
if (!op->e.sym) {
|
if (!op->e.sym) {
|
||||||
if ((int) op->e.v >= -2048 && (int) op->e.v < 2048)
|
if ((int) op->e.v >= -2048 && (int) op->e.v < 2048)
|
||||||
op->type = OP_IM12S;
|
op->type = OP_IM12S;
|
||||||
} else
|
} else
|
||||||
expect("operand");
|
expect(S, "operand");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ENCODE_RS1(register_index) ((register_index) << 15)
|
#define ENCODE_RS1(register_index) ((register_index) << 15)
|
||||||
@ -152,96 +152,96 @@ static void parse_operand(TCCState *s1, Operand *op)
|
|||||||
#define ENCODE_RD(register_index) ((register_index) << 7)
|
#define ENCODE_RD(register_index) ((register_index) << 7)
|
||||||
|
|
||||||
// Note: Those all map to CSR--so they are pseudo-instructions.
|
// Note: Those all map to CSR--so they are pseudo-instructions.
|
||||||
static void asm_unary_opcode(TCCState *s1, int token)
|
static void asm_unary_opcode(TCCState *S, int token)
|
||||||
{
|
{
|
||||||
uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);
|
uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);
|
||||||
Operand op;
|
Operand op;
|
||||||
parse_operand(s1, &op);
|
parse_operand(S, &op);
|
||||||
if (op.type != OP_REG) {
|
if (op.type != OP_REG) {
|
||||||
expect("register");
|
expect(S, "register");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
opcode |= ENCODE_RD(op.reg);
|
opcode |= ENCODE_RD(op.reg);
|
||||||
|
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case TOK_ASM_rdcycle:
|
case TOK_ASM_rdcycle:
|
||||||
asm_emit_opcode(opcode | (0xC00 << 20));
|
asm_emit_opcode(S, opcode | (0xC00 << 20));
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_rdcycleh:
|
case TOK_ASM_rdcycleh:
|
||||||
asm_emit_opcode(opcode | (0xC80 << 20));
|
asm_emit_opcode(S, opcode | (0xC80 << 20));
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_rdtime:
|
case TOK_ASM_rdtime:
|
||||||
asm_emit_opcode(opcode | (0xC01 << 20) | ENCODE_RD(op.reg));
|
asm_emit_opcode(S, opcode | (0xC01 << 20) | ENCODE_RD(op.reg));
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_rdtimeh:
|
case TOK_ASM_rdtimeh:
|
||||||
asm_emit_opcode(opcode | (0xC81 << 20) | ENCODE_RD(op.reg));
|
asm_emit_opcode(S, opcode | (0xC81 << 20) | ENCODE_RD(op.reg));
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_rdinstret:
|
case TOK_ASM_rdinstret:
|
||||||
asm_emit_opcode(opcode | (0xC02 << 20) | ENCODE_RD(op.reg));
|
asm_emit_opcode(S, opcode | (0xC02 << 20) | ENCODE_RD(op.reg));
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_rdinstreth:
|
case TOK_ASM_rdinstreth:
|
||||||
asm_emit_opcode(opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
|
asm_emit_opcode(S, opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
expect("unary instruction");
|
expect(S, "unary instruction");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_u(int token, uint32_t opcode, const Operand* rd, const Operand* rs2)
|
static void asm_emit_u(TCCState *S, int token, uint32_t opcode, const Operand* rd, const Operand* rs2)
|
||||||
{
|
{
|
||||||
if (rd->type != OP_REG) {
|
if (rd->type != OP_REG) {
|
||||||
tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rs2->type != OP_IM12S && rs2->type != OP_IM32) {
|
if (rs2->type != OP_IM12S && rs2->type != OP_IM32) {
|
||||||
tcc_error("'%s': Expected second source operand that is an immediate value", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected second source operand that is an immediate value", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
} else if (rs2->e.v >= 0x100000) {
|
} else if (rs2->e.v >= 0x100000) {
|
||||||
tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 0xfffff", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected second source operand that is an immediate value between 0 and 0xfffff", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* U-type instruction:
|
/* U-type instruction:
|
||||||
31...12 imm[31:12]
|
31...12 imm[31:12]
|
||||||
11...7 rd
|
11...7 rd
|
||||||
6...0 opcode */
|
6...0 opcode */
|
||||||
gen_le32(opcode | ENCODE_RD(rd->reg) | (rs2->e.v << 12));
|
gen_le32(S, opcode | ENCODE_RD(rd->reg) | (rs2->e.v << 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_binary_opcode(TCCState* s1, int token)
|
static void asm_binary_opcode(TCCState* S, int token)
|
||||||
{
|
{
|
||||||
Operand ops[2];
|
Operand ops[2];
|
||||||
parse_operand(s1, &ops[0]);
|
parse_operand(S, &ops[0]);
|
||||||
if (tok == ',')
|
if (S->tccpp_tok == ',')
|
||||||
next();
|
next(S);
|
||||||
else
|
else
|
||||||
expect("','");
|
expect(S, "','");
|
||||||
parse_operand(s1, &ops[1]);
|
parse_operand(S, &ops[1]);
|
||||||
|
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case TOK_ASM_lui:
|
case TOK_ASM_lui:
|
||||||
asm_emit_u(token, (0xD << 2) | 3, &ops[0], &ops[1]);
|
asm_emit_u(S, token, (0xD << 2) | 3, &ops[0], &ops[1]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_auipc:
|
case TOK_ASM_auipc:
|
||||||
asm_emit_u(token, (0x05 << 2) | 3, &ops[0], &ops[1]);
|
asm_emit_u(S, token, (0x05 << 2) | 3, &ops[0], &ops[1]);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
expect("binary instruction");
|
expect(S, "binary instruction");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* caller: Add funct3, funct7 into opcode */
|
/* caller: Add funct3, funct7 into opcode */
|
||||||
static void asm_emit_r(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
|
static void asm_emit_r(TCCState* S, int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
|
||||||
{
|
{
|
||||||
if (rd->type != OP_REG) {
|
if (rd->type != OP_REG) {
|
||||||
tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rs1->type != OP_REG) {
|
if (rs1->type != OP_REG) {
|
||||||
tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected first source operand that is a register", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rs2->type != OP_REG) {
|
if (rs2->type != OP_REG) {
|
||||||
tcc_error("'%s': Expected second source operand that is a register or immediate", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected second source operand that is a register or immediate", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* R-type instruction:
|
/* R-type instruction:
|
||||||
@ -251,22 +251,22 @@ static void asm_emit_r(int token, uint32_t opcode, const Operand* rd, const Oper
|
|||||||
14...12 funct3
|
14...12 funct3
|
||||||
11...7 rd
|
11...7 rd
|
||||||
6...0 opcode */
|
6...0 opcode */
|
||||||
gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg));
|
gen_le32(S, opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* caller: Add funct3 into opcode */
|
/* caller: Add funct3 into opcode */
|
||||||
static void asm_emit_i(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
|
static void asm_emit_i(TCCState* S, int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
|
||||||
{
|
{
|
||||||
if (rd->type != OP_REG) {
|
if (rd->type != OP_REG) {
|
||||||
tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rs1->type != OP_REG) {
|
if (rs1->type != OP_REG) {
|
||||||
tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected first source operand that is a register", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rs2->type != OP_IM12S) {
|
if (rs2->type != OP_IM12S) {
|
||||||
tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 4095", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected second source operand that is an immediate value between 0 and 4095", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* I-type instruction:
|
/* I-type instruction:
|
||||||
@ -276,156 +276,156 @@ static void asm_emit_i(int token, uint32_t opcode, const Operand* rd, const Oper
|
|||||||
11...7 rd
|
11...7 rd
|
||||||
6...0 opcode */
|
6...0 opcode */
|
||||||
|
|
||||||
gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | (rs2->e.v << 20));
|
gen_le32(S, opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | (rs2->e.v << 20));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_shift_opcode(TCCState *s1, int token)
|
static void asm_shift_opcode(TCCState *S, int token)
|
||||||
{
|
{
|
||||||
Operand ops[3];
|
Operand ops[3];
|
||||||
parse_operand(s1, &ops[0]);
|
parse_operand(S, &ops[0]);
|
||||||
if (tok == ',')
|
if (S->tccpp_tok == ',')
|
||||||
next();
|
next(S);
|
||||||
else
|
else
|
||||||
expect("','");
|
expect(S, "','");
|
||||||
parse_operand(s1, &ops[1]);
|
parse_operand(S, &ops[1]);
|
||||||
if (tok == ',')
|
if (S->tccpp_tok == ',')
|
||||||
next();
|
next(S);
|
||||||
else
|
else
|
||||||
expect("','");
|
expect(S, "','");
|
||||||
parse_operand(s1, &ops[2]);
|
parse_operand(S, &ops[2]);
|
||||||
|
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case TOK_ASM_sll:
|
case TOK_ASM_sll:
|
||||||
asm_emit_r(token, (0xC << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xC << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_slli:
|
case TOK_ASM_slli:
|
||||||
asm_emit_i(token, (4 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (4 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_srl:
|
case TOK_ASM_srl:
|
||||||
asm_emit_r(token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_srli:
|
case TOK_ASM_srli:
|
||||||
asm_emit_i(token, (0x4 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x4 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sra:
|
case TOK_ASM_sra:
|
||||||
asm_emit_r(token, (0xC << 2) | 3 | (5 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xC << 2) | 3 | (5 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_srai:
|
case TOK_ASM_srai:
|
||||||
asm_emit_i(token, (0x4 << 2) | 3 | (5 << 12) | (16 << 26), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x4 << 2) | 3 | (5 << 12) | (16 << 26), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sllw:
|
case TOK_ASM_sllw:
|
||||||
asm_emit_r(token, (0xE << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xE << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_slliw:
|
case TOK_ASM_slliw:
|
||||||
asm_emit_i(token, (6 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (6 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_srlw:
|
case TOK_ASM_srlw:
|
||||||
asm_emit_r(token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_srliw:
|
case TOK_ASM_srliw:
|
||||||
asm_emit_i(token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sraw:
|
case TOK_ASM_sraw:
|
||||||
asm_emit_r(token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sraiw:
|
case TOK_ASM_sraiw:
|
||||||
asm_emit_i(token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
expect("shift instruction");
|
expect(S, "shift instruction");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_data_processing_opcode(TCCState* s1, int token)
|
static void asm_data_processing_opcode(TCCState* S, int token)
|
||||||
{
|
{
|
||||||
Operand ops[3];
|
Operand ops[3];
|
||||||
parse_operand(s1, &ops[0]);
|
parse_operand(S, &ops[0]);
|
||||||
if (tok == ',')
|
if (S->tccpp_tok == ',')
|
||||||
next();
|
next(S);
|
||||||
else
|
else
|
||||||
expect("','");
|
expect(S, "','");
|
||||||
parse_operand(s1, &ops[1]);
|
parse_operand(S, &ops[1]);
|
||||||
if (tok == ',')
|
if (S->tccpp_tok == ',')
|
||||||
next();
|
next(S);
|
||||||
else
|
else
|
||||||
expect("','");
|
expect(S, "','");
|
||||||
parse_operand(s1, &ops[2]);
|
parse_operand(S, &ops[2]);
|
||||||
|
|
||||||
switch (token) {
|
switch (token) {
|
||||||
// Arithmetic (RD,RS1,(RS2|IMM)); R-format, I-format or U-format
|
// Arithmetic (RD,RS1,(RS2|IMM)); R-format, I-format or U-format
|
||||||
|
|
||||||
case TOK_ASM_add:
|
case TOK_ASM_add:
|
||||||
asm_emit_r(token, (0xC << 2) | 3, &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xC << 2) | 3, &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_addi:
|
case TOK_ASM_addi:
|
||||||
asm_emit_i(token, (4 << 2) | 3, &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (4 << 2) | 3, &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sub:
|
case TOK_ASM_sub:
|
||||||
asm_emit_r(token, (0xC << 2) | 3 | (32 << 25), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xC << 2) | 3 | (32 << 25), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_addw:
|
case TOK_ASM_addw:
|
||||||
asm_emit_r(token, (0xE << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xE << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_addiw: // 64 bit
|
case TOK_ASM_addiw: // 64 bit
|
||||||
asm_emit_i(token, (0x6 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x6 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_subw:
|
case TOK_ASM_subw:
|
||||||
asm_emit_r(token, (0xE << 2) | 3 | (0 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xE << 2) | 3 | (0 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Logical (RD,RS1,(RS2|IMM)); R-format or I-format
|
// Logical (RD,RS1,(RS2|IMM)); R-format or I-format
|
||||||
|
|
||||||
case TOK_ASM_xor:
|
case TOK_ASM_xor:
|
||||||
asm_emit_r(token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_xori:
|
case TOK_ASM_xori:
|
||||||
asm_emit_i(token, (0x4 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x4 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_or:
|
case TOK_ASM_or:
|
||||||
asm_emit_r(token, (0xC << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xC << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_ori:
|
case TOK_ASM_ori:
|
||||||
asm_emit_i(token, (0x4 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x4 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_and:
|
case TOK_ASM_and:
|
||||||
asm_emit_r(token, (0xC << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xC << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_andi:
|
case TOK_ASM_andi:
|
||||||
asm_emit_i(token, (0x4 << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x4 << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Compare (RD,RS1,(RS2|IMM)); R-format or I-format
|
// Compare (RD,RS1,(RS2|IMM)); R-format or I-format
|
||||||
|
|
||||||
case TOK_ASM_slt:
|
case TOK_ASM_slt:
|
||||||
asm_emit_r(token, (0xC << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xC << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_slti:
|
case TOK_ASM_slti:
|
||||||
asm_emit_i(token, (0x4 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x4 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sltu:
|
case TOK_ASM_sltu:
|
||||||
asm_emit_r(token, (0xC << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_r(S, token, (0xC << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sltiu:
|
case TOK_ASM_sltiu:
|
||||||
asm_emit_i(token, (0x4 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x4 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
expect("known data processing instruction");
|
expect(S, "known data processing instruction");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* caller: Add funct3 to opcode */
|
/* caller: Add funct3 to opcode */
|
||||||
static void asm_emit_s(int token, uint32_t opcode, const Operand* rs1, const Operand* rs2, const Operand* imm)
|
static void asm_emit_s(TCCState* S, int token, uint32_t opcode, const Operand* rs1, const Operand* rs2, const Operand* imm)
|
||||||
{
|
{
|
||||||
if (rs1->type != OP_REG) {
|
if (rs1->type != OP_REG) {
|
||||||
tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected first source operand that is a register", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rs2->type != OP_REG) {
|
if (rs2->type != OP_REG) {
|
||||||
tcc_error("'%s': Expected second source operand that is a register", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected second source operand that is a register", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (imm->type != OP_IM12S) {
|
if (imm->type != OP_IM12S) {
|
||||||
tcc_error("'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -438,112 +438,112 @@ static void asm_emit_s(int token, uint32_t opcode, const Operand* rs1, const Ope
|
|||||||
11...7 imm[4:0]
|
11...7 imm[4:0]
|
||||||
6...0 opcode
|
6...0 opcode
|
||||||
opcode always fixed pos. */
|
opcode always fixed pos. */
|
||||||
gen_le32(opcode | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg) | ((v & 0x1F) << 7) | ((v >> 5) << 25));
|
gen_le32(S, opcode | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg) | ((v & 0x1F) << 7) | ((v >> 5) << 25));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_data_transfer_opcode(TCCState* s1, int token)
|
static void asm_data_transfer_opcode(TCCState* S, int token)
|
||||||
{
|
{
|
||||||
Operand ops[3];
|
Operand ops[3];
|
||||||
parse_operand(s1, &ops[0]);
|
parse_operand(S, &ops[0]);
|
||||||
if (ops[0].type != OP_REG) {
|
if (ops[0].type != OP_REG) {
|
||||||
expect("register");
|
expect(S, "register");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tok == ',')
|
if (S->tccpp_tok == ',')
|
||||||
next();
|
next(S);
|
||||||
else
|
else
|
||||||
expect("','");
|
expect(S, "','");
|
||||||
parse_operand(s1, &ops[1]);
|
parse_operand(S, &ops[1]);
|
||||||
if (ops[1].type != OP_REG) {
|
if (ops[1].type != OP_REG) {
|
||||||
expect("register");
|
expect(S, "register");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tok == ',')
|
if (S->tccpp_tok == ',')
|
||||||
next();
|
next(S);
|
||||||
else
|
else
|
||||||
expect("','");
|
expect(S, "','");
|
||||||
parse_operand(s1, &ops[2]);
|
parse_operand(S, &ops[2]);
|
||||||
|
|
||||||
switch (token) {
|
switch (token) {
|
||||||
// Loads (RD,RS1,I); I-format
|
// Loads (RD,RS1,I); I-format
|
||||||
|
|
||||||
case TOK_ASM_lb:
|
case TOK_ASM_lb:
|
||||||
asm_emit_i(token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_lh:
|
case TOK_ASM_lh:
|
||||||
asm_emit_i(token, (0x0 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x0 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_lw:
|
case TOK_ASM_lw:
|
||||||
asm_emit_i(token, (0x0 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x0 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_lbu:
|
case TOK_ASM_lbu:
|
||||||
asm_emit_i(token, (0x0 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x0 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_lhu:
|
case TOK_ASM_lhu:
|
||||||
asm_emit_i(token, (0x0 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x0 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
// 64 bit
|
// 64 bit
|
||||||
case TOK_ASM_ld:
|
case TOK_ASM_ld:
|
||||||
asm_emit_i(token, (0x0 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x0 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_lwu:
|
case TOK_ASM_lwu:
|
||||||
asm_emit_i(token, (0x0 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_i(S, token, (0x0 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Stores (RS1,RS2,I); S-format
|
// Stores (RS1,RS2,I); S-format
|
||||||
|
|
||||||
case TOK_ASM_sb:
|
case TOK_ASM_sb:
|
||||||
asm_emit_s(token, (0x8 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_s(S, token, (0x8 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sh:
|
case TOK_ASM_sh:
|
||||||
asm_emit_s(token, (0x8 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_s(S, token, (0x8 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sw:
|
case TOK_ASM_sw:
|
||||||
asm_emit_s(token, (0x8 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_s(S, token, (0x8 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
case TOK_ASM_sd:
|
case TOK_ASM_sd:
|
||||||
asm_emit_s(token, (0x8 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
asm_emit_s(S, token, (0x8 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
expect("known data transfer instruction");
|
expect(S, "known data transfer instruction");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_branch_opcode(TCCState* s1, int token)
|
static void asm_branch_opcode(TCCState* S, int token)
|
||||||
{
|
{
|
||||||
// Branch (RS1,RS2,IMM); SB-format
|
// Branch (RS1,RS2,IMM); SB-format
|
||||||
uint32_t opcode = (0x18 << 2) | 3;
|
uint32_t opcode = (0x18 << 2) | 3;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
Operand ops[3];
|
Operand ops[3];
|
||||||
parse_operand(s1, &ops[0]);
|
parse_operand(S, &ops[0]);
|
||||||
if (ops[0].type != OP_REG) {
|
if (ops[0].type != OP_REG) {
|
||||||
expect("register");
|
expect(S, "register");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tok == ',')
|
if (S->tccpp_tok == ',')
|
||||||
next();
|
next(S);
|
||||||
else
|
else
|
||||||
expect("','");
|
expect(S, "','");
|
||||||
parse_operand(s1, &ops[1]);
|
parse_operand(S, &ops[1]);
|
||||||
if (ops[1].type != OP_REG) {
|
if (ops[1].type != OP_REG) {
|
||||||
expect("register");
|
expect(S, "register");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tok == ',')
|
if (S->tccpp_tok == ',')
|
||||||
next();
|
next(S);
|
||||||
else
|
else
|
||||||
expect("','");
|
expect(S, "','");
|
||||||
parse_operand(s1, &ops[2]);
|
parse_operand(S, &ops[2]);
|
||||||
|
|
||||||
if (ops[2].type != OP_IM12S) {
|
if (ops[2].type != OP_IM12S) {
|
||||||
tcc_error("'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
offset = ops[2].e.v;
|
offset = ops[2].e.v;
|
||||||
if (offset & 1) {
|
if (offset & 1) {
|
||||||
tcc_error("'%s': Expected third operand that is an even immediate value", get_tok_str(token, NULL));
|
tcc_error(S, "'%s': Expected third operand that is an even immediate value", get_tok_str(S, token, NULL));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,12 +567,12 @@ static void asm_branch_opcode(TCCState* s1, int token)
|
|||||||
opcode |= 7 << 12;
|
opcode |= 7 << 12;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
expect("known branch instruction");
|
expect(S, "known branch instruction");
|
||||||
}
|
}
|
||||||
asm_emit_opcode(opcode | ENCODE_RS1(ops[0].reg) | ENCODE_RS2(ops[1].reg) | (((offset >> 1) & 0xF) << 8) | (((offset >> 5) & 0x1f) << 25) | (((offset >> 11) & 1) << 7) | (((offset >> 12) & 1) << 31));
|
asm_emit_opcode(S, opcode | ENCODE_RS1(ops[0].reg) | ENCODE_RS2(ops[1].reg) | (((offset >> 1) & 0xF) << 8) | (((offset >> 5) & 0x1f) << 25) | (((offset >> 11) & 1) << 7) | (((offset >> 12) & 1) << 31));
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_opcode(TCCState *s1, int token)
|
ST_FUNC void asm_opcode(TCCState *S, int token)
|
||||||
{
|
{
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case TOK_ASM_fence:
|
case TOK_ASM_fence:
|
||||||
@ -585,7 +585,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||||||
case TOK_ASM_mrth:
|
case TOK_ASM_mrth:
|
||||||
case TOK_ASM_hrts:
|
case TOK_ASM_hrts:
|
||||||
case TOK_ASM_wfi:
|
case TOK_ASM_wfi:
|
||||||
asm_nullary_opcode(s1, token);
|
asm_nullary_opcode(S, token);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case TOK_ASM_rdcycle:
|
case TOK_ASM_rdcycle:
|
||||||
@ -594,12 +594,12 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||||||
case TOK_ASM_rdtimeh:
|
case TOK_ASM_rdtimeh:
|
||||||
case TOK_ASM_rdinstret:
|
case TOK_ASM_rdinstret:
|
||||||
case TOK_ASM_rdinstreth:
|
case TOK_ASM_rdinstreth:
|
||||||
asm_unary_opcode(s1, token);
|
asm_unary_opcode(S, token);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case TOK_ASM_lui:
|
case TOK_ASM_lui:
|
||||||
case TOK_ASM_auipc:
|
case TOK_ASM_auipc:
|
||||||
asm_binary_opcode(s1, token);
|
asm_binary_opcode(S, token);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case TOK_ASM_sll:
|
case TOK_ASM_sll:
|
||||||
@ -620,7 +620,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||||||
case TOK_ASM_srad:
|
case TOK_ASM_srad:
|
||||||
case TOK_ASM_sraiw:
|
case TOK_ASM_sraiw:
|
||||||
case TOK_ASM_sraid:
|
case TOK_ASM_sraid:
|
||||||
asm_shift_opcode(s1, token);
|
asm_shift_opcode(S, token);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case TOK_ASM_add:
|
case TOK_ASM_add:
|
||||||
@ -642,7 +642,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||||||
case TOK_ASM_slti:
|
case TOK_ASM_slti:
|
||||||
case TOK_ASM_sltu:
|
case TOK_ASM_sltu:
|
||||||
case TOK_ASM_sltiu:
|
case TOK_ASM_sltiu:
|
||||||
asm_data_processing_opcode(s1, token);
|
asm_data_processing_opcode(S, token);
|
||||||
|
|
||||||
case TOK_ASM_lb:
|
case TOK_ASM_lb:
|
||||||
case TOK_ASM_lh:
|
case TOK_ASM_lh:
|
||||||
@ -655,7 +655,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||||||
case TOK_ASM_sh:
|
case TOK_ASM_sh:
|
||||||
case TOK_ASM_sw:
|
case TOK_ASM_sw:
|
||||||
case TOK_ASM_sd:
|
case TOK_ASM_sd:
|
||||||
asm_data_transfer_opcode(s1, token);
|
asm_data_transfer_opcode(S, token);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case TOK_ASM_beq:
|
case TOK_ASM_beq:
|
||||||
@ -664,35 +664,35 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||||||
case TOK_ASM_bge:
|
case TOK_ASM_bge:
|
||||||
case TOK_ASM_bltu:
|
case TOK_ASM_bltu:
|
||||||
case TOK_ASM_bgeu:
|
case TOK_ASM_bgeu:
|
||||||
asm_branch_opcode(s1, token);
|
asm_branch_opcode(S, token);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
expect("known instruction");
|
expect(S, "known instruction");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
|
ST_FUNC void subst_asm_operand(TCCState *S, CString *add_str, SValue *sv, int modifier)
|
||||||
{
|
{
|
||||||
tcc_error("RISCV64 asm not implemented.");
|
tcc_error(S, "RISCV64 asm not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate prolog and epilog code for asm statement */
|
/* generate prolog and epilog code for asm statement */
|
||||||
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
ST_FUNC void asm_gen_code(TCCState *S, ASMOperand *operands, int nb_operands,
|
||||||
int nb_outputs, int is_output,
|
int nb_outputs, int is_output,
|
||||||
uint8_t *clobber_regs,
|
uint8_t *clobber_regs,
|
||||||
int out_reg)
|
int out_reg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
ST_FUNC void asm_compute_constraints(TCCState *S, ASMOperand *operands,
|
||||||
int nb_operands, int nb_outputs,
|
int nb_operands, int nb_outputs,
|
||||||
const uint8_t *clobber_regs,
|
const uint8_t *clobber_regs,
|
||||||
int *pout_reg)
|
int *pout_reg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
ST_FUNC void asm_clobber(TCCState *S, uint8_t *clobber_regs, const char *str)
|
||||||
{
|
{
|
||||||
int reg;
|
int reg;
|
||||||
TokenSym *ts;
|
TokenSym *ts;
|
||||||
@ -701,15 +701,15 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
|
|||||||
!strcmp(str, "cc") ||
|
!strcmp(str, "cc") ||
|
||||||
!strcmp(str, "flags"))
|
!strcmp(str, "flags"))
|
||||||
return;
|
return;
|
||||||
ts = tok_alloc(str, strlen(str));
|
ts = tok_alloc(S, str, strlen(str));
|
||||||
reg = asm_parse_regvar(ts->tok);
|
reg = asm_parse_regvar(S, ts->tok);
|
||||||
if (reg == -1) {
|
if (reg == -1) {
|
||||||
tcc_error("invalid clobber register '%s'", str);
|
tcc_error(S, "invalid clobber register '%s'", str);
|
||||||
}
|
}
|
||||||
clobber_regs[reg] = 1;
|
clobber_regs[reg] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int asm_parse_regvar (int t)
|
ST_FUNC int asm_parse_regvar (TCCState* S, int t)
|
||||||
{
|
{
|
||||||
if (t >= TOK_ASM_x0 && t <= TOK_ASM_pc) { /* register name */
|
if (t >= TOK_ASM_x0 && t <= TOK_ASM_pc) { /* register name */
|
||||||
switch (t) {
|
switch (t) {
|
||||||
|
908
riscv64-gen.c
908
riscv64-gen.c
File diff suppressed because it is too large
Load Diff
@ -95,39 +95,39 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
Section *plt = s1->plt;
|
Section *plt = S->plt;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
unsigned plt_offset;
|
unsigned plt_offset;
|
||||||
|
|
||||||
if (plt->data_offset == 0)
|
if (plt->data_offset == 0)
|
||||||
section_ptr_add(plt, 32);
|
section_ptr_add(S, plt, 32);
|
||||||
plt_offset = plt->data_offset;
|
plt_offset = plt->data_offset;
|
||||||
|
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(S, plt, 16);
|
||||||
write64le(p, got_offset);
|
write64le(p, got_offset);
|
||||||
return plt_offset;
|
return plt_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||||
address for PLT and GOT are known (see fill_program_header) */
|
address for PLT and GOT are known (see fill_program_header) */
|
||||||
ST_FUNC void relocate_plt(TCCState *s1)
|
ST_FUNC void relocate_plt(TCCState *S)
|
||||||
{
|
{
|
||||||
uint8_t *p, *p_end;
|
uint8_t *p, *p_end;
|
||||||
|
|
||||||
if (!s1->plt)
|
if (!S->plt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p = s1->plt->data;
|
p = S->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
p_end = p + S->plt->data_offset;
|
||||||
|
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
uint64_t plt = s1->plt->sh_addr;
|
uint64_t plt = S->plt->sh_addr;
|
||||||
uint64_t got = s1->got->sh_addr;
|
uint64_t got = S->got->sh_addr;
|
||||||
uint64_t off = (got - plt + 0x800) >> 12;
|
uint64_t off = (got - plt + 0x800) >> 12;
|
||||||
if ((off + ((uint32_t)1 << 20)) >> 21)
|
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||||
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
|
tcc_error(S, "Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
|
||||||
write32le(p, 0x397 | (off << 12)); // auipc t2, %pcrel_hi(got)
|
write32le(p, 0x397 | (off << 12)); // auipc t2, %pcrel_hi(got)
|
||||||
write32le(p + 4, 0x41c30333); // sub t1, t1, t3
|
write32le(p + 4, 0x41c30333); // sub t1, t1, t3
|
||||||
write32le(p + 8, 0x0003be03 // ld t3, %pcrel_lo(got)(t2)
|
write32le(p + 8, 0x0003be03 // ld t3, %pcrel_lo(got)(t2)
|
||||||
@ -140,11 +140,11 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
write32le(p + 28, 0x000e0067); // jr t3
|
write32le(p + 28, 0x000e0067); // jr t3
|
||||||
p += 32;
|
p += 32;
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
uint64_t pc = plt + (p - s1->plt->data);
|
uint64_t pc = plt + (p - S->plt->data);
|
||||||
uint64_t addr = got + read64le(p);
|
uint64_t addr = got + read64le(p);
|
||||||
uint64_t off = (addr - pc + 0x800) >> 12;
|
uint64_t off = (addr - pc + 0x800) >> 12;
|
||||||
if ((off + ((uint32_t)1 << 20)) >> 21)
|
if ((off + ((uint32_t)1 << 20)) >> 21)
|
||||||
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
|
tcc_error(S, "Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
|
||||||
write32le(p, 0xe17 | (off << 12)); // auipc t3, %pcrel_hi(func@got)
|
write32le(p, 0xe17 | (off << 12)); // auipc t3, %pcrel_hi(func@got)
|
||||||
write32le(p + 4, 0x000e3e03 // ld t3, %pcrel_lo(func@got)(t3)
|
write32le(p + 4, 0x000e3e03 // ld t3, %pcrel_lo(func@got)(t3)
|
||||||
| (((addr - pc) & 0xfff) << 20));
|
| (((addr - pc) & 0xfff) << 20));
|
||||||
@ -154,16 +154,16 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->plt->reloc) {
|
if (S->plt->reloc) {
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
p = s1->got->data;
|
p = S->got->data;
|
||||||
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
write64le(p + rel->r_offset, s1->plt->sh_addr);
|
write64le(p + rel->r_offset, S->plt->sh_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||||
addr_t addr, addr_t val)
|
addr_t addr, addr_t val)
|
||||||
{
|
{
|
||||||
uint64_t off64;
|
uint64_t off64;
|
||||||
@ -179,7 +179,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
case R_RISCV_BRANCH:
|
case R_RISCV_BRANCH:
|
||||||
off64 = val - addr;
|
off64 = val - addr;
|
||||||
if ((off64 + (1 << 12)) & ~(uint64_t)0x1ffe)
|
if ((off64 + (1 << 12)) & ~(uint64_t)0x1ffe)
|
||||||
tcc_error("R_RISCV_BRANCH relocation failed"
|
tcc_error(S, "R_RISCV_BRANCH relocation failed"
|
||||||
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
off32 = off64 >> 1;
|
off32 = off64 >> 1;
|
||||||
write32le(ptr, (read32le(ptr) & ~0xfe000f80)
|
write32le(ptr, (read32le(ptr) & ~0xfe000f80)
|
||||||
@ -191,7 +191,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
case R_RISCV_JAL:
|
case R_RISCV_JAL:
|
||||||
off64 = val - addr;
|
off64 = val - addr;
|
||||||
if ((off64 + (1 << 21)) & ~(((uint64_t)1 << 22) - 2))
|
if ((off64 + (1 << 21)) & ~(((uint64_t)1 << 22) - 2))
|
||||||
tcc_error("R_RISCV_JAL relocation failed"
|
tcc_error(S, "R_RISCV_JAL relocation failed"
|
||||||
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
off32 = off64;
|
off32 = off64;
|
||||||
write32le(ptr, (read32le(ptr) & 0xfff)
|
write32le(ptr, (read32le(ptr) & 0xfff)
|
||||||
@ -213,7 +213,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
#endif
|
#endif
|
||||||
off64 = (int64_t)(val - addr + 0x800) >> 12;
|
off64 = (int64_t)(val - addr + 0x800) >> 12;
|
||||||
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
||||||
tcc_error("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s",
|
tcc_error(S, "R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s",
|
||||||
(long)off64, (long)((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21),
|
(long)off64, (long)((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21),
|
||||||
symtab_section->link->data + sym->st_name);
|
symtab_section->link->data + sym->st_name);
|
||||||
write32le(ptr, (read32le(ptr) & 0xfff)
|
write32le(ptr, (read32le(ptr) & 0xfff)
|
||||||
@ -222,10 +222,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
last_hi.val = val;
|
last_hi.val = val;
|
||||||
return;
|
return;
|
||||||
case R_RISCV_GOT_HI20:
|
case R_RISCV_GOT_HI20:
|
||||||
val = s1->got->sh_addr + get_sym_attr(s1, sym_index, 0)->got_offset;
|
val = S->got->sh_addr + get_sym_attr(S, sym_index, 0)->got_offset;
|
||||||
off64 = (int64_t)(val - addr + 0x800) >> 12;
|
off64 = (int64_t)(val - addr + 0x800) >> 12;
|
||||||
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
||||||
tcc_error("R_RISCV_GOT_HI20 relocation failed");
|
tcc_error(S, "R_RISCV_GOT_HI20 relocation failed");
|
||||||
last_hi.addr = addr;
|
last_hi.addr = addr;
|
||||||
last_hi.val = val;
|
last_hi.val = val;
|
||||||
write32le(ptr, (read32le(ptr) & 0xfff)
|
write32le(ptr, (read32le(ptr) & 0xfff)
|
||||||
@ -236,7 +236,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
printf("PCREL_LO12_I: val=%lx addr=%lx\n", (long)val, (long)addr);
|
printf("PCREL_LO12_I: val=%lx addr=%lx\n", (long)val, (long)addr);
|
||||||
#endif
|
#endif
|
||||||
if (val != last_hi.addr)
|
if (val != last_hi.addr)
|
||||||
tcc_error("unsupported hi/lo pcrel reloc scheme");
|
tcc_error(S, "unsupported hi/lo pcrel reloc scheme");
|
||||||
val = last_hi.val;
|
val = last_hi.val;
|
||||||
addr = last_hi.addr;
|
addr = last_hi.addr;
|
||||||
write32le(ptr, (read32le(ptr) & 0xfffff)
|
write32le(ptr, (read32le(ptr) & 0xfffff)
|
||||||
@ -244,7 +244,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
return;
|
return;
|
||||||
case R_RISCV_PCREL_LO12_S:
|
case R_RISCV_PCREL_LO12_S:
|
||||||
if (val != last_hi.addr)
|
if (val != last_hi.addr)
|
||||||
tcc_error("unsupported hi/lo pcrel reloc scheme");
|
tcc_error(S, "unsupported hi/lo pcrel reloc scheme");
|
||||||
val = last_hi.val;
|
val = last_hi.val;
|
||||||
addr = last_hi.addr;
|
addr = last_hi.addr;
|
||||||
off32 = val - addr;
|
off32 = val - addr;
|
||||||
@ -256,7 +256,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
case R_RISCV_RVC_BRANCH:
|
case R_RISCV_RVC_BRANCH:
|
||||||
off64 = (val - addr);
|
off64 = (val - addr);
|
||||||
if ((off64 + (1 << 8)) & ~(uint64_t)0x1fe)
|
if ((off64 + (1 << 8)) & ~(uint64_t)0x1fe)
|
||||||
tcc_error("R_RISCV_RVC_BRANCH relocation failed"
|
tcc_error(S, "R_RISCV_RVC_BRANCH relocation failed"
|
||||||
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
off32 = off64;
|
off32 = off64;
|
||||||
write16le(ptr, (read16le(ptr) & 0xe383)
|
write16le(ptr, (read16le(ptr) & 0xe383)
|
||||||
@ -269,7 +269,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
case R_RISCV_RVC_JUMP:
|
case R_RISCV_RVC_JUMP:
|
||||||
off64 = (val - addr);
|
off64 = (val - addr);
|
||||||
if ((off64 + (1 << 11)) & ~(uint64_t)0xffe)
|
if ((off64 + (1 << 11)) & ~(uint64_t)0xffe)
|
||||||
tcc_error("R_RISCV_RVC_BRANCH relocation failed"
|
tcc_error(S, "R_RISCV_RVC_BRANCH relocation failed"
|
||||||
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
" (val=%lx, addr=%lx)", (long)val, (long)addr);
|
||||||
off32 = off64;
|
off32 = off64;
|
||||||
write16le(ptr, (read16le(ptr) & 0xe003)
|
write16le(ptr, (read16le(ptr) & 0xe003)
|
||||||
@ -284,7 +284,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case R_RISCV_32:
|
case R_RISCV_32:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
/* XXX: this logic may depend on TCC's codegen
|
/* XXX: this logic may depend on TCC's codegen
|
||||||
now TCC uses R_RISCV_RELATIVE even for a 64bit pointer */
|
now TCC uses R_RISCV_RELATIVE even for a 64bit pointer */
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
@ -296,8 +296,8 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
add32le(ptr, val);
|
add32le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_RISCV_64:
|
case R_RISCV_64:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_RISCV_64);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_RISCV_64);
|
||||||
|
238
tcc.c
238
tcc.c
@ -199,40 +199,40 @@ static void print_dirs(const char *msg, char **paths, int nb_paths)
|
|||||||
printf(" %s\n", paths[i]);
|
printf(" %s\n", paths[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_search_dirs(TCCState *s)
|
static void print_search_dirs(TCCState *S)
|
||||||
{
|
{
|
||||||
printf("install: %s\n", s->tcc_lib_path);
|
printf("install: %s\n", S->tcc_lib_path);
|
||||||
/* print_dirs("programs", NULL, 0); */
|
/* print_dirs("programs", NULL, 0); */
|
||||||
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
print_dirs("include", S->sysinclude_paths, S->nb_sysinclude_paths);
|
||||||
print_dirs("libraries", s->library_paths, s->nb_library_paths);
|
print_dirs("libraries", S->library_paths, S->nb_library_paths);
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
printf("libtcc1:\n %s/lib/"TCC_LIBTCC1"\n", s->tcc_lib_path);
|
printf("libtcc1:\n %s/lib/"TCC_LIBTCC1"\n", S->tcc_lib_path);
|
||||||
#else
|
#else
|
||||||
printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path);
|
printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", S->tcc_lib_path);
|
||||||
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
|
print_dirs("crt", S->crt_paths, S->nb_crt_paths);
|
||||||
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
|
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(S));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_environment(TCCState *s)
|
static void set_environment(TCCState *S)
|
||||||
{
|
{
|
||||||
char * path;
|
char * path;
|
||||||
|
|
||||||
path = getenv("C_INCLUDE_PATH");
|
path = getenv("C_INCLUDE_PATH");
|
||||||
if(path != NULL) {
|
if(path != NULL) {
|
||||||
tcc_add_sysinclude_path(s, path);
|
tcc_add_sysinclude_path(S, path);
|
||||||
}
|
}
|
||||||
path = getenv("CPATH");
|
path = getenv("CPATH");
|
||||||
if(path != NULL) {
|
if(path != NULL) {
|
||||||
tcc_add_include_path(s, path);
|
tcc_add_include_path(S, path);
|
||||||
}
|
}
|
||||||
path = getenv("LIBRARY_PATH");
|
path = getenv("LIBRARY_PATH");
|
||||||
if(path != NULL) {
|
if(path != NULL) {
|
||||||
tcc_add_library_path(s, path);
|
tcc_add_library_path(S, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *default_outputfile(TCCState *s, const char *first_file)
|
static char *default_outputfile(TCCState *S, const char *first_file)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *ext;
|
char *ext;
|
||||||
@ -243,18 +243,18 @@ static char *default_outputfile(TCCState *s, const char *first_file)
|
|||||||
snprintf(buf, sizeof(buf), "%s", name);
|
snprintf(buf, sizeof(buf), "%s", name);
|
||||||
ext = tcc_fileextension(buf);
|
ext = tcc_fileextension(buf);
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (s->output_type == TCC_OUTPUT_DLL)
|
if (S->output_type == TCC_OUTPUT_DLL)
|
||||||
strcpy(ext, ".dll");
|
strcpy(ext, ".dll");
|
||||||
else
|
else
|
||||||
if (s->output_type == TCC_OUTPUT_EXE)
|
if (S->output_type == TCC_OUTPUT_EXE)
|
||||||
strcpy(ext, ".exe");
|
strcpy(ext, ".exe");
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if ((s->just_deps || s->output_type == TCC_OUTPUT_OBJ) && !s->option_r && *ext)
|
if ((S->just_deps || S->output_type == TCC_OUTPUT_OBJ) && !S->option_r && *ext)
|
||||||
strcpy(ext, ".o");
|
strcpy(ext, ".o");
|
||||||
else
|
else
|
||||||
strcpy(buf, "a.out");
|
strcpy(buf, "a.out");
|
||||||
return tcc_strdup(buf);
|
return tcc_strdup(S, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned getclock_ms(void)
|
static unsigned getclock_ms(void)
|
||||||
@ -268,9 +268,101 @@ static unsigned getclock_ms(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_ATTACHMENTS
|
||||||
|
#include "tcc_attachments.h"
|
||||||
|
#define ATTACH_PREFIX "/_attach_"
|
||||||
|
|
||||||
|
static vio_module_t vio_module;
|
||||||
|
|
||||||
|
typedef struct vio_memfile_t {
|
||||||
|
off_t size;
|
||||||
|
off_t pos;
|
||||||
|
const unsigned char *mem;
|
||||||
|
} vio_memfile_t;
|
||||||
|
|
||||||
|
static int vio_mem_open(vio_fd *fd, const char *fn, int oflag) {
|
||||||
|
//printf("%d:%s\n", fd->fd, fn);
|
||||||
|
if(fd->vio_module && strncmp(ATTACH_PREFIX, fn, sizeof(ATTACH_PREFIX)-1) == 0){
|
||||||
|
int i, count = sizeof(bin2c_filesAttached)/sizeof(bin2c_filesAttached_st);
|
||||||
|
for(i=0; i < count; ++i) {
|
||||||
|
//printf("%s:%s\n", fn, bin2c_filesAttached[i].file_name);
|
||||||
|
if(strcmp(fn, bin2c_filesAttached[i].file_name) == 0) {
|
||||||
|
vio_memfile_t *mf = (vio_memfile_t*)tcc_malloc(S, fd->vio_module->tcc_state);
|
||||||
|
mf->mem = bin2c_filesAttached[i].sym_name;
|
||||||
|
mf->size = bin2c_filesAttached[i].size;
|
||||||
|
mf->pos = 0;
|
||||||
|
fd->fd = 1;
|
||||||
|
fd->vio_udata = mf;
|
||||||
|
//printf("%d:%s\n", fd->fd, fn);
|
||||||
|
return fd->fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static off_t vio_mem_lseek(vio_fd fd, off_t offset, int whence) {
|
||||||
|
if(fd.vio_udata) {
|
||||||
|
off_t loffset = 0;
|
||||||
|
vio_memfile_t *mf = (vio_memfile_t*)fd.vio_udata;
|
||||||
|
if (whence == SEEK_CUR)
|
||||||
|
loffset = mf->pos + offset;
|
||||||
|
else if (whence == SEEK_SET)
|
||||||
|
loffset = offset;
|
||||||
|
else if (whence == SEEK_END)
|
||||||
|
loffset = ((off_t)mf->size) + offset;
|
||||||
|
|
||||||
|
if (loffset < 0 && loffset > mf->size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mf->pos = loffset;
|
||||||
|
|
||||||
|
return mf->pos;
|
||||||
|
}
|
||||||
|
return lseek(fd.fd, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t vio_mem_read(vio_fd fd, void *buf, size_t bytes) {
|
||||||
|
if(fd.vio_udata) {
|
||||||
|
vio_memfile_t *mf = (vio_memfile_t*)fd.vio_udata;
|
||||||
|
if( (mf->pos + bytes) > mf->size) {
|
||||||
|
long bc = mf->size - mf->pos;
|
||||||
|
if(bc > 0) {
|
||||||
|
memcpy(buf, mf->mem + mf->pos, bc);
|
||||||
|
mf->pos = mf->size;
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(buf, mf->mem + mf->pos, bytes);
|
||||||
|
mf->pos += bytes;
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vio_mem_close(vio_fd *fd) {
|
||||||
|
if(fd->vio_udata){
|
||||||
|
tcc_free(S, fd->vio_udata);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_vio_module(TCCState *S){
|
||||||
|
vio_module.user_data = NULL;
|
||||||
|
vio_module.call_vio_open_flags = CALL_VIO_OPEN_FIRST;
|
||||||
|
vio_module.vio_open = &vio_mem_open;
|
||||||
|
vio_module.vio_lseek = &vio_mem_lseek;
|
||||||
|
vio_module.vio_read = &vio_mem_read;
|
||||||
|
vio_module.vio_close = &vio_mem_close;
|
||||||
|
tcc_set_vio_module(s, &vio_module);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc0, char **argv0)
|
int main(int argc0, char **argv0)
|
||||||
{
|
{
|
||||||
TCCState *s, *s1;
|
TCCState *S, *s1;
|
||||||
int ret, opt, n = 0, t = 0, done;
|
int ret, opt, n = 0, t = 0, done;
|
||||||
unsigned start_time = 0, end_time = 0;
|
unsigned start_time = 0, end_time = 0;
|
||||||
const char *first_file;
|
const char *first_file;
|
||||||
@ -279,13 +371,19 @@ int main(int argc0, char **argv0)
|
|||||||
|
|
||||||
redo:
|
redo:
|
||||||
argc = argc0, argv = argv0;
|
argc = argc0, argv = argv0;
|
||||||
s = s1 = tcc_new();
|
S = s1 = tcc_new();
|
||||||
opt = tcc_parse_args(s, &argc, &argv, 1);
|
opt = tcc_parse_args(S, &argc, &argv, 1);
|
||||||
|
|
||||||
|
#ifdef WITH_ATTACHMENTS
|
||||||
|
tcc_set_lib_path(S, ATTACH_PREFIX);
|
||||||
|
tcc_add_include_path(S, ATTACH_PREFIX);
|
||||||
|
set_vio_module(S);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
if (opt == OPT_HELP) {
|
if (opt == OPT_HELP) {
|
||||||
fputs(help, stdout);
|
fputs(help, stdout);
|
||||||
if (!s->verbose)
|
if (!S->verbose)
|
||||||
return 0;
|
return 0;
|
||||||
++opt;
|
++opt;
|
||||||
}
|
}
|
||||||
@ -294,57 +392,57 @@ redo:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (opt == OPT_M32 || opt == OPT_M64)
|
if (opt == OPT_M32 || opt == OPT_M64)
|
||||||
tcc_tool_cross(s, argv, opt); /* never returns */
|
tcc_tool_cross(S, argv, opt); /* never returns */
|
||||||
if (s->verbose)
|
if (S->verbose)
|
||||||
printf(version);
|
printf(version);
|
||||||
if (opt == OPT_AR)
|
if (opt == OPT_AR)
|
||||||
return tcc_tool_ar(s, argc, argv);
|
return tcc_tool_ar(S, argc, argv);
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (opt == OPT_IMPDEF)
|
if (opt == OPT_IMPDEF)
|
||||||
return tcc_tool_impdef(s, argc, argv);
|
return tcc_tool_impdef(S, argc, argv);
|
||||||
#endif
|
#endif
|
||||||
if (opt == OPT_V)
|
if (opt == OPT_V)
|
||||||
return 0;
|
return 0;
|
||||||
if (opt == OPT_PRINT_DIRS) {
|
if (opt == OPT_PRINT_DIRS) {
|
||||||
/* initialize search dirs */
|
/* initialize search dirs */
|
||||||
set_environment(s);
|
set_environment(S);
|
||||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
tcc_set_output_type(S, TCC_OUTPUT_MEMORY);
|
||||||
print_search_dirs(s);
|
print_search_dirs(S);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->nb_files == 0)
|
if (S->nb_files == 0)
|
||||||
tcc_error("no input files");
|
tcc_error(S, "no input files");
|
||||||
|
|
||||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
if (S->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||||
if (s->outfile && 0!=strcmp("-",s->outfile)) {
|
if (S->outfile && 0!=strcmp("-",S->outfile)) {
|
||||||
ppfp = fopen(s->outfile, "w");
|
ppfp = fopen(S->outfile, "w");
|
||||||
if (!ppfp)
|
if (!ppfp)
|
||||||
tcc_error("could not write '%s'", s->outfile);
|
tcc_error(S, "could not write '%s'", S->outfile);
|
||||||
}
|
}
|
||||||
} else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
|
} else if (S->output_type == TCC_OUTPUT_OBJ && !S->option_r) {
|
||||||
if (s->nb_libraries)
|
if (S->nb_libraries)
|
||||||
tcc_error("cannot specify libraries with -c");
|
tcc_error(S, "cannot specify libraries with -c");
|
||||||
if (s->nb_files > 1 && s->outfile)
|
if (S->nb_files > 1 && S->outfile)
|
||||||
tcc_error("cannot specify output file with -c many files");
|
tcc_error(S, "cannot specify output file with -c many files");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->do_bench)
|
if (S->do_bench)
|
||||||
start_time = getclock_ms();
|
start_time = getclock_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
set_environment(s);
|
set_environment(S);
|
||||||
if (s->output_type == 0)
|
if (S->output_type == 0)
|
||||||
s->output_type = TCC_OUTPUT_EXE;
|
S->output_type = TCC_OUTPUT_EXE;
|
||||||
tcc_set_output_type(s, s->output_type);
|
tcc_set_output_type(S, S->output_type);
|
||||||
s->ppfp = ppfp;
|
S->ppfp = ppfp;
|
||||||
|
|
||||||
if ((s->output_type == TCC_OUTPUT_MEMORY
|
if ((S->output_type == TCC_OUTPUT_MEMORY
|
||||||
|| s->output_type == TCC_OUTPUT_PREPROCESS)
|
|| S->output_type == TCC_OUTPUT_PREPROCESS)
|
||||||
&& (s->dflag & 16)) { /* -dt option */
|
&& (S->dflag & TCC_OPTION_d_t)) { /* -dt option */
|
||||||
if (t)
|
if (t)
|
||||||
s->dflag |= 32;
|
S->dflag |= TCC_OPTION_d_32;
|
||||||
s->run_test = ++t;
|
S->run_test = ++t;
|
||||||
if (n)
|
if (n)
|
||||||
--n;
|
--n;
|
||||||
}
|
}
|
||||||
@ -352,48 +450,48 @@ redo:
|
|||||||
/* compile or add each files or library */
|
/* compile or add each files or library */
|
||||||
first_file = NULL, ret = 0;
|
first_file = NULL, ret = 0;
|
||||||
do {
|
do {
|
||||||
struct filespec *f = s->files[n];
|
struct filespec *f = S->files[n];
|
||||||
s->filetype = f->type;
|
S->filetype = f->type;
|
||||||
if (f->type & AFF_TYPE_LIB) {
|
if (f->type & AFF_TYPE_LIB) {
|
||||||
if (tcc_add_library_err(s, f->name) < 0)
|
if (tcc_add_library_err(S, f->name) < 0)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
} else {
|
} else {
|
||||||
if (1 == s->verbose)
|
if (1 == S->verbose)
|
||||||
printf("-> %s\n", f->name);
|
printf("-> %s\n", f->name);
|
||||||
if (!first_file)
|
if (!first_file)
|
||||||
first_file = f->name;
|
first_file = f->name;
|
||||||
if (tcc_add_file(s, f->name) < 0)
|
if (tcc_add_file(S, f->name) < 0)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
done = ret || ++n >= s->nb_files;
|
done = ret || ++n >= S->nb_files;
|
||||||
} while (!done && (s->output_type != TCC_OUTPUT_OBJ || s->option_r));
|
} while (!done && (S->output_type != TCC_OUTPUT_OBJ || S->option_r));
|
||||||
|
|
||||||
if (s->do_bench)
|
if (S->do_bench)
|
||||||
end_time = getclock_ms();
|
end_time = getclock_ms();
|
||||||
|
|
||||||
if (s->run_test) {
|
if (S->run_test) {
|
||||||
t = 0;
|
t = 0;
|
||||||
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
} else if (S->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||||
;
|
;
|
||||||
} else if (0 == ret) {
|
} else if (0 == ret) {
|
||||||
if (s->output_type == TCC_OUTPUT_MEMORY) {
|
if (S->output_type == TCC_OUTPUT_MEMORY) {
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
ret = tcc_run(s, argc, argv);
|
ret = tcc_run(S, argc, argv);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (!s->outfile)
|
if (!S->outfile)
|
||||||
s->outfile = default_outputfile(s, first_file);
|
S->outfile = default_outputfile(S, first_file);
|
||||||
if (!s->just_deps && tcc_output_file(s, s->outfile))
|
if (!S->just_deps && tcc_output_file(S, S->outfile))
|
||||||
ret = 1;
|
ret = 1;
|
||||||
else if (s->gen_deps)
|
else if (S->gen_deps)
|
||||||
gen_makedeps(s, s->outfile, s->deps_outfile);
|
gen_makedeps(S, S->outfile, S->deps_outfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done && 0 == t && 0 == ret && s->do_bench)
|
if (done && 0 == t && 0 == ret && S->do_bench)
|
||||||
tcc_print_stats(s, end_time - start_time);
|
tcc_print_stats(S, end_time - start_time);
|
||||||
|
|
||||||
tcc_delete(s);
|
tcc_delete(S);
|
||||||
if (!done)
|
if (!done)
|
||||||
goto redo; /* compile more files with -c */
|
goto redo; /* compile more files with -c */
|
||||||
if (t)
|
if (t)
|
||||||
|
745
tcc.h
745
tcc.h
@ -585,7 +585,7 @@ typedef struct Section {
|
|||||||
unsigned long data_offset; /* current data offset */
|
unsigned long data_offset; /* current data offset */
|
||||||
unsigned char *data; /* section data */
|
unsigned char *data; /* section data */
|
||||||
unsigned long data_allocated; /* used for realloc() handling */
|
unsigned long data_allocated; /* used for realloc() handling */
|
||||||
TCCState *s1;
|
TCCState *S;
|
||||||
int sh_name; /* elf section name (only used during output) */
|
int sh_name; /* elf section name (only used during output) */
|
||||||
int sh_num; /* elf section number */
|
int sh_num; /* elf section number */
|
||||||
int sh_type; /* elf section type */
|
int sh_type; /* elf section type */
|
||||||
@ -743,6 +743,78 @@ struct sym_attr {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*From tccpp.c*/
|
||||||
|
typedef struct TinyAlloc {
|
||||||
|
unsigned limit;
|
||||||
|
unsigned size;
|
||||||
|
uint8_t *buffer;
|
||||||
|
uint8_t *p;
|
||||||
|
unsigned nb_allocs;
|
||||||
|
struct TinyAlloc *next, *top;
|
||||||
|
#ifdef TAL_INFO
|
||||||
|
unsigned nb_peak;
|
||||||
|
unsigned nb_total;
|
||||||
|
unsigned nb_missed;
|
||||||
|
uint8_t *peak_p;
|
||||||
|
#endif
|
||||||
|
} TinyAlloc;
|
||||||
|
|
||||||
|
/*From tccgen.c*/
|
||||||
|
typedef struct scope_t {
|
||||||
|
struct scope_t *prev;
|
||||||
|
struct { int loc, locorig, num; } vla;
|
||||||
|
struct { Sym *s; int n; } cl;
|
||||||
|
int *bsym, *csym;
|
||||||
|
Sym *lstk, *llstk;
|
||||||
|
} scope_t;
|
||||||
|
|
||||||
|
typedef struct switch_t {
|
||||||
|
struct case_t {
|
||||||
|
int64_t v1, v2;
|
||||||
|
int sym;
|
||||||
|
} **p; int n; /* list of case ranges */
|
||||||
|
int def_sym; /* default symbol */
|
||||||
|
int *bsym;
|
||||||
|
scope_t *scope;
|
||||||
|
struct switch_t *prev;
|
||||||
|
SValue sv;
|
||||||
|
} switch_t;
|
||||||
|
|
||||||
|
#define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8
|
||||||
|
/*list of temporary local variables on the stack in current function. */
|
||||||
|
typedef struct temp_local_variable_t {
|
||||||
|
int location; //offset on stack. Svalue.c.i
|
||||||
|
short size;
|
||||||
|
short align;
|
||||||
|
} temp_local_variable_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned long last_file_name;
|
||||||
|
unsigned long last_func_name;
|
||||||
|
int ind;
|
||||||
|
int line;
|
||||||
|
} tcov_data_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int debug_type;
|
||||||
|
Sym *type;
|
||||||
|
} debug_hash_t;
|
||||||
|
|
||||||
|
typedef struct debug_info_t {
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
int n_sym;
|
||||||
|
struct debug_sym {
|
||||||
|
int type;
|
||||||
|
unsigned long value;
|
||||||
|
char *str;
|
||||||
|
Section *sec;
|
||||||
|
int sym_index;
|
||||||
|
} *sym;
|
||||||
|
struct debug_info_t *child, *next, *last, *parent;
|
||||||
|
} debug_info_t;
|
||||||
|
|
||||||
struct TCCState {
|
struct TCCState {
|
||||||
unsigned char verbose; /* if true, display some information during compilation */
|
unsigned char verbose; /* if true, display some information during compilation */
|
||||||
unsigned char nostdinc; /* if true, no standard headers are added */
|
unsigned char nostdinc; /* if true, no standard headers are added */
|
||||||
@ -927,11 +999,11 @@ struct TCCState {
|
|||||||
int nb_sym_attrs;
|
int nb_sym_attrs;
|
||||||
/* ptr to next reloc entry reused */
|
/* ptr to next reloc entry reused */
|
||||||
ElfW_Rel *qrel;
|
ElfW_Rel *qrel;
|
||||||
#define qrel s1->qrel
|
#define qrel S->qrel
|
||||||
|
|
||||||
#ifdef TCC_TARGET_RISCV64
|
#ifdef TCC_TARGET_RISCV64
|
||||||
struct pcrel_hi { addr_t addr, val; } last_hi;
|
struct pcrel_hi { addr_t addr, val; } last_hi;
|
||||||
#define last_hi s1->last_hi
|
#define last_hi S->last_hi
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
@ -962,6 +1034,10 @@ struct TCCState {
|
|||||||
const char *runtime_main;
|
const char *runtime_main;
|
||||||
void **runtime_mem;
|
void **runtime_mem;
|
||||||
int nb_runtime_mem;
|
int nb_runtime_mem;
|
||||||
|
# ifdef HAVE_SELINUX
|
||||||
|
void *write_mem;
|
||||||
|
unsigned long mem_size;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
@ -991,6 +1067,117 @@ struct TCCState {
|
|||||||
char *deps_outfile; /* option -MF */
|
char *deps_outfile; /* option -MF */
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
|
|
||||||
|
/* Entries needed to make it reentrant */
|
||||||
|
vio_module_t *vio_module;
|
||||||
|
|
||||||
|
/* ------------ tccpp.c ------------ */
|
||||||
|
|
||||||
|
struct BufferedFile *tccpp_file;
|
||||||
|
int tccpp_ch, tccpp_tok;
|
||||||
|
CValue tccpp_tokc;
|
||||||
|
const int *tccpp_macro_ptr;
|
||||||
|
int tccpp_parse_flags;
|
||||||
|
int tccpp_tok_flags;
|
||||||
|
CString tccpp_tokcstr; /* current parsed string, if any */
|
||||||
|
CString tccpp_cstr_buf;
|
||||||
|
CString tccpp_macro_equal_buf;
|
||||||
|
TokenString tccpp_tokstr_buf;
|
||||||
|
TokenString *tccpp_macro_stack;
|
||||||
|
|
||||||
|
/* display benchmark infos */
|
||||||
|
int tccpp_total_lines;
|
||||||
|
int tccpp_total_bytes;
|
||||||
|
int tccpp_tok_ident;
|
||||||
|
TokenSym **tccpp_table_ident;
|
||||||
|
|
||||||
|
int *tccpp_macro_ptr_allocated;
|
||||||
|
const int *tccpp_unget_saved_macro_ptr;
|
||||||
|
int tccpp_unget_saved_buffer[TOK_MAX_SIZE + 1];
|
||||||
|
int tccpp_unget_buffer_enabled;
|
||||||
|
TokenSym *tccpp_hash_ident[TOK_HASH_SIZE];
|
||||||
|
char tccpp_token_buf[STRING_MAX_SIZE + 1];
|
||||||
|
/* true if isid(c) || isnum(c) */
|
||||||
|
unsigned char tccpp_isidnum_table[256-CH_EOF];
|
||||||
|
|
||||||
|
int tccpp_pp_debug_tok, tccpp_pp_debug_symv;
|
||||||
|
int tccpp_pp_once;
|
||||||
|
int tccpp_pp_expr;
|
||||||
|
int tccpp_pp_counter;
|
||||||
|
|
||||||
|
TinyAlloc *tccpp_toksym_alloc;
|
||||||
|
TinyAlloc *tccpp_tokstr_alloc;
|
||||||
|
|
||||||
|
/*----------- tccasm.c --------*/
|
||||||
|
Section *tccasm_last_text_section; /* to handle .previous asm directive */
|
||||||
|
|
||||||
|
/* ------------ tccgen.c ------------ */
|
||||||
|
|
||||||
|
Sym *tccgen_global_stack;
|
||||||
|
Sym *tccgen_local_stack;
|
||||||
|
Sym *tccgen_local_label_stack;
|
||||||
|
Sym *tccgen_global_label_stack;
|
||||||
|
Sym *tccgen_define_stack;
|
||||||
|
CType tccgen_int_type, tccgen_func_old_type, tccgen_char_type, tccgen_char_pointer_type;
|
||||||
|
SValue *tccgen_vtop;
|
||||||
|
SValue tccgen__vstack[1 + VSTACK_SIZE];
|
||||||
|
int tccgen_rsym, tccgen_anon_sym, tccgen_ind, tccgen_loc;
|
||||||
|
char tccgen_debug_modes;
|
||||||
|
|
||||||
|
int tccgen_const_wanted; /* true if constant wanted */
|
||||||
|
int tccgen_nocode_wanted; /* true if no code generation wanted for an expression */
|
||||||
|
int tccgen_global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
||||||
|
CType tccgen_func_vt; /* current function return type (used by return instruction) */
|
||||||
|
int tccgen_func_var; /* true if current function is variadic */
|
||||||
|
int tccgen_func_vc;
|
||||||
|
const char *tccgen_funcname;
|
||||||
|
|
||||||
|
Sym *tccgen_sym_free_first;
|
||||||
|
void **tccgen_sym_pools;
|
||||||
|
int tccgen_nb_sym_pools;
|
||||||
|
Sym *tccgen_all_cleanups, *tccgen_pending_gotos;
|
||||||
|
int tccgen_local_scope;
|
||||||
|
int tccgen_in_sizeof;
|
||||||
|
int tccgen_in_generic;
|
||||||
|
int tccgen_section_sym;
|
||||||
|
|
||||||
|
int tccgen_last_line_num, tccgen_new_file, tccgen_func_ind; /* debug info control */
|
||||||
|
CString tccgen_initstr;
|
||||||
|
|
||||||
|
switch_t *tccgen_cur_switch; /* current switch */
|
||||||
|
|
||||||
|
temp_local_variable_t tccgen_arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
|
||||||
|
int tccgen_nb_temp_local_vars;
|
||||||
|
|
||||||
|
scope_t *tccgen_cur_scope, *tccgen_loop_scope, *tccgen_root_scope;
|
||||||
|
|
||||||
|
tcov_data_t tccgen_tcov_data;
|
||||||
|
int tccgen_debug_next_type;
|
||||||
|
debug_hash_t *tccgen_debug_hash;
|
||||||
|
int tccgen_n_debug_hash;
|
||||||
|
debug_info_t *tccgen_debug_info, *tccgen_debug_info_root;
|
||||||
|
|
||||||
|
unsigned char tccgen_prec[256];
|
||||||
|
|
||||||
|
/*--------armg-gen.c-----------*/
|
||||||
|
/*#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)*/
|
||||||
|
CType armgen_float_type, armgen_double_type, armgen_func_float_type, armgen_func_double_type;
|
||||||
|
/*#endif*/
|
||||||
|
|
||||||
|
/*------- tccrun.c ------------*/
|
||||||
|
|
||||||
|
/*--------x86_64-gen.c --------*/
|
||||||
|
unsigned long x86_64_gen_func_sub_sp_offset;
|
||||||
|
int x86_64_gen_func_ret_sub;
|
||||||
|
#if defined(CONFIG_TCC_BCHECK)
|
||||||
|
addr_t func_bound_offset;
|
||||||
|
unsigned long func_bound_ind;
|
||||||
|
int func_bound_add_epilog;
|
||||||
|
#endif
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
int x86_64_gen_func_scratch, x86_64_gen_func_alloca;
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct filespec {
|
struct filespec {
|
||||||
@ -1174,7 +1361,7 @@ enum tcc_token {
|
|||||||
|
|
||||||
/* ------------ libtcc.c ------------ */
|
/* ------------ libtcc.c ------------ */
|
||||||
|
|
||||||
ST_DATA struct TCCState *tcc_state;
|
//ST_DATA struct TCCState *S;
|
||||||
|
|
||||||
/* public functions currently used by the tcc main function */
|
/* public functions currently used by the tcc main function */
|
||||||
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s);
|
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s);
|
||||||
@ -1183,53 +1370,56 @@ ST_FUNC char *pstrncpy(char *out, const char *in, size_t num);
|
|||||||
PUB_FUNC char *tcc_basename(const char *name);
|
PUB_FUNC char *tcc_basename(const char *name);
|
||||||
PUB_FUNC char *tcc_fileextension (const char *name);
|
PUB_FUNC char *tcc_fileextension (const char *name);
|
||||||
|
|
||||||
|
PUB_FUNC void tcc_free_base(void *ptr);
|
||||||
|
PUB_FUNC void *tcc_malloc_base(unsigned long size);
|
||||||
|
PUB_FUNC void *tcc_mallocz_base(unsigned long size);
|
||||||
#ifndef MEM_DEBUG
|
#ifndef MEM_DEBUG
|
||||||
PUB_FUNC void tcc_free(void *ptr);
|
PUB_FUNC void tcc_free(TCCState* S, void *ptr);
|
||||||
PUB_FUNC void *tcc_malloc(unsigned long size);
|
PUB_FUNC void *tcc_malloc(TCCState* S, unsigned long size);
|
||||||
PUB_FUNC void *tcc_mallocz(unsigned long size);
|
PUB_FUNC void *tcc_mallocz(TCCState* S, unsigned long size);
|
||||||
PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size);
|
PUB_FUNC void *tcc_realloc(TCCState* S, void *ptr, unsigned long size);
|
||||||
PUB_FUNC char *tcc_strdup(const char *str);
|
PUB_FUNC char *tcc_strdup(TCCState* S, const char *str);
|
||||||
#else
|
#else
|
||||||
#define tcc_free(ptr) tcc_free_debug(ptr)
|
#define tcc_free(s, ptr) tcc_free_debug(s, ptr)
|
||||||
#define tcc_malloc(size) tcc_malloc_debug(size, __FILE__, __LINE__)
|
#define tcc_malloc(s, size) tcc_malloc_debug(s, size, __FILE__, __LINE__)
|
||||||
#define tcc_mallocz(size) tcc_mallocz_debug(size, __FILE__, __LINE__)
|
#define tcc_mallocz(s, size) tcc_mallocz_debug(s, size, __FILE__, __LINE__)
|
||||||
#define tcc_realloc(ptr,size) tcc_realloc_debug(ptr, size, __FILE__, __LINE__)
|
#define tcc_realloc(s, ptr, size) tcc_realloc_debug(s, ptr, size, __FILE__, __LINE__)
|
||||||
#define tcc_strdup(str) tcc_strdup_debug(str, __FILE__, __LINE__)
|
#define tcc_strdup(s, str) tcc_strdup_debug(s, str, __FILE__, __LINE__)
|
||||||
PUB_FUNC void tcc_free_debug(void *ptr);
|
PUB_FUNC void tcc_free_debug(TCCState* S, void *ptr);
|
||||||
PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line);
|
PUB_FUNC void *tcc_malloc_debug(TCCState* S, unsigned long size, const char *file, int line);
|
||||||
PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line);
|
PUB_FUNC void *tcc_mallocz_debug(TCCState* S, unsigned long size, const char *file, int line);
|
||||||
PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line);
|
PUB_FUNC void *tcc_realloc_debug(TCCState* S, void *ptr, unsigned long size, const char *file, int line);
|
||||||
PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
|
PUB_FUNC char *tcc_strdup_debug(TCCState* S, const char *str, const char *file, int line);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define free(p) use_tcc_free(p)
|
#define free(p) use_tcc_free(S, p)
|
||||||
#define malloc(s) use_tcc_malloc(s)
|
#define malloc(s) use_tcc_malloc(S, s)
|
||||||
#define realloc(p, s) use_tcc_realloc(p, s)
|
#define realloc(p, s) use_tcc_realloc(S, p, s)
|
||||||
#undef strdup
|
#undef strdup
|
||||||
#define strdup(s) use_tcc_strdup(s)
|
#define strdup(s) use_tcc_strdup(S, s)
|
||||||
PUB_FUNC void _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2);
|
PUB_FUNC void _tcc_error_noabort(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3);
|
||||||
PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2);
|
PUB_FUNC NORETURN void _tcc_error(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3);
|
||||||
PUB_FUNC void _tcc_warning(const char *fmt, ...) PRINTF_LIKE(1,2);
|
PUB_FUNC void _tcc_warning(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3);
|
||||||
#define tcc_internal_error(msg) tcc_error("internal compiler error\n"\
|
#define tcc_internal_error(S, msg) tcc_error(S, "internal compiler error\n"\
|
||||||
"%s:%d: in %s(): " msg, __FILE__,__LINE__,__FUNCTION__)
|
"%s:%d: in %s(): " msg, __FILE__,__LINE__,__FUNCTION__)
|
||||||
|
|
||||||
/* other utilities */
|
/* other utilities */
|
||||||
ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data);
|
ST_FUNC void dynarray_add(TCCState* S, void *ptab, int *nb_ptr, void *data);
|
||||||
ST_FUNC void dynarray_reset(void *pp, int *n);
|
ST_FUNC void dynarray_reset(TCCState* S, void *pp, int *n);
|
||||||
ST_INLN void cstr_ccat(CString *cstr, int ch);
|
ST_INLN void cstr_ccat(TCCState* S, CString *cstr, int ch);
|
||||||
ST_FUNC void cstr_cat(CString *cstr, const char *str, int len);
|
ST_FUNC void cstr_cat(TCCState* S, CString *cstr, const char *str, int len);
|
||||||
ST_FUNC void cstr_wccat(CString *cstr, int ch);
|
ST_FUNC void cstr_wccat(TCCState* S, CString *cstr, int ch);
|
||||||
ST_FUNC void cstr_new(CString *cstr);
|
ST_FUNC void cstr_new(TCCState* S, CString *cstr);
|
||||||
ST_FUNC void cstr_free(CString *cstr);
|
ST_FUNC void cstr_free(TCCState* S, CString *cstr);
|
||||||
ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3);
|
ST_FUNC int cstr_printf(TCCState* S, CString *cs, const char *fmt, ...) PRINTF_LIKE(3,4);
|
||||||
ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap);
|
ST_FUNC int cstr_vprintf(TCCState* S, CString *cstr, const char *fmt, va_list ap);
|
||||||
ST_FUNC void cstr_reset(CString *cstr);
|
ST_FUNC void cstr_reset(CString *cstr);
|
||||||
|
|
||||||
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
|
ST_FUNC void tcc_open_bf(TCCState *S, const char *filename, int initlen);
|
||||||
ST_FUNC int tcc_open(TCCState *s1, const char *filename);
|
ST_FUNC int tcc_open(TCCState *S, const char *filename);
|
||||||
ST_FUNC void tcc_close(void);
|
ST_FUNC void tcc_close(TCCState *S);
|
||||||
|
|
||||||
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
|
ST_FUNC int tcc_add_file_internal(TCCState *S, const char *filename, int flags);
|
||||||
/* flags: */
|
/* flags: */
|
||||||
#define AFF_PRINT_ERROR 0x10 /* print error if file not found */
|
#define AFF_PRINT_ERROR 0x10 /* print error if file not found */
|
||||||
#define AFF_REFERENCED_DLL 0x20 /* load a referenced dll from another dll */
|
#define AFF_REFERENCED_DLL 0x20 /* load a referenced dll from another dll */
|
||||||
@ -1249,26 +1439,26 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||||||
#define AFF_BINTYPE_C67 4
|
#define AFF_BINTYPE_C67 4
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
|
ST_FUNC int tcc_add_crt(TCCState *S, const char *filename);
|
||||||
#endif
|
#endif
|
||||||
#ifndef TCC_TARGET_MACHO
|
#ifndef TCC_TARGET_MACHO
|
||||||
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
|
ST_FUNC int tcc_add_dll(TCCState *S, const char *filename, int flags);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
ST_FUNC void tcc_add_bcheck(TCCState *s1);
|
ST_FUNC void tcc_add_bcheck(TCCState *S);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
ST_FUNC void tcc_add_btstub(TCCState *s1);
|
ST_FUNC void tcc_add_btstub(TCCState *S);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
|
ST_FUNC void tcc_add_pragma_libs(TCCState *S);
|
||||||
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
|
PUB_FUNC int tcc_add_library_err(TCCState *S, const char *f);
|
||||||
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
PUB_FUNC void tcc_print_stats(TCCState *S, unsigned total_time);
|
||||||
PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
|
PUB_FUNC int tcc_parse_args(TCCState *S, int *argc, char ***argv, int optind);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ST_FUNC char *normalize_slashes(char *path);
|
ST_FUNC char *normalize_slashes(char *path);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname);
|
ST_FUNC DLLReference *tcc_add_dllref(TCCState *S, const char *dllname);
|
||||||
ST_FUNC char *tcc_load_text(int fd);
|
ST_FUNC char *tcc_load_text(TCCState *S, int fd);
|
||||||
|
|
||||||
/* tcc_parse_args return codes: */
|
/* tcc_parse_args return codes: */
|
||||||
#define OPT_HELP 1
|
#define OPT_HELP 1
|
||||||
@ -1282,18 +1472,6 @@ ST_FUNC char *tcc_load_text(int fd);
|
|||||||
|
|
||||||
/* ------------ tccpp.c ------------ */
|
/* ------------ tccpp.c ------------ */
|
||||||
|
|
||||||
ST_DATA struct BufferedFile *file;
|
|
||||||
ST_DATA int ch, tok;
|
|
||||||
ST_DATA CValue tokc;
|
|
||||||
ST_DATA const int *macro_ptr;
|
|
||||||
ST_DATA int parse_flags;
|
|
||||||
ST_DATA int tok_flags;
|
|
||||||
ST_DATA CString tokcstr; /* current parsed string, if any */
|
|
||||||
|
|
||||||
/* display benchmark infos */
|
|
||||||
ST_DATA int tok_ident;
|
|
||||||
ST_DATA TokenSym **table_ident;
|
|
||||||
|
|
||||||
#define TOK_FLAG_BOL 0x0001 /* beginning of line before */
|
#define TOK_FLAG_BOL 0x0001 /* beginning of line before */
|
||||||
#define TOK_FLAG_BOF 0x0002 /* beginning of file before */
|
#define TOK_FLAG_BOF 0x0002 /* beginning of file before */
|
||||||
#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
|
#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
|
||||||
@ -1321,36 +1499,36 @@ enum line_macro_output_format {
|
|||||||
LINE_MACRO_OUTPUT_FORMAT_P10 = 11
|
LINE_MACRO_OUTPUT_FORMAT_P10 = 11
|
||||||
};
|
};
|
||||||
|
|
||||||
ST_FUNC TokenSym *tok_alloc(const char *str, int len);
|
ST_FUNC TokenSym *tok_alloc(TCCState* S, const char *str, int len);
|
||||||
ST_FUNC int tok_alloc_const(const char *str);
|
ST_FUNC int tok_alloc_const(TCCState* S, const char *str);
|
||||||
ST_FUNC const char *get_tok_str(int v, CValue *cv);
|
ST_FUNC const char *get_tok_str(TCCState* S, int v, CValue *cv);
|
||||||
ST_FUNC void begin_macro(TokenString *str, int alloc);
|
ST_FUNC void begin_macro(TCCState* S, TokenString *str, int alloc);
|
||||||
ST_FUNC void end_macro(void);
|
ST_FUNC void end_macro(TCCState* S);
|
||||||
ST_FUNC int set_idnum(int c, int val);
|
ST_FUNC int set_idnum(TCCState* S, int c, int val);
|
||||||
ST_INLN void tok_str_new(TokenString *s);
|
ST_INLN void tok_str_new(TokenString *s);
|
||||||
ST_FUNC TokenString *tok_str_alloc(void);
|
ST_FUNC TokenString *tok_str_alloc(TCCState* S);
|
||||||
ST_FUNC void tok_str_free(TokenString *s);
|
ST_FUNC void tok_str_free(TCCState* S, TokenString *s);
|
||||||
ST_FUNC void tok_str_free_str(int *str);
|
ST_FUNC void tok_str_free_str(TCCState* S, int *str);
|
||||||
ST_FUNC void tok_str_add(TokenString *s, int t);
|
ST_FUNC void tok_str_add(TCCState* S, TokenString *s, int t);
|
||||||
ST_FUNC void tok_str_add_tok(TokenString *s);
|
ST_FUNC void tok_str_add_tok(TCCState* S, TokenString *s);
|
||||||
ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg);
|
ST_INLN void define_push(TCCState* S, int v, int macro_type, int *str, Sym *first_arg);
|
||||||
ST_FUNC void define_undef(Sym *s);
|
ST_FUNC void define_undef(TCCState* S, Sym *s);
|
||||||
ST_INLN Sym *define_find(int v);
|
ST_INLN Sym *define_find(TCCState* S, int v);
|
||||||
ST_FUNC void free_defines(Sym *b);
|
ST_FUNC void free_defines(TCCState* S, Sym *b);
|
||||||
ST_FUNC Sym *label_find(int v);
|
ST_FUNC Sym *label_find(TCCState* S, int v);
|
||||||
ST_FUNC Sym *label_push(Sym **ptop, int v, int flags);
|
ST_FUNC Sym *label_push(TCCState* S, Sym **ptop, int v, int flags);
|
||||||
ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep);
|
ST_FUNC void label_pop(TCCState* S, Sym **ptop, Sym *slast, int keep);
|
||||||
ST_FUNC void parse_define(void);
|
ST_FUNC void parse_define(TCCState* S);
|
||||||
ST_FUNC void preprocess(int is_bof);
|
ST_FUNC void preprocess(TCCState* S, int is_bof);
|
||||||
ST_FUNC void next(void);
|
ST_FUNC void next(TCCState* S);
|
||||||
ST_INLN void unget_tok(int last_tok);
|
ST_INLN void unget_tok(TCCState* S, int last_tok);
|
||||||
ST_FUNC void preprocess_start(TCCState *s1, int filetype);
|
ST_FUNC void preprocess_start(TCCState *S, int filetype);
|
||||||
ST_FUNC void preprocess_end(TCCState *s1);
|
ST_FUNC void preprocess_end(TCCState *S);
|
||||||
ST_FUNC void tccpp_new(TCCState *s);
|
ST_FUNC void tccpp_new(TCCState *S);
|
||||||
ST_FUNC void tccpp_delete(TCCState *s);
|
ST_FUNC void tccpp_delete(TCCState *S);
|
||||||
ST_FUNC int tcc_preprocess(TCCState *s1);
|
ST_FUNC int tcc_preprocess(TCCState *S);
|
||||||
ST_FUNC void skip(int c);
|
ST_FUNC void skip(TCCState* S, int c);
|
||||||
ST_FUNC NORETURN void expect(const char *msg);
|
ST_FUNC NORETURN void expect(TCCState* S, const char *msg);
|
||||||
|
|
||||||
/* space excluding newline */
|
/* space excluding newline */
|
||||||
static inline int is_space(int ch) {
|
static inline int is_space(int ch) {
|
||||||
@ -1372,104 +1550,85 @@ static inline int toup(int c) {
|
|||||||
/* ------------ tccgen.c ------------ */
|
/* ------------ tccgen.c ------------ */
|
||||||
|
|
||||||
#define SYM_POOL_NB (8192 / sizeof(Sym))
|
#define SYM_POOL_NB (8192 / sizeof(Sym))
|
||||||
|
ST_FUNC void tcc_debug_start(TCCState *S);
|
||||||
|
ST_FUNC void tcc_debug_end(TCCState *S);
|
||||||
|
ST_FUNC void tcc_debug_bincl(TCCState *S);
|
||||||
|
ST_FUNC void tcc_debug_eincl(TCCState *S);
|
||||||
|
ST_FUNC void tcc_debug_putfile(TCCState *S, const char *filename);
|
||||||
|
|
||||||
ST_DATA Sym *global_stack;
|
ST_FUNC void tccgen_init(TCCState *S);
|
||||||
ST_DATA Sym *local_stack;
|
ST_FUNC int tccgen_compile(TCCState *S);
|
||||||
ST_DATA Sym *local_label_stack;
|
ST_FUNC void tccgen_finish(TCCState *S);
|
||||||
ST_DATA Sym *global_label_stack;
|
ST_FUNC void check_vstack(TCCState* S);
|
||||||
ST_DATA Sym *define_stack;
|
|
||||||
ST_DATA CType int_type, func_old_type, char_pointer_type;
|
|
||||||
ST_DATA SValue *vtop;
|
|
||||||
ST_DATA int rsym, anon_sym, ind, loc;
|
|
||||||
ST_DATA char debug_modes;
|
|
||||||
|
|
||||||
ST_DATA int const_wanted; /* true if constant wanted */
|
|
||||||
ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
|
|
||||||
ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
|
||||||
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
|
|
||||||
ST_DATA int func_var; /* true if current function is variadic */
|
|
||||||
ST_DATA int func_vc;
|
|
||||||
ST_DATA const char *funcname;
|
|
||||||
|
|
||||||
ST_FUNC void tcc_debug_start(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_debug_end(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_debug_bincl(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_debug_eincl(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename);
|
|
||||||
|
|
||||||
ST_FUNC void tccgen_init(TCCState *s1);
|
|
||||||
ST_FUNC int tccgen_compile(TCCState *s1);
|
|
||||||
ST_FUNC void tccgen_finish(TCCState *s1);
|
|
||||||
ST_FUNC void check_vstack(void);
|
|
||||||
|
|
||||||
ST_INLN int is_float(int t);
|
ST_INLN int is_float(int t);
|
||||||
ST_FUNC int ieee_finite(double d);
|
ST_FUNC int ieee_finite(double d);
|
||||||
ST_FUNC int exact_log2p1(int i);
|
ST_FUNC int exact_log2p1(int i);
|
||||||
ST_FUNC void test_lvalue(void);
|
ST_FUNC void test_lvalue(TCCState* S);
|
||||||
|
|
||||||
ST_FUNC ElfSym *elfsym(Sym *);
|
ST_FUNC ElfSym *elfsym(TCCState* S, Sym *);
|
||||||
ST_FUNC void update_storage(Sym *sym);
|
ST_FUNC void update_storage(TCCState* S, Sym *sym);
|
||||||
ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
|
ST_FUNC void put_extern_sym2(TCCState* S, Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
|
||||||
ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
|
ST_FUNC void put_extern_sym(TCCState* S, Sym *sym, Section *section, addr_t value, unsigned long size);
|
||||||
#if PTR_SIZE == 4
|
#if PTR_SIZE == 4
|
||||||
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);
|
ST_FUNC void greloc(TCCState* S, Section *s, Sym *sym, unsigned long offset, int type);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
ST_FUNC void greloca(TCCState* S, Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
||||||
|
|
||||||
ST_INLN void sym_free(Sym *sym);
|
ST_INLN void sym_free(TCCState* S, Sym *sym);
|
||||||
ST_FUNC Sym *sym_push(int v, CType *type, int r, int c);
|
ST_FUNC Sym *sym_push(TCCState* S, int v, CType *type, int r, int c);
|
||||||
ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
|
ST_FUNC void sym_pop(TCCState* S, Sym **ptop, Sym *b, int keep);
|
||||||
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c);
|
ST_FUNC Sym *sym_push2(TCCState* S, Sym **ps, int v, int t, int c);
|
||||||
ST_FUNC Sym *sym_find2(Sym *s, int v);
|
ST_FUNC Sym *sym_find2(Sym *s, int v);
|
||||||
ST_INLN Sym *sym_find(int v);
|
ST_INLN Sym *sym_find(TCCState* S, int v);
|
||||||
ST_INLN Sym *struct_find(int v);
|
ST_INLN Sym *struct_find(TCCState* S, int v);
|
||||||
|
|
||||||
ST_FUNC Sym *global_identifier_push(int v, int t, int c);
|
ST_FUNC Sym *global_identifier_push(TCCState* S, int v, int t, int c);
|
||||||
ST_FUNC Sym *external_global_sym(int v, CType *type);
|
ST_FUNC Sym *external_global_sym(TCCState* S, int v, CType *type);
|
||||||
ST_FUNC Sym *external_helper_sym(int v);
|
ST_FUNC Sym *external_helper_sym(TCCState* S, int v);
|
||||||
ST_FUNC void vpush_helper_func(int v);
|
ST_FUNC void vpush_helper_func(TCCState* S, int v);
|
||||||
ST_FUNC void vset(CType *type, int r, int v);
|
ST_FUNC void vset(TCCState* S, CType *type, int r, int v);
|
||||||
ST_FUNC void vset_VT_CMP(int op);
|
ST_FUNC void vset_VT_CMP(TCCState* S, int op);
|
||||||
ST_FUNC void vpushi(int v);
|
ST_FUNC void vpushi(TCCState* S, int v);
|
||||||
ST_FUNC void vpushv(SValue *v);
|
ST_FUNC void vpushv(TCCState* S, SValue *v);
|
||||||
ST_FUNC void vpushsym(CType *type, Sym *sym);
|
ST_FUNC void vpushsym(TCCState* S, CType *type, Sym *sym);
|
||||||
ST_FUNC void vswap(void);
|
ST_FUNC void vswap(TCCState* S);
|
||||||
ST_FUNC void vrote(SValue *e, int n);
|
ST_FUNC void vrote(TCCState* S, SValue *e, int n);
|
||||||
ST_FUNC void vrott(int n);
|
ST_FUNC void vrott(TCCState* S, int n);
|
||||||
ST_FUNC void vrotb(int n);
|
ST_FUNC void vrotb(TCCState* S, int n);
|
||||||
ST_FUNC void vpop(void);
|
ST_FUNC void vpop(TCCState* S);
|
||||||
#if PTR_SIZE == 4
|
#if PTR_SIZE == 4
|
||||||
ST_FUNC void lexpand(void);
|
ST_FUNC void lexpand(TCCState* S);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TCC_TARGET_ARM
|
#ifdef TCC_TARGET_ARM
|
||||||
ST_FUNC int get_reg_ex(int rc, int rc2);
|
ST_FUNC int get_reg_ex(TCCState* S, int rc, int rc2);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC void save_reg(int r);
|
ST_FUNC void save_reg(TCCState* S, int r);
|
||||||
ST_FUNC void save_reg_upstack(int r, int n);
|
ST_FUNC void save_reg_upstack(TCCState* S, int r, int n);
|
||||||
ST_FUNC int get_reg(int rc);
|
ST_FUNC int get_reg(TCCState* S, int rc);
|
||||||
ST_FUNC void save_regs(int n);
|
ST_FUNC void save_regs(TCCState* S, int n);
|
||||||
ST_FUNC void gaddrof(void);
|
ST_FUNC void gaddrof(TCCState* S);
|
||||||
ST_FUNC int gv(int rc);
|
ST_FUNC int gv(TCCState* S, int rc);
|
||||||
ST_FUNC void gv2(int rc1, int rc2);
|
ST_FUNC void gv2(TCCState* S, int rc1, int rc2);
|
||||||
ST_FUNC void gen_op(int op);
|
ST_FUNC void gen_op(TCCState* S, int op);
|
||||||
ST_FUNC int type_size(CType *type, int *a);
|
ST_FUNC int type_size(CType *type, int *a);
|
||||||
ST_FUNC void mk_pointer(CType *type);
|
ST_FUNC void mk_pointer(TCCState* S, CType *type);
|
||||||
ST_FUNC void vstore(void);
|
ST_FUNC void vstore(TCCState* S);
|
||||||
ST_FUNC void inc(int post, int c);
|
ST_FUNC void inc(TCCState* S, int post, int c);
|
||||||
ST_FUNC void parse_mult_str (CString *astr, const char *msg);
|
ST_FUNC void parse_mult_str (TCCState* S, CString *astr, const char *msg);
|
||||||
ST_FUNC void parse_asm_str(CString *astr);
|
ST_FUNC void parse_asm_str(TCCState* S, CString *astr);
|
||||||
ST_FUNC void indir(void);
|
ST_FUNC void indir(TCCState* S);
|
||||||
ST_FUNC void unary(void);
|
ST_FUNC void unary(TCCState* S);
|
||||||
ST_FUNC void gexpr(void);
|
ST_FUNC void gexpr(TCCState* S);
|
||||||
ST_FUNC int expr_const(void);
|
ST_FUNC int expr_const(TCCState* S);
|
||||||
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
|
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
|
||||||
ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size);
|
ST_FUNC Sym *get_sym_ref(TCCState* S, CType *type, Section *sec, unsigned long offset, unsigned long size);
|
||||||
#endif
|
#endif
|
||||||
#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
|
#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
|
||||||
ST_FUNC int classify_x86_64_va_arg(CType *ty);
|
ST_FUNC int classify_x86_64_va_arg(CType *ty);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
ST_FUNC void gbound_args(int nb_args);
|
ST_FUNC void gbound_args(TCCState* S, int nb_args);
|
||||||
ST_DATA int func_bound_add_epilog;
|
ST_DATA int func_bound_add_epilog;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1489,51 +1648,51 @@ typedef struct {
|
|||||||
unsigned int n_value; /* value of symbol */
|
unsigned int n_value; /* value of symbol */
|
||||||
} Stab_Sym;
|
} Stab_Sym;
|
||||||
|
|
||||||
ST_FUNC void tccelf_new(TCCState *s);
|
ST_FUNC void tccelf_new(TCCState *S);
|
||||||
ST_FUNC void tccelf_delete(TCCState *s);
|
ST_FUNC void tccelf_delete(TCCState *S);
|
||||||
ST_FUNC void tccelf_stab_new(TCCState *s);
|
ST_FUNC void tccelf_stab_new(TCCState *S);
|
||||||
ST_FUNC void tccelf_begin_file(TCCState *s1);
|
ST_FUNC void tccelf_begin_file(TCCState *S);
|
||||||
ST_FUNC void tccelf_end_file(TCCState *s1);
|
ST_FUNC void tccelf_end_file(TCCState *S);
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
ST_FUNC void tccelf_bounds_new(TCCState *s);
|
ST_FUNC void tccelf_bounds_new(TCCState *S);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
|
ST_FUNC Section *new_section(TCCState *S, const char *name, int sh_type, int sh_flags);
|
||||||
ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
|
ST_FUNC void section_realloc(TCCState* S, Section *sec, unsigned long new_size);
|
||||||
ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
|
ST_FUNC size_t section_add(TCCState* S, Section *sec, addr_t size, int align);
|
||||||
ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
|
ST_FUNC void *section_ptr_add(TCCState* S, Section *sec, addr_t size);
|
||||||
ST_FUNC Section *find_section(TCCState *s1, const char *name);
|
ST_FUNC Section *find_section(TCCState *S, const char *name);
|
||||||
ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
|
ST_FUNC Section *new_symtab(TCCState *S, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
|
||||||
|
|
||||||
ST_FUNC int put_elf_str(Section *s, const char *sym);
|
ST_FUNC int put_elf_str(TCCState* S, Section *s, const char *sym);
|
||||||
ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
ST_FUNC int put_elf_sym(TCCState* S, Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
||||||
ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
ST_FUNC int set_elf_sym(Section *S, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
||||||
ST_FUNC int find_elf_sym(Section *s, const char *name);
|
ST_FUNC int find_elf_sym(Section *S, const char *name);
|
||||||
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);
|
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);
|
||||||
ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend);
|
ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend);
|
||||||
|
|
||||||
ST_FUNC void put_stabs(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value);
|
ST_FUNC void put_stabs(TCCState *S, const char *str, int type, int other, int desc, unsigned long value);
|
||||||
ST_FUNC void put_stabs_r(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index);
|
ST_FUNC void put_stabs_r(TCCState *S, const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index);
|
||||||
ST_FUNC void put_stabn(TCCState *s1, int type, int other, int desc, int value);
|
ST_FUNC void put_stabn(TCCState *S, int type, int other, int desc, int value);
|
||||||
|
|
||||||
ST_FUNC void resolve_common_syms(TCCState *s1);
|
ST_FUNC void resolve_common_syms(TCCState *S);
|
||||||
ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
|
ST_FUNC void relocate_syms(TCCState *S, Section *symtab, int do_resolve);
|
||||||
ST_FUNC void relocate_sections(TCCState *s1);
|
ST_FUNC void relocate_sections(TCCState *S);
|
||||||
|
|
||||||
ST_FUNC ssize_t full_read(int fd, void *buf, size_t count);
|
ST_FUNC ssize_t full_read(int fd, void *buf, size_t count);
|
||||||
ST_FUNC void *load_data(int fd, unsigned long file_offset, unsigned long size);
|
ST_FUNC void *load_data(TCCState* S, int fd, unsigned long file_offset, unsigned long size);
|
||||||
ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);
|
ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);
|
||||||
ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
|
ST_FUNC int tcc_load_object_file(TCCState *S, int fd, unsigned long file_offset);
|
||||||
ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte);
|
ST_FUNC int tcc_load_archive(TCCState *S, int fd, int alacarte);
|
||||||
ST_FUNC void add_array(TCCState *s1, const char *sec, int c);
|
ST_FUNC void add_array(TCCState *S, const char *sec, int c);
|
||||||
|
|
||||||
#if !defined(ELF_OBJ_ONLY) || (defined(TCC_TARGET_MACHO) && defined TCC_IS_NATIVE)
|
#if !defined(ELF_OBJ_ONLY) || (defined(TCC_TARGET_MACHO) && defined TCC_IS_NATIVE)
|
||||||
ST_FUNC void build_got_entries(TCCState *s1);
|
ST_FUNC void build_got_entries(TCCState *S);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);
|
ST_FUNC struct sym_attr *get_sym_attr(TCCState *S, int index, int alloc);
|
||||||
ST_FUNC addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc);
|
ST_FUNC addr_t get_sym_addr(TCCState *S, const char *name, int err, int forc);
|
||||||
ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,
|
ST_FUNC void list_elf_symbols(TCCState *S, void *ctx,
|
||||||
void (*symbol_cb)(void *ctx, const char *name, const void *val));
|
void (*symbol_cb)(void *ctx, const char *name, const void *val));
|
||||||
ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs);
|
ST_FUNC int set_global_sym(TCCState *S, const char *name, Section *sec, addr_t offs);
|
||||||
|
|
||||||
/* Browse each elem of type <type> in section <sec> starting at elem <startoff>
|
/* Browse each elem of type <type> in section <sec> starting at elem <startoff>
|
||||||
using variable <elem> */
|
using variable <elem> */
|
||||||
@ -1542,11 +1701,11 @@ ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t
|
|||||||
elem < (type *) (sec->data + sec->data_offset); elem++)
|
elem < (type *) (sec->data + sec->data_offset); elem++)
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
|
ST_FUNC int tcc_load_dll(TCCState *S, int fd, const char *filename, int level);
|
||||||
ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd);
|
ST_FUNC int tcc_load_ldscript(TCCState *S, int fd);
|
||||||
#endif
|
#endif
|
||||||
#ifndef TCC_TARGET_PE
|
#ifndef TCC_TARGET_PE
|
||||||
ST_FUNC void tcc_add_runtime(TCCState *s1);
|
ST_FUNC void tcc_add_runtime(TCCState *S);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------ xxx-link.c ------------ */
|
/* ------------ xxx-link.c ------------ */
|
||||||
@ -1564,41 +1723,41 @@ enum gotplt_entry {
|
|||||||
ST_FUNC int code_reloc (int reloc_type);
|
ST_FUNC int code_reloc (int reloc_type);
|
||||||
ST_FUNC int gotplt_entry_type (int reloc_type);
|
ST_FUNC int gotplt_entry_type (int reloc_type);
|
||||||
#if !defined(TCC_TARGET_MACHO) || defined TCC_IS_NATIVE
|
#if !defined(TCC_TARGET_MACHO) || defined TCC_IS_NATIVE
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
|
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr);
|
||||||
ST_FUNC void relocate_plt(TCCState *s1);
|
ST_FUNC void relocate_plt(TCCState *S);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
|
||||||
|
|
||||||
/* ------------ xxx-gen.c ------------ */
|
/* ------------ xxx-gen.c ------------ */
|
||||||
ST_DATA const char * const 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(TCCState* S, int t, int a);
|
||||||
ST_FUNC void gsym(int t);
|
ST_FUNC void gsym(TCCState* S, int t);
|
||||||
ST_FUNC void load(int r, SValue *sv);
|
ST_FUNC void load(TCCState *S, int r, SValue *sv);
|
||||||
ST_FUNC void store(int r, SValue *v);
|
ST_FUNC void store(TCCState *S, int r, SValue *v);
|
||||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
|
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
|
||||||
ST_FUNC void gfunc_call(int nb_args);
|
ST_FUNC void gfunc_call(TCCState *S, int nb_args);
|
||||||
ST_FUNC void gfunc_prolog(Sym *func_sym);
|
ST_FUNC void gfunc_prolog(TCCState *S, Sym *func_sym);
|
||||||
ST_FUNC void gfunc_epilog(void);
|
ST_FUNC void gfunc_epilog(TCCState *S);
|
||||||
ST_FUNC void gen_fill_nops(int);
|
ST_FUNC void gen_fill_nops(TCCState* S, int);
|
||||||
ST_FUNC int gjmp(int t);
|
ST_FUNC int gjmp(TCCState* S, int t);
|
||||||
ST_FUNC void gjmp_addr(int a);
|
ST_FUNC void gjmp_addr(TCCState* S, int a);
|
||||||
ST_FUNC int gjmp_cond(int op, int t);
|
ST_FUNC int gjmp_cond(TCCState* S, int op, int t);
|
||||||
ST_FUNC int gjmp_append(int n, int t);
|
ST_FUNC int gjmp_append(TCCState *S, int n, int t);
|
||||||
ST_FUNC void gen_opi(int op);
|
ST_FUNC void gen_opi(TCCState* S, int op);
|
||||||
ST_FUNC void gen_opf(int op);
|
ST_FUNC void gen_opf(TCCState* S, int op);
|
||||||
ST_FUNC void gen_cvt_ftoi(int t);
|
ST_FUNC void gen_cvt_ftoi(TCCState *S, int t);
|
||||||
ST_FUNC void gen_cvt_itof(int t);
|
ST_FUNC void gen_cvt_itof(TCCState *S, int t);
|
||||||
ST_FUNC void gen_cvt_ftof(int t);
|
ST_FUNC void gen_cvt_ftof(TCCState *S, int t);
|
||||||
ST_FUNC void ggoto(void);
|
ST_FUNC void ggoto(TCCState *S);
|
||||||
#ifndef TCC_TARGET_C67
|
#ifndef TCC_TARGET_C67
|
||||||
ST_FUNC void o(unsigned int c);
|
ST_FUNC void o(TCCState* S, unsigned int c);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC void gen_vla_sp_save(int addr);
|
ST_FUNC void gen_vla_sp_save(TCCState* S, int addr);
|
||||||
ST_FUNC void gen_vla_sp_restore(int addr);
|
ST_FUNC void gen_vla_sp_restore(TCCState* S, int addr);
|
||||||
ST_FUNC void gen_vla_alloc(CType *type, int align);
|
ST_FUNC void gen_vla_alloc(TCCState* S, CType *type, int align);
|
||||||
|
|
||||||
static inline uint16_t read16le(unsigned char *p) {
|
static inline uint16_t read16le(unsigned char *p) {
|
||||||
return p[0] | (uint16_t)p[1] << 8;
|
return p[0] | (uint16_t)p[1] << 8;
|
||||||
@ -1627,57 +1786,57 @@ static inline void add64le(unsigned char *p, int64_t x) {
|
|||||||
|
|
||||||
/* ------------ i386-gen.c ------------ */
|
/* ------------ i386-gen.c ------------ */
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
|
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
|
||||||
ST_FUNC void g(int c);
|
ST_FUNC void g(TCCState* S, int c);
|
||||||
ST_FUNC void gen_le16(int c);
|
ST_FUNC void gen_le16(TCCState* S, int c);
|
||||||
ST_FUNC void gen_le32(int c);
|
ST_FUNC void gen_le32(TCCState* S, int c);
|
||||||
#endif
|
#endif
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||||
ST_FUNC void gen_addr32(int r, Sym *sym, int c);
|
ST_FUNC void gen_addr32(TCCState* S, int r, Sym *sym, int c);
|
||||||
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);
|
ST_FUNC void gen_addrpc32(TCCState* S, int r, Sym *sym, int c);
|
||||||
ST_FUNC void gen_cvt_csti(int t);
|
ST_FUNC void gen_cvt_csti(TCCState* S, int t);
|
||||||
ST_FUNC void gen_increment_tcov (SValue *sv);
|
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------ x86_64-gen.c ------------ */
|
/* ------------ x86_64-gen.c ------------ */
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c);
|
ST_FUNC void gen_addr64(TCCState* S, int r, Sym *sym, int64_t c);
|
||||||
ST_FUNC void gen_opl(int op);
|
ST_FUNC void gen_opl(TCCState* S, int op);
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
ST_FUNC void gen_vla_result(int addr);
|
ST_FUNC void gen_vla_result(TCCState* S, int addr);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC void gen_cvt_sxtw(void);
|
ST_FUNC void gen_cvt_sxtw(TCCState *S);
|
||||||
ST_FUNC void gen_cvt_csti(int t);
|
ST_FUNC void gen_cvt_csti(TCCState* S, int t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------ arm-gen.c ------------ */
|
/* ------------ arm-gen.c ------------ */
|
||||||
#ifdef TCC_TARGET_ARM
|
#ifdef TCC_TARGET_ARM
|
||||||
#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP)
|
#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP)
|
||||||
PUB_FUNC const char *default_elfinterp(struct TCCState *s);
|
PUB_FUNC const char *default_elfinterp(TCCState *S);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC void arm_init(struct TCCState *s);
|
ST_FUNC void arm_init(TCCState *S);
|
||||||
ST_FUNC void gen_increment_tcov (SValue *sv);
|
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------ arm64-gen.c ------------ */
|
/* ------------ arm64-gen.c ------------ */
|
||||||
#ifdef TCC_TARGET_ARM64
|
#ifdef TCC_TARGET_ARM64
|
||||||
ST_FUNC void gen_opl(int op);
|
ST_FUNC void gen_opl(TCCState* S, int op);
|
||||||
ST_FUNC void gfunc_return(CType *func_type);
|
ST_FUNC void gfunc_return(TCCState *S, CType *func_type);
|
||||||
ST_FUNC void gen_va_start(void);
|
ST_FUNC void gen_va_start(TCCState *S);
|
||||||
ST_FUNC void gen_va_arg(CType *t);
|
ST_FUNC void gen_va_arg(TCCState *S, CType *t);
|
||||||
ST_FUNC void gen_clear_cache(void);
|
ST_FUNC void gen_clear_cache(TCCState *S);
|
||||||
ST_FUNC void gen_cvt_sxtw(void);
|
ST_FUNC void gen_cvt_sxtw(TCCState *S);
|
||||||
ST_FUNC void gen_cvt_csti(int t);
|
ST_FUNC void gen_cvt_csti(TCCState *S, int t);
|
||||||
ST_FUNC void gen_increment_tcov (SValue *sv);
|
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------ riscv64-gen.c ------------ */
|
/* ------------ riscv64-gen.c ------------ */
|
||||||
#ifdef TCC_TARGET_RISCV64
|
#ifdef TCC_TARGET_RISCV64
|
||||||
ST_FUNC void gen_opl(int op);
|
ST_FUNC void gen_opl(TCCState* S, int op);
|
||||||
//ST_FUNC void gfunc_return(CType *func_type);
|
//ST_FUNC void gfunc_return(TCCState *S, CType *func_type);
|
||||||
ST_FUNC void gen_va_start(void);
|
ST_FUNC void gen_va_start(TCCState *S);
|
||||||
ST_FUNC void arch_transfer_ret_regs(int);
|
ST_FUNC void arch_transfer_ret_regs(TCCState* S, int);
|
||||||
ST_FUNC void gen_cvt_sxtw(void);
|
ST_FUNC void gen_cvt_sxtw(TCCState *S);
|
||||||
ST_FUNC void gen_increment_tcov (SValue *sv);
|
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------ c67-gen.c ------------ */
|
/* ------------ c67-gen.c ------------ */
|
||||||
@ -1687,44 +1846,44 @@ ST_FUNC void gen_increment_tcov (SValue *sv);
|
|||||||
/* ------------ tcccoff.c ------------ */
|
/* ------------ tcccoff.c ------------ */
|
||||||
|
|
||||||
#ifdef TCC_TARGET_COFF
|
#ifdef TCC_TARGET_COFF
|
||||||
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f);
|
ST_FUNC int tcc_output_coff(TCCState *S, FILE *f);
|
||||||
ST_FUNC int tcc_load_coff(TCCState * s1, int fd);
|
ST_FUNC int tcc_load_coff(TCCState *S, int fd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------ tccasm.c ------------ */
|
/* ------------ tccasm.c ------------ */
|
||||||
ST_FUNC void asm_instr(void);
|
ST_FUNC void asm_instr(TCCState* S);
|
||||||
ST_FUNC void asm_global_instr(void);
|
ST_FUNC void asm_global_instr(TCCState* S);
|
||||||
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess);
|
ST_FUNC int tcc_assemble(TCCState *S, int do_preprocess);
|
||||||
#ifdef CONFIG_TCC_ASM
|
#ifdef CONFIG_TCC_ASM
|
||||||
ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
|
ST_FUNC int find_constraint(TCCState* S, ASMOperand *operands, int nb_operands, const char *name, const char **pp);
|
||||||
ST_FUNC Sym* get_asm_sym(int name, Sym *csym);
|
ST_FUNC Sym* get_asm_sym(TCCState* S, int name, Sym *csym);
|
||||||
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
|
ST_FUNC void asm_expr(TCCState *S, ExprValue *pe);
|
||||||
ST_FUNC int asm_int_expr(TCCState *s1);
|
ST_FUNC int asm_int_expr(TCCState *S);
|
||||||
/* ------------ i386-asm.c ------------ */
|
/* ------------ i386-asm.c ------------ */
|
||||||
ST_FUNC void gen_expr32(ExprValue *pe);
|
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe);
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
ST_FUNC void gen_expr64(ExprValue *pe);
|
ST_FUNC void gen_expr64(TCCState* S, ExprValue *pe);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC void asm_opcode(TCCState *s1, int opcode);
|
ST_FUNC void asm_opcode(TCCState *S, int opcode);
|
||||||
ST_FUNC int asm_parse_regvar(int t);
|
ST_FUNC int asm_parse_regvar(TCCState* S, int t);
|
||||||
ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
|
ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
|
||||||
ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
|
ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str, SValue *sv, int modifier);
|
||||||
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
|
ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
|
||||||
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
|
ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------ tccpe.c -------------- */
|
/* ------------ tccpe.c -------------- */
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename);
|
ST_FUNC int pe_load_file(struct TCCState *S, int fd, const char *filename);
|
||||||
ST_FUNC int pe_output_file(TCCState * s1, const char *filename);
|
ST_FUNC int pe_output_file(TCCState * S, const char *filename);
|
||||||
ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value);
|
ST_FUNC int pe_putimport(TCCState *S, int dllindex, const char *name, addr_t value);
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||||
ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
|
ST_FUNC SValue *pe_getimport(TCCState * S, SValue *sv, SValue *v2);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
|
ST_FUNC void pe_add_unwind_data(TCCState* S, unsigned start, unsigned end, unsigned stack);
|
||||||
#endif
|
#endif
|
||||||
PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp);
|
PUB_FUNC int tcc_get_dllexports(TCCState* S, const char *filename, char **pp);
|
||||||
/* symbol properties stored in Elf32_Sym->st_other */
|
/* symbol properties stored in Elf32_Sym->st_other */
|
||||||
# define ST_PE_EXPORT 0x10
|
# define ST_PE_EXPORT 0x10
|
||||||
# define ST_PE_IMPORT 0x20
|
# define ST_PE_IMPORT 0x20
|
||||||
@ -1734,11 +1893,11 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp);
|
|||||||
|
|
||||||
/* ------------ tccmacho.c ----------------- */
|
/* ------------ tccmacho.c ----------------- */
|
||||||
#ifdef TCC_TARGET_MACHO
|
#ifdef TCC_TARGET_MACHO
|
||||||
ST_FUNC int macho_output_file(TCCState * s1, const char *filename);
|
ST_FUNC int macho_output_file(TCCState * S, const char *filename);
|
||||||
ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev);
|
ST_FUNC int macho_load_dll(TCCState *S, int fd, const char *filename, int lev);
|
||||||
ST_FUNC int macho_load_tbd(TCCState *s1, int fd, const char *filename, int lev);
|
ST_FUNC int macho_load_tbd(TCCState *S, int fd, const char *filename, int lev);
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
ST_FUNC void tcc_add_macos_sdkpath(TCCState* s);
|
ST_FUNC void tcc_add_macos_sdkpath(TCCState* S);
|
||||||
ST_FUNC const char* macho_tbd_soname(const char* filename);
|
ST_FUNC const char* macho_tbd_soname(const char* filename);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -1755,17 +1914,17 @@ ST_FUNC void dlclose(void *p);
|
|||||||
ST_FUNC const char *dlerror(void);
|
ST_FUNC const char *dlerror(void);
|
||||||
ST_FUNC void *dlsym(void *handle, const char *symbol);
|
ST_FUNC void *dlsym(void *handle, const char *symbol);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC void tcc_run_free(TCCState *s1);
|
ST_FUNC void tcc_run_free(TCCState *S);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------ tcctools.c ----------------- */
|
/* ------------ tcctools.c ----------------- */
|
||||||
#if 0 /* included in tcc.c */
|
#if 0 /* included in tcc.c */
|
||||||
ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv);
|
ST_FUNC int tcc_tool_ar(TCCState *S, int argc, char **argv);
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv);
|
ST_FUNC int tcc_tool_impdef(TCCState *S, int argc, char **argv);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option);
|
ST_FUNC void tcc_tool_cross(TCCState *S, char **argv, int option);
|
||||||
ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename);
|
ST_FUNC void gen_makedeps(TCCState *S, const char *target, const char *filename);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
@ -1820,12 +1979,12 @@ ST_FUNC void post_sem(TCCSem *p);
|
|||||||
#define total_lines TCC_STATE_VAR(total_lines)
|
#define total_lines TCC_STATE_VAR(total_lines)
|
||||||
#define total_bytes TCC_STATE_VAR(total_bytes)
|
#define total_bytes TCC_STATE_VAR(total_bytes)
|
||||||
|
|
||||||
PUB_FUNC void tcc_enter_state(TCCState *s1);
|
PUB_FUNC void tcc_enter_state(TCCState *S);
|
||||||
PUB_FUNC void tcc_exit_state(TCCState *s1);
|
PUB_FUNC void tcc_exit_state(TCCState *S);
|
||||||
|
|
||||||
/* conditional warning depending on switch */
|
/* conditional warning depending on switch */
|
||||||
#define tcc_warning_c(sw) TCC_SET_STATE((\
|
#define tcc_warning_c(sw) TCC_SET_STATE((\
|
||||||
tcc_state->warn_num = offsetof(TCCState, sw) \
|
S->warn_num = offsetof(TCCState, sw) \
|
||||||
- offsetof(TCCState, warn_none), _tcc_warning))
|
- offsetof(TCCState, warn_none), _tcc_warning))
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
@ -1835,10 +1994,10 @@ PUB_FUNC void tcc_exit_state(TCCState *s1);
|
|||||||
#undef TCC_SET_STATE
|
#undef TCC_SET_STATE
|
||||||
|
|
||||||
#ifdef USING_GLOBALS
|
#ifdef USING_GLOBALS
|
||||||
# define TCC_STATE_VAR(sym) tcc_state->sym
|
# define TCC_STATE_VAR(sym) S->sym
|
||||||
# define TCC_SET_STATE(fn) fn
|
# define TCC_SET_STATE(fn) fn
|
||||||
# undef USING_GLOBALS
|
# undef USING_GLOBALS
|
||||||
#else
|
#else
|
||||||
# define TCC_STATE_VAR(sym) s1->sym
|
# define TCC_STATE_VAR(sym) S->sym
|
||||||
# define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn)
|
# define TCC_SET_STATE(fn) (tcc_enter_state(S),fn)
|
||||||
#endif
|
#endif
|
||||||
|
116
tcccoff.c
116
tcccoff.c
@ -40,12 +40,12 @@ int FuncEntries[MAX_FUNCS];
|
|||||||
|
|
||||||
int OutputTheSection(Section * sect);
|
int OutputTheSection(Section * sect);
|
||||||
short int GetCoffFlags(const char *s);
|
short int GetCoffFlags(const char *s);
|
||||||
void SortSymbolTable(TCCState *s1);
|
void SortSymbolTable(TCCState *S);
|
||||||
Section *FindSection(TCCState * s1, const char *sname);
|
Section *FindSection(TCCState * S, const char *sname);
|
||||||
|
|
||||||
int C67_main_entry_point;
|
int C67_main_entry_point;
|
||||||
|
|
||||||
int FindCoffSymbolIndex(TCCState * s1, const char *func_name);
|
int FindCoffSymbolIndex(TCCState * S, const char *func_name);
|
||||||
int nb_syms;
|
int nb_syms;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -74,7 +74,7 @@ typedef struct {
|
|||||||
unsigned short dummy4;
|
unsigned short dummy4;
|
||||||
} AUXEF;
|
} AUXEF;
|
||||||
|
|
||||||
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
|
||||||
{
|
{
|
||||||
Section *tcc_sect;
|
Section *tcc_sect;
|
||||||
SCNHDR *coff_sec;
|
SCNHDR *coff_sec;
|
||||||
@ -87,12 +87,12 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
|
|
||||||
Coff_str_table = pCoff_str_table = NULL;
|
Coff_str_table = pCoff_str_table = NULL;
|
||||||
|
|
||||||
stext = FindSection(s1, ".text");
|
stext = FindSection(S, ".text");
|
||||||
sdata = FindSection(s1, ".data");
|
sdata = FindSection(S, ".data");
|
||||||
sbss = FindSection(s1, ".bss");
|
sbss = FindSection(S, ".bss");
|
||||||
|
|
||||||
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
|
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
|
||||||
coff_nb_syms = FindCoffSymbolIndex(s1, "XXXXXXXXXX1");
|
coff_nb_syms = FindCoffSymbolIndex(S, "XXXXXXXXXX1");
|
||||||
|
|
||||||
file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
|
file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
|
||||||
file_hdr.f_timdat = 0; /* time & date stamp */
|
file_hdr.f_timdat = 0; /* time & date stamp */
|
||||||
@ -116,9 +116,9 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
|
|
||||||
CoffTextSectionNo = -1;
|
CoffTextSectionNo = -1;
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < S->nb_sections; i++) {
|
||||||
coff_sec = §ion_header[i];
|
coff_sec = §ion_header[i];
|
||||||
tcc_sect = s1->sections[i];
|
tcc_sect = S->sections[i];
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
if (OutputTheSection(tcc_sect)) {
|
||||||
NSectionsToOutput++;
|
NSectionsToOutput++;
|
||||||
@ -149,9 +149,9 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
// for the raw data
|
// for the raw data
|
||||||
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < S->nb_sections; i++) {
|
||||||
coff_sec = §ion_header[i];
|
coff_sec = §ion_header[i];
|
||||||
tcc_sect = s1->sections[i];
|
tcc_sect = S->sections[i];
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
if (OutputTheSection(tcc_sect)) {
|
||||||
// put raw data
|
// put raw data
|
||||||
@ -163,9 +163,9 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
// now loop through and determine file pointer locations
|
// now loop through and determine file pointer locations
|
||||||
// for the relocation data
|
// for the relocation data
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < S->nb_sections; i++) {
|
||||||
coff_sec = §ion_header[i];
|
coff_sec = §ion_header[i];
|
||||||
tcc_sect = s1->sections[i];
|
tcc_sect = S->sections[i];
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
if (OutputTheSection(tcc_sect)) {
|
||||||
// put relocations data
|
// put relocations data
|
||||||
@ -179,14 +179,14 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
// now loop through and determine file pointer locations
|
// now loop through and determine file pointer locations
|
||||||
// for the line number data
|
// for the line number data
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < S->nb_sections; i++) {
|
||||||
coff_sec = §ion_header[i];
|
coff_sec = §ion_header[i];
|
||||||
tcc_sect = s1->sections[i];
|
tcc_sect = S->sections[i];
|
||||||
|
|
||||||
coff_sec->s_nlnno = 0;
|
coff_sec->s_nlnno = 0;
|
||||||
coff_sec->s_lnnoptr = 0;
|
coff_sec->s_lnnoptr = 0;
|
||||||
|
|
||||||
if (s1->do_debug && tcc_sect == stext) {
|
if (S->do_debug && tcc_sect == stext) {
|
||||||
// count how many line nos data
|
// count how many line nos data
|
||||||
|
|
||||||
// also find association between source file name and function
|
// also find association between source file name and function
|
||||||
@ -314,7 +314,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
|
|
||||||
file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
|
file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
|
||||||
|
|
||||||
if (s1->do_debug)
|
if (S->do_debug)
|
||||||
file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */
|
file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */
|
||||||
else
|
else
|
||||||
file_hdr.f_nsyms = 0;
|
file_hdr.f_nsyms = 0;
|
||||||
@ -328,9 +328,9 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
|
fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
|
||||||
|
|
||||||
// write section headers
|
// write section headers
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < S->nb_sections; i++) {
|
||||||
coff_sec = §ion_header[i];
|
coff_sec = §ion_header[i];
|
||||||
tcc_sect = s1->sections[i];
|
tcc_sect = S->sections[i];
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
if (OutputTheSection(tcc_sect)) {
|
||||||
fwrite(coff_sec, sizeof(SCNHDR), 1, f);
|
fwrite(coff_sec, sizeof(SCNHDR), 1, f);
|
||||||
@ -338,9 +338,9 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write raw data
|
// write raw data
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < S->nb_sections; i++) {
|
||||||
coff_sec = §ion_header[i];
|
coff_sec = §ion_header[i];
|
||||||
tcc_sect = s1->sections[i];
|
tcc_sect = S->sections[i];
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
if (OutputTheSection(tcc_sect)) {
|
||||||
fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
|
fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
|
||||||
@ -348,9 +348,9 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write relocation data
|
// write relocation data
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < S->nb_sections; i++) {
|
||||||
coff_sec = §ion_header[i];
|
coff_sec = §ion_header[i];
|
||||||
tcc_sect = s1->sections[i];
|
tcc_sect = S->sections[i];
|
||||||
|
|
||||||
if (OutputTheSection(tcc_sect)) {
|
if (OutputTheSection(tcc_sect)) {
|
||||||
// put relocations data
|
// put relocations data
|
||||||
@ -365,16 +365,16 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
// group the symbols in order of filename, func1, func2, etc
|
// group the symbols in order of filename, func1, func2, etc
|
||||||
// finally global symbols
|
// finally global symbols
|
||||||
|
|
||||||
if (s1->do_debug)
|
if (S->do_debug)
|
||||||
SortSymbolTable(s1);
|
SortSymbolTable(S);
|
||||||
|
|
||||||
// write line no data
|
// write line no data
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < S->nb_sections; i++) {
|
||||||
coff_sec = §ion_header[i];
|
coff_sec = §ion_header[i];
|
||||||
tcc_sect = s1->sections[i];
|
tcc_sect = S->sections[i];
|
||||||
|
|
||||||
if (s1->do_debug && tcc_sect == stext) {
|
if (S->do_debug && tcc_sect == stext) {
|
||||||
// count how many line nos data
|
// count how many line nos data
|
||||||
|
|
||||||
|
|
||||||
@ -437,7 +437,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
// output a function begin
|
// output a function begin
|
||||||
|
|
||||||
CoffLineNo.l_addr.l_symndx =
|
CoffLineNo.l_addr.l_symndx =
|
||||||
FindCoffSymbolIndex(s1, func_name);
|
FindCoffSymbolIndex(S, func_name);
|
||||||
CoffLineNo.l_lnno = 0;
|
CoffLineNo.l_lnno = 0;
|
||||||
|
|
||||||
fwrite(&CoffLineNo, 6, 1, f);
|
fwrite(&CoffLineNo, 6, 1, f);
|
||||||
@ -502,7 +502,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write symbol table
|
// write symbol table
|
||||||
if (s1->do_debug) {
|
if (S->do_debug) {
|
||||||
int k;
|
int k;
|
||||||
struct syment csym;
|
struct syment csym;
|
||||||
AUXFUNC auxfunc;
|
AUXFUNC auxfunc;
|
||||||
@ -514,7 +514,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
int nstr;
|
int nstr;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE);
|
Coff_str_table = (char *) tcc_malloc(S, MAX_STR_TABLE);
|
||||||
pCoff_str_table = Coff_str_table;
|
pCoff_str_table = Coff_str_table;
|
||||||
nstr = 0;
|
nstr = 0;
|
||||||
|
|
||||||
@ -533,7 +533,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
} else {
|
} else {
|
||||||
if (pCoff_str_table - Coff_str_table + strlen(name) >
|
if (pCoff_str_table - Coff_str_table + strlen(name) >
|
||||||
MAX_STR_TABLE - 1)
|
MAX_STR_TABLE - 1)
|
||||||
tcc_error("String table too large");
|
tcc_error(S, "String table too large");
|
||||||
|
|
||||||
csym._n._n_n._n_zeroes = 0;
|
csym._n._n_n._n_zeroes = 0;
|
||||||
csym._n._n_n._n_offset =
|
csym._n._n_n._n_offset =
|
||||||
@ -563,7 +563,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (k >= nFuncs) {
|
if (k >= nFuncs) {
|
||||||
tcc_error("debug info can't find function: %s", name);
|
tcc_error(S, "debug info can't find function: %s", name);
|
||||||
}
|
}
|
||||||
// put a Function Name
|
// put a Function Name
|
||||||
|
|
||||||
@ -669,7 +669,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->do_debug) {
|
if (S->do_debug) {
|
||||||
// write string table
|
// write string table
|
||||||
|
|
||||||
// first write the size
|
// first write the size
|
||||||
@ -679,7 +679,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
// then write the strings
|
// then write the strings
|
||||||
fwrite(Coff_str_table, i, 1, f);
|
fwrite(Coff_str_table, i, 1, f);
|
||||||
|
|
||||||
tcc_free(Coff_str_table);
|
tcc_free(S, Coff_str_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -690,13 +690,13 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
|
|||||||
// group the symbols in order of filename, func1, func2, etc
|
// group the symbols in order of filename, func1, func2, etc
|
||||||
// finally global symbols
|
// finally global symbols
|
||||||
|
|
||||||
void SortSymbolTable(TCCState *s1)
|
void SortSymbolTable(TCCState *S)
|
||||||
{
|
{
|
||||||
int i, j, k, n = 0;
|
int i, j, k, n = 0;
|
||||||
Elf32_Sym *p, *p2, *NewTable;
|
Elf32_Sym *p, *p2, *NewTable;
|
||||||
char *name, *name2;
|
char *name, *name2;
|
||||||
|
|
||||||
NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
|
NewTable = (Elf32_Sym *) tcc_malloc(S, nb_syms * sizeof(Elf32_Sym));
|
||||||
|
|
||||||
p = (Elf32_Sym *) symtab_section->data;
|
p = (Elf32_Sym *) symtab_section->data;
|
||||||
|
|
||||||
@ -730,7 +730,7 @@ void SortSymbolTable(TCCState *s1)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (k >= nFuncs) {
|
if (k >= nFuncs) {
|
||||||
tcc_error("debug (sort) info can't find function: %s", name2);
|
tcc_error(S, "debug (sort) info can't find function: %s", name2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(AssociatedFile[k], name) == 0) {
|
if (strcmp(AssociatedFile[k], name) == 0) {
|
||||||
@ -757,7 +757,7 @@ void SortSymbolTable(TCCState *s1)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (n != nb_syms)
|
if (n != nb_syms)
|
||||||
tcc_error("Internal Compiler error, debug info");
|
tcc_error(S, "Internal Compiler error, debug info");
|
||||||
|
|
||||||
// copy it all back
|
// copy it all back
|
||||||
|
|
||||||
@ -766,11 +766,11 @@ void SortSymbolTable(TCCState *s1)
|
|||||||
*p++ = NewTable[i];
|
*p++ = NewTable[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
tcc_free(NewTable);
|
tcc_free(S, NewTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int FindCoffSymbolIndex(TCCState *s1, const char *func_name)
|
int FindCoffSymbolIndex(TCCState *S, const char *func_name)
|
||||||
{
|
{
|
||||||
int i, n = 0;
|
int i, n = 0;
|
||||||
Elf32_Sym *p;
|
Elf32_Sym *p;
|
||||||
@ -842,23 +842,23 @@ short int GetCoffFlags(const char *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Section *FindSection(TCCState * s1, const char *sname)
|
Section *FindSection(TCCState * S, const char *sname)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < S->nb_sections; i++) {
|
||||||
s = s1->sections[i];
|
s = S->sections[i];
|
||||||
|
|
||||||
if (!strcmp(sname, s->name))
|
if (!strcmp(sname, s->name))
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcc_error("could not find section %s", sname);
|
tcc_error(S, "could not find section %s", sname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
|
ST_FUNC int tcc_load_coff(TCCState * S, int fd)
|
||||||
{
|
{
|
||||||
// tktk TokenSym *ts;
|
// tktk TokenSym *ts;
|
||||||
|
|
||||||
@ -872,39 +872,39 @@ ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
|
|||||||
|
|
||||||
f = fdopen(fd, "rb");
|
f = fdopen(fd, "rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
tcc_error("Unable to open .out file for input");
|
tcc_error(S, "Unable to open .out file for input");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fread(&file_hdr, FILHSZ, 1, f) != 1)
|
if (fread(&file_hdr, FILHSZ, 1, f) != 1)
|
||||||
tcc_error("error reading .out file for input");
|
tcc_error(S, "error reading .out file for input");
|
||||||
|
|
||||||
if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
|
if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
|
||||||
tcc_error("error reading .out file for input");
|
tcc_error(S, "error reading .out file for input");
|
||||||
|
|
||||||
// first read the string table
|
// first read the string table
|
||||||
|
|
||||||
if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
|
if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
|
||||||
tcc_error("error reading .out file for input");
|
tcc_error(S, "error reading .out file for input");
|
||||||
|
|
||||||
if (fread(&str_size, sizeof(int), 1, f) != 1)
|
if (fread(&str_size, sizeof(int), 1, f) != 1)
|
||||||
tcc_error("error reading .out file for input");
|
tcc_error(S, "error reading .out file for input");
|
||||||
|
|
||||||
|
|
||||||
Coff_str_table = (char *) tcc_malloc(str_size);
|
Coff_str_table = (char *) tcc_malloc(S, str_size);
|
||||||
|
|
||||||
if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
|
if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
|
||||||
tcc_error("error reading .out file for input");
|
tcc_error(S, "error reading .out file for input");
|
||||||
|
|
||||||
// read/process all the symbols
|
// read/process all the symbols
|
||||||
|
|
||||||
// seek back to symbols
|
// seek back to symbols
|
||||||
|
|
||||||
if (fseek(f, file_hdr.f_symptr, SEEK_SET))
|
if (fseek(f, file_hdr.f_symptr, SEEK_SET))
|
||||||
tcc_error("error reading .out file for input");
|
tcc_error(S, "error reading .out file for input");
|
||||||
|
|
||||||
for (i = 0; i < file_hdr.f_nsyms; i++) {
|
for (i = 0; i < file_hdr.f_nsyms; i++) {
|
||||||
if (fread(&csym, SYMESZ, 1, f) != 1)
|
if (fread(&csym, SYMESZ, 1, f) != 1)
|
||||||
tcc_error("error reading .out file for input");
|
tcc_error(S, "error reading .out file for input");
|
||||||
|
|
||||||
if (csym._n._n_n._n_zeroes == 0) {
|
if (csym._n._n_n._n_zeroes == 0) {
|
||||||
name = Coff_str_table + csym._n._n_n._n_offset - 4;
|
name = Coff_str_table + csym._n._n_n._n_offset - 4;
|
||||||
@ -933,13 +933,13 @@ ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
|
|||||||
if (name[0] == '_' && strcmp(name, "_main") != 0)
|
if (name[0] == '_' && strcmp(name, "_main") != 0)
|
||||||
name++;
|
name++;
|
||||||
|
|
||||||
tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
|
tcc_add_symbol(S, name, (void*)(uintptr_t)csym.n_value);
|
||||||
}
|
}
|
||||||
// skip any aux records
|
// skip any aux records
|
||||||
|
|
||||||
if (csym.n_numaux == 1) {
|
if (csym.n_numaux == 1) {
|
||||||
if (fread(&csym, SYMESZ, 1, f) != 1)
|
if (fread(&csym, SYMESZ, 1, f) != 1)
|
||||||
tcc_error("error reading .out file for input");
|
tcc_error(S, "error reading .out file for input");
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
225
tccmacho.c
225
tccmacho.c
@ -249,19 +249,19 @@ struct macho {
|
|||||||
#define SHT_LINKEDIT (SHT_LOOS + 42)
|
#define SHT_LINKEDIT (SHT_LOOS + 42)
|
||||||
#define SHN_FROMDLL (SHN_LOOS + 2) /* Symbol is undefined, comes from a DLL */
|
#define SHN_FROMDLL (SHN_LOOS + 2) /* Symbol is undefined, comes from a DLL */
|
||||||
|
|
||||||
static void * add_lc(struct macho *mo, uint32_t cmd, uint32_t cmdsize)
|
static void * add_lc(TCCState* S, struct macho *mo, uint32_t cmd, uint32_t cmdsize)
|
||||||
{
|
{
|
||||||
struct load_command *lc = tcc_mallocz(cmdsize);
|
struct load_command *lc = tcc_mallocz(S, cmdsize);
|
||||||
lc->cmd = cmd;
|
lc->cmd = cmd;
|
||||||
lc->cmdsize = cmdsize;
|
lc->cmdsize = cmdsize;
|
||||||
mo->lc = tcc_realloc(mo->lc, sizeof(mo->lc[0]) * (mo->nlc + 1));
|
mo->lc = tcc_realloc(S, mo->lc, sizeof(mo->lc[0]) * (mo->nlc + 1));
|
||||||
mo->lc[mo->nlc++] = lc;
|
mo->lc[mo->nlc++] = lc;
|
||||||
return lc;
|
return lc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct segment_command_64 * add_segment(struct macho *mo, const char *name)
|
static struct segment_command_64 * add_segment(TCCState* S, 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(S, mo, LC_SEGMENT_64, sizeof(*sc));
|
||||||
strncpy(sc->segname, name, 16);
|
strncpy(sc->segname, name, 16);
|
||||||
mo->seg2lc[mo->nseg++] = mo->nlc - 1;
|
mo->seg2lc[mo->nseg++] = mo->nlc - 1;
|
||||||
return sc;
|
return sc;
|
||||||
@ -272,14 +272,14 @@ 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, const char *name)
|
static int add_section(TCCState* S, 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;
|
||||||
struct section_64 *sec;
|
struct section_64 *sec;
|
||||||
seg->nsects++;
|
seg->nsects++;
|
||||||
seg->cmdsize += sizeof(*sec);
|
seg->cmdsize += sizeof(*sec);
|
||||||
seg = tcc_realloc(seg, sizeof(*seg) + seg->nsects * sizeof(*sec));
|
seg = tcc_realloc(S, seg, sizeof(*seg) + seg->nsects * sizeof(*sec));
|
||||||
sec = (struct section_64*)((char*)seg + sizeof(*seg)) + ret;
|
sec = (struct section_64*)((char*)seg + sizeof(*seg)) + ret;
|
||||||
memset(sec, 0, sizeof(*sec));
|
memset(sec, 0, sizeof(*sec));
|
||||||
strncpy(sec->sectname, name, 16);
|
strncpy(sec->sectname, name, 16);
|
||||||
@ -293,11 +293,11 @@ static struct section_64 *get_section(struct segment_command_64 *seg, int i)
|
|||||||
return (struct section_64*)((char*)seg + sizeof(*seg)) + i;
|
return (struct section_64*)((char*)seg + sizeof(*seg)) + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void * add_dylib(struct macho *mo, char *name)
|
static void * add_dylib(TCCState* S, struct macho *mo, char *name)
|
||||||
{
|
{
|
||||||
struct dylib_command *lc;
|
struct dylib_command *lc;
|
||||||
int sz = (sizeof(*lc) + strlen(name) + 1 + 7) & -8;
|
int sz = (sizeof(*lc) + strlen(name) + 1 + 7) & -8;
|
||||||
lc = add_lc(mo, LC_LOAD_DYLIB, sz);
|
lc = add_lc(S, mo, LC_LOAD_DYLIB, sz);
|
||||||
lc->name = sizeof(*lc);
|
lc->name = sizeof(*lc);
|
||||||
strcpy((char*)lc + lc->name, name);
|
strcpy((char*)lc + lc->name, name);
|
||||||
lc->timestamp = 2;
|
lc->timestamp = 2;
|
||||||
@ -306,7 +306,7 @@ static void * add_dylib(struct macho *mo, char *name)
|
|||||||
return lc;
|
return lc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_relocs(TCCState *s1, struct macho *mo)
|
static void check_relocs(TCCState *S, struct macho *mo)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
@ -314,10 +314,10 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
|||||||
int i, type, gotplt_entry, sym_index, for_code;
|
int i, type, gotplt_entry, sym_index, for_code;
|
||||||
struct sym_attr *attr;
|
struct sym_attr *attr;
|
||||||
|
|
||||||
s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
|
S->got = new_section(S, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
|
||||||
mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
mo->indirsyms = new_section(S, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < S->nb_sections; i++) {
|
||||||
s = s1->sections[i];
|
s = S->sections[i];
|
||||||
if (s->sh_type != SHT_RELX)
|
if (s->sh_type != SHT_RELX)
|
||||||
continue;
|
continue;
|
||||||
for_each_elem(s, 0, rel, ElfW_Rel) {
|
for_each_elem(s, 0, rel, ElfW_Rel) {
|
||||||
@ -331,21 +331,21 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
|||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
if (sym->st_shndx == SHN_UNDEF
|
if (sym->st_shndx == SHN_UNDEF
|
||||||
|| gotplt_entry == ALWAYS_GOTPLT_ENTRY) {
|
|| gotplt_entry == ALWAYS_GOTPLT_ENTRY) {
|
||||||
attr = get_sym_attr(s1, sym_index, 1);
|
attr = get_sym_attr(S, sym_index, 1);
|
||||||
if (!attr->dyn_index) {
|
if (!attr->dyn_index) {
|
||||||
uint32_t *pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
|
uint32_t *pi = section_ptr_add(S, mo->indirsyms, sizeof(*pi));
|
||||||
attr->got_offset = s1->got->data_offset;
|
attr->got_offset = S->got->data_offset;
|
||||||
attr->plt_offset = -1;
|
attr->plt_offset = -1;
|
||||||
attr->dyn_index = 1; /* used as flag */
|
attr->dyn_index = 1; /* used as flag */
|
||||||
section_ptr_add(s1->got, PTR_SIZE);
|
section_ptr_add(S, S->got, PTR_SIZE);
|
||||||
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
|
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
|
||||||
if (sym->st_shndx == SHN_UNDEF)
|
if (sym->st_shndx == SHN_UNDEF)
|
||||||
tcc_error("undefined local symbol???");
|
tcc_error(S, "undefined local symbol???");
|
||||||
*pi = INDIRECT_SYMBOL_LOCAL;
|
*pi = INDIRECT_SYMBOL_LOCAL;
|
||||||
/* The pointer slot we generated must point to the
|
/* The pointer slot we generated must point to the
|
||||||
symbol, whose address is only known after layout,
|
symbol, whose address is only known after layout,
|
||||||
so register a simple relocation for that. */
|
so register a simple relocation for that. */
|
||||||
put_elf_reloc(s1->symtab, s1->got, attr->got_offset,
|
put_elf_reloc(S->symtab, S->got, attr->got_offset,
|
||||||
R_DATA_PTR, sym_index);
|
R_DATA_PTR, sym_index);
|
||||||
} else
|
} else
|
||||||
*pi = mo->e2msym[sym_index];
|
*pi = mo->e2msym[sym_index];
|
||||||
@ -354,10 +354,10 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
|||||||
if (attr->plt_offset == -1) {
|
if (attr->plt_offset == -1) {
|
||||||
uint8_t *jmp;
|
uint8_t *jmp;
|
||||||
attr->plt_offset = mo->stubs->data_offset;
|
attr->plt_offset = mo->stubs->data_offset;
|
||||||
jmp = section_ptr_add(mo->stubs, 6);
|
jmp = section_ptr_add(S, mo->stubs, 6);
|
||||||
jmp[0] = 0xff; /* jmpq *ofs(%rip) */
|
jmp[0] = 0xff; /* jmpq *ofs(%rip) */
|
||||||
jmp[1] = 0x25;
|
jmp[1] = 0x25;
|
||||||
put_elf_reloc(s1->symtab, mo->stubs,
|
put_elf_reloc(S->symtab, mo->stubs,
|
||||||
attr->plt_offset + 2,
|
attr->plt_offset + 2,
|
||||||
R_X86_64_GOTPCREL, sym_index);
|
R_X86_64_GOTPCREL, sym_index);
|
||||||
}
|
}
|
||||||
@ -369,7 +369,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_symbols(TCCState *s1, struct macho *mo)
|
static int check_symbols(TCCState *S, struct macho *mo)
|
||||||
{
|
{
|
||||||
int sym_index, sym_end;
|
int sym_index, sym_end;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -391,17 +391,17 @@ static int check_symbols(TCCState *s1, struct macho *mo)
|
|||||||
if (mo->ilocal == -1)
|
if (mo->ilocal == -1)
|
||||||
mo->ilocal = sym_index - 1;
|
mo->ilocal = sym_index - 1;
|
||||||
if (mo->iextdef != -1 || mo->iundef != -1)
|
if (mo->iextdef != -1 || mo->iundef != -1)
|
||||||
tcc_error("local syms after global ones");
|
tcc_error(S, "local syms after global ones");
|
||||||
} else if (sym->st_shndx != SHN_UNDEF) {
|
} else if (sym->st_shndx != SHN_UNDEF) {
|
||||||
if (mo->iextdef == -1)
|
if (mo->iextdef == -1)
|
||||||
mo->iextdef = sym_index - 1;
|
mo->iextdef = sym_index - 1;
|
||||||
if (mo->iundef != -1)
|
if (mo->iundef != -1)
|
||||||
tcc_error("external defined symbol after undefined");
|
tcc_error(S, "external defined symbol after undefined");
|
||||||
} else if (sym->st_shndx == SHN_UNDEF) {
|
} else if (sym->st_shndx == SHN_UNDEF) {
|
||||||
if (mo->iundef == -1)
|
if (mo->iundef == -1)
|
||||||
mo->iundef = sym_index - 1;
|
mo->iundef = sym_index - 1;
|
||||||
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK
|
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK
|
||||||
|| find_elf_sym(s1->dynsymtab_section, name)) {
|
|| find_elf_sym(S->dynsymtab_section, name)) {
|
||||||
/* Mark the symbol as coming from a dylib so that
|
/* Mark the symbol as coming from a dylib so that
|
||||||
relocate_syms doesn't complain. Normally bind_exe_dynsyms
|
relocate_syms doesn't complain. Normally bind_exe_dynsyms
|
||||||
would do this check, and place the symbol into dynsym
|
would do this check, and place the symbol into dynsym
|
||||||
@ -410,14 +410,14 @@ static int check_symbols(TCCState *s1, struct macho *mo)
|
|||||||
sym->st_shndx = SHN_FROMDLL;
|
sym->st_shndx = SHN_FROMDLL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tcc_error_noabort("undefined symbol '%s'", name);
|
tcc_error_noabort(S, "undefined symbol '%s'", name);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn)
|
static void convert_symbol(TCCState *S, struct macho *mo, struct nlist_64 *pn)
|
||||||
{
|
{
|
||||||
struct nlist_64 n = *pn;
|
struct nlist_64 n = *pn;
|
||||||
ElfSym *sym = (ElfW(Sym) *)symtab_section->data + pn->n_value;
|
ElfSym *sym = (ElfW(Sym) *)symtab_section->data + pn->n_value;
|
||||||
@ -433,19 +433,19 @@ static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn)
|
|||||||
n.n_type = N_ABS;
|
n.n_type = N_ABS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcc_error("unhandled ELF symbol type %d %s",
|
tcc_error(S, "unhandled ELF symbol type %d %s",
|
||||||
ELFW(ST_TYPE)(sym->st_info), name);
|
ELFW(ST_TYPE)(sym->st_info), name);
|
||||||
}
|
}
|
||||||
if (sym->st_shndx == SHN_UNDEF)
|
if (sym->st_shndx == SHN_UNDEF)
|
||||||
tcc_error("should have been rewritten to SHN_FROMDLL: %s", name);
|
tcc_error(S, "should have been rewritten to SHN_FROMDLL: %s", name);
|
||||||
else if (sym->st_shndx == SHN_FROMDLL)
|
else if (sym->st_shndx == SHN_FROMDLL)
|
||||||
n.n_type = N_UNDF, n.n_sect = 0;
|
n.n_type = N_UNDF, n.n_sect = 0;
|
||||||
else if (sym->st_shndx == SHN_ABS)
|
else if (sym->st_shndx == SHN_ABS)
|
||||||
n.n_type = N_ABS, n.n_sect = 0;
|
n.n_type = N_ABS, n.n_sect = 0;
|
||||||
else if (sym->st_shndx >= SHN_LORESERVE)
|
else if (sym->st_shndx >= SHN_LORESERVE)
|
||||||
tcc_error("unhandled ELF symbol section %d %s", sym->st_shndx, name);
|
tcc_error(S, "unhandled ELF symbol section %d %s", sym->st_shndx, name);
|
||||||
else if (!mo->elfsectomacho[sym->st_shndx])
|
else if (!mo->elfsectomacho[sym->st_shndx])
|
||||||
tcc_error("ELF section %d not mapped into Mach-O for symbol %s",
|
tcc_error(S, "ELF section %d not mapped into Mach-O for symbol %s",
|
||||||
sym->st_shndx, name);
|
sym->st_shndx, name);
|
||||||
else
|
else
|
||||||
n.n_sect = mo->elfsectomacho[sym->st_shndx];
|
n.n_sect = mo->elfsectomacho[sym->st_shndx];
|
||||||
@ -458,16 +458,15 @@ static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn)
|
|||||||
*pn = n;
|
*pn = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void convert_symbols(TCCState *s1, struct macho *mo)
|
static void convert_symbols(TCCState *S, struct macho *mo)
|
||||||
{
|
{
|
||||||
struct nlist_64 *pn;
|
struct nlist_64 *pn;
|
||||||
for_each_elem(mo->symtab, 0, pn, struct nlist_64)
|
for_each_elem(mo->symtab, 0, pn, struct nlist_64)
|
||||||
convert_symbol(s1, mo, pn);
|
convert_symbol(S, mo, pn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int machosymcmp(const void *_a, const void *_b)
|
static int machosymcmp(const void *_a, const void *_b, TCCState *S)
|
||||||
{
|
{
|
||||||
TCCState *s1 = tcc_state;
|
|
||||||
int ea = ((struct nlist_64 *)_a)->n_value;
|
int ea = ((struct nlist_64 *)_a)->n_value;
|
||||||
int eb = ((struct nlist_64 *)_b)->n_value;
|
int eb = ((struct nlist_64 *)_b)->n_value;
|
||||||
ElfSym *sa = (ElfSym *)symtab_section->data + ea;
|
ElfSym *sa = (ElfSym *)symtab_section->data + ea;
|
||||||
@ -492,33 +491,33 @@ static int machosymcmp(const void *_a, const void *_b)
|
|||||||
return ea - eb;
|
return ea - eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_symtab(TCCState *s1, struct macho *mo)
|
static void create_symtab(TCCState *S, struct macho *mo)
|
||||||
{
|
{
|
||||||
int sym_index, sym_end;
|
int sym_index, sym_end;
|
||||||
struct nlist_64 *pn;
|
struct nlist_64 *pn;
|
||||||
|
|
||||||
/* Stub creation belongs to check_relocs, but we need to create
|
/* Stub creation belongs to check_relocs, but we need to create
|
||||||
the symbol now, so its included in the sorting. */
|
the symbol now, so its included in the sorting. */
|
||||||
mo->stubs = new_section(s1, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
|
mo->stubs = new_section(S, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
|
||||||
mo->stubsym = put_elf_sym(s1->symtab, 0, 0,
|
mo->stubsym = put_elf_sym(S, S->symtab, 0, 0,
|
||||||
ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
|
ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
|
||||||
mo->stubs->sh_num, ".__stubs");
|
mo->stubs->sh_num, ".__stubs");
|
||||||
|
|
||||||
mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
mo->symtab = new_section(S, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
||||||
mo->strtab = new_section(s1, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
mo->strtab = new_section(S, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
||||||
put_elf_str(mo->strtab, " "); /* Mach-O starts strtab with a space */
|
put_elf_str(S, mo->strtab, " "); /* Mach-O starts strtab with a space */
|
||||||
sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
|
sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
|
||||||
pn = section_ptr_add(mo->symtab, sizeof(*pn) * (sym_end - 1));
|
pn = section_ptr_add(S, mo->symtab, sizeof(*pn) * (sym_end - 1));
|
||||||
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
||||||
ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
|
ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
|
||||||
const char *name = (char*)symtab_section->link->data + sym->st_name;
|
const char *name = (char*)symtab_section->link->data + sym->st_name;
|
||||||
pn[sym_index - 1].n_strx = put_elf_str(mo->strtab, name);
|
pn[sym_index - 1].n_strx = put_elf_str(S, mo->strtab, name);
|
||||||
pn[sym_index - 1].n_value = sym_index;
|
pn[sym_index - 1].n_value = sym_index;
|
||||||
}
|
}
|
||||||
tcc_enter_state(s1); /* qsort needs global state */
|
tcc_enter_state(S); /* qsort needs global state */
|
||||||
qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp);
|
tcc_qsort_s(pn, sym_end - 1, sizeof(*pn), (tcc_cmpfun)machosymcmp, S);
|
||||||
tcc_exit_state(s1);
|
tcc_exit_state(S);
|
||||||
mo->e2msym = tcc_malloc(sym_end * sizeof(*mo->e2msym));
|
mo->e2msym = tcc_malloc(S, sym_end * sizeof(*mo->e2msym));
|
||||||
mo->e2msym[0] = -1;
|
mo->e2msym[0] = -1;
|
||||||
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
||||||
mo->e2msym[pn[sym_index - 1].n_value] = sym_index - 1;
|
mo->e2msym[pn[sym_index - 1].n_value] = sym_index - 1;
|
||||||
@ -546,7 +545,7 @@ const struct {
|
|||||||
/*[sk_linkedit] =*/ { 3, S_REGULAR, NULL },
|
/*[sk_linkedit] =*/ { 3, S_REGULAR, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static void collect_sections(TCCState *s1, struct macho *mo)
|
static void collect_sections(TCCState *S, struct macho *mo)
|
||||||
{
|
{
|
||||||
int i, sk, numsec;
|
int i, sk, numsec;
|
||||||
uint64_t curaddr, fileofs;
|
uint64_t curaddr, fileofs;
|
||||||
@ -557,49 +556,49 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
|||||||
struct dysymtab_command *dysymlc;
|
struct dysymtab_command *dysymlc;
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
seg = add_segment(mo, "__PAGEZERO");
|
seg = add_segment(S, mo, "__PAGEZERO");
|
||||||
seg->vmsize = (uint64_t)1 << 32;
|
seg->vmsize = (uint64_t)1 << 32;
|
||||||
|
|
||||||
seg = add_segment(mo, "__TEXT");
|
seg = add_segment(S, mo, "__TEXT");
|
||||||
seg->vmaddr = (uint64_t)1 << 32;
|
seg->vmaddr = (uint64_t)1 << 32;
|
||||||
seg->maxprot = 7; // rwx
|
seg->maxprot = 7; // rwx
|
||||||
seg->initprot = 5; // r-x
|
seg->initprot = 5; // r-x
|
||||||
|
|
||||||
seg = add_segment(mo, "__DATA");
|
seg = add_segment(S, mo, "__DATA");
|
||||||
seg->vmaddr = -1;
|
seg->vmaddr = -1;
|
||||||
seg->maxprot = 7; // rwx
|
seg->maxprot = 7; // rwx
|
||||||
seg->initprot = 3; // rw-
|
seg->initprot = 3; // rw-
|
||||||
|
|
||||||
seg = add_segment(mo, "__LINKEDIT");
|
seg = add_segment(S, mo, "__LINKEDIT");
|
||||||
seg->vmaddr = -1;
|
seg->vmaddr = -1;
|
||||||
seg->maxprot = 7; // rwx
|
seg->maxprot = 7; // rwx
|
||||||
seg->initprot = 1; // r--
|
seg->initprot = 1; // r--
|
||||||
|
|
||||||
mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep));
|
mo->ep = add_lc(S, mo, LC_MAIN, sizeof(*mo->ep));
|
||||||
mo->ep->entryoff = 4096;
|
mo->ep->entryoff = 4096;
|
||||||
|
|
||||||
i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8;
|
i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8;
|
||||||
dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i);
|
dyldlc = add_lc(S, mo, LC_LOAD_DYLINKER, i);
|
||||||
dyldlc->name = sizeof(*dyldlc);
|
dyldlc->name = sizeof(*dyldlc);
|
||||||
str = (char*)dyldlc + dyldlc->name;
|
str = (char*)dyldlc + dyldlc->name;
|
||||||
strcpy(str, "/usr/lib/dyld");
|
strcpy(str, "/usr/lib/dyld");
|
||||||
|
|
||||||
symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc));
|
symlc = add_lc(S, mo, LC_SYMTAB, sizeof(*symlc));
|
||||||
dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc));
|
dysymlc = add_lc(S, mo, LC_DYSYMTAB, sizeof(*dysymlc));
|
||||||
|
|
||||||
for(i = 0; i < s1->nb_loaded_dlls; i++) {
|
for(i = 0; i < S->nb_loaded_dlls; i++) {
|
||||||
DLLReference *dllref = s1->loaded_dlls[i];
|
DLLReference *dllref = S->loaded_dlls[i];
|
||||||
if (dllref->level == 0)
|
if (dllref->level == 0)
|
||||||
add_dylib(mo, dllref->name);
|
add_dylib(S, mo, dllref->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dyld requires a writable segment with classic Mach-O, but it ignores
|
/* dyld requires a writable segment with classic Mach-O, but it ignores
|
||||||
zero-sized segments for this, so force to have some data. */
|
zero-sized segments for this, so force to have some data. */
|
||||||
section_ptr_add(data_section, 1);
|
section_ptr_add(S, data_section, 1);
|
||||||
memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect));
|
memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect));
|
||||||
for (i = s1->nb_sections; i-- > 1;) {
|
for (i = S->nb_sections; i-- > 1;) {
|
||||||
int type, flags;
|
int type, flags;
|
||||||
s = s1->sections[i];
|
s = S->sections[i];
|
||||||
type = s->sh_type;
|
type = s->sh_type;
|
||||||
flags = s->sh_flags;
|
flags = s->sh_flags;
|
||||||
sk = sk_unknown;
|
sk = sk_unknown;
|
||||||
@ -614,7 +613,7 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
|||||||
case SHT_RELX: sk = sk_discard; break;
|
case SHT_RELX: sk = sk_discard; break;
|
||||||
case SHT_LINKEDIT: sk = sk_linkedit; break;
|
case SHT_LINKEDIT: sk = sk_linkedit; break;
|
||||||
case SHT_PROGBITS:
|
case SHT_PROGBITS:
|
||||||
if (s == s1->got)
|
if (s == S->got)
|
||||||
sk = sk_nl_ptr;
|
sk = sk_nl_ptr;
|
||||||
else if (flags & SHF_EXECINSTR)
|
else if (flags & SHF_EXECINSTR)
|
||||||
sk = sk_text;
|
sk = sk_text;
|
||||||
@ -634,7 +633,7 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
|||||||
curaddr += 4096;
|
curaddr += 4096;
|
||||||
seg = NULL;
|
seg = NULL;
|
||||||
numsec = 0;
|
numsec = 0;
|
||||||
mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->nb_sections);
|
mo->elfsectomacho = tcc_mallocz(S, sizeof(*mo->elfsectomacho) * S->nb_sections);
|
||||||
for (sk = sk_unknown; sk < sk_last; sk++) {
|
for (sk = sk_unknown; sk < sk_last; sk++) {
|
||||||
struct section_64 *sec = NULL;
|
struct section_64 *sec = NULL;
|
||||||
if (seg) {
|
if (seg) {
|
||||||
@ -646,7 +645,7 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
|||||||
int si;
|
int si;
|
||||||
seg = get_segment(mo, skinfo[sk].seg);
|
seg = get_segment(mo, skinfo[sk].seg);
|
||||||
if (skinfo[sk].name) {
|
if (skinfo[sk].name) {
|
||||||
si = add_section(mo, &seg, skinfo[sk].name);
|
si = add_section(S, mo, &seg, skinfo[sk].name);
|
||||||
numsec++;
|
numsec++;
|
||||||
mo->lc[mo->seg2lc[skinfo[sk].seg]] = (struct load_command*)seg;
|
mo->lc[mo->seg2lc[skinfo[sk].seg]] = (struct load_command*)seg;
|
||||||
mo->sk_to_sect[sk].machosect = si;
|
mo->sk_to_sect[sk].machosect = si;
|
||||||
@ -670,7 +669,7 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
|||||||
sec->align = al;
|
sec->align = al;
|
||||||
al = 1ULL << al;
|
al = 1ULL << al;
|
||||||
if (al > 4096)
|
if (al > 4096)
|
||||||
tcc_warning("alignment > 4096"), sec->align = 12, al = 4096;
|
tcc_warning(S, "alignment > 4096"), sec->align = 12, al = 4096;
|
||||||
curaddr = (curaddr + al - 1) & -al;
|
curaddr = (curaddr + al - 1) & -al;
|
||||||
fileofs = (fileofs + al - 1) & -al;
|
fileofs = (fileofs + al - 1) & -al;
|
||||||
if (sec) {
|
if (sec) {
|
||||||
@ -739,7 +738,7 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
|||||||
dysymlc->nindirectsyms = mo->indirsyms->data_offset / sizeof(uint32_t);
|
dysymlc->nindirectsyms = mo->indirsyms->data_offset / sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void macho_write(TCCState *s1, struct macho *mo, FILE *fp)
|
static void macho_write(TCCState *S, struct macho *mo, FILE *fp)
|
||||||
{
|
{
|
||||||
int i, sk;
|
int i, sk;
|
||||||
uint64_t fileofs = 0;
|
uint64_t fileofs = 0;
|
||||||
@ -779,7 +778,7 @@ static void macho_write(TCCState *s1, struct macho *mo, FILE *fp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
|
ST_FUNC int macho_output_file(TCCState *S, const char *filename)
|
||||||
{
|
{
|
||||||
int fd, mode, file_type;
|
int fd, mode, file_type;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
@ -788,7 +787,7 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
|
|||||||
|
|
||||||
(void)memset(&mo, 0, sizeof(mo));
|
(void)memset(&mo, 0, sizeof(mo));
|
||||||
|
|
||||||
file_type = s1->output_type;
|
file_type = S->output_type;
|
||||||
if (file_type == TCC_OUTPUT_OBJ)
|
if (file_type == TCC_OUTPUT_OBJ)
|
||||||
mode = 0666;
|
mode = 0666;
|
||||||
else
|
else
|
||||||
@ -796,36 +795,36 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
|
|||||||
unlink(filename);
|
unlink(filename);
|
||||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
|
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
tcc_error_noabort("could not write '%s: %s'", filename, strerror(errno));
|
tcc_error_noabort(S, "could not write '%s: %s'", filename, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fp = fdopen(fd, "wb");
|
fp = fdopen(fd, "wb");
|
||||||
if (s1->verbose)
|
if (S->verbose)
|
||||||
printf("<- %s\n", filename);
|
printf("<- %s\n", filename);
|
||||||
|
|
||||||
tcc_add_runtime(s1);
|
tcc_add_runtime(S);
|
||||||
resolve_common_syms(s1);
|
resolve_common_syms(S);
|
||||||
create_symtab(s1, &mo);
|
create_symtab(S, &mo);
|
||||||
check_relocs(s1, &mo);
|
check_relocs(S, &mo);
|
||||||
ret = check_symbols(s1, &mo);
|
ret = check_symbols(S, &mo);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
collect_sections(s1, &mo);
|
collect_sections(S, &mo);
|
||||||
relocate_syms(s1, s1->symtab, 0);
|
relocate_syms(S, S->symtab, 0);
|
||||||
mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1)
|
mo.ep->entryoff = get_sym_addr(S, "main", 1, 1)
|
||||||
- get_segment(&mo, 1)->vmaddr;
|
- get_segment(&mo, 1)->vmaddr;
|
||||||
if (s1->nb_errors)
|
if (S->nb_errors)
|
||||||
goto do_ret;
|
goto do_ret;
|
||||||
relocate_sections(s1);
|
relocate_sections(S);
|
||||||
convert_symbols(s1, &mo);
|
convert_symbols(S, &mo);
|
||||||
macho_write(s1, &mo, fp);
|
macho_write(S, &mo, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
do_ret:
|
do_ret:
|
||||||
for (i = 0; i < mo.nlc; i++)
|
for (i = 0; i < mo.nlc; i++)
|
||||||
tcc_free(mo.lc[i]);
|
tcc_free(S, mo.lc[i]);
|
||||||
tcc_free(mo.lc);
|
tcc_free(S, mo.lc);
|
||||||
tcc_free(mo.elfsectomacho);
|
tcc_free(S, mo.elfsectomacho);
|
||||||
tcc_free(mo.e2msym);
|
tcc_free(S, mo.e2msym);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return ret;
|
return ret;
|
||||||
@ -837,13 +836,13 @@ static uint32_t macho_swap32(uint32_t x)
|
|||||||
}
|
}
|
||||||
#define SWAP(x) (swap ? macho_swap32(x) : (x))
|
#define SWAP(x) (swap ? macho_swap32(x) : (x))
|
||||||
|
|
||||||
ST_FUNC int macho_add_dllref(TCCState* s1, int lev, const char* soname)
|
ST_FUNC int macho_add_dllref(TCCState* S, int lev, const char* soname)
|
||||||
{
|
{
|
||||||
/* if the dll is already loaded, do not load it */
|
/* if the dll is already loaded, do not load it */
|
||||||
DLLReference *dllref;
|
DLLReference *dllref;
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < s1->nb_loaded_dlls; i++) {
|
for(i = 0; i < S->nb_loaded_dlls; i++) {
|
||||||
dllref = s1->loaded_dlls[i];
|
dllref = S->loaded_dlls[i];
|
||||||
if (!strcmp(soname, dllref->name)) {
|
if (!strcmp(soname, dllref->name)) {
|
||||||
/* but update level if needed */
|
/* but update level if needed */
|
||||||
if (lev < dllref->level)
|
if (lev < dllref->level)
|
||||||
@ -851,7 +850,7 @@ ST_FUNC int macho_add_dllref(TCCState* s1, int lev, const char* soname)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tcc_add_dllref(s1, soname)->level = lev;
|
tcc_add_dllref(S, soname)->level = lev;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,12 +912,12 @@ the_end:
|
|||||||
}
|
}
|
||||||
#endif /* TCC_IS_NATIVE */
|
#endif /* TCC_IS_NATIVE */
|
||||||
|
|
||||||
ST_FUNC int macho_load_tbd(TCCState* s1, int fd, const char* filename, int lev)
|
ST_FUNC int macho_load_tbd(TCCState* S, int fd, const char* filename, int lev)
|
||||||
{
|
{
|
||||||
char *soname, *data, *pos;
|
char *soname, *data, *pos;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
pos = data = tcc_load_text(fd);
|
pos = data = tcc_load_text(S, fd);
|
||||||
if (!tbd_parse_movepast("install-name: ")) goto the_end;
|
if (!tbd_parse_movepast("install-name: ")) goto the_end;
|
||||||
tbd_parse_skipws;
|
tbd_parse_skipws;
|
||||||
tbd_parse_tramplequote;
|
tbd_parse_tramplequote;
|
||||||
@ -926,7 +925,7 @@ ST_FUNC int macho_load_tbd(TCCState* s1, int fd, const char* filename, int lev)
|
|||||||
if (!tbd_parse_movetoany("\n \"'")) goto the_end;
|
if (!tbd_parse_movetoany("\n \"'")) goto the_end;
|
||||||
tbd_parse_trample;
|
tbd_parse_trample;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (macho_add_dllref(s1, lev, soname) != 0) goto the_end;
|
if (macho_add_dllref(S, lev, soname) != 0) goto the_end;
|
||||||
while(pos) {
|
while(pos) {
|
||||||
char* sym = NULL;
|
char* sym = NULL;
|
||||||
int cont = 1;
|
int cont = 1;
|
||||||
@ -942,17 +941,17 @@ ST_FUNC int macho_load_tbd(TCCState* s1, int fd, const char* filename, int lev)
|
|||||||
tbd_parse_skipws;
|
tbd_parse_skipws;
|
||||||
if (*pos==0||*pos==']') cont=0;
|
if (*pos==0||*pos==']') cont=0;
|
||||||
tbd_parse_trample;
|
tbd_parse_trample;
|
||||||
set_elf_sym(s1->dynsymtab_section, 0, 0,
|
set_elf_sym(S->dynsymtab_section, 0, 0,
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, SHN_UNDEF, sym);
|
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, SHN_UNDEF, sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
the_end:
|
the_end:
|
||||||
tcc_free(data);
|
tcc_free(S, data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
|
ST_FUNC int macho_load_dll(TCCState * S, int fd, const char* filename, int lev)
|
||||||
{
|
{
|
||||||
unsigned char buf[sizeof(struct mach_header_64)];
|
unsigned char buf[sizeof(struct mach_header_64)];
|
||||||
void *buf2;
|
void *buf2;
|
||||||
@ -974,7 +973,7 @@ ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
|
|||||||
return -1;
|
return -1;
|
||||||
memcpy(&fh, buf, sizeof(fh));
|
memcpy(&fh, buf, sizeof(fh));
|
||||||
if (fh.magic == FAT_MAGIC || fh.magic == FAT_CIGAM) {
|
if (fh.magic == FAT_MAGIC || fh.magic == FAT_CIGAM) {
|
||||||
struct fat_arch *fa = load_data(fd, sizeof(fh),
|
struct fat_arch *fa = load_data(S, fd, sizeof(fh),
|
||||||
fh.nfat_arch * sizeof(*fa));
|
fh.nfat_arch * sizeof(*fa));
|
||||||
swap = fh.magic == FAT_CIGAM;
|
swap = fh.magic == FAT_CIGAM;
|
||||||
for (i = 0; i < SWAP(fh.nfat_arch); i++)
|
for (i = 0; i < SWAP(fh.nfat_arch); i++)
|
||||||
@ -982,15 +981,15 @@ ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
|
|||||||
&& SWAP(fa[i].cpusubtype) == 3) /* CPU_SUBTYPE_X86_ALL */
|
&& SWAP(fa[i].cpusubtype) == 3) /* CPU_SUBTYPE_X86_ALL */
|
||||||
break;
|
break;
|
||||||
if (i == SWAP(fh.nfat_arch)) {
|
if (i == SWAP(fh.nfat_arch)) {
|
||||||
tcc_free(fa);
|
tcc_free(S, fa);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
machofs = SWAP(fa[i].offset);
|
machofs = SWAP(fa[i].offset);
|
||||||
tcc_free(fa);
|
tcc_free(S, fa);
|
||||||
lseek(fd, machofs, SEEK_SET);
|
lseek(fd, machofs, SEEK_SET);
|
||||||
goto again;
|
goto again;
|
||||||
} else if (fh.magic == FAT_MAGIC_64 || fh.magic == FAT_CIGAM_64) {
|
} else if (fh.magic == FAT_MAGIC_64 || fh.magic == FAT_CIGAM_64) {
|
||||||
tcc_warning("%s: Mach-O fat 64bit files of type 0x%x not handled",
|
tcc_warning(S, "%s: Mach-O fat 64bit files of type 0x%x not handled",
|
||||||
filename, fh.magic);
|
filename, fh.magic);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -999,7 +998,7 @@ ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
|
|||||||
if (mh.magic != MH_MAGIC_64)
|
if (mh.magic != MH_MAGIC_64)
|
||||||
return -1;
|
return -1;
|
||||||
dprintf("found Mach-O at %d\n", machofs);
|
dprintf("found Mach-O at %d\n", machofs);
|
||||||
buf2 = load_data(fd, machofs + sizeof(struct mach_header_64), mh.sizeofcmds);
|
buf2 = load_data(S, fd, machofs + sizeof(struct mach_header_64), mh.sizeofcmds);
|
||||||
for (i = 0, lc = buf2; i < mh.ncmds; i++) {
|
for (i = 0, lc = buf2; i < mh.ncmds; i++) {
|
||||||
dprintf("lc %2d: 0x%08x\n", i, lc->cmd);
|
dprintf("lc %2d: 0x%08x\n", i, lc->cmd);
|
||||||
switch (lc->cmd) {
|
switch (lc->cmd) {
|
||||||
@ -1007,9 +1006,9 @@ ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
|
|||||||
{
|
{
|
||||||
struct symtab_command *sc = (struct symtab_command*)lc;
|
struct symtab_command *sc = (struct symtab_command*)lc;
|
||||||
nsyms = sc->nsyms;
|
nsyms = sc->nsyms;
|
||||||
symtab = load_data(fd, machofs + sc->symoff, nsyms * sizeof(*symtab));
|
symtab = load_data(S, fd, machofs + sc->symoff, nsyms * sizeof(*symtab));
|
||||||
strsize = sc->strsize;
|
strsize = sc->strsize;
|
||||||
strtab = load_data(fd, machofs + sc->stroff, strsize);
|
strtab = load_data(S, fd, machofs + sc->stroff, strsize);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LC_ID_DYLIB:
|
case LC_ID_DYLIB:
|
||||||
@ -1028,11 +1027,11 @@ ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
|
|||||||
int subfd = open(name, O_RDONLY | O_BINARY);
|
int subfd = open(name, O_RDONLY | O_BINARY);
|
||||||
dprintf(" REEXPORT %s\n", name);
|
dprintf(" REEXPORT %s\n", name);
|
||||||
if (subfd < 0)
|
if (subfd < 0)
|
||||||
tcc_warning("can't open %s (reexported from %s)", name, filename);
|
tcc_warning(S, "can't open %s (reexported from %s)", name, filename);
|
||||||
else {
|
else {
|
||||||
/* Hopefully the REEXPORTs never form a cycle, we don't check
|
/* Hopefully the REEXPORTs never form a cycle, we don't check
|
||||||
for that! */
|
for that! */
|
||||||
macho_load_dll(s1, subfd, name, lev + 1);
|
macho_load_dll(S, subfd, name, lev + 1);
|
||||||
close(subfd);
|
close(subfd);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1048,11 +1047,11 @@ ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
|
|||||||
lc = (struct load_command*) ((char*)lc + lc->cmdsize);
|
lc = (struct load_command*) ((char*)lc + lc->cmdsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != macho_add_dllref(s1, lev, soname))
|
if (0 != macho_add_dllref(S, lev, soname))
|
||||||
goto the_end;
|
goto the_end;
|
||||||
|
|
||||||
if (!nsyms || !nextdef)
|
if (!nsyms || !nextdef)
|
||||||
tcc_warning("%s doesn't export any symbols?", filename);
|
tcc_warning(S, "%s doesn't export any symbols?", filename);
|
||||||
|
|
||||||
//dprintf("symbols (all):\n");
|
//dprintf("symbols (all):\n");
|
||||||
dprintf("symbols (exported):\n");
|
dprintf("symbols (exported):\n");
|
||||||
@ -1063,14 +1062,14 @@ ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
|
|||||||
dprintf("%5d: %3d %3d 0x%04x 0x%016lx %s\n",
|
dprintf("%5d: %3d %3d 0x%04x 0x%016lx %s\n",
|
||||||
i, sym->n_type, sym->n_sect, sym->n_desc, (long)sym->n_value,
|
i, sym->n_type, sym->n_sect, sym->n_desc, (long)sym->n_value,
|
||||||
strtab + sym->n_strx);
|
strtab + sym->n_strx);
|
||||||
set_elf_sym(s1->dynsymtab_section, 0, 0,
|
set_elf_sym(S->dynsymtab_section, 0, 0,
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
|
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
|
||||||
0, SHN_UNDEF, strtab + sym->n_strx);
|
0, SHN_UNDEF, strtab + sym->n_strx);
|
||||||
}
|
}
|
||||||
|
|
||||||
the_end:
|
the_end:
|
||||||
tcc_free(strtab);
|
tcc_free(S, strtab);
|
||||||
tcc_free(symtab);
|
tcc_free(S, symtab);
|
||||||
tcc_free(buf2);
|
tcc_free(S, buf2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
355
tccpe.c
355
tccpe.c
@ -345,7 +345,7 @@ struct pe_import_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pe_info {
|
struct pe_info {
|
||||||
TCCState *s1;
|
TCCState *S;
|
||||||
Section *reloc;
|
Section *reloc;
|
||||||
Section *thunk;
|
Section *thunk;
|
||||||
const char *filename;
|
const char *filename;
|
||||||
@ -377,15 +377,15 @@ struct pe_info {
|
|||||||
|
|
||||||
/* --------------------------------------------*/
|
/* --------------------------------------------*/
|
||||||
|
|
||||||
static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym)
|
static const char *pe_export_name(TCCState *S, ElfW(Sym) *sym)
|
||||||
{
|
{
|
||||||
const char *name = (char*)symtab_section->link->data + sym->st_name;
|
const char *name = (char*)symtab_section->link->data + sym->st_name;
|
||||||
if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL))
|
if (S->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL))
|
||||||
return name + 1;
|
return name + 1;
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pe_find_import(TCCState * s1, ElfW(Sym) *sym)
|
static int pe_find_import(TCCState * S, ElfW(Sym) *sym)
|
||||||
{
|
{
|
||||||
char buffer[200];
|
char buffer[200];
|
||||||
const char *s, *p;
|
const char *s, *p;
|
||||||
@ -393,7 +393,7 @@ static int pe_find_import(TCCState * s1, ElfW(Sym) *sym)
|
|||||||
int a, err = 0;
|
int a, err = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
s = pe_export_name(s1, sym);
|
s = pe_export_name(S, sym);
|
||||||
a = 0;
|
a = 0;
|
||||||
if (n) {
|
if (n) {
|
||||||
/* second try: */
|
/* second try: */
|
||||||
@ -414,7 +414,7 @@ static int pe_find_import(TCCState * s1, ElfW(Sym) *sym)
|
|||||||
}
|
}
|
||||||
s = buffer;
|
s = buffer;
|
||||||
}
|
}
|
||||||
sym_index = find_elf_sym(s1->dynsymtab_section, s);
|
sym_index = find_elf_sym(S->dynsymtab_section, s);
|
||||||
// printf("find (%d) %d %s\n", n, sym_index, s);
|
// printf("find (%d) %d %s\n", n, sym_index, s);
|
||||||
if (sym_index
|
if (sym_index
|
||||||
&& ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT
|
&& ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT
|
||||||
@ -460,7 +460,7 @@ static void pe_align_section(Section *s, int a)
|
|||||||
{
|
{
|
||||||
int i = s->data_offset & (a-1);
|
int i = s->data_offset & (a-1);
|
||||||
if (i)
|
if (i)
|
||||||
section_ptr_add(s, a - i);
|
section_ptr_add(s->S, s, a - i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD size)
|
static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD size)
|
||||||
@ -615,11 +615,11 @@ static int pe_write(struct pe_info *pe)
|
|||||||
DWORD file_offset;
|
DWORD file_offset;
|
||||||
struct section_info *si;
|
struct section_info *si;
|
||||||
IMAGE_SECTION_HEADER *psh;
|
IMAGE_SECTION_HEADER *psh;
|
||||||
TCCState *s1 = pe->s1;
|
TCCState *S = pe->S;
|
||||||
|
|
||||||
pf.op = fopen(pe->filename, "wb");
|
pf.op = fopen(pe->filename, "wb");
|
||||||
if (NULL == pf.op) {
|
if (NULL == pf.op) {
|
||||||
tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
|
tcc_error_noabort(S, "could not write '%s': %s", pe->filename, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,7 +630,7 @@ static int pe_write(struct pe_info *pe)
|
|||||||
|
|
||||||
file_offset = pe->sizeofheaders;
|
file_offset = pe->sizeofheaders;
|
||||||
|
|
||||||
if (2 == pe->s1->verbose)
|
if (2 == pe->S->verbose)
|
||||||
printf("-------------------------------"
|
printf("-------------------------------"
|
||||||
"\n virt file size section" "\n");
|
"\n virt file size section" "\n");
|
||||||
for (i = 0; i < pe->sec_count; ++i) {
|
for (i = 0; i < pe->sec_count; ++i) {
|
||||||
@ -643,7 +643,7 @@ static int pe_write(struct pe_info *pe)
|
|||||||
size = si->sh_size;
|
size = si->sh_size;
|
||||||
psh = &si->ish;
|
psh = &si->ish;
|
||||||
|
|
||||||
if (2 == pe->s1->verbose)
|
if (2 == pe->S->verbose)
|
||||||
printf("%6x %6x %6x %s\n",
|
printf("%6x %6x %6x %s\n",
|
||||||
(unsigned)addr, (unsigned)file_offset, (unsigned)size, sh_name);
|
(unsigned)addr, (unsigned)file_offset, (unsigned)size, sh_name);
|
||||||
|
|
||||||
@ -712,11 +712,11 @@ static int pe_write(struct pe_info *pe)
|
|||||||
pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
|
pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
|
||||||
pe_header.opthdr.ImageBase = pe->imagebase;
|
pe_header.opthdr.ImageBase = pe->imagebase;
|
||||||
pe_header.opthdr.Subsystem = pe->subsystem;
|
pe_header.opthdr.Subsystem = pe->subsystem;
|
||||||
if (pe->s1->pe_stack_size)
|
if (pe->S->pe_stack_size)
|
||||||
pe_header.opthdr.SizeOfStackReserve = pe->s1->pe_stack_size;
|
pe_header.opthdr.SizeOfStackReserve = pe->S->pe_stack_size;
|
||||||
if (PE_DLL == pe->type)
|
if (PE_DLL == pe->type)
|
||||||
pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
|
pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
|
||||||
pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics;
|
pe_header.filehdr.Characteristics |= pe->S->pe_characteristics;
|
||||||
|
|
||||||
pe_fwrite(&pe_header, sizeof pe_header, &pf);
|
pe_fwrite(&pe_header, sizeof pe_header, &pf);
|
||||||
for (i = 0; i < pe->sec_count; ++i)
|
for (i = 0; i < pe->sec_count; ++i)
|
||||||
@ -747,9 +747,9 @@ static int pe_write(struct pe_info *pe)
|
|||||||
chmod(pe->filename, 0777);
|
chmod(pe->filename, 0777);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (2 == pe->s1->verbose)
|
if (2 == pe->S->verbose)
|
||||||
printf("-------------------------------\n");
|
printf("-------------------------------\n");
|
||||||
if (pe->s1->verbose)
|
if (pe->S->verbose)
|
||||||
printf("<- %s (%u bytes)\n", pe->filename, (unsigned)file_offset);
|
printf("<- %s (%u bytes)\n", pe->filename, (unsigned)file_offset);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -765,7 +765,7 @@ static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index)
|
|||||||
struct import_symbol *s;
|
struct import_symbol *s;
|
||||||
ElfW(Sym) *isym;
|
ElfW(Sym) *isym;
|
||||||
|
|
||||||
isym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
|
isym = (ElfW(Sym) *)pe->S->dynsymtab_section->data + sym_index;
|
||||||
dll_index = isym->st_size;
|
dll_index = isym->st_size;
|
||||||
|
|
||||||
i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index);
|
i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index);
|
||||||
@ -773,17 +773,17 @@ static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index)
|
|||||||
p = pe->imp_info[i];
|
p = pe->imp_info[i];
|
||||||
goto found_dll;
|
goto found_dll;
|
||||||
}
|
}
|
||||||
p = tcc_mallocz(sizeof *p);
|
p = tcc_mallocz(pe->S, sizeof *p);
|
||||||
p->dll_index = dll_index;
|
p->dll_index = dll_index;
|
||||||
dynarray_add(&pe->imp_info, &pe->imp_count, p);
|
dynarray_add(pe->S, &pe->imp_info, &pe->imp_count, p);
|
||||||
|
|
||||||
found_dll:
|
found_dll:
|
||||||
i = dynarray_assoc ((void**)p->symbols, p->sym_count, sym_index);
|
i = dynarray_assoc ((void**)p->symbols, p->sym_count, sym_index);
|
||||||
if (-1 != i)
|
if (-1 != i)
|
||||||
return p->symbols[i];
|
return p->symbols[i];
|
||||||
|
|
||||||
s = tcc_mallocz(sizeof *s);
|
s = tcc_mallocz(pe->S, sizeof *s);
|
||||||
dynarray_add(&p->symbols, &p->sym_count, s);
|
dynarray_add(pe->S, &p->symbols, &p->sym_count, s);
|
||||||
s->sym_index = sym_index;
|
s->sym_index = sym_index;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -793,9 +793,9 @@ void pe_free_imports(struct pe_info *pe)
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < pe->imp_count; ++i) {
|
for (i = 0; i < pe->imp_count; ++i) {
|
||||||
struct pe_import_info *p = pe->imp_info[i];
|
struct pe_import_info *p = pe->imp_info[i];
|
||||||
dynarray_reset(&p->symbols, &p->sym_count);
|
dynarray_reset(pe->S, &p->symbols, &p->sym_count);
|
||||||
}
|
}
|
||||||
dynarray_reset(&pe->imp_info, &pe->imp_count);
|
dynarray_reset(pe->S, &pe->imp_info, &pe->imp_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
@ -804,7 +804,7 @@ static void pe_build_imports(struct pe_info *pe)
|
|||||||
int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
|
int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
|
||||||
DWORD rva_base = pe->thunk->sh_addr - pe->imagebase;
|
DWORD rva_base = pe->thunk->sh_addr - pe->imagebase;
|
||||||
int ndlls = pe->imp_count;
|
int ndlls = pe->imp_count;
|
||||||
TCCState *s1 = pe->s1;
|
TCCState *S = pe->S;
|
||||||
|
|
||||||
for (sym_cnt = i = 0; i < ndlls; ++i)
|
for (sym_cnt = i = 0; i < ndlls; ++i)
|
||||||
sym_cnt += pe->imp_info[i]->sym_count;
|
sym_cnt += pe->imp_info[i]->sym_count;
|
||||||
@ -820,7 +820,7 @@ static void pe_build_imports(struct pe_info *pe)
|
|||||||
ent_ptr = thk_ptr + pe->iat_size;
|
ent_ptr = thk_ptr + pe->iat_size;
|
||||||
pe->imp_offs = dll_ptr + rva_base;
|
pe->imp_offs = dll_ptr + rva_base;
|
||||||
pe->iat_offs = thk_ptr + rva_base;
|
pe->iat_offs = thk_ptr + rva_base;
|
||||||
section_ptr_add(pe->thunk, pe->imp_size + 2*pe->iat_size);
|
section_ptr_add(pe->S, pe->thunk, pe->imp_size + 2*pe->iat_size);
|
||||||
|
|
||||||
for (i = 0; i < pe->imp_count; ++i) {
|
for (i = 0; i < pe->imp_count; ++i) {
|
||||||
IMAGE_IMPORT_DESCRIPTOR *hdr;
|
IMAGE_IMPORT_DESCRIPTOR *hdr;
|
||||||
@ -832,12 +832,12 @@ static void pe_build_imports(struct pe_info *pe)
|
|||||||
|
|
||||||
dllindex = p->dll_index;
|
dllindex = p->dll_index;
|
||||||
if (dllindex)
|
if (dllindex)
|
||||||
name = tcc_basename((dllref = pe->s1->loaded_dlls[dllindex-1])->name);
|
name = tcc_basename((dllref = pe->S->loaded_dlls[dllindex-1])->name);
|
||||||
else
|
else
|
||||||
name = "", dllref = NULL;
|
name = "", dllref = NULL;
|
||||||
|
|
||||||
/* put the dll name into the import header */
|
/* put the dll name into the import header */
|
||||||
v = put_elf_str(pe->thunk, name);
|
v = put_elf_str(pe->S, pe->thunk, name);
|
||||||
hdr = (IMAGE_IMPORT_DESCRIPTOR*)(pe->thunk->data + dll_ptr);
|
hdr = (IMAGE_IMPORT_DESCRIPTOR*)(pe->thunk->data + dll_ptr);
|
||||||
hdr->FirstThunk = thk_ptr + rva_base;
|
hdr->FirstThunk = thk_ptr + rva_base;
|
||||||
hdr->OriginalFirstThunk = ent_ptr + rva_base;
|
hdr->OriginalFirstThunk = ent_ptr + rva_base;
|
||||||
@ -847,9 +847,9 @@ static void pe_build_imports(struct pe_info *pe)
|
|||||||
if (k < n) {
|
if (k < n) {
|
||||||
int iat_index = p->symbols[k]->iat_index;
|
int iat_index = p->symbols[k]->iat_index;
|
||||||
int sym_index = p->symbols[k]->sym_index;
|
int sym_index = p->symbols[k]->sym_index;
|
||||||
ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
|
ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->S->dynsymtab_section->data + sym_index;
|
||||||
ElfW(Sym) *org_sym = (ElfW(Sym) *)symtab_section->data + iat_index;
|
ElfW(Sym) *org_sym = (ElfW(Sym) *)symtab_section->data + iat_index;
|
||||||
const char *name = (char*)pe->s1->dynsymtab_section->link->data + imp_sym->st_name;
|
const char *name = (char*)pe->S->dynsymtab_section->link->data + imp_sym->st_name;
|
||||||
int ordinal;
|
int ordinal;
|
||||||
|
|
||||||
org_sym->st_value = thk_ptr;
|
org_sym->st_value = thk_ptr;
|
||||||
@ -875,8 +875,8 @@ static void pe_build_imports(struct pe_info *pe)
|
|||||||
v = ordinal | (ADDR3264)1 << (sizeof(ADDR3264)*8 - 1);
|
v = ordinal | (ADDR3264)1 << (sizeof(ADDR3264)*8 - 1);
|
||||||
} else {
|
} else {
|
||||||
v = pe->thunk->data_offset + rva_base;
|
v = pe->thunk->data_offset + rva_base;
|
||||||
section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
|
section_ptr_add(pe->S, pe->thunk, sizeof(WORD)); /* hint, not used */
|
||||||
put_elf_str(pe->thunk, name);
|
put_elf_str(pe->S, pe->thunk, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -915,7 +915,7 @@ static void pe_build_exports(struct pe_info *pe)
|
|||||||
IMAGE_EXPORT_DIRECTORY *hdr;
|
IMAGE_EXPORT_DIRECTORY *hdr;
|
||||||
int sym_count, ord;
|
int sym_count, ord;
|
||||||
struct pe_sort_sym **sorted, *p;
|
struct pe_sort_sym **sorted, *p;
|
||||||
TCCState *s1 = pe->s1;
|
TCCState *S = pe->S;
|
||||||
|
|
||||||
FILE *op;
|
FILE *op;
|
||||||
char buf[260];
|
char buf[260];
|
||||||
@ -928,12 +928,12 @@ static void pe_build_exports(struct pe_info *pe)
|
|||||||
sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
|
sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
|
||||||
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
||||||
sym = (ElfW(Sym)*)symtab_section->data + sym_index;
|
sym = (ElfW(Sym)*)symtab_section->data + sym_index;
|
||||||
name = pe_export_name(pe->s1, sym);
|
name = pe_export_name(pe->S, sym);
|
||||||
if (sym->st_other & ST_PE_EXPORT) {
|
if (sym->st_other & ST_PE_EXPORT) {
|
||||||
p = tcc_malloc(sizeof *p);
|
p = tcc_malloc(pe->S, sizeof *p);
|
||||||
p->index = sym_index;
|
p->index = sym_index;
|
||||||
p->name = name;
|
p->name = name;
|
||||||
dynarray_add(&sorted, &sym_count, p);
|
dynarray_add(pe->S, &sorted, &sym_count, p);
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
if (sym->st_other & ST_PE_EXPORT)
|
if (sym->st_other & ST_PE_EXPORT)
|
||||||
@ -957,7 +957,7 @@ static void pe_build_exports(struct pe_info *pe)
|
|||||||
ord_o = name_o + sym_count * sizeof (DWORD);
|
ord_o = name_o + sym_count * sizeof (DWORD);
|
||||||
str_o = ord_o + sym_count * sizeof(WORD);
|
str_o = ord_o + sym_count * sizeof(WORD);
|
||||||
|
|
||||||
hdr = section_ptr_add(pe->thunk, str_o - base_o);
|
hdr = section_ptr_add(pe->S, pe->thunk, str_o - base_o);
|
||||||
hdr->Characteristics = 0;
|
hdr->Characteristics = 0;
|
||||||
hdr->Base = 1;
|
hdr->Base = 1;
|
||||||
hdr->NumberOfFunctions = sym_count;
|
hdr->NumberOfFunctions = sym_count;
|
||||||
@ -966,7 +966,7 @@ static void pe_build_exports(struct pe_info *pe)
|
|||||||
hdr->AddressOfNames = name_o + rva_base;
|
hdr->AddressOfNames = name_o + rva_base;
|
||||||
hdr->AddressOfNameOrdinals = ord_o + rva_base;
|
hdr->AddressOfNameOrdinals = ord_o + rva_base;
|
||||||
hdr->Name = str_o + rva_base;
|
hdr->Name = str_o + rva_base;
|
||||||
put_elf_str(pe->thunk, dllname);
|
put_elf_str(pe->S, pe->thunk, dllname);
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
/* automatically write exports to <output-filename>.def */
|
/* automatically write exports to <output-filename>.def */
|
||||||
@ -974,10 +974,10 @@ static void pe_build_exports(struct pe_info *pe)
|
|||||||
strcpy(tcc_fileextension(buf), ".def");
|
strcpy(tcc_fileextension(buf), ".def");
|
||||||
op = fopen(buf, "wb");
|
op = fopen(buf, "wb");
|
||||||
if (NULL == op) {
|
if (NULL == op) {
|
||||||
tcc_error_noabort("could not create '%s': %s", buf, strerror(errno));
|
tcc_error_noabort(pe->S, "could not create '%s': %s", buf, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
|
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
|
||||||
if (pe->s1->verbose)
|
if (pe->S->verbose)
|
||||||
printf("<- %s (%d symbol%s)\n", buf, sym_count, &"s"[sym_count < 2]);
|
printf("<- %s (%d symbol%s)\n", buf, sym_count, &"s"[sym_count < 2]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -992,7 +992,7 @@ static void pe_build_exports(struct pe_info *pe)
|
|||||||
= pe->thunk->data_offset + rva_base;
|
= pe->thunk->data_offset + rva_base;
|
||||||
*(WORD*)(pe->thunk->data + ord_o)
|
*(WORD*)(pe->thunk->data + ord_o)
|
||||||
= ord;
|
= ord;
|
||||||
put_elf_str(pe->thunk, name);
|
put_elf_str(pe->S, pe->thunk, name);
|
||||||
func_o += sizeof (DWORD);
|
func_o += sizeof (DWORD);
|
||||||
name_o += sizeof (DWORD);
|
name_o += sizeof (DWORD);
|
||||||
ord_o += sizeof (WORD);
|
ord_o += sizeof (WORD);
|
||||||
@ -1002,7 +1002,7 @@ static void pe_build_exports(struct pe_info *pe)
|
|||||||
|
|
||||||
pe->exp_offs = base_o + rva_base;
|
pe->exp_offs = base_o + rva_base;
|
||||||
pe->exp_size = pe->thunk->data_offset - base_o;
|
pe->exp_size = pe->thunk->data_offset - base_o;
|
||||||
dynarray_reset(&sorted, &sym_count);
|
dynarray_reset(pe->S, &sorted, &sym_count);
|
||||||
if (op)
|
if (op)
|
||||||
fclose(op);
|
fclose(op);
|
||||||
}
|
}
|
||||||
@ -1028,11 +1028,11 @@ static void pe_build_reloc (struct pe_info *pe)
|
|||||||
continue;
|
continue;
|
||||||
if (count == 0) { /* new block */
|
if (count == 0) { /* new block */
|
||||||
block_ptr = pe->reloc->data_offset;
|
block_ptr = pe->reloc->data_offset;
|
||||||
section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
|
section_ptr_add(pe->S, pe->reloc, sizeof(struct pe_reloc_header));
|
||||||
offset = addr & 0xFFFFFFFF<<12;
|
offset = addr & 0xFFFFFFFF<<12;
|
||||||
}
|
}
|
||||||
if ((addr -= offset) < (1<<12)) { /* one block spans 4k addresses */
|
if ((addr -= offset) < (1<<12)) { /* one block spans 4k addresses */
|
||||||
WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD));
|
WORD *wp = section_ptr_add(pe->S, pe->reloc, sizeof (WORD));
|
||||||
*wp = addr | PE_IMAGE_REL<<12;
|
*wp = addr | PE_IMAGE_REL<<12;
|
||||||
++count;
|
++count;
|
||||||
continue;
|
continue;
|
||||||
@ -1058,7 +1058,7 @@ static void pe_build_reloc (struct pe_info *pe)
|
|||||||
|
|
||||||
/* fill the last block and ready for a new one */
|
/* fill the last block and ready for a new one */
|
||||||
if (count & 1) /* align for DWORDS */
|
if (count & 1) /* align for DWORDS */
|
||||||
section_ptr_add(pe->reloc, sizeof(WORD)), ++count;
|
section_ptr_add(pe->S, pe->reloc, sizeof(WORD)), ++count;
|
||||||
hdr = (struct pe_reloc_header *)(pe->reloc->data + block_ptr);
|
hdr = (struct pe_reloc_header *)(pe->reloc->data + block_ptr);
|
||||||
hdr -> offset = offset - pe->imagebase;
|
hdr -> offset = offset - pe->imagebase;
|
||||||
hdr -> size = count * sizeof(WORD) + sizeof(struct pe_reloc_header);
|
hdr -> size = count * sizeof(WORD) + sizeof(struct pe_reloc_header);
|
||||||
@ -1110,16 +1110,16 @@ 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;
|
TCCState *S = pe->S;
|
||||||
|
|
||||||
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->S, ".reloc", SHT_PROGBITS, 0);
|
||||||
// pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
|
// pe->thunk = new_section(pe->S, ".iedat", SHT_PROGBITS, SHF_ALLOC);
|
||||||
|
|
||||||
section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));
|
section_order = tcc_malloc(pe->S, pe->S->nb_sections * sizeof (int));
|
||||||
for (o = k = 0 ; k < sec_last; ++k) {
|
for (o = k = 0 ; k < sec_last; ++k) {
|
||||||
for (i = 1; i < s1->nb_sections; ++i) {
|
for (i = 1; i < S->nb_sections; ++i) {
|
||||||
s = s1->sections[i];
|
s = S->sections[i];
|
||||||
if (k == pe_section_class(s))
|
if (k == pe_section_class(s))
|
||||||
section_order[o++] = i;
|
section_order[o++] = i;
|
||||||
}
|
}
|
||||||
@ -1130,10 +1130,10 @@ 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 = s1->sections[k];
|
s = S->sections[k];
|
||||||
c = pe_section_class(s);
|
c = pe_section_class(s);
|
||||||
|
|
||||||
if ((c == sec_stab || c == sec_stabstr) && 0 == s1->do_debug)
|
if ((c == sec_stab || c == sec_stabstr) && 0 == S->do_debug)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (PE_MERGE_DATA && c == sec_bss)
|
if (PE_MERGE_DATA && c == sec_bss)
|
||||||
@ -1164,8 +1164,8 @@ static int pe_assign_addresses (struct pe_info *pe)
|
|||||||
if (si)
|
if (si)
|
||||||
goto add_section;
|
goto add_section;
|
||||||
|
|
||||||
si = tcc_mallocz(sizeof *si);
|
si = tcc_mallocz(pe->S, sizeof *si);
|
||||||
dynarray_add(&pe->sec_info, &pe->sec_count, si);
|
dynarray_add(pe->S, &pe->sec_info, &pe->sec_count, si);
|
||||||
|
|
||||||
strcpy(si->name, s->name);
|
strcpy(si->name, s->name);
|
||||||
si->cls = c;
|
si->cls = c;
|
||||||
@ -1195,10 +1195,10 @@ add_section:
|
|||||||
}
|
}
|
||||||
//printf("%08x %05x %08x %s\n", si->sh_addr, si->sh_size, si->pe_flags, s->name);
|
//printf("%08x %05x %08x %s\n", si->sh_addr, si->sh_size, si->pe_flags, s->name);
|
||||||
}
|
}
|
||||||
tcc_free(section_order);
|
tcc_free(pe->S, section_order);
|
||||||
#if 0
|
#if 0
|
||||||
for (i = 1; i < s1->nb_sections; ++i) {
|
for (i = 1; i < S->nb_sections; ++i) {
|
||||||
Section *s = s1->sections[i];
|
Section *s = S->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",
|
||||||
@ -1215,14 +1215,14 @@ add_section:
|
|||||||
flags & SHF_EXECINSTR ? "exec" : ""
|
flags & SHF_EXECINSTR ? "exec" : ""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
s1->verbose = 2;
|
S->verbose = 2;
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int pe_isafunc(TCCState *s1, int sym_index)
|
static int pe_isafunc(TCCState *S, int sym_index)
|
||||||
{
|
{
|
||||||
Section *sr = text_section->reloc;
|
Section *sr = text_section->reloc;
|
||||||
ElfW_Rel *rel, *rel_end;
|
ElfW_Rel *rel, *rel_end;
|
||||||
@ -1250,7 +1250,7 @@ static int pe_check_symbols(struct pe_info *pe)
|
|||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int sym_index, sym_end;
|
int sym_index, sym_end;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
TCCState *s1 = pe->s1;
|
TCCState *S = pe->S;
|
||||||
|
|
||||||
pe_align_section(text_section, 8);
|
pe_align_section(text_section, 8);
|
||||||
|
|
||||||
@ -1262,7 +1262,7 @@ static int pe_check_symbols(struct pe_info *pe)
|
|||||||
|
|
||||||
const char *name = (char*)symtab_section->link->data + sym->st_name;
|
const char *name = (char*)symtab_section->link->data + sym->st_name;
|
||||||
unsigned type = ELFW(ST_TYPE)(sym->st_info);
|
unsigned type = ELFW(ST_TYPE)(sym->st_info);
|
||||||
int imp_sym = pe_find_import(pe->s1, sym);
|
int imp_sym = pe_find_import(pe->S, sym);
|
||||||
struct import_symbol *is;
|
struct import_symbol *is;
|
||||||
|
|
||||||
if (imp_sym <= 0)
|
if (imp_sym <= 0)
|
||||||
@ -1270,7 +1270,7 @@ static int pe_check_symbols(struct pe_info *pe)
|
|||||||
|
|
||||||
if (type == STT_NOTYPE) {
|
if (type == STT_NOTYPE) {
|
||||||
/* symbols from assembler have no type, find out which */
|
/* symbols from assembler have no type, find out which */
|
||||||
if (pe_isafunc(s1, sym_index))
|
if (pe_isafunc(S, sym_index))
|
||||||
type = STT_FUNC;
|
type = STT_FUNC;
|
||||||
else
|
else
|
||||||
type = STT_OBJECT;
|
type = STT_OBJECT;
|
||||||
@ -1289,7 +1289,7 @@ static int pe_check_symbols(struct pe_info *pe)
|
|||||||
/* add a helper symbol, will be patched later in
|
/* add a helper symbol, will be patched later in
|
||||||
pe_build_imports */
|
pe_build_imports */
|
||||||
sprintf(buffer, "IAT.%s", name);
|
sprintf(buffer, "IAT.%s", name);
|
||||||
is->iat_index = put_elf_sym(
|
is->iat_index = put_elf_sym(pe->S,
|
||||||
symtab_section, 0, sizeof(DWORD),
|
symtab_section, 0, sizeof(DWORD),
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
|
ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
|
||||||
0, SHN_UNDEF, buffer);
|
0, SHN_UNDEF, buffer);
|
||||||
@ -1299,13 +1299,13 @@ static int pe_check_symbols(struct pe_info *pe)
|
|||||||
|
|
||||||
/* add the 'jmp IAT[x]' instruction */
|
/* add the 'jmp IAT[x]' instruction */
|
||||||
#ifdef TCC_TARGET_ARM
|
#ifdef TCC_TARGET_ARM
|
||||||
p = section_ptr_add(text_section, 8+4); // room for code and address
|
p = section_ptr_add(pe->S, text_section, 8+4); // room for code and address
|
||||||
write32le(p + 0, 0xE59FC000); // arm code ldr ip, [pc] ; PC+8+0 = 0001xxxx
|
write32le(p + 0, 0xE59FC000); // arm code ldr ip, [pc] ; PC+8+0 = 0001xxxx
|
||||||
write32le(p + 4, 0xE59CF000); // arm code ldr pc, [ip]
|
write32le(p + 4, 0xE59CF000); // arm code ldr pc, [ip]
|
||||||
put_elf_reloc(symtab_section, text_section,
|
put_elf_reloc(symtab_section, text_section,
|
||||||
offset + 8, R_XXX_THUNKFIX, is->iat_index); // offset to IAT position
|
offset + 8, R_XXX_THUNKFIX, is->iat_index); // offset to IAT position
|
||||||
#else
|
#else
|
||||||
p = section_ptr_add(text_section, 8);
|
p = section_ptr_add(pe->S, text_section, 8);
|
||||||
write16le(p, 0x25FF);
|
write16le(p, 0x25FF);
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
write32le(p + 2, (DWORD)-4);
|
write32le(p + 2, (DWORD)-4);
|
||||||
@ -1336,11 +1336,11 @@ static int pe_check_symbols(struct pe_info *pe)
|
|||||||
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
|
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
|
||||||
/* STB_WEAK undefined symbols are accepted */
|
/* STB_WEAK undefined symbols are accepted */
|
||||||
continue;
|
continue;
|
||||||
tcc_error_noabort("undefined symbol '%s'%s", name,
|
tcc_error_noabort(pe->S, "undefined symbol '%s'%s", name,
|
||||||
imp_sym < 0 ? ", missing __declspec(dllimport)?":"");
|
imp_sym < 0 ? ", missing __declspec(dllimport)?":"");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
} else if (pe->s1->rdynamic
|
} else if (pe->S->rdynamic
|
||||||
&& ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
|
&& ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
|
||||||
/* if -rdynamic option, then export all non local symbols */
|
/* if -rdynamic option, then export all non local symbols */
|
||||||
sym->st_other |= ST_PE_EXPORT;
|
sym->st_other |= ST_PE_EXPORT;
|
||||||
@ -1473,17 +1473,17 @@ static void pe_print_section(FILE * f, Section * s)
|
|||||||
fprintf(f, "\n\n");
|
fprintf(f, "\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pe_print_sections(TCCState *s1, const char *fname)
|
static void pe_print_sections(TCCState *S, const char *fname)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int i;
|
int i;
|
||||||
f = fopen(fname, "w");
|
f = fopen(fname, "w");
|
||||||
for (i = 1; i < s1->nb_sections; ++i) {
|
for (i = 1; i < S->nb_sections; ++i) {
|
||||||
s = s1->sections[i];
|
s = S->sections[i];
|
||||||
pe_print_section(f, s);
|
pe_print_section(f, s);
|
||||||
}
|
}
|
||||||
pe_print_section(f, s1->dynsymtab_section);
|
pe_print_section(f, S->dynsymtab_section);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1492,7 +1492,7 @@ static void pe_print_sections(TCCState *s1, const char *fname)
|
|||||||
/* helper function for load/store to insert one more indirection */
|
/* helper function for load/store to insert one more indirection */
|
||||||
|
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||||
ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
|
ST_FUNC SValue *pe_getimport(TCCState* S, SValue *sv, SValue *v2)
|
||||||
{
|
{
|
||||||
int r2;
|
int r2;
|
||||||
if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST))
|
if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST))
|
||||||
@ -1505,14 +1505,14 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
|
|||||||
v2->r = VT_CONST | VT_SYM | VT_LVAL;
|
v2->r = VT_CONST | VT_SYM | VT_LVAL;
|
||||||
v2->sym = sv->sym;
|
v2->sym = sv->sym;
|
||||||
|
|
||||||
r2 = get_reg(RC_INT);
|
r2 = get_reg(S, RC_INT);
|
||||||
load(r2, v2);
|
load(S, r2, v2);
|
||||||
v2->r = r2;
|
v2->r = r2;
|
||||||
if ((uint32_t)sv->c.i) {
|
if ((uint32_t)sv->c.i) {
|
||||||
vpushv(v2);
|
vpushv(S, v2);
|
||||||
vpushi(sv->c.i);
|
vpushi(S, sv->c.i);
|
||||||
gen_opi('+');
|
gen_opi(S, '+');
|
||||||
*v2 = *vtop--;
|
*v2 = *S->tccgen_vtop--;
|
||||||
}
|
}
|
||||||
v2->type.t = sv->type.t;
|
v2->type.t = sv->type.t;
|
||||||
v2->r |= sv->r & VT_LVAL;
|
v2->r |= sv->r & VT_LVAL;
|
||||||
@ -1520,10 +1520,10 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value)
|
ST_FUNC int pe_putimport(TCCState *S, int dllindex, const char *name, addr_t value)
|
||||||
{
|
{
|
||||||
return set_elf_sym(
|
return set_elf_sym(
|
||||||
s1->dynsymtab_section,
|
S->dynsymtab_section,
|
||||||
value,
|
value,
|
||||||
dllindex, /* st_size */
|
dllindex, /* st_size */
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
|
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
|
||||||
@ -1533,14 +1533,14 @@ ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t va
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pe_add_dllref(TCCState *s1, const char *dllname)
|
static int pe_add_dllref(TCCState *S, const char *dllname)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < s1->nb_loaded_dlls; ++i)
|
for (i = 0; i < S->nb_loaded_dlls; ++i)
|
||||||
if (0 == strcmp(s1->loaded_dlls[i]->name, dllname))
|
if (0 == strcmp(S->loaded_dlls[i]->name, dllname))
|
||||||
return i + 1;
|
return i + 1;
|
||||||
tcc_add_dllref(s1, dllname);
|
tcc_add_dllref(S, dllname);
|
||||||
return s1->nb_loaded_dlls;
|
return S->nb_loaded_dlls;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
||||||
@ -1551,7 +1551,7 @@ static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
|
|
||||||
static int get_dllexports(int fd, char **pp)
|
static int get_dllexports(TCCState* S, int fd, char **pp)
|
||||||
{
|
{
|
||||||
int l, i, n, n0, ret;
|
int l, i, n, n0, ret;
|
||||||
char *p;
|
char *p;
|
||||||
@ -1618,9 +1618,9 @@ found:
|
|||||||
namep += sizeof ptr;
|
namep += sizeof ptr;
|
||||||
for (l = 0;;) {
|
for (l = 0;;) {
|
||||||
if (n+1 >= n0)
|
if (n+1 >= n0)
|
||||||
p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
|
p = tcc_realloc(S, p, n0 = n0 ? n0 * 2 : 256);
|
||||||
if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
|
if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
|
||||||
tcc_free(p), p = NULL;
|
tcc_free(S, p), p = NULL;
|
||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
if (p[n++] == 0)
|
if (p[n++] == 0)
|
||||||
@ -1641,7 +1641,7 @@ the_end:
|
|||||||
* as generated by 'windres.exe -O coff ...'.
|
* as generated by 'windres.exe -O coff ...'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int pe_load_res(TCCState *s1, int fd)
|
static int pe_load_res(TCCState *S, int fd)
|
||||||
{
|
{
|
||||||
struct pe_rsrc_header hdr;
|
struct pe_rsrc_header hdr;
|
||||||
Section *rsrc_section;
|
Section *rsrc_section;
|
||||||
@ -1657,13 +1657,13 @@ static int pe_load_res(TCCState *s1, int fd)
|
|||||||
|| strcmp((char*)hdr.sectionhdr.Name, ".rsrc") != 0)
|
|| strcmp((char*)hdr.sectionhdr.Name, ".rsrc") != 0)
|
||||||
goto quit;
|
goto quit;
|
||||||
|
|
||||||
rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
|
rsrc_section = new_section(S, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
|
||||||
ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
|
ptr = section_ptr_add(S, rsrc_section, hdr.sectionhdr.SizeOfRawData);
|
||||||
offs = hdr.sectionhdr.PointerToRawData;
|
offs = hdr.sectionhdr.PointerToRawData;
|
||||||
if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData))
|
if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData))
|
||||||
goto quit;
|
goto quit;
|
||||||
offs = hdr.sectionhdr.PointerToRelocations;
|
offs = hdr.sectionhdr.PointerToRelocations;
|
||||||
sym_index = put_elf_sym(symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc");
|
sym_index = put_elf_sym(S, symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc");
|
||||||
for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) {
|
for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) {
|
||||||
struct pe_rsrc_reloc rel;
|
struct pe_rsrc_reloc rel;
|
||||||
if (!read_mem(fd, offs, &rel, sizeof rel))
|
if (!read_mem(fd, offs, &rel, sizeof rel))
|
||||||
@ -1709,12 +1709,12 @@ static char *get_token(char **s, char *f)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pe_load_def(TCCState *s1, int fd)
|
static int pe_load_def(TCCState *S, int fd)
|
||||||
{
|
{
|
||||||
int state = 0, ret = -1, dllindex = 0, ord;
|
int state = 0, ret = -1, dllindex = 0, ord;
|
||||||
char dllname[80], *buf, *line, *p, *x, next;
|
char dllname[80], *buf, *line, *p, *x, next;
|
||||||
|
|
||||||
buf = tcc_load_text(fd);
|
buf = tcc_load_text(S, fd);
|
||||||
for (line = buf;; ++line) {
|
for (line = buf;; ++line) {
|
||||||
p = get_token(&line, &next);
|
p = get_token(&line, &next);
|
||||||
if (!(*p && *p != ';'))
|
if (!(*p && *p != ';'))
|
||||||
@ -1732,7 +1732,7 @@ static int pe_load_def(TCCState *s1, int fd)
|
|||||||
++state;
|
++state;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
dllindex = pe_add_dllref(s1, dllname);
|
dllindex = pe_add_dllref(S, dllname);
|
||||||
++state;
|
++state;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
@ -1743,7 +1743,7 @@ static int pe_load_def(TCCState *s1, int fd)
|
|||||||
ord = (int)strtol(x + 1, &x, 10);
|
ord = (int)strtol(x + 1, &x, 10);
|
||||||
}
|
}
|
||||||
//printf("token %s ; %s : %d\n", dllname, p, ord);
|
//printf("token %s ; %s : %d\n", dllname, p, ord);
|
||||||
pe_putimport(s1, dllindex, p, ord);
|
pe_putimport(S, dllindex, p, ord);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
skip:
|
skip:
|
||||||
@ -1754,63 +1754,63 @@ skip:
|
|||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
quit:
|
quit:
|
||||||
tcc_free(buf);
|
tcc_free(S, buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
|
|
||||||
static int pe_load_dll(TCCState *s1, int fd, const char *filename)
|
static int pe_load_dll(TCCState *S, int fd, const char *filename)
|
||||||
{
|
{
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
int index, ret;
|
int index, ret;
|
||||||
|
|
||||||
ret = get_dllexports(fd, &p);
|
ret = get_dllexports(S, fd, &p);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (p) {
|
} else if (p) {
|
||||||
index = pe_add_dllref(s1, filename);
|
index = pe_add_dllref(S, filename);
|
||||||
for (q = p; *q; q += 1 + strlen(q))
|
for (q = p; *q; q += 1 + strlen(q))
|
||||||
pe_putimport(s1, index, q, 0);
|
pe_putimport(S, index, q, 0);
|
||||||
tcc_free(p);
|
tcc_free(S, p);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename)
|
ST_FUNC int pe_load_file(TCCState *S, int fd, const char *filename)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
char buf[10];
|
char buf[10];
|
||||||
if (0 == strcmp(tcc_fileextension(filename), ".def"))
|
if (0 == strcmp(tcc_fileextension(filename), ".def"))
|
||||||
ret = pe_load_def(s1, fd);
|
ret = pe_load_def(S, fd);
|
||||||
else if (pe_load_res(s1, fd) == 0)
|
else if (pe_load_res(S, fd) == 0)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ", 2))
|
else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ", 2))
|
||||||
ret = pe_load_dll(s1, fd, filename);
|
ret = pe_load_dll(S, fd, filename);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
|
PUB_FUNC int tcc_get_dllexports(TCCState *S, const char *filename, char **pp)
|
||||||
{
|
{
|
||||||
int ret, fd = open(filename, O_RDONLY | O_BINARY);
|
int ret, fd = open(filename, O_RDONLY | O_BINARY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
ret = get_dllexports(fd, pp);
|
ret = get_dllexports(S, fd, pp);
|
||||||
close(fd);
|
close(fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
static unsigned pe_add_uwwind_info(TCCState *s1)
|
static unsigned pe_add_uwwind_info(TCCState *S)
|
||||||
{
|
{
|
||||||
if (NULL == s1->uw_pdata) {
|
if (NULL == S->uw_pdata) {
|
||||||
s1->uw_pdata = find_section(s1, ".pdata");
|
S->uw_pdata = find_section(S, ".pdata");
|
||||||
s1->uw_pdata->sh_addralign = 4;
|
S->uw_pdata->sh_addralign = 4;
|
||||||
}
|
}
|
||||||
if (0 == s1->uw_sym)
|
if (0 == S->uw_sym)
|
||||||
s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base");
|
S->uw_sym = put_elf_sym(S, symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base");
|
||||||
if (0 == s1->uw_offs) {
|
if (0 == S->uw_offs) {
|
||||||
/* As our functions all have the same stackframe, we use one entry for all */
|
/* As our functions all have the same stackframe, we use one entry for all */
|
||||||
static const unsigned char uw_info[] = {
|
static const unsigned char uw_info[] = {
|
||||||
0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
|
0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
|
||||||
@ -1826,18 +1826,17 @@ static unsigned pe_add_uwwind_info(TCCState *s1)
|
|||||||
Section *s = text_section;
|
Section *s = text_section;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
|
||||||
section_ptr_add(s, -s->data_offset & 3); /* align */
|
section_ptr_add(S, s, -s->data_offset & 3); /* align */
|
||||||
s1->uw_offs = s->data_offset;
|
S->uw_offs = s->data_offset;
|
||||||
p = section_ptr_add(s, sizeof uw_info);
|
p = section_ptr_add(S, s, sizeof uw_info);
|
||||||
memcpy(p, uw_info, sizeof uw_info);
|
memcpy(p, uw_info, sizeof uw_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
return s1->uw_offs;
|
return S->uw_offs;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
ST_FUNC void pe_add_unwind_data(TCCState *S, unsigned start, unsigned end, unsigned stack)
|
||||||
{
|
{
|
||||||
TCCState *s1 = tcc_state;
|
|
||||||
Section *pd;
|
Section *pd;
|
||||||
unsigned o, n, d;
|
unsigned o, n, d;
|
||||||
struct /* _RUNTIME_FUNCTION */ {
|
struct /* _RUNTIME_FUNCTION */ {
|
||||||
@ -1846,10 +1845,10 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
|||||||
DWORD UnwindData;
|
DWORD UnwindData;
|
||||||
} *p;
|
} *p;
|
||||||
|
|
||||||
d = pe_add_uwwind_info(s1);
|
d = pe_add_uwwind_info(S);
|
||||||
pd = s1->uw_pdata;
|
pd = S->uw_pdata;
|
||||||
o = pd->data_offset;
|
o = pd->data_offset;
|
||||||
p = section_ptr_add(pd, sizeof *p);
|
p = section_ptr_add(S, pd, sizeof *p);
|
||||||
|
|
||||||
/* record this function */
|
/* record this function */
|
||||||
p->BeginAddress = start;
|
p->BeginAddress = start;
|
||||||
@ -1858,7 +1857,7 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
|||||||
|
|
||||||
/* put relocations on it */
|
/* put relocations on it */
|
||||||
for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
|
for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
|
||||||
put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
|
put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, S->uw_sym);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
@ -1868,18 +1867,18 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
|||||||
#define PE_STDSYM(n,s) "_" n s
|
#define PE_STDSYM(n,s) "_" n s
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void tcc_add_support(TCCState *s1, const char *filename)
|
static void tcc_add_support(TCCState *S, const char *filename)
|
||||||
{
|
{
|
||||||
if (tcc_add_dll(s1, filename, 0) < 0)
|
if (tcc_add_dll(S, filename, 0) < 0)
|
||||||
tcc_error_noabort("%s not found", filename);
|
tcc_error_noabort(S, "%s not found", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
static void pe_add_runtime(TCCState *S, struct pe_info *pe)
|
||||||
{
|
{
|
||||||
const char *start_symbol;
|
const char *start_symbol;
|
||||||
int pe_type;
|
int pe_type;
|
||||||
|
|
||||||
if (TCC_OUTPUT_DLL == s1->output_type) {
|
if (TCC_OUTPUT_DLL == S->output_type) {
|
||||||
pe_type = PE_DLL;
|
pe_type = PE_DLL;
|
||||||
start_symbol = PE_STDSYM("__dllstart","@12");
|
start_symbol = PE_STDSYM("__dllstart","@12");
|
||||||
} else {
|
} else {
|
||||||
@ -1902,61 +1901,61 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
|||||||
pe_type = PE_EXE;
|
pe_type = PE_EXE;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (TCC_OUTPUT_MEMORY == s1->output_type)
|
if (TCC_OUTPUT_MEMORY == S->output_type)
|
||||||
start_symbol = run_symbol;
|
start_symbol = run_symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
pe->start_symbol = start_symbol + 1;
|
pe->start_symbol = start_symbol + 1;
|
||||||
if (!s1->leading_underscore || strchr(start_symbol, '@'))
|
if (!S->leading_underscore || strchr(start_symbol, '@'))
|
||||||
++start_symbol;
|
++start_symbol;
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
if (s1->do_backtrace) {
|
if (S->do_backtrace) {
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL)
|
if (S->do_bounds_check && S->output_type != TCC_OUTPUT_DLL)
|
||||||
tcc_add_support(s1, "bcheck.o");
|
tcc_add_support(S, "bcheck.o");
|
||||||
#endif
|
#endif
|
||||||
if (s1->output_type == TCC_OUTPUT_EXE)
|
if (S->output_type == TCC_OUTPUT_EXE)
|
||||||
tcc_add_support(s1, "bt-exe.o");
|
tcc_add_support(S, "bt-exe.o");
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
if (S->output_type == TCC_OUTPUT_DLL)
|
||||||
tcc_add_support(s1, "bt-dll.o");
|
tcc_add_support(S, "bt-dll.o");
|
||||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
if (S->output_type != TCC_OUTPUT_DLL)
|
||||||
tcc_add_support(s1, "bt-log.o");
|
tcc_add_support(S, "bt-log.o");
|
||||||
if (s1->output_type != TCC_OUTPUT_MEMORY)
|
if (S->output_type != TCC_OUTPUT_MEMORY)
|
||||||
tcc_add_btstub(s1);
|
tcc_add_btstub(S);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* grab the startup code from libtcc1.a */
|
/* grab the startup code from libtcc1.a */
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main)
|
if (TCC_OUTPUT_MEMORY != S->output_type || S->runtime_main)
|
||||||
#endif
|
#endif
|
||||||
set_global_sym(s1, start_symbol, NULL, 0);
|
set_global_sym(S, start_symbol, NULL, 0);
|
||||||
|
|
||||||
if (0 == s1->nostdlib) {
|
if (0 == S->nostdlib) {
|
||||||
static const char * const libs[] = {
|
static const char * const libs[] = {
|
||||||
"msvcrt", "kernel32", "", "user32", "gdi32", NULL
|
"msvcrt", "kernel32", "", "user32", "gdi32", NULL
|
||||||
};
|
};
|
||||||
const char * const *pp, *p;
|
const char * const *pp, *p;
|
||||||
if (TCC_LIBTCC1[0])
|
if (TCC_LIBTCC1[0])
|
||||||
tcc_add_support(s1, TCC_LIBTCC1);
|
tcc_add_support(S, TCC_LIBTCC1);
|
||||||
for (pp = libs; 0 != (p = *pp); ++pp) {
|
for (pp = libs; 0 != (p = *pp); ++pp) {
|
||||||
if (*p)
|
if (*p)
|
||||||
tcc_add_library_err(s1, p);
|
tcc_add_library_err(S, p);
|
||||||
else if (PE_DLL != pe_type && PE_GUI != pe_type)
|
else if (PE_DLL != pe_type && PE_GUI != pe_type)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* need this for 'tccelf.c:relocate_sections()' */
|
/* need this for 'tccelf.c:relocate_sections()' */
|
||||||
if (TCC_OUTPUT_DLL == s1->output_type)
|
if (TCC_OUTPUT_DLL == S->output_type)
|
||||||
s1->output_type = TCC_OUTPUT_EXE;
|
S->output_type = TCC_OUTPUT_EXE;
|
||||||
if (TCC_OUTPUT_MEMORY == s1->output_type)
|
if (TCC_OUTPUT_MEMORY == S->output_type)
|
||||||
pe_type = PE_RUN;
|
pe_type = PE_RUN;
|
||||||
pe->type = pe_type;
|
pe->type = pe_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pe_set_options(TCCState * s1, struct pe_info *pe)
|
static void pe_set_options(TCCState * S, struct pe_info *pe)
|
||||||
{
|
{
|
||||||
if (PE_DLL == pe->type) {
|
if (PE_DLL == pe->type) {
|
||||||
/* XXX: check if is correct for arm-pe target */
|
/* XXX: check if is correct for arm-pe target */
|
||||||
@ -1979,8 +1978,8 @@ static void pe_set_options(TCCState * s1, struct pe_info *pe)
|
|||||||
pe->subsystem = 3;
|
pe->subsystem = 3;
|
||||||
#endif
|
#endif
|
||||||
/* Allow override via -Wl,-subsystem=... option */
|
/* Allow override via -Wl,-subsystem=... option */
|
||||||
if (s1->pe_subsystem != 0)
|
if (S->pe_subsystem != 0)
|
||||||
pe->subsystem = s1->pe_subsystem;
|
pe->subsystem = S->pe_subsystem;
|
||||||
|
|
||||||
/* set default file/section alignment */
|
/* set default file/section alignment */
|
||||||
if (pe->subsystem == 1) {
|
if (pe->subsystem == 1) {
|
||||||
@ -1991,58 +1990,58 @@ static void pe_set_options(TCCState * s1, struct pe_info *pe)
|
|||||||
pe->file_align = 0x200;
|
pe->file_align = 0x200;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->section_align != 0)
|
if (S->section_align != 0)
|
||||||
pe->section_align = s1->section_align;
|
pe->section_align = S->section_align;
|
||||||
if (s1->pe_file_align != 0)
|
if (S->pe_file_align != 0)
|
||||||
pe->file_align = s1->pe_file_align;
|
pe->file_align = S->pe_file_align;
|
||||||
|
|
||||||
if ((pe->subsystem >= 10) && (pe->subsystem <= 12))
|
if ((pe->subsystem >= 10) && (pe->subsystem <= 12))
|
||||||
pe->imagebase = 0;
|
pe->imagebase = 0;
|
||||||
|
|
||||||
if (s1->has_text_addr)
|
if (S->has_text_addr)
|
||||||
pe->imagebase = s1->text_addr;
|
pe->imagebase = S->text_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
ST_FUNC int pe_output_file(TCCState *S, const char *filename)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct pe_info pe;
|
struct pe_info pe;
|
||||||
|
|
||||||
memset(&pe, 0, sizeof pe);
|
memset(&pe, 0, sizeof pe);
|
||||||
pe.filename = filename;
|
pe.filename = filename;
|
||||||
pe.s1 = s1;
|
pe.S = S;
|
||||||
s1->filetype = 0;
|
S->filetype = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
tcc_add_bcheck(s1);
|
tcc_add_bcheck(S);
|
||||||
#endif
|
#endif
|
||||||
tcc_add_pragma_libs(s1);
|
tcc_add_pragma_libs(S);
|
||||||
pe_add_runtime(s1, &pe);
|
pe_add_runtime(S, &pe);
|
||||||
resolve_common_syms(s1);
|
resolve_common_syms(S);
|
||||||
pe_set_options(s1, &pe);
|
pe_set_options(S, &pe);
|
||||||
|
|
||||||
ret = pe_check_symbols(&pe);
|
ret = pe_check_symbols(&pe);
|
||||||
if (ret)
|
if (ret)
|
||||||
;
|
;
|
||||||
else if (filename) {
|
else if (filename) {
|
||||||
pe_assign_addresses(&pe);
|
pe_assign_addresses(&pe);
|
||||||
relocate_syms(s1, s1->symtab, 0);
|
relocate_syms(S, S->symtab, 0);
|
||||||
s1->pe_imagebase = pe.imagebase;
|
S->pe_imagebase = pe.imagebase;
|
||||||
relocate_sections(s1);
|
relocate_sections(S);
|
||||||
pe.start_addr = (DWORD)
|
pe.start_addr = (DWORD)
|
||||||
(get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase);
|
(get_sym_addr(S, pe.start_symbol, 1, 1) - pe.imagebase);
|
||||||
if (s1->nb_errors)
|
if (S->nb_errors)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
else
|
else
|
||||||
ret = pe_write(&pe);
|
ret = pe_write(&pe);
|
||||||
dynarray_reset(&pe.sec_info, &pe.sec_count);
|
dynarray_reset(S, &pe.sec_info, &pe.sec_count);
|
||||||
} else {
|
} else {
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
pe.thunk = data_section;
|
pe.thunk = data_section;
|
||||||
pe_build_imports(&pe);
|
pe_build_imports(&pe);
|
||||||
s1->runtime_main = pe.start_symbol;
|
S->runtime_main = pe.start_symbol;
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
s1->uw_pdata = find_section(s1, ".pdata");
|
S->uw_pdata = find_section(S, ".pdata");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -2050,8 +2049,8 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
|||||||
pe_free_imports(&pe);
|
pe_free_imports(&pe);
|
||||||
|
|
||||||
#if PE_PRINT_SECTIONS
|
#if PE_PRINT_SECTIONS
|
||||||
if (s1->g_debug & 8)
|
if (S->g_debug & 8)
|
||||||
pe_print_sections(s1, "tcc.log");
|
pe_print_sections(S, "tcc.log");
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
261
tccqsort.c
Normal file
261
tccqsort.c
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
/* Copyright (C) 2011 by Valentin Ochs
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Minor changes by Rich Felker for integration in musl, 2011-04-27. */
|
||||||
|
|
||||||
|
/* Smoothsort, an adaptive variant of Heapsort. Memory usage: O(1).
|
||||||
|
Run time: Worst case O(n log n), close to O(n) in the mostly-sorted case. */
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
//#include "atomic.h"
|
||||||
|
#ifndef a_ctz_32
|
||||||
|
#define a_ctz_32 a_ctz_32
|
||||||
|
static inline int a_ctz_32(uint32_t x)
|
||||||
|
{
|
||||||
|
#ifdef a_clz_32
|
||||||
|
return 31-a_clz_32(x&-x);
|
||||||
|
#else
|
||||||
|
static const char debruijn32[32] = {
|
||||||
|
0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
|
||||||
|
31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
|
||||||
|
};
|
||||||
|
return debruijn32[(x&-x)*0x076be629 >> 27];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef a_ctz_64
|
||||||
|
#define a_ctz_64 a_ctz_64
|
||||||
|
static inline int a_ctz_64(uint64_t x)
|
||||||
|
{
|
||||||
|
static const char debruijn64[64] = {
|
||||||
|
0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
|
||||||
|
62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
|
||||||
|
63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
|
||||||
|
51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
|
||||||
|
};
|
||||||
|
if (sizeof(long) < 8) {
|
||||||
|
uint32_t y = x;
|
||||||
|
if (!y) {
|
||||||
|
y = x>>32;
|
||||||
|
return 32 + a_ctz_32(y);
|
||||||
|
}
|
||||||
|
return a_ctz_32(y);
|
||||||
|
}
|
||||||
|
return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline int a_ctz_l(unsigned long x)
|
||||||
|
{
|
||||||
|
return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ntz(x) a_ctz_l((x))
|
||||||
|
|
||||||
|
typedef int (*tcc_cmpfun)(const void *, const void *, void *);
|
||||||
|
|
||||||
|
static inline int pntz(size_t p[2]) {
|
||||||
|
int r = ntz(p[0] - 1);
|
||||||
|
if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cycle(size_t width, unsigned char* ar[], int n)
|
||||||
|
{
|
||||||
|
unsigned char tmp[256];
|
||||||
|
size_t l;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(n < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ar[n] = tmp;
|
||||||
|
while(width) {
|
||||||
|
l = sizeof(tmp) < width ? sizeof(tmp) : width;
|
||||||
|
memcpy(ar[n], ar[0], l);
|
||||||
|
for(i = 0; i < n; i++) {
|
||||||
|
memcpy(ar[i], ar[i + 1], l);
|
||||||
|
ar[i] += l;
|
||||||
|
}
|
||||||
|
width -= l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shl() and shr() need n > 0 */
|
||||||
|
static inline void shl(size_t p[2], int n)
|
||||||
|
{
|
||||||
|
if(n >= 8 * sizeof(size_t)) {
|
||||||
|
n -= 8 * sizeof(size_t);
|
||||||
|
p[1] = p[0];
|
||||||
|
p[0] = 0;
|
||||||
|
}
|
||||||
|
p[1] <<= n;
|
||||||
|
p[1] |= p[0] >> (sizeof(size_t) * 8 - n);
|
||||||
|
p[0] <<= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void shr(size_t p[2], int n)
|
||||||
|
{
|
||||||
|
if(n >= 8 * sizeof(size_t)) {
|
||||||
|
n -= 8 * sizeof(size_t);
|
||||||
|
p[0] = p[1];
|
||||||
|
p[1] = 0;
|
||||||
|
}
|
||||||
|
p[0] >>= n;
|
||||||
|
p[0] |= p[1] << (sizeof(size_t) * 8 - n);
|
||||||
|
p[1] >>= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sift(unsigned char *head, size_t width, tcc_cmpfun cmp, int pshift, size_t lp[], void* ctx)
|
||||||
|
{
|
||||||
|
unsigned char *rt, *lf;
|
||||||
|
unsigned char *ar[14 * sizeof(size_t) + 1];
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
ar[0] = head;
|
||||||
|
while(pshift > 1) {
|
||||||
|
rt = head - width;
|
||||||
|
lf = head - width - lp[pshift - 2];
|
||||||
|
|
||||||
|
if((*cmp)(ar[0], lf, ctx) >= 0 && (*cmp)(ar[0], rt, ctx) >= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if((*cmp)(lf, rt, ctx) >= 0) {
|
||||||
|
ar[i++] = lf;
|
||||||
|
head = lf;
|
||||||
|
pshift -= 1;
|
||||||
|
} else {
|
||||||
|
ar[i++] = rt;
|
||||||
|
head = rt;
|
||||||
|
pshift -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cycle(width, ar, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void trinkle(unsigned char *head, size_t width, tcc_cmpfun cmp, size_t pp[2], int pshift, int trusty, size_t lp[], void* ctx)
|
||||||
|
{
|
||||||
|
unsigned char *stepson,
|
||||||
|
*rt, *lf;
|
||||||
|
size_t p[2];
|
||||||
|
unsigned char *ar[14 * sizeof(size_t) + 1];
|
||||||
|
int i = 1;
|
||||||
|
int trail;
|
||||||
|
|
||||||
|
p[0] = pp[0];
|
||||||
|
p[1] = pp[1];
|
||||||
|
|
||||||
|
ar[0] = head;
|
||||||
|
while(p[0] != 1 || p[1] != 0) {
|
||||||
|
stepson = head - lp[pshift];
|
||||||
|
if((*cmp)(stepson, ar[0], ctx) <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!trusty && pshift > 1) {
|
||||||
|
rt = head - width;
|
||||||
|
lf = head - width - lp[pshift - 2];
|
||||||
|
if((*cmp)(rt, stepson, ctx) >= 0 || (*cmp)(lf, stepson, ctx) >= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ar[i++] = stepson;
|
||||||
|
head = stepson;
|
||||||
|
trail = pntz(p);
|
||||||
|
shr(p, trail);
|
||||||
|
pshift += trail;
|
||||||
|
trusty = 0;
|
||||||
|
}
|
||||||
|
if(!trusty) {
|
||||||
|
cycle(width, ar, i);
|
||||||
|
sift(head, width, cmp, pshift, lp, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBTCCAPI void tcc_qsort_s(void *base, size_t nel, size_t width, tcc_cmpfun cmp, void *ctx)
|
||||||
|
{
|
||||||
|
size_t lp[12*sizeof(size_t)];
|
||||||
|
size_t i, size = width * nel;
|
||||||
|
unsigned char *head, *high;
|
||||||
|
size_t p[2] = {1, 0};
|
||||||
|
int pshift = 1;
|
||||||
|
int trail;
|
||||||
|
|
||||||
|
if (!size) return;
|
||||||
|
|
||||||
|
head = base;
|
||||||
|
high = head + size - width;
|
||||||
|
|
||||||
|
/* Precompute Leonardo numbers, scaled by element width */
|
||||||
|
for(lp[0]=lp[1]=width, i=2; (lp[i]=lp[i-2]+lp[i-1]+width) < size; i++);
|
||||||
|
|
||||||
|
while(head < high) {
|
||||||
|
if((p[0] & 3) == 3) {
|
||||||
|
sift(head, width, cmp, pshift, lp, ctx);
|
||||||
|
shr(p, 2);
|
||||||
|
pshift += 2;
|
||||||
|
} else {
|
||||||
|
if(lp[pshift - 1] >= high - head) {
|
||||||
|
trinkle(head, width, cmp, p, pshift, 0, lp, ctx);
|
||||||
|
} else {
|
||||||
|
sift(head, width, cmp, pshift, lp, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pshift == 1) {
|
||||||
|
shl(p, 1);
|
||||||
|
pshift = 0;
|
||||||
|
} else {
|
||||||
|
shl(p, pshift - 1);
|
||||||
|
pshift = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p[0] |= 1;
|
||||||
|
head += width;
|
||||||
|
}
|
||||||
|
|
||||||
|
trinkle(head, width, cmp, p, pshift, 0, lp, ctx);
|
||||||
|
|
||||||
|
while(pshift != 1 || p[0] != 1 || p[1] != 0) {
|
||||||
|
if(pshift <= 1) {
|
||||||
|
trail = pntz(p);
|
||||||
|
shr(p, trail);
|
||||||
|
pshift += trail;
|
||||||
|
} else {
|
||||||
|
shl(p, 2);
|
||||||
|
pshift -= 2;
|
||||||
|
p[0] ^= 7;
|
||||||
|
shr(p, 1);
|
||||||
|
trinkle(head - lp[pshift] - width, width, cmp, p, pshift + 1, 1, lp, ctx);
|
||||||
|
shl(p, 1);
|
||||||
|
p[0] |= 1;
|
||||||
|
trinkle(head - width, width, cmp, p, pshift, 1, lp, ctx);
|
||||||
|
}
|
||||||
|
head -= width;
|
||||||
|
}
|
||||||
|
}
|
128
tccrun.c
128
tccrun.c
@ -55,11 +55,11 @@ static void rt_exit(int code);
|
|||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length);
|
static void set_pages_executable(TCCState *S, 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 *S, void *ptr, addr_t ptr_diff);
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
static void *win64_add_function_table(TCCState *s1);
|
static void *win64_add_function_table(TCCState *S);
|
||||||
static void win64_del_function_table(void *);
|
static void win64_del_function_table(void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -67,15 +67,15 @@ static void win64_del_function_table(void *);
|
|||||||
/* Do all relocations (needed before using tcc_get_symbol())
|
/* Do all relocations (needed before using tcc_get_symbol())
|
||||||
Returns -1 on error. */
|
Returns -1 on error. */
|
||||||
|
|
||||||
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
|
LIBTCCAPI int tcc_relocate(TCCState *S, void *ptr)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
addr_t ptr_diff = 0;
|
addr_t ptr_diff = 0;
|
||||||
|
|
||||||
if (TCC_RELOCATE_AUTO != ptr)
|
if (TCC_RELOCATE_AUTO != ptr)
|
||||||
return tcc_relocate_ex(s1, ptr, 0);
|
return tcc_relocate_ex(S, ptr, 0);
|
||||||
|
|
||||||
size = tcc_relocate_ex(s1, NULL, 0);
|
size = tcc_relocate_ex(S, NULL, 0);
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -93,52 +93,52 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
|
|||||||
/* mmap RX memory at a fixed distance */
|
/* mmap RX memory at a fixed distance */
|
||||||
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(S, "tccrun: could not map memory");
|
||||||
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);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ptr = tcc_malloc(size);
|
ptr = tcc_malloc(S, size);
|
||||||
#endif
|
#endif
|
||||||
tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */
|
tcc_relocate_ex(S, ptr, ptr_diff); /* no more errors expected */
|
||||||
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);
|
dynarray_add(S, &S->runtime_mem, &S->nb_runtime_mem, (void*)(addr_t)size);
|
||||||
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr);
|
dynarray_add(S, &S->runtime_mem, &S->nb_runtime_mem, ptr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tcc_run_free(TCCState *s1)
|
ST_FUNC void tcc_run_free(TCCState *S)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < s1->nb_runtime_mem; i += 2) {
|
for (i = 0; i < S->nb_runtime_mem; i += 2) {
|
||||||
unsigned size = (unsigned)(addr_t)s1->runtime_mem[i];
|
unsigned size = (unsigned)(addr_t)S->runtime_mem[i];
|
||||||
void *ptr = s1->runtime_mem[i+1];
|
void *ptr = S->runtime_mem[i+1];
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
munmap(ptr, size * 2);
|
munmap(ptr, size * 2);
|
||||||
#else
|
#else
|
||||||
/* unprotect memory to make it usable for malloc again */
|
/* unprotect memory to make it usable for malloc again */
|
||||||
set_pages_executable(s1, 2, ptr, size);
|
set_pages_executable(S, 2, ptr, size);
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
win64_del_function_table(*(void**)ptr);
|
win64_del_function_table(*(void**)ptr);
|
||||||
#endif
|
#endif
|
||||||
tcc_free(ptr);
|
tcc_free(S, ptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
tcc_free(s1->runtime_mem);
|
tcc_free(S, S->runtime_mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_cdtors(TCCState *s1, const char *start, const char *end,
|
static void run_cdtors(TCCState *S, const char *start, const char *end,
|
||||||
int argc, char **argv, char **envp)
|
int argc, char **argv, char **envp)
|
||||||
{
|
{
|
||||||
void **a = (void **)get_sym_addr(s1, start, 0, 0);
|
void **a = (void **)get_sym_addr(S, start, 0, 0);
|
||||||
void **b = (void **)get_sym_addr(s1, end, 0, 0);
|
void **b = (void **)get_sym_addr(S, end, 0, 0);
|
||||||
while (a != b)
|
while (a != b)
|
||||||
((void(*)(int, char **, char **))*a++)(argc, argv, envp);
|
((void(*)(int, char **, char **))*a++)(argc, argv, envp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* launch the compiled program with the given arguments */
|
/* launch the compiled program with the given arguments */
|
||||||
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
LIBTCCAPI int tcc_run(TCCState *S, int argc, char **argv)
|
||||||
{
|
{
|
||||||
int (*prog_main)(int, char **, char **), ret;
|
int (*prog_main)(int, char **, char **), ret;
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
@ -154,20 +154,20 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
|||||||
char **envp = environ;
|
char **envp = environ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s1->runtime_main = s1->nostdlib ? "_start" : "main";
|
S->runtime_main = S->nostdlib ? "_start" : "main";
|
||||||
if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, s1->runtime_main, 0, 1))
|
if ((S->dflag & TCC_OPTION_d_t) && (addr_t)-1 == get_sym_addr(S, S->runtime_main, 0, 1))
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
if (s1->do_debug)
|
if (S->do_debug)
|
||||||
tcc_add_symbol(s1, "exit", rt_exit);
|
tcc_add_symbol(S, "exit", rt_exit);
|
||||||
#endif
|
#endif
|
||||||
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
|
if (tcc_relocate(S, TCC_RELOCATE_AUTO) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1);
|
prog_main = (void*)get_sym_addr(S, S->runtime_main, 1, 1);
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
memset(rc, 0, sizeof *rc);
|
memset(rc, 0, sizeof *rc);
|
||||||
if (s1->do_debug) {
|
if (S->do_debug) {
|
||||||
void *p;
|
void *p;
|
||||||
rc->stab_sym = (Stab_Sym *)stab_section->data;
|
rc->stab_sym = (Stab_Sym *)stab_section->data;
|
||||||
rc->stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
|
rc->stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
|
||||||
@ -178,15 +178,15 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
|||||||
#if PTR_SIZE == 8
|
#if PTR_SIZE == 8
|
||||||
rc->prog_base = text_section->sh_addr & 0xffffffff00000000ULL;
|
rc->prog_base = text_section->sh_addr & 0xffffffff00000000ULL;
|
||||||
#endif
|
#endif
|
||||||
rc->top_func = tcc_get_symbol(s1, "main");
|
rc->top_func = tcc_get_symbol(S, "main");
|
||||||
rc->num_callers = s1->rt_num_callers;
|
rc->num_callers = S->rt_num_callers;
|
||||||
rc->do_jmp = 1;
|
rc->do_jmp = 1;
|
||||||
if ((p = tcc_get_symbol(s1, "__rt_error")))
|
if ((p = tcc_get_symbol(S, "__rt_error")))
|
||||||
*(void**)p = _rt_error;
|
*(void**)p = _rt_error;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (s1->do_bounds_check) {
|
if (S->do_bounds_check) {
|
||||||
rc->bounds_start = (void*)bounds_section->sh_addr;
|
rc->bounds_start = (void*)bounds_section->sh_addr;
|
||||||
if ((p = tcc_get_symbol(s1, "__bound_init")))
|
if ((p = tcc_get_symbol(S, "__bound_init")))
|
||||||
((void(*)(void*,int))p)(rc->bounds_start, 1);
|
((void(*)(void*,int))p)(rc->bounds_start, 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -198,16 +198,16 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
/* These aren't C symbols, so don't need leading underscore handling. */
|
/* These aren't C symbols, so don't need leading underscore handling. */
|
||||||
run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp);
|
run_cdtors(S, "__init_array_start", "__init_array_end", argc, argv, envp);
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
#ifdef CONFIG_TCC_BACKTRACE
|
||||||
if (!rc->do_jmp || !(ret = setjmp(rc->jmp_buf)))
|
if (!rc->do_jmp || !(ret = setjmp(rc->jmp_buf)))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ret = prog_main(argc, argv, envp);
|
ret = prog_main(argc, argv, envp);
|
||||||
}
|
}
|
||||||
run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
|
run_cdtors(S, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
|
||||||
if ((s1->dflag & 16) && ret)
|
if ((S->dflag & TCC_OPTION_d_t) && ret)
|
||||||
fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp);
|
fprintf(S->ppfp, "[returns %d]\n", ret), fflush(S->ppfp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
|||||||
|
|
||||||
/* relocate code. Return -1 on error, required size if ptr is NULL,
|
/* relocate code. Return -1 on error, required size if ptr is NULL,
|
||||||
otherwise copy code into buffer passed by the caller */
|
otherwise copy code into buffer passed by the caller */
|
||||||
static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
|
static int tcc_relocate_ex(TCCState *S, 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;
|
||||||
@ -237,15 +237,15 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
|
|||||||
addr_t mem, addr;
|
addr_t mem, addr;
|
||||||
|
|
||||||
if (NULL == ptr) {
|
if (NULL == ptr) {
|
||||||
s1->nb_errors = 0;
|
S->nb_errors = 0;
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
pe_output_file(s1, NULL);
|
pe_output_file(S, NULL);
|
||||||
#else
|
#else
|
||||||
tcc_add_runtime(s1);
|
tcc_add_runtime(S);
|
||||||
resolve_common_syms(s1);
|
resolve_common_syms(S);
|
||||||
build_got_entries(s1);
|
build_got_entries(S);
|
||||||
#endif
|
#endif
|
||||||
if (s1->nb_errors)
|
if (S->nb_errors)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,11 +257,11 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
|
|||||||
redo:
|
redo:
|
||||||
for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
|
for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
|
||||||
n = 0; addr = 0;
|
n = 0; addr = 0;
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < S->nb_sections; i++) {
|
||||||
static const char shf[] = {
|
static const char shf[] = {
|
||||||
SHF_ALLOC|SHF_EXECINSTR, SHF_ALLOC, SHF_ALLOC|SHF_WRITE
|
SHF_ALLOC|SHF_EXECINSTR, SHF_ALLOC, SHF_ALLOC|SHF_WRITE
|
||||||
};
|
};
|
||||||
s = s1->sections[i];
|
s = S->sections[i];
|
||||||
if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR)))
|
if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR)))
|
||||||
continue;
|
continue;
|
||||||
length = s->data_offset;
|
length = s->data_offset;
|
||||||
@ -277,11 +277,11 @@ redo:
|
|||||||
else
|
else
|
||||||
memcpy(ptr, s->data, length);
|
memcpy(ptr, s->data, length);
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
if (s == s1->uw_pdata)
|
if (s == S->uw_pdata)
|
||||||
*(void**)mem = win64_add_function_table(s1);
|
*(void**)mem = win64_add_function_table(S);
|
||||||
#endif
|
#endif
|
||||||
if (s->data) {
|
if (s->data) {
|
||||||
tcc_free(s->data);
|
tcc_free(S, s->data);
|
||||||
s->data = NULL;
|
s->data = NULL;
|
||||||
s->data_allocated = 0;
|
s->data_allocated = 0;
|
||||||
}
|
}
|
||||||
@ -316,7 +316,7 @@ redo:
|
|||||||
printf("protect %d %p %04x\n", f, (void*)addr, n);
|
printf("protect %d %p %04x\n", f, (void*)addr, n);
|
||||||
#endif
|
#endif
|
||||||
if (n)
|
if (n)
|
||||||
set_pages_executable(s1, f, (void*)addr, n);
|
set_pages_executable(S, f, (void*)addr, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,21 +324,21 @@ redo:
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* relocate symbols */
|
/* relocate symbols */
|
||||||
relocate_syms(s1, s1->symtab, !(s1->nostdlib));
|
relocate_syms(S, S->symtab, !(S->nostdlib));
|
||||||
if (s1->nb_errors)
|
if (S->nb_errors)
|
||||||
return -1;
|
return -1;
|
||||||
if (0 == mem)
|
if (0 == mem)
|
||||||
return offset + max_align;
|
return offset + max_align;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
s1->pe_imagebase = mem;
|
S->pe_imagebase = mem;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* relocate sections */
|
/* relocate sections */
|
||||||
#ifndef TCC_TARGET_PE
|
#ifndef TCC_TARGET_PE
|
||||||
relocate_plt(s1);
|
relocate_plt(S);
|
||||||
#endif
|
#endif
|
||||||
relocate_sections(s1);
|
relocate_sections(S);
|
||||||
copy = 1;
|
copy = 1;
|
||||||
goto redo;
|
goto redo;
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ redo:
|
|||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
/* allow to run code in memory */
|
/* allow to run code in memory */
|
||||||
|
|
||||||
static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length)
|
static void set_pages_executable(TCCState *S, int mode, void *ptr, unsigned long length)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static const unsigned char protect[] = {
|
static const unsigned char protect[] = {
|
||||||
@ -369,7 +369,7 @@ static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned lon
|
|||||||
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, protect[mode]))
|
if (mprotect((void *)start, end - start, protect[mode]))
|
||||||
tcc_error("mprotect failed: did you mean to configure --with-selinux?");
|
tcc_error(S, "mprotect failed: did you mean to configure --with-selinux?");
|
||||||
|
|
||||||
/* XXX: BSD sometimes dump core with bad system call */
|
/* XXX: BSD sometimes dump core with bad system call */
|
||||||
# if (TCC_TARGET_ARM && !TARGETOS_BSD) || TCC_TARGET_ARM64
|
# if (TCC_TARGET_ARM && !TARGETOS_BSD) || TCC_TARGET_ARM64
|
||||||
@ -383,17 +383,17 @@ static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned lon
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
static void *win64_add_function_table(TCCState *s1)
|
static void *win64_add_function_table(TCCState *S)
|
||||||
{
|
{
|
||||||
void *p = NULL;
|
void *p = NULL;
|
||||||
if (s1->uw_pdata) {
|
if (S->uw_pdata) {
|
||||||
p = (void*)s1->uw_pdata->sh_addr;
|
p = (void*)S->uw_pdata->sh_addr;
|
||||||
RtlAddFunctionTable(
|
RtlAddFunctionTable(
|
||||||
(RUNTIME_FUNCTION*)p,
|
(RUNTIME_FUNCTION*)p,
|
||||||
s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
|
S->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
|
||||||
s1->pe_imagebase
|
S->pe_imagebase
|
||||||
);
|
);
|
||||||
s1->uw_pdata = NULL;
|
S->uw_pdata = NULL;
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
54
tcctools.c
54
tcctools.c
@ -66,7 +66,7 @@ static int ar_usage(int ret) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
ST_FUNC int tcc_tool_ar(TCCState *S, int argc, char **argv)
|
||||||
{
|
{
|
||||||
static const ArHdr arhdr_init = {
|
static const ArHdr arhdr_init = {
|
||||||
"/ ",
|
"/ ",
|
||||||
@ -135,7 +135,7 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
funcmax = 250;
|
funcmax = 250;
|
||||||
afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
afpos = tcc_realloc(S, NULL, funcmax * sizeof *afpos); // 250 func
|
||||||
memcpy(&arhdro.ar_mode, "100666", 6);
|
memcpy(&arhdro.ar_mode, "100666", 6);
|
||||||
|
|
||||||
// i_obj = first input object file
|
// i_obj = first input object file
|
||||||
@ -155,7 +155,7 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
fseek(fi, 0, SEEK_END);
|
fseek(fi, 0, SEEK_END);
|
||||||
fsize = ftell(fi);
|
fsize = ftell(fi);
|
||||||
fseek(fi, 0, SEEK_SET);
|
fseek(fi, 0, SEEK_SET);
|
||||||
buf = tcc_malloc(fsize + 1);
|
buf = tcc_malloc(S, fsize + 1);
|
||||||
fread(buf, fsize, 1, fi);
|
fread(buf, fsize, 1, fi);
|
||||||
fclose(fi);
|
fclose(fi);
|
||||||
|
|
||||||
@ -203,12 +203,12 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
)) {
|
)) {
|
||||||
//printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
|
//printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
|
||||||
istrlen = strlen(strtab + sym->st_name)+1;
|
istrlen = strlen(strtab + sym->st_name)+1;
|
||||||
anames = tcc_realloc(anames, strpos+istrlen);
|
anames = tcc_realloc(S, anames, strpos+istrlen);
|
||||||
strcpy(anames + strpos, strtab + sym->st_name);
|
strcpy(anames + strpos, strtab + sym->st_name);
|
||||||
strpos += istrlen;
|
strpos += istrlen;
|
||||||
if (++funccnt >= funcmax) {
|
if (++funccnt >= funcmax) {
|
||||||
funcmax += 250;
|
funcmax += 250;
|
||||||
afpos = tcc_realloc(afpos, funcmax * sizeof *afpos); // 250 func more
|
afpos = tcc_realloc(S, afpos, funcmax * sizeof *afpos); // 250 func more
|
||||||
}
|
}
|
||||||
afpos[funccnt] = fpos;
|
afpos[funccnt] = fpos;
|
||||||
}
|
}
|
||||||
@ -229,7 +229,7 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
memcpy(&arhdro.ar_size, stmp, 10);
|
memcpy(&arhdro.ar_size, stmp, 10);
|
||||||
fwrite(&arhdro, sizeof(arhdro), 1, fo);
|
fwrite(&arhdro, sizeof(arhdro), 1, fo);
|
||||||
fwrite(buf, fsize, 1, fo);
|
fwrite(buf, fsize, 1, fo);
|
||||||
tcc_free(buf);
|
tcc_free(S, buf);
|
||||||
i_obj++;
|
i_obj++;
|
||||||
fpos += (fsize + sizeof(arhdro));
|
fpos += (fsize + sizeof(arhdro));
|
||||||
}
|
}
|
||||||
@ -253,16 +253,16 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
|||||||
fseek(fo, 0, SEEK_END);
|
fseek(fo, 0, SEEK_END);
|
||||||
fsize = ftell(fo);
|
fsize = ftell(fo);
|
||||||
fseek(fo, 0, SEEK_SET);
|
fseek(fo, 0, SEEK_SET);
|
||||||
buf = tcc_malloc(fsize + 1);
|
buf = tcc_malloc(S, fsize + 1);
|
||||||
fread(buf, fsize, 1, fo);
|
fread(buf, fsize, 1, fo);
|
||||||
fwrite(buf, fsize, 1, fh);
|
fwrite(buf, fsize, 1, fh);
|
||||||
tcc_free(buf);
|
tcc_free(S, buf);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
the_end:
|
the_end:
|
||||||
if (anames)
|
if (anames)
|
||||||
tcc_free(anames);
|
tcc_free(S, anames);
|
||||||
if (afpos)
|
if (afpos)
|
||||||
tcc_free(afpos);
|
tcc_free(S, afpos);
|
||||||
if (fh)
|
if (fh)
|
||||||
fclose(fh);
|
fclose(fh);
|
||||||
if (fo)
|
if (fo)
|
||||||
@ -294,7 +294,7 @@ the_end:
|
|||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
|
|
||||||
ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv)
|
ST_FUNC int tcc_tool_impdef(TCCState *S, int argc, char **argv)
|
||||||
{
|
{
|
||||||
int ret, v, i;
|
int ret, v, i;
|
||||||
char infile[260];
|
char infile[260];
|
||||||
@ -353,7 +353,7 @@ usage:
|
|||||||
if (SearchPath(NULL, file, ".dll", sizeof path, path, NULL))
|
if (SearchPath(NULL, file, ".dll", sizeof path, path, NULL))
|
||||||
file = path;
|
file = path;
|
||||||
#endif
|
#endif
|
||||||
ret = tcc_get_dllexports(file, &p);
|
ret = tcc_get_dllexports(S, file, &p);
|
||||||
if (ret || !p) {
|
if (ret || !p) {
|
||||||
fprintf(stderr, "tcc: impdef: %s '%s'\n",
|
fprintf(stderr, "tcc: impdef: %s '%s'\n",
|
||||||
ret == -1 ? "can't find file" :
|
ret == -1 ? "can't find file" :
|
||||||
@ -386,7 +386,7 @@ usage:
|
|||||||
|
|
||||||
the_end:
|
the_end:
|
||||||
if (p)
|
if (p)
|
||||||
tcc_free(p);
|
tcc_free(S, p);
|
||||||
if (fp)
|
if (fp)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (op)
|
if (op)
|
||||||
@ -421,9 +421,9 @@ the_end:
|
|||||||
|
|
||||||
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
|
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
|
||||||
|
|
||||||
ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int option)
|
ST_FUNC void tcc_tool_cross(TCCState *S, char **argv, int option)
|
||||||
{
|
{
|
||||||
tcc_error("-m%d not implemented.", option);
|
tcc_error(S, "-m%d not implemented.", option);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -439,7 +439,7 @@ static char *str_replace(const char *str, const char *p, const char *r)
|
|||||||
sl = strlen(str);
|
sl = strlen(str);
|
||||||
pl = strlen(p);
|
pl = strlen(p);
|
||||||
rl = strlen(r);
|
rl = strlen(r);
|
||||||
for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
|
for (d0 = NULL;; d0 = tcc_malloc(S, sl + 1)) {
|
||||||
for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
|
for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
|
||||||
if (d) {
|
if (d) {
|
||||||
memcpy(d, s0, sl = s - s0), d += sl;
|
memcpy(d, s0, sl = s - s0), d += sl;
|
||||||
@ -470,7 +470,7 @@ static int execvp_win32(const char *prog, char **argv)
|
|||||||
#define execvp execvp_win32
|
#define execvp execvp_win32
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int target)
|
ST_FUNC void tcc_tool_cross(TCCState *S, char **argv, int target)
|
||||||
{
|
{
|
||||||
char program[4096];
|
char program[4096];
|
||||||
char *a0 = argv[0];
|
char *a0 = argv[0];
|
||||||
@ -489,7 +489,7 @@ ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int target)
|
|||||||
|
|
||||||
if (strcmp(a0, program))
|
if (strcmp(a0, program))
|
||||||
execvp(argv[0] = program, argv);
|
execvp(argv[0] = program, argv);
|
||||||
tcc_error("could not run '%s'", program);
|
tcc_error(S, "could not run '%s'", program);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
|
#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
|
||||||
@ -506,8 +506,8 @@ const int _dowildcard = 1;
|
|||||||
/* -------------------------------------------------------------- */
|
/* -------------------------------------------------------------- */
|
||||||
/* generate xxx.d file */
|
/* generate xxx.d file */
|
||||||
|
|
||||||
static char *escape_target_dep(const char *s) {
|
static char *escape_target_dep(TCCState *S, const char *s) {
|
||||||
char *res = tcc_malloc(strlen(s) * 2 + 1);
|
char *res = tcc_malloc(S, strlen(s) * 2 + 1);
|
||||||
int j;
|
int j;
|
||||||
for (j = 0; *s; s++, j++) {
|
for (j = 0; *s; s++, j++) {
|
||||||
if (is_space(*s)) {
|
if (is_space(*s)) {
|
||||||
@ -519,7 +519,7 @@ static char *escape_target_dep(const char *s) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_makedeps(TCCState *s1, const char *target, const char *filename)
|
ST_FUNC void gen_makedeps(TCCState *S, const char *target, const char *filename)
|
||||||
{
|
{
|
||||||
FILE *depout;
|
FILE *depout;
|
||||||
char buf[1024], *escaped_target;
|
char buf[1024], *escaped_target;
|
||||||
@ -532,7 +532,7 @@ ST_FUNC void gen_makedeps(TCCState *s1, const char *target, const char *filename
|
|||||||
filename = buf;
|
filename = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->verbose)
|
if (S->verbose)
|
||||||
printf("<- %s\n", filename);
|
printf("<- %s\n", filename);
|
||||||
|
|
||||||
if(!strcmp(filename, "-"))
|
if(!strcmp(filename, "-"))
|
||||||
@ -541,15 +541,15 @@ ST_FUNC void gen_makedeps(TCCState *s1, const char *target, const char *filename
|
|||||||
/* XXX return err codes instead of error() ? */
|
/* XXX return err codes instead of error() ? */
|
||||||
depout = fopen(filename, "w");
|
depout = fopen(filename, "w");
|
||||||
if (!depout)
|
if (!depout)
|
||||||
tcc_error("could not open '%s'", filename);
|
tcc_error(S, "could not open '%s'", filename);
|
||||||
fprintf(depout, "%s:", target);
|
fprintf(depout, "%s:", target);
|
||||||
for (i = 0; i<s1->nb_target_deps; ++i) {
|
for (i = 0; i<S->nb_target_deps; ++i) {
|
||||||
for (k = 0; k < i; ++k)
|
for (k = 0; k < i; ++k)
|
||||||
if (0 == strcmp(s1->target_deps[i], s1->target_deps[k]))
|
if (0 == strcmp(S->target_deps[i], S->target_deps[k]))
|
||||||
goto next;
|
goto next;
|
||||||
escaped_target = escape_target_dep(s1->target_deps[i]);
|
escaped_target = escape_target_dep(S, S->target_deps[i]);
|
||||||
fprintf(depout, " \\\n %s", escaped_target);
|
fprintf(depout, " \\\n %s", escaped_target);
|
||||||
tcc_free(escaped_target);
|
tcc_free(S, escaped_target);
|
||||||
next:;
|
next:;
|
||||||
}
|
}
|
||||||
fprintf(depout, "\n");
|
fprintf(depout, "\n");
|
||||||
|
1347
x86_64-gen.c
1347
x86_64-gen.c
File diff suppressed because it is too large
Load Diff
@ -105,9 +105,9 @@ int gotplt_entry_type (int reloc_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(TCC_TARGET_MACHO) || defined TCC_IS_NATIVE
|
#if !defined(TCC_TARGET_MACHO) || defined TCC_IS_NATIVE
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
|
||||||
{
|
{
|
||||||
Section *plt = s1->plt;
|
Section *plt = S->plt;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
int modrm;
|
int modrm;
|
||||||
unsigned plt_offset, relofs;
|
unsigned plt_offset, relofs;
|
||||||
@ -118,7 +118,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
|
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
|
||||||
(GOT + 2 * PTR_SIZE) */
|
(GOT + 2 * PTR_SIZE) */
|
||||||
if (plt->data_offset == 0) {
|
if (plt->data_offset == 0) {
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(S, plt, 16);
|
||||||
p[0] = 0xff; /* pushl got + PTR_SIZE */
|
p[0] = 0xff; /* pushl got + PTR_SIZE */
|
||||||
p[1] = modrm + 0x10;
|
p[1] = modrm + 0x10;
|
||||||
write32le(p + 2, PTR_SIZE);
|
write32le(p + 2, PTR_SIZE);
|
||||||
@ -131,10 +131,10 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
/* The PLT slot refers to the relocation entry it needs via offset.
|
/* The PLT slot refers to the relocation entry it needs via offset.
|
||||||
The reloc entry is created below, so its offset is the current
|
The reloc entry is created below, so its offset is the current
|
||||||
data_offset */
|
data_offset */
|
||||||
relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
|
relofs = S->plt->reloc ? S->plt->reloc->data_offset : 0;
|
||||||
|
|
||||||
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(S, plt, 16);
|
||||||
p[0] = 0xff; /* jmp *(got + x) */
|
p[0] = 0xff; /* jmp *(got + x) */
|
||||||
p[1] = modrm;
|
p[1] = modrm;
|
||||||
write32le(p + 2, got_offset);
|
write32le(p + 2, got_offset);
|
||||||
@ -148,32 +148,32 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||||||
|
|
||||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||||
address for PLT and GOT are known (see fill_program_header) */
|
address for PLT and GOT are known (see fill_program_header) */
|
||||||
ST_FUNC void relocate_plt(TCCState *s1)
|
ST_FUNC void relocate_plt(TCCState *S)
|
||||||
{
|
{
|
||||||
uint8_t *p, *p_end;
|
uint8_t *p, *p_end;
|
||||||
|
|
||||||
if (!s1->plt)
|
if (!S->plt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p = s1->plt->data;
|
p = S->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
p_end = p + S->plt->data_offset;
|
||||||
|
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
|
int x = S->got->sh_addr - S->plt->sh_addr - 6;
|
||||||
add32le(p + 2, x);
|
add32le(p + 2, x);
|
||||||
add32le(p + 8, x - 6);
|
add32le(p + 8, x - 6);
|
||||||
p += 16;
|
p += 16;
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
add32le(p + 2, x + (s1->plt->data - p));
|
add32le(p + 2, x + (S->plt->data - p));
|
||||||
p += 16;
|
p += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->plt->reloc) {
|
if (S->plt->reloc) {
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
int x = s1->plt->sh_addr + 16 + 6;
|
int x = S->plt->sh_addr + 16 + 6;
|
||||||
p = s1->got->data;
|
p = S->got->data;
|
||||||
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
write64le(p + rel->r_offset, x);
|
write64le(p + rel->r_offset, x);
|
||||||
x += 16;
|
x += 16;
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||||
{
|
{
|
||||||
int sym_index, esym_index;
|
int sym_index, esym_index;
|
||||||
|
|
||||||
@ -190,8 +190,8 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case R_X86_64_64:
|
case R_X86_64_64:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
|
||||||
@ -208,7 +208,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
break;
|
break;
|
||||||
case R_X86_64_32:
|
case R_X86_64_32:
|
||||||
case R_X86_64_32S:
|
case R_X86_64_32S:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
/* XXX: this logic may depend on TCC's codegen
|
/* XXX: this logic may depend on TCC's codegen
|
||||||
now TCC uses R_X86_64_32 even for a 64bit pointer */
|
now TCC uses R_X86_64_32 even for a 64bit pointer */
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
@ -221,9 +221,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case R_X86_64_PC32:
|
case R_X86_64_PC32:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
/* DLL relocation */
|
/* DLL relocation */
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
|
||||||
@ -243,20 +243,20 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
long long diff;
|
long long diff;
|
||||||
diff = (long long)val - addr;
|
diff = (long long)val - addr;
|
||||||
if (diff < -2147483648LL || diff > 2147483647LL) {
|
if (diff < -2147483648LL || diff > 2147483647LL) {
|
||||||
tcc_error("internal error: relocation failed");
|
tcc_error(S, "internal error: relocation failed");
|
||||||
}
|
}
|
||||||
add32le(ptr, diff);
|
add32le(ptr, diff);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_X86_64_PLTOFF64:
|
case R_X86_64_PLTOFF64:
|
||||||
add64le(ptr, val - s1->got->sh_addr + rel->r_addend);
|
add64le(ptr, val - S->got->sh_addr + rel->r_addend);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_X86_64_PC64:
|
case R_X86_64_PC64:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
if (S->output_type == TCC_OUTPUT_DLL) {
|
||||||
/* DLL relocation */
|
/* DLL relocation */
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
|
||||||
if (esym_index) {
|
if (esym_index) {
|
||||||
qrel->r_offset = rel->r_offset;
|
qrel->r_offset = rel->r_offset;
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC64);
|
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC64);
|
||||||
@ -276,28 +276,28 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
case R_X86_64_GOTPCREL:
|
case R_X86_64_GOTPCREL:
|
||||||
case R_X86_64_GOTPCRELX:
|
case R_X86_64_GOTPCRELX:
|
||||||
case R_X86_64_REX_GOTPCRELX:
|
case R_X86_64_REX_GOTPCRELX:
|
||||||
add32le(ptr, s1->got->sh_addr - addr +
|
add32le(ptr, S->got->sh_addr - addr +
|
||||||
get_sym_attr(s1, sym_index, 0)->got_offset - 4);
|
get_sym_attr(S, sym_index, 0)->got_offset - 4);
|
||||||
break;
|
break;
|
||||||
case R_X86_64_GOTPC32:
|
case R_X86_64_GOTPC32:
|
||||||
add32le(ptr, s1->got->sh_addr - addr + rel->r_addend);
|
add32le(ptr, S->got->sh_addr - addr + rel->r_addend);
|
||||||
break;
|
break;
|
||||||
case R_X86_64_GOTPC64:
|
case R_X86_64_GOTPC64:
|
||||||
add64le(ptr, s1->got->sh_addr - addr + rel->r_addend);
|
add64le(ptr, S->got->sh_addr - addr + rel->r_addend);
|
||||||
break;
|
break;
|
||||||
case R_X86_64_GOTTPOFF:
|
case R_X86_64_GOTTPOFF:
|
||||||
add32le(ptr, val - s1->got->sh_addr);
|
add32le(ptr, val - S->got->sh_addr);
|
||||||
break;
|
break;
|
||||||
case R_X86_64_GOT32:
|
case R_X86_64_GOT32:
|
||||||
/* we load the got offset */
|
/* we load the got offset */
|
||||||
add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
|
add32le(ptr, get_sym_attr(S, sym_index, 0)->got_offset);
|
||||||
break;
|
break;
|
||||||
case R_X86_64_GOT64:
|
case R_X86_64_GOT64:
|
||||||
/* we load the got offset */
|
/* we load the got offset */
|
||||||
add64le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
|
add64le(ptr, get_sym_attr(S, sym_index, 0)->got_offset);
|
||||||
break;
|
break;
|
||||||
case R_X86_64_GOTOFF64:
|
case R_X86_64_GOTOFF64:
|
||||||
add64le(ptr, val - s1->got->sh_addr);
|
add64le(ptr, val - S->got->sh_addr);
|
||||||
break;
|
break;
|
||||||
case R_X86_64_TLSGD:
|
case R_X86_64_TLSGD:
|
||||||
{
|
{
|
||||||
@ -320,12 +320,12 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
memcpy(ptr-4, replace, sizeof(replace));
|
memcpy(ptr-4, replace, sizeof(replace));
|
||||||
rel[1].r_info = ELFW(R_INFO)(0, R_X86_64_NONE);
|
rel[1].r_info = ELFW(R_INFO)(0, R_X86_64_NONE);
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
sec = s1->sections[sym->st_shndx];
|
sec = S->sections[sym->st_shndx];
|
||||||
x = sym->st_value - sec->sh_addr - sec->data_offset;
|
x = sym->st_value - sec->sh_addr - sec->data_offset;
|
||||||
add32le(ptr + 8, x);
|
add32le(ptr + 8, x);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tcc_error("unexpected R_X86_64_TLSGD pattern");
|
tcc_error(S, "unexpected R_X86_64_TLSGD pattern");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R_X86_64_TLSLD:
|
case R_X86_64_TLSLD:
|
||||||
@ -345,7 +345,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
rel[1].r_info = ELFW(R_INFO)(0, R_X86_64_NONE);
|
rel[1].r_info = ELFW(R_INFO)(0, R_X86_64_NONE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tcc_error("unexpected R_X86_64_TLSLD pattern");
|
tcc_error(S, "unexpected R_X86_64_TLSLD pattern");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R_X86_64_DTPOFF32:
|
case R_X86_64_DTPOFF32:
|
||||||
@ -356,7 +356,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
int32_t x;
|
int32_t x;
|
||||||
|
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
sec = s1->sections[sym->st_shndx];
|
sec = S->sections[sym->st_shndx];
|
||||||
x = val - sec->sh_addr - sec->data_offset;
|
x = val - sec->sh_addr - sec->data_offset;
|
||||||
add32le(ptr, x);
|
add32le(ptr, x);
|
||||||
}
|
}
|
||||||
@ -365,7 +365,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
break;
|
break;
|
||||||
case R_X86_64_RELATIVE:
|
case R_X86_64_RELATIVE:
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
add32le(ptr, val - s1->pe_imagebase);
|
add32le(ptr, val - S->pe_imagebase);
|
||||||
#endif
|
#endif
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user