|
|
@@ -0,0 +1,124 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+#
|
|
|
+# Copyright (C) 2023 Intel Corporation. All rights reserved.
|
|
|
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
+#
|
|
|
+
|
|
|
+import argparse
|
|
|
+import time
|
|
|
+from pathlib import Path
|
|
|
+import subprocess, shlex
|
|
|
+
|
|
|
+SCRIPT_DIR = Path(__file__).parent.resolve()
|
|
|
+REPO_ROOT_DIR = SCRIPT_DIR.parent
|
|
|
+SAMPLE_CODE_FILE = REPO_ROOT_DIR / 'product-mini/app-samples/hello-world/main.c'
|
|
|
+WASM_OUT_FILE = SCRIPT_DIR / 'out.wasm'
|
|
|
+
|
|
|
+parser = argparse.ArgumentParser(
|
|
|
+ description="Validate the customized lldb with sample code"
|
|
|
+)
|
|
|
+parser.add_argument(
|
|
|
+ "-l", "--lldb", dest='lldb', default='lldb', help="path to lldb executable"
|
|
|
+)
|
|
|
+parser.add_argument(
|
|
|
+ "-w", "--wamr", dest='wamr', default='iwasm', help="path to iwasm executable"
|
|
|
+)
|
|
|
+parser.add_argument(
|
|
|
+ "-p", "--port", dest='port', default='1234', help="debug server listen port"
|
|
|
+)
|
|
|
+parser.add_argument(
|
|
|
+ "-v", "--verbose", dest='verbose', action='store_true', default=False, help="display lldb stdout"
|
|
|
+)
|
|
|
+
|
|
|
+options = parser.parse_args()
|
|
|
+
|
|
|
+lldb_command_prologue = f'{options.lldb} -o "process connect -p wasm connect://127.0.0.1:{options.port}"'
|
|
|
+lldb_command_epilogue = '-o q'
|
|
|
+
|
|
|
+test_cases = {
|
|
|
+ 'run_to_exit': '-o c',
|
|
|
+ 'func_breakpoint': '-o "b main" -o c -o c',
|
|
|
+ 'line_breakpoint': '-o "b main.c:12" -o c -o c',
|
|
|
+ 'break_on_unknown_func': '-o "b not_a_func" -o c',
|
|
|
+ 'watch_point': '-o "b main" -o c -o "watchpoint set variable buf" -o c -o "fr v buf" -o c',
|
|
|
+}
|
|
|
+
|
|
|
+# Step1: Build wasm module with debug information
|
|
|
+build_cmd = f'/opt/wasi-sdk/bin/clang -g -O0 -o {WASM_OUT_FILE} {SAMPLE_CODE_FILE}'
|
|
|
+try:
|
|
|
+ print(f'building wasm module ...', end='', flush=True)
|
|
|
+ subprocess.check_call(shlex.split(build_cmd))
|
|
|
+ print(f'\t OK')
|
|
|
+except subprocess.CalledProcessError:
|
|
|
+ print("Failed to build wasm module with debug information")
|
|
|
+ exit(1)
|
|
|
+
|
|
|
+def print_process_output(p):
|
|
|
+ try:
|
|
|
+ outs, errs = p.communicate(timeout=2)
|
|
|
+ print("stdout:")
|
|
|
+ print(outs)
|
|
|
+ print("stderr:")
|
|
|
+ print(errs)
|
|
|
+ except subprocess.TimeoutExpired:
|
|
|
+ print("Failed to get process output")
|
|
|
+
|
|
|
+# Step2: Launch WAMR in debug mode and validate lldb commands
|
|
|
+wamr_cmd = f'{options.wamr} -g=127.0.0.1:{options.port} {WASM_OUT_FILE}'
|
|
|
+for case, cmd in test_cases.items():
|
|
|
+ has_error = False
|
|
|
+ print(f'validating case [{case}] ...', end='', flush=True)
|
|
|
+ lldb_cmd = f'{lldb_command_prologue} {cmd} {lldb_command_epilogue}'
|
|
|
+
|
|
|
+ wamr_process = subprocess.Popen(shlex.split(
|
|
|
+ wamr_cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
|
|
|
+
|
|
|
+ time.sleep(0.1)
|
|
|
+ if (wamr_process.poll() != None):
|
|
|
+ print("\nWAMR doesn't wait for lldb connection")
|
|
|
+ print_process_output(wamr_process)
|
|
|
+ exit(1)
|
|
|
+
|
|
|
+ lldb_process = subprocess.Popen(shlex.split(
|
|
|
+ lldb_cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
|
|
|
+
|
|
|
+ if (options.verbose):
|
|
|
+ while (lldb_process.poll() is None):
|
|
|
+ print(lldb_process.stdout.read(), end='', flush=True)
|
|
|
+
|
|
|
+ try:
|
|
|
+ if (lldb_process.wait(5) != 0):
|
|
|
+ print(f"\nFailed to validate case [{case}]")
|
|
|
+ print_process_output(lldb_process)
|
|
|
+ has_error = True
|
|
|
+
|
|
|
+ if wamr_process.wait(2) != 0:
|
|
|
+ print("\nWAMR process doesn't exit normally")
|
|
|
+ print_process_output(wamr_process)
|
|
|
+ has_error = True
|
|
|
+
|
|
|
+ except subprocess.TimeoutExpired:
|
|
|
+ print(f"\nFailed to validate case [{case}]")
|
|
|
+ print("wamr output:")
|
|
|
+ print_process_output(wamr_process)
|
|
|
+ print("lldb output:")
|
|
|
+ print_process_output(lldb_process)
|
|
|
+ has_error = True
|
|
|
+ finally:
|
|
|
+ if (lldb_process.poll() == None):
|
|
|
+ print(f'\nterminating lldb process [{lldb_process.pid}]')
|
|
|
+ lldb_process.kill()
|
|
|
+ if (wamr_process.poll() == None):
|
|
|
+ print(f'terminating wamr process [{wamr_process.pid}]')
|
|
|
+ wamr_process.kill()
|
|
|
+
|
|
|
+ if (has_error):
|
|
|
+ exit(1)
|
|
|
+
|
|
|
+ print(f'\t OK')
|
|
|
+
|
|
|
+ # wait 100ms to ensure the socket is closed
|
|
|
+ time.sleep(0.1)
|
|
|
+
|
|
|
+print('Validate lldb success')
|
|
|
+exit(0)
|