1
0
Fork 0

Revert "Move almost all global variables to TCCState, actually all tests pass on Ubuntu 18.04 x86_64"

This reverts commit af686a796b.
This commit is contained in:
mingodad 2021-10-22 07:39:54 +02:00
parent 2ce2dbcb09
commit 1645616843
30 changed files with 10723 additions and 11190 deletions

1112
arm-asm.c

File diff suppressed because it is too large Load Diff

1135
arm-gen.c

File diff suppressed because it is too large Load Diff

View File

@ -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 *S, unsigned got_offset, struct sym_attr *attr) ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{ {
Section *plt = S->plt; Section *plt = s1->plt;
uint8_t *p; uint8_t *p;
unsigned plt_offset; unsigned plt_offset;
@ -119,7 +119,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
/* 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(S, plt, 20); p = section_ptr_add(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 *S, unsigned got_offset, struct sym_a
plt_offset = plt->data_offset; plt_offset = plt->data_offset;
if (attr->plt_thumb_stub) { if (attr->plt_thumb_stub) {
p = section_ptr_add(S, plt, 4); p = section_ptr_add(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(S, plt, 16); p = section_ptr_add(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 *S, unsigned got_offset, struct sym_a
/* 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 *S) ST_FUNC void relocate_plt(TCCState *s1)
{ {
uint8_t *p, *p_end; uint8_t *p, *p_end;
if (!S->plt) if (!s1->plt)
return; return;
p = S->plt->data; p = s1->plt->data;
p_end = p + S->plt->data_offset; p_end = p + s1->plt->data_offset;
if (p < p_end) { if (p < p_end) {
int x = S->got->sh_addr - S->plt->sh_addr - 12; int x = s1->got->sh_addr - s1->plt->sh_addr - 12;
write32le(S->plt->data + 16, x - 4); write32le(s1->plt->data + 16, x - 4);
p += 20; p += 20;
while (p < p_end) { while (p < p_end) {
unsigned off = x + read32le(p + 4) + (S->plt->data - p) + 4; unsigned off = x + read32le(p + 4) + (s1->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 *S)
} }
} }
if (S->plt->reloc) { if (s1->plt->reloc) {
ElfW_Rel *rel; ElfW_Rel *rel;
p = S->got->data; p = s1->got->data;
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) { for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
write32le(p + rel->r_offset, S->plt->sh_addr); write32le(p + rel->r_offset, s1->plt->sh_addr);
} }
} }
} }
#endif #endif
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val) void relocate(TCCState *s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
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(S, "can't relocate value at %x,%d",addr, type); tcc_error("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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
/* Relocation infos */ /* Relocation infos */
to_thumb = val & 1; to_thumb = val & 1;
plt = S->plt; plt = s1->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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
Section *text; Section *text;
name = (char *) symtab_section->link->data + sym->st_name; name = (char *) symtab_section->link->data + sym->st_name;
text = S->sections[sym->st_shndx]; text = s1->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(S, symtab_section, index = put_elf_sym(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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
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(S, text, 8); p = section_ptr_add(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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
- 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(S, "can't relocate value at %x,%d",addr, type); tcc_error("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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
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(S, "can't relocate value at %x,%d",addr, type); tcc_error("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 (S->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index; esym_index = get_sym_attr(s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
*(int *)ptr += val - addr; *(int *)ptr += val - addr;
return; return;
case R_ARM_GOTPC: case R_ARM_GOTPC:
*(int *)ptr += S->got->sh_addr - addr; *(int *)ptr += s1->got->sh_addr - addr;
return; return;
case R_ARM_GOTOFF: case R_ARM_GOTOFF:
*(int *)ptr += val - S->got->sh_addr; *(int *)ptr += val - s1->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(S, sym_index, 0)->got_offset; *(int *)ptr += get_sym_attr(s1, 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 += S->got->sh_addr + *(int *)ptr += s1->got->sh_addr +
get_sym_attr(S, sym_index, 0)->got_offset - get_sym_attr(s1, sym_index, 0)->got_offset -
addr; addr;
return; return;
case R_ARM_COPY: case R_ARM_COPY:
@ -428,7 +428,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
return; return;
case R_ARM_RELATIVE: case R_ARM_RELATIVE:
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
add32le(ptr, val - S->pe_imagebase); add32le(ptr, val - s1->pe_imagebase);
#endif #endif
/* do nothing */ /* do nothing */
return; return;

View File

@ -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(TCCState* S, int c); ST_FUNC void g(int c);
ST_FUNC void gen_le16(TCCState* S, int c); ST_FUNC void gen_le16(int c);
ST_FUNC void gen_le32(TCCState* S, int c); ST_FUNC void gen_le32(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(TCCState* S, int c) ST_FUNC void g(int c)
{ {
int ind1; int ind1;
if (nocode_wanted) if (nocode_wanted)
@ -37,24 +37,24 @@ ST_FUNC void g(TCCState* S, int c)
ind = ind1; ind = ind1;
} }
ST_FUNC void gen_le16 (TCCState* S, int i) ST_FUNC void gen_le16 (int i)
{ {
g(S, i); g(i);
g(S, i>>8); g(i>>8);
} }
ST_FUNC void gen_le32 (TCCState* S, int i) ST_FUNC void gen_le32 (int i)
{ {
gen_le16(S, i); gen_le16(i);
gen_le16(S, i>>16); gen_le16(i>>16);
} }
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe) ST_FUNC void gen_expr32(ExprValue *pe)
{ {
gen_le32(S, pe->v); gen_le32(pe->v);
} }
ST_FUNC void asm_opcode(TCCState *S, int opcode) ST_FUNC void asm_opcode(TCCState *s1, int opcode)
{ {
asm_error(); asm_error();
} }

File diff suppressed because it is too large Load Diff

View File

@ -90,18 +90,18 @@ int gotplt_entry_type (int reloc_type)
return -1; return -1;
} }
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr) ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{ {
Section *plt = S->plt; Section *plt = s1->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(S, plt, 32); section_ptr_add(plt, 32);
} }
plt_offset = plt->data_offset; plt_offset = plt->data_offset;
p = section_ptr_add(S, plt, 16); p = section_ptr_add(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 *S, unsigned got_offset, struct sym_a
/* 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 *S) ST_FUNC void relocate_plt(TCCState *s1)
{ {
uint8_t *p, *p_end; uint8_t *p, *p_end;
if (!S->plt) if (!s1->plt)
return; return;
p = S->plt->data; p = s1->plt->data;
p_end = p + S->plt->data_offset; p_end = p + s1->plt->data_offset;
if (p < p_end) { if (p < p_end) {
uint64_t plt = S->plt->sh_addr; uint64_t plt = s1->plt->sh_addr;
uint64_t got = S->got->sh_addr + 16; uint64_t got = s1->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(S, "Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt); tcc_error("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 *S)
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 = S->got->sh_addr; got = s1->got->sh_addr;
while (p < p_end) { while (p < p_end) {
uint64_t pc = plt + (p - S->plt->data); uint64_t pc = plt + (p - s1->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(S, "Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc); tcc_error("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 *S)
} }
} }
if (S->plt->reloc) { if (s1->plt->reloc) {
ElfW_Rel *rel; ElfW_Rel *rel;
p = S->got->data; p = s1->got->data;
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) { for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
write64le(p + rel->r_offset, S->plt->sh_addr); write64le(p + rel->r_offset, s1->plt->sh_addr);
} }
} }
} }
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val) void relocate(TCCState *s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
switch(type) { switch(type) {
case R_AARCH64_ABS64: case R_AARCH64_ABS64:
if (S->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index; esym_index = get_sym_attr(s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
add64le(ptr, val); add64le(ptr, val);
return; return;
case R_AARCH64_ABS32: case R_AARCH64_ABS32:
if (S->output_type == TCC_OUTPUT_DLL) { if (s1->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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
add32le(ptr, val); add32le(ptr, val);
return; return;
case R_AARCH64_PREL32: case R_AARCH64_PREL32:
if (S->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
/* DLL relocation */ /* DLL relocation */
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index; esym_index = get_sym_attr(s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
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(S, "R_AARCH64_ADR_PREL_PG_HI21 relocation failed"); tcc_error("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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
(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(S, "R_AARCH64_(JUMP|CALL)26 relocation failed" tcc_error("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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
return; return;
case R_AARCH64_ADR_GOT_PAGE: { case R_AARCH64_ADR_GOT_PAGE: {
uint64_t off = uint64_t off =
(((S->got->sh_addr + (((s1->got->sh_addr +
get_sym_attr(S, sym_index, 0)->got_offset) >> 12) - (addr >> 12)); get_sym_attr(s1, sym_index, 0)->got_offset) >> 12) - (addr >> 12));
if ((off + ((uint64_t)1 << 20)) >> 21) if ((off + ((uint64_t)1 << 20)) >> 21)
tcc_error(S, "R_AARCH64_ADR_GOT_PAGE relocation failed"); tcc_error("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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
case R_AARCH64_LD64_GOT_LO12_NC: case R_AARCH64_LD64_GOT_LO12_NC:
write32le(ptr, write32le(ptr,
((read32le(ptr) & 0xfff803ff) | ((read32le(ptr) & 0xfff803ff) |
((S->got->sh_addr + ((s1->got->sh_addr +
get_sym_attr(S, sym_index, 0)->got_offset) & 0xff8) << 7)); get_sym_attr(s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
return; return;
case R_AARCH64_RELATIVE: case R_AARCH64_RELATIVE:
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
add32le(ptr, val - S->pe_imagebase); add32le(ptr, val - s1->pe_imagebase);
#endif #endif
/* do nothing */ /* do nothing */
return; return;

1516
c67-gen.c

File diff suppressed because it is too large Load Diff

View File

@ -65,23 +65,23 @@ int gotplt_entry_type (int reloc_type)
return -1; return -1;
} }
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr) ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{ {
tcc_error(S, "C67 got not implemented"); tcc_error("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 *S) ST_FUNC void relocate_plt(TCCState *s1)
{ {
uint8_t *p, *p_end; uint8_t *p, *p_end;
if (!S->plt) if (!s1->plt)
return; return;
p = S->plt->data; p = s1->plt->data;
p_end = p + S->plt->data_offset; p_end = p + s1->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 *S)
} }
} }
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val) void relocate(TCCState *s1, 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:

View File

@ -253,10 +253,10 @@ static const uint16_t op0_codes[] = {
#endif #endif
}; };
static inline int get_reg_shift(TCCState *S) static inline int get_reg_shift(TCCState *s1)
{ {
int shift, v; int shift, v;
v = asm_int_expr(S); v = asm_int_expr(s1);
switch(v) { switch(v) {
case 1: case 1:
shift = 0; shift = 0;
@ -271,7 +271,7 @@ static inline int get_reg_shift(TCCState *S)
shift = 3; shift = 3;
break; break;
default: default:
expect(S, "1, 2, 4 or 8 constant"); expect("1, 2, 4 or 8 constant");
shift = 0; shift = 0;
break; break;
} }
@ -279,11 +279,11 @@ static inline int get_reg_shift(TCCState *S)
} }
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
static int asm_parse_numeric_reg(TCCState *S, int t, unsigned int *type) static int asm_parse_numeric_reg(int t, unsigned int *type)
{ {
int reg = -1; int reg = -1;
if (t >= TOK_IDENT && t < S->tccpp_tok_ident) { if (t >= TOK_IDENT && t < tok_ident) {
const char *s = S->tccpp_table_ident[t - TOK_IDENT]->str; const char *s = 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(TCCState *S, int t, unsigned int *type)
} }
#endif #endif
static int asm_parse_reg(TCCState* S, unsigned int *type) static int asm_parse_reg(unsigned int *type)
{ {
int reg = 0; int reg = 0;
*type = 0; *type = 0;
if (S->tccpp_tok != '%') if (tok != '%')
goto error_32; goto error_32;
next(S); next();
if (S->tccpp_tok >= TOK_ASM_eax && S->tccpp_tok <= TOK_ASM_edi) { if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
reg = S->tccpp_tok - TOK_ASM_eax; reg = tok - TOK_ASM_eax;
*type = OP_REG32; *type = OP_REG32;
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
} else if (S->tccpp_tok >= TOK_ASM_rax && S->tccpp_tok <= TOK_ASM_rdi) { } else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) {
reg = S->tccpp_tok - TOK_ASM_rax; reg = tok - TOK_ASM_rax;
*type = OP_REG64; *type = OP_REG64;
} else if (S->tccpp_tok == TOK_ASM_rip) { } else if (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(S, S->tccpp_tok, type)) >= 0 } else if ((reg = asm_parse_numeric_reg(tok, type)) >= 0
&& (*type == OP_REG32 || *type == OP_REG64)) { && (*type == OP_REG32 || *type == OP_REG64)) {
; ;
#endif #endif
} else { } else {
error_32: error_32:
expect(S, "register"); expect("register");
} }
next(S); next();
return reg; return reg;
} }
static void parse_operand(TCCState *S, Operand *op) static void parse_operand(TCCState *s1, Operand *op)
{ {
ExprValue e; ExprValue e;
int reg, indir; int reg, indir;
const char *p; const char *p;
indir = 0; indir = 0;
if (S->tccpp_tok == '*') { if (tok == '*') {
next(S); next();
indir = OP_INDIR; indir = OP_INDIR;
} }
if (S->tccpp_tok == '%') { if (tok == '%') {
next(S); next();
if (S->tccpp_tok >= TOK_ASM_al && S->tccpp_tok <= TOK_ASM_db7) { if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
reg = S->tccpp_tok - TOK_ASM_al; reg = 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 *S, 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 (S->tccpp_tok >= TOK_ASM_dr0 && S->tccpp_tok <= TOK_ASM_dr7) { } else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
op->type = OP_DB; op->type = OP_DB;
op->reg = S->tccpp_tok - TOK_ASM_dr0; op->reg = tok - TOK_ASM_dr0;
} else if (S->tccpp_tok >= TOK_ASM_es && S->tccpp_tok <= TOK_ASM_gs) { } else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
op->type = OP_SEG; op->type = OP_SEG;
op->reg = S->tccpp_tok - TOK_ASM_es; op->reg = tok - TOK_ASM_es;
} else if (S->tccpp_tok == TOK_ASM_st) { } else if (tok == TOK_ASM_st) {
op->type = OP_ST; op->type = OP_ST;
op->reg = 0; op->reg = 0;
next(S); next();
if (S->tccpp_tok == '(') { if (tok == '(') {
next(S); next();
if (S->tccpp_tok != TOK_PPNUM) if (tok != TOK_PPNUM)
goto reg_error; goto reg_error;
p = S->tccpp_tokc.str.data; p = 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(S); next();
skip(S, ')'); skip(')');
} }
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 (S->tccpp_tok >= TOK_ASM_spl && S->tccpp_tok <= TOK_ASM_dil) { } else if (tok >= TOK_ASM_spl && tok <= TOK_ASM_dil) {
op->type = OP_REG8 | OP_REG8_LOW; op->type = OP_REG8 | OP_REG8_LOW;
op->reg = 4 + S->tccpp_tok - TOK_ASM_spl; op->reg = 4 + tok - TOK_ASM_spl;
} else if ((op->reg = asm_parse_numeric_reg(S, S->tccpp_tok, &op->type)) >= 0) { } else if ((op->reg = asm_parse_numeric_reg(tok, &op->type)) >= 0) {
; ;
#endif #endif
} else { } else {
reg_error: reg_error:
tcc_error(S, "unknown register %%%s", get_tok_str(S, S->tccpp_tok, &S->tccpp_tokc)); tcc_error("unknown register %%%s", get_tok_str(tok, &tokc));
} }
next(S); next();
no_skip: ; no_skip: ;
} else if (S->tccpp_tok == '$') { } else if (tok == '$') {
/* constant value */ /* constant value */
next(S); next();
asm_expr(S, &e); asm_expr(s1, &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 *S, Operand *op)
op->reg = -1; op->reg = -1;
op->reg2 = -1; op->reg2 = -1;
op->shift = 0; op->shift = 0;
if (S->tccpp_tok != '(') { if (tok != '(') {
asm_expr(S, &e); asm_expr(s1, &e);
op->e = e; op->e = e;
} else { } else {
next(S); next();
if (S->tccpp_tok == '%') { if (tok == '%') {
unget_tok(S, '('); unget_tok('(');
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(S, &e); asm_expr(s1, &e);
if (S->tccpp_tok != ')') if (tok != ')')
expect(S, ")"); expect(")");
next(S); next();
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 (S->tccpp_tok == '(') { if (tok == '(') {
unsigned int type = 0; unsigned int type = 0;
next(S); next();
if (S->tccpp_tok != ',') { if (tok != ',') {
op->reg = asm_parse_reg(S, &type); op->reg = asm_parse_reg(&type);
} }
if (S->tccpp_tok == ',') { if (tok == ',') {
next(S); next();
if (S->tccpp_tok != ',') { if (tok != ',') {
op->reg2 = asm_parse_reg(S, &type); op->reg2 = asm_parse_reg(&type);
} }
if (S->tccpp_tok == ',') { if (tok == ',') {
next(S); next();
op->shift = get_reg_shift(S); op->shift = get_reg_shift(s1);
} }
} }
if (type & OP_REG32) if (type & OP_REG32)
op->type |= OP_EA32; op->type |= OP_EA32;
skip(S, ')'); skip(')');
} }
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 *S, Operand *op)
} }
/* XXX: unify with C code output ? */ /* XXX: unify with C code output ? */
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe) ST_FUNC void gen_expr32(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(S, VT_SYM, pe->sym, pe->v); gen_addrpc32(VT_SYM, pe->sym, pe->v);
else else
gen_addr32(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v); gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
} }
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
ST_FUNC void gen_expr64(TCCState* S, ExprValue *pe) ST_FUNC void gen_expr64(ExprValue *pe)
{ {
gen_addr64(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v); gen_addr64(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(TCCState* S, ExprValue *pe) static void gen_disp32(ExprValue *pe)
{ {
Sym *sym = pe->sym; Sym *sym = pe->sym;
ElfSym *esym = elfsym(S, sym); ElfSym *esym = elfsym(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(S, pe->v + esym->st_value - S->tccgen_ind - 4); gen_le32(pe->v + esym->st_value - 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(S, VT_SYM, sym, pe->v); gen_addrpc32(VT_SYM, sym, pe->v);
} }
} }
/* generate the modrm operand */ /* generate the modrm operand */
static inline int asm_modrm(TCCState* S, int reg, Operand *op) static inline int asm_modrm(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(S, 0xc0 + (reg << 3) + op->reg); g(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(S, 0x04 + (reg << 3)); g(0x04 + (reg << 3));
g(S, 0x25); g(0x25);
#else #else
g(S, 0x05 + (reg << 3)); g(0x05 + (reg << 3));
#endif #endif
gen_expr32(S, &op->e); gen_expr32(&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(S, 0x05 + (reg << 3)); g(0x05 + (reg << 3));
gen_addrpc32(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v); gen_addrpc32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
return S->tccgen_ind; return ind;
#endif #endif
} else { } else {
sib_reg1 = op->reg; sib_reg1 = op->reg;
@ -557,19 +557,19 @@ static inline int asm_modrm(TCCState* S, int reg, Operand *op)
reg1 = op->reg; reg1 = op->reg;
if (op->reg2 != -1) if (op->reg2 != -1)
reg1 = 4; reg1 = 4;
g(S, mod + (reg << 3) + reg1); g(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(S, (op->shift << 6) + (reg2 << 3) + sib_reg1); g((op->shift << 6) + (reg2 << 3) + sib_reg1);
} }
/* add offset */ /* add offset */
if (mod == 0x40) { if (mod == 0x40) {
g(S, op->e.v); g(op->e.v);
} else if (mod == 0x80 || op->reg == -1) { } else if (mod == 0x80 || op->reg == -1) {
gen_expr32(S, &op->e); gen_expr32(&op->e);
} }
} }
return 0; return 0;
@ -581,7 +581,7 @@ static inline int asm_modrm(TCCState* S, int reg, Operand *op)
#define REX_X 0x42 #define REX_X 0x42
#define REX_B 0x41 #define REX_B 0x41
static void asm_rex(TCCState* S, int width64, Operand *ops, int nb_ops, int *op_type, static void asm_rex(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(TCCState* S, int width64, Operand *ops, int nb_ops, int *op_
} }
if (rex) { if (rex) {
if (saw_high_8bit) if (saw_high_8bit)
tcc_error(S, "can't encode register %%%ch when REX prefix is required", tcc_error("can't encode register %%%ch when REX prefix is required",
"acdb"[saw_high_8bit-4]); "acdb"[saw_high_8bit-4]);
g(S, rex); g(rex);
} }
} }
#endif #endif
@ -679,7 +679,7 @@ static void maybe_print_stats (void)
} }
} }
ST_FUNC void asm_opcode(TCCState *S, int opcode) ST_FUNC void asm_opcode(TCCState *s1, 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 *S, 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(S, ';'); unget_tok(';');
/* get operands */ /* get operands */
pop = ops; pop = ops;
@ -705,27 +705,27 @@ ST_FUNC void asm_opcode(TCCState *S, int opcode)
seg_prefix = 0; seg_prefix = 0;
alltypes = 0; alltypes = 0;
for(;;) { for(;;) {
if (S->tccpp_tok == ';' || S->tccpp_tok == TOK_LINEFEED) if (tok == ';' || tok == TOK_LINEFEED)
break; break;
if (nb_ops >= MAX_OPERANDS) { if (nb_ops >= MAX_OPERANDS) {
tcc_error(S, "incorrect number of operands"); tcc_error("incorrect number of operands");
} }
parse_operand(S, pop); parse_operand(s1, pop);
if (S->tccpp_tok == ':') { if (tok == ':') {
if (pop->type != OP_SEG || seg_prefix) if (pop->type != OP_SEG || seg_prefix)
tcc_error(S, "incorrect prefix"); tcc_error("incorrect prefix");
seg_prefix = segment_prefixes[pop->reg]; seg_prefix = segment_prefixes[pop->reg];
next(S); next();
parse_operand(S, pop); parse_operand(s1, pop);
if (!(pop->type & OP_EA)) { if (!(pop->type & OP_EA)) {
tcc_error(S, "segment prefix must be followed by memory reference"); tcc_error("segment prefix must be followed by memory reference");
} }
} }
pop++; pop++;
nb_ops++; nb_ops++;
if (S->tccpp_tok != ',') if (tok != ',')
break; break;
next(S); next();
} }
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(S, b >> 8); g(b >> 8);
g(S, b); g(b);
return; return;
} else if (opcode <= TOK_ASM_alllast) { } else if (opcode <= TOK_ASM_alllast) {
tcc_error(S, "bad operand with opcode '%s'", tcc_error("bad operand with opcode '%s'",
get_tok_str(S, opcode, NULL)); get_tok_str(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 = S->tccpp_table_ident[opcode - TOK_IDENT]; TokenSym *ts = 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(S, ts->str, ts->len-1)->tok; opcode = tok_alloc(ts->str, ts->len-1)->tok;
goto again; goto again;
} }
tcc_error(S, "unknown opcode '%s'", ts->str); tcc_error("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(S, "cannot infer opcode suffix"); tcc_error("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(S, 0x67); g(0x67);
break; break;
} }
} }
@ -913,7 +913,7 @@ again:
p66 = 1; p66 = 1;
} }
if (p66) if (p66)
g(S, 0x66); g(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(S, 0x9b); g(0x9b);
if (seg_prefix) if (seg_prefix)
g(S, seg_prefix); g(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(S, "bad op table"); tcc_error("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 (S, rex64, ops, nb_ops, op_type, modreg_index, modrm_index); asm_rex (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(S, ops[0].e.sym); esym = elfsym(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 - S->tccgen_ind - 2 - (v >= 0xff); jmp_disp = ops[0].e.v + esym->st_value - 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(S, "invalid displacement"); tcc_error("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(S, op1); g(op1);
op1 = (v >> 8) & 0xff; op1 = (v >> 8) & 0xff;
if (op1) if (op1)
g(S, op1); g(op1);
g(S, v); g(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(S, reg, &ops[modrm_index]); pc = asm_modrm(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(S, &ops[1].e); gen_expr32(&ops[1].e);
if (ops[0].e.sym) if (ops[0].e.sym)
tcc_error(S, "cannot relocate"); tcc_error("cannot relocate");
gen_le16(S, ops[0].e.v); gen_le16(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(S, "cannot relocate"); tcc_error("cannot relocate");
if (v & (OP_IM8 | OP_IM8S)) { if (v & (OP_IM8 | OP_IM8S)) {
g(S, ops[i].e.v); g(ops[i].e.v);
} else if (v & OP_IM16) { } else if (v & OP_IM16) {
gen_le16(S, ops[i].e.v); gen_le16(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(S, &ops[i].e); gen_expr64(&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(S, &ops[i].e); gen_disp32(&ops[i].e);
} else { } else {
gen_expr32(S, &ops[i].e); gen_expr32(&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 - S->tccgen_ind); add32le(cur_text_section->data + pc - 4, pc - 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(TCCState* S, const char *str) static inline int constraint_priority(const char *str)
{ {
int priority, c, pr; int priority, c, pr;
@ -1182,7 +1182,7 @@ static inline int constraint_priority(TCCState* S, const char *str)
pr = 4; pr = 4;
break; break;
default: default:
tcc_error(S, "unknown constraint '%c'", c); tcc_error("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 (TCCState* S, int t) ST_FUNC int asm_parse_regvar (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 = S->tccpp_table_ident[t - TOK_IDENT]->str; s = table_ident[t - TOK_IDENT]->str;
if (s[0] != '%') if (s[0] != '%')
return -1; return -1;
t = tok_alloc_const(S, s + 1); t = tok_alloc_const(s + 1);
unget_tok(S, t); unget_tok(t);
unget_tok(S, '%'); unget_tok('%');
parse_operand(S, &op); parse_operand(tcc_state, &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 (TCCState* S, 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(TCCState* S, ASMOperand *operands, ST_FUNC void asm_compute_constraints(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(TCCState* S, 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(S, operands, nb_operands, str, NULL); k = find_constraint(operands, nb_operands, str, NULL);
if ((unsigned)k >= i || i < nb_outputs) if ((unsigned)k >= i || i < nb_outputs)
tcc_error(S, "invalid reference in constraint %d ('%s')", tcc_error("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(S, "cannot reference twice the same operand"); tcc_error("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(TCCState* S, ASMOperand *operands,
op->priority = 1; op->priority = 1;
op->reg = reg; op->reg = reg;
} else { } else {
op->priority = constraint_priority(S, str); op->priority = constraint_priority(str);
} }
} }
@ -1316,7 +1316,7 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
} }
if (op->reg >= 0) { if (op->reg >= 0) {
if (is_reg_allocated(op->reg)) if (is_reg_allocated(op->reg))
tcc_error(S, "asm regvar requests register that's taken already"); tcc_error("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(TCCState* S, ASMOperand *operands,
/* FALL THRU */ /* FALL THRU */
case '&': case '&':
if (j >= nb_outputs) if (j >= nb_outputs)
tcc_error(S, "'%c' modifier can only be applied to outputs", c); tcc_error("'%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(TCCState* S, ASMOperand *operands,
} }
break; break;
default: default:
tcc_error(S, "asm constraint %d ('%s') could not be satisfied", tcc_error("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(TCCState* S, ASMOperand *operands,
if (!(regs_allocated[reg] & REG_OUT_MASK)) if (!(regs_allocated[reg] & REG_OUT_MASK))
goto reg_found2; goto reg_found2;
} }
tcc_error(S, "could not find free output register for reloading"); tcc_error("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(TCCState* S, 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(S, op->id, NULL) : "", op->id ? get_tok_str(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(TCCState* S, ASMOperand *operands,
#endif #endif
} }
ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str, ST_FUNC void subst_asm_operand(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(TCCState* S, 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(S, add_str, '$'); cstr_ccat(add_str, '$');
if (r & VT_SYM) { if (r & VT_SYM) {
const char *name = get_tok_str(S, sv->sym->v, NULL); const char *name = get_tok_str(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(S, tok_alloc_const(S, name), sv->sym); get_asm_sym(tok_alloc_const(name), sv->sym);
} }
if (S->leading_underscore) if (tcc_state->leading_underscore)
cstr_ccat(S, add_str, '_'); cstr_ccat(add_str, '_');
cstr_cat(S, add_str, name, -1); cstr_cat(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(S, add_str, '+'); cstr_ccat(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(S, add_str, buf, -1); cstr_cat(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(S, add_str, "(%rip)", -1); cstr_cat(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(TCCState* S, 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(S, add_str, buf, -1); cstr_cat(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(S, ""); tcc_internal_error("");
snprintf(buf, sizeof(buf), "(%%%s)", snprintf(buf, sizeof(buf), "(%%%s)",
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
get_tok_str(S, TOK_ASM_rax + reg, NULL) get_tok_str(TOK_ASM_rax + reg, NULL)
#else #else
get_tok_str(S, TOK_ASM_eax + reg, NULL) get_tok_str(TOK_ASM_eax + reg, NULL)
#endif #endif
); );
cstr_cat(S, add_str, buf, -1); cstr_cat(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(S, ""); tcc_internal_error("");
/* 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(TCCState* S, CString *add_str,
if (modifier == 'b') { if (modifier == 'b') {
if (reg >= 4) if (reg >= 4)
tcc_error(S, "cannot use byte register"); tcc_error("cannot use byte register");
size = 1; size = 1;
} else if (modifier == 'h') { } else if (modifier == 'h') {
if (reg >= 4) if (reg >= 4)
tcc_error(S, "cannot use byte register"); tcc_error("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(TCCState* S, CString *add_str,
break; break;
#endif #endif
} }
snprintf(buf, sizeof(buf), "%%%s", get_tok_str(S, reg, NULL)); snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
cstr_cat(S, add_str, buf, -1); cstr_cat(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(TCCState* S, ASMOperand *operands, int nb_operands, ST_FUNC void asm_gen_code(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(TCCState* S, 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(S, 0x41), reg-=8; g(0x41), reg-=8;
g(S, 0x50 + reg); g(0x50 + reg);
} }
} }
@ -1644,15 +1644,15 @@ ST_FUNC void asm_gen_code(TCCState* S, 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(S, op->reg, &sv); load(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(S, op->reg, op->vt); load(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(S, TREG_XDX, &sv); load(TREG_XDX, &sv);
} }
} }
} }
@ -1668,19 +1668,19 @@ ST_FUNC void asm_gen_code(TCCState* S, 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(S, out_reg, &sv); load(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(S, op->reg, &sv); store(op->reg, &sv);
} }
} else { } else {
store(S, op->reg, op->vt); store(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(S, TREG_XDX, &sv); store(TREG_XDX, &sv);
} }
} }
} }
@ -1690,14 +1690,14 @@ ST_FUNC void asm_gen_code(TCCState* S, 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(S, 0x41), reg-=8; g(0x41), reg-=8;
g(S, 0x58 + reg); g(0x58 + reg);
} }
} }
} }
} }
ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str) ST_FUNC void asm_clobber(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(TCCState* S, 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(S, str); reg = tok_alloc_const(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(TCCState* S, 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(S, reg, &type)) >= 0) { } else if ((reg = asm_parse_numeric_reg(reg, &type)) >= 0) {
; ;
#endif #endif
} else { } else {
tcc_error(S, "invalid clobber register '%s'", str); tcc_error("invalid clobber register '%s'", str);
} }
clobber_regs[reg] = 1; clobber_regs[reg] = 1;
} }

File diff suppressed because it is too large Load Diff

View File

@ -91,15 +91,15 @@ int gotplt_entry_type (int reloc_type)
return -1; return -1;
} }
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr) ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{ {
Section *plt = S->plt; Section *plt = s1->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 (S->output_type == TCC_OUTPUT_DLL) if (s1->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 *S, unsigned got_offset, struct sym_a
(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(S, plt, 16); p = section_ptr_add(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 *S, unsigned got_offset, struct sym_a
/* 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 = S->plt->reloc ? S->plt->reloc->data_offset : 0; relofs = s1->plt->reloc ? s1->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(S, plt, 16); p = section_ptr_add(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 *S, unsigned got_offset, struct sym_a
/* 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 *S) ST_FUNC void relocate_plt(TCCState *s1)
{ {
uint8_t *p, *p_end; uint8_t *p, *p_end;
if (!S->plt) if (!s1->plt)
return; return;
p = S->plt->data; p = s1->plt->data;
p_end = p + S->plt->data_offset; p_end = p + s1->plt->data_offset;
if (S->output_type != TCC_OUTPUT_DLL && p < p_end) { if (s1->output_type != TCC_OUTPUT_DLL && p < p_end) {
add32le(p + 2, S->got->sh_addr); add32le(p + 2, s1->got->sh_addr);
add32le(p + 8, S->got->sh_addr); add32le(p + 8, s1->got->sh_addr);
p += 16; p += 16;
while (p < p_end) { while (p < p_end) {
add32le(p + 2, S->got->sh_addr); add32le(p + 2, s1->got->sh_addr);
p += 16; p += 16;
} }
} }
if (S->plt->reloc) { if (s1->plt->reloc) {
ElfW_Rel *rel; ElfW_Rel *rel;
int x = S->plt->sh_addr + 16 + 6; int x = s1->plt->sh_addr + 16 + 6;
p = S->got->data; p = s1->got->data;
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) { for_each_elem(s1->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 *S)
} }
#endif #endif
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val) void relocate(TCCState *s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
switch (type) { switch (type) {
case R_386_32: case R_386_32:
if (S->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index; esym_index = get_sym_attr(s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
add32le(ptr, val); add32le(ptr, val);
return; return;
case R_386_PC32: case R_386_PC32:
if (S->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
/* DLL relocation */ /* DLL relocation */
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index; esym_index = get_sym_attr(s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
write32le(ptr, val); write32le(ptr, val);
return; return;
case R_386_GOTPC: case R_386_GOTPC:
add32le(ptr, S->got->sh_addr - addr); add32le(ptr, s1->got->sh_addr - addr);
return; return;
case R_386_GOTOFF: case R_386_GOTOFF:
add32le(ptr, val - S->got->sh_addr); add32le(ptr, val - s1->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(S, sym_index, 0)->got_offset); add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
return; return;
case R_386_16: case R_386_16:
if (S->output_format != TCC_OUTPUT_FORMAT_BINARY) { if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
output_file: output_file:
tcc_error(S, "can only produce 16-bit binary files"); tcc_error("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 (S->output_format != TCC_OUTPUT_FORMAT_BINARY) if (s1->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 - S->pe_imagebase); add32le(ptr, val - s1->pe_imagebase);
#endif #endif
/* do nothing */ /* do nothing */
return; return;
@ -267,12 +267,12 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
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 = S->sections[sym->st_shndx]; sec = s1->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(S, "unexpected R_386_TLS_GD pattern"); tcc_error("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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
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(S, "unexpected R_386_TLS_LDM pattern"); tcc_error("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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
int32_t x; int32_t x;
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
sec = S->sections[sym->st_shndx]; sec = s1->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);
} }

861
libtcc.c

File diff suppressed because it is too large Load Diff

View File

@ -15,95 +15,56 @@ 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 */
@ -111,24 +72,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 *S, void *ptr); LIBTCCAPI int tcc_relocate(TCCState *s1, 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
@ -137,24 +98,12 @@ LIBTCCAPI int tcc_relocate(TCCState *S, 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

View File

@ -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(TCCState* S, int c); ST_FUNC void g(int c);
ST_FUNC void gen_le16(TCCState* S, int c); ST_FUNC void gen_le16(int c);
ST_FUNC void gen_le32(TCCState* S, int c); ST_FUNC void gen_le32(int c);
/*************************************************************/ /*************************************************************/
#else #else
@ -20,85 +20,85 @@ ST_FUNC void gen_le32(TCCState* S, int c);
#include "tcc.h" #include "tcc.h"
/* XXX: make it faster ? */ /* XXX: make it faster ? */
ST_FUNC void g(TCCState* S, int c) ST_FUNC void g(int c)
{ {
int ind1; int ind1;
if (S->tccgen_nocode_wanted) if (nocode_wanted)
return; return;
ind1 = S->tccgen_ind + 1; ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated) if (ind1 > cur_text_section->data_allocated)
section_realloc(S, cur_text_section, ind1); section_realloc(cur_text_section, ind1);
cur_text_section->data[S->tccgen_ind] = c; cur_text_section->data[ind] = c;
S->tccgen_ind = ind1; ind = ind1;
} }
ST_FUNC void gen_le16 (TCCState* S, int i) ST_FUNC void gen_le16 (int i)
{ {
g(S, i); g(i);
g(S, i>>8); g(i>>8);
} }
ST_FUNC void gen_le32 (TCCState* S, int i) ST_FUNC void gen_le32 (int i)
{ {
int ind1; int ind1;
if (S->tccgen_nocode_wanted) if (nocode_wanted)
return; return;
ind1 = S->tccgen_ind + 4; ind1 = ind + 4;
if (ind1 > cur_text_section->data_allocated) if (ind1 > cur_text_section->data_allocated)
section_realloc(S, cur_text_section, ind1); section_realloc(cur_text_section, ind1);
cur_text_section->data[S->tccgen_ind++] = i & 0xFF; cur_text_section->data[ind++] = i & 0xFF;
cur_text_section->data[S->tccgen_ind++] = (i >> 8) & 0xFF; cur_text_section->data[ind++] = (i >> 8) & 0xFF;
cur_text_section->data[S->tccgen_ind++] = (i >> 16) & 0xFF; cur_text_section->data[ind++] = (i >> 16) & 0xFF;
cur_text_section->data[S->tccgen_ind++] = (i >> 24) & 0xFF; cur_text_section->data[ind++] = (i >> 24) & 0xFF;
} }
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe) ST_FUNC void gen_expr32(ExprValue *pe)
{ {
gen_le32(S, pe->v); gen_le32(pe->v);
} }
static void asm_emit_opcode(TCCState* S, uint32_t opcode) { static void asm_emit_opcode(uint32_t opcode) {
gen_le32(S, opcode); gen_le32(opcode);
} }
static void asm_nullary_opcode(TCCState *S, int token) static void asm_nullary_opcode(TCCState *s1, int token)
{ {
switch (token) { switch (token) {
// Sync instructions // Sync instructions
case TOK_ASM_fence: // I case TOK_ASM_fence: // I
asm_emit_opcode(S, (0x3 << 2) | 3 | (0 << 12)); asm_emit_opcode((0x3 << 2) | 3 | (0 << 12));
return; return;
case TOK_ASM_fence_i: // I case TOK_ASM_fence_i: // I
asm_emit_opcode(S, (0x3 << 2) | 3| (1 << 12)); asm_emit_opcode((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(S, (0x1C << 2) | 3 | (0 << 12)); asm_emit_opcode((0x1C << 2) | 3 | (0 << 12));
return; return;
case TOK_ASM_sbreak: // I (pseudo) case TOK_ASM_sbreak: // I (pseudo)
asm_emit_opcode(S, (0x1C << 2) | 3 | (0 << 12) | (1 << 20)); asm_emit_opcode((0x1C << 2) | 3 | (0 << 12) | (1 << 20));
return; return;
// Privileged Instructions // Privileged Instructions
case TOK_ASM_ecall: case TOK_ASM_ecall:
asm_emit_opcode(S, (0x1C << 2) | 3 | (0 << 20)); asm_emit_opcode((0x1C << 2) | 3 | (0 << 20));
return; return;
case TOK_ASM_ebreak: case TOK_ASM_ebreak:
asm_emit_opcode(S, (0x1C << 2) | 3 | (1 << 20)); asm_emit_opcode((0x1C << 2) | 3 | (1 << 20));
return; return;
// Other // Other
case TOK_ASM_wfi: case TOK_ASM_wfi:
asm_emit_opcode(S, (0x1C << 2) | 3 | (0x105 << 20)); asm_emit_opcode((0x1C << 2) | 3 | (0x105 << 20));
return; return;
default: default:
expect(S, "nullary instruction"); expect("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 *S, Operand *op) static void parse_operand(TCCState *s1, Operand *op)
{ {
ExprValue e; ExprValue e;
int8_t reg; int8_t reg;
op->type = 0; op->type = 0;
if ((reg = asm_parse_regvar(S, S->tccpp_tok)) != -1) { if ((reg = asm_parse_regvar(tok)) != -1) {
next(S); // skip register name next(); // 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 (S->tccpp_tok == '$') { } else if (tok == '$') {
/* constant value */ /* constant value */
next(S); // skip '#' or '$' next(); // skip '#' or '$'
} }
asm_expr(S, &e); asm_expr(s1, &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(S, "operand"); expect("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 *S, 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 *S, int token) static void asm_unary_opcode(TCCState *s1, int token)
{ {
uint32_t opcode = (0x1C << 2) | 3 | (2 << 12); uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);
Operand op; Operand op;
parse_operand(S, &op); parse_operand(s1, &op);
if (op.type != OP_REG) { if (op.type != OP_REG) {
expect(S, "register"); expect("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(S, opcode | (0xC00 << 20)); asm_emit_opcode(opcode | (0xC00 << 20));
return; return;
case TOK_ASM_rdcycleh: case TOK_ASM_rdcycleh:
asm_emit_opcode(S, opcode | (0xC80 << 20)); asm_emit_opcode(opcode | (0xC80 << 20));
return; return;
case TOK_ASM_rdtime: case TOK_ASM_rdtime:
asm_emit_opcode(S, opcode | (0xC01 << 20) | ENCODE_RD(op.reg)); asm_emit_opcode(opcode | (0xC01 << 20) | ENCODE_RD(op.reg));
return; return;
case TOK_ASM_rdtimeh: case TOK_ASM_rdtimeh:
asm_emit_opcode(S, opcode | (0xC81 << 20) | ENCODE_RD(op.reg)); asm_emit_opcode(opcode | (0xC81 << 20) | ENCODE_RD(op.reg));
return; return;
case TOK_ASM_rdinstret: case TOK_ASM_rdinstret:
asm_emit_opcode(S, opcode | (0xC02 << 20) | ENCODE_RD(op.reg)); asm_emit_opcode(opcode | (0xC02 << 20) | ENCODE_RD(op.reg));
return; return;
case TOK_ASM_rdinstreth: case TOK_ASM_rdinstreth:
asm_emit_opcode(S, opcode | (0xC82 << 20) | ENCODE_RD(op.reg)); asm_emit_opcode(opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
return; return;
default: default:
expect(S, "unary instruction"); expect("unary instruction");
} }
} }
static void asm_emit_u(TCCState *S, int token, uint32_t opcode, const Operand* rd, const Operand* rs2) static void asm_emit_u(int token, uint32_t opcode, const Operand* rd, const Operand* rs2)
{ {
if (rd->type != OP_REG) { if (rd->type != OP_REG) {
tcc_error(S, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected destination operand that is a register", get_tok_str(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, "'%s': Expected second source operand that is an immediate value", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected second source operand that is an immediate value", get_tok_str(token, NULL));
return; return;
} else if (rs2->e.v >= 0x100000) { } else if (rs2->e.v >= 0x100000) {
tcc_error(S, "'%s': Expected second source operand that is an immediate value between 0 and 0xfffff", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 0xfffff", get_tok_str(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(S, opcode | ENCODE_RD(rd->reg) | (rs2->e.v << 12)); gen_le32(opcode | ENCODE_RD(rd->reg) | (rs2->e.v << 12));
} }
static void asm_binary_opcode(TCCState* S, int token) static void asm_binary_opcode(TCCState* s1, int token)
{ {
Operand ops[2]; Operand ops[2];
parse_operand(S, &ops[0]); parse_operand(s1, &ops[0]);
if (S->tccpp_tok == ',') if (tok == ',')
next(S); next();
else else
expect(S, "','"); expect("','");
parse_operand(S, &ops[1]); parse_operand(s1, &ops[1]);
switch (token) { switch (token) {
case TOK_ASM_lui: case TOK_ASM_lui:
asm_emit_u(S, token, (0xD << 2) | 3, &ops[0], &ops[1]); asm_emit_u(token, (0xD << 2) | 3, &ops[0], &ops[1]);
return; return;
case TOK_ASM_auipc: case TOK_ASM_auipc:
asm_emit_u(S, token, (0x05 << 2) | 3, &ops[0], &ops[1]); asm_emit_u(token, (0x05 << 2) | 3, &ops[0], &ops[1]);
return; return;
default: default:
expect(S, "binary instruction"); expect("binary instruction");
} }
} }
/* caller: Add funct3, funct7 into opcode */ /* caller: Add funct3, funct7 into opcode */
static void asm_emit_r(TCCState* S, int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2) static void asm_emit_r(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, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
return; return;
} }
if (rs1->type != OP_REG) { if (rs1->type != OP_REG) {
tcc_error(S, "'%s': Expected first source operand that is a register", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
return; return;
} }
if (rs2->type != OP_REG) { if (rs2->type != OP_REG) {
tcc_error(S, "'%s': Expected second source operand that is a register or immediate", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected second source operand that is a register or immediate", get_tok_str(token, NULL));
return; return;
} }
/* R-type instruction: /* R-type instruction:
@ -251,22 +251,22 @@ static void asm_emit_r(TCCState* S, int token, uint32_t opcode, const Operand* r
14...12 funct3 14...12 funct3
11...7 rd 11...7 rd
6...0 opcode */ 6...0 opcode */
gen_le32(S, opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg)); gen_le32(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(TCCState* S, int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2) static void asm_emit_i(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, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
return; return;
} }
if (rs1->type != OP_REG) { if (rs1->type != OP_REG) {
tcc_error(S, "'%s': Expected first source operand that is a register", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
return; return;
} }
if (rs2->type != OP_IM12S) { if (rs2->type != OP_IM12S) {
tcc_error(S, "'%s': Expected second source operand that is an immediate value between 0 and 4095", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 4095", get_tok_str(token, NULL));
return; return;
} }
/* I-type instruction: /* I-type instruction:
@ -276,156 +276,156 @@ static void asm_emit_i(TCCState* S, int token, uint32_t opcode, const Operand* r
11...7 rd 11...7 rd
6...0 opcode */ 6...0 opcode */
gen_le32(S, opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | (rs2->e.v << 20)); gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | (rs2->e.v << 20));
} }
static void asm_shift_opcode(TCCState *S, int token) static void asm_shift_opcode(TCCState *s1, int token)
{ {
Operand ops[3]; Operand ops[3];
parse_operand(S, &ops[0]); parse_operand(s1, &ops[0]);
if (S->tccpp_tok == ',') if (tok == ',')
next(S); next();
else else
expect(S, "','"); expect("','");
parse_operand(S, &ops[1]); parse_operand(s1, &ops[1]);
if (S->tccpp_tok == ',') if (tok == ',')
next(S); next();
else else
expect(S, "','"); expect("','");
parse_operand(S, &ops[2]); parse_operand(s1, &ops[2]);
switch (token) { switch (token) {
case TOK_ASM_sll: case TOK_ASM_sll:
asm_emit_r(S, token, (0xC << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (4 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0x4 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0xC << 2) | 3 | (5 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0x4 << 2) | 3 | (5 << 12) | (16 << 26), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0xE << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (6 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return; return;
default: default:
expect(S, "shift instruction"); expect("shift instruction");
} }
} }
static void asm_data_processing_opcode(TCCState* S, int token) static void asm_data_processing_opcode(TCCState* s1, int token)
{ {
Operand ops[3]; Operand ops[3];
parse_operand(S, &ops[0]); parse_operand(s1, &ops[0]);
if (S->tccpp_tok == ',') if (tok == ',')
next(S); next();
else else
expect(S, "','"); expect("','");
parse_operand(S, &ops[1]); parse_operand(s1, &ops[1]);
if (S->tccpp_tok == ',') if (tok == ',')
next(S); next();
else else
expect(S, "','"); expect("','");
parse_operand(S, &ops[2]); parse_operand(s1, &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(S, token, (0xC << 2) | 3, &ops[0], &ops[1], &ops[2]); asm_emit_r(token, (0xC << 2) | 3, &ops[0], &ops[1], &ops[2]);
return; return;
case TOK_ASM_addi: case TOK_ASM_addi:
asm_emit_i(S, token, (4 << 2) | 3, &ops[0], &ops[1], &ops[2]); asm_emit_i(token, (4 << 2) | 3, &ops[0], &ops[1], &ops[2]);
return; return;
case TOK_ASM_sub: case TOK_ASM_sub:
asm_emit_r(S, token, (0xC << 2) | 3 | (32 << 25), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0xE << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0x6 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0xE << 2) | 3 | (0 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0x4 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0xC << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0x4 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0xC << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0x4 << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0xC << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0x4 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0xC << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_r(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(S, token, (0x4 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(token, (0x4 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
return; return;
default: default:
expect(S, "known data processing instruction"); expect("known data processing instruction");
} }
} }
/* caller: Add funct3 to opcode */ /* caller: Add funct3 to opcode */
static void asm_emit_s(TCCState* S, int token, uint32_t opcode, const Operand* rs1, const Operand* rs2, const Operand* imm) static void asm_emit_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, "'%s': Expected first source operand that is a register", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
return; return;
} }
if (rs2->type != OP_REG) { if (rs2->type != OP_REG) {
tcc_error(S, "'%s': Expected second source operand that is a register", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected second source operand that is a register", get_tok_str(token, NULL));
return; return;
} }
if (imm->type != OP_IM12S) { if (imm->type != OP_IM12S) {
tcc_error(S, "'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(token, NULL));
return; return;
} }
{ {
@ -438,112 +438,112 @@ static void asm_emit_s(TCCState* S, int token, uint32_t opcode, const Operand* r
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(S, opcode | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg) | ((v & 0x1F) << 7) | ((v >> 5) << 25)); gen_le32(opcode | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg) | ((v & 0x1F) << 7) | ((v >> 5) << 25));
} }
} }
static void asm_data_transfer_opcode(TCCState* S, int token) static void asm_data_transfer_opcode(TCCState* s1, int token)
{ {
Operand ops[3]; Operand ops[3];
parse_operand(S, &ops[0]); parse_operand(s1, &ops[0]);
if (ops[0].type != OP_REG) { if (ops[0].type != OP_REG) {
expect(S, "register"); expect("register");
return; return;
} }
if (S->tccpp_tok == ',') if (tok == ',')
next(S); next();
else else
expect(S, "','"); expect("','");
parse_operand(S, &ops[1]); parse_operand(s1, &ops[1]);
if (ops[1].type != OP_REG) { if (ops[1].type != OP_REG) {
expect(S, "register"); expect("register");
return; return;
} }
if (S->tccpp_tok == ',') if (tok == ',')
next(S); next();
else else
expect(S, "','"); expect("','");
parse_operand(S, &ops[2]); parse_operand(s1, &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(S, token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]); asm_emit_i(token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);
return; return;
case TOK_ASM_lh: case TOK_ASM_lh:
asm_emit_i(S, token, (0x0 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0x0 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0x0 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0x0 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0x0 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0x0 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_i(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(S, token, (0x8 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_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(S, token, (0x8 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_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(S, token, (0x8 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_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(S, token, (0x8 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]); asm_emit_s(token, (0x8 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
return; return;
default: default:
expect(S, "known data transfer instruction"); expect("known data transfer instruction");
} }
} }
static void asm_branch_opcode(TCCState* S, int token) static void asm_branch_opcode(TCCState* s1, 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(S, &ops[0]); parse_operand(s1, &ops[0]);
if (ops[0].type != OP_REG) { if (ops[0].type != OP_REG) {
expect(S, "register"); expect("register");
return; return;
} }
if (S->tccpp_tok == ',') if (tok == ',')
next(S); next();
else else
expect(S, "','"); expect("','");
parse_operand(S, &ops[1]); parse_operand(s1, &ops[1]);
if (ops[1].type != OP_REG) { if (ops[1].type != OP_REG) {
expect(S, "register"); expect("register");
return; return;
} }
if (S->tccpp_tok == ',') if (tok == ',')
next(S); next();
else else
expect(S, "','"); expect("','");
parse_operand(S, &ops[2]); parse_operand(s1, &ops[2]);
if (ops[2].type != OP_IM12S) { if (ops[2].type != OP_IM12S) {
tcc_error(S, "'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(token, NULL));
return; return;
} }
offset = ops[2].e.v; offset = ops[2].e.v;
if (offset & 1) { if (offset & 1) {
tcc_error(S, "'%s': Expected third operand that is an even immediate value", get_tok_str(S, token, NULL)); tcc_error("'%s': Expected third operand that is an even immediate value", get_tok_str(token, NULL));
return; return;
} }
@ -567,12 +567,12 @@ static void asm_branch_opcode(TCCState* S, int token)
opcode |= 7 << 12; opcode |= 7 << 12;
break; break;
default: default:
expect(S, "known branch instruction"); expect("known branch instruction");
} }
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)); 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));
} }
ST_FUNC void asm_opcode(TCCState *S, int token) ST_FUNC void asm_opcode(TCCState *s1, int token)
{ {
switch (token) { switch (token) {
case TOK_ASM_fence: case TOK_ASM_fence:
@ -585,7 +585,7 @@ ST_FUNC void asm_opcode(TCCState *S, 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(S, token); asm_nullary_opcode(s1, token);
return; return;
case TOK_ASM_rdcycle: case TOK_ASM_rdcycle:
@ -594,12 +594,12 @@ ST_FUNC void asm_opcode(TCCState *S, 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(S, token); asm_unary_opcode(s1, token);
return; return;
case TOK_ASM_lui: case TOK_ASM_lui:
case TOK_ASM_auipc: case TOK_ASM_auipc:
asm_binary_opcode(S, token); asm_binary_opcode(s1, token);
return; return;
case TOK_ASM_sll: case TOK_ASM_sll:
@ -620,7 +620,7 @@ ST_FUNC void asm_opcode(TCCState *S, 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(S, token); asm_shift_opcode(s1, token);
return; return;
case TOK_ASM_add: case TOK_ASM_add:
@ -642,7 +642,7 @@ ST_FUNC void asm_opcode(TCCState *S, 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(S, token); asm_data_processing_opcode(s1, 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 *S, 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(S, token); asm_data_transfer_opcode(s1, token);
return; return;
case TOK_ASM_beq: case TOK_ASM_beq:
@ -664,35 +664,35 @@ ST_FUNC void asm_opcode(TCCState *S, 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(S, token); asm_branch_opcode(s1, token);
return; return;
default: default:
expect(S, "known instruction"); expect("known instruction");
} }
} }
ST_FUNC void subst_asm_operand(TCCState *S, CString *add_str, SValue *sv, int modifier) ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
{ {
tcc_error(S, "RISCV64 asm not implemented."); tcc_error("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(TCCState *S, ASMOperand *operands, int nb_operands, ST_FUNC void asm_gen_code(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(TCCState *S, ASMOperand *operands, ST_FUNC void asm_compute_constraints(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(TCCState *S, uint8_t *clobber_regs, const char *str) ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
{ {
int reg; int reg;
TokenSym *ts; TokenSym *ts;
@ -701,15 +701,15 @@ ST_FUNC void asm_clobber(TCCState *S, uint8_t *clobber_regs, const char *str)
!strcmp(str, "cc") || !strcmp(str, "cc") ||
!strcmp(str, "flags")) !strcmp(str, "flags"))
return; return;
ts = tok_alloc(S, str, strlen(str)); ts = tok_alloc(str, strlen(str));
reg = asm_parse_regvar(S, ts->tok); reg = asm_parse_regvar(ts->tok);
if (reg == -1) { if (reg == -1) {
tcc_error(S, "invalid clobber register '%s'", str); tcc_error("invalid clobber register '%s'", str);
} }
clobber_regs[reg] = 1; clobber_regs[reg] = 1;
} }
ST_FUNC int asm_parse_regvar (TCCState* S, int t) ST_FUNC int asm_parse_regvar (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) {

File diff suppressed because it is too large Load Diff

View File

@ -95,39 +95,39 @@ int gotplt_entry_type (int reloc_type)
return -1; return -1;
} }
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr) ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{ {
Section *plt = S->plt; Section *plt = s1->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(S, plt, 32); section_ptr_add(plt, 32);
plt_offset = plt->data_offset; plt_offset = plt->data_offset;
p = section_ptr_add(S, plt, 16); p = section_ptr_add(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 *S) ST_FUNC void relocate_plt(TCCState *s1)
{ {
uint8_t *p, *p_end; uint8_t *p, *p_end;
if (!S->plt) if (!s1->plt)
return; return;
p = S->plt->data; p = s1->plt->data;
p_end = p + S->plt->data_offset; p_end = p + s1->plt->data_offset;
if (p < p_end) { if (p < p_end) {
uint64_t plt = S->plt->sh_addr; uint64_t plt = s1->plt->sh_addr;
uint64_t got = S->got->sh_addr; uint64_t got = s1->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(S, "Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt); tcc_error("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 *S)
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 - S->plt->data); uint64_t pc = plt + (p - s1->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(S, "Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc); tcc_error("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 *S)
} }
} }
if (S->plt->reloc) { if (s1->plt->reloc) {
ElfW_Rel *rel; ElfW_Rel *rel;
p = S->got->data; p = s1->got->data;
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) { for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
write64le(p + rel->r_offset, S->plt->sh_addr); write64le(p + rel->r_offset, s1->plt->sh_addr);
} }
} }
} }
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, void relocate(TCCState *s1, 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 *S, 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(S, "R_RISCV_BRANCH relocation failed" tcc_error("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 *S, 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(S, "R_RISCV_JAL relocation failed" tcc_error("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 *S, 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(S, "R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s", tcc_error("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 *S, 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 = S->got->sh_addr + get_sym_attr(S, sym_index, 0)->got_offset; val = s1->got->sh_addr + get_sym_attr(s1, 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(S, "R_RISCV_GOT_HI20 relocation failed"); tcc_error("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 *S, 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(S, "unsupported hi/lo pcrel reloc scheme"); tcc_error("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 *S, 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(S, "unsupported hi/lo pcrel reloc scheme"); tcc_error("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 *S, 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(S, "R_RISCV_RVC_BRANCH relocation failed" tcc_error("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 *S, 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(S, "R_RISCV_RVC_BRANCH relocation failed" tcc_error("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 *S, ElfW_Rel *rel, int type, unsigned char *ptr,
return; return;
case R_RISCV_32: case R_RISCV_32:
if (S->output_type == TCC_OUTPUT_DLL) { if (s1->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 *S, 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 (S->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index; esym_index = get_sym_attr(s1, 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
View File

@ -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(S, buf); return tcc_strdup(buf);
} }
static unsigned getclock_ms(void) static unsigned getclock_ms(void)
@ -268,101 +268,9 @@ 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;
@ -371,19 +279,13 @@ 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;
} }
@ -392,57 +294,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(S, "no input files"); tcc_error("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(S, "could not write '%s'", S->outfile); tcc_error("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(S, "cannot specify libraries with -c"); tcc_error("cannot specify libraries with -c");
if (S->nb_files > 1 && S->outfile) if (s->nb_files > 1 && s->outfile)
tcc_error(S, "cannot specify output file with -c many files"); tcc_error("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 & TCC_OPTION_d_t)) { /* -dt option */ && (s->dflag & 16)) { /* -dt option */
if (t) if (t)
S->dflag |= TCC_OPTION_d_32; s->dflag |= 32;
S->run_test = ++t; s->run_test = ++t;
if (n) if (n)
--n; --n;
} }
@ -450,48 +352,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
View File

@ -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 *S; TCCState *s1;
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,78 +743,6 @@ 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 */
@ -999,11 +927,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 S->qrel #define qrel s1->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 S->last_hi #define last_hi s1->last_hi
#endif #endif
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
@ -1034,10 +962,6 @@ 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
@ -1067,117 +991,6 @@ 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 {
@ -1361,7 +1174,7 @@ enum tcc_token {
/* ------------ libtcc.c ------------ */ /* ------------ libtcc.c ------------ */
//ST_DATA struct TCCState *S; ST_DATA struct TCCState *tcc_state;
/* 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);
@ -1370,56 +1183,53 @@ 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(TCCState* S, void *ptr); PUB_FUNC void tcc_free(void *ptr);
PUB_FUNC void *tcc_malloc(TCCState* S, unsigned long size); PUB_FUNC void *tcc_malloc(unsigned long size);
PUB_FUNC void *tcc_mallocz(TCCState* S, unsigned long size); PUB_FUNC void *tcc_mallocz(unsigned long size);
PUB_FUNC void *tcc_realloc(TCCState* S, void *ptr, unsigned long size); PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size);
PUB_FUNC char *tcc_strdup(TCCState* S, const char *str); PUB_FUNC char *tcc_strdup(const char *str);
#else #else
#define tcc_free(s, ptr) tcc_free_debug(s, ptr) #define tcc_free(ptr) tcc_free_debug(ptr)
#define tcc_malloc(s, size) tcc_malloc_debug(s, size, __FILE__, __LINE__) #define tcc_malloc(size) tcc_malloc_debug(size, __FILE__, __LINE__)
#define tcc_mallocz(s, size) tcc_mallocz_debug(s, size, __FILE__, __LINE__) #define tcc_mallocz(size) tcc_mallocz_debug(size, __FILE__, __LINE__)
#define tcc_realloc(s, ptr, size) tcc_realloc_debug(s, ptr, size, __FILE__, __LINE__) #define tcc_realloc(ptr,size) tcc_realloc_debug(ptr, size, __FILE__, __LINE__)
#define tcc_strdup(s, str) tcc_strdup_debug(s, str, __FILE__, __LINE__) #define tcc_strdup(str) tcc_strdup_debug(str, __FILE__, __LINE__)
PUB_FUNC void tcc_free_debug(TCCState* S, void *ptr); PUB_FUNC void tcc_free_debug(void *ptr);
PUB_FUNC void *tcc_malloc_debug(TCCState* S, unsigned long size, const char *file, int line); PUB_FUNC void *tcc_malloc_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_mallocz_debug(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 void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line);
PUB_FUNC char *tcc_strdup_debug(TCCState* S, const char *str, const char *file, int line); PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
#endif #endif
#define free(p) use_tcc_free(S, p) #define free(p) use_tcc_free(p)
#define malloc(s) use_tcc_malloc(S, s) #define malloc(s) use_tcc_malloc(s)
#define realloc(p, s) use_tcc_realloc(S, p, s) #define realloc(p, s) use_tcc_realloc(p, s)
#undef strdup #undef strdup
#define strdup(s) use_tcc_strdup(S, s) #define strdup(s) use_tcc_strdup(s)
PUB_FUNC void _tcc_error_noabort(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3); PUB_FUNC void _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2);
PUB_FUNC NORETURN void _tcc_error(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3); PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2);
PUB_FUNC void _tcc_warning(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3); PUB_FUNC void _tcc_warning(const char *fmt, ...) PRINTF_LIKE(1,2);
#define tcc_internal_error(S, msg) tcc_error(S, "internal compiler error\n"\ #define tcc_internal_error(msg) tcc_error("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(TCCState* S, void *ptab, int *nb_ptr, void *data); ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data);
ST_FUNC void dynarray_reset(TCCState* S, void *pp, int *n); ST_FUNC void dynarray_reset(void *pp, int *n);
ST_INLN void cstr_ccat(TCCState* S, CString *cstr, int ch); ST_INLN void cstr_ccat(CString *cstr, int ch);
ST_FUNC void cstr_cat(TCCState* S, CString *cstr, const char *str, int len); ST_FUNC void cstr_cat(CString *cstr, const char *str, int len);
ST_FUNC void cstr_wccat(TCCState* S, CString *cstr, int ch); ST_FUNC void cstr_wccat(CString *cstr, int ch);
ST_FUNC void cstr_new(TCCState* S, CString *cstr); ST_FUNC void cstr_new(CString *cstr);
ST_FUNC void cstr_free(TCCState* S, CString *cstr); ST_FUNC void cstr_free(CString *cstr);
ST_FUNC int cstr_printf(TCCState* S, CString *cs, const char *fmt, ...) PRINTF_LIKE(3,4); ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3);
ST_FUNC int cstr_vprintf(TCCState* S, CString *cstr, const char *fmt, va_list ap); ST_FUNC int cstr_vprintf(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 *S, const char *filename, int initlen); ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
ST_FUNC int tcc_open(TCCState *S, const char *filename); ST_FUNC int tcc_open(TCCState *s1, const char *filename);
ST_FUNC void tcc_close(TCCState *S); ST_FUNC void tcc_close(void);
ST_FUNC int tcc_add_file_internal(TCCState *S, const char *filename, int flags); ST_FUNC int tcc_add_file_internal(TCCState *s1, 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 */
@ -1439,26 +1249,26 @@ ST_FUNC int tcc_add_file_internal(TCCState *S, 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 *S); ST_FUNC void tcc_add_bcheck(TCCState *s1);
#endif #endif
#ifdef CONFIG_TCC_BACKTRACE #ifdef CONFIG_TCC_BACKTRACE
ST_FUNC void tcc_add_btstub(TCCState *S); ST_FUNC void tcc_add_btstub(TCCState *s1);
#endif #endif
ST_FUNC void tcc_add_pragma_libs(TCCState *S); ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
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 *S, const char *dllname); ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname);
ST_FUNC char *tcc_load_text(TCCState *S, int fd); ST_FUNC char *tcc_load_text(int fd);
/* tcc_parse_args return codes: */ /* tcc_parse_args return codes: */
#define OPT_HELP 1 #define OPT_HELP 1
@ -1472,6 +1282,18 @@ ST_FUNC char *tcc_load_text(TCCState *S, 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 */
@ -1499,36 +1321,36 @@ enum line_macro_output_format {
LINE_MACRO_OUTPUT_FORMAT_P10 = 11 LINE_MACRO_OUTPUT_FORMAT_P10 = 11
}; };
ST_FUNC TokenSym *tok_alloc(TCCState* S, const char *str, int len); ST_FUNC TokenSym *tok_alloc(const char *str, int len);
ST_FUNC int tok_alloc_const(TCCState* S, const char *str); ST_FUNC int tok_alloc_const(const char *str);
ST_FUNC const char *get_tok_str(TCCState* S, int v, CValue *cv); ST_FUNC const char *get_tok_str(int v, CValue *cv);
ST_FUNC void begin_macro(TCCState* S, TokenString *str, int alloc); ST_FUNC void begin_macro(TokenString *str, int alloc);
ST_FUNC void end_macro(TCCState* S); ST_FUNC void end_macro(void);
ST_FUNC int set_idnum(TCCState* S, int c, int val); ST_FUNC int set_idnum(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(TCCState* S); ST_FUNC TokenString *tok_str_alloc(void);
ST_FUNC void tok_str_free(TCCState* S, TokenString *s); ST_FUNC void tok_str_free(TokenString *s);
ST_FUNC void tok_str_free_str(TCCState* S, int *str); ST_FUNC void tok_str_free_str(int *str);
ST_FUNC void tok_str_add(TCCState* S, TokenString *s, int t); ST_FUNC void tok_str_add(TokenString *s, int t);
ST_FUNC void tok_str_add_tok(TCCState* S, TokenString *s); ST_FUNC void tok_str_add_tok(TokenString *s);
ST_INLN void define_push(TCCState* S, int v, int macro_type, int *str, Sym *first_arg); ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg);
ST_FUNC void define_undef(TCCState* S, Sym *s); ST_FUNC void define_undef(Sym *s);
ST_INLN Sym *define_find(TCCState* S, int v); ST_INLN Sym *define_find(int v);
ST_FUNC void free_defines(TCCState* S, Sym *b); ST_FUNC void free_defines(Sym *b);
ST_FUNC Sym *label_find(TCCState* S, int v); ST_FUNC Sym *label_find(int v);
ST_FUNC Sym *label_push(TCCState* S, Sym **ptop, int v, int flags); ST_FUNC Sym *label_push(Sym **ptop, int v, int flags);
ST_FUNC void label_pop(TCCState* S, Sym **ptop, Sym *slast, int keep); ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep);
ST_FUNC void parse_define(TCCState* S); ST_FUNC void parse_define(void);
ST_FUNC void preprocess(TCCState* S, int is_bof); ST_FUNC void preprocess(int is_bof);
ST_FUNC void next(TCCState* S); ST_FUNC void next(void);
ST_INLN void unget_tok(TCCState* S, int last_tok); ST_INLN void unget_tok(int last_tok);
ST_FUNC void preprocess_start(TCCState *S, int filetype); ST_FUNC void preprocess_start(TCCState *s1, int filetype);
ST_FUNC void preprocess_end(TCCState *S); ST_FUNC void preprocess_end(TCCState *s1);
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 *S); ST_FUNC int tcc_preprocess(TCCState *s1);
ST_FUNC void skip(TCCState* S, int c); ST_FUNC void skip(int c);
ST_FUNC NORETURN void expect(TCCState* S, const char *msg); ST_FUNC NORETURN void expect(const char *msg);
/* space excluding newline */ /* space excluding newline */
static inline int is_space(int ch) { static inline int is_space(int ch) {
@ -1550,85 +1372,104 @@ 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_FUNC void tccgen_init(TCCState *S); ST_DATA Sym *global_stack;
ST_FUNC int tccgen_compile(TCCState *S); ST_DATA Sym *local_stack;
ST_FUNC void tccgen_finish(TCCState *S); ST_DATA Sym *local_label_stack;
ST_FUNC void check_vstack(TCCState* S); ST_DATA Sym *global_label_stack;
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(TCCState* S); ST_FUNC void test_lvalue(void);
ST_FUNC ElfSym *elfsym(TCCState* S, Sym *); ST_FUNC ElfSym *elfsym(Sym *);
ST_FUNC void update_storage(TCCState* S, Sym *sym); ST_FUNC void update_storage(Sym *sym);
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_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
ST_FUNC void put_extern_sym(TCCState* S, Sym *sym, Section *section, addr_t value, unsigned long size); ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
#if PTR_SIZE == 4 #if PTR_SIZE == 4
ST_FUNC void greloc(TCCState* S, Section *s, Sym *sym, unsigned long offset, int type); ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);
#endif #endif
ST_FUNC void greloca(TCCState* S, Section *s, Sym *sym, unsigned long offset, int type, addr_t addend); ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
ST_INLN void sym_free(TCCState* S, Sym *sym); ST_INLN void sym_free(Sym *sym);
ST_FUNC Sym *sym_push(TCCState* S, int v, CType *type, int r, int c); ST_FUNC Sym *sym_push(int v, CType *type, int r, int c);
ST_FUNC void sym_pop(TCCState* S, Sym **ptop, Sym *b, int keep); ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
ST_FUNC Sym *sym_push2(TCCState* S, Sym **ps, int v, int t, int c); ST_FUNC Sym *sym_push2(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(TCCState* S, int v); ST_INLN Sym *sym_find(int v);
ST_INLN Sym *struct_find(TCCState* S, int v); ST_INLN Sym *struct_find(int v);
ST_FUNC Sym *global_identifier_push(TCCState* S, int v, int t, int c); ST_FUNC Sym *global_identifier_push(int v, int t, int c);
ST_FUNC Sym *external_global_sym(TCCState* S, int v, CType *type); ST_FUNC Sym *external_global_sym(int v, CType *type);
ST_FUNC Sym *external_helper_sym(TCCState* S, int v); ST_FUNC Sym *external_helper_sym(int v);
ST_FUNC void vpush_helper_func(TCCState* S, int v); ST_FUNC void vpush_helper_func(int v);
ST_FUNC void vset(TCCState* S, CType *type, int r, int v); ST_FUNC void vset(CType *type, int r, int v);
ST_FUNC void vset_VT_CMP(TCCState* S, int op); ST_FUNC void vset_VT_CMP(int op);
ST_FUNC void vpushi(TCCState* S, int v); ST_FUNC void vpushi(int v);
ST_FUNC void vpushv(TCCState* S, SValue *v); ST_FUNC void vpushv(SValue *v);
ST_FUNC void vpushsym(TCCState* S, CType *type, Sym *sym); ST_FUNC void vpushsym(CType *type, Sym *sym);
ST_FUNC void vswap(TCCState* S); ST_FUNC void vswap(void);
ST_FUNC void vrote(TCCState* S, SValue *e, int n); ST_FUNC void vrote(SValue *e, int n);
ST_FUNC void vrott(TCCState* S, int n); ST_FUNC void vrott(int n);
ST_FUNC void vrotb(TCCState* S, int n); ST_FUNC void vrotb(int n);
ST_FUNC void vpop(TCCState* S); ST_FUNC void vpop(void);
#if PTR_SIZE == 4 #if PTR_SIZE == 4
ST_FUNC void lexpand(TCCState* S); ST_FUNC void lexpand(void);
#endif #endif
#ifdef TCC_TARGET_ARM #ifdef TCC_TARGET_ARM
ST_FUNC int get_reg_ex(TCCState* S, int rc, int rc2); ST_FUNC int get_reg_ex(int rc, int rc2);
#endif #endif
ST_FUNC void save_reg(TCCState* S, int r); ST_FUNC void save_reg(int r);
ST_FUNC void save_reg_upstack(TCCState* S, int r, int n); ST_FUNC void save_reg_upstack(int r, int n);
ST_FUNC int get_reg(TCCState* S, int rc); ST_FUNC int get_reg(int rc);
ST_FUNC void save_regs(TCCState* S, int n); ST_FUNC void save_regs(int n);
ST_FUNC void gaddrof(TCCState* S); ST_FUNC void gaddrof(void);
ST_FUNC int gv(TCCState* S, int rc); ST_FUNC int gv(int rc);
ST_FUNC void gv2(TCCState* S, int rc1, int rc2); ST_FUNC void gv2(int rc1, int rc2);
ST_FUNC void gen_op(TCCState* S, int op); ST_FUNC void gen_op(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(TCCState* S, CType *type); ST_FUNC void mk_pointer(CType *type);
ST_FUNC void vstore(TCCState* S); ST_FUNC void vstore(void);
ST_FUNC void inc(TCCState* S, int post, int c); ST_FUNC void inc(int post, int c);
ST_FUNC void parse_mult_str (TCCState* S, CString *astr, const char *msg); ST_FUNC void parse_mult_str (CString *astr, const char *msg);
ST_FUNC void parse_asm_str(TCCState* S, CString *astr); ST_FUNC void parse_asm_str(CString *astr);
ST_FUNC void indir(TCCState* S); ST_FUNC void indir(void);
ST_FUNC void unary(TCCState* S); ST_FUNC void unary(void);
ST_FUNC void gexpr(TCCState* S); ST_FUNC void gexpr(void);
ST_FUNC int expr_const(TCCState* S); ST_FUNC int expr_const(void);
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67 #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
ST_FUNC Sym *get_sym_ref(TCCState* S, CType *type, Section *sec, unsigned long offset, unsigned long size); ST_FUNC Sym *get_sym_ref(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(TCCState* S, int nb_args); ST_FUNC void gbound_args(int nb_args);
ST_DATA int func_bound_add_epilog; ST_DATA int func_bound_add_epilog;
#endif #endif
@ -1648,51 +1489,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 *S); ST_FUNC void tccelf_begin_file(TCCState *s1);
ST_FUNC void tccelf_end_file(TCCState *S); ST_FUNC void tccelf_end_file(TCCState *s1);
#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 *S, const char *name, int sh_type, int sh_flags); ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
ST_FUNC void section_realloc(TCCState* S, Section *sec, unsigned long new_size); ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
ST_FUNC size_t section_add(TCCState* S, Section *sec, addr_t size, int align); ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
ST_FUNC void *section_ptr_add(TCCState* S, Section *sec, addr_t size); ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
ST_FUNC Section *find_section(TCCState *S, const char *name); ST_FUNC Section *find_section(TCCState *s1, const char *name);
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 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 int put_elf_str(TCCState* S, Section *s, const char *sym); ST_FUNC int put_elf_str(Section *s, const char *sym);
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 put_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 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 *S, const char *str, int type, int other, int desc, unsigned long value); ST_FUNC void put_stabs(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value);
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_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_stabn(TCCState *S, int type, int other, int desc, int value); ST_FUNC void put_stabn(TCCState *s1, int type, int other, int desc, int value);
ST_FUNC void resolve_common_syms(TCCState *S); ST_FUNC void resolve_common_syms(TCCState *s1);
ST_FUNC void relocate_syms(TCCState *S, Section *symtab, int do_resolve); ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
ST_FUNC void relocate_sections(TCCState *S); ST_FUNC void relocate_sections(TCCState *s1);
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(TCCState* S, int fd, unsigned long file_offset, unsigned long size); ST_FUNC void *load_data(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 *S, int fd, unsigned long file_offset); ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
ST_FUNC int tcc_load_archive(TCCState *S, int fd, int alacarte); ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte);
ST_FUNC void add_array(TCCState *S, const char *sec, int c); ST_FUNC void add_array(TCCState *s1, 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 *S); ST_FUNC void build_got_entries(TCCState *s1);
#endif #endif
ST_FUNC struct sym_attr *get_sym_attr(TCCState *S, int index, int alloc); ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, 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 *S, const char *name, Section *sec, addr_t offs); ST_FUNC int set_global_sym(TCCState *s1, 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> */
@ -1701,11 +1542,11 @@ ST_FUNC int set_global_sym(TCCState *S, const char *name, Section *sec, addr_t o
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 *S, int fd, const char *filename, int level); ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
ST_FUNC int tcc_load_ldscript(TCCState *S, int fd); ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd);
#endif #endif
#ifndef TCC_TARGET_PE #ifndef TCC_TARGET_PE
ST_FUNC void tcc_add_runtime(TCCState *S); ST_FUNC void tcc_add_runtime(TCCState *s1);
#endif #endif
/* ------------ xxx-link.c ------------ */ /* ------------ xxx-link.c ------------ */
@ -1723,41 +1564,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 *S, unsigned got_offset, struct sym_attr *attr); ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
ST_FUNC void relocate_plt(TCCState *S); ST_FUNC void relocate_plt(TCCState *s1);
#endif #endif
#endif #endif
ST_FUNC void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val); ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
/* ------------ xxx-gen.c ------------ */ /* ------------ xxx-gen.c ------------ */
ST_DATA const char * 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(TCCState* S, int t, int a); ST_FUNC void gsym_addr(int t, int a);
ST_FUNC void gsym(TCCState* S, int t); ST_FUNC void gsym(int t);
ST_FUNC void load(TCCState *S, int r, SValue *sv); ST_FUNC void load(int r, SValue *sv);
ST_FUNC void store(TCCState *S, int r, SValue *v); ST_FUNC void store(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(TCCState *S, int nb_args); ST_FUNC void gfunc_call(int nb_args);
ST_FUNC void gfunc_prolog(TCCState *S, Sym *func_sym); ST_FUNC void gfunc_prolog(Sym *func_sym);
ST_FUNC void gfunc_epilog(TCCState *S); ST_FUNC void gfunc_epilog(void);
ST_FUNC void gen_fill_nops(TCCState* S, int); ST_FUNC void gen_fill_nops(int);
ST_FUNC int gjmp(TCCState* S, int t); ST_FUNC int gjmp(int t);
ST_FUNC void gjmp_addr(TCCState* S, int a); ST_FUNC void gjmp_addr(int a);
ST_FUNC int gjmp_cond(TCCState* S, int op, int t); ST_FUNC int gjmp_cond(int op, int t);
ST_FUNC int gjmp_append(TCCState *S, int n, int t); ST_FUNC int gjmp_append(int n, int t);
ST_FUNC void gen_opi(TCCState* S, int op); ST_FUNC void gen_opi(int op);
ST_FUNC void gen_opf(TCCState* S, int op); ST_FUNC void gen_opf(int op);
ST_FUNC void gen_cvt_ftoi(TCCState *S, int t); ST_FUNC void gen_cvt_ftoi(int t);
ST_FUNC void gen_cvt_itof(TCCState *S, int t); ST_FUNC void gen_cvt_itof(int t);
ST_FUNC void gen_cvt_ftof(TCCState *S, int t); ST_FUNC void gen_cvt_ftof(int t);
ST_FUNC void ggoto(TCCState *S); ST_FUNC void ggoto(void);
#ifndef TCC_TARGET_C67 #ifndef TCC_TARGET_C67
ST_FUNC void o(TCCState* S, unsigned int c); ST_FUNC void o(unsigned int c);
#endif #endif
ST_FUNC void gen_vla_sp_save(TCCState* S, int addr); ST_FUNC void gen_vla_sp_save(int addr);
ST_FUNC void gen_vla_sp_restore(TCCState* S, int addr); ST_FUNC void gen_vla_sp_restore(int addr);
ST_FUNC void gen_vla_alloc(TCCState* S, CType *type, int align); ST_FUNC void gen_vla_alloc(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;
@ -1786,57 +1627,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(TCCState* S, int c); ST_FUNC void g(int c);
ST_FUNC void gen_le16(TCCState* S, int c); ST_FUNC void gen_le16(int c);
ST_FUNC void gen_le32(TCCState* S, int c); ST_FUNC void gen_le32(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(TCCState* S, int r, Sym *sym, int c); ST_FUNC void gen_addr32(int r, Sym *sym, int c);
ST_FUNC void gen_addrpc32(TCCState* S, int r, Sym *sym, int c); ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);
ST_FUNC void gen_cvt_csti(TCCState* S, int t); ST_FUNC void gen_cvt_csti(int t);
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv); ST_FUNC void gen_increment_tcov (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(TCCState* S, int r, Sym *sym, int64_t c); ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c);
ST_FUNC void gen_opl(TCCState* S, int op); ST_FUNC void gen_opl(int op);
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
ST_FUNC void gen_vla_result(TCCState* S, int addr); ST_FUNC void gen_vla_result(int addr);
#endif #endif
ST_FUNC void gen_cvt_sxtw(TCCState *S); ST_FUNC void gen_cvt_sxtw(void);
ST_FUNC void gen_cvt_csti(TCCState* S, int t); ST_FUNC void gen_cvt_csti(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(TCCState *S); PUB_FUNC const char *default_elfinterp(struct TCCState *s);
#endif #endif
ST_FUNC void arm_init(TCCState *S); ST_FUNC void arm_init(struct TCCState *s);
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv); ST_FUNC void gen_increment_tcov (SValue *sv);
#endif #endif
/* ------------ arm64-gen.c ------------ */ /* ------------ arm64-gen.c ------------ */
#ifdef TCC_TARGET_ARM64 #ifdef TCC_TARGET_ARM64
ST_FUNC void gen_opl(TCCState* S, int op); ST_FUNC void gen_opl(int op);
ST_FUNC void gfunc_return(TCCState *S, CType *func_type); ST_FUNC void gfunc_return(CType *func_type);
ST_FUNC void gen_va_start(TCCState *S); ST_FUNC void gen_va_start(void);
ST_FUNC void gen_va_arg(TCCState *S, CType *t); ST_FUNC void gen_va_arg(CType *t);
ST_FUNC void gen_clear_cache(TCCState *S); ST_FUNC void gen_clear_cache(void);
ST_FUNC void gen_cvt_sxtw(TCCState *S); ST_FUNC void gen_cvt_sxtw(void);
ST_FUNC void gen_cvt_csti(TCCState *S, int t); ST_FUNC void gen_cvt_csti(int t);
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv); ST_FUNC void gen_increment_tcov (SValue *sv);
#endif #endif
/* ------------ riscv64-gen.c ------------ */ /* ------------ riscv64-gen.c ------------ */
#ifdef TCC_TARGET_RISCV64 #ifdef TCC_TARGET_RISCV64
ST_FUNC void gen_opl(TCCState* S, int op); ST_FUNC void gen_opl(int op);
//ST_FUNC void gfunc_return(TCCState *S, CType *func_type); //ST_FUNC void gfunc_return(CType *func_type);
ST_FUNC void gen_va_start(TCCState *S); ST_FUNC void gen_va_start(void);
ST_FUNC void arch_transfer_ret_regs(TCCState* S, int); ST_FUNC void arch_transfer_ret_regs(int);
ST_FUNC void gen_cvt_sxtw(TCCState *S); ST_FUNC void gen_cvt_sxtw(void);
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv); ST_FUNC void gen_increment_tcov (SValue *sv);
#endif #endif
/* ------------ c67-gen.c ------------ */ /* ------------ c67-gen.c ------------ */
@ -1846,44 +1687,44 @@ ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
/* ------------ tcccoff.c ------------ */ /* ------------ tcccoff.c ------------ */
#ifdef TCC_TARGET_COFF #ifdef TCC_TARGET_COFF
ST_FUNC int tcc_output_coff(TCCState *S, FILE *f); ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f);
ST_FUNC int tcc_load_coff(TCCState *S, int fd); ST_FUNC int tcc_load_coff(TCCState * s1, int fd);
#endif #endif
/* ------------ tccasm.c ------------ */ /* ------------ tccasm.c ------------ */
ST_FUNC void asm_instr(TCCState* S); ST_FUNC void asm_instr(void);
ST_FUNC void asm_global_instr(TCCState* S); ST_FUNC void asm_global_instr(void);
ST_FUNC int tcc_assemble(TCCState *S, int do_preprocess); ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess);
#ifdef CONFIG_TCC_ASM #ifdef CONFIG_TCC_ASM
ST_FUNC int find_constraint(TCCState* S, ASMOperand *operands, int nb_operands, const char *name, const char **pp); ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
ST_FUNC Sym* get_asm_sym(TCCState* S, int name, Sym *csym); ST_FUNC Sym* get_asm_sym(int name, Sym *csym);
ST_FUNC void asm_expr(TCCState *S, ExprValue *pe); ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
ST_FUNC int asm_int_expr(TCCState *S); ST_FUNC int asm_int_expr(TCCState *s1);
/* ------------ i386-asm.c ------------ */ /* ------------ i386-asm.c ------------ */
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe); ST_FUNC void gen_expr32(ExprValue *pe);
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
ST_FUNC void gen_expr64(TCCState* S, ExprValue *pe); ST_FUNC void gen_expr64(ExprValue *pe);
#endif #endif
ST_FUNC void asm_opcode(TCCState *S, int opcode); ST_FUNC void asm_opcode(TCCState *s1, int opcode);
ST_FUNC int asm_parse_regvar(TCCState* S, int t); ST_FUNC int asm_parse_regvar(int t);
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 asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str, SValue *sv, int modifier); ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
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_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str); ST_FUNC void asm_clobber(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 *S, int fd, const char *filename); ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename);
ST_FUNC int pe_output_file(TCCState * S, const char *filename); ST_FUNC int pe_output_file(TCCState * s1, const char *filename);
ST_FUNC int pe_putimport(TCCState *S, int dllindex, const char *name, addr_t value); ST_FUNC int pe_putimport(TCCState *s1, 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(TCCState * S, SValue *sv, SValue *v2); ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
#endif #endif
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
ST_FUNC void pe_add_unwind_data(TCCState* S, unsigned start, unsigned end, unsigned stack); ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
#endif #endif
PUB_FUNC int tcc_get_dllexports(TCCState* S, const char *filename, char **pp); PUB_FUNC int tcc_get_dllexports(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
@ -1893,11 +1734,11 @@ PUB_FUNC int tcc_get_dllexports(TCCState* S, const char *filename, char **pp);
/* ------------ tccmacho.c ----------------- */ /* ------------ tccmacho.c ----------------- */
#ifdef TCC_TARGET_MACHO #ifdef TCC_TARGET_MACHO
ST_FUNC int macho_output_file(TCCState * S, const char *filename); ST_FUNC int macho_output_file(TCCState * s1, const char *filename);
ST_FUNC int macho_load_dll(TCCState *S, int fd, const char *filename, int lev); ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev);
ST_FUNC int macho_load_tbd(TCCState *S, int fd, const char *filename, int lev); ST_FUNC int macho_load_tbd(TCCState *s1, 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
@ -1914,17 +1755,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 *S); ST_FUNC void tcc_run_free(TCCState *s1);
#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
/********************************************************/ /********************************************************/
@ -1979,12 +1820,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 *S); PUB_FUNC void tcc_enter_state(TCCState *s1);
PUB_FUNC void tcc_exit_state(TCCState *S); PUB_FUNC void tcc_exit_state(TCCState *s1);
/* 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((\
S->warn_num = offsetof(TCCState, sw) \ tcc_state->warn_num = offsetof(TCCState, sw) \
- offsetof(TCCState, warn_none), _tcc_warning)) - offsetof(TCCState, warn_none), _tcc_warning))
/********************************************************/ /********************************************************/
@ -1994,10 +1835,10 @@ PUB_FUNC void tcc_exit_state(TCCState *S);
#undef TCC_SET_STATE #undef TCC_SET_STATE
#ifdef USING_GLOBALS #ifdef USING_GLOBALS
# define TCC_STATE_VAR(sym) S->sym # define TCC_STATE_VAR(sym) tcc_state->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) S->sym # define TCC_STATE_VAR(sym) s1->sym
# define TCC_SET_STATE(fn) (tcc_enter_state(S),fn) # define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn)
#endif #endif

834
tccasm.c

File diff suppressed because it is too large Load Diff

116
tcccoff.c
View File

@ -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 *S); void SortSymbolTable(TCCState *s1);
Section *FindSection(TCCState * S, const char *sname); Section *FindSection(TCCState * s1, const char *sname);
int C67_main_entry_point; int C67_main_entry_point;
int FindCoffSymbolIndex(TCCState * S, const char *func_name); int FindCoffSymbolIndex(TCCState * s1, 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 *S, FILE *f) ST_FUNC int tcc_output_coff(TCCState *s1, 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 *S, FILE *f)
Coff_str_table = pCoff_str_table = NULL; Coff_str_table = pCoff_str_table = NULL;
stext = FindSection(S, ".text"); stext = FindSection(s1, ".text");
sdata = FindSection(S, ".data"); sdata = FindSection(s1, ".data");
sbss = FindSection(S, ".bss"); sbss = FindSection(s1, ".bss");
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
coff_nb_syms = FindCoffSymbolIndex(S, "XXXXXXXXXX1"); coff_nb_syms = FindCoffSymbolIndex(s1, "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 *S, FILE *f)
CoffTextSectionNo = -1; CoffTextSectionNo = -1;
for (i = 1; i < S->nb_sections; i++) { for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i]; coff_sec = &section_header[i];
tcc_sect = S->sections[i]; tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) { if (OutputTheSection(tcc_sect)) {
NSectionsToOutput++; NSectionsToOutput++;
@ -149,9 +149,9 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
// for the raw data // for the raw data
for (i = 1; i < S->nb_sections; i++) { for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i]; coff_sec = &section_header[i];
tcc_sect = S->sections[i]; tcc_sect = s1->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 *S, 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 < S->nb_sections; i++) { for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i]; coff_sec = &section_header[i];
tcc_sect = S->sections[i]; tcc_sect = s1->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 *S, 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 < S->nb_sections; i++) { for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i]; coff_sec = &section_header[i];
tcc_sect = S->sections[i]; tcc_sect = s1->sections[i];
coff_sec->s_nlnno = 0; coff_sec->s_nlnno = 0;
coff_sec->s_lnnoptr = 0; coff_sec->s_lnnoptr = 0;
if (S->do_debug && tcc_sect == stext) { if (s1->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 *S, FILE *f)
file_hdr.f_symptr = file_pointer; /* file pointer to symtab */ file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
if (S->do_debug) if (s1->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 *S, 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 < S->nb_sections; i++) { for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i]; coff_sec = &section_header[i];
tcc_sect = S->sections[i]; tcc_sect = s1->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 *S, FILE *f)
} }
// write raw data // write raw data
for (i = 1; i < S->nb_sections; i++) { for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i]; coff_sec = &section_header[i];
tcc_sect = S->sections[i]; tcc_sect = s1->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 *S, FILE *f)
} }
// write relocation data // write relocation data
for (i = 1; i < S->nb_sections; i++) { for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i]; coff_sec = &section_header[i];
tcc_sect = S->sections[i]; tcc_sect = s1->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 *S, 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 (S->do_debug) if (s1->do_debug)
SortSymbolTable(S); SortSymbolTable(s1);
// write line no data // write line no data
for (i = 1; i < S->nb_sections; i++) { for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i]; coff_sec = &section_header[i];
tcc_sect = S->sections[i]; tcc_sect = s1->sections[i];
if (S->do_debug && tcc_sect == stext) { if (s1->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 *S, FILE *f)
// output a function begin // output a function begin
CoffLineNo.l_addr.l_symndx = CoffLineNo.l_addr.l_symndx =
FindCoffSymbolIndex(S, func_name); FindCoffSymbolIndex(s1, 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 *S, FILE *f)
} }
// write symbol table // write symbol table
if (S->do_debug) { if (s1->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 *S, FILE *f)
int nstr; int nstr;
int n = 0; int n = 0;
Coff_str_table = (char *) tcc_malloc(S, MAX_STR_TABLE); Coff_str_table = (char *) tcc_malloc(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 *S, 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(S, "String table too large"); tcc_error("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 *S, FILE *f)
} }
if (k >= nFuncs) { if (k >= nFuncs) {
tcc_error(S, "debug info can't find function: %s", name); tcc_error("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 *S, FILE *f)
} }
} }
if (S->do_debug) { if (s1->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 *S, 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(S, Coff_str_table); tcc_free(Coff_str_table);
} }
return 0; return 0;
@ -690,13 +690,13 @@ ST_FUNC int tcc_output_coff(TCCState *S, 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 *S) void SortSymbolTable(TCCState *s1)
{ {
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(S, nb_syms * sizeof(Elf32_Sym)); NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
p = (Elf32_Sym *) symtab_section->data; p = (Elf32_Sym *) symtab_section->data;
@ -730,7 +730,7 @@ void SortSymbolTable(TCCState *S)
} }
if (k >= nFuncs) { if (k >= nFuncs) {
tcc_error(S, "debug (sort) info can't find function: %s", name2); tcc_error("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 *S)
} }
if (n != nb_syms) if (n != nb_syms)
tcc_error(S, "Internal Compiler error, debug info"); tcc_error("Internal Compiler error, debug info");
// copy it all back // copy it all back
@ -766,11 +766,11 @@ void SortSymbolTable(TCCState *S)
*p++ = NewTable[i]; *p++ = NewTable[i];
} }
tcc_free(S, NewTable); tcc_free(NewTable);
} }
int FindCoffSymbolIndex(TCCState *S, const char *func_name) int FindCoffSymbolIndex(TCCState *s1, 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 * S, const char *sname) Section *FindSection(TCCState * s1, const char *sname)
{ {
Section *s; Section *s;
int i; int i;
for (i = 1; i < S->nb_sections; i++) { for (i = 1; i < s1->nb_sections; i++) {
s = S->sections[i]; s = s1->sections[i];
if (!strcmp(sname, s->name)) if (!strcmp(sname, s->name))
return s; return s;
} }
tcc_error(S, "could not find section %s", sname); tcc_error("could not find section %s", sname);
return 0; return 0;
} }
ST_FUNC int tcc_load_coff(TCCState * S, int fd) ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
{ {
// tktk TokenSym *ts; // tktk TokenSym *ts;
@ -872,39 +872,39 @@ ST_FUNC int tcc_load_coff(TCCState * S, int fd)
f = fdopen(fd, "rb"); f = fdopen(fd, "rb");
if (!f) { if (!f) {
tcc_error(S, "Unable to open .out file for input"); tcc_error("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(S, "error reading .out file for input"); tcc_error("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(S, "error reading .out file for input"); tcc_error("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(S, "error reading .out file for input"); tcc_error("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(S, "error reading .out file for input"); tcc_error("error reading .out file for input");
Coff_str_table = (char *) tcc_malloc(S, str_size); Coff_str_table = (char *) tcc_malloc(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(S, "error reading .out file for input"); tcc_error("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(S, "error reading .out file for input"); tcc_error("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(S, "error reading .out file for input"); tcc_error("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 * S, int fd)
if (name[0] == '_' && strcmp(name, "_main") != 0) if (name[0] == '_' && strcmp(name, "_main") != 0)
name++; name++;
tcc_add_symbol(S, name, (void*)(uintptr_t)csym.n_value); tcc_add_symbol(s1, 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(S, "error reading .out file for input"); tcc_error("error reading .out file for input");
i++; i++;
} }
} }

1345
tccelf.c

File diff suppressed because it is too large Load Diff

5334
tccgen.c

File diff suppressed because it is too large Load Diff

View File

@ -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(TCCState* S, struct macho *mo, uint32_t cmd, uint32_t cmdsize) static void * add_lc(struct macho *mo, uint32_t cmd, uint32_t cmdsize)
{ {
struct load_command *lc = tcc_mallocz(S, cmdsize); struct load_command *lc = tcc_mallocz(cmdsize);
lc->cmd = cmd; lc->cmd = cmd;
lc->cmdsize = cmdsize; lc->cmdsize = cmdsize;
mo->lc = tcc_realloc(S, mo->lc, sizeof(mo->lc[0]) * (mo->nlc + 1)); mo->lc = tcc_realloc(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(TCCState* S, struct macho *mo, const char *name) static struct segment_command_64 * add_segment(struct macho *mo, const char *name)
{ {
struct segment_command_64 *sc = add_lc(S, mo, LC_SEGMENT_64, sizeof(*sc)); struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc));
strncpy(sc->segname, name, 16); strncpy(sc->segname, name, 16);
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(TCCState* S, struct macho *mo, struct segment_command_64 **_seg, const char *name) static int add_section(struct macho *mo, struct segment_command_64 **_seg, const char *name)
{ {
struct segment_command_64 *seg = *_seg; struct segment_command_64 *seg = *_seg;
int ret = seg->nsects; int ret = seg->nsects;
struct section_64 *sec; struct section_64 *sec;
seg->nsects++; seg->nsects++;
seg->cmdsize += sizeof(*sec); seg->cmdsize += sizeof(*sec);
seg = tcc_realloc(S, seg, sizeof(*seg) + seg->nsects * sizeof(*sec)); seg = tcc_realloc(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(TCCState* S, struct macho *mo, char *name) static void * add_dylib(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(S, mo, LC_LOAD_DYLIB, sz); lc = add_lc(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(TCCState* S, struct macho *mo, char *name)
return lc; return lc;
} }
static void check_relocs(TCCState *S, struct macho *mo) static void check_relocs(TCCState *s1, struct macho *mo)
{ {
Section *s; Section *s;
ElfW_Rel *rel; ElfW_Rel *rel;
@ -314,10 +314,10 @@ static void check_relocs(TCCState *S, 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;
S->got = new_section(S, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
mo->indirsyms = new_section(S, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
for (i = 1; i < S->nb_sections; i++) { for (i = 1; i < s1->nb_sections; i++) {
s = S->sections[i]; s = s1->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 *S, 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(S, sym_index, 1); attr = get_sym_attr(s1, sym_index, 1);
if (!attr->dyn_index) { if (!attr->dyn_index) {
uint32_t *pi = section_ptr_add(S, mo->indirsyms, sizeof(*pi)); uint32_t *pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
attr->got_offset = S->got->data_offset; attr->got_offset = s1->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(S, S->got, PTR_SIZE); section_ptr_add(s1->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(S, "undefined local symbol???"); tcc_error("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(S->symtab, S->got, attr->got_offset, put_elf_reloc(s1->symtab, s1->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 *S, 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(S, mo->stubs, 6); jmp = section_ptr_add(mo->stubs, 6);
jmp[0] = 0xff; /* jmpq *ofs(%rip) */ jmp[0] = 0xff; /* jmpq *ofs(%rip) */
jmp[1] = 0x25; jmp[1] = 0x25;
put_elf_reloc(S->symtab, mo->stubs, put_elf_reloc(s1->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 *S, struct macho *mo)
} }
} }
static int check_symbols(TCCState *S, struct macho *mo) static int check_symbols(TCCState *s1, 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 *S, 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(S, "local syms after global ones"); tcc_error("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(S, "external defined symbol after undefined"); tcc_error("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(S->dynsymtab_section, name)) { || find_elf_sym(s1->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 *S, struct macho *mo)
sym->st_shndx = SHN_FROMDLL; sym->st_shndx = SHN_FROMDLL;
continue; continue;
} }
tcc_error_noabort(S, "undefined symbol '%s'", name); tcc_error_noabort("undefined symbol '%s'", name);
ret = -1; ret = -1;
} }
} }
return ret; return ret;
} }
static void convert_symbol(TCCState *S, struct macho *mo, struct nlist_64 *pn) static void convert_symbol(TCCState *s1, 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 *S, struct macho *mo, struct nlist_64 *pn)
n.n_type = N_ABS; n.n_type = N_ABS;
break; break;
default: default:
tcc_error(S, "unhandled ELF symbol type %d %s", tcc_error("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(S, "should have been rewritten to SHN_FROMDLL: %s", name); tcc_error("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(S, "unhandled ELF symbol section %d %s", sym->st_shndx, name); tcc_error("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(S, "ELF section %d not mapped into Mach-O for symbol %s", tcc_error("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,15 +458,16 @@ static void convert_symbol(TCCState *S, struct macho *mo, struct nlist_64 *pn)
*pn = n; *pn = n;
} }
static void convert_symbols(TCCState *S, struct macho *mo) static void convert_symbols(TCCState *s1, 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(S, mo, pn); convert_symbol(s1, mo, pn);
} }
static int machosymcmp(const void *_a, const void *_b, TCCState *S) static int machosymcmp(const void *_a, const void *_b)
{ {
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;
@ -491,33 +492,33 @@ static int machosymcmp(const void *_a, const void *_b, TCCState *S)
return ea - eb; return ea - eb;
} }
static void create_symtab(TCCState *S, struct macho *mo) static void create_symtab(TCCState *s1, 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(S, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); mo->stubs = new_section(s1, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
mo->stubsym = put_elf_sym(S, S->symtab, 0, 0, mo->stubsym = put_elf_sym(s1->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(S, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
mo->strtab = new_section(S, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); mo->strtab = new_section(s1, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
put_elf_str(S, mo->strtab, " "); /* Mach-O starts strtab with a space */ put_elf_str(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(S, mo->symtab, sizeof(*pn) * (sym_end - 1)); pn = section_ptr_add(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(S, mo->strtab, name); pn[sym_index - 1].n_strx = put_elf_str(mo->strtab, name);
pn[sym_index - 1].n_value = sym_index; pn[sym_index - 1].n_value = sym_index;
} }
tcc_enter_state(S); /* qsort needs global state */ tcc_enter_state(s1); /* qsort needs global state */
tcc_qsort_s(pn, sym_end - 1, sizeof(*pn), (tcc_cmpfun)machosymcmp, S); qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp);
tcc_exit_state(S); tcc_exit_state(s1);
mo->e2msym = tcc_malloc(S, sym_end * sizeof(*mo->e2msym)); mo->e2msym = tcc_malloc(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;
@ -545,7 +546,7 @@ const struct {
/*[sk_linkedit] =*/ { 3, S_REGULAR, NULL }, /*[sk_linkedit] =*/ { 3, S_REGULAR, NULL },
}; };
static void collect_sections(TCCState *S, struct macho *mo) static void collect_sections(TCCState *s1, struct macho *mo)
{ {
int i, sk, numsec; int i, sk, numsec;
uint64_t curaddr, fileofs; uint64_t curaddr, fileofs;
@ -556,49 +557,49 @@ static void collect_sections(TCCState *S, struct macho *mo)
struct dysymtab_command *dysymlc; struct dysymtab_command *dysymlc;
char *str; char *str;
seg = add_segment(S, mo, "__PAGEZERO"); seg = add_segment(mo, "__PAGEZERO");
seg->vmsize = (uint64_t)1 << 32; seg->vmsize = (uint64_t)1 << 32;
seg = add_segment(S, mo, "__TEXT"); seg = add_segment(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(S, mo, "__DATA"); seg = add_segment(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(S, mo, "__LINKEDIT"); seg = add_segment(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(S, mo, LC_MAIN, sizeof(*mo->ep)); mo->ep = add_lc(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(S, mo, LC_LOAD_DYLINKER, i); dyldlc = add_lc(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(S, mo, LC_SYMTAB, sizeof(*symlc)); symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc));
dysymlc = add_lc(S, mo, LC_DYSYMTAB, sizeof(*dysymlc)); dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc));
for(i = 0; i < S->nb_loaded_dlls; i++) { for(i = 0; i < s1->nb_loaded_dlls; i++) {
DLLReference *dllref = S->loaded_dlls[i]; DLLReference *dllref = s1->loaded_dlls[i];
if (dllref->level == 0) if (dllref->level == 0)
add_dylib(S, mo, dllref->name); add_dylib(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(S, data_section, 1); section_ptr_add(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 = S->nb_sections; i-- > 1;) { for (i = s1->nb_sections; i-- > 1;) {
int type, flags; int type, flags;
s = S->sections[i]; s = s1->sections[i];
type = s->sh_type; type = s->sh_type;
flags = s->sh_flags; flags = s->sh_flags;
sk = sk_unknown; sk = sk_unknown;
@ -613,7 +614,7 @@ static void collect_sections(TCCState *S, 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 == S->got) if (s == s1->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;
@ -633,7 +634,7 @@ static void collect_sections(TCCState *S, struct macho *mo)
curaddr += 4096; curaddr += 4096;
seg = NULL; seg = NULL;
numsec = 0; numsec = 0;
mo->elfsectomacho = tcc_mallocz(S, sizeof(*mo->elfsectomacho) * S->nb_sections); mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->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) {
@ -645,7 +646,7 @@ static void collect_sections(TCCState *S, 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(S, mo, &seg, skinfo[sk].name); si = add_section(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;
@ -669,7 +670,7 @@ static void collect_sections(TCCState *S, struct macho *mo)
sec->align = al; sec->align = al;
al = 1ULL << al; al = 1ULL << al;
if (al > 4096) if (al > 4096)
tcc_warning(S, "alignment > 4096"), sec->align = 12, al = 4096; tcc_warning("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) {
@ -738,7 +739,7 @@ static void collect_sections(TCCState *S, 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 *S, struct macho *mo, FILE *fp) static void macho_write(TCCState *s1, struct macho *mo, FILE *fp)
{ {
int i, sk; int i, sk;
uint64_t fileofs = 0; uint64_t fileofs = 0;
@ -778,7 +779,7 @@ static void macho_write(TCCState *S, struct macho *mo, FILE *fp)
} }
} }
ST_FUNC int macho_output_file(TCCState *S, const char *filename) ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
{ {
int fd, mode, file_type; int fd, mode, file_type;
FILE *fp; FILE *fp;
@ -787,7 +788,7 @@ ST_FUNC int macho_output_file(TCCState *S, const char *filename)
(void)memset(&mo, 0, sizeof(mo)); (void)memset(&mo, 0, sizeof(mo));
file_type = S->output_type; file_type = s1->output_type;
if (file_type == TCC_OUTPUT_OBJ) if (file_type == TCC_OUTPUT_OBJ)
mode = 0666; mode = 0666;
else else
@ -795,36 +796,36 @@ ST_FUNC int macho_output_file(TCCState *S, 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(S, "could not write '%s: %s'", filename, strerror(errno)); tcc_error_noabort("could not write '%s: %s'", filename, strerror(errno));
return -1; return -1;
} }
fp = fdopen(fd, "wb"); fp = fdopen(fd, "wb");
if (S->verbose) if (s1->verbose)
printf("<- %s\n", filename); printf("<- %s\n", filename);
tcc_add_runtime(S); tcc_add_runtime(s1);
resolve_common_syms(S); resolve_common_syms(s1);
create_symtab(S, &mo); create_symtab(s1, &mo);
check_relocs(S, &mo); check_relocs(s1, &mo);
ret = check_symbols(S, &mo); ret = check_symbols(s1, &mo);
if (!ret) { if (!ret) {
collect_sections(S, &mo); collect_sections(s1, &mo);
relocate_syms(S, S->symtab, 0); relocate_syms(s1, s1->symtab, 0);
mo.ep->entryoff = get_sym_addr(S, "main", 1, 1) mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1)
- get_segment(&mo, 1)->vmaddr; - get_segment(&mo, 1)->vmaddr;
if (S->nb_errors) if (s1->nb_errors)
goto do_ret; goto do_ret;
relocate_sections(S); relocate_sections(s1);
convert_symbols(S, &mo); convert_symbols(s1, &mo);
macho_write(S, &mo, fp); macho_write(s1, &mo, fp);
} }
do_ret: do_ret:
for (i = 0; i < mo.nlc; i++) for (i = 0; i < mo.nlc; i++)
tcc_free(S, mo.lc[i]); tcc_free(mo.lc[i]);
tcc_free(S, mo.lc); tcc_free(mo.lc);
tcc_free(S, mo.elfsectomacho); tcc_free(mo.elfsectomacho);
tcc_free(S, mo.e2msym); tcc_free(mo.e2msym);
fclose(fp); fclose(fp);
return ret; return ret;
@ -836,13 +837,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* S, int lev, const char* soname) ST_FUNC int macho_add_dllref(TCCState* s1, 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 < S->nb_loaded_dlls; i++) { for(i = 0; i < s1->nb_loaded_dlls; i++) {
dllref = S->loaded_dlls[i]; dllref = s1->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)
@ -850,7 +851,7 @@ ST_FUNC int macho_add_dllref(TCCState* S, int lev, const char* soname)
return -1; return -1;
} }
} }
tcc_add_dllref(S, soname)->level = lev; tcc_add_dllref(s1, soname)->level = lev;
return 0; return 0;
} }
@ -912,12 +913,12 @@ the_end:
} }
#endif /* TCC_IS_NATIVE */ #endif /* TCC_IS_NATIVE */
ST_FUNC int macho_load_tbd(TCCState* S, int fd, const char* filename, int lev) ST_FUNC int macho_load_tbd(TCCState* s1, 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(S, fd); pos = data = tcc_load_text(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;
@ -925,7 +926,7 @@ ST_FUNC int macho_load_tbd(TCCState* S, 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(S, lev, soname) != 0) goto the_end; if (macho_add_dllref(s1, lev, soname) != 0) goto the_end;
while(pos) { while(pos) {
char* sym = NULL; char* sym = NULL;
int cont = 1; int cont = 1;
@ -941,17 +942,17 @@ ST_FUNC int macho_load_tbd(TCCState* S, 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(S->dynsymtab_section, 0, 0, set_elf_sym(s1->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(S, data); tcc_free(data);
return ret; return ret;
} }
ST_FUNC int macho_load_dll(TCCState * S, int fd, const char* filename, int lev) ST_FUNC int macho_load_dll(TCCState * s1, 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;
@ -973,7 +974,7 @@ ST_FUNC int macho_load_dll(TCCState * S, 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(S, fd, sizeof(fh), struct fat_arch *fa = load_data(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++)
@ -981,15 +982,15 @@ ST_FUNC int macho_load_dll(TCCState * S, 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(S, fa); tcc_free(fa);
return -1; return -1;
} }
machofs = SWAP(fa[i].offset); machofs = SWAP(fa[i].offset);
tcc_free(S, fa); tcc_free(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, "%s: Mach-O fat 64bit files of type 0x%x not handled", tcc_warning("%s: Mach-O fat 64bit files of type 0x%x not handled",
filename, fh.magic); filename, fh.magic);
return -1; return -1;
} }
@ -998,7 +999,7 @@ ST_FUNC int macho_load_dll(TCCState * S, 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(S, fd, machofs + sizeof(struct mach_header_64), mh.sizeofcmds); buf2 = load_data(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) {
@ -1006,9 +1007,9 @@ ST_FUNC int macho_load_dll(TCCState * S, 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(S, fd, machofs + sc->symoff, nsyms * sizeof(*symtab)); symtab = load_data(fd, machofs + sc->symoff, nsyms * sizeof(*symtab));
strsize = sc->strsize; strsize = sc->strsize;
strtab = load_data(S, fd, machofs + sc->stroff, strsize); strtab = load_data(fd, machofs + sc->stroff, strsize);
break; break;
} }
case LC_ID_DYLIB: case LC_ID_DYLIB:
@ -1027,11 +1028,11 @@ ST_FUNC int macho_load_dll(TCCState * S, 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(S, "can't open %s (reexported from %s)", name, filename); tcc_warning("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(S, subfd, name, lev + 1); macho_load_dll(s1, subfd, name, lev + 1);
close(subfd); close(subfd);
} }
break; break;
@ -1047,11 +1048,11 @@ ST_FUNC int macho_load_dll(TCCState * S, 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(S, lev, soname)) if (0 != macho_add_dllref(s1, lev, soname))
goto the_end; goto the_end;
if (!nsyms || !nextdef) if (!nsyms || !nextdef)
tcc_warning(S, "%s doesn't export any symbols?", filename); tcc_warning("%s doesn't export any symbols?", filename);
//dprintf("symbols (all):\n"); //dprintf("symbols (all):\n");
dprintf("symbols (exported):\n"); dprintf("symbols (exported):\n");
@ -1062,14 +1063,14 @@ ST_FUNC int macho_load_dll(TCCState * S, 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(S->dynsymtab_section, 0, 0, set_elf_sym(s1->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(S, strtab); tcc_free(strtab);
tcc_free(S, symtab); tcc_free(symtab);
tcc_free(S, buf2); tcc_free(buf2);
return 0; return 0;
} }

355
tccpe.c
View File

@ -345,7 +345,7 @@ struct pe_import_info {
}; };
struct pe_info { struct pe_info {
TCCState *S; TCCState *s1;
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 *S, ElfW(Sym) *sym) static const char *pe_export_name(TCCState *s1, 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 (S->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL)) if (s1->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 * S, ElfW(Sym) *sym) static int pe_find_import(TCCState * s1, 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 * S, ElfW(Sym) *sym)
int a, err = 0; int a, err = 0;
do { do {
s = pe_export_name(S, sym); s = pe_export_name(s1, sym);
a = 0; a = 0;
if (n) { if (n) {
/* second try: */ /* second try: */
@ -414,7 +414,7 @@ static int pe_find_import(TCCState * S, ElfW(Sym) *sym)
} }
s = buffer; s = buffer;
} }
sym_index = find_elf_sym(S->dynsymtab_section, s); sym_index = find_elf_sym(s1->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->S, s, a - i); section_ptr_add(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 *S = pe->S; TCCState *s1 = pe->s1;
pf.op = fopen(pe->filename, "wb"); pf.op = fopen(pe->filename, "wb");
if (NULL == pf.op) { if (NULL == pf.op) {
tcc_error_noabort(S, "could not write '%s': %s", pe->filename, strerror(errno)); tcc_error_noabort("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->S->verbose) if (2 == pe->s1->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->S->verbose) if (2 == pe->s1->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->S->pe_stack_size) if (pe->s1->pe_stack_size)
pe_header.opthdr.SizeOfStackReserve = pe->S->pe_stack_size; pe_header.opthdr.SizeOfStackReserve = pe->s1->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->S->pe_characteristics; pe_header.filehdr.Characteristics |= pe->s1->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->S->verbose) if (2 == pe->s1->verbose)
printf("-------------------------------\n"); printf("-------------------------------\n");
if (pe->S->verbose) if (pe->s1->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->S->dynsymtab_section->data + sym_index; isym = (ElfW(Sym) *)pe->s1->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(pe->S, sizeof *p); p = tcc_mallocz(sizeof *p);
p->dll_index = dll_index; p->dll_index = dll_index;
dynarray_add(pe->S, &pe->imp_info, &pe->imp_count, p); dynarray_add(&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(pe->S, sizeof *s); s = tcc_mallocz(sizeof *s);
dynarray_add(pe->S, &p->symbols, &p->sym_count, s); dynarray_add(&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(pe->S, &p->symbols, &p->sym_count); dynarray_reset(&p->symbols, &p->sym_count);
} }
dynarray_reset(pe->S, &pe->imp_info, &pe->imp_count); dynarray_reset(&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 *S = pe->S; TCCState *s1 = pe->s1;
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->S, pe->thunk, pe->imp_size + 2*pe->iat_size); section_ptr_add(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->S->loaded_dlls[dllindex-1])->name); name = tcc_basename((dllref = pe->s1->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->S, pe->thunk, name); v = put_elf_str(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->S->dynsymtab_section->data + sym_index; ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->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->S->dynsymtab_section->link->data + imp_sym->st_name; const char *name = (char*)pe->s1->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->S, pe->thunk, sizeof(WORD)); /* hint, not used */ section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
put_elf_str(pe->S, pe->thunk, name); put_elf_str(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 *S = pe->S; TCCState *s1 = pe->s1;
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->S, sym); name = pe_export_name(pe->s1, sym);
if (sym->st_other & ST_PE_EXPORT) { if (sym->st_other & ST_PE_EXPORT) {
p = tcc_malloc(pe->S, sizeof *p); p = tcc_malloc(sizeof *p);
p->index = sym_index; p->index = sym_index;
p->name = name; p->name = name;
dynarray_add(pe->S, &sorted, &sym_count, p); dynarray_add(&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->S, pe->thunk, str_o - base_o); hdr = section_ptr_add(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->S, pe->thunk, dllname); put_elf_str(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(pe->S, "could not create '%s': %s", buf, strerror(errno)); tcc_error_noabort("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->S->verbose) if (pe->s1->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->S, pe->thunk, name); put_elf_str(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(pe->S, &sorted, &sym_count); dynarray_reset(&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->S, pe->reloc, sizeof(struct pe_reloc_header)); section_ptr_add(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->S, pe->reloc, sizeof (WORD)); WORD *wp = section_ptr_add(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->S, pe->reloc, sizeof(WORD)), ++count; section_ptr_add(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 *S = pe->S; TCCState *s1 = pe->s1;
if (PE_DLL == pe->type) if (PE_DLL == pe->type)
pe->reloc = new_section(pe->S, ".reloc", SHT_PROGBITS, 0); pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);
// pe->thunk = new_section(pe->S, ".iedat", SHT_PROGBITS, SHF_ALLOC); // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
section_order = tcc_malloc(pe->S, pe->S->nb_sections * sizeof (int)); section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));
for (o = k = 0 ; k < sec_last; ++k) { for (o = k = 0 ; k < sec_last; ++k) {
for (i = 1; i < S->nb_sections; ++i) { for (i = 1; i < s1->nb_sections; ++i) {
s = S->sections[i]; s = s1->sections[i];
if (k == pe_section_class(s)) if (k == pe_section_class(s))
section_order[o++] = i; section_order[o++] = i;
} }
@ -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 = S->sections[k]; s = s1->sections[k];
c = pe_section_class(s); c = pe_section_class(s);
if ((c == sec_stab || c == sec_stabstr) && 0 == S->do_debug) if ((c == sec_stab || c == sec_stabstr) && 0 == s1->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(pe->S, sizeof *si); si = tcc_mallocz(sizeof *si);
dynarray_add(pe->S, &pe->sec_info, &pe->sec_count, si); dynarray_add(&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(pe->S, section_order); tcc_free(section_order);
#if 0 #if 0
for (i = 1; i < S->nb_sections; ++i) { for (i = 1; i < s1->nb_sections; ++i) {
Section *s = S->sections[i]; Section *s = s1->sections[i];
int type = s->sh_type; int type = s->sh_type;
int flags = s->sh_flags; int flags = s->sh_flags;
printf("section %-16s %-10s %08x %04x %s,%s,%s\n", printf("section %-16s %-10s %08x %04x %s,%s,%s\n",
@ -1215,14 +1215,14 @@ add_section:
flags & SHF_EXECINSTR ? "exec" : "" flags & SHF_EXECINSTR ? "exec" : ""
); );
} }
S->verbose = 2; s1->verbose = 2;
#endif #endif
return 0; return 0;
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
static int pe_isafunc(TCCState *S, int sym_index) static int pe_isafunc(TCCState *s1, 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 *S = pe->S; TCCState *s1 = pe->s1;
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->S, sym); int imp_sym = pe_find_import(pe->s1, 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(S, sym_index)) if (pe_isafunc(s1, 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(pe->S, is->iat_index = put_elf_sym(
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(pe->S, text_section, 8+4); // room for code and address p = section_ptr_add(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(pe->S, text_section, 8); p = section_ptr_add(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(pe->S, "undefined symbol '%s'%s", name, tcc_error_noabort("undefined symbol '%s'%s", name,
imp_sym < 0 ? ", missing __declspec(dllimport)?":""); imp_sym < 0 ? ", missing __declspec(dllimport)?":"");
ret = -1; ret = -1;
} else if (pe->S->rdynamic } else if (pe->s1->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 *S, const char *fname) static void pe_print_sections(TCCState *s1, 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 < S->nb_sections; ++i) { for (i = 1; i < s1->nb_sections; ++i) {
s = S->sections[i]; s = s1->sections[i];
pe_print_section(f, s); pe_print_section(f, s);
} }
pe_print_section(f, S->dynsymtab_section); pe_print_section(f, s1->dynsymtab_section);
fclose(f); fclose(f);
} }
#endif #endif
@ -1492,7 +1492,7 @@ static void pe_print_sections(TCCState *S, 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(TCCState* S, SValue *sv, SValue *v2) ST_FUNC SValue *pe_getimport(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(TCCState* S, 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(S, RC_INT); r2 = get_reg(RC_INT);
load(S, r2, v2); load(r2, v2);
v2->r = r2; v2->r = r2;
if ((uint32_t)sv->c.i) { if ((uint32_t)sv->c.i) {
vpushv(S, v2); vpushv(v2);
vpushi(S, sv->c.i); vpushi(sv->c.i);
gen_opi(S, '+'); gen_opi('+');
*v2 = *S->tccgen_vtop--; *v2 = *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(TCCState* S, SValue *sv, SValue *v2)
} }
#endif #endif
ST_FUNC int pe_putimport(TCCState *S, int dllindex, const char *name, addr_t value) ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value)
{ {
return set_elf_sym( return set_elf_sym(
S->dynsymtab_section, s1->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 *S, int dllindex, const char *name, addr_t val
); );
} }
static int pe_add_dllref(TCCState *S, const char *dllname) static int pe_add_dllref(TCCState *s1, const char *dllname)
{ {
int i; int i;
for (i = 0; i < S->nb_loaded_dlls; ++i) for (i = 0; i < s1->nb_loaded_dlls; ++i)
if (0 == strcmp(S->loaded_dlls[i]->name, dllname)) if (0 == strcmp(s1->loaded_dlls[i]->name, dllname))
return i + 1; return i + 1;
tcc_add_dllref(S, dllname); tcc_add_dllref(s1, dllname);
return S->nb_loaded_dlls; return s1->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(TCCState* S, int fd, char **pp) static int get_dllexports(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(S, p, n0 = n0 ? n0 * 2 : 256); p = tcc_realloc(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(S, p), p = NULL; tcc_free(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 *S, int fd) static int pe_load_res(TCCState *s1, 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 *S, int fd)
|| strcmp((char*)hdr.sectionhdr.Name, ".rsrc") != 0) || strcmp((char*)hdr.sectionhdr.Name, ".rsrc") != 0)
goto quit; goto quit;
rsrc_section = new_section(S, ".rsrc", SHT_PROGBITS, SHF_ALLOC); rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
ptr = section_ptr_add(S, rsrc_section, hdr.sectionhdr.SizeOfRawData); ptr = section_ptr_add(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(S, symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc"); sym_index = put_elf_sym(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 *S, int fd) static int pe_load_def(TCCState *s1, 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(S, fd); buf = tcc_load_text(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 *S, int fd)
++state; ++state;
break; break;
case 2: case 2:
dllindex = pe_add_dllref(S, dllname); dllindex = pe_add_dllref(s1, dllname);
++state; ++state;
/* fall through */ /* fall through */
default: default:
@ -1743,7 +1743,7 @@ static int pe_load_def(TCCState *S, 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(S, dllindex, p, ord); pe_putimport(s1, dllindex, p, ord);
break; break;
} }
skip: skip:
@ -1754,63 +1754,63 @@ skip:
} }
ret = 0; ret = 0;
quit: quit:
tcc_free(S, buf); tcc_free(buf);
return ret; return ret;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static int pe_load_dll(TCCState *S, int fd, const char *filename) static int pe_load_dll(TCCState *s1, int fd, const char *filename)
{ {
char *p, *q; char *p, *q;
int index, ret; int index, ret;
ret = get_dllexports(S, fd, &p); ret = get_dllexports(fd, &p);
if (ret) { if (ret) {
return -1; return -1;
} else if (p) { } else if (p) {
index = pe_add_dllref(S, filename); index = pe_add_dllref(s1, filename);
for (q = p; *q; q += 1 + strlen(q)) for (q = p; *q; q += 1 + strlen(q))
pe_putimport(S, index, q, 0); pe_putimport(s1, index, q, 0);
tcc_free(S, p); tcc_free(p);
} }
return 0; return 0;
} }
ST_FUNC int pe_load_file(TCCState *S, int fd, const char *filename) ST_FUNC int pe_load_file(struct TCCState *s1, 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(S, fd); ret = pe_load_def(s1, fd);
else if (pe_load_res(S, fd) == 0) else if (pe_load_res(s1, 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(S, fd, filename); ret = pe_load_dll(s1, fd, filename);
return ret; return ret;
} }
PUB_FUNC int tcc_get_dllexports(TCCState *S, const char *filename, char **pp) PUB_FUNC int tcc_get_dllexports(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(S, fd, pp); ret = get_dllexports(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 *S) static unsigned pe_add_uwwind_info(TCCState *s1)
{ {
if (NULL == S->uw_pdata) { if (NULL == s1->uw_pdata) {
S->uw_pdata = find_section(S, ".pdata"); s1->uw_pdata = find_section(s1, ".pdata");
S->uw_pdata->sh_addralign = 4; s1->uw_pdata->sh_addralign = 4;
} }
if (0 == S->uw_sym) if (0 == s1->uw_sym)
S->uw_sym = put_elf_sym(S, symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base"); s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base");
if (0 == S->uw_offs) { if (0 == s1->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,17 +1826,18 @@ static unsigned pe_add_uwwind_info(TCCState *S)
Section *s = text_section; Section *s = text_section;
unsigned char *p; unsigned char *p;
section_ptr_add(S, s, -s->data_offset & 3); /* align */ section_ptr_add(s, -s->data_offset & 3); /* align */
S->uw_offs = s->data_offset; s1->uw_offs = s->data_offset;
p = section_ptr_add(S, s, sizeof uw_info); p = section_ptr_add(s, sizeof uw_info);
memcpy(p, uw_info, sizeof uw_info); memcpy(p, uw_info, sizeof uw_info);
} }
return S->uw_offs; return s1->uw_offs;
} }
ST_FUNC void pe_add_unwind_data(TCCState *S, unsigned start, unsigned end, unsigned stack) ST_FUNC void pe_add_unwind_data(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 */ {
@ -1845,10 +1846,10 @@ ST_FUNC void pe_add_unwind_data(TCCState *S, unsigned start, unsigned end, unsig
DWORD UnwindData; DWORD UnwindData;
} *p; } *p;
d = pe_add_uwwind_info(S); d = pe_add_uwwind_info(s1);
pd = S->uw_pdata; pd = s1->uw_pdata;
o = pd->data_offset; o = pd->data_offset;
p = section_ptr_add(S, pd, sizeof *p); p = section_ptr_add(pd, sizeof *p);
/* record this function */ /* record this function */
p->BeginAddress = start; p->BeginAddress = start;
@ -1857,7 +1858,7 @@ ST_FUNC void pe_add_unwind_data(TCCState *S, unsigned start, unsigned end, unsig
/* 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, S->uw_sym); put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
} }
#endif #endif
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
@ -1867,18 +1868,18 @@ ST_FUNC void pe_add_unwind_data(TCCState *S, unsigned start, unsigned end, unsig
#define PE_STDSYM(n,s) "_" n s #define PE_STDSYM(n,s) "_" n s
#endif #endif
static void tcc_add_support(TCCState *S, const char *filename) static void tcc_add_support(TCCState *s1, const char *filename)
{ {
if (tcc_add_dll(S, filename, 0) < 0) if (tcc_add_dll(s1, filename, 0) < 0)
tcc_error_noabort(S, "%s not found", filename); tcc_error_noabort("%s not found", filename);
} }
static void pe_add_runtime(TCCState *S, struct pe_info *pe) static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
{ {
const char *start_symbol; const char *start_symbol;
int pe_type; int pe_type;
if (TCC_OUTPUT_DLL == S->output_type) { if (TCC_OUTPUT_DLL == s1->output_type) {
pe_type = PE_DLL; pe_type = PE_DLL;
start_symbol = PE_STDSYM("__dllstart","@12"); start_symbol = PE_STDSYM("__dllstart","@12");
} else { } else {
@ -1901,61 +1902,61 @@ static void pe_add_runtime(TCCState *S, struct pe_info *pe)
pe_type = PE_EXE; pe_type = PE_EXE;
} }
if (TCC_OUTPUT_MEMORY == S->output_type) if (TCC_OUTPUT_MEMORY == s1->output_type)
start_symbol = run_symbol; start_symbol = run_symbol;
} }
pe->start_symbol = start_symbol + 1; pe->start_symbol = start_symbol + 1;
if (!S->leading_underscore || strchr(start_symbol, '@')) if (!s1->leading_underscore || strchr(start_symbol, '@'))
++start_symbol; ++start_symbol;
#ifdef CONFIG_TCC_BACKTRACE #ifdef CONFIG_TCC_BACKTRACE
if (S->do_backtrace) { if (s1->do_backtrace) {
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
if (S->do_bounds_check && S->output_type != TCC_OUTPUT_DLL) if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL)
tcc_add_support(S, "bcheck.o"); tcc_add_support(s1, "bcheck.o");
#endif #endif
if (S->output_type == TCC_OUTPUT_EXE) if (s1->output_type == TCC_OUTPUT_EXE)
tcc_add_support(S, "bt-exe.o"); tcc_add_support(s1, "bt-exe.o");
if (S->output_type == TCC_OUTPUT_DLL) if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_support(S, "bt-dll.o"); tcc_add_support(s1, "bt-dll.o");
if (S->output_type != TCC_OUTPUT_DLL) if (s1->output_type != TCC_OUTPUT_DLL)
tcc_add_support(S, "bt-log.o"); tcc_add_support(s1, "bt-log.o");
if (S->output_type != TCC_OUTPUT_MEMORY) if (s1->output_type != TCC_OUTPUT_MEMORY)
tcc_add_btstub(S); tcc_add_btstub(s1);
} }
#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 != S->output_type || S->runtime_main) if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main)
#endif #endif
set_global_sym(S, start_symbol, NULL, 0); set_global_sym(s1, start_symbol, NULL, 0);
if (0 == S->nostdlib) { if (0 == s1->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(S, TCC_LIBTCC1); tcc_add_support(s1, TCC_LIBTCC1);
for (pp = libs; 0 != (p = *pp); ++pp) { for (pp = libs; 0 != (p = *pp); ++pp) {
if (*p) if (*p)
tcc_add_library_err(S, p); tcc_add_library_err(s1, 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 == S->output_type) if (TCC_OUTPUT_DLL == s1->output_type)
S->output_type = TCC_OUTPUT_EXE; s1->output_type = TCC_OUTPUT_EXE;
if (TCC_OUTPUT_MEMORY == S->output_type) if (TCC_OUTPUT_MEMORY == s1->output_type)
pe_type = PE_RUN; pe_type = PE_RUN;
pe->type = pe_type; pe->type = pe_type;
} }
static void pe_set_options(TCCState * S, struct pe_info *pe) static void pe_set_options(TCCState * s1, 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 */
@ -1978,8 +1979,8 @@ static void pe_set_options(TCCState * S, 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 (S->pe_subsystem != 0) if (s1->pe_subsystem != 0)
pe->subsystem = S->pe_subsystem; pe->subsystem = s1->pe_subsystem;
/* set default file/section alignment */ /* set default file/section alignment */
if (pe->subsystem == 1) { if (pe->subsystem == 1) {
@ -1990,58 +1991,58 @@ static void pe_set_options(TCCState * S, struct pe_info *pe)
pe->file_align = 0x200; pe->file_align = 0x200;
} }
if (S->section_align != 0) if (s1->section_align != 0)
pe->section_align = S->section_align; pe->section_align = s1->section_align;
if (S->pe_file_align != 0) if (s1->pe_file_align != 0)
pe->file_align = S->pe_file_align; pe->file_align = s1->pe_file_align;
if ((pe->subsystem >= 10) && (pe->subsystem <= 12)) if ((pe->subsystem >= 10) && (pe->subsystem <= 12))
pe->imagebase = 0; pe->imagebase = 0;
if (S->has_text_addr) if (s1->has_text_addr)
pe->imagebase = S->text_addr; pe->imagebase = s1->text_addr;
} }
ST_FUNC int pe_output_file(TCCState *S, const char *filename) ST_FUNC int pe_output_file(TCCState *s1, 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.S = S; pe.s1 = s1;
S->filetype = 0; s1->filetype = 0;
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
tcc_add_bcheck(S); tcc_add_bcheck(s1);
#endif #endif
tcc_add_pragma_libs(S); tcc_add_pragma_libs(s1);
pe_add_runtime(S, &pe); pe_add_runtime(s1, &pe);
resolve_common_syms(S); resolve_common_syms(s1);
pe_set_options(S, &pe); pe_set_options(s1, &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(S, S->symtab, 0); relocate_syms(s1, s1->symtab, 0);
S->pe_imagebase = pe.imagebase; s1->pe_imagebase = pe.imagebase;
relocate_sections(S); relocate_sections(s1);
pe.start_addr = (DWORD) pe.start_addr = (DWORD)
(get_sym_addr(S, pe.start_symbol, 1, 1) - pe.imagebase); (get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase);
if (S->nb_errors) if (s1->nb_errors)
ret = -1; ret = -1;
else else
ret = pe_write(&pe); ret = pe_write(&pe);
dynarray_reset(S, &pe.sec_info, &pe.sec_count); dynarray_reset(&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);
S->runtime_main = pe.start_symbol; s1->runtime_main = pe.start_symbol;
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
S->uw_pdata = find_section(S, ".pdata"); s1->uw_pdata = find_section(s1, ".pdata");
#endif #endif
#endif #endif
} }
@ -2049,8 +2050,8 @@ ST_FUNC int pe_output_file(TCCState *S, const char *filename)
pe_free_imports(&pe); pe_free_imports(&pe);
#if PE_PRINT_SECTIONS #if PE_PRINT_SECTIONS
if (S->g_debug & 8) if (s1->g_debug & 8)
pe_print_sections(S, "tcc.log"); pe_print_sections(s1, "tcc.log");
#endif #endif
return ret; return ret;
} }

2167
tccpp.c

File diff suppressed because it is too large Load Diff

View File

@ -1,261 +0,0 @@
/* 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
View File

@ -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 *S, int mode, void *ptr, unsigned long length); static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length);
static int tcc_relocate_ex(TCCState *S, void *ptr, addr_t ptr_diff); static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff);
#ifdef _WIN64 #ifdef _WIN64
static void *win64_add_function_table(TCCState *S); static void *win64_add_function_table(TCCState *s1);
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 *S, void *ptr) LIBTCCAPI int tcc_relocate(TCCState *s1, 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(S, ptr, 0); return tcc_relocate_ex(s1, ptr, 0);
size = tcc_relocate_ex(S, NULL, 0); size = tcc_relocate_ex(s1, NULL, 0);
if (size < 0) if (size < 0)
return -1; return -1;
@ -93,52 +93,52 @@ LIBTCCAPI int tcc_relocate(TCCState *S, 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(S, "tccrun: could not map memory"); tcc_error("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(S, size); ptr = tcc_malloc(size);
#endif #endif
tcc_relocate_ex(S, ptr, ptr_diff); /* no more errors expected */ tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */
dynarray_add(S, &S->runtime_mem, &S->nb_runtime_mem, (void*)(addr_t)size); dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);
dynarray_add(S, &S->runtime_mem, &S->nb_runtime_mem, ptr); dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr);
return 0; return 0;
} }
ST_FUNC void tcc_run_free(TCCState *S) ST_FUNC void tcc_run_free(TCCState *s1)
{ {
int i; int i;
for (i = 0; i < S->nb_runtime_mem; i += 2) { for (i = 0; i < s1->nb_runtime_mem; i += 2) {
unsigned size = (unsigned)(addr_t)S->runtime_mem[i]; unsigned size = (unsigned)(addr_t)s1->runtime_mem[i];
void *ptr = S->runtime_mem[i+1]; void *ptr = s1->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(S, 2, ptr, size); set_pages_executable(s1, 2, ptr, size);
#ifdef _WIN64 #ifdef _WIN64
win64_del_function_table(*(void**)ptr); win64_del_function_table(*(void**)ptr);
#endif #endif
tcc_free(S, ptr); tcc_free(ptr);
#endif #endif
} }
tcc_free(S, S->runtime_mem); tcc_free(s1->runtime_mem);
} }
static void run_cdtors(TCCState *S, const char *start, const char *end, static void run_cdtors(TCCState *s1, const char *start, const char *end,
int argc, char **argv, char **envp) int argc, char **argv, char **envp)
{ {
void **a = (void **)get_sym_addr(S, start, 0, 0); void **a = (void **)get_sym_addr(s1, start, 0, 0);
void **b = (void **)get_sym_addr(S, end, 0, 0); void **b = (void **)get_sym_addr(s1, 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 *S, int argc, char **argv) LIBTCCAPI int tcc_run(TCCState *s1, 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 *S, int argc, char **argv)
char **envp = environ; char **envp = environ;
#endif #endif
S->runtime_main = S->nostdlib ? "_start" : "main"; s1->runtime_main = s1->nostdlib ? "_start" : "main";
if ((S->dflag & TCC_OPTION_d_t) && (addr_t)-1 == get_sym_addr(S, S->runtime_main, 0, 1)) if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, s1->runtime_main, 0, 1))
return 0; return 0;
#ifdef CONFIG_TCC_BACKTRACE #ifdef CONFIG_TCC_BACKTRACE
if (S->do_debug) if (s1->do_debug)
tcc_add_symbol(S, "exit", rt_exit); tcc_add_symbol(s1, "exit", rt_exit);
#endif #endif
if (tcc_relocate(S, TCC_RELOCATE_AUTO) < 0) if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
return -1; return -1;
prog_main = (void*)get_sym_addr(S, S->runtime_main, 1, 1); prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1);
#ifdef CONFIG_TCC_BACKTRACE #ifdef CONFIG_TCC_BACKTRACE
memset(rc, 0, sizeof *rc); memset(rc, 0, sizeof *rc);
if (S->do_debug) { if (s1->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 *S, 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(S, "main"); rc->top_func = tcc_get_symbol(s1, "main");
rc->num_callers = S->rt_num_callers; rc->num_callers = s1->rt_num_callers;
rc->do_jmp = 1; rc->do_jmp = 1;
if ((p = tcc_get_symbol(S, "__rt_error"))) if ((p = tcc_get_symbol(s1, "__rt_error")))
*(void**)p = _rt_error; *(void**)p = _rt_error;
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
if (S->do_bounds_check) { if (s1->do_bounds_check) {
rc->bounds_start = (void*)bounds_section->sh_addr; rc->bounds_start = (void*)bounds_section->sh_addr;
if ((p = tcc_get_symbol(S, "__bound_init"))) if ((p = tcc_get_symbol(s1, "__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 *S, 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(S, "__init_array_start", "__init_array_end", argc, argv, envp); run_cdtors(s1, "__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(S, "__fini_array_start", "__fini_array_end", 0, NULL, NULL); run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
if ((S->dflag & TCC_OPTION_d_t) && ret) if ((s1->dflag & 16) && ret)
fprintf(S->ppfp, "[returns %d]\n", ret), fflush(S->ppfp); fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp);
return ret; return ret;
} }
@ -229,7 +229,7 @@ LIBTCCAPI int tcc_run(TCCState *S, 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 *S, void *ptr, addr_t ptr_diff) static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
{ {
Section *s; Section *s;
unsigned offset, length, align, max_align, i, k, f; unsigned offset, length, align, max_align, i, k, f;
@ -237,15 +237,15 @@ static int tcc_relocate_ex(TCCState *S, void *ptr, addr_t ptr_diff)
addr_t mem, addr; addr_t mem, addr;
if (NULL == ptr) { if (NULL == ptr) {
S->nb_errors = 0; s1->nb_errors = 0;
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
pe_output_file(S, NULL); pe_output_file(s1, NULL);
#else #else
tcc_add_runtime(S); tcc_add_runtime(s1);
resolve_common_syms(S); resolve_common_syms(s1);
build_got_entries(S); build_got_entries(s1);
#endif #endif
if (S->nb_errors) if (s1->nb_errors)
return -1; return -1;
} }
@ -257,11 +257,11 @@ static int tcc_relocate_ex(TCCState *S, 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 < S->nb_sections; i++) { for(i = 1; i < s1->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 = S->sections[i]; s = s1->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 == S->uw_pdata) if (s == s1->uw_pdata)
*(void**)mem = win64_add_function_table(S); *(void**)mem = win64_add_function_table(s1);
#endif #endif
if (s->data) { if (s->data) {
tcc_free(S, s->data); tcc_free(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(S, f, (void*)addr, n); set_pages_executable(s1, f, (void*)addr, n);
} }
} }
@ -324,21 +324,21 @@ redo:
return 0; return 0;
/* relocate symbols */ /* relocate symbols */
relocate_syms(S, S->symtab, !(S->nostdlib)); relocate_syms(s1, s1->symtab, !(s1->nostdlib));
if (S->nb_errors) if (s1->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
S->pe_imagebase = mem; s1->pe_imagebase = mem;
#endif #endif
/* relocate sections */ /* relocate sections */
#ifndef TCC_TARGET_PE #ifndef TCC_TARGET_PE
relocate_plt(S); relocate_plt(s1);
#endif #endif
relocate_sections(S); relocate_sections(s1);
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 *S, int mode, void *ptr, unsigned long length) static void set_pages_executable(TCCState *s1, 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 *S, int mode, void *ptr, unsigned long
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(S, "mprotect failed: did you mean to configure --with-selinux?"); tcc_error("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 *S, int mode, void *ptr, unsigned long
} }
#ifdef _WIN64 #ifdef _WIN64
static void *win64_add_function_table(TCCState *S) static void *win64_add_function_table(TCCState *s1)
{ {
void *p = NULL; void *p = NULL;
if (S->uw_pdata) { if (s1->uw_pdata) {
p = (void*)S->uw_pdata->sh_addr; p = (void*)s1->uw_pdata->sh_addr;
RtlAddFunctionTable( RtlAddFunctionTable(
(RUNTIME_FUNCTION*)p, (RUNTIME_FUNCTION*)p,
S->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION), s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
S->pe_imagebase s1->pe_imagebase
); );
S->uw_pdata = NULL; s1->uw_pdata = NULL;
} }
return p; return p;
} }

View File

@ -66,7 +66,7 @@ static int ar_usage(int ret) {
return ret; return ret;
} }
ST_FUNC int tcc_tool_ar(TCCState *S, int argc, char **argv) ST_FUNC int tcc_tool_ar(TCCState *s1, 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 *S, int argc, char **argv)
} }
funcmax = 250; funcmax = 250;
afpos = tcc_realloc(S, NULL, funcmax * sizeof *afpos); // 250 func afpos = tcc_realloc(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 *S, 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(S, fsize + 1); buf = tcc_malloc(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 *S, 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(S, anames, strpos+istrlen); anames = tcc_realloc(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(S, afpos, funcmax * sizeof *afpos); // 250 func more afpos = tcc_realloc(afpos, funcmax * sizeof *afpos); // 250 func more
} }
afpos[funccnt] = fpos; afpos[funccnt] = fpos;
} }
@ -229,7 +229,7 @@ ST_FUNC int tcc_tool_ar(TCCState *S, 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(S, buf); tcc_free(buf);
i_obj++; i_obj++;
fpos += (fsize + sizeof(arhdro)); fpos += (fsize + sizeof(arhdro));
} }
@ -253,16 +253,16 @@ ST_FUNC int tcc_tool_ar(TCCState *S, 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(S, fsize + 1); buf = tcc_malloc(fsize + 1);
fread(buf, fsize, 1, fo); fread(buf, fsize, 1, fo);
fwrite(buf, fsize, 1, fh); fwrite(buf, fsize, 1, fh);
tcc_free(S, buf); tcc_free(buf);
ret = 0; ret = 0;
the_end: the_end:
if (anames) if (anames)
tcc_free(S, anames); tcc_free(anames);
if (afpos) if (afpos)
tcc_free(S, afpos); tcc_free(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 *S, int argc, char **argv) ST_FUNC int tcc_tool_impdef(TCCState *s1, 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(S, file, &p); ret = tcc_get_dllexports(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(S, p); tcc_free(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 *S, char **argv, int option) ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int option)
{ {
tcc_error(S, "-m%d not implemented.", option); tcc_error("-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(S, sl + 1)) { for (d0 = NULL;; d0 = tcc_malloc(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 *S, char **argv, int target) ST_FUNC void tcc_tool_cross(TCCState *s1, 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 *S, char **argv, int target)
if (strcmp(a0, program)) if (strcmp(a0, program))
execvp(argv[0] = program, argv); execvp(argv[0] = program, argv);
tcc_error(S, "could not run '%s'", program); tcc_error("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(TCCState *S, const char *s) { static char *escape_target_dep(const char *s) {
char *res = tcc_malloc(S, strlen(s) * 2 + 1); char *res = tcc_malloc(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(TCCState *S, const char *s) {
return res; return res;
} }
ST_FUNC void gen_makedeps(TCCState *S, const char *target, const char *filename) ST_FUNC void gen_makedeps(TCCState *s1, 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 *S, const char *target, const char *filename)
filename = buf; filename = buf;
} }
if (S->verbose) if (s1->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 *S, 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(S, "could not open '%s'", filename); tcc_error("could not open '%s'", filename);
fprintf(depout, "%s:", target); fprintf(depout, "%s:", target);
for (i = 0; i<S->nb_target_deps; ++i) { for (i = 0; i<s1->nb_target_deps; ++i) {
for (k = 0; k < i; ++k) for (k = 0; k < i; ++k)
if (0 == strcmp(S->target_deps[i], S->target_deps[k])) if (0 == strcmp(s1->target_deps[i], s1->target_deps[k]))
goto next; goto next;
escaped_target = escape_target_dep(S, S->target_deps[i]); escaped_target = escape_target_dep(s1->target_deps[i]);
fprintf(depout, " \\\n %s", escaped_target); fprintf(depout, " \\\n %s", escaped_target);
tcc_free(S, escaped_target); tcc_free(escaped_target);
next:; next:;
} }
fprintf(depout, "\n"); fprintf(depout, "\n");

File diff suppressed because it is too large Load Diff

View File

@ -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 *S, unsigned got_offset, struct sym_attr *attr) ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{ {
Section *plt = S->plt; Section *plt = s1->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 *S, unsigned got_offset, struct sym_a
(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(S, plt, 16); p = section_ptr_add(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 *S, unsigned got_offset, struct sym_a
/* 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 = S->plt->reloc ? S->plt->reloc->data_offset : 0; relofs = s1->plt->reloc ? s1->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(S, plt, 16); p = section_ptr_add(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 *S, unsigned got_offset, struct sym_a
/* 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 *S) ST_FUNC void relocate_plt(TCCState *s1)
{ {
uint8_t *p, *p_end; uint8_t *p, *p_end;
if (!S->plt) if (!s1->plt)
return; return;
p = S->plt->data; p = s1->plt->data;
p_end = p + S->plt->data_offset; p_end = p + s1->plt->data_offset;
if (p < p_end) { if (p < p_end) {
int x = S->got->sh_addr - S->plt->sh_addr - 6; int x = s1->got->sh_addr - s1->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 + (S->plt->data - p)); add32le(p + 2, x + (s1->plt->data - p));
p += 16; p += 16;
} }
} }
if (S->plt->reloc) { if (s1->plt->reloc) {
ElfW_Rel *rel; ElfW_Rel *rel;
int x = S->plt->sh_addr + 16 + 6; int x = s1->plt->sh_addr + 16 + 6;
p = S->got->data; p = s1->got->data;
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) { for_each_elem(s1->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 *S)
#endif #endif
#endif #endif
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val) void relocate(TCCState *s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
switch (type) { switch (type) {
case R_X86_64_64: case R_X86_64_64:
if (S->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index; esym_index = get_sym_attr(s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
break; break;
case R_X86_64_32: case R_X86_64_32:
case R_X86_64_32S: case R_X86_64_32S:
if (S->output_type == TCC_OUTPUT_DLL) { if (s1->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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
break; break;
case R_X86_64_PC32: case R_X86_64_PC32:
if (S->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
/* DLL relocation */ /* DLL relocation */
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index; esym_index = get_sym_attr(s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
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(S, "internal error: relocation failed"); tcc_error("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 - S->got->sh_addr + rel->r_addend); add64le(ptr, val - s1->got->sh_addr + rel->r_addend);
break; break;
case R_X86_64_PC64: case R_X86_64_PC64:
if (S->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
/* DLL relocation */ /* DLL relocation */
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index; esym_index = get_sym_attr(s1, 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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
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, S->got->sh_addr - addr + add32le(ptr, s1->got->sh_addr - addr +
get_sym_attr(S, sym_index, 0)->got_offset - 4); get_sym_attr(s1, sym_index, 0)->got_offset - 4);
break; break;
case R_X86_64_GOTPC32: case R_X86_64_GOTPC32:
add32le(ptr, S->got->sh_addr - addr + rel->r_addend); add32le(ptr, s1->got->sh_addr - addr + rel->r_addend);
break; break;
case R_X86_64_GOTPC64: case R_X86_64_GOTPC64:
add64le(ptr, S->got->sh_addr - addr + rel->r_addend); add64le(ptr, s1->got->sh_addr - addr + rel->r_addend);
break; break;
case R_X86_64_GOTTPOFF: case R_X86_64_GOTTPOFF:
add32le(ptr, val - S->got->sh_addr); add32le(ptr, val - s1->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(S, sym_index, 0)->got_offset); add32le(ptr, get_sym_attr(s1, 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(S, sym_index, 0)->got_offset); add64le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
break; break;
case R_X86_64_GOTOFF64: case R_X86_64_GOTOFF64:
add64le(ptr, val - S->got->sh_addr); add64le(ptr, val - s1->got->sh_addr);
break; break;
case R_X86_64_TLSGD: case R_X86_64_TLSGD:
{ {
@ -320,12 +320,12 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
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 = S->sections[sym->st_shndx]; sec = s1->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(S, "unexpected R_X86_64_TLSGD pattern"); tcc_error("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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
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(S, "unexpected R_X86_64_TLSLD pattern"); tcc_error("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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
int32_t x; int32_t x;
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
sec = S->sections[sym->st_shndx]; sec = s1->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 *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
break; break;
case R_X86_64_RELATIVE: case R_X86_64_RELATIVE:
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
add32le(ptr, val - S->pe_imagebase); add32le(ptr, val - s1->pe_imagebase);
#endif #endif
/* do nothing */ /* do nothing */
break; break;