Найдите начало кучи, используя lld и s2wasm
Я компилирую из C в WebAssembly с помощью clang -> llc -> s2wasm
а также clang -> lld
, Поскольку нет поставляемой библиотеки c, я написал свой собственный распределитель. Но я не уверен, что лучший способ найти начало свободной памяти.
Кажется, что и lld, и s2wasm имеют структуру памяти: | globals | stack | free memory |
, Указатель стека с помощью s2wasm находится по адресу памяти, а с помощью lld - в глобальном (который недоступен из C?).
Я нашел способ прочитать указатель стека в начале выполнения wasm, используя этот хак:
int stacktop()
{
int a;
return (int)(&a+1);
}
Это создает локальную переменную, которая не находится в линейной памяти и получает ее адрес. Чтобы сгенерировать адрес, компилятор помещает его в стек в памяти.
Я использую возвращенное значение как начало моей кучи. Есть ли более элегантный и перспективный способ найти свободную память?
1 ответ
Lld создает символ C под названием __heap_base
который указывает на основание кучи. Он также экспортирует это как глобальный wasm, чтобы кодировщик мог знать, где начинается куча.
Вам нужно получить адрес __heap_base
символ, созданный lld:
$ cat wasm-heap.c
extern unsigned char __heap_base;
__attribute__ ((visibility("default")))
void * get_heap_base(void) {
return &__heap_base;
}
Это вернет то же значение, что и __heap_base
Переменная WASM, экспортированная в JavaScript:
$ cat wasm-heap.js
var imports = {memory: new WebAssembly.Memory({initial:2})};
const module = new WebAssembly.Module(read('wasm-heap.wasm', 'binary'));
const instance = new WebAssembly.Instance(module, { "env" : imports }).exports;
var u8_data = new Uint8Array(imports["memory"]["buffer"]);
print("Heap base in WASM: " + instance.get_heap_base());
print("Heap base exported to JS: " + instance.__heap_base);
$ js52 wasm-heap.js
Heap base in WASM: 66560
Heap base exported to JS: 66560