win64: try to fix linkage

- revert to R_X86_64_PC32 for near calls on PE
- revert to s1->section_align set to zero by default

Untested. Compared to release_0_9_26 the pe-image looks back to
normal.  There are some differences in dissassembly (r10/r11 usage)
but maybe that's ok.
master
grischka 2014-05-08 17:32:29 +02:00
parent ad787abea6
commit 0f51ccd4e4
3 changed files with 23 additions and 18 deletions

View File

@ -1033,7 +1033,6 @@ LIBTCCAPI TCCState *tcc_new(void)
".dynhashtab", SHF_PRIVATE); ".dynhashtab", SHF_PRIVATE);
s->alacarte_link = 1; s->alacarte_link = 1;
s->nocommon = 1; s->nocommon = 1;
s->section_align = ELF_PAGE_SIZE;
#ifdef CHAR_IS_UNSIGNED #ifdef CHAR_IS_UNSIGNED
s->char_is_unsigned = 1; s->char_is_unsigned = 1;

View File

@ -1596,7 +1596,7 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
put32(s1->got->data + offset, sym->st_value & 0xffffffff); put32(s1->got->data + offset, sym->st_value & 0xffffffff);
} }
/* Perform relocation to GOT or PLT entries */ /* Perform relocation to GOT or PLT entries */
ST_FUNC void fill_got(TCCState *s1) ST_FUNC void fill_got(TCCState *s1)
{ {
Section *s; Section *s;
@ -1848,6 +1848,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
int *sec_order) int *sec_order)
{ {
int i, j, k, file_type, sh_order_index, file_offset; int i, j, k, file_type, sh_order_index, file_offset;
unsigned long s_align;
long long tmp; long long tmp;
addr_t addr; addr_t addr;
ElfW(Phdr) *ph; ElfW(Phdr) *ph;
@ -1855,10 +1856,12 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
file_type = s1->output_type; file_type = s1->output_type;
sh_order_index = 1; sh_order_index = 1;
file_offset = 0;
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr)); file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
else s_align = ELF_PAGE_SIZE;
file_offset = 0; if (s1->section_align)
s_align = s1->section_align;
if (phnum > 0) { if (phnum > 0) {
if (s1->has_text_addr) { if (s1->has_text_addr) {
@ -1866,10 +1869,10 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
addr = s1->text_addr; addr = s1->text_addr;
/* we ensure that (addr % ELF_PAGE_SIZE) == file_offset % /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
ELF_PAGE_SIZE */ ELF_PAGE_SIZE */
a_offset = (int) (addr & (s1->section_align - 1)); a_offset = (int) (addr & (s_align - 1));
p_offset = file_offset & (s1->section_align - 1); p_offset = file_offset & (s_align - 1);
if (a_offset < p_offset) if (a_offset < p_offset)
a_offset += s1->section_align; a_offset += s_align;
file_offset += (a_offset - p_offset); file_offset += (a_offset - p_offset);
} else { } else {
if (file_type == TCC_OUTPUT_DLL) if (file_type == TCC_OUTPUT_DLL)
@ -1877,7 +1880,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
else else
addr = ELF_START_ADDR; addr = ELF_START_ADDR;
/* compute address after headers */ /* compute address after headers */
addr += (file_offset & (s1->section_align - 1)); addr += (file_offset & (s_align - 1));
} }
ph = &phdr[0]; ph = &phdr[0];
@ -1899,7 +1902,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
ph->p_flags = PF_R | PF_X; ph->p_flags = PF_R | PF_X;
else else
ph->p_flags = PF_R | PF_W; ph->p_flags = PF_R | PF_W;
ph->p_align = s1->section_align; ph->p_align = s_align;
/* Decide the layout of sections loaded in memory. This must /* Decide the layout of sections loaded in memory. This must
be done before program headers are filled since they contain be done before program headers are filled since they contain
@ -1991,12 +1994,11 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
/* if in the middle of a page, we duplicate the page in /* if in the middle of a page, we duplicate the page in
memory so that one copy is RX and the other is RW */ memory so that one copy is RX and the other is RW */
if ((addr & (s1->section_align - 1)) != 0) if ((addr & (s_align - 1)) != 0)
addr += s1->section_align; addr += s_align;
} else { } else {
addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1); addr = (addr + s_align - 1) & ~(s_align - 1);
file_offset = (file_offset + s1->section_align - 1) & file_offset = (file_offset + s_align - 1) & ~(s_align - 1);
~(s1->section_align - 1);
} }
} }
} }
@ -2469,7 +2471,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
goto the_end; goto the_end;
} }
/* Perform relocation to GOT or PLT entries */ /* Perform relocation to GOT or PLT entries */
if (file_type == TCC_OUTPUT_EXE && s1->static_link) if (file_type == TCC_OUTPUT_EXE && s1->static_link)
fill_got(s1); fill_got(s1);

View File

@ -288,7 +288,8 @@ static void gen_gotpcrel(int r, Sym *sym, int c)
rel = (ElfW(Rela) *)(sr->data + sr->data_offset - sizeof(ElfW(Rela))); rel = (ElfW(Rela) *)(sr->data + sr->data_offset - sizeof(ElfW(Rela)));
rel->r_addend = -4; rel->r_addend = -4;
#else #else
printf("picpic: %s %x %x | %02x %02x %02x\n", get_tok_str(sym->v, NULL), c, r, tcc_error("internal error: no GOT on PE: %s %x %x | %02x %02x %02x\n",
get_tok_str(sym->v, NULL), c, r,
cur_text_section->data[ind-3], cur_text_section->data[ind-3],
cur_text_section->data[ind-2], cur_text_section->data[ind-2],
cur_text_section->data[ind-1] cur_text_section->data[ind-1]
@ -603,8 +604,11 @@ static void gcall_or_jmp(int is_jmp)
/* constant case */ /* constant case */
if (vtop->r & VT_SYM) { if (vtop->r & VT_SYM) {
/* relocation case */ /* relocation case */
greloc(cur_text_section, vtop->sym, #ifdef TCC_TARGET_PE
ind + 1, R_X86_64_PLT32); greloc(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32);
#else
greloc(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32);
#endif
} else { } else {
/* put an empty PC32 relocation */ /* put an empty PC32 relocation */
put_elf_reloc(symtab_section, cur_text_section, put_elf_reloc(symtab_section, cur_text_section,