Помогите новичку

Applications development, KoOS API questions
  • Пробую сделать PE dll по инструкции, не линкуется в dll-ку, потому что требует некоторые функции из libc, а если подключать libc, то ругается на отсутствие main, __cmdline и __pgmname. Проще заменить функции, используемые freetype, на аналоги, или есть другие методы?

    upd: Нет функций printf, ftell, fread, fseek, fclose, fopen, memmove. С printf я разберусь, файловые операции есть в libio - можно ли использовать coff-библиотеки из dll, и если да, то как? Что делать с memmove?
  • Sorcerer

    Bce функции есть, надо линковать не со статической libc, а с библиотеками импорта. Посмотри svn://kolibrios.org/programs/develop/libraries/libmpg123 Библиотеки импорта и длл http://code.google.com/p/kolibri-pe/downloads/list
  • Угу, собралось. Заголовок у библиотеки MZ, так и должно быть? Как проверить, что все правильно собралось (т.е. как подключать pe-библиотеки к Си-программам)? Я правильно понял, что нужно все делать, как и при статической линковке, но линковать с libfreetypeimp.a?
  • Sorcerer
    Я правильно понял, что нужно все делать, как и при статической линковке, но линковать с libfreetypeimp.a?
    Почти. Надо собирать PE приложение.
    1. Пишешь обычную программу на С.
    2. Линкуешь с ключами -nostdlib -pie -s -T pe_app.lds --image-base 0 --stack 0x100000 -Map test.map -lamz -lgcc -lcimp + остальные библиотеки импорта.
    3. Получившийся екзешник встраиваешь в demo.asm (он есть amz-dev.12.03.11.7z)

    Для проверки PE екзешников и ддлок рекомендую pedump:
    pedump моя_программа_или_длл >dump.txt
    Spoiler:Dump of file LIBMPG123.DLL
    File Header
    Machine: 014C (i386)
    Number of Sections: 0007
    TimeDateStamp: 4D7A75F9
    PointerToSymbolTable: 00000000
    NumberOfSymbols: 00000000
    SizeOfOptionalHeader: 00E0
    Characteristics: 230E
    EXECUTABLE_IMAGE
    LINE_NUMS_STRIPPED
    LOCAL_SYMS_STRIPPED
    32BIT_MACHINE
    DLL

    Optional Header
    Magic 010B
    linker version 2.21
    size of code F600
    size of initialized data 6000
    size of uninitialized data 10000
    entrypoint RVA 1000
    base of code 1000
    base of data 15000
    image base 0
    section align 1000
    file align 200
    required OS version 4.00
    image version 1.00
    subsystem version 4.00
    Reserved1 0
    size of image 2A000
    size of headers 400
    checksum 1D4B2
    Subsystem 0003 (Windows character)
    DLL flags 0000
    stack reserve size 200000
    stack commit size 1000
    heap reserve size 100000
    heap commit size 1000
    loader flags 00000000
    RVAs & sizes 10

    Data Directory
    EXPORT rva: 00027000 size: 00000706
    IMPORT rva: 00028000 size: 00000118
    RESOURCE rva: 00000000 size: 00000000
    EXCEPTION rva: 00000000 size: 00000000
    SECURITY rva: 00000000 size: 00000000
    BASERELOC rva: 00029000 size: 000005B8
    DEBUG rva: 00000000 size: 00000000
    COPYRIGHT rva: 00000000 size: 00000000
    GLOBALPTR rva: 00000000 size: 00000000
    TLS rva: 00000000 size: 00000000
    LOAD_CONFIG rva: 00000000 size: 00000000
    unused rva: 00000000 size: 00000000
    unused rva: 00000000 size: 00000000
    unused rva: 00000000 size: 00000000
    unused rva: 00000000 size: 00000000
    unused rva: 00000000 size: 00000000

    Section Table
    01 .text VirtSize: 0000F59C VirtAddr: 00001000
    raw data offs: 00000400 raw data size: 0000F600
    relocation offs: 00000000 relocations: 00000000
    line # offs: 00000000 line #'s: 00000000
    characteristics: 60600020
    CODE MEM_EXECUTE MEM_READ

    02 .rdata VirtSize: 00003260 VirtAddr: 00011000
    raw data offs: 0000FA00 raw data size: 00003400
    relocation offs: 00000000 relocations: 00000000
    line # offs: 00000000 line #'s: 00000000
    characteristics: 40600040
    INITIALIZED_DATA MEM_READ

    03 .data VirtSize: 00001AA4 VirtAddr: 00015000
    raw data offs: 00012E00 raw data size: 00001C00
    relocation offs: 00000000 relocations: 00000000
    line # offs: 00000000 line #'s: 00000000
    characteristics: C0600040
    INITIALIZED_DATA MEM_READ MEM_WRITE

    04 .bss VirtSize: 0000FF84 VirtAddr: 00017000
    raw data offs: 00000000 raw data size: 00000000
    relocation offs: 00000000 relocations: 00000000
    line # offs: 00000000 line #'s: 00000000
    characteristics: C0600080
    UNINITIALIZED_DATA MEM_READ MEM_WRITE

    05 .edata VirtSize: 00000706 VirtAddr: 00027000
    raw data offs: 00014A00 raw data size: 00000800
    relocation offs: 00000000 relocations: 00000000
    line # offs: 00000000 line #'s: 00000000
    characteristics: 40300040
    INITIALIZED_DATA MEM_READ

    06 .idata VirtSize: 00000118 VirtAddr: 00028000
    raw data offs: 00015200 raw data size: 00000200
    relocation offs: 00000000 relocations: 00000000
    line # offs: 00000000 line #'s: 00000000
    characteristics: C0300040
    INITIALIZED_DATA MEM_READ MEM_WRITE

    07 .reloc VirtSize: 000005B8 VirtAddr: 00029000
    raw data offs: 00015400 raw data size: 00000600
    relocation offs: 00000000 relocations: 00000000
    line # offs: 00000000 line #'s: 00000000
    characteristics: 42300040
    INITIALIZED_DATA MEM_DISCARDABLE MEM_READ

    Imports Table:
    libc.dll
    Hint/Name Table: 00028028
    TimeDateStamp: 00000000
    ForwarderChain: 00000000
    First thunk RVA: 00028054
    Ordn Name
    306 close
    378 free
    465 lseek
    466 malloc
    473 memmove
    490 open
    492 pow
    503 read
    505 realloc
    548 strcasecmp


    exports table:

    Name: libmpg123.dll
    Characteristics: 00000000
    TimeDateStamp: 4D7A75F9
    Version: 0.00
    Ordinal base: 00000001
    # of functions: 00000044
    # of Names: 00000044

    Entry Pt Ordn Name
    00001EE4 1 mpg123_clip
    00002B88 2 mpg123_close
    00003FF4 3 mpg123_current_decoder
    00001D1C 4 mpg123_decode
    00001BC4 5 mpg123_decode_frame
    00001A28 6 mpg123_decoder
    00004010 7 mpg123_decoders
    00002CC8 8 mpg123_delete
    0000DC70 9 mpg123_delete_pars
    00002B14 10 mpg123_enc_from_id3
    0000F310 11 mpg123_encodings
    000015C4 12 mpg123_eq
    00002D24 13 mpg123_errcode
    0000110C 14 mpg123_exit
    00001CC4 15 mpg123_feed
    00002124 16 mpg123_feedseek
    0000F660 17 mpg123_fmt
    0000F5B8 18 mpg123_fmt_all
    0000F558 19 mpg123_fmt_none
    0000F7A4 20 mpg123_fmt_support
    0000F750 21 mpg123_format
    0000F624 22 mpg123_format_all
    0000F57C 23 mpg123_format_none
    0000F810 24 mpg123_format_support
    00001650 25 mpg123_geteq
    00001F04 26 mpg123_getformat
    000013CC 27 mpg123_getpar
    00001518 28 mpg123_getparam
    0000156C 29 mpg123_getstate
    0000F094 30 mpg123_getvolume
    00002AF8 31 mpg123_icy
    00002B10 32 mpg123_icy2utf8
    00002A84 33 mpg123_id3
    00002B2C 34 mpg123_index
    0000E48C 35 mpg123_info
    000010D8 36 mpg123_init
    00002508 37 mpg123_length
    00002A70 38 mpg123_meta_check
    000011D0 39 mpg123_new
    0000DBC4 40 mpg123_new_pars
    00002C7C 41 mpg123_open
    00002C30 42 mpg123_open_fd
    00002BF4 43 mpg123_open_feed
    00001AF8 44 mpg123_outblock
    000011F8 45 mpg123_par
    00001348 46 mpg123_param
    00001110 47 mpg123_parnew
    00002CF8 48 mpg123_plain_strerror
    0000CE60 49 mpg123_position
    0000F2F0 50 mpg123_rates
    00001EA8 51 mpg123_read
    0000DF24 52 mpg123_replace_buffer
    000016B0 53 mpg123_replace_reader
    0000DC8C 54 mpg123_reset_eq
    00001AF0 55 mpg123_safe_buffer
    000026A0 56 mpg123_scan
    0000283C 57 mpg123_seek
    00002350 58 mpg123_seek_frame
    000024E8 59 mpg123_set_filesize
    00002D3C 60 mpg123_strerror
    00004018 61 mpg123_supported_decoders
    0000200C 62 mpg123_tell
    000020FC 63 mpg123_tell_stream
    000020C0 64 mpg123_tellframe
    00001F88 65 mpg123_timeframe
    0000CE1C 66 mpg123_tpf
    0000EE44 67 mpg123_volume
    0000EF84 68 mpg123_volume_change
    Для запуска понадобятся libc.obj system.env из последней демки Cairo (amz-12.03.11.7z)
    Attachments
    pedump.zip (16.61 KiB)
    Matt Pietrek's PE dump
    Downloaded 144 times
  • Update.
    В system.env надо прописать путь к PE ддлкам.
  • Спасибо! Вечером попробую.
    Обидно, что тяжеловаты бинарники получаются - непакованный freetype.dll занимает 97 килобайт (а ему еще libc.obj будет нужен, верно?). Хм, а в запакованном - всего 37 килобайт.

    И как это - "встроить экзешник в demo.asm"?
  • Sorcerer

    в demo.asm есть строчки
    my_app:
    file 'my_app.exe'
    фактически это контейнер для PE приложения. DLL можно сжимать kpack, хотя и не рекомендуется. Вообще всё это больше рассчитано за работу с винта или LiveCD. Пишешь в system.env свой путь к длл и их размер больше не волнует. Опция ld -s удаляет отладочную информацию. -file-alignment 32 --section-alignment 32 помогают уменьшить размер.
  • Имею всевозможные инклуды в подпапке include, компилирую библиотеку, всё хорошо.
    Затем в другой папке с теми же инклудами компилирую common.c и ftstrpnm.c в объектники. Копирую в папку к o-файлам все imp-библиотеки, libamz и свежесобранную freetype. Пытаюсь слинковать:
    i586-mingw32msvc-ld -nostdlib -pie -s -T pe_app.lds --image-base 0 --stack 0x100000 -Map test.map -L ./ -lamz -lcimp -lgcc -lfreetypeimp -o ftpnm.exe *.o
    Получаю undefinded reference на все функции libc и freetype, используемые в программе.

    Если вместо библиотек указывать напрямую a и o файлы, то остается undefined reference только на __getreent.

    И всё же хотя PE-библиотеки более перспективны, их нельзя так же легко использовать, как COFF-библиотеки Колибри, верно?
  • Sorcerer

    Mingw ld чувствителен к порядку в котором перечисляются библиотеки. Почему так не знаю. Попробуй поставить -lcimp после -lfreetypeimp и все либы после объектников. __getreent - это что-то компилировал без -D__DYNAMIC_REENT__.
    И всё же хотя PE-библиотеки более перспективны, их нельзя так же легко использовать, как COFF-библиотеки Колибри, верно?
    Не думаю что с COFF легче. Для COFF библиотек надо всё вручную импортировать или писать таблицы импорта. Для PE всё делается автоматически. Единственная сложность то, что ядро пока не умеет грузить PE приложения.

    Тут ещё один момент. Для отладки и поиска ошибок лучше линковать со статическими библиотеками, легче найти по map где вылетает. В случае PE это совсем не требует модификации исходного кода.
  • Code: Select all

    sourcerer@sourcerer-laptop ~/projects/libc/ftdemo $ i586-mingw32msvc-gcc -c *.c  -fomit-frame-pointer -I include/ -D__DYNAMIC_REENT__ -O2
    In file included from common.c:34:
    include/stdlib.h:110: предупреждение: директива описания атрибутов ‘__warning__’ проигнорирована
    include/stdlib.h:117: предупреждение: директива описания атрибутов ‘__warning__’ проигнорирована
    In file included from ftstrpnm.c:18:
    include/stdlib.h:110: предупреждение: директива описания атрибутов ‘__warning__’ проигнорирована
    include/stdlib.h:117: предупреждение: директива описания атрибутов ‘__warning__’ проигнорирована
    sourcerer@sourcerer-laptop ~/projects/libc/ftdemo $ i586-mingw32msvc-ld -nostdlib -pie -s -T pe_app.lds --image-base 0 --stack 0x100000 -Map test.map ftstrpnm.o common.o -L ./ -lfreetypeimp -lamz -lcimp  -o ftpnm.exe 
    ftstrpnm.o:ftstrpnm.c:(.text+0x75f): undefined reference to `__getreent'
    common.o:common.c:(.text+0x2ad): undefined reference to `__getreent'
    common.o:common.c:(.text+0x2e9): undefined reference to `__getreent'
    
    В опциях сборки библиотеки тоже есть -D__DYNAMIC_REENT__.
  • Sorcerer

    Проверь заголовочные файлы newlib на svn. Там лежит самая последняя версия. __getreent определена в include/sys/reent.h

    Code: Select all

    static inline struct _reent *__getreent(void)
    {
        struct _reent *ent;
        __asm__ __volatile__(
        "movl %%fs:12, %0"
        :"=r"(ent));
        return ent;
    };
  • CleverMouse wrote: Возможны варианты - компилятор может не решиться делать все действия прямо с hidden, а честно заполнять локальную переменную и потом её копировать в *hidden; компилятор может возвращать не void, а сам указатель hidden для удобства, - но суть такая: если возвращаемое значение не умещается в регистр, то функция имеет неявный первый параметр, являющийся указателем на результат.
    Спасибо, CleverMouse, это многое объясняет :)

    Ещё: допустим, я хочу определить аналог C-шного union:
    Spoiler:typedef union tp_obj {
    int type;
    tp_number_ number;
    tp_string_ string;
    tp_dict_ dict;
    } tp_obj;
    Пишу:
    Spoiler:struct tp_obj
    type rd 1
    virtual at 0
    string tp_string_
    end virtual
    virtual at 0
    number tp_number_
    end virtual
    virtual at 0
    dict tp_dict_
    end virtual
    ends
    Но sizeof.tp_obj почему-то равен не макcимуму из 16 и длин структур tp_string_, tp_number_, и tp_dict_, а их сумме. В чём дело и правильно ли я вообще определяю объединение?
  • Нет, неправильно. Если использовать struct.inc, то делать надо так:

    Code: Select all

    struct tp_obj
    union
    type dd ?
    string tp_string_
    number tp_number_
    dict tp_dict_
    ends
    ends
    
    Сделаем мир лучше!
  • что будет со скомпилированой программой, если ее после компиляции поместить в чужое адресное пространство (т.е. не с нуля код будет начинаться), и как этого можно избежать в пользу нормальной работы?
    P.S.: помнится, раньше, до плоской модели в Колибри, рабочее пространство программ начиналось не с нуля - это не описанная выше ситуация? я тогда просто не писал вроде еще программ.
    И мы уже давно не пешки,
    Мы пули, мы орлы, и решки!
    Война ютит бинарный код,
    Умри, или иди вперед!
  • Who is online

    Users browsing this forum: No registered users and 11 guests