Исполняемая память в пределах 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 или если система не настроена на выполнение макета памяти сверху вниз для выявления проблем с усечением указателя. Суть в том, что вы можете только увеличить вероятность размещения внутри границы, но у вас должен быть код для обработки, когда распределение выходит за границы.