Формат объектных файлов

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Формат объектных файлов

Сообщение XProger » 22.12.2008 19:27:17

Всем привет.
Задача стоит в "выдёргивании" скомпилированного кода из *.o файлов, с целью его последующего самостоятельного выполнения.
Не подскажите, где можно почитать о его структуре?
Аватара пользователя
XProger
новенький
 
Сообщения: 44
Зарегистрирован: 13.08.2007 02:52:28
Откуда: Москва

Re: Формат объектных файлов

Сообщение vital » 22.12.2008 21:36:59

http://www.opennet.ru/soft/ruprog/coff.txt
http://www.rsdn.ru/article/baseserv/pe_coff.xml
Если не секрет, для чего это понадобилось?
vital
новенький
 
Сообщения: 86
Зарегистрирован: 17.10.2007 14:52:59

Re: Формат объектных файлов

Сообщение bw » 22.12.2008 21:47:40

Зависит от целевой платформы, кроме COFF это может быть и ELF.

..bw
Аватара пользователя
bw
постоялец
 
Сообщения: 359
Зарегистрирован: 01.12.2005 11:36:23
Откуда: Усть-Илимск

Re: Формат объектных файлов

Сообщение shade » 22.12.2008 23:49:14

Я как-то писал пару программулек:
http://forum.shamangrad.net/viewtopic.php?f=18&t=284
http://forum.shamangrad.net/viewtopic.php?f=18&t=285

может поможет
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Re: Формат объектных файлов

Сообщение XProger » 23.12.2008 00:29:15

vital,
игровой многопользовательский сервер помимо постоянной нагрузки будет часто запускать скрипты, хотелось бы максимально выиграть в этом месте по производительности. А т.к. FPC компилирует код с космической скоростью, посчитал оптимальным решением использовать именно его в качестве "языка скриптов". Компиляция в dll не устраивает тем, что таких dll будет более 1000 и держать их всех в памяти неразумно, да и хранить на диске также неразумно т.к. стараемся минимизировать обращения к диску.
Всякие Lua, Python и прочую дребедень использовать на многопользовательском сервере имхо неразумно, когда под рукой есть такой инструмент как FPC.

bw,
Машинный код содержащийся в *.o скомпилированный win32 версией компилятора может быть запущен на *nix системе, при условии того, что не юзает API?

shade,
Вот это да! Пасиба! )

Пойду изучать...
Аватара пользователя
XProger
новенький
 
Сообщения: 44
Зарегистрирован: 13.08.2007 02:52:28
Откуда: Москва

Re: Формат объектных файлов

Сообщение bw » 23.12.2008 01:43:36

Вообще-то объект, полученный при компиляции модуля и приложения в FPC не получится использовать как есть. Такой объект будет иметь внешние ссылки, как минимум на system.o (для винды это еще и sysinitpas.o), а скорее всего придется "подключать" и такие объекты, как objects.o, objpas.o и т.д. Фактически, ты будешь вынужден делать линковку, а это довольно дорогая процедура, и релокации в загруженных секциях, ну и не забудь, что может потребоваться (если ты используешь виндовый RTL, то обязательно потребуется) импорт DLL, прописанных в коде используемых модулей (это, как минимум, kernel32.dll). Ну и т.д. :-). Т.е. сложность возрастает неимоверно, сответственно возрастает процент возможных ошибок и вероятность падения сервера.

> Машинный код содержащийся в *.o скомпилированный win32 версией компилятора может быть запущен на *nix системе, при условии того, что не юзает API?
Да, когда ты разрешишь все зависимости этого объекта (читать выше). Код, содержащийся в COFF и ELF ничем не отличается, просто используются разные контейнеры.

p.s. Я использую дребедень Python ;-).

..bw
Аватара пользователя
bw
постоялец
 
Сообщения: 359
Зарегистрирован: 01.12.2005 11:36:23
Откуда: Усть-Илимск

Re: Формат объектных файлов

Сообщение shade » 23.12.2008 01:47:25

Сайт, старый и заброшеный (zolotov.h14.ru), жаль если добро на нём лежащее пропадёт.

Зарегистрировал проект на Шаманграде и добавил исходники в svn

Проект: http://shamangrad.net/project.php?act=v ... =codetools
svn: svn://svn.shamangrad.net/codetools или http://svn.shamangrad.net/codetools/
Багтреккер: http://shamangrad.net/report.php?act=list&prj=codetools
Архивы, релизы: http://download.shamangrad.net/codetools/

Хотя врядли буду в ближайщее время что-то дорабатывать или исправлять ошибки...

Фактически, ты будешь вынужден делать линковку, а это довольно дорогая процедура, и релокации в загруженных секциях, ну и не забудь, что может потребоваться (если ты используешь виндовый RTL, то обязательно потребуется) импорт DLL

Линковка и релокации не дорогая процедура, это просто ld тормоз...
А вот в Delphi на сколько я помню очень быстрый и компилятор и компоновщик - сколько кодил на Delphi не помню чтобы я когда-нибудь задумывался о времени компиляции/компоновки...

Добавлено спустя 6 минут 32 секунды:
XProger
Удачи!
Будут вопросы по линковке и релокациям, можешь задавать ;)

Кстати, чтоб знал, есть две модификации COFF, одна так сказать оригинальная (используется в Linux), другая от Microsoft (используется под Windows) - разница, как раз в релокациях.
Причем версия Windows-версия FPC производит MS-модификацию, а Linux-версия оригинальную.

Я в link вроде делал поддержку обоих форматов.

PS: врочем писал давно, так что отдельные факты могу путать...
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Re: Формат объектных файлов

Сообщение XProger » 23.12.2008 02:03:11

bw,
проблема внешних ссылок ясна как день. Поэтому никакого RTL и тем более стороннего API код использовать не будет, к этому мы морально готовы )
shade,
думаю, вопросов будет немеряно. А пока изучаю и вникаю. Спасибо за код и инфу )

Сейчас лишь вижу проблему переназначения адресов call инструкций, это видимо то что делает ОС при загрузке dll в память... и моих знаний пока не достаточно чтобы понять как оно там устроено. Или же call адрес постоянен и не меняется от запуска к запуску, тогда не ясно относительно чего он отсчитывается и есть ли необходимость переназначать call адреса при "выдёргивании" кода из объектных файлов :\
Аватара пользователя
XProger
новенький
 
Сообщения: 44
Зарегистрирован: 13.08.2007 02:52:28
Откуда: Москва

Re: Формат объектных файлов

Сообщение shade » 23.12.2008 02:16:49

В принципе в моих модулях (по крайней мере в link) реализованы классы для работы с объектными файлами и в этих классах уже реализована релокация.

Возможно просто прокатит такой фокус:
1. загрузить все необходимые объектыне модули
2. для каждого объекта узнать адрес блока с данными
3. для каждого объекта вызывать метод Relocate указав ему адрес из п2.
4. отредактировать связи (тут уже не помню как, надо смотерть код компоновщика)

По сути, нужно откомпоновать объекты прям в памяти - это фактически и делает компоновщик, но результат записывает в файл.
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Re: Формат объектных файлов

Сообщение XProger » 23.12.2008 02:25:21

shade,
А если объектный файл абсолютно независим (не использует API и RTL/CRT), то такие фокусы не понадобятся? Релоки нужно учитывать только при взаимосвязях модулей? )
Аватара пользователя
XProger
новенький
 
Сообщения: 44
Зарегистрирован: 13.08.2007 02:52:28
Откуда: Москва

Re: Формат объектных файлов

Сообщение shade » 23.12.2008 03:59:41

Уверен, что ваши объектные файлы будут зависеть от какого-либо API - и это НЕ проблема :wink:

Не удержался и попробовал немного модифицировать исходники, чтобы динамически загружать и выполнять объектные модули.

Код: Выделить всё
alex@notebook:~/prj/codetools/trunk/link> svn info
Path: .
URL: svn://svn.shamangrad.net/codetools/trunk/link
Repository Root: svn://svn.shamangrad.net/codetools
Repository UUID: 8795bce7-64d0-dd11-9702-0030485a0448
Revision: 5
Node Kind: directory
Schedule: normal
Last Changed Author: shade
Last Changed Rev: 5
Last Changed Date: 2008-12-23 02:55:10 +0300 (Втр, 23 Дек 2008)

