Исполняемая память в пределах 32-битного смещения области кода

При написании JIT-компилятора на C++ в 64-битной Windows сгенерированный код иногда должен вызывать функции времени выполнения, написанные на C++. На данный момент я выделяю память для размещения сгенерированного кода с помощью VirtualAlloc(0, bytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE); последний флаг важен, потому что выделенная память не может быть выполнена другим способом.

VirtualAlloc предположительно может вернуть память в любом месте 64-битного адресного пространства, что хорошо для данных (из которых, как правило, потребуется более 4 гигабайт, поэтому необходима 64-битная адресация), но наиболее эффективная форма x64 call Инструкция требует 32-битного IP-относительного смещения, и, поскольку объем сгенерированного кода будет меньше 4 гигабайт, было бы предпочтительно разместить его в пределах 32-битного смещения кода, скомпилированного из C++.

Есть ли способ это устроить?

1 ответ

Решение

В качестве первого аргумента вы можете указать виртуальный адрес, рядом с которым вы хотите, чтобы распределение происходило. Чтобы повысить вероятность получения выделения в границах, которые вы хотите, можно сначала зарезервировать область виртуальной памяти, а затем запросить выделенную память по мере необходимости из зарезервированного пространства. Распределение по умолчанию происходит внизу, если не указано MEM_TOP_DOWN или если система не настроена на выполнение макета памяти сверху вниз для выявления проблем с усечением указателя. Суть в том, что вы можете только увеличить вероятность размещения внутри границы, но у вас должен быть код для обработки, когда распределение выходит за границы.

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