Как я могу попросить Mac OS выделить память в определенном диапазоне адресов?

Я пишу для Mac OS 9 "слой совместимости" для Mac OS X, потому что недавно меня поразила ностальгия, и потому что все текущие решения требуют, чтобы вы запускали Classic на виртуальной машине, которая не поддерживает все, что нужно для запуска того, что я хочу использовать.

Для достижения этой цели я реализовал исполняемый загрузчик PEF, интерпретатор PowerPC, который может связываться с собственным кодом, и некоторые библиотеки Mac OS 9. Все это отчасти работает: в интерпретаторе есть некоторые ошибки, но это было ожидаемо, и я работаю над этим.

Моя самая большая проблема на данный момент заключается в том, что программы PowerPC являются 32-разрядными, поэтому указатели должны быть 32-разрядными. Чтобы удовлетворить это ограничение, в настоящее время я компилирую только для i386. Однако, поскольку я пытаюсь построить вокруг этого ядра, оно становится все более и более ограниченным (например, вы не можете использовать ARC с 32-битными приложениями Какао). Не говоря уже о том, что небезопасно позволять коду PowerPC получать доступ ко всему, что может делать процесс хоста.

Я спроектировал "платформу" с возможным переключением на 64-битный тип: интерпретатор ожидает базовый адрес, а все указатели PowerPC смещены на этот базовый адрес. (Наличие карты, которая переводит адреса PowerPC в собственные адреса, не подлежит обсуждению по соображениям производительности и дизайна.)

Поскольку в 64-битном адресном пространстве достаточно места для размещения четырех миллиардов независимых 32-битных адресных пространств, для меня это хороший способ.

Но у меня все еще есть проблема: мне нужно быть уверенным, что я смогу выделить память внутри этого диапазона адресов, потому что для интерпретатора PPC было бы невозможно получить доступ к чему-либо за его пределами.

Есть два решения, о которых я сейчас думаю:

  • Узнайте, могу ли я попросить Mac OS выделить что-то внутри определенного диапазона адресов. Я знаю, что могу использовать mmap, но mmap будет запрашивать распределение в кратных страницах, что мне кажется очень расточительным, так как мне понадобится полная страница для каждого размещения, независимо от того, насколько она мала (хотя это может быть вполне приемлемо, учитывая, что у Mac с классической эпохой было очень мало памяти по сравнению на современные компьютеры);
  • использование mmap зарезервировать полный 0x100000000 байт с PROT_NONE, затем mprotect страницы по требованию, чтобы фактически выделить память, когда это необходимо, и вернуть их обратно PROT_NONE когда они больше не нужны. Это хорошо выглядит на бумаге, но это означает, что я должен реализовать malloc замена.

И что же мне делать? Есть ли встроенный механизм, который позволит мне попытаться выделить память, mallocв стиле, внутри определенного диапазона адресов? В противном случае, есть хорошая, читабельная, открытая реализация malloc Я мог бы основываться на себе?

2 ответа

Я не знаю встроенного способа сделать это, но это выполнимо с небольшим количеством работы. Один из подходов состоит в том, чтобы создать пользовательскую зону malloc, а затем использовать malloc_zone_* версии обычных функций malloc при выделении любой памяти, которая должна быть видна вашему коду PPC. Для вашей пользовательской зоны потребуется реализация malloc, но вы можете выбрать любое количество из них с открытым исходным кодом (например, tcmalloc). Также необходимо подключить, чтобы использовать что-то вроде vm_allocate с адресом подсказки, чтобы обеспечить распределение в нужном диапазоне.

Итак, я сам рассмотрел эту проблему для очень похожего (неопубликованного) проекта, и попытка использовать этот 64-битный подход (или вообще любой вид памяти с прямым порядком байтов в x86!) Быстро наталкивается на несколько неприятных проблем,

  1. Хотя вы можете указывать нативные API-интерфейсы на эмулируемые структуры, вы не можете заставить их самостоятельно распределять ресурсы внутри этой арены. Вы можете предоставить свои собственные реализации всех наиболее очевидных, таких как _NewPointer, но внутренние распределения другими функциями (как, скажем, _NewWindow с нулем wStorage) в значительной степени вне вашего контроля.

  2. Структуры системы (например, Rect), выделенные эмулированным кодом, будут иметь порядок с прямым порядком байтов, но ОС будет хотеть их с прямым порядком байтов. Нет простого способа обойти это, кроме, может быть, замены всех байтов при входе и выходе из нативных функций, и это кажется чрезвычайно подверженным ошибкам. (Другой подход, который я рассмотрел здесь, состоял в том, чтобы эмулируемое ядро ​​работало с прямым порядком байтов, но, к сожалению, некоторые программы чувствительны к этому изменению.)

Чтобы было ясно, мне чертовски нравится идея API-переводчика Classic-to-OS-X. Но я уверен, что это непрактично - учитывая, что Apple прекратила использовать виртуальную машину для Classic на PPC, я подозреваю, что они решили, что подход к переводу не сработает.

Другие вопросы по тегам