alex@notebook:~/prj/codetools/trunk/link> ./test.sh
compile dload...
Free Pascal Compiler version 2.2.2 [2008/10/25] for i386
Copyright (c) 1993-2008 by Florian Klaempfl
Target OS: Linux for i386
Compiling dload.pas
Compiling sys.pas
Compiling soff.pas
Compiling mylink.pas
Compiling coff.pas
Compiling ar.pas
Compiling aout.pas
Linking dload
3180 lines compiled, 0.3 sec
compile hello.pas
Free Pascal Compiler version 2.2.2 [2008/10/25] for i386
Copyright (c) 1993-2008 by Florian Klaempfl
Target OS: Linux for i386
Compiling hello.pas
Assembling hello
20 lines compiled, 0.0 sec
run dload...
dload 0.1.0, (c) 2008, zolotov-alex@shamangrad.net

loading hello.o
mark sections...
relocate...
resolve...
run...

hello world :)

ok
alex@notebook:~/prj/codetools/trunk/link>


test.sh:
Код: Выделить всё
echo compile dload...
fpc -Mobjfpc dload.pas

echo compile hello.pas
fpc -al -Anasmobj hello.pas
nasm -f coff hello.s -o hello.o

echo run dload...
./dload -entry HELLO_MAIN hello.o


Осталось отрефакторить :D
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Re: Формат объектных файлов

Сообщение XProger » 23.12.2008 04:09:00

Вах! Крут, теперь верю в то, что это действительно реально )

upd: правда кода в этом линкере просто жуть... попробую сделать чего попроще )
Аватара пользователя
XProger
новенький
 
Сообщения: 44
Зарегистрирован: 13.08.2007 02:52:28
Откуда: Москва

Re: Формат объектных файлов

Сообщение bw » 23.12.2008 04:51:56

Не понятно, как этот код работает :-).
В hello.o отсутствует реализация PrintLn/WriteLn.
XProger, RTL это значительно больше чем тот же WriteLn и GetMem. Это любые манипуляции со строками, динамическими списками, вообщем это туева хуча внешних зависимостей (ну, может, я немного преувеличиваю :-), вот я и удивляюсь, как без всего этого hello.o заработал. Не хочу тебя отпугивать, всё это можно реализовать, но вот достигнешь ли ты в результате первоначальной цели, не получится ли так, что такой объект будет грузиться в 10 дольше обычной DLL?

..bw
Аватара пользователя
bw
постоялец
 
Сообщения: 359
Зарегистрирован: 01.12.2005 11:36:23
Откуда: Усть-Илимск

Re: Формат объектных файлов

Сообщение XProger » 23.12.2008 05:00:42

bw,
я в курсе в каких местах явно/неявно происходит вызов RTL функционала. От RTL зависеть не буду, хотя shade наглядно показал как можно "подменить" этот RTL функционал при переназначении call адресов, но мне бы пока независимый код выдрать и запустить )
А дольше чем dll грузиться не может по определению. Кода ведь меньше )
Аватара пользователя
XProger
новенький
 
Сообщения: 44
Зарегистрирован: 13.08.2007 02:52:28
Откуда: Москва

Re: Формат объектных файлов

Сообщение shade » 23.12.2008 13:24:57

bw писал(а):Не понятно, как этот код работает :-).
В hello.o отсутствует реализация PrintLn/WriteLn.

См. внимательно uses и sys.pas - его подключает и hello.pas и dload.pas ;)
Я его сделать просто чтобы сократить код, но аналогично можно заюзать и сам system в ключая все его функции ;)

dload
1. загружает указанные объектные файлы
2. добавляет символ println (эту часть можно и автоматизировать, чтобы вручную все символы не прописывать)
Код: Выделить всё
  println_sys := TSymbol.Create(nil);
  println_sys.Name := 'SYS_PRINTLN$ANSISTRING';
  println_sys.Offset := Longword( @println );
  println_sys.SymType := SOFF_EXTERN;
  println_sys.Section := dummy;
  Linker.Globals.Add(println_sys);

3. отмечает секции которые нужны для компоновки
4. делает релокацию отмеченых секций
5. редактирует связи отмеченых секций, в том числе и связь на sys.println
6. находит точку входа (которая указана параметром -entry)
7. вызывает точку входа, управление попадает в загруженый объектный файл
8. там вызывается функция sys.println, которая реализована в dload, таким образом управление временно обратно передается в dload
9. println выводит строку
10. println возращает управление и мы снова в hello.o
11. hello.main возращает управление в dload
12. dload завершает свою работу

