Git Product home page Git Product logo

wasabi's Introduction

Wasabi: A Dynamic Analysis Framework for WebAssembly

Wasabi is a framework for dynamically analyzing WebAssembly binaries. A high-level introduction, live demo, and more can be found at http://wasabi.software-lab.org. Our ASPLOS 2019 paper Wasabi: A Framework for Dynamically Analyzing WebAssembly (which won a best paper award) contains more in-depth explanations and evaluation results. Check also the READMEs in the other directories of this repository.

Source Code

Wasabi is built on binary instrumentation. For that, we have developed our own WebAssembly parser, instrumentation library, and encoder in Rust. This code may be useful independently of Wasabi as well. In fact, we have used it also for other projects on WebAssembly analysis and instrumentation. You can find the source code in crates/ (the Rust term for libraries).

Tutorial at PLDI 2019

We gave an introduction and tutorial on using Wasabi at PLDI 2019. See tutorial-pldi2019/ for more information.

Installation

Dependencies and useful tools:

  • Git, CMake, and GCC or Clang for building the dependencies (possibly more).
  • A modern browser, e.g., Firefox or Chrome.
  • WebAssembly Binary Toolkit (WABT): https://github.com/WebAssembly/wabt. wat2wasm/wasm2wat for converting Wasm binaries to/from text, wasm-objdump for inspecting binaries, and wasm-interp for a simple interpreter.
  • Emscripten: https://emscripten.org. For compiling C/C++ programs to WebAssembly.
  • Rust: https://www.rust-lang.org/tools/install. cargo as Rust's package manager and build tool and rustup for managing different Rust toolchains versions. If there are build errors, please make sure you use a recent stable version of Rust.

Building Wasabi itself:

git clone https://github.com/danleh/wasabi.git
cd wasabi/crates/wasabi
# Download dependencies from https://crates.io, compile with optimizations, make wasabi binary available in $PATH.
cargo install --path .

# Test:
wasabi
> Error: expected at least one argument
> Usage: wasabi <input_wasm_file> [<output_dir>]

Short Usage Instructions

Create a WebAssembly program:

Option A) Manually:

;; Paste into hello-manual.wat
(module
    (import "host" "print" (func $i (param i32)))
    (func $somefun
    i32.const 42
    call $i)
    (export "somefun" (func $somefun))
)
# Assemble to binary .wasm file
wat2wasm hello-manual.wat

# Run the binary. (The imported function host.print is provided by the interpreter.)
wasm-interp --host-print --run-all-exports hello-manual.wasm
> called host host.print(i32:42) =>
> somefun() =>

Option B) Compile from C with Emscripten:

// Paste into hello.c
#include <stdio.h>
int main(int argc, char const *argv[]) {
    printf("Hello, world!\n");
    return 0;
}
# Emscripten produces a small wrapper website alongside the WebAssembly code, such that you can execute it in the browser.
emcc hello.c -o hello.html

# Due to browser security policies, you need to serve the website from a web server. 
emrun --no_browser --port 8080 .

# Open website with Firefox or Chrome.
firefox http://localhost:8080/hello.html
chromium-browser http://localhost:8080/hello.html

# (Optional:) Inspect the produced binary with wasm2wat or wasm-objdump.
wasm2wat hello.wasm -o hello.wat
wasm-objdump hello.wasm -hdx | less

