OSDev

для всех
Текущее время: 30 апр 2024, 07:28

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 12 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Хранение кода и данных в памяти
СообщениеДобавлено: 12 янв 2011, 14:47 

Зарегистрирован: 30 янв 2010, 19:44
Сообщения: 63
Вобщем назрело.. Видимо пора по немногу делиться идеями, выносить их на обсуждение, т.к. уже силами одного мозга не получается придумать чтото толковое и стоящее.

Задача такая:
Условие Как известно код и данные жестко зависимы между собой. Т.е. при компиляции исходников мы получаем бинарник с жестко прописанными ссылками на данные. Т.е. например такой код:
Код:
string1 db 'Test',0
...
mov eax, string1
mov cl, [string1][0]

будет скомпилирован в процессорные коды в виде жетких ссылок на эту переменную 'string1' относительно начала этого бинарника (другие варианты смотри ниже).
Задача Так вот требуется реализовать некий алгоритм/механизм при котором будет возможность переместить данные и/или код в любое место памяти обеспечив при этом, нормальное выполнение кода.

Варианты решения:
1. Использование объектных файлов.
Существует некий стандарт как бы "прекомпилированных" файлов, который еще не является кодом готовым к выполнению, но уже и не является исходником. Если утрировать, то это бинарник, со скомпилированным кодом в котором есть секция непосредственно машинных кодов и секция указателей на места в этом коде где используется прямые указатели, ну и секция данных. Т.е. в нашем случае будут указатели на значения в командах mov.
В этом варианте есть свои плюсы и минусы.
Плюсы:
- очень распространенный стандарт. практически любой компилятор может создать такой файл
Минусы:
- при перемещении нужно изменять данные указатели в этом коде. т.е. менять данные в сегменте кода
- данными управляет исполняемый код, т.е. нельзя контролировать ядром тип данных или например, можно ли переместить данные, или данные только для чтения и т.д.
2. Вариант который я пытаюсь реализовать.
Весь код компилируется без прямых указателей, т.е. чтобы получить символ в строке, сначала необходимо получить его реальное местоположение в памяти. Структура получается примерно такой:
    - Есть код, который можно разместить в любое место памяти.
    - Есть указатель на таблицу указателей данных (назовем ее RVA_table). Он хранится в регистре ESI при выполнении этого кода.
    - Есть таблица указателей на структуры переменных (VAR_record). Очень простая, 4 байта адрес в памяти.
    - Есть структура (record/struct) описания переменной, которая хранит состояние этой записи, ее тип, размер данных и указатель на сами данные.
При работе получается такой алгоритм:
    - получаем смещение переменной в таблице RVA_table
    - прибавляем местоположение этой таблицы из регистра ESI
    - получаем местоположение записи VAR_record в памяти из таблицы RVA_table
    - после этого из записи VAR_record мы можем получить реальное местоположение описанных данных в памяти
Плюсы:
- исполняемый код неизменяем, т.е. можно отслеживать целостность кода
- один и тот же код может работать с разными экземплярами данных
- данные располагаются в памяти независимо от кода и могут быть легко перемещены при необходимости
Минусы:
- как мне кажется этот вариант будет требовать больше процессорного времени на получение ссылок на реальные данные
3. Возможно есть какой либо еще вариант о котором я не знаю.
Не исключаю, что существует более эффективный алгоритм.

В общем если есть мысли или идеи прошу высказаться.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Хранение кода и данных в памяти
СообщениеДобавлено: 12 янв 2011, 16:28 

Зарегистрирован: 11 янв 2011, 22:17
Сообщения: 21
qeos, релокейшины на мой взгляд самое удачное решение проблемы.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Хранение кода и данных в памяти
СообщениеДобавлено: 12 янв 2011, 17:03 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
qeos, динамические вычисления адресов - это усложнение кода и потеря производительности. В стандартных форматах принято корректировать бинарный образ программы непосредственно в оперативной памяти перед запуском. Это называется настройкой адресов. В результате, на стадии выполнения, все адреса уже настроены на рабочий адрес, "как буд-то так и было".


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Хранение кода и данных в памяти
СообщениеДобавлено: 12 янв 2011, 17:12 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Обычно наиболее критичным является именно время исполнения, поэтому не стоит делать что-то заведомо существенно более медленное. Кроме того, незачем опасаться за целостность кода в памяти, надо лишь обеспечивать, чтобы его не мог модифицировать кто попало.

