KX - новый формат исполнимых файлов

Applications development, KoOS API questions
User avatar
Kenshin
Posts: 41
Joined: Tue Jan 26, 2021 3:38 am

KX - новый формат исполнимых файлов

Post by Kenshin »

Короче, новый формат исполняемых файлов, с блекджеком и пончиками.
Вот "официальная" документация по формату KX (версия 0.0):
KX 0.0 Specification.pdf
(84.56 KiB) Downloaded 213 times
В спецификации всё описано подробно и детально, а далее я опишу покороче и в общих чертах.
KolibriOS eXecutable File Format (KX) был разработан в качестве преемника формата M0x (MENUET0x). При этом преследовались две цели: компактность (заголовка и полей в нём) и расширяемость (от версии к версии). Все KX файлы состоят из двух либо трёх частей: заголовок, необязательный подзаголовок и код/данные. Заголовок должен присутствовать обязательно и выглядит таким образом:

Code: Select all

        db      "KX", maj_kx_ver shl 4 + min_kx_ver, kx_flags
Всего четыре байта. Если подзаголовок не используется (младший бит kx_flags сброшен), то после этого сразу идёт первая инструкция программы (т.е. точка входа).
Т.е. простейшая программа выглядит примерно так:

Code: Select all

        use32
        org     0

        db      "KX", 0, 0
        
        include "macros.inc"
        
        mcall   -1
Если самый старший бит kx_flags установлен, то при загрузке программы сразу после/кода данных будет выделено дополнительно 4КБ под неинициализированные данные. После загрузки такая программа получает инициализированную кучу, стэк размером 4КБ, ESP указывает на вершину, основные регистры и флаги обнулены (кроме EAX – в нём хранится указатель на PRDB, о нём будет рассказано чуть позже). Для простых программ этого может быть достаточно, но если нужны дополнительные возможности, необходимо задействовать подзаголовок.
При использования подзаголовка, устанавливаются флаги в kx_flags (самый младший бит устанавливается в 1, биты 1-2 в 00/01/10 - для 8-/16-/32-битных чанков). Подзаголовок является линейным массивом из чанков (chunks) или фреймов и располагается сразу после заголовка. Каждый чанк состоит из заголовка (тип чанка + размер данных) и непосредственно данных. Завершает заголовок специальный чанк -1. Для версии 0.0 с помощью чанков можно определить точку входа, стартовый размер памяти процесса, размер стека, атрибуты исполняемого файла, краткое описание программы и множество чанков с таблицей импорта (один на одну библиотеку).
Файл с чанками загружаются похожим образом, но с небольшими отличиями. Если определена точка входа, EIP устанавливается на неё. Если был определён размер стэка, то выделяется не 4КБ, а указанное кол-во. Если был определён стартовый размер памяти, то выделяется память не по размеру образа программы, а указанное кол-во.
Все KX-процессы получают при запуске в EAX указатель на PRDB (Pre-Runtime Data Block). В нём загрузчик размещает следующие данные:
  • PID процесса
  • PID родителя (загрузчика)
  • указатель на строку с именем KX-файла
  • указатель на строку с переданными параметрами
Для тестирования формата был специально написан загрузчик runkx [rʌŋks].
runkx.7z
(7.96 KiB) Downloaded 157 times
В архиве также лежит тестовый KX-вариант программы calc. Пока что runkx не поддерживает все возможности формата (например, загрузку библиотек и обработку атрибутов), но большей части "стандарта" он уже соответствует. Также, пока что не реализована поддержка упаковки. Формат KX на уровне спецификации поддерживает сжатие файлов с помощью kpack (или других утилит). При этом подзаголовок и код/данные сжимаются отдельно. Заголовок никогда не сжимается.
Last edited by Kenshin on Wed Feb 24, 2021 1:59 am, edited 1 time in total.
User avatar
Kenshin
Posts: 41
Joined: Tue Jan 26, 2021 3:38 am

Re: KX - новый формат исполнимых файлов

Post by Kenshin »

Пример простой программы, использующей неинициализированные переменные:

Code: Select all

        use32
        org     0
        
        db      "KX", 0, 0x80
        
        call    proc0
        call    proc1
        ...
        mov     [x], 5
        mov     eax, [x]
        mov     [y], eax
        ...
        xor     eax, eax
        dec     eax
        int     0x40
        
x       dd      ?
y       dd      ?

User avatar
Kenshin
Posts: 41
Joined: Tue Jan 26, 2021 3:38 am

Re: KX - новый формат исполнимых файлов

Post by Kenshin »

Структура чанка с 8-битным заголовком:

Code: Select all

        db      chunk_type
        db      chunk_data_size
        db      chunk_data_size dup ? ;chunk_data
с 16-битным заголовком:

Code: Select all

        dw      chunk_type
        dw      chunk_data_size
        db      chunk_data_size dup ? ;chunk_data
с 32-битным заголовком:

Code: Select all

        dd      chunk_type
        dd      chunk_data_size
        db      chunk_data_size dup ? ;chunk_data
User avatar
Kenshin
Posts: 41
Joined: Tue Jan 26, 2021 3:38 am

Re: KX - новый формат исполнимых файлов

Post by Kenshin »

Забыл написать про то, что runkx - это консольная программа, поэтому её нужно запускать в shell-е так:
runkx kxapp kxparams
или
runkx "kx app" "kx params"
Например, для того, чтобы запустить calc.test в шелле введите:
runkx calc.test

Для работы программы требуется наличие /tmp0/1 раздела и свободного места на нём.
User avatar
dunkaist
Mentor
Posts: 730
Joined: Mon Oct 19, 2009 10:58 am
Has thanked: 4 times
Been thanked: 2 times

Re: KX - новый формат исполнимых файлов

Post by dunkaist »

Hi Kenshin,

I appreciate your work and value your experience. There are, however, two things I don't get:
  1. What is the problem you are solving with another custom format?
  2. What is your position on PE-related activities in this thread? I particularly mean arguments for PE and against custom formats like the current one.
User avatar
Kenshin
Posts: 41
Joined: Tue Jan 26, 2021 3:38 am

Re: KX - новый формат исполнимых файлов

Post by Kenshin »

dunkaist wrote:What is the problem you are solving with another custom format?
  1. Заголовок короче, чем M0x или PE/ELF.
  2. Меньше кода, загрузчик подготавливает всё для работы программы (стэк, память, загружает библиотеки (пока не реализовано)), выделяет необходимое кол-во памяти под строку с именем файла и строку с параметрами (т.е. не важно сколько они занимают, выделяется ровно столько места, сколько необходимо).
  3. Так как под стэк выделяется отдельный блок памяти, при переполнении произойдёт исключение General Fault, в существующих же программах при переполнении будут затираться лежащие перед стэком данные.
  4. Чтобы узнать такие важные параметры, например, как PID, теперь не нужно выделять килобайтный буфер и ждать пока его заполнит функция 9.
  5. Даже если программа в формате KX запакована, любая программа может быстро понять (т.е. не распаковывая весь файл), что это именно KX-файл, т.к. заголовок не упаковывается. Чтобы прочитать описание/иконки (будут в будущих версиях)/таблицы импорта, опять же не нужно распаковывать весь файл, достаточно разжать только данные подзаголовка.
  6. Различные фичи, которых нет в формате M0x, например краткое описание программы или аттрибуты файла (тип файла, тип используемого интерфейса (GUI/TUI и т.д.), минимальная SVN-ревизия ядра для запуска), в будущих версиях будут новые и (надеюсь) полезные фичи.
  7. Название формата, которое отражает то, что программа для KolibriOS, а не MenuetOS.
User avatar
Kenshin
Posts: 41
Joined: Tue Jan 26, 2021 3:38 am

Re: KX - новый формат исполнимых файлов

Post by Kenshin »

Против PE/ELF я ничего не имею, но идея заключалась в том, чтобы сделать формат в духе Колибри.
User avatar
Kenshin
Posts: 41
Joined: Tue Jan 26, 2021 3:38 am

Re: KX - новый формат исполнимых файлов

Post by Kenshin »

runkx теперь поддерживает чанк "General Executable File Attributes", который позволяет указать вид исполняемого файла, тип используемого интерфейса (GUI/TUI или неопределённый UI для служб, демонов и т.д.), флаги исполняемого файла, а также номер минимальной ревизии ядра, которая поддерживает данный KX-файл (например, если ваша программа использует фьютексы, вам нужно указать здесь ревизию 6926, т.к. их поддержка в ядре появилась в этой ревизии, и в таком случае runkx запустит такой файл только на ядре рев. 6926+).
runkx_0.0.1b.7z
(8.1 KiB) Downloaded 141 times
User avatar
Kenshin
Posts: 41
Joined: Tue Jan 26, 2021 3:38 am

Re: KX - новый формат исполнимых файлов

Post by Kenshin »

Пример программы в формате KX с использованием подзаголовка:

Code: Select all

        use32
        org     0x0

        db      "KX", 0, 0x81           ;the KX header

        db      0, 4                    ;default entry point chunk
        dd      entry_point

        db      0x20, 12                ;general executable file attributes chunk
        dw      0                       ;a regular 32-bit KolibriOS application/program
        dw      1                       ;uses GUI
        dd      0                       ;executable file flags
        dd      0                       ;any version of kernel
        
        db      0xA0, 23                ;short description chunk
        db      "myapp - my application", 0

        db      -1
        
entry_point:
        call    proc1
        call    proc2
        
        xor     eax, eax
        dec     eax
        int     0x40
        
proc1:
        ...
        ret
        
proc2:
        ...
        ret
Флаги KX, установленные в 0x81, обозначают, что данная программа использует подзаголовок и что во время загрузки будут выделены 4 КБ памяти под неинициализированные данные. Если нужно больше 4 КБ, то можно использовать чанк "Initial Process Memory Size", указав в нём начальный размер общей памяти процесса. Если программа не использует неинициализированные данные, нужно сбросить старший бит флагов (т.е. должно быть 0x01).
User avatar
rgimad
Posts: 162
Joined: Mon Apr 06, 2020 1:09 pm
Has thanked: 6 times
Been thanked: 1 time

