Foreword

What is WebAssembly?

Here are the definitions from the official:

WebAssembly or wasm is a new portable, size- and load-time-efficient format suitable for compilation to the web.

Keywords: "format", WebAssembly is an encoding format suitable for compiling to the web.

In fact, WebAssembly can be seen as an enhancement to JavaScript that compensates for the flaws in JavaScript’s execution efficiency.

  • It is a new language that defines an AST and can be expressed in bytecode format.
  • It is a browser enhancement that allows the browser to directly understand WebAssembly and turn it into machine code.
  • It is a target language, and any other language can be compiled into WebAssembly to run on the browser.

Imagine that in computer vision, game animation, video encoding and decoding, data encryption, etc., which require high computational complexity, if you want to implement it on a browser and support it across browsers, the only thing you can do is to use JavaScript to run. It is a thankless thing. WebAssembly can directly compile existing libraries written in C, C++ into WebAssembly and run them on the browser, and can be referenced as JavaScript by the library. That means we can move a lot of back-end work to the front end, reducing the pressure on the server. This is the most attractive feature of WebAssembly. And WebAssembly is running in the sandbox to ensure its security.

For more information on the basics of WebAssembly, you can read this article: https://segmentfault.com/a/1190000012110615, written in great detail.

(The following will mainly use the wasm name to represent WebAssembly)

How to debug?

People who know a little about javascript should know that it is very convenient to add breakpoints, view variables, single-step execution, etc. to the js code in the developer panel of chrome or firefox. It is very convenient!