Apply Wasabi to WebAssembly programs in the browser:

  • Step 1: Instrument

    # Start with the C to Wasm (via Emscripten) project from the previous step:
    ls
    > hello.c  hello.html  hello.js  hello.wasm
    
    # Instrument hello.wasm, produces 2 files in out/:
    # - out/hello.wasm: instrumented binary, with imported hooks and calls to these hooks inserted between instructions
    # - out/hello.wasabi.js: Wasabi loader, runtime, and generated program-dependent JavaScript (low-level monomorphized hooks and statically extracted information about the binary)
    wasabi hello.wasm
    
    # Replace the original binary with the instrumented one and copy generated JavaScript.
    mv hello.wasm hello.orig.wasm
    cp out/* .
    
    # Insert Wasabi-generated JavaScript into Emscripten-generated HTML harness (FIXME hacky).
    sed -i '/<script async type="text\/javascript" src="hello.js"><\/script>/a <script src="hello.wasabi.js"></script>' hello.html
    
    # Should still run as before the instrumentation.
    emrun --no_browser --port 8080 .
    firefox http://localhost:8080/hello.html
  • Step 2: Analyze

    # Use one of the example analyses, e.g., that logs all instructions with their inputs and results.
    cp /path/to/wasabi/analyses/log-all.js .
    
    # Include analysis in Emscripten-generated HTML harness (FIXME hacky).
    # NOTE The analysis must be loaded *after* the Wasabi-generated JavaScript.
    sed -i '/<script src="hello.wasabi.js"><\/script>/a <script src="log-all.js"></script>' hello.html
    
    # Run in the browser again, you should see lots of output on JavaScript console.
    emrun --no_browser --port 8080 .
    firefox http://localhost:8080/hello.html

You can find more example Wasabi analyses in example-analyses/.

License

Wasabi is licensed under the MIT license. See LICENSE for details. Other code in this repository or used as a dependency may be licensed differently.

wasabi's People

Contributors

antdum avatar ctfhacker avatar danleh avatar frgossen avatar michaelpradel avatar michelledaviest avatar mtorp avatar vaibspider avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wasabi's Issues

Pass type to const hook

Inside the const_ hook, one cannot distinguish an i32 from an f32 or f64 (assuming the latter have no fractional portion).
Add op argument, similar to local and global hooks.

CORS block tutorial in newest Firefow

Running the first tutorial (hello.html) in Firefox and clicking the button, the console repsonds with this error:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///home/hjort/code/wasabi/tutorial/task0/1-hello/hello.wasm. (Reason: CORS request not http).

Update binary format parser to new syn/quote crates

Rust has evolved quite a lot since the starting of Wasabi. In particular, we are now using stable Rust edition 2018.

One thing where the old code shows is the procedural macro that generates a wasm parser from the wasm ast in the lib/wasm crate. Update it to use newest quote/synn crates

Docker Build Error on Compiling proc-macro2-error

When running docker build --rm -t wasabi . the following error message is displayed:

...
   Compiling proc-macro-error v0.2.6
error[E0658]: :literal fragment specifier is experimental and subject to change (see issue #35625)
   --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-0.2.6/src/lib.rs:161:18
    |
161 |     ($span:expr, $fmt:literal, $($args:expr),*) => {{
    |                  ^^^^^^^^^^^^

error[E0658]: :literal fragment specifier is experimental and subject to change (see issue #35625)
   --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-0.2.6/src/lib.rs:181:6
    |
181 |     ($fmt:literal, $($args:expr),*) => {{
    |      ^^^^^^^^^^^^

error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
   --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-0.2.6/src/lib.rs:139:9
    |
135 | pub mod dummy;
    | -------------- not an extern crate passed with `--extern`
...
139 | pub use dummy::set_dummy;
    |         ^^^^^
    |
note: this import refers to the module defined here
   --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-0.2.6/src/lib.rs:135:1
    |
135 | pub mod dummy;
    | ^^^^^^^^^^^^^^

error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
   --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-0.2.6/src/lib.rs:140:9
    |
136 | pub mod multi;
    | -------------- not an extern crate passed with `--extern`
...
140 | pub use multi::MultiMacroErrors;
    |         ^^^^^
    |
note: this import refers to the module defined here
   --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-0.2.6/src/lib.rs:136:1
    |
136 | pub mod multi;
    | ^^^^^^^^^^^^^^

error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
   --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-0.2.6/src/lib.rs:141:9
    |
137 | pub mod single;
    | --------------- not an extern crate passed with `--extern`
...
141 | pub use single::MacroError;
    |         ^^^^^^
    |
note: this import refers to the module defined here
   --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-0.2.6/src/lib.rs:137:1
    |
137 | pub mod single;
    | ^^^^^^^^^^^^^^^

error[E0308]: match arms have incompatible types
   --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-0.2.6/src/lib.rs:244:9
    |
244 | /         match self {
245 | |             Some(res) => res,
246 | |             None => call_site_error!(message),
    | |                     ------------------------- match arm with an incompatible type
247 | |         }
    | |_________^ expected type parameter, found bool
    |
    = note: expected type `T`
               found type `bool`

error: aborting due to 6 previous errors

Some errors occurred: E0308, E0658.
For more information about an error, try `rustc --explain E0308`.
error: Could not compile `proc-macro-error`.
...

WASI module instrumentation

It would be really great if this tool could help with debugging WASI.
I see 2 challenges here:

  1. WASI runtimes typically do not have any JS engine at all. This makes the generated js file useless.
  2. WASI aims to define a stable system interface, so adding additional imported functions is impossible.

I think that it still could be done. By using the WASI API wasabi could output the trace to a log file. Then the generated .js file could be transformed into a log file parser/decoder.

Access Memory in Hook

Is there currently a feature to access the current state of the Memory in a hook?
I know you have the option to access Wasabi.module.exports which contains the memory if it is exported. But what if we deal with imported memory?

I like this project name

the name wasabi is funny in chinese, may pronounce as 哇撒比
sounds like wow, that idiot

you guys genius

Is Wasabi.analysis.memory implemented?

Hello,

I instrumented my code with Wasabi and run, I got the following error:

Uncaught TypeError: Cannot read property 'size' of undefined
at memory.size (main.wasabi.js:577)
at <anonymous>:wasm-function[495]:0x52dbf
at malloc (<anonymous>:wasm-function[493]:0x43f4c)
at <anonymous>:wasm-function[379]:0x1690b
at send (<anonymous>:wasm-function[168]:0x2438)
at main.js:1730
at Object.ccall (main.js:751)
at <anonymous>:1:8

This is because Wasabi.analysis.memory is undefined, so my question is, is Wasabi.analysis.memory implemented anywhere in wasabi.js or I have to implement it by myself? I did not see any example in analyses/ defining memory as well.

'__wasabi_hooks' is not an Object

When I tested the taint.js and call-graph.js, I found some bugs in *.wasabi.js.

Some errors occurred when I was testing importObjectWithHooks in the console such as "importObjectWithHooks.__wasabi_hooks was undefineded."

call-graph.js's error:
wasm streaming compile failed: TypeError: import object field '__wasabi_hooks' is not an Object
...
and many Wasabi.HOOK_NAMES func not found.

taint.js 's error:
Starting taint analysis taint.js:13:13
Warning: No exported source function found. taint.js:53:42
Warning: No exported sink function found. taint.js:54:40
wasm streaming compile failed: TypeError: import object field '__wasabi_hooks' is not an Object test.html:1246:19
falling back to ArrayBuffer instantiation test.html:1246:19
nop hook not provided by Wasabi.analysis, add empty function as fallback test.wasabi.js:142:25
unreachable hook not provided by Wasabi.analysis, add empty function as fallback

Replace Long.js conversion of i64 with JS BigNum support

See #31 (comment)

Copied from there: remove Long.js dependency completely and use JavaScript BigNums instead, see https://github.com/WebAssembly/proposals/blob/master/finished-proposals.md and https://github.com/WebAssembly/JS-BigInt-integration

  • this wasn't possible back in 2018 because the proposal wasn't finished yet
  • check browser and Node.js compatibility of JS BigNums
  • change low-level hook code to use BigNums instead of Long.js (should be quite easy/mechanical)

Modify state inside of hooks

It would be very useful to be able to modify the state of an operation inside of a hook. E.g.

Wasabi.analysis = {
    binary(location, op, first, second, r) {
        // If result for i32.eq operations in function 47 are 0, change it to 1 
        // then continue execution with the new result.
        if (op == 'i32.eq' && location['func'] == 47 && result == 0) {
            result = 1;
            console.log(location, op, "result =", result);
        }
    }
};

Error parsing Element section

I have the following webassembly text file:

(module 
  (table 94 anyfunc)
  (elem (i32.const 43) 0)
  (elem (i32.const 45) 1)
  (elem (i32.const 60) 2)
  (elem (i32.const 62) 3)
  (elem (i32.const 91) 4)
  (elem (i32.const 93) 5)
  (elem (i32.const 46) 6)
  (func)
  (func)
  (func)
  (func)
  (func)
  (func)
  (func))

When compiled with wabt using wat2wasm (commit 76ff3af), the resulting binary could not be instrumented with Wasabi. The error received is Error: expected tag for ValType, got 0x00

If compiled with webassembly.studio instead, Wasabi is able to instrument the binary.


I tried to narrow down the issue and I think the cause could be related to differences in how the Element section is encoded by the tools.

With wat2wasm

Contents of section Elem:
0000020: 0702 0041 2b0b 0001 0002 0041 2d0b 0001  ...A+......A-...
0000030: 0102 0041 3c0b 0001 0202 0041 3e0b 0001  ...A<......A>...
0000040: 0302 0041 db00 0b00 0104 0200 41dd 000b  ...A........A...
0000050: 0001 0502 0041 2e0b 0001 06              .....A.....

With webassembly.studio

Contents of section Elem:
0000020: 0700 412b 0b01 0000 412d 0b01 0100 413c  ..A+....A-....A<
0000030: 0b01 0200 413e 0b01 0300 41db 000b 0104  ....A>....A.....
0000040: 0041 dd00 0b01 0500 412e 0b01 06         .A......A....

Output of wasm-objdump -s

Any thoughts would be appreciated.

Missing {end_function} call

In the following case, Wasabi misses to place the {end_function} instruction call (call 551). I would expect that before every return statement, one is missing.

Looking at the ends of nested if statements, it seems as if there may be some more misplaced instructions. However, I do not understand this in detail so it might as well be wrong about that.

Original code:

  (func (;787;) (type 8) (param i32 i32)
    (local i32 i32 i32 i32)
    block  ;; label = @1
      block  ;; label = @2
        local.get 0
        i32.load
        local.tee 3
        if  ;; label = @3
          local.get 1
          i32.const 15
          i32.gt_u
          local.set 5
          local.get 0
          i32.const 4
          i32.add
          local.tee 2
          i32.load
          i32.eqz
          if  ;; label = @4
            local.get 5
            if  ;; label = @5
              local.get 0
              local.get 1
              i32.const 1
              i32.add
              i32.const 16
              local.get 0
              i32.load offset=24
              i32.const 0
              i32.const 1783927
              i32.const 305
              call 2729
              local.tee 2
              i32.store
              i32.const 0
              local.set 4
              br 3 (;@2;)
            else
              local.get 0
              i32.const 0
              i32.store
              i32.const 0
              local.set 4
              i32.const 0
              local.set 2
              br 3 (;@2;)
            end
          end
          local.get 5
          i32.eqz
          if  ;; label = @4
            local.get 0
            i32.const 0
            i32.store
            i32.const 1
            local.set 4
            i32.const 0
            local.set 2
            br 2 (;@2;)
          end
          local.get 0
          local.get 3
          local.get 1
          i32.const 1
          i32.add
          i32.const 16
          local.get 0
          i32.load offset=24
          i32.const 0
          i32.const 1783927
          i32.const 285
          call 2832
          i32.store
          local.get 2
          local.get 1
          i32.store
          return
        else
          local.get 1
          i32.const 16
          i32.lt_u
          if  ;; label = @4
            return
          else
            local.get 0
            local.get 1
            i32.const 1
            i32.add
            i32.const 16
            local.get 0
            i32.load offset=24
            i32.const 0
            i32.const 1783927
            i32.const 276
            call 2729
            local.tee 2
            i32.store
            i32.const 0
            local.set 4
            local.get 0
            i32.const 4
            i32.add
            local.set 3
          end
        end
      end
      local.get 0
      i32.const 4
      i32.add
      local.set 5
      local.get 2
      if (result i32)  ;; label = @2
        local.get 2
      else
        local.get 5
      end
      local.get 3
      local.get 0
      i32.load offset=20
      i32.const 1
      i32.add
      call 34059
      drop
      local.get 4
      if  ;; label = @2
        local.get 3
        local.get 0
        i32.load offset=24
        call 2687
      end
      local.get 0
      i32.load
      i32.eqz
      if  ;; label = @2
        return
      end
      local.get 0
      local.get 1
      i32.store offset=4
    end)

Instructed code (--hooks=begin,end, 11 additional imports):

  (func (;798;) (type 29) (param i32 i32)
    (local i32 i32 i32 i32)
    i32.const 787
    i32.const -1
    call 548
    block  ;; label = @1
      i32.const 787
      i32.const 0
      call 549
      block  ;; label = @2
        i32.const 787
        i32.const 1
        call 549
        local.get 0
        i32.load
        local.tee 3
        if  ;; label = @3
          i32.const 787
          i32.const 5
          call 550
          local.get 1
          i32.const 15
          i32.gt_u
          local.set 5
          local.get 0
          i32.const 4
          i32.add
          local.tee 2
          i32.load
          i32.eqz
          if  ;; label = @4
            i32.const 787
            i32.const 16
            call 550
            local.get 5
            if  ;; label = @5
              i32.const 787
              i32.const 18
              call 550
              local.get 0
              local.get 1
              i32.const 1
              i32.add
              i32.const 16
              local.get 0
              i32.load offset=24
              i32.const 0
              i32.const 1783927
              i32.const 305
              call 2740
              local.tee 2
              i32.store
              i32.const 0
              local.set 4
              i32.const 787
              i32.const 44
              i32.const 18
              call 552
              i32.const 787
              i32.const 45
              i32.const 16
              call 552
              i32.const 787
              i32.const 102
              i32.const 5
              call 552
              i32.const 787
              i32.const 103
              i32.const 1
              call 554
              br 3 (;@2;)
            else
              local.get 0
              i32.const 0
              i32.store
              i32.const 0
              local.set 4
              i32.const 0
              local.set 2
              br 3 (;@2;)
              i32.const 787
              i32.const 44
              i32.const 18
              call 552
            end
            i32.const 787
            i32.const 45
            i32.const 16
            call 552
          end
          local.get 5
          i32.eqz
          if  ;; label = @4
            i32.const 787
            i32.const 48
            call 550
            local.get 0
            i32.const 0
            i32.store
            i32.const 1
            local.set 4
            i32.const 0
            local.set 2
            i32.const 787
            i32.const 57
            i32.const 48
            call 552
            i32.const 787
            i32.const 102
            i32.const 5
            call 552
            i32.const 787
            i32.const 103
            i32.const 1
            call 554
            br 2 (;@2;)
            i32.const 787
            i32.const 57
            i32.const 48
            call 552
          end
          local.get 0
          local.get 3
          local.get 1
          i32.const 1
          i32.add
          i32.const 16
          local.get 0
          i32.load offset=24
          i32.const 0
          i32.const 1783927
          i32.const 285
          call 2843
          i32.store
          local.get 2
          local.get 1
          i32.store
          i32.const 787
          i32.const 102
          i32.const 5
          call 552
          i32.const 787
          i32.const 103
          i32.const 1
          call 554
          i32.const 787
          i32.const 137
          i32.const 0
          call 554
          i32.const 787
          i32.const 138
          call 551
          return
        else
          local.get 1
          i32.const 16
          i32.lt_u
          if  ;; label = @4
            return
          else
            local.get 0
            local.get 1
            i32.const 1
            i32.add
            i32.const 16
            local.get 0
            i32.load offset=24
            i32.const 0
            i32.const 1783927
            i32.const 276
            call 2740
            local.tee 2
            i32.store
            i32.const 0
            local.set 4
            local.get 0
            i32.const 4
            i32.add
            local.set 3
          end
          i32.const 787
          i32.const 102
          i32.const 5
          call 552
        end
        i32.const 787
        i32.const 103
        i32.const 1
        call 554
      end
      local.get 0
      i32.const 4
      i32.add
      local.set 5
      local.get 2
      if (result i32)  ;; label = @2
        i32.const 787
        i32.const 109
        call 550
        local.get 2
        i32.const 787
        i32.const 111
        i32.const 109
        call 552
      else
        i32.const 787
        i32.const 111
        i32.const 109
        call 555
        local.get 5
        i32.const 787
        i32.const 113
        i32.const 111
        i32.const 109
        call 556
      end
      local.get 3
      local.get 0
      i32.load offset=20
      i32.const 1
      i32.add
      call 34070
      drop
      local.get 4
      if  ;; label = @2
        i32.const 787
        i32.const 122
        call 550
        local.get 3
        local.get 0
        i32.load offset=24
        call 2698
        i32.const 787
        i32.const 127
        i32.const 122
        call 552
      end
      local.get 0
      i32.load
      i32.eqz
      if  ;; label = @2
        i32.const 787
        i32.const 131
        call 550
        i32.const 787
        i32.const 133
        i32.const 131
        call 552
        i32.const 787
        i32.const 137
        i32.const 0
        call 554
        i32.const 787
        i32.const 138
        call 551
        return
        i32.const 787
        i32.const 133
        i32.const 131
        call 552
      end
      local.get 0
      local.get 1
      i32.store offset=4
      i32.const 787
      i32.const 137
      i32.const 0
      call 554
    end
    i32.const 787
    i32.const 138
    call 551)

Wasabi imports:

 - func[548] sig=29 <begin_function> <- __wasabi_hooks.begin_function
 - func[549] sig=29 <begin_block> <- __wasabi_hooks.begin_block
 - func[550] sig=29 <begin_if> <- __wasabi_hooks.begin_if
 - func[551] sig=29 <end_function> <- __wasabi_hooks.end_function
 - func[552] sig=20 <end_if> <- __wasabi_hooks.end_if
 - func[553] sig=29 <begin_loop> <- __wasabi_hooks.begin_loop
 - func[554] sig=20 <end_block> <- __wasabi_hooks.end_block
 - func[555] sig=20 <begin_else> <- __wasabi_hooks.begin_else
 - func[556] sig=28 <end_else> <- __wasabi_hooks.end_else
 - func[557] sig=20 <end_loop> <- __wasabi_hooks.end_loop
 - func[558] sig=28 <br_table> <- __wasabi_hooks.br_table

Reuse inserted locals for stack value duplication

Currently, Wasabi inserts a fresh local (quite primitively) for every stack value it needs to duplicate. This causes some binaries with large functions to contain tons of locals after instrumentation. E.g., binary 9b3a05f8927a35b011f23eae30c9f11f8dcae299f3f400d7960a8aa20cec7a27.wasm from WasmBench contains a function with >50k locals after instrumentation, which trips wasm-validate from WABT with the error

error: function local count exceeds maximum value

A workaround is to optimize the instrumented files with wasm-opt from Binaryen, i.e. run wasm-opt -Os <instrumented.wasm> -o <instrumented-smaller.wasm>

Wasabi be killed

I tried to use wasabi to analyze opencv.js but it was killed everytime I implemented it to opencv_js.wasm:
$wasabi opencv_js.wasm
and the result goes:
Killed

Is it because this opencv_js.wasm is too large(5.4MB)?

Wasabi.resolveTableIdx implementation needs fixing

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:

const functionIdx = parseInt(Wasabi.module.table.get(tableIdx).name);


If we look at what happens when we do wasm-objdump -x for an instrumented binary we will get this:

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.

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.

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! 🎉

hook function

i want to hook at a start of a function and see it's arguments, how can i do it ?

Long.js dependency with Node.js application (ReferenceError: Long is not defined)

Hi Daniel,

first some informations about the situation:

  • program written in c compiled to .wasm binary with emscripten
  • instrumenting binary with wasabi
  • execution in NodeJS through emscriptens generated module object with ccall or cwrap

I keep getting the error ReferenceError: Long is not defined which is thrown by the js-glue code from emscripten. I think this problem is caused by i64 instructions and their low level hooks, since a new Long-object is generated in each of them. Long is not in the scope of the js-glue from emscripten.

Did you ever faced this issue and maybe have a fix/workaround for this? I thought about somehow adding Long to the js-glue codes scope but i don't know how and if this is even the right solution for this problem.

ReferenceError: Long is not defined
/path/to/emscriptens/glue_code.js:196
      throw ex;
      ^

RuntimeError: abort(ReferenceError: Long is not defined) at Error
    at jsStackTrace (/path/to/emscriptens/glue_code.js:1752:19)
    at stackTrace (/path/to/emscriptens/glue_code.js:1769:16)
    at process.abort (/path/to/emscriptens/glue_code.js:1463:44)
    at process.emit (events.js:198:13)
    at emitPromiseRejectionWarnings (internal/process/promises.js:140:18)
    at process._tickCallback (internal/process/next_tick.js:69:34)
    at process.abort (/path/to/emscriptens/glue_code.js:1469:11)
    at process.emit (events.js:198:13)
    at emitPromiseRejectionWarnings (internal/process/promises.js:140:18)
    at process._tickCallback (internal/process/next_tick.js:69:34)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.