2017-02-03 12 views
5

У меня есть следующая программа C:Как создать крошечные PE (Win32) исполняемых файлов с помощью MinGW

#include <windows.h> 
void __cdecl mainCRTStartup() { 
    DWORD bw; 
    HANDLE hfile = GetStdHandle(STD_OUTPUT_HANDLE); 
    WriteFile(hfile, "Hello, World!\r\n", 15, &bw, 0); 
    ExitProcess(0); /* Needed for successful (0) exit. */ 
} 

я скомпилировать его с GCC 4.8.2, используя следующую командную строку:

i686-w64-mingw32-gcc -s -Os -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 -mconsole \ 
-nostdlib -nodefaultlibs -nostartfiles -o h.exe h.c -lkernel32 

Сгенерированный файл .exe имеет длину 2048 байт. Как уменьшить его с помощью MinGW, желательно не более 1024 байт или (еще лучше) не более 512 байт?

Я бы предпочел решение без написания ассемблерного кода, но меня также интересуют монтажные решения.

Я пробовал -Wl,-N, чтобы уменьшить количество разделов (сегментов), но это вызвало segfault при запуске .exe в Wine.

Этот article предлагает использовать 480 байтов. Он использует следующие настройки:

#pragma comment(linker, "/FILEALIGN:16") 
#pragma comment(linker, "/ALIGN:16")// Merge sections 
#pragma comment(linker, "/MERGE:.rdata=.data") 
#pragma comment(linker, "/MERGE:.text=.data") 
#pragma comment(linker, "/MERGE:.reloc=.data") 
#pragma optimize("gsy", on) 

К сожалению, эти #pragma s не работает с MinGW GCC. Есть ли эквиваленты?

В here Мне удалось найти флаги GCC -Wl,--section-alignment,16,--file-alignment,16, которые снижают размер .exe до 752 байта. Кажется, что .exe работает в Wine.

От modifying the linker script Мне удалось объединить .data и .rdata и спуститься до 736 байт. Я использую эти флаги GCC в дополнение к перечисленным выше: -Wl,--section-alignment,16,--file-alignment,16,-T,tinygccpe.scr.

Я по-прежнему ищу эквивалент MinGW /MERGE.

This question похоже, но он не пытается опускаться ниже 9000 байт.

Я также ищу strip инструмента (strip команды в MinGW не уменьшает .exe размера любых дальнейший), который может удалить заглушку DOS (которая находится между зачетами 0x40 и 0x80, он содержит This program cannot be run in DOS mode., мы может сохранить 64 байта). This code может удалить его, но он также разбивает все абсолютные смещения в .exe. К сожалению, компоновщик ld в MinGW не может удалить заглушку DOS, он жестко закодирован в файле bfd/peXXigen.c, чуть выше NT_SIGNATURE.

Можно ли вырезать больше заголовков из .exe, то есть заголовков, которые загрузчик не использует?

+2

Связанная статья очень старая. Речь идет о VC++ 6, который был выпущен в 1998 году. Какова мотивация для попытки сделать ничего-ничего двоичного? Чтобы сделать что-нибудь продуктивным, вам захочется установить ссылку в библиотеке времени выполнения, что сделает ваш двоичный файл большим. Я, конечно, не сторонник написания * раздутого * кода (очень против этого тоже), но, на мой взгляд, вы наклонены на ветряные мельницы. Есть веские причины, по которым компоновщики вставляют прописку, и это просто не имеет значения, если у вас есть нетривиальное количество кода. (Несмотря ни на что, это - достойный вопрос.) –

+0

@Cody Grey: Мотивация сохранения 1536 заголовков PE и байтов шаблонов в основном академическая. Эти байты, вероятно, не принесут заметной пользы для пользователя с современной многогигабайтной оперативной системой. Я также разрабатываю некоторые программы с небольшим общим количеством кода (менее 50 000 байтов при компиляции с указанными выше настройками). – pts

+1

Помните, что на носителе существует минимальный размер кластера. например. в Windows это обычно 4k. Даже если вам удастся получить компоновщик для создания меньшего исполняемого файла, он все равно займет столько места на диске. – greatwolf

ответ

0

Этот вопрос имеет обширную онлайн литературу, начиная с 1995 года около

Каждая версия 32-битной и 64-битной Windows, имеет другой набор правил о том, что заголовок значения, которые они принимают в PE EXE-исполняемых файлов. Например, Windows XP отклоняет 32-разрядные .exe-файлы с импортом, если у них не менее 3 разделов, а их выравнивание по секциям составляет 4096, а их выравнивание по файлам - 2 не менее 512. (Команда i686-w64-mingw32-gcc в вопросе генерирует такие исполняемые файлы.) Windows 7 принимает эти .exe-файлы, но также принимает файлы .exe с 0 разделами, выравниванием раздела 4, выравниванием файлов. 4.

Возможно создание рабочих файлов .exe размером менее 2048 байт.Пример:

  • hh2.golden.exe (402 bytes) работает в Windows XP, Windows 7 и выше.
  • hh4.golden.exe (268 bytes) не работает в Windows XP, он работает на Windows 7 и выше.
  • Исходный код сборки, входящий в комплект поставки pts-tinype.

Файлы .exe размером менее 268 байт работают только в версиях Windows, предшествующих Windows XP, и они не работают в 64-разрядных системах Windows.

Связанные литературы: