Board.KolibriOS.org

Official KolibriOS board
It is currently Sat Sep 25, 2021 6:20 pm

All times are UTC+03:00




Post new topic  Reply to topic  [ 21 posts ]  Go to page 1 2 Next
Author Message
PostPosted: Mon Feb 22, 2021 9:05 am 
Offline
User avatar

Joined: Tue Jan 26, 2021 3:38 am
Posts: 40
Короче, новый формат исполняемых файлов, с блекджеком и пончиками.
Вот "официальная" документация по формату KX (версия 0.0):
Attachment:
KX 0.0 Specification.pdf [84.56 KiB]
Downloaded 121 times


В спецификации всё описано подробно и детально, а далее я опишу покороче и в общих чертах.
KolibriOS eXecutable File Format (KX) был разработан в качестве преемника формата M0x (MENUET0x). При этом преследовались две цели: компактность (заголовка и полей в нём) и расширяемость (от версии к версии). Все KX файлы состоят из двух либо трёх частей: заголовок, необязательный подзаголовок и код/данные. Заголовок должен присутствовать обязательно и выглядит таким образом:
Code:
        db      "KX", maj_kx_ver shl 4 + min_kx_ver, kx_flags

Всего четыре байта. Если подзаголовок не используется (младший бит kx_flags сброшен), то после этого сразу идёт первая инструкция программы (т.е. точка входа).
Т.е. простейшая программа выглядит примерно так:
Code:
        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].
Attachment:
runkx.7z [7.96 KiB]
Downloaded 78 times

В архиве также лежит тестовый KX-вариант программы calc. Пока что runkx не поддерживает все возможности формата (например, загрузку библиотек и обработку атрибутов), но большей части "стандарта" он уже соответствует. Также, пока что не реализована поддержка упаковки. Формат KX на уровне спецификации поддерживает сжатие файлов с помощью kpack (или других утилит). При этом подзаголовок и код/данные сжимаются отдельно. Заголовок никогда не сжимается.


Last edited by Kenshin on Wed Feb 24, 2021 1:59 am, edited 1 time in total.

Top
   
PostPosted: Mon Feb 22, 2021 9:17 am 
Offline
User avatar

Joined: Tue Jan 26, 2021 3:38 am
Posts: 40
Пример простой программы, использующей неинициализированные переменные:
Code:
        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      ?



Top
   
PostPosted: Mon Feb 22, 2021 9:21 am 
Offline
User avatar

Joined: Tue Jan 26, 2021 3:38 am
Posts: 40
Структура чанка с 8-битным заголовком:
Code:
        db      chunk_type
        db      chunk_data_size
        db      chunk_data_size dup ? ;chunk_data

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

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


Top
   
PostPosted: Mon Feb 22, 2021 12:41 pm 
Offline
User avatar

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

Для работы программы требуется наличие /tmp0/1 раздела и свободного места на нём.


Top
   
PostPosted: Mon Feb 22, 2021 1:42 pm 
Offline
Mentor
User avatar

Joined: Mon Oct 19, 2009 10:58 am
Posts: 675
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.


Top
   
PostPosted: Mon Feb 22, 2021 3:19 pm 
Offline
User avatar

Joined: Tue Jan 26, 2021 3:38 am
Posts: 40
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.


Top
   
PostPosted: Mon Feb 22, 2021 3:20 pm 
Offline
User avatar

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


Top
   
PostPosted: Wed Feb 24, 2021 2:15 am 
Offline
User avatar

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


Top
   
PostPosted: Wed Feb 24, 2021 2:38 am 
Offline
User avatar

Joined: Tue Jan 26, 2021 3:38 am
Posts: 40
Пример программы в формате KX с использованием подзаголовка:
Code:
        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).


Top
   
PostPosted: Wed Feb 24, 2021 10:25 am 
Offline
User avatar

Joined: Mon Apr 06, 2020 1:09 pm
Posts: 112
думаю, когда формат уже устаканится, можно попробовать внедрить поддержку данного формата в ядро.

_________________
The best way to predict the future is to create it.


Top
   
PostPosted: Thu Feb 25, 2021 9:33 am 
Offline
User avatar

Joined: Wed Mar 18, 2015 8:22 am
Posts: 341
На каких языках программирования можно писать программы с использованием формата kx?

_________________
Я один из тех, кто ещё не программист, но уже не новичок.
Редактор в группе "KolibriOS - официальная группа".


Top
   
PostPosted: Thu Feb 25, 2021 11:36 am 
Offline

Joined: Mon Sep 07, 2020 7:09 pm
Posts: 411
На любом ведь
Главное чтобы компилер смог в этот формат


Top
   
PostPosted: Fri Feb 26, 2021 1:50 pm 
Offline
User avatar

Joined: Mon Nov 19, 2012 5:22 pm
Posts: 471
maxcodehack wrote:
На любом ведь
Главное чтобы компилер смог в этот формат

1. Вот в том и проблема. Ассемблеры. Вроде всё. Потому и первоначальный заголовок Menuet не очень. С-- научили, местные С компилеры тоже. Из pascal и C (msvc или gcc) делали ухищрения в линкерах. Для паскаля вроде прога специальная была из виндового PE делать.
2. Динамические библиотеки, линковка, как дела с этим? Этот формат для библиотек годится?
3. Ресурсы предполагаются? Или хотя бы можно ли будет хранить иконку приложения в стандартном для всей Кос месте?

_________________
Чем больше сыра, тем больше в нём дыр. Чем больше дыр, тем меньше в нём собственно сыра. Значит, чем больше сыра, тем меньше сыра!


Top
   
PostPosted: Fri Feb 26, 2021 10:32 pm 
Offline
User avatar

Joined: Tue Jan 26, 2021 3:38 am
Posts: 40
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 практически нет. Также появятся возможность расширенного описания программы (версия, автор, дата сборки, описание и т.д.). Возможно ещё что-то будет, хотя лишних вещей в формате тоже не хочется.


Top
   
PostPosted: Tue Mar 02, 2021 4:51 pm 
Offline
User avatar

Joined: Thu Aug 04, 2016 10:43 am
Posts: 45
Kenshin, а разве код лоадера не самая информативная часть после непосредственно описания спецификации?
правильно ли я понимаю, что какой то формат тестируется вначале лоадером, и лишь потом помещается в ядро. управление памятью в пространстве адресов процесса вещь интересная. Она может быть реализована в юзермод лоадером?
А еще как загрузка библиотек стыкуется с загрузкой их системой.
Имею в виду что система загружает библиотеку в память однажды, НО...
НО если код библиотеки не адресонезависимый то в процесс загружается свой экземпляр библиотеки...
это то делает система, понятно.
Но данные и код в библиотеке адресуются процессами по разному: данные в реальной памяти полностью разделяемы по разным адресам виртуальной памяти каждого процесса, а код наоборот: для каждого виртуального адреса создается свой экземпляр в реальной памяти релоцированный на этот адрес, в пределах одного виртуального адреса разных процессов в реальной памяти создается только 1 его экземпляр.
Т.е. список подгруженных библиотек можно также на уровне лоадера хранить, а не на уровне ядра? И так вот с памятью тоже лоадер может играться?


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 21 posts ]  Go to page 1 2 Next

All times are UTC+03:00


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Limited