summaryrefslogtreecommitdiffstats
path: root/util/wasm/preload/wasm_binary_tools.py
diff options
context:
space:
mode:
Diffstat (limited to 'util/wasm/preload/wasm_binary_tools.py')
-rw-r--r--util/wasm/preload/wasm_binary_tools.py78
1 files changed, 78 insertions, 0 deletions
diff --git a/util/wasm/preload/wasm_binary_tools.py b/util/wasm/preload/wasm_binary_tools.py
new file mode 100644
index 0000000000..9a2150b964
--- /dev/null
+++ b/util/wasm/preload/wasm_binary_tools.py
@@ -0,0 +1,78 @@
+
+#!/usr/bin/env python3
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import sys
+import struct
+
+
+class WasmBinary:
+ """For reference of binary format see Emscripten source code, especially library_dylink.js."""
+
+ def __init__(self, filepath):
+ self._offset = 0
+ self._end = 0
+ self._dependencies = []
+ with open(filepath, 'rb') as file:
+ self._binary = file.read()
+ self._check_preamble()
+ self._parse_subsections()
+
+ def get_dependencies(self):
+ return self._dependencies
+
+ def _get_leb(self):
+ ret = 0
+ mul = 1
+ while True:
+ byte = self._binary[self._offset]
+ self._offset += 1
+ ret += (byte & 0x7f) * mul
+ mul *= 0x80
+ if not (byte & 0x80):
+ break
+ return ret
+
+ def _get_string(self):
+ length = self._get_leb()
+ self._offset += length
+ return self._binary[self._offset - length:self._offset].decode('utf-8')
+
+ def _check_preamble(self):
+ preamble = memoryview(self._binary)[:24]
+ int32View = struct.unpack('<6I', preamble)
+ assert int32View[0] == 0x6d736100, "magic number not found"
+ assert self._binary[8] == 0, "dynlink section needs to be first"
+ self._offset = 9
+ section_size = self._get_leb()
+ self._end = self._offset + section_size
+ name = self._get_string()
+ assert name == "dylink.0", "section dylink.0 not found"
+
+ def _parse_subsections(self):
+ WASM_DYLINK_NEEDED = 0x2
+
+ while self._offset < self._end:
+ subsection_type = self._binary[self._offset]
+ self._offset += 1
+ subsection_size = self._get_leb()
+
+ if subsection_type == WASM_DYLINK_NEEDED:
+ needed_dynlibs_count = self._get_leb()
+ for _ in range(needed_dynlibs_count):
+ self._dependencies.append(self._get_string())
+ else:
+ self._offset += subsection_size # we don't care about other sections for now
+
+
+if __name__ == "__main__":
+ if len(sys.argv) != 2:
+ print("Usage: python wasm_binary_tools.py <shared_object>")
+ sys.exit(1)
+
+ file_path = sys.argv[1]
+ binary = WasmBinary(file_path)
+ dependencies = binary.get_dependencies()
+ for d in dependencies:
+ print(d)