various fixes and new options for PE format

This commit is contained in:
Frederic Feret 2009-08-27 10:12:13 +02:00 committed by grischka
parent 526c464504
commit 2f73e42d87
5 changed files with 100 additions and 18 deletions

View File

@ -1944,6 +1944,10 @@ TCCState *tcc_new(void)
/* XXX: currently the PE linker is not ready to support that */
s->leading_underscore = 1;
#endif
if (s->section_align == 0)
s->section_align = ELF_PAGE_SIZE;
#ifdef TCC_TARGET_I386
s->seg_size = 32;
#endif

39
tcc.c
View File

@ -386,8 +386,47 @@ int parse_args(TCCState *s, int argc, char **argv)
if (strstart(optarg, "-Ttext,", &p)) {
s->text_addr = strtoul(p, NULL, 16);
s->has_text_addr = 1;
} else if (strstart(optarg, "--section-alignment,", &p)) {
s->section_align = strtoul(p, NULL, 16);
} else if (strstart(optarg, "--image-base,", &p)) {
s->text_addr = strtoul(p, NULL, 16);
s->has_text_addr = 1;
#ifdef TCC_TARGET_PE
} else if (strstart(optarg, "--file-alignment,", &p)) {
s->pe_file_align = strtoul(p, NULL, 16);
} else if (strstart(optarg, "--subsystem,", &p)) {
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
if (!strcmp(p, "native"))
s->pe_subsystem = 1;
else if (!strcmp(p, "console"))
s->pe_subsystem = 3;
else if (!strcmp(p, "gui"))
s->pe_subsystem = 2;
else if (!strcmp(p, "posix"))
s->pe_subsystem = 7;
else if (!strcmp(p, "efiapp"))
s->pe_subsystem = 10;
else if (!strcmp(p, "efiboot"))
s->pe_subsystem = 11;
else if (!strcmp(p, "efiruntime"))
s->pe_subsystem = 12;
else if (!strcmp(p, "efirom"))
s->pe_subsystem = 13;
#endif
else {
error("invalid subsystem '%s'", p);
}
#endif
} else if (strstart(optarg, "--oformat,", &p)) {
#if defined(TCC_TARGET_PE)
if (strstart(p, "pe-", NULL)) {
#else
#if defined(TCC_TARGET_X86_64)
if (strstart(p, "elf64-", NULL)) {
#else
if (strstart(p, "elf32-", NULL)) {
#endif
#endif
s->output_format = TCC_OUTPUT_FORMAT_ELF;
} else if (!strcmp(p, "binary")) {
s->output_format = TCC_OUTPUT_FORMAT_BINARY;

9
tcc.h
View File

@ -515,6 +515,15 @@ struct TCCState {
int seg_size;
#endif
/* section alignment */
unsigned long section_align;
#ifdef TCC_TARGET_PE
/* PE info */
int pe_subsystem;
unsigned long pe_file_align;
#endif
#ifndef TCC_TARGET_PE
#ifdef TCC_TARGET_X86_64
/* write PLT and GOT here */

View File

@ -1632,10 +1632,10 @@ int elf_output_file(TCCState *s1, const char *filename)
addr = s1->text_addr;
/* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
ELF_PAGE_SIZE */
a_offset = addr & (ELF_PAGE_SIZE - 1);
p_offset = file_offset & (ELF_PAGE_SIZE - 1);
a_offset = addr & (s1->section_align - 1);
p_offset = file_offset & (s1->section_align - 1);
if (a_offset < p_offset)
a_offset += ELF_PAGE_SIZE;
a_offset += s1->section_align;
file_offset += (a_offset - p_offset);
} else {
if (file_type == TCC_OUTPUT_DLL)
@ -1643,7 +1643,7 @@ int elf_output_file(TCCState *s1, const char *filename)
else
addr = ELF_START_ADDR;
/* compute address after headers */
addr += (file_offset & (ELF_PAGE_SIZE - 1));
addr += (file_offset & (s1->section_align - 1));
}
/* dynamic relocation table information, for .dynamic section */
@ -1661,7 +1661,7 @@ int elf_output_file(TCCState *s1, const char *filename)
ph->p_flags = PF_R | PF_X;
else
ph->p_flags = PF_R | PF_W;
ph->p_align = ELF_PAGE_SIZE;
ph->p_align = s1->section_align;
/* we do the following ordering: interp, symbol tables,
relocations, progbits, nobits */
@ -1731,12 +1731,12 @@ int elf_output_file(TCCState *s1, const char *filename)
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
/* if in the middle of a page, we duplicate the page in
memory so that one copy is RX and the other is RW */
if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
addr += ELF_PAGE_SIZE;
if ((addr & (s1->section_align - 1)) != 0)
addr += s1->section_align;
} else {
addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
~(ELF_PAGE_SIZE - 1);
addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
file_offset = (file_offset + s1->section_align - 1) &
~(s1->section_align - 1);
}
}
}

46
tccpe.c
View File

@ -349,6 +349,9 @@ struct pe_info {
DWORD iat_size;
DWORD exp_offs;
DWORD exp_size;
int subsystem;
DWORD section_align;
DWORD file_align;
struct section_info *sec_info;
int sec_count;
struct pe_import_info **imp_info;
@ -417,14 +420,14 @@ ST_FN DWORD umax(DWORD a, DWORD b)
return a < b ? b : a;
}
ST_FN DWORD pe_file_align(DWORD n)
ST_FN DWORD pe_file_align(struct pe_info *pe, DWORD n)
{
return (n + (0x200 - 1)) & ~(0x200 - 1);
return (n + (pe->file_align - 1)) & ~(pe->file_align - 1);
}
ST_FN DWORD pe_virtual_align(DWORD n)
ST_FN DWORD pe_virtual_align(struct pe_info *pe, DWORD n)
{
return (n + (0x1000 - 1)) & ~(0x1000 - 1);
return (n + (pe->section_align - 1)) & ~(pe->section_align - 1);
}
ST_FN void pe_align_section(Section *s, int a)
@ -578,7 +581,7 @@ ST_FN int pe_write(struct pe_info *pe)
return -1;
}
pe->sizeofheaders = pe_file_align(
pe->sizeofheaders = pe_file_align(pe,
sizeof (struct pe_header)
+ pe->sec_count * sizeof (IMAGE_SECTION_HEADER)
);
@ -648,11 +651,11 @@ ST_FN int pe_write(struct pe_info *pe)
psh->VirtualAddress = addr;
psh->Misc.VirtualSize = size;
pe_header.opthdr.SizeOfImage =
umax(pe_virtual_align(size + addr), pe_header.opthdr.SizeOfImage);
umax(pe_virtual_align(pe, size + addr), pe_header.opthdr.SizeOfImage);
if (si->data_size) {
psh->PointerToRawData = file_offset;
file_offset = pe_file_align(file_offset + si->data_size);
file_offset = pe_file_align(pe, file_offset + si->data_size);
psh->SizeOfRawData = file_offset - psh->PointerToRawData;
}
}
@ -1085,7 +1088,7 @@ ST_FN int pe_assign_addresses (struct pe_info *pe)
strcpy(si->name, s->name);
si->cls = c;
si->ord = k;
si->sh_addr = s->sh_addr = addr = pe_virtual_align(addr);
si->sh_addr = s->sh_addr = addr = pe_virtual_align(pe, addr);
si->sh_flags = s->sh_flags;
if (c == sec_data && NULL == pe->thunk)
@ -1649,6 +1652,33 @@ PUB_FN int pe_output_file(TCCState * s1, const char *filename)
} else {
pe.imagebase = 0x00400000;
}
/* if no subsystem specified, we use "console" subsystem by default */
if (s1->pe_subsystem != 0)
pe.subsystem = s1->pe_subsystem;
else
pe.subsystem = 3;
/* set default file/section alignment */
if (pe.subsystem == 1) {
pe.section_align = 0x20;
pe.file_align = 0x20;
} else {
pe.section_align = 0x1000;
pe.file_align = 0x200;
}
if (s1->section_align != 0)
pe.section_align = s1->section_align;
if (s1->pe_file_align != 0)
pe.file_align = s1->pe_file_align;
if ((pe.subsystem >= 10) && (pe.subsystem <= 12))
pe.imagebase = 0;
if (s1->has_text_addr)
pe.imagebase = s1->text_addr;
pe_assign_addresses(&pe);
relocate_syms(s1, 0);
for (i = 1; i < s1->nb_sections; ++i) {