Since wasm is mainly run on a web browser (of course, it can also be run in a non-web environment, see the official documentation: http://webassembly.org/docs/non-web/), the main debugging method is nothing more than Is using the developer console!

But the problem is that the above mentioned wasm is a binary format. Although there is a readable text format wast, it is still very difficult to debug. The main question is: Do you want to be able to debug it? Compile the previous c/c++ source code?

Debugging exploration

I searched a lot of information and took a lot of detours. I finally found a feasible way to debug! (Of course, if you have a better debugging method, please let me know!?)

Environment & Tool Preparation

Note: If you want to customize your own wasm compilation environment [docker] (https://blog.zhouzhipeng.com/walk-in-docker-beginning.html) image, it is strongly recommended to refer to the official documentation steps in Ubuntu: http ://webassembly.org/getting-started/developers-guide/

Experiment code preparation

Github address: https://github.com/zhouzhipeng/wasm-debug-test

  1. Write a simple c program to find the sum of the squares of the two numbers

debug.c

Int sumOfSquare(int a,int b){
Int t1=a*a;
Int t2=b*b;
Return t1+t2;
}
  1. Compile debug.c —> debug.wasm

Use the docker image from the previous section: zhouzhipeng/wasm-build

#1. First run wasm to compile the docker container (mirror hosted in the docker official hub, it may be slow, please be patient)
➜ wasm-debug-test git:(master) ✗ docker run -it --name wasm-test -v $(pwd):/data/ zhouzhipeng/wasm-build bash

#2. Compile debug.c as debug.wasm file
Root@f4d3ee71bec8:/data# cd /data/
Root@f4d3ee71bec8:/data# emcc debug.c -O1 -s WASM=1 -s SIDE_MODULE=1 -o debug.wasm

Note: For details on the emcc command, refer to: [http://kripken.github.io/emscripten-site/docs/compiling/WebAssembly.html] (http://kripken.github.io/emscripten-site/ Docs/compiling/WebAssembly.html)

  1. Write a test page

Say the general logic: the page is loaded with the debug.wasm file and initialized, the click event is bound to the button on the page, and the sumOfSquare function in debug.c above is called when clicked.

debug.html

<html>
<head>
  <script>
    // The following configuration is used as the wasm initialization, and removing one will report an error.
    Const importObj = {
        Env: {
            Memory: new WebAssembly.Memory({initial: 256, maximum: 256}),
            memoryBase: 0,
            tableBase: 0,
            Table: new WebAssembly.Table({initial: 10, element: 'anyfunc'}),
            Abort:function(){}
        }
    };

  
  // Directly using WebAssembly.instantiateStream will report an error, saying that the debug.wasm resource is not in application/wasm format s.
  Fetch('./debug.wasm').then(response =>
    response.arrayBuffer()
  ).then(bytes => WebAssembly.instantiate(bytes,importObj)).then(results => {
    Instance = results.instance;
    Var sumOfSquare= instance.exports._sumOfSquare; //Note that the method name exported here is underlined!!

     Var button = document.getElementById('run');
     button.addEventListener('click', function() {
          Var input1 = 3;
          Var input2 = 4;
          Alert('sumOfSquare('+input1+','+input2+')='+sumOfSquare(input1,input2));
     }, false);
  });

  </script>
</head>
<body>
  <input type="button" id="run" value="click"/>
</body>
</html>
  1. Run the viewing effect

For the sake of simplicity, start a http service temporarily in the current directory with python:

➜ wasm-debug-test git:(master) ✗ python -m SimpleHTTPServer 8081
Serving HTTP on 0.0.0.0 port 8081 ...

Open the Firefox Developer Edition browser to access: http://localhost:8081/debug.html

Click the click button:

Very good, everything works fine. Next, try to use breakpoint debugging, and look at local variables and so on.

Basic debugging

Go to the debugger panel and find the following file (wasm’s visual text format, is it similar to the assembly instructions?! So the name comes with assembly, haha?)

And make a breakpoint at the corresponding line of code:

Ok, let’s go ahead and click the "click" button again, the breakpoint will come in:

Note that the local variable var0, var1 in the red box above is our input1 and input2.

 You can then step through it (note that it is not the step over button next to it, it is the step in !! shown by the arrow! Could it be a bug?):

A little understanding of the function stack should know: the above instructions such as get_local, i32.mul, etc. will perform a series of stacking and pop operations, so you can’t see the temporary variables t1, t2 we defined at the time, it is directly The top element of the stack.

Firefox can’t see the elements in the stack stack. In the following advanced debugging, the chrome browser will be used to demonstrate. Interested visitors should continue to look down! !

Advanced debugging

Nima, say good debugging c / c + + source code! ! ! !

Need to debug c source code, the previous emcc compiler command needs to add some parameters, associated with source map:

Root@f4d3ee71bec8:/data# emcc debug.c -O1 -s WASM=1 -s SIDE_MODULE=1 -o debug.wasm -g4 --source-map-base http://localhost:8081/

Root@f4d3ee71bec8:/data# ls
README.md debug.c debug.html debug.wasm debug.wasm.map debug.wast

As you can see, there are three files in total: debug.wasm, debug.wasm.map, debug.wast

Handling debug.wasm (binary) can’t be viewed, others can be seen:

Root@f4d3ee71bec8:/data# cat debug.wast
(module
 (type $FUNCSIG$vi (func (param i32)))
 (import "env" "table" (table 2 anyfunc))
 (import "env" "memoryBase" (global $memoryBase i32))
 (import "env" "tableBase" (global $tableBase i32))
 (import "env" "abort" (func $abort (param i32)))
 (global $STACKTOP (mut i32) (i32.const 0))
 (global $STACK_MAX (mut i32) (i32.const 0))
 (global $fp$_sumOfSquare i32 (i32.const 1))
 (elem (get_global $tableBase) $b0 $_sumOfSquare)
 (export "__post_instantiate" (func $__post_instantiate))
 (export "_sumOfSquare" (func $_sumOfSquare))
 (export "runPostSets" (func $runPostSets))
 (export "fp$_sumOfSquare" (global $fp$_sumOfSquare))
 (func $_sumOfSquare (; 1 ;) (param $0 i32) (param $1 i32) (result i32)
  ;;@debug.c:2:0
  (set_local $0
   (i32.mul
    (get_local $0)
    (get_local $0)
   )
  )
.... the latter content is omitted
Root@f4d3ee71bec8:/data# cat debug.wasm.map
{"version":3,"sources":["debug.c"],"names":[],"mappings":"mNACA,OACA,OACA"}

Is there a feeling of great understanding! It’s a lot like the js that is confused with debugging.

Refresh your browser and take a look:

One more debug.c! Yes, indicating that our sourcemap is in effect, and we have a breakpoint on the second line.

Click the click button and click on it:

A little embarrassed, I clearly hit the second line, but the breakpoint entered the third line. . . (beta version.)

Even more catchy is that the red box in the upper right corner of the above picture, the variable a can not be viewed! ! ? A little sad, but fortunately, the local variables in the lower right corner can still look at it.

So my suggestion is: Make a breakpoint in debug.c, and then go to debug.html:xxxx to step through, as follows, you can double-click to enter, the breakpoint state is synchronized:

Filling the pit

In the [Basic Debugging] section, I left a hole and said that I can use chrome to see the status of the stack stack at runtime. Let’s take a screenshot to prove that I am not lying? :

Seeing the red arrow, did you think of get_local 0 , which is actually pushing our input1 (3) onto the stack. You can step through the stack/stack effect step by step.

Another: chromd can also debug wast, but it splits the content into a lot of small parts, which is not convenient for debugging. But the advantage is that there is a stack view function than the Firefox development version. Very practical! !

to sum up

  1. Run the image of the wasm build environment: zhouzhipeng/wasm-build
  2. Compile command: emcc debug.c -O1 -s WASM=1 -s SIDE_MODULE=1 -o debug.wasm -g4 --source-map-base http://localhost:8081/
  3. This article demonstrates the source code address: https://github.com/zhouzhipeng/wasm-debug-test

Official tool recommendation:

references

Last modified: 2019年3月29日

Author

Comments

开发者头条 

感谢分享!已推荐到《开发者头条》:https://toutiao.io/posts/z29mwp 欢迎点赞支持!
使用开发者头条 App 搜索 185910 即可订阅《CodingAir》

Write a Reply or Comment

Your email address will not be published.