Найдите начало кучи, используя 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
Другие вопросы по тегам