mirror of
				https://github.com/bytecodealliance/wasm-micro-runtime.git
				synced 2025-10-31 05:11:19 +00:00 
			
		
		
		
	 480ee02615
			
		
	
	
		480ee02615
		
			
		
	
	
	
	
		
			
			``` shell $ python3 append_aot_to_wasm.py --wasm waf.wasm --aot waf.aot -o waf.aot.wasm $ /opt/wabt-1.0.34/bin/wasm-objdump -h waf.aot.wasm | grep wamr-aot Custom start=0x007520c7 end=0x00e021a0 (size=0x006b00d9) "wamr-aot" $ python3 append_aot_to_wasm.py --wasm waf.wasm --aot waf.aot --ver-str 2.0.0 -o waf.aot.wasm $ /opt/wabt-1.0.34/bin/wasm-objdump -h waf.aot.wasm | grep wamr-aot Custom start=0x007520c7 end=0x00e021a4 (size=0x006b00dd) "wamr-aot-2.0.0" ```
		
			
				
	
	
		
			168 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/env python3
 | |
| #
 | |
| # Copyright (C) 2019 Intel Corporation.  All rights reserved.
 | |
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| #
 | |
| """
 | |
| It is used to append a .aot to a .wasm as a custom section.
 | |
| The custom section name is "aot".
 | |
| 
 | |
| e.g.
 | |
| $ python3 append_aot_to_wasm.py --wasm quicksort.wasm --aot quicksort.aot --output quicksort.aot.wasm
 | |
| """
 | |
| 
 | |
| import argparse
 | |
| from pathlib import Path
 | |
| 
 | |
| 
 | |
| def leb128_encode_uint(value: int) -> bytes:
 | |
|     """
 | |
|     encode unsigned int into a leb128 bytes
 | |
|     """
 | |
|     binary = []
 | |
|     while value != 0:
 | |
|         lower_7_bits = value & 0x7F
 | |
|         value >>= 7
 | |
| 
 | |
|         if value != 0:
 | |
|             current_byte = 0x80 | lower_7_bits
 | |
|         else:
 | |
|             current_byte = 0x00 | lower_7_bits
 | |
| 
 | |
|         binary.append(current_byte)
 | |
| 
 | |
|     return bytes(binary)
 | |
| 
 | |
| 
 | |
| def leb128_decode_uint(binary: bytes) -> (int, int):
 | |
|     """
 | |
|     decode binary unsigned from a leb128 bytes
 | |
|     """
 | |
| 
 | |
|     result = 0
 | |
|     shift = 0
 | |
|     for i, b in enumerate(binary):
 | |
|         lower_7_bits = b & 0x7F
 | |
|         result |= lower_7_bits << shift
 | |
| 
 | |
|         highest_bit = b & 0x80
 | |
|         if not highest_bit:
 | |
|             break
 | |
| 
 | |
|         shift += 7
 | |
| 
 | |
|     return i + 1, result
 | |
| 
 | |
| 
 | |
| def is_aligned(n: int, alignment: int):
 | |
|     return (n & (alignment - 1)) == 0
 | |
| 
 | |
| 
 | |
| def align_up(n: int, alignment: int):
 | |
|     return n + (alignment - 1) & ~(alignment - 1)
 | |
| 
 | |
| 
 | |
| def present_as_vector(content: bytes) -> bytes:
 | |
|     v_l = len(content)
 | |
|     v_bin = leb128_encode_uint(v_l) if v_l else b"\x00"
 | |
|     return v_bin + content
 | |
| 
 | |
| 
 | |
| def calc_padding(
 | |
|     alignment: int, name_bin_len: int, content_len: int, start_pos: int
 | |
| ) -> bytes:
 | |
|     for padding in range(alignment * 2):
 | |
|         padding_bin = present_as_vector(b"\x00" * padding)
 | |
|         section_length = name_bin_len + len(padding_bin) + content_len
 | |
|         section_length_bin = leb128_encode_uint(section_length)
 | |
| 
 | |
|         pos = start_pos + 1 + len(section_length_bin) + name_bin_len + len(padding_bin)
 | |
|         if is_aligned(pos, alignment):
 | |
|             return padding_bin
 | |
| 
 | |
| 
 | |
| def build_content(content: bytes, pos: int, adding: bytes) -> (int, bytes):
 | |
|     return pos + len(adding), content + adding
 | |
| 
 | |
| 
 | |
| def create_custom_section_aligned(
 | |
|     start_pos: int, name: str, content: bytes, alignment: int = 4
 | |
| ) -> bytes:
 | |
|     """
 | |
|         be sure the section_content starts at a X alignment position
 | |
| 
 | |
|           1B
 | |
|         | \x00 | length | name vec | padding vec | content |
 | |
|         ^                                        ^
 | |
|         |                                        |
 | |
|     start address                           aligned address
 | |
|     """
 | |
| 
 | |
|     name_bin = present_as_vector(name.encode("ascii"))
 | |
|     padding_bin = calc_padding(alignment, len(name_bin), len(content), start_pos)
 | |
| 
 | |
|     full_content_bin = b""
 | |
|     pos = start_pos
 | |
| 
 | |
|     # custome section id 0
 | |
|     pos, full_content_bin = build_content(full_content_bin, pos, b"\x00")
 | |
| 
 | |
|     # custom section length
 | |
|     section_length = len(name_bin) + len(padding_bin) + len(content)
 | |
|     section_length_bin = leb128_encode_uint(section_length)
 | |
|     pos, full_content_bin = build_content(full_content_bin, pos, section_length_bin)
 | |
| 
 | |
|     # custom section name
 | |
|     pos, full_content_bin = build_content(full_content_bin, pos, name_bin)
 | |
| 
 | |
|     # padding
 | |
|     pos, full_content_bin = build_content(full_content_bin, pos, padding_bin)
 | |
|     assert is_aligned(pos, alignment), f"{pos} is not aligned to {alignment}"
 | |
| 
 | |
|     print(f"append .aot @ offset {pos}(0x{pos:X})")
 | |
|     _, full_content_bin = build_content(full_content_bin, pos, content)
 | |
| 
 | |
|     return full_content_bin
 | |
| 
 | |
| 
 | |
| def main(wasm_file: str, aot_file: str, output: str, ver_str: str) -> None:
 | |
|     cwd = Path.cwd()
 | |
|     wasm_file = cwd.joinpath(wasm_file).resolve()
 | |
|     aot_file = cwd.joinpath(aot_file).resolve()
 | |
|     output = cwd.joinpath(output).resolve()
 | |
| 
 | |
|     assert wasm_file.exists()
 | |
|     assert aot_file.exists()
 | |
|     output.unlink(missing_ok=True)
 | |
| 
 | |
|     # read aot content
 | |
|     with open(aot_file, "rb") as f:
 | |
|         aot_content = f.read()
 | |
| 
 | |
|     # append to .wasm
 | |
|     with open(wasm_file, "rb") as f_in, open(output, "wb") as f_out:
 | |
|         wasm_content = f_in.read(1024)
 | |
|         while wasm_content:
 | |
|             f_out.write(wasm_content)
 | |
|             wasm_content = f_in.read(1024)
 | |
| 
 | |
|         section_name = f"wamr-aot-{ver_str}" if ver_str else "wamr-aot"
 | |
|         f_out.write(
 | |
|             create_custom_section_aligned(f_out.tell(), section_name, aot_content, 4)
 | |
|         )
 | |
| 
 | |
|     print(f"{wasm_file.name} + {aot_file.name} ==> {output}")
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     argparse = argparse.ArgumentParser()
 | |
|     argparse.add_argument("--wasm", help="a .wasm")
 | |
|     argparse.add_argument("--aot", help="a .aot")
 | |
|     argparse.add_argument(
 | |
|         "--ver-str", help="a version string will be used to construct section name"
 | |
|     )
 | |
|     argparse.add_argument("-o", "--output", help="the output, still be a .wasm")
 | |
| 
 | |
|     args = argparse.parse_args()
 | |
|     main(args.wasm, args.aot, args.output, args.ver_str)
 |