Документ взят из кэша поисковой машины. Адрес оригинального документа : http://www.fds-net.ru/ashowflat.php?Cat=&Board=prog&Number=6240482
Дата изменения: Unknown
Дата индексирования: Tue Apr 12 02:21:36 2016
Кодировка: Windows-1251
сборка динамических библиотек из Ocaml - Public forum of MSU united student networks
Root | Google | Yandex | Mail.ru | Kommersant | Afisha | LAN Support
  
Technical >> Development (Archive)

Страницы: 1
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
 

Quote:

Кто-нибудь сталкивался с этой проблемой?




Ага:
http://caml.inria.fr/pub/ml-archives/caml-list/2005/08/9fbbc...
http://caml.inria.fr/pub/ml-archives/caml-list/2005/08/0904e...

Только их что-то никто не спас



Dixi.
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
 

http://www.x86-64.org/documentation/abi.pdf

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 в данных, но в коде вроде бы все ок. Думаю, скоро сделают.

Страницы: 1

Technical >> Development (Archive)

Дополнительная информация
2 зарегистрированных и 0 анонимных пользователей просматривают этот форум.

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

Печать темы

Права
      Вы можете создавать новые темы
      Вы можете отвечать на сообщения
      HTML отключен
      UBBCode включен

Рейтинг:
Просмотров темы:

Переход в