Re: KX - новый формат исполнимых файлов

Post by rgimad »

думаю, когда формат уже устаканится, можно попробовать внедрить поддержку данного формата в ядро.
The best way to predict the future is to create it.
User avatar
Alex2003
Posts: 350
Joined: Wed Mar 18, 2015 8:22 am

Re: KX - новый формат исполнимых файлов

Post by Alex2003 »

На каких языках программирования можно писать программы с использованием формата kx?
Я один из тех, кто ещё не программист, но уже не новичок.
Редактор в группе "KolibriOS - официальная группа".
maxcodehack
Posts: 412
Joined: Mon Sep 07, 2020 7:09 pm

Re: KX - новый формат исполнимых файлов

Post by maxcodehack »

На любом ведь
Главное чтобы компилер смог в этот формат
(просто редко захожу на пару минут)
User avatar
GerdtR
Posts: 471
Joined: Mon Nov 19, 2012 5:22 pm

Re: KX - новый формат исполнимых файлов

Post by GerdtR »

maxcodehack wrote:На любом ведь
Главное чтобы компилер смог в этот формат
1. Вот в том и проблема. Ассемблеры. Вроде всё. Потому и первоначальный заголовок Menuet не очень. С-- научили, местные С компилеры тоже. Из pascal и C (msvc или gcc) делали ухищрения в линкерах. Для паскаля вроде прога специальная была из виндового PE делать.
2. Динамические библиотеки, линковка, как дела с этим? Этот формат для библиотек годится?
3. Ресурсы предполагаются? Или хотя бы можно ли будет хранить иконку приложения в стандартном для всей Кос месте?
Чем больше сыра, тем больше в нём дыр. Чем больше дыр, тем меньше в нём собственно сыра. Значит, чем больше сыра, тем меньше сыра!
User avatar
Kenshin
Posts: 41
Joined: Tue Jan 26, 2021 3:38 am

Re: KX - новый формат исполнимых файлов

Post by Kenshin »

GerdtR wrote:
maxcodehack wrote:На любом ведь
Главное чтобы компилер смог в этот формат
1. Вот в том и проблема. Ассемблеры. Вроде всё. Потому и первоначальный заголовок Menuet не очень. С-- научили, местные С компилеры тоже. Из pascal и C (msvc или gcc) делали ухищрения в линкерах. Для паскаля вроде прога специальная была из виндового PE делать.
2. Динамические библиотеки, линковка, как дела с этим? Этот формат для библиотек годится?
3. Ресурсы предполагаются? Или хотя бы можно ли будет хранить иконку приложения в стандартном для всей Кос месте?
1. Привязки к какому-то определённому языку нет, хотя да, формат лучше всего подходит для fasm'а, который может создавать практически любые файлы с самой разной структурой.
2. а) Текущая версия формата поддерживает таблицы импорта для неограниченного кол-ва библиотек, а runkx скоро научится их автоматически подключать (при этом разработчику не обязательно знать, где хранятся системные библиотеки, он может указать либо имя библиотеки полное,т.е. с путём, либо базовое - например, "libini.obg"). Сейчас для каждой библиотеки своя отдельная таблица импорта, а в версии 0.1 появится общая или универсальная таблица, описывающая импорт сразу нескольких библиотек.
б) Изначально KX разработан именно для обычных программ и приложений, т.к. есть MS COFF, но расширяемость формата позволяет в будущем использовать его для библиотек/драйверов/чего-либо ещё, если такая надобность возникнет, разумеется.
3. Да, поддержка ресурсов была запланирована с самого начала. В версии 0.1 появятся как минимум иконки, а насчёт других ништяков надо думать, ибо стандартов ресурсов (например, форм) в Kolibri практически нет. Также появятся возможность расширенного описания программы (версия, автор, дата сборки, описание и т.д.). Возможно ещё что-то будет, хотя лишних вещей в формате тоже не хочется.
User avatar
ProMiNick
Posts: 46
Joined: Thu Aug 04, 2016 10:43 am

Re: KX - новый формат исполнимых файлов

Post by ProMiNick »

Kenshin, а разве код лоадера не самая информативная часть после непосредственно описания спецификации?
правильно ли я понимаю, что какой то формат тестируется вначале лоадером, и лишь потом помещается в ядро. управление памятью в пространстве адресов процесса вещь интересная. Она может быть реализована в юзермод лоадером?
А еще как загрузка библиотек стыкуется с загрузкой их системой.
Имею в виду что система загружает библиотеку в память однажды, НО...
НО если код библиотеки не адресонезависимый то в процесс загружается свой экземпляр библиотеки...
это то делает система, понятно.
Но данные и код в библиотеке адресуются процессами по разному: данные в реальной памяти полностью разделяемы по разным адресам виртуальной памяти каждого процесса, а код наоборот: для каждого виртуального адреса создается свой экземпляр в реальной памяти релоцированный на этот адрес, в пределах одного виртуального адреса разных процессов в реальной памяти создается только 1 его экземпляр.
Т.е. список подгруженных библиотек можно также на уровне лоадера хранить, а не на уровне ядра? И так вот с памятью тоже лоадер может играться?
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests