Автор: lonesome [TSH/Digital Daemons]
Дата: 30.10.2003
Раздел: Разработка ОС
Сегодня в номере:
Доброго!
В связи с тем, что мы в последнее время не изучаем процесс написания ОС "по порядку", а уже углубляемся в различные аспекты этого занятия (а значит для меня нет большой разницы, чему посвящать дальнейшие выпуски), предлагаю вам, как подписчикам, самостоятельно решить, какие темы вам хотелось бы увидеть в следующих выпусках. Посему - небольшое голосование :)
Формат ELF - далеко не единственный формат исполняемых файлов. Почему же мы уделяем такое внимание именно ему? Дело в том, что он во первых очень логичен, во вторых очень прост, а в третьих обладает достаточной гибкостью и расширяемостью, благодаря чему он и стал настолько распространен (в настоящий момент это самый популярный формат для UNIX-подобных операционных систем на платформе i386. В ELF может быть и ядро системы и приложения (как в случае с Tyros/Neutronix)
Существует как 32-битный, так и 64-битный ELF-формат. Нас интересует в первую очередь первый вариант.
Формат имеет три основные разновидности:
Как вы уже догадались, ELF определяется заголовком, формат которого мы рассмотрим позже (наша основная задача сейчас - понять основные принципы работы с ELF-файлами). Помимо прочих данных, заголовок содержит адрес таблицы программных секций (Program Header Table) и таблицы объектных секций (Section Header Table)
Программные секции необходимы для исполняемого файла, объектные, соответственно - для объектного.
Вообще, ELF-файл можно как раз представить как совокупность его секций. К примеру, обычный исполняемый файл в простейшем случае может содержать две программных секции - секцию кода и секцию данных.
Для загрузки в память исполняемого файла (другими словами - для создания образа процесса в памяти) необходимо загрузить в память все его программные секции, на которых стоит флаг LOAD и выделить память для тех секций, на которых стоит ALLOC (такой к примеру будет секция неинициализированных данных - .bss)
Каждая программная секция имеет в своем заголовке адрес LMA (Load Memory Address) - адрес загрузки в память. По этому адресу секция должна находится в момент выполнения (как правило, это означает, что по этому адресу она была скомпонована). Фактически это означает, что таблицы страниц для процесса, образ которого мы грузим, должны быть подготовлены соответствующим образом. Если же мы загружаем ядро системы (а значит, страничная адресация еще не включена), то секции должны физически находится по адресам LMA.
Итак, алгоритм загрузки ядра формата ELF в память таков: из заголовка извлекаем адрес таблицы программных секций, затем по очереди анализируем все секции в этой таблице, если LOAD - то копируем секцию в память по указанному в ее заголовке адресу LMA. Передаем управление на точку входа. Готово!
Если тема заинтересовала - пишите - тогда в следующий раз рассмотрим более подробно этот процесс и выполняющий эти действия код.
На этом, уважаемые подписчики, я прощаюсь, и как всегда напоминаю, что:
lonesome AT lowlevel DOT ru - мой почтовый ящик, который с нетерпением ждет ваших писем в любое время дня и ночи