Alex
|
veteran
|
|
|
|
Рег.: 16.10.2002
|
Сообщений: 1940
|
Из: ЮЗАО
|
Рейтинг: 18
|
|
сборка динамических библиотек из Ocaml
05.06.2007 16:05
|
|
|
Нужно собрать динамическую библиотеку (.so-файл) из исходников на языке OCaml. Требуется обеспечить работоспособность на x86 и x86-64. Все делается в соответствии с руководством http://caml.inria.fr/pub/docs/manual-ocaml/manual032.html Однако, при сборке выдается ошибка: ld: caml_lib.o: relocation R_X86_64_32S against `caml_curry2_1' can not be used when making a shared object; recompile with -fPIC Объектный файл caml_lib.o создается с помощью ocamlopt, который компилирует программу в код на ассемблере, а затем вызывает ассемблер as. Если с помощью опции -S попросить его оставить временный .S-файл, то видно, что в нем попадаются команды типа call <имя_функции>, которые приводят к relocation R_X86_64_32S, которые не могут быть в .so-файлах. Компилятор C при генерации ассемблерных файлов вставляет специальные указания, например, call <имя_функции>@PLT, которые приводят к другому типу relocation: R_X86_64_PLT32 (для кода) и R_X86_64_GOTPCREL (для данных).
Кто-нибудь сталкивался с этой проблемой? Или, может быть, у кого-то есть идеи, как это решить?
Хотелось бы понять, в чем разница между разными типами relocation.
|
|
Alex
|
veteran
|
|
|
|
Рег.: 16.10.2002
|
Сообщений: 1940
|
Из: ЮЗАО
|
Рейтинг: 18
|
|
Re: сборка динамических библиотек из Ocaml
[re: Alex]
05.06.2007 21:02
|
|
|
С Haskell еще лучше:
code:
$ cat adder.hs
module Adder where
f :: IO ()
f = putStrLn "hello"
$ ghc -c -fPIC adder.hs
ghc-6.6.1: panic! (the 'impossible' happened)
(GHC version 6.6.1 for x86_64-unknown-linux):
initializePicBase
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
Читаем сырцы:
code:
initializePicBase :: Reg -> [NatCmmTop] -> NatM [NatCmmTop]
#if darwin_TARGET_OS
....
#elif powerpc_TARGET_ARCH && linux_TARGET_OS
....
#elif i386_TARGET_ARCH && linux_TARGET_OS
....
#else
initializePicBase picReg proc = panic "initializePicBase"
#endif
x86_64_TARGET_ARCH отсутствует напрочь (вне зависимости от _TARGET_OS)
|
|
Alex
|
veteran
|
|
|
|
Рег.: 16.10.2002
|
Сообщений: 1940
|
Из: ЮЗАО
|
Рейтинг: 18
|
|
Re: сборка динамических библиотек из Ocaml
[re: Alex]
06.06.2007 10:30
|
|
|
up! чего все молчат-то?
|
|
__No__
|
|
|
|
|
Рег.: 17.01.2005
|
Сообщений: 21059
|
Из: Внутренняя Монголия
|
Рейтинг: 6312
|
|
Re: сборка динамических библиотек из Ocaml
[re: Alex]
06.06.2007 11:34
|
|
|
|
gadfather
|
Carpal Tunnel
|
|
|
|
Рег.: 05.11.2003
|
Сообщений: 47302
|
Из: пл. Гагарина
|
Рейтинг: 16961
|
|
Re: сборка динамических библиотек из Ocaml
[re: Alex]
06.06.2007 11:53
|
|
|
напиши скрипт, который call будет заменять на правильные команды 
|
You can't always get what you want |
|
Alex
|
veteran
|
|
|
|
Рег.: 16.10.2002
|
Сообщений: 1940
|
Из: ЮЗАО
|
Рейтинг: 18
|
|
Re: сборка динамических библиотек из Ocaml
[re: gadfather]
06.06.2007 12:22
|
|
|
> напиши скрипт, который call будет заменять на правильные команды Не совсем, понимаю как правильно заменять. Попробовал в паре мест заменить func на func@PLT. Собралось. Но при запуске падает в segfault. По всей видимости, такой простой замены не хватает. Может кто-то объяснит, как работают relocation-ы, и что делает ассемблер, когда обрабатывает команду 'call func@PLT' ?
|
|
Nine17
|
Furia Roja
|
|
|
|
Рег.: 26.06.2003
|
Сообщений: 25543
|
|
Рейтинг: 13161
|
|
Re: сборка динамических библиотек из Ocaml
[re: Alex]
06.06.2007 13:38
|
|
|
а -fPIC впехнуть нельзя?
|
Entre flores fandanguillos y alegria nació España mi tierra de amor! |
|
Shurick
|
Bad Man
|
|
|
|
Рег.: 30.08.2002
|
Сообщений: 6379
|
|
Рейтинг: 303
|
|
Re: сборка динамических библиотек из Ocaml
[re: Alex]
06.06.2007 17:55
|
|
|
|
Alex
|
veteran
|
|
|
|
Рег.: 16.10.2002
|
Сообщений: 1940
|
Из: ЮЗАО
|
Рейтинг: 18
|
|
Re: сборка динамических библиотек из Ocaml
[re: Alex]
10.06.2007 18:57
|
|
|
Update.
Почитал документацию про x86-64 ABI. Понял, что обращение к переменным в PIC требует дополнительного уровня косвенности. То есть, код
movq %rbx, varname(%rip)
меняется не на
movq %rbx, varname@GOTPCREL(%rip)
а на следующее
movq varname@GOTPCREL(%rip), %rax movq %rbx, (%rax)
Теперь понятно, почему мои предыдущие попытки приводят к segfault.
Я попробовал позаменять так часть вызовов - программа продолжила работать правильно. Можно дозаменять остальные и попробовать собрать shared библиотеку. НО: Каждое такое обращение к переменной требует кучу дополнительных действий. Например, выделение блока памяти небольшого размера устроено так:
FUNCTION(caml_alloc1) subq $16, %r15 cmpq caml_young_limit(%rip), %r15 jb .L100 ret .L100: // вызвать GC
Текущий указатель на кучу лежит в регистре %r15. Если начать вставлять операции по типу описанных выше, то получится что-то типа:
push %r12 // %r12 - какой-нибудь временный регистр subq $16, %r15 movq caml_young_limit@GOTPCREL(%rip), %r12 cmpq %(r12), %r15 jb .L100 pop %r12 ret
Такое изменение замедлит функцию caml_alloc1 в несколько раз, чего сильно не хотелось бы.
Как можно бороться с такой проблемой?
Я слышал, что в некоторых языках/компиляторах выделяют отдельный регистр, в который при инициализации записывают адрес GOT, а обычный код его не трогает. При этом все ссылки на переменные записываются относительно него, например в виде varname@GOTOFF(%r11).
Можно попробовать применить этот способ и в Ocaml. Фишка в том, что у него собственный кодогенератор, который сам распределяет переменные по регистрам. Причем по умолчанию он юзает все доступные регистры (что весьма логично). Соответственно, надо хачить этот кодогенератор, чтобы оставлял один регистр свободным.
С учетом этого, что лучше сделать: вставить вызовы push/pop/movq@GOTPCREL везде или выделить отдельный регистр для GOT?
Как делают другие языки, например, C, C++, Java, C#, Lisp, Scheme ?
|
|
Alex
|
veteran
|
|
|
|
Рег.: 16.10.2002
|
Сообщений: 1940
|
Из: ЮЗАО
|
Рейтинг: 18
|
|
Re: сборка динамических библиотек из Ocaml
[re: Alex]
10.06.2007 19:04
|
|
|
По поводу Haskell: вопрос ответ еще сцылка.
Будем надеяться, что товарищей все получится. Конец лета - не за горами.
|
|
Alex
|
veteran
|
|
|
|
Рег.: 16.10.2002
|
Сообщений: 1940
|
Из: ЮЗАО
|
Рейтинг: 18
|
|
Re: сборка динамических библиотек из Ocaml
[re: Alex]
11.06.2007 09:25
|
|
|
Скачал текущую версию GHC из darcs-репозитория (GHC 6.7.20070609). Стало значительно лучше. На приведенном выше примере генерит код следующего вида:
code:
movq stg_CAF_BLACKHOLE_info@gotpcrel(%rip),%rax
movq %rax,-8(%r12)
movq %rbx,%rdi
movl $0,%eax
call newCAF@plt
leaq -8(%r12),%rax
movq %rax,8(%rbx)
movq stg_IND_STATIC_info@gotpcrel(%rip),%rax
movq %rax,(%rbx)
movq stg_upd_frame_info@gotpcrel(%rip),%rax
movq %rax,-16(%rbp)
В большинстве мест @gotpcrel и @plt расставлены, нереализованные ранее функции содержат теперь осмысленный код. Правда, остались еще неправильные relacation в данных, но в коде вроде бы все ок. Думаю, скоро сделают.
|
|