:mrgreen:

Добавлено спустя 43 минуты 43 секунды:
XProger писал(а):А если объектный файл абсолютно независим (не использует API и RTL/CRT), то такие фокусы не понадобятся? Релоки нужно учитывать только при взаимосвязях модулей? )

Релокация и редактирование связей нужны в любом случае.

Релокация нужна, т.к. заранее не известно куда будет загружен код, исколючение может составлять позициононезависимый код (PIC) - некоторые компиляторы умеют генерить такой код, FPC не исколючение:
Код: Выделить всё
alex@notebook:~> fpc -h | grep PIC
      -Cg        Generate PIC code
  -fPIC  Same as -Cg
alex@notebook:~>

Отмечу, что для PIC таблица релокаций по идее должна быть пустой, а следовательно в коде релокации будет просто пустой цикл. Так что совсем не обязательно переписывать код - тогда будет работать и PIC и не PIC. Точно не знаю, но PIC вроде быть менее производительным, чем обычный - так что лучше один раз произвести небольшую релокацию, чем в цикле крутить не эффективный PIC.

Редактирование связей нужны для настройки ссылок между секциями в объектом файле (их может быть несколько, .data, .bss, .text), для связи нескольких объектных файлов и для связи с API.

Отредактирования связей действительно можно отказаться, если ваш код действительно не экспортирует никаких символов (например, на вход подается объект, а в объекте вызываются только виртуальные методы), но для этого нужно педварительно обработать объектный модуль - нужно все его секции объединить в одну. Так можно один раз "прелинковать" объектный модуль, созранить в файл, а потом при выполнении просто подгружать этот подготовленый модуль и делать только релокации.

Но я бы не советовал так париться, релокации и редактирования связей не такие дорогие операции как некоторые думают. Есть таблица релокаций и таблица символов. Алгоритм релокации линеен - один цикл по таблице релокации и алгоритм редактирования связей тоже линеен - тоже один цикл по таблице символов. Релокации и редактированию связей подвергается только ссылки, а их не так уж и много относительно остального кода.

Добавлено спустя 3 часа 36 минут 42 секунды:
Немного отрефакторил модули и переписал пример.

Получилось вот что:
Код: Выделить всё
  // Создаем компоновщик
  Linker := TRuntimeLinker.Create;
 
  try
    // Используем оригинальный COFF
    Linker.UseMSCOFF := false;
   
    // подключаем API
    api := Linker.Modules.Add.Sections.Add;
    api.AddGlobal('SYS_PRINTLN$ANSISTRING', @println);
    api.AddGlobal('FPC_PUSHEXCEPTADDR', @FPC_PUSHEXCEPTADDR);
    api.AddGlobal('FPC_SETJMP', @FPC_SETJMP);
    api.AddGlobal('FPC_POPADDRSTACK', @FPC_POPADDRSTACK);
    api.AddGlobal('FPC_RERAISE', @FPC_RERAISE);
    api.AddGlobal('FPC_ANSISTR_DECR_REF', @FPC_ANSISTR_DECR_REF);
    api.AddGlobal('fpc_shortstr_to_ansistr', @fpc_shortstr_to_ansistr);
    api.AddGlobal('SYSTEM_TOBJECT_$__CLASSNAME$$SHORTSTRING', @TObject.ClassName);
   
    // Загружаем объектный модуль
    mod_hello := Linker.LoadFile('hello.o');
   
    // Компонуем
    Linker.Link;
   
    // Выполняем код
    Linker.Execute('HELLO_MAIN');
   
    // выгрузить mod_hello
    Linker.Modules.Remove(mod_hello);
   
    // загрузить другой модуль 'showclass.o'
    mod_showclass := Linker.LoadFile('showclass.o');
   
    // перекомпонуем
    Linker.Link;
   
    Linker.Execute('SHOWCLASS_SHOWCLASSNAME$TOBJECT', Linker);
    Linker.Execute('SHOWCLASS_SHOWCLASSNAME$TOBJECT', mod_showclass);
   
  finally
    // Почистить мусор
    Linker.Free;
  end;


PS: полный пример см. в svn
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

След.

Вернуться в Free Pascal Compiler

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

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

Рейтинг@Mail.ru