OberonCore https://forum.oberoncore.ru/ |
|
ElfLinker https://forum.oberoncore.ru/viewtopic.php?f=34&t=5459 |
Страница 7 из 9 |
Автор: | Димыч [ Понедельник, 07 Ноябрь, 2016 19:23 ] |
Заголовок сообщения: | Re: ElfLinker |
Я, честно говоря, так и не понял, как переменные отображаются в память из модулей-dll. Т.е. как заставить загрузчик Linux связать stdin с местом в памяти я понимаю, а вот как привязать Libc.stdin к этому участку - нет. Похоже, надо читать символьный файл дополнительно. |
Автор: | Иван Денисов [ Понедельник, 07 Ноябрь, 2016 19:35 ] |
Заголовок сообщения: | Re: ElfLinker |
Сама идея динамической библиотеки не должна тебе позволять привязывать переменную к другому месту в памяти, так как другие приложения могут эту переменную использовать ведь... |
Автор: | Valery Solovey [ Понедельник, 07 Ноябрь, 2016 19:55 ] |
Заголовок сообщения: | Re: ElfLinker |
А наоборот сделать можно? Не переменную привязать к другой, внешней библиотеке, а библиотеку ко внешней переменной. То есть, на этапе компоновки указать библиотеке (или модулю), что вот эта переменная находится вот по такому смещению в стеке или по такому адресу в куче. |
Автор: | Trurl [ Понедельник, 07 Ноябрь, 2016 22:35 ] |
Заголовок сообщения: | Re: ElfLinker |
Можно не импортировать, а экспортировать. По идее должно работать. |
Автор: | Trurl [ Вторник, 08 Ноябрь, 2016 09:43 ] |
Заголовок сообщения: | Re: ElfLinker |
Действительно, работает. Добавляем в LnkBase Код: PROCEDURE ExportVar*(mod: Module; IN name: STRING; addr: INTEGER); VAR sym: Symbol; BEGIN NEW(sym); sym.name := name$; sym.sect := mod.vars; sym.addr := addr; sym.next := expList; expList := sym; INC(expCount); END ExportVar; Правим CollectExports Код: PROCEDURE CollectExports(mod: Module); VAR p, numobj: INTEGER; id, vis, mode, addr: INTEGER; name: StrPtr; BEGIN IF ~mod.exported THEN GetDir(mod, p, numobj); WHILE numobj > 0 DO id := DWord(mod, p + 8); mode := id MOD 16; vis := id DIV 16 MOD 16; IF (vis # mInternal) THEN name := GetPName(mod, id DIV 256); addr := DWord(mod, p + 4); IF (mode = mProc) THEN LB.ExportProc(mod, name$, addr) ELSIF (mode = mVar) THEN LB.ExportVar(mod, name$, addr) END; END; DEC(numobj); INC(p, 16) END; mod.exported := TRUE; END; END CollectExports; Теперь объявляем в модуле Код: VAR stdin*, stdout*, stderr* : Libc.PtrFILE; и экспортируем его. Voila.Только проблема возникает. Поскольку имена переменных экпортируются без префикса, надо следить, чтобы не смешивались. |
Автор: | Димыч [ Вторник, 08 Ноябрь, 2016 12:12 ] |
Заголовок сообщения: | Re: ElfLinker |
Это уже сделано. Я добавил процедуры LB.ExportVar и Load.ExportVariable, которые делают то, что нужно. Проблема в том, что переменные, экспортируемые таким способом, должны находиться НЕ в модуле-dll. И тут есть три варианта:
У меня не получилось экспортировать переменные из Libc. Пробежался по подсистеме Win, там вообще нет переменных в dll-модулях. Так что, полагаю, можно попробовать остановиться на последнем варианте и сделать процедуру ExportModuleVars(mod) для единовременного вызова при любой компоновке. |
Автор: | Trurl [ Вторник, 08 Ноябрь, 2016 13:02 ] |
Заголовок сообщения: | Re: ElfLinker |
Димыч писал(а): Проблема в том, что переменные, экспортируемые таким способом, должны находиться НЕ в модуле-dll. Ну конечно. То, что в dll, импортируется, а не экспортируется. |
Автор: | Trurl [ Вторник, 08 Ноябрь, 2016 13:08 ] |
Заголовок сообщения: | Re: ElfLinker |
Димыч писал(а): Пробежался по подсистеме Win, там вообще нет переменных в dll-модулях. В Windows нельзя импортировать переменную из dll. Точнее, можно, но не с этим компилятором. Там схема напоминает GOT, нужен дополнительный уровень косвенности. |
Автор: | Иван Денисов [ Среда, 09 Ноябрь, 2016 09:51 ] |
Заголовок сообщения: | Re: ElfLinker |
Trurl писал(а): Только проблема возникает. Поскольку имена переменных экпортируются без префикса, надо следить, чтобы не смешивались. Проблема не сильно страшная, так как переменных не очень много. Стоит сделать проверку, и если возникают такие коллизии, то в журнал будет выдаваться предупреждение. |
Автор: | prospero78 [ Среда, 09 Ноябрь, 2016 13:00 ] |
Заголовок сообщения: | Re: ElfLinker |
Хм... Строго говоря в .Net DLL переменную экспортировать вполне себе можно. Как и объекты. |
Автор: | Димыч [ Среда, 09 Ноябрь, 2016 16:14 ] | ||
Заголовок сообщения: | Re: ElfLinker | ||
Димыч писал(а): Это уже сделано. ... ... Так что, полагаю, можно попробовать остановиться на последнем варианте и сделать процедуру ExportModuleVars(mod) для единовременного вызова при любой компоновке. В общем я так и сделал. ConsHello0 собирается хорошо. Добавлен модуль LinLibcVars, из Libc переменные убраны, добавлен вызов процедуры ExportModuleVars.
|
Автор: | Димыч [ Среда, 09 Ноябрь, 2016 16:33 ] |
Заголовок сообщения: | Re: ElfLinker |
Возможно надо перекомпилировать все модули в цепочке сборки. |
Автор: | Alexander Shiryaev [ Среда, 09 Ноябрь, 2016 22:05 ] |
Заголовок сообщения: | Re: ElfLinker |
Trurl писал(а): Навскидку 3 варианта: 1. Использовать функции, работающие со стандартными потоками (printf, scanf). 2. Роботать с дескрипторами (read, write). 3. Переоткрыть дескрипторы с помощью fdopen. Убрал stdin из Libc и реализовал 3-й вариант. |
Автор: | Иван Денисов [ Четверг, 10 Ноябрь, 2016 22:08 ] |
Заголовок сообщения: | Re: ElfLinker |
Alexander Shiryaev писал(а): Trurl писал(а): Навскидку 3 варианта: 1. Использовать функции, работающие со стандартными потоками (printf, scanf). 2. Роботать с дескрипторами (read, write). 3. Переоткрыть дескрипторы с помощью fdopen. Убрал stdin из Libc и реализовал 3-й вариант. Александр, есть еще h_errno в LinNet. |
Автор: | Димыч [ Пятница, 11 Ноябрь, 2016 07:04 ] |
Заголовок сообщения: | Re: ElfLinker |
Alexander Shiryaev писал(а): Убрал stdin из Libc и реализовал 3-й вариант. Подход имеет право на существование, но потенциально имеет и проблемы. stdin и stdout инициализирует libc и, строго говоря, мы не знаем, как она это делает. Приложение по факту получает готовый дескриптор. Который затем использует в своих целях. Для этого приложение указывает загрузчику "разъем", куда нужно "воткнуть" значение дескриптора. Когда мы экспортируем переменные в ELF, мы и помещаем слоты переменных так, чтобы libc могла их использовать. Поэтому мне подход с экспортом кажется более правильным. Хотя, еще раз, подход с переоткрытием дескрипторов тоже уместен. |
Автор: | Trurl [ Пятница, 11 Ноябрь, 2016 08:50 ] |
Заголовок сообщения: | Re: ElfLinker |
Ну, строго говоря, дескрипторами занимается ядро. Libc создает обертки-потоки для доступа к файлам. То, что мы не знаем как она это делает, неважно. Мы делаем точно так же, вызывая fdopen. А проблемы могут быть. Если включена буферизация, а мы начнем вызывать попеременно printf/fprintf, то вывод может перемешаться. А трюк с экпортом работает из-за особенностей динамической линковки. В libc есть свои stdin/stdout/stderr, но по умочанию поиск символов начинается с исполнимого файла. Но если кто-от соберет libc с флагом DT_SYMBOLIC, будет облом. |
Автор: | Alexander Shiryaev [ Пятница, 11 Ноябрь, 2016 11:08 ] |
Заголовок сообщения: | Re: ElfLinker |
Димыч писал(а): stdin и stdout инициализирует libc и, строго говоря, мы не знаем, как она это делает. Приложение по факту получает готовый дескриптор. Который затем использует в своих целях. ... Для этого приложение указывает загрузчику "разъем", куда нужно "воткнуть" значение дескриптора. Вот так в OpenBSD, например (а вот fdopen). B ещё там нет на экспорт переменных stdin, stdout, stderr. Вместо них -- __sF. Код: #define stdin (&__sF[0]) #define stdout (&__sF[1]) #define stderr (&__sF[2]) И приходилось к ним получать доступ так: Код: MODULE LinLibc; ... VAR (* OpenBSD: stdin, stdout, stderr *) __sF*: ARRAY [untagged] 3 OF FILE; (* OpenBSD /usr/include/stdio.h *) (* stdin = SYSTEM.ADR(__sF[0]) stdout = SYSTEM.ADR(__sF[1]) stderr = SYSTEM.ADR(__sF[2]) *) ... END LinLibc. В FreeBSD: Код: VAR stdin* ["__stdinp"]: PtrFILE;
|
Автор: | Димыч [ Пятница, 11 Ноябрь, 2016 11:29 ] |
Заголовок сообщения: | Re: ElfLinker |
Какие же все-таки разные подходы в ОС... Согласен, тут без fdopen сложно. |
Автор: | Alexander Shiryaev [ Пятница, 11 Ноябрь, 2016 12:22 ] |
Заголовок сообщения: | Re: ElfLinker |
Иван Денисов писал(а): Alexander Shiryaev писал(а): Trurl писал(а): Навскидку 3 варианта: 1. Использовать функции, работающие со стандартными потоками (printf, scanf). 2. Роботать с дескрипторами (read, write). 3. Переоткрыть дескрипторы с помощью fdopen. Убрал stdin из Libc и реализовал 3-й вариант. Александр, есть еще h_errno в LinNet. Исправил. В Linux h_errno на самом деле нет, есть __h_errno_location() А вот в OpenBSD переменная h_errno есть, а функции, аналогичной __h_errno_location(), нет ;( |
Автор: | Trurl [ Пятница, 11 Ноябрь, 2016 12:50 ] |
Заголовок сообщения: | Re: ElfLinker |
h_errno deprecated в posix-2001 и совсем удалена в posix-2008, надо от неё избавляться. |
Страница 7 из 9 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |