Closed rxEckT closed 2 years ago
Hi Daniel,
When using the same program from #20, I realised that Wasabi returned incorrect answers for indirect function calls.
In [0]: Wasabi.resolveTableIdx(45) Out[0]: 0 // should be 2 In [1]: instance.exports.__wasabi_table.get(45) Out[1]: function 33()
The code in question is this: https://github.com/danleh/wasabi/blob/af37e2e0f6f1221a2b40500bf2372b8e7f87680f/lib/runtime.js#L46
If we look at what happens when we do wasm-objdump -x for an instrumented binary we will get this:
wasm-objdump -x
brainfuck.test.instrumented.wasm: file format wasm 0x1 Section Details: Type[6]: - type[0] (i32, i32) -> nil - type[1] (i32, i32, i32, i32) -> nil - type[2] (i32, i32, i32, i32, i32, i32) -> nil - type[3] (i32, i32, i32) -> nil - type[4] (i32, i32, i32, i32, i32) -> nil - type[5] () -> nil Import[32]: - func[0] sig=0 <a> <- a - func[1] sig=0 <__wasabi_hooks.begin_function> <- __wasabi_hooks.begin_function - func[2] sig=1 <__wasabi_hooks.global.get_i> <- __wasabi_hooks.global.get_i - func[3] sig=2 <__wasabi_hooks.i32.load8_u> <- __wasabi_hooks.i32.load8_u - func[4] sig=3 <__wasabi_hooks.i32.const> <- __wasabi_hooks.i32.const - func[5] sig=4 <__wasabi_hooks.i32.add> <- __wasabi_hooks.i32.add - func[6] sig=2 <__wasabi_hooks.i32.store8> <- __wasabi_hooks.i32.store8 - func[7] sig=0 <__wasabi_hooks.return> <- __wasabi_hooks.return - func[8] sig=0 <__wasabi_hooks.end_function> <- __wasabi_hooks.end_function - func[9] sig=4 <__wasabi_hooks.i32.sub> <- __wasabi_hooks.i32.sub - func[10] sig=1 <__wasabi_hooks.global.set_i> <- __wasabi_hooks.global.set_i - func[11] sig=1 <__wasabi_hooks.i32.eqz> <- __wasabi_hooks.i32.eqz - func[12] sig=3 <__wasabi_hooks.if> <- __wasabi_hooks.if - func[13] sig=0 <__wasabi_hooks.begin_if> <- __wasabi_hooks.begin_if - func[14] sig=3 <__wasabi_hooks.call> <- __wasabi_hooks.call - func[15] sig=0 <__wasabi_hooks.call_post> <- __wasabi_hooks.call_post - func[16] sig=3 <__wasabi_hooks.end_if> <- __wasabi_hooks.end_if - func[17] sig=3 <__wasabi_hooks.begin_else> <- __wasabi_hooks.begin_else - func[18] sig=1 <__wasabi_hooks.end_else> <- __wasabi_hooks.end_else - func[19] sig=1 <__wasabi_hooks.local.set_i> <- __wasabi_hooks.local.set_i - func[20] sig=0 <__wasabi_hooks.begin_loop> <- __wasabi_hooks.begin_loop - func[21] sig=1 <__wasabi_hooks.local.get_i> <- __wasabi_hooks.local.get_i - func[22] sig=1 <__wasabi_hooks.local.tee_i> <- __wasabi_hooks.local.tee_i - func[23] sig=4 <__wasabi_hooks.i32.ne> <- __wasabi_hooks.i32.ne - func[24] sig=4 <__wasabi_hooks.br_if> <- __wasabi_hooks.br_if - func[25] sig=3 <__wasabi_hooks.end_loop> <- __wasabi_hooks.end_loop - func[26] sig=3 <__wasabi_hooks.call_indirect> <- __wasabi_hooks.call_indirect - func[27] sig=4 <__wasabi_hooks.i32.gt_s> <- __wasabi_hooks.i32.gt_s - func[28] sig=4 <__wasabi_hooks.i32.xor> <- __wasabi_hooks.i32.xor - func[29] sig=4 <__wasabi_hooks.i32.gt_u> <- __wasabi_hooks.i32.gt_u - func[30] sig=2 <__wasabi_hooks.call_iii> <- __wasabi_hooks.call_iii - func[31] sig=4 <__wasabi_hooks.call_ii> <- __wasabi_hooks.call_ii Function[12]: - func[32] sig=5 <inc> - func[33] sig=5 <dec> - func[34] sig=5 <shl> - func[35] sig=5 <shr> - func[36] sig=5 <start> - func[37] sig=5 <end> - func[38] sig=5 <prn> - func[39] sig=5 - func[40] sig=5 - func[41] sig=5 - func[42] sig=3 - func[43] sig=5 <b> Table[1]: - table[0] type=funcref initial=94 Memory[1]: - memory[0] pages: initial=1 Global[5]: - global[0] i32 mutable=1 - init i32=0 - global[1] i32 mutable=1 - init i32=0 - global[2] i32 mutable=1 - init i32=0 - global[3] i32 mutable=1 - init i32=0 - global[4] i32 mutable=1 - init i32=1 Export[10]: - func[32] <inc> -> "inc" - func[33] <dec> -> "dec" - func[34] <shl> -> "shl" - func[35] <shr> -> "shr" - func[36] <start> -> "start" - func[37] <end> -> "end" - func[38] <prn> -> "prn" - func[43] <b> -> "b" - table[0] -> "__wasabi_table" - memory[0] -> "c" Elem[7]: - segment[0] table=0 count=1 - init i32=43 - elem[43] = func[32] <inc> - segment[1] table=0 count=1 - init i32=45 - elem[45] = func[33] <dec> - segment[2] table=0 count=1 - init i32=60 - elem[60] = func[34] <shl> - segment[3] table=0 count=1 - init i32=62 - elem[62] = func[35] <shr> - segment[4] table=0 count=1 - init i32=91 - elem[91] = func[36] <start> - segment[5] table=0 count=1 - init i32=93 - elem[93] = func[37] <end> - segment[6] table=0 count=1 - init i32=46 - elem[46] = func[38] <prn> Code[12]: - func[32] size=125 <inc> - func[33] size=125 <dec> - func[34] size=77 <shl> - func[35] size=77 <shr> - func[36] size=158 <start> - func[37] size=134 <end> - func[38] size=149 <prn> - func[39] size=225 - func[40] size=44 - func[41] size=246 - func[42] size=380 - func[43] size=150 <b>
In [2] is 33 because of the imported hooks inflating the function ids.
In [2]
33
Therefore, my first thought was subtracting the hook count like so:
const functionIdx = parseInt(Wasabi.module.table.get(tableIdx).name) - Object.entries(Wasabi.module.lowlevelHooks).length;
However, the approach would not work properly if there are existing imports.
I think the best solution would be for Wasabi to emit a importCount in Wasabi.module.info to be used together with the code above.
importCount
Wasabi.module.info
var functionIdx = parseInt(Wasabi.module.table.get(tableIdx).name); if (functionIdx > Wasabi.module.info.importCount - 1) { functionIdx = functionIdx - Object.entries(Wasabi.module.lowlevelHooks).length; } return functionIdx;
Merry Christmas and a Happy New Year! :tada:
Sorry for coming back to this so late. I finally ended up fixing the issue, essentially as you described. Thanks again!
Hi Daniel,
When using the same program from #20, I realised that Wasabi returned incorrect answers for indirect function calls.
The code in question is this: https://github.com/danleh/wasabi/blob/af37e2e0f6f1221a2b40500bf2372b8e7f87680f/lib/runtime.js#L46
If we look at what happens when we do
wasm-objdump -x
for an instrumented binary we will get this:In [2]
is33
because of the imported hooks inflating the function ids.Therefore, my first thought was subtracting the hook count like so:
However, the approach would not work properly if there are existing imports.
I think the best solution would be for Wasabi to emit a
importCount
inWasabi.module.info
to be used together with the code above.Merry Christmas and a Happy New Year! :tada: