Вобщем назрело.. Видимо пора по немногу делиться идеями, выносить их на обсуждение, т.к. уже силами одного мозга не получается придумать чтото толковое и стоящее.
Задача такая:Условие Как известно код и данные жестко зависимы между собой. Т.е. при компиляции исходников мы получаем бинарник с жестко прописанными ссылками на данные. Т.е. например такой код:
Код:
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. Возможно есть какой либо еще вариант о котором я не знаю.Не исключаю, что существует более эффективный алгоритм.
В общем если есть мысли или идеи прошу высказаться.