В общем, думаю, целесообразно использовать формат исполняемых модулей, подобный формату объектных: в нём должна сохраняться вся информация о настройке на адрес загрузки, причём не модуля в целом (это обеспечивает и виндузовый ПЕ ЕХЕ, если принудительно не убивать таблицу перемещений, как это обычно делается), а отдельных программных секций (того, что в МАСМе именуется сегментами, но что не является сегментами в смысле архитектуры ИА-32; вроде в ФАСМе они секциями и именуются, но этого я не знаю, поскольку им не пользуюсь). Настройка в любом случае выполняется один раз -- при загрузке модуля в память, и осуществляет это код оси, который имеет полное право модифицировать всю память, в т.ч. и занимаемую кодом задач.

Что касается адресации, опираясь на базовый адрес в одном из регистров, то эта идея тоже имеет полное право на существование; более того, существует немало процессорных архитектур, где иное попросту невозможно (например, ИБМовские мэйнфреймы или АРМ). Тут главная проблема в том, что у ИА-32 мало регистров, да к тому же все они имеют специальное назначение. Например, заняв под базу ЕСИ, мы автоматически лишаемся возможности использовать строковые команды. Именно поэтому разработчики Винды сделали финт ушами и используют ФС не как сегментный регистр, а как базовый (фактически, а не формально -- в чисто формальном смысле он, конечно, остался сегментным регистром): для использования в качестве РОНа он всё равно непригоден, а вот для хранения в нём базы чего-нибудь -- очень даже. Собственно, это сохраняется и в 64-разрядном режиме ИА-32, только там ФС и ГС уже официально стали базовыми, поскольку сегментация умерла.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Хранение кода и данных в памяти
СообщениеДобавлено: 13 янв 2011, 01:05 

Зарегистрирован: 30 янв 2010, 19:44
Сообщения: 63
SII писал(а):
поэтому разработчики Винды сделали финт ушами


Об этом я совершенно не знал. Действительно можно использовать эти сегментные регистры! А я еще думал зачем их так много.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Хранение кода и данных в памяти
СообщениеДобавлено: 13 янв 2011, 16:56 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
Релокация и позиционно-независимый код (можно и совместить) - это единственно возможные современные решения на IA32/AMD64 - от сегментации уже практически все отказались. У меня раньше дрова на основе сегментации работали. С введением релокации все стало значительно проще. В линуксе есть модули на основе позиционно-независимого кода. DSO вроде. Для их создания нужно просто указать спец. ключ компиляции. В AMD64 вообще все просто, т.к. появилась относительная адресация при обращении к данным (через rip). Объектники по сути используют механиз релокации, только помимо всего прочего содержат много бесполезной инфы. Я сначала хотел для дров использовать Object ELF, но потом это понят и сделал свой формат на основе релокации.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Хранение кода и данных в памяти
СообщениеДобавлено: 13 янв 2011, 17:28 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
А тут речь не о сегментации как таковой, а об использовании сегментных регистров качестве базовых. Сегментация -- это когда память разделена на, вообще говоря, неперекрывающиеся сегменты, доступ к которым осуществляется через сегментные регистры. А здесь, хотя технически используются сегментные регистры, логически применяется обычная адресация относительно базы. Например, сегменты CS, SS, DS и ES отображены на адрес 0, сегмент GS -- на адрес 1000, а сегмент FS -- на адрес 2000. Тогда команда mov eax, gs:0 будет эквивалентна последовательности mov esi, 1000; mov eax, [esi]. Единственный недостаток такой базовой адресации по сравнению с обычной -- это невозможность изменить базу без помощи ОС (поскольку нужно менять соответствующий дескриптор сегмента, а не просто грузить в сегментный регистр нужное значение).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Хранение кода и данных в памяти
СообщениеДобавлено: 13 янв 2011, 19:44 

