Unified · Split
| @@ -1944,6 +1944,10 @@ TCCState *tcc_new(void) · 1943 unmodified lines | ||
| 1944 | 1944 | /* XXX: currently the PE linker is not ready to support that */ |
| 1945 | 1945 | s->leading_underscore = 1; |
| 1946 | 1946 | #endif |
| 1947 | + | |
| 1948 | + if (s->section_align == 0) | |
| 1949 | + s->section_align = ELF_PAGE_SIZE; | |
| 1950 | + | |
| 1947 | 1951 | #ifdef TCC_TARGET_I386 |
| 1948 | 1952 | s->seg_size = 32; |
| 1949 | 1953 | #endif |
| @@ -386,8 +386,47 @@ int parse_args(TCCState *s, int argc, char **argv) · 385 unmodified lines | ||
| 386 | 386 | if (strstart(optarg, "-Ttext,", &p)) { |
| 387 | 387 | s->text_addr = strtoul(p, NULL, 16); |
| 388 | 388 | s->has_text_addr = 1; |
| 389 | + } else if (strstart(optarg, "--section-alignment,", &p)) { | |
| 390 | + s->section_align = strtoul(p, NULL, 16); | |
| 391 | + } else if (strstart(optarg, "--image-base,", &p)) { | |
| 392 | + s->text_addr = strtoul(p, NULL, 16); | |
| 393 | + s->has_text_addr = 1; | |
| 394 | +#ifdef TCC_TARGET_PE | |
| 395 | + } else if (strstart(optarg, "--file-alignment,", &p)) { | |
| 396 | + s->pe_file_align = strtoul(p, NULL, 16); | |
| 397 | + } else if (strstart(optarg, "--subsystem,", &p)) { | |
| 398 | +#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) | |
| 399 | + if (!strcmp(p, "native")) | |
| 400 | + s->pe_subsystem = 1; | |
| 401 | + else if (!strcmp(p, "console")) | |
| 402 | + s->pe_subsystem = 3; | |
| 403 | + else if (!strcmp(p, "gui")) | |
| 404 | + s->pe_subsystem = 2; | |
| 405 | + else if (!strcmp(p, "posix")) | |
| 406 | + s->pe_subsystem = 7; | |
| 407 | + else if (!strcmp(p, "efiapp")) | |
| 408 | + s->pe_subsystem = 10; | |
| 409 | + else if (!strcmp(p, "efiboot")) | |
| 410 | + s->pe_subsystem = 11; | |
| 411 | + else if (!strcmp(p, "efiruntime")) | |
| 412 | + s->pe_subsystem = 12; | |
| 413 | + else if (!strcmp(p, "efirom")) | |
| 414 | + s->pe_subsystem = 13; | |
| 415 | +#endif | |
| 416 | + else { | |
| 417 | + error("invalid subsystem '%s'", p); | |
| 418 | + } | |
| 419 | +#endif | |
| 389 | 420 | } else if (strstart(optarg, "--oformat,", &p)) { |
| 421 | +#if defined(TCC_TARGET_PE) | |
| 422 | + if (strstart(p, "pe-", NULL)) { | |
| 423 | +#else | |
| 424 | +#if defined(TCC_TARGET_X86_64) | |
| 425 | + if (strstart(p, "elf64-", NULL)) { | |
| 426 | +#else | |
| 390 | 427 | if (strstart(p, "elf32-", NULL)) { |
| 428 | +#endif | |
| 429 | +#endif | |
| 391 | 430 | s->output_format = TCC_OUTPUT_FORMAT_ELF; |
| 392 | 431 | } else if (!strcmp(p, "binary")) { |
| 393 | 432 | s->output_format = TCC_OUTPUT_FORMAT_BINARY; |
| @@ -515,6 +515,15 @@ struct TCCState { · 514 unmodified lines | ||
| 515 | 515 | int seg_size; |
| 516 | 516 | #endif |
| 517 | 517 | |
| 518 | + /* section alignment */ | |
| 519 | + unsigned long section_align; | |
| 520 | + | |
| 521 | +#ifdef TCC_TARGET_PE | |
| 522 | + /* PE info */ | |
| 523 | + int pe_subsystem; | |
| 524 | + unsigned long pe_file_align; | |
| 525 | +#endif | |
| 526 | + | |
| 518 | 527 | #ifndef TCC_TARGET_PE |
| 519 | 528 | #ifdef TCC_TARGET_X86_64 |
| 520 | 529 | /* write PLT and GOT here */ |
| @@ -1632,10 +1632,10 @@ int elf_output_file(TCCState *s1, const char *filename) · 1631 unmodified lines | ||
| 1632 | 1632 | addr = s1->text_addr; |
| 1633 | 1633 | /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset % |
| 1634 | 1634 | ELF_PAGE_SIZE */ |
| 1635 | − a_offset = addr & (ELF_PAGE_SIZE - 1); | |
| 1636 | − p_offset = file_offset & (ELF_PAGE_SIZE - 1); | |
| 1635 | + a_offset = addr & (s1->section_align - 1); | |
| 1636 | + p_offset = file_offset & (s1->section_align - 1); | |
| 1637 | 1637 | if (a_offset < p_offset) |
| 1638 | − a_offset += ELF_PAGE_SIZE; | |
| 1638 | + a_offset += s1->section_align; | |
| 1639 | 1639 | file_offset += (a_offset - p_offset); |
| 1640 | 1640 | } else { |
| 1641 | 1641 | if (file_type == TCC_OUTPUT_DLL) |
| @@ -1643,7 +1643,7 @@ int elf_output_file(TCCState *s1, const char *filename) · 1 unmodified line | ||
| 1643 | 1643 | else |
| 1644 | 1644 | addr = ELF_START_ADDR; |
| 1645 | 1645 | /* compute address after headers */ |
| 1646 | − addr += (file_offset & (ELF_PAGE_SIZE - 1)); | |
| 1646 | + addr += (file_offset & (s1->section_align - 1)); | |
| 1647 | 1647 | } |
| 1648 | 1648 | |
| 1649 | 1649 | /* dynamic relocation table information, for .dynamic section */ |
| @@ -1661,7 +1661,7 @@ int elf_output_file(TCCState *s1, const char *filename) · 11 unmodified lines | ||
| 1661 | 1661 | ph->p_flags = PF_R | PF_X; |
| 1662 | 1662 | else |
| 1663 | 1663 | ph->p_flags = PF_R | PF_W; |
| 1664 | − ph->p_align = ELF_PAGE_SIZE; | |
| 1664 | + ph->p_align = s1->section_align; | |
| 1665 | 1665 | |
| 1666 | 1666 | /* we do the following ordering: interp, symbol tables, |
| 1667 | 1667 | relocations, progbits, nobits */ |
| @@ -1731,12 +1731,12 @@ int elf_output_file(TCCState *s1, const char *filename) · 63 unmodified lines | ||
| 1731 | 1731 | if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { |
| 1732 | 1732 | /* if in the middle of a page, we duplicate the page in |
| 1733 | 1733 | memory so that one copy is RX and the other is RW */ |
| 1734 | − if ((addr & (ELF_PAGE_SIZE - 1)) != 0) | |
| 1735 | − addr += ELF_PAGE_SIZE; | |
| 1734 | + if ((addr & (s1->section_align - 1)) != 0) | |
| 1735 | + addr += s1->section_align; | |
| 1736 | 1736 | } else { |
| 1737 | − addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1); | |
| 1738 | − file_offset = (file_offset + ELF_PAGE_SIZE - 1) & | |
| 1739 | − ~(ELF_PAGE_SIZE - 1); | |
| 1737 | + addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1); | |
| 1738 | + file_offset = (file_offset + s1->section_align - 1) & | |
| 1739 | + ~(s1->section_align - 1); | |
| 1740 | 1740 | } |
| 1741 | 1741 | } |
| 1742 | 1742 | } |
| @@ -349,6 +349,9 @@ struct pe_info { · 348 unmodified lines | ||
| 349 | 349 | DWORD iat_size; |
| 350 | 350 | DWORD exp_offs; |
| 351 | 351 | DWORD exp_size; |
| 352 | + int subsystem; | |
| 353 | + DWORD section_align; | |
| 354 | + DWORD file_align; | |
| 352 | 355 | struct section_info *sec_info; |
| 353 | 356 | int sec_count; |
| 354 | 357 | struct pe_import_info **imp_info; |
| @@ -417,14 +420,14 @@ ST_FN DWORD umax(DWORD a, DWORD b) · 62 unmodified lines | ||
| 417 | 420 | return a < b ? b : a; |
| 418 | 421 | } |
| 419 | 422 | |
| 420 | −ST_FN DWORD pe_file_align(DWORD n) | |
| 423 | +ST_FN DWORD pe_file_align(struct pe_info *pe, DWORD n) | |
| 421 | 424 | { |
| 422 | − return (n + (0x200 - 1)) & ~(0x200 - 1); | |
| 425 | + return (n + (pe->file_align - 1)) & ~(pe->file_align - 1); | |
| 423 | 426 | } |
| 424 | 427 | |
| 425 | −ST_FN DWORD pe_virtual_align(DWORD n) | |
| 428 | +ST_FN DWORD pe_virtual_align(struct pe_info *pe, DWORD n) | |
| 426 | 429 | { |
| 427 | − return (n + (0x1000 - 1)) & ~(0x1000 - 1); | |
| 430 | + return (n + (pe->section_align - 1)) & ~(pe->section_align - 1); | |
| 428 | 431 | } |
| 429 | 432 | |
| 430 | 433 | ST_FN void pe_align_section(Section *s, int a) |
| @@ -578,7 +581,7 @@ ST_FN int pe_write(struct pe_info *pe) · 147 unmodified lines | ||
| 578 | 581 | return -1; |
| 579 | 582 | } |
| 580 | 583 | |
| 581 | − pe->sizeofheaders = pe_file_align( | |
| 584 | + pe->sizeofheaders = pe_file_align(pe, | |
| 582 | 585 | sizeof (struct pe_header) |
| 583 | 586 | + pe->sec_count * sizeof (IMAGE_SECTION_HEADER) |
| 584 | 587 | ); |
| @@ -648,11 +651,11 @@ ST_FN int pe_write(struct pe_info *pe) · 63 unmodified lines | ||
| 648 | 651 | psh->VirtualAddress = addr; |
| 649 | 652 | psh->Misc.VirtualSize = size; |
| 650 | 653 | pe_header.opthdr.SizeOfImage = |
| 651 | − umax(pe_virtual_align(size + addr), pe_header.opthdr.SizeOfImage); | |
| 654 | + umax(pe_virtual_align(pe, size + addr), pe_header.opthdr.SizeOfImage); | |
| 652 | 655 | |
| 653 | 656 | if (si->data_size) { |
| 654 | 657 | psh->PointerToRawData = file_offset; |
| 655 | − file_offset = pe_file_align(file_offset + si->data_size); | |
| 658 | + file_offset = pe_file_align(pe, file_offset + si->data_size); | |
| 656 | 659 | psh->SizeOfRawData = file_offset - psh->PointerToRawData; |
| 657 | 660 | } |
| 658 | 661 | } |
| @@ -1085,7 +1088,7 @@ ST_FN int pe_assign_addresses (struct pe_info *pe) · 426 unmodified lines | ||
| 1085 | 1088 | strcpy(si->name, s->name); |
| 1086 | 1089 | si->cls = c; |
| 1087 | 1090 | si->ord = k; |
| 1088 | − si->sh_addr = s->sh_addr = addr = pe_virtual_align(addr); | |
| 1091 | + si->sh_addr = s->sh_addr = addr = pe_virtual_align(pe, addr); | |
| 1089 | 1092 | si->sh_flags = s->sh_flags; |
| 1090 | 1093 | |
| 1091 | 1094 | if (c == sec_data && NULL == pe->thunk) |
| @@ -1649,6 +1652,33 @@ PUB_FN int pe_output_file(TCCState * s1, const char *filename) · 557 unmodified lines | ||
| 1649 | 1652 | } else { |
| 1650 | 1653 | pe.imagebase = 0x00400000; |
| 1651 | 1654 | } |
| 1655 | + | |
| 1656 | + /* if no subsystem specified, we use "console" subsystem by default */ | |
| 1657 | + if (s1->pe_subsystem != 0) | |
| 1658 | + pe.subsystem = s1->pe_subsystem; | |
| 1659 | + else | |
| 1660 | + pe.subsystem = 3; | |
| 1661 | + | |
| 1662 | + /* set default file/section alignment */ | |
| 1663 | + if (pe.subsystem == 1) { | |
| 1664 | + pe.section_align = 0x20; | |
| 1665 | + pe.file_align = 0x20; | |
| 1666 | + } else { | |
| 1667 | + pe.section_align = 0x1000; | |
| 1668 | + pe.file_align = 0x200; | |
| 1669 | + } | |
| 1670 | + | |
| 1671 | + if (s1->section_align != 0) | |
| 1672 | + pe.section_align = s1->section_align; | |
| 1673 | + if (s1->pe_file_align != 0) | |
| 1674 | + pe.file_align = s1->pe_file_align; | |
| 1675 | + | |
| 1676 | + if ((pe.subsystem >= 10) && (pe.subsystem <= 12)) | |
| 1677 | + pe.imagebase = 0; | |
| 1678 | + | |
| 1679 | + if (s1->has_text_addr) | |
| 1680 | + pe.imagebase = s1->text_addr; | |
| 1681 | + | |
| 1652 | 1682 | pe_assign_addresses(&pe); |
| 1653 | 1683 | relocate_syms(s1, 0); |
| 1654 | 1684 | for (i = 1; i < s1->nb_sections; ++i) { |