Можно ли принудительно указать диапазон виртуальных адресов?

У меня есть программа на Аде, написанная для конкретной (встроенной, многопроцессорной, 32-разрядной) архитектуры. Я пытаюсь использовать этот же код в моделировании на 64-битном RHEL в качестве общего объекта (поскольку существует несколько версий, и мне нужно выбрать версию во время выполнения).

У меня проблема в том, что в коде есть несколько мест, где люди, которые его написали (не я...), использовали Unchecked_Conversions для преобразования System.Addresses в 32-битные целые числа. Не только это, но и множество подпрограмм с жестко закодированными адресами памяти. Я могу внести небольшие изменения в этот код, но полностью портировать его на x86_64 на самом деле не вариант. Существуют подпрограммы, которые обрабатывают прерывания, планируют задачи ЦП и т. д.

Этот код работал нормально в прошлом, когда он был статически связан с предыдущей версией моделирования (состоящей из Fortran/C/C++). Однако теперь запускается основной исполняемый файл, а затем загружается общий объект на основе некоторых входных данных. Затем этот общий объект проверяет некоторые другие входные данные и загружает соответствующий общий объект Ады.

Просматривая код, становится очевидным, что он должен работать нормально, если я могу сохранить адреса логической памяти от 0 до 2 147 483 647 (32-разрядное целое число со знаком). Есть ли способ заставить загрузчик общих объектов оставить место в нижних диапазонах для кода Ады или, возможно, заставить код Ады «думать», что его адреса находятся в диапазоне от 0 до 2 147 483 647?


person zappyzap    schedule 29.04.2015    source источник
comment
Вы можете попробовать скомпилировать с параметром -m32. Это создаст 32-битные (i386) исполняемые файлы.   -  person Ulfalizer    schedule 29.04.2015
comment
Если вы можете перекомпилировать стандартную библиотеку Ada из исходников, вы можете попробовать изменить определение System.Address (примерно в system.ads) на тип Address is mod 2 ** 32; - но я не могу гарантировать, что он будет работать [на моей 64-битной системе он определяется как мод 2**64].   -  person darkestkhan    schedule 02.06.2015


Ответы (1)


Есть ли способ заставить загрузчик общих объектов оставить место в нижних диапазонах для кода Ады?

Хорошей новостью является то, что загрузчик оставит нижние диапазоны нетронутыми.

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

Тем не менее, dlopen из памяти (который мы реализовали в нашей частной вилке glibc) позволит вам это сделать. Но этого нет в открытом доступе.

Ваши другие возможные варианты:

  • если вы можете уместить весь процесс в 32-битное адресное пространство, то ваше решение тривиально: просто соберите все с -m32.

  • используйте prelink для перемещения библиотеки по нужному адресу. Поскольку этот адрес почти всегда должен быть доступен, загрузчик, скорее всего, загрузит библиотеку именно по нему.

  • связать загрузчик с пользовательской реализацией mmap, которая обнаруживает интересующую библиотеку через какой-то побочный канал и выполняет системный вызов mmap с установленным MAP_32BIT, или

  • запустите программу в ptrace песочнице. Такая песочница может снова перехватить системный вызов mmap и MAP_32BIT, когда это необходимо.

или, возможно, заставить код Ады «думать», что его адреса находятся в диапазоне от 0 до 2 147 483 647?

Я не понимаю, как это возможно. Если библиотека хранит адрес функции или глобальную переменную в 32-битной ячейке памяти, затем загружает этот адрес и разыменовывает его... она получит 32-битный усеченный адрес и SIGSEGV при разыменовании.

person Employed Russian    schedule 30.04.2015