Зарегистрирован: 30 янв 2010, 19:44
Сообщения: 63
phantom-84 писал(а):
Релокация и позиционно-независимый код (можно и совместить) - это единственно возможные современные решения на IA32/AMD64 - от сегментации уже практически все отказались. У меня раньше дрова на основе сегментации работали. С введением релокации все стало значительно проще. В линуксе есть модули на основе позиционно-независимого кода. DSO вроде. Для их создания нужно просто указать спец. ключ компиляции. В AMD64 вообще все просто, т.к. появилась относительная адресация при обращении к данным (через rip). Объектники по сути используют механиз релокации, только помимо всего прочего содержат много бесполезной инфы. Я сначала хотел для дров использовать Object ELF, но потом это понят и сделал свой формат на основе релокации.

вот, вот.. что-то похожее на то, что мне требуется..
использование %rip не совсем то что мне нужно. как описано в http://www.x86-64.org/documentation/assembly.html:
Код:
  movl $0x1, 0x10(%rip)
will store the value 0x1 10 bytes after the end of the instruction.

т.е. задача наполовину решена: 1 код + 1 вариант данных = 1 объект. У меня идея реализовать выполнение кода (по сути код объекта) для разных данных. Т.е. несколько одинаковых объектов будут иметь разные пространства данных (1 код + много вариантов данных = много объектов). В связи с этим можно строить массивы объектов без ущерба ресурсам.

Кстати, интересно узнать что за формат на основе релокации. Что изменил? что добавил? в чем преимущество?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Хранение кода и данных в памяти
СообщениеДобавлено: 14 янв 2011, 11:46 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
Цитата:
Единственный недостаток такой базовой адресации по сравнению с обычной -- это невозможность изменить базу без помощи ОС (поскольку нужно менять соответствующий дескриптор сегмента, а не просто грузить в сегментный регистр нужное значение).
А каждый раз менять базу при помощи ОС нормально? Поэтому нужно этим пользоваться редко, а лучше вообще один раз для обеспечения сегментации при обращении к данному модулю извне (если этого не делает само ядро), а еще лучше вообще не пользоваться.

Цитата:
использование %rip не совсем то что мне нужно.
Компилятор тебе нормальный нужен. Им должен поддерживаться спец. ключ компиляции, уточняющая директива для группы команд/отдельной команды или просто соглашение об адресации. Например, когда я на fasm'е в длинном режиме пишу mov byte [var],1, я знаю, что будет использоваться относительная адресация (относительно rip). А если мне нужно использовать абсолютную адресацию, то я должен написать mov byte [dword var],1.

Цитата:
Кстати, интересно узнать что за формат на основе релокации. Что изменил? что добавил? в чем преимущество?
Формат предельно прост. Для драйверов я сохраняю одну единственную секцию с кодом и данными (вообще формат позволяет сохранять в файле две секции) плюс таблицу релокации.
Модули ядра в формате DEF v4/a
Модули ядра в формате DEF v3


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Хранение кода и данных в памяти
СообщениеДобавлено: 14 янв 2011, 17:02 

Зарегистрирован: 16 фев 2010, 22:03
Сообщения: 101
На мой взгляд самое лучше - пи код. Поскольку релоки могут занимать много места и требуют усложнения загрузчика.
Но делать таблицу переменных считаю не рациональным - достаточно одного базового адреса, а смещения в этом блоке уже жёстко заданы в программе, хотя это не мешает разместить данные в любом месте памяти указав другую базу. Единственное ограничение в 32-битном режиме придётся забрать один регистр общего назначения (кстати, лучше не ESI, а EBX, чтобы не лишать программиста строковых команд). А вот в long mode пи код делать благодаря адресации относительно RIP можно очень легко. И самое главное практически без потери производительности и отнимания регистров у программиста (RIP не получится всё равно использовать как регистр общего назначения). В ассемблере fasm например единственное, что придётся сделать - загружать адрес в регистр не с помощью mov rax, label, а с помощью lea rax, [label]. Таким образом загрузчик исполняемых файлов может быть предельно простым, но потерь производительности как в случае использования таблицы адресов переменных не будет. Да и все более менее нормальные компиляторы умеют генерировать пи код. Как 32-битный, так и 64-битный.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 12 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB