Миниприложение на gcc

Тема в разделе "WASM.ZEN", создана пользователем alpet, 27 июл 2005.

  1. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Застрял вот на проблеме с правильным обьявлением entry-point.



    1.c:
    Код (Text):
    1. <font color="green]
    2. int main()
    3. {
    4.    return 1;
    5. }
    6.  
    </font><!--color-->

    build.bat:
    Код (Text):
    1. <font color="green]
    2. @echo off
    3. set align=-Wl,--file-alignment,0x20 -Wl,--section-alignment,0x20
    4. set linko=-Wl,-e,main
    5. set libs=-L../lib/ ..\lib\crt2.o -luser32 -lkernel32 -lmingw32 -lmsvcrt -lgcc
    6.  
    7. gcc 1.c -O3 -s -ffast-math -mwindows -nostdlib %align% %linko% %libs%
    8.  
    </font><!--color-->



    Жалуется так: ld.exe: warning: cannot find entry symbol main; defaulting to 00400020



    Чего ему не хватает собственно?
     
  2. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    вроде так по стандарту:

    int main(int argc,char* argv[]);
     
  3. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    IceStudent

    Нет не помогает, я и такой прототип задавал, и вот такой:

    <font color="green]int APIENTRY WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)</font><!--color-->



    Сдается мне что линкер по какой-то причине просто не видит обьявленной функции, т.к. если бы не совпадали прототипы ошибка была бы наверное другая. С mvsc таких проблем нет - что ни задай - все кушает.



    По идее правильный прототип с void аргументом, я потрассировал несколько прог на VC++, они начинались с WinMainStartup (см. Vc7\crt\src\crt0.c):
    Код (Text):
    1.  
    2. #ifdef _WINMAIN_
    3.  
    4. #ifdef WPRFLAG
    5. int wWinMainCRTStartup(
    6. #else  /* WPRFLAG */
    7. int WinMainCRTStartup(
    8. #endif  /* WPRFLAG */
    9.  
    10. #else  /* _WINMAIN_ */
    11.  
    12. #ifdef WPRFLAG
    13. int wmainCRTStartup(
    14. #else  /* WPRFLAG */
    15. int mainCRTStartup(
    16. #endif  /* WPRFLAG */
    17.  
    18. #endif  /* _WINMAIN_ */
    19.  
    20.         void
    21.         )
    22.  




    Если задать aligment в 0x400 программа начинает работать несмотря на воринг, но при этом раздувается до 4Кб (так она всего 960 байт).
     
  4. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    может надо явно указать, примерно как в msvc:

    #pragma comment(linker, "/entry:main")
     
  5. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Однако нет. Всем спасибо, промучавшись 2 часа, я нашел проблему - компилятор мало того что искажает имя функций, он к ним еще и символ подчеркивания добавляет.

    Поэтому обьявление должно быть таким:

    extern "C" int main()

    А параметры линкера: -e _main



    З.Ы. Достаточно было заглянуть в обьектник промежуточный. Вместе с тем обидно - назначение entry работспособности проге не добавило - при загрузке выводится "1.exe не является приложением Win32".
     
  6. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Теперь вылепился вопрос - как заставить линкер соединить все секции в одну (.text + .data + .idata + .rdata), или ld здесь мне не помощник (т.е. надо юзать unilink) или как заставить его генерить рабочий exe-файл размером < 2Kb.
     
  7. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Попробуй глянуть в диру \mingw32\lib\ldscripts\

    там какие-то интересные файлы. правда, ничего не понятно мне в них :)
     
  8. rgo

    rgo New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2005
    Сообщения:
    87
    а файлик точно называется 1.c, не 1.cc и не 1.cpp? в *nix gcc (точнее C-frontend) никаких искажений имён, не выполняет. Этим g++ балуется. И то упомянутый extern "C", говорит о том же: программа компилируется как C++ программа, не как C.



    Насколько я помню свой недолгий опыт пользования gcc с target=i386-cygwin-pe, надо передать также опцию --subsystem=



    А, насчёт, собрать все секции в одну... Здесь я согласен со S_T_A_S_ наверное надо искать в ldscripts, и скорее всего писать новый скрипт сборки.
     
  9. rgo

    rgo New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2005
    Сообщения:
    87
    И ещё, мне кажется что entry point должен быть не main, а дефолтовый -- _start, который должен быть определён в crt*.o. А main будет из него вызыватся.
     
  10. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    rgo

    Пробывал в обоих вариантах, от .c пришлось отказаться в пользу .c++ - с ним не требуется подлючаться RTL (т.е. crt2.o и еще несколько зависимых либ), и использовать только -lkernel32 & -luser32. Со знаком подчеркивания ситуация одинаковая в обоих случаях - но в случае не задания extern "C" имя main искажается еще сильнее. В данной программе использовать стандартный entry никчему - инициализация RTL не нужна, используются только WinAPI функции.

    Со скриптами еще не разбирался.
     
  11. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Вобщем я обламываюсь пока достичь лучшего - сделал тоже самое на ассемблере:
    Код (Text):
    1.  
    2. .intel_syntax
    3. ; Source file "1.s"
    4. .text
    5. caption:    .ascii   "helloworld\0"
    6. textmsg:    .ascii   "Hi! I'm the example program!\0"
    7.  
    8. .global main
    9. /*  .type main, @function   */
    10.  
    11. main:
    12.             push        ebp
    13.             mov         ebp, esp
    14.             xor         eax, eax           
    15.             push        eax
    16.             push        offset caption
    17.             push        offset textmsg
    18.             push        eax
    19.             call        _MessageBoxA@16
    20.             leave
    21.             ret
    22.  




    Компилирую его с ключами:

    <font color="green]

    @echo off

    rem build.bat

    set addp= -Wl,-e,main,-b,pei-i386

    gcc 1.s -o 1.exe -Os -s -masm=intel -mwindows -nostdlib -luser32 %addp%

    </font><!--color-->



    В итоге получается EXE файл размером в 2048 байт. Если использовать скрипт линкера отменяющий выравнивание (параметр -n), файл уменьшается до 1720 байт, но становится не работоспособным. Файл с той же функциональностью на С++ весит 2560 байт, но в основном из-за того что строки компилятор помещает в отдельно для этого созданную секцию ресурсов. Как его отучить от этого я пока инфы не нашел.
     
  12. rgo

    rgo New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2005
    Сообщения:
    87
    На самом деле, есть такой пакет binutils -- который пользуя libBFD, может делать с объектным кодом кучу всяких вещей, от вывода данных о файле, типа списка символов, до дизассемблирования секций, вырезания отладочной информации/символов или даже секций, и перевода из одного формата в другой. Ручаться, что с его помощью можно слить две секции в одну, не буду, но мне кажется что можно.



    Но пакет, выполнен в лучших традициях *nix (Software Toolbox), и как им пользоваться без sh (ну или csh и пр), я не представляю. Хотя я точно также не представляю как вообще можно работать с компутером без sh :derisive:
     
  13. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    rgo

    libBFD - как я понял библиотека, которую нужно компилировать с проектом. Мне несовсем ясно как в этом деле может помочь либа. Конкретно из пакета binutils у меня есть утилиты, но с ними я еще не разбирался.



    Что касается sh - это не проблема, т.к. у меня есть MSYS - довольно полноценная оболочка с поддержкой скриптов. Недавно пытался с ее помощью собрать gcc 4.0.1, но потерпел неудачу на этапе конфигурирования - перед самым созданием makefile вывелась ошибка:

    "creating ./config.status

    creating Makefile

    sed: file conftest.s1 line 85: Unterminated `s' command"




    Сам я привык к cmd, который конечно смотрится примитивным на фоне никсовых команд-интерпретаторов, но его на основные задачи хватает.



    [edit]

    Хм. Странности какие-то, я сегодня попробывал опять сконфигурить - и прошло. Сейчас во всю идет сборка, и неизвестно когда она закончится. До конца сборки так и не дошло, хотя основные бинарники не собрались. Попробывал еще раз - уже конфигурация перестала работать нормально.
     
  14. Nothing

    Nothing New Member

    Публикаций:
    0
    Регистрация:
    4 авг 2003
    Сообщения:
    139
    Адрес:
    Russia
    alpet

    Я когда-то ковырял эту тему (минимальное приложение на gcc). Копал в сторону редактирования скриптов линкера (которые подключаются опцией ld -T xxx). Удалось многие секции засунуть в одну и сократить размер. А вообще у gcc жутко "мусорный" компилятор. Ну например выравнивание константных строк, процедур и прыжков у него прописано насмерть внутри самого gcc (я правил это бинарным патчем - размеры получаемых exe'шников уменьшились)... Ну и еще куча таких же "приколов" от разработчиков; может в 4.х что-то пофиксили, не знаю еще. Еще способ - заставить gcc сгенерить .s файл и пройтись там руками, хлама всякого там хватает.

    В аттаче пример i386pe.x у которого некоторые секции сведены воедино.

    [​IMG] _2103307015__i386pe.x
     
  15. rgo

    rgo New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2005
    Сообщения:
    87


    Нет, libBFD это либа, через которую в *nix происходит, вся user-mode работа с объектными файлами (были б в *nix актуальны вирусы, думается мне, и они бы тоже инфицировали используя libBFD). И binutils её активно пользует, по сути предоставляя все возможности libBFD для командной строки.