GNU ld linker script for smaller PE .exe output
February 3, 2017 · View on GitHub
/* tinygccpe.scr: GNU ld linker script for smaller PE .exe output
- by pts@fazekas.hu at Fri Feb 3 15:41:13 CET 2017
- It's different from the default by:
-
- It drops initializers (e.g. .init, .ctors), and fails if the code tries
- to use them.
-
- It drops exceptions (e.g. .pdata), and fails if the code tries
- to use them.
-
- It merges .data and .rdata.
- Other recommended gcc flags for small .exe file: -fno-ident -fno-stack-protector -fomit-frame-pointer -fno-unwind-tables -fno-asynchronous-unwind-tables -falign-functions=1 -mpreferred-stack-boundary=2 -falign-jumps=1 -falign-loops=1
- Use with: i686-w64-mingw32-gcc -Wl,--section-alignment,16,--file-alignment,16,-T,tinygccpe.scr -nostdlib -nodefaultlibs -nostartfiles ... -lkernel32
- Also works with: i586-mingw32msvc-gcc -Wl,...
- Define
void __cdecl mainCRTStartup()' instead ofmain'. - Define
void __stdcall WinMainCRTStartup()' instead ofWinMain'.
/ OUTPUT_FORMAT(pei-i386) SECTIONS { / Make the virtual address and file offset synced if the alignment is
- lower than the target page size. / . = SIZEOF_HEADERS; . = ALIGN(section_alignment); .text image_base + (section_alignment < 0x1000 ? . : section_alignment) : { (.text) (SORT(.text*)) *(.text.*) *(.gnu.linkonce.t.*) *(.glue_7t) *(.glue_7) PROVIDE (etext = .); PROVIDE (_etext = .); } .data BLOCK(__section_alignment__) : { __data_start__ = .; *(.data) *(.data2) *(SORT(.data)) (.rdata) (SORT(.rdata*)) /* Merge .data and .rdata to save size. */ __rt_psrelocs_start = .; *(.rdata_runtime_pseudo_reloc) __rt_psrelocs_end = .; __data_end__ = .; *(.data_cygwin_nocopy) } __rt_psrelocs_size = __rt_psrelocs_end - __rt_psrelocs_start; ___RUNTIME_PSEUDO_RELOC_LIST_END__ = .; __RUNTIME_PSEUDO_RELOC_LIST_END__ = .; ___RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size; __RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size; .bss BLOCK(__section_alignment__) : { __bss_start__ = .; *(.bss) *(COMMON) __bss_end__ = .; } .idata BLOCK(__section_alignment__) : { /* This is pure magic. */ SORT(*)(.idata\2) SORT()(.idata$3) / These zeroes mark the end of the import list. / LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); SORT()(.idata$4) IAT_start = .; SORT()(.idata$5) IAT_end = .; SORT()(.idata$6) SORT()(.idata$7) } / Windows TLS expects .tlsZZZ to be at the end of section. This is important because _tls_start MUST be at the beginning of the section to enable SECREL32 relocations with TLS data. / .tls BLOCK(section_alignment) : { / Thread-local. */ _tls_start = .; *(.tls) (SORT(.tlsZZZ) _tls_end = .; } .endjunk BLOCK(section_alignment) : { PROVIDE (end = .); / Deprecated. / PROVIDE (end = .); end = .; } .rsrc BLOCK(section_alignment) : { *(.rsrc) (SORT(.rsrc$)) } .reloc BLOCK(section_alignment) : { *(.reloc) } .init : { *(.init) *(.fini) *(.ctors) *(.ctor) (SORT(.ctors.)) *(.dtors) *(.dtor) (SORT(.dtors.)) (.CRT) ASSERT(0, "Initializers (constructors and destructors) are not supported."); } .pdata : { *(.gcc_exc) *(.gcc_except_table) *(.pdata) ASSERT(0, "Exception handling is not supported."); } /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto) *(.note.ABI-tag) (.eh_frame .eh_frame_hdr) / CFI for the debugger (gdb). */ (.jcr) / Java class registrations. */ (.got.plt) (.comment) (.note) (.drectve) / DWARF debug, by `gcc -g'. / (.debug .line .zdebug .gnu.linkonce.wi. .gnu.linkonce.wt.) (.stab .stabstr .stab.) / Stabs debug. / / No difference, link warnings still displayed. / (.gnu.warning .gnu.warning.) (.gnu.version) } / Without this block ld will append all such sections to the target
- executable. We don't know how to handle them, so let's not append them. / .unsupported : / ALIGN(1) SUBALIGN(1) */ { () ASSERT(0, "Found non-empty unsupported section in object files."); } }