wasm32: add node-only TB wasm dump tooling for static analysis (E9)

This commit is contained in:
2026-07-22 08:00:39 -04:00
parent e80c3c7088
commit e45c1e2db1
4 changed files with 38 additions and 1 deletions
+13 -1
View File
@@ -6675,7 +6675,19 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
} }
*(uint32_t *)wasm_blob_ptr_base = s->code_ptr - wasm_blob_ptr_base - 4; *(uint32_t *)wasm_blob_ptr_base = s->code_ptr - wasm_blob_ptr_base - 4;
// record importing helper functions {
static __thread int dumped_store, dumped_load;
uint32_t mod_len = *(uint32_t *)wasm_blob_ptr_base;
const uint8_t *mod = wasm_blob_ptr_base + 4;
if (wasm_tb_had_store && !dumped_store) {
dumped_store = 1;
wasm_dump_module(mod, mod_len, "store");
} else if (wasm_tb_had_load && !wasm_tb_had_store && !dumped_load) {
dumped_load = 1;
wasm_dump_module(mod, mod_len, "load");
}
}
size_base = (uint32_t*)s->code_ptr; size_base = (uint32_t*)s->code_ptr;
s->code_ptr += 4; s->code_ptr += 4;
memcpy(s->code_ptr, target_helper_funcs, num_helper_funcs * 4); memcpy(s->code_ptr, target_helper_funcs, num_helper_funcs * 4);
+17
View File
@@ -39,6 +39,23 @@ EMSCRIPTEN_KEEPALIVE int wasm_instantiated_tb_count(void)
return qatomic_read(&instantiated_wasm_count); return qatomic_read(&instantiated_wasm_count);
} }
EM_JS(void, wasm_dump_module_js, (int ptr, int len, int name), {
try {
const fs = require('fs');
const bytes = Uint8Array.from(HEAP8.subarray(ptr, ptr + len));
const fname = '/tmp/tbdump-' + UTF8ToString(name) + '.wasm';
fs.writeFileSync(fname, bytes);
out('WASM_DUMP wrote ' + fname + ' (' + len + ' bytes)');
} catch (e) {
/* Browser has no require('fs'); dump is a node-only analysis aid. */
}
});
void wasm_dump_module(const uint8_t *p, int len, const char *name)
{
wasm_dump_module_js((int)p, len, (int)name);
}
/* Disassemble TCI bytecode. */ /* Disassemble TCI bytecode. */
int print_insn_tci(bfd_vma addr, disassemble_info *info) int print_insn_tci(bfd_vma addr, disassemble_info *info)
{ {
+2
View File
@@ -41,6 +41,8 @@ void flush_tb_instances(void);
void init_wasm32(); void init_wasm32();
void wasm_dump_module(const uint8_t *p, int len, const char *name);
extern __thread bool wasm_tci_only_tb; extern __thread bool wasm_tci_only_tb;
#define INSTANTIATE_NUM 1500 #define INSTANTIATE_NUM 1500
+6
View File
@@ -3362,13 +3362,19 @@ static uint8_t tcg_tci_out_qemu_ldst(TCGContext *s, TCGOpcode opc, const TCGArg
insn = deposit32(insn, 0, 8, opc); insn = deposit32(insn, 0, 8, opc);
tcg_tci_out32(s, insn); tcg_tci_out32(s, insn);
} }
/* Dump tags: instrumentation-only, set during codegen so tcg.c can dump one store-TB / load-TB
* module for static analysis. No effect on emitted code. */
__thread bool wasm_tb_had_store;
__thread bool wasm_tb_had_load;
static void tcg_out_qemu_ld(TCGContext *s, TCGOpcode opc, const TCGArg *args, bool is_64) static void tcg_out_qemu_ld(TCGContext *s, TCGOpcode opc, const TCGArg *args, bool is_64)
{ {
wasm_tb_had_load = true;
tcg_tci_out_qemu_ldst(s, opc, args); tcg_tci_out_qemu_ldst(s, opc, args);
tcg_wasm_out_qemu_ld(s, args, is_64); tcg_wasm_out_qemu_ld(s, args, is_64);
} }
static void tcg_out_qemu_st(TCGContext *s, TCGOpcode opc, const TCGArg *args, bool is_64) static void tcg_out_qemu_st(TCGContext *s, TCGOpcode opc, const TCGArg *args, bool is_64)
{ {
wasm_tb_had_store = true;
tcg_tci_out_qemu_ldst(s, opc, args); tcg_tci_out_qemu_ldst(s, opc, args);
tcg_wasm_out_qemu_st(s, args, is_64); tcg_wasm_out_qemu_st(s, args, is_64);
/* ponytail: Store-Containing TBs Run on TCI - Upstream qemu-wasm sets this for every guest store. /* ponytail: Store-Containing TBs Run on TCI - Upstream qemu-wasm sets this for every guest store.