Просмотр исходного кода

Add scripts to validate lldb source debugger (#2150)

Xu Jun 2 лет назад
Родитель
Сommit
25a1985413
2 измененных файлов с 149 добавлено и 0 удалено
  1. 25 0
      .github/workflows/build_wamr_lldb.yml
  2. 124 0
      ci/validate_lldb.py

+ 25 - 0
.github/workflows/build_wamr_lldb.yml

@@ -22,6 +22,12 @@ on:
         description: a semantic version number
         type: string
         required: true
+      wasi_sdk_url:
+        description: download WASI_SDK from this URL
+        type: string
+        required: false
+        default: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz"
+      
 
 jobs:
   try_reuse:
@@ -43,6 +49,15 @@ jobs:
       PYTHON_MACOS_STANDALONE_BUILD: https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-apple-darwin-install_only.tar.gz
     steps:
       - uses: actions/checkout@v3
+      
+      - name: download and install wasi-sdk
+        run: |
+          cd /opt
+          basename=$(basename ${{ inputs.wasi_sdk_url }})
+          sudo wget --progress=dot:giga ${{ inputs.wasi_sdk_url }}
+          sudo tar -xzf ${basename}
+          sudo rm ${basename}
+          sudo mv wasi-sdk-* wasi-sdk
 
       - name: Cache build
         id: lldb_build_cache
@@ -141,6 +156,16 @@ jobs:
           cmake --build build --target lldb install --parallel $(nproc)
         working-directory: core/deps/llvm-project
 
+      - name: validate lldb ubuntu
+        if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'ubuntu')
+        run: |
+          echo "start to validate lldb..."
+          mkdir -p wamr-debug
+          cmake -S product-mini/platforms/linux -B wamr-debug -DWAMR_BUILD_DEBUG_INTERP=1
+          cmake --build wamr-debug --parallel $(nproc)
+          python3 ci/validate_lldb.py --port 1239 --lldb core/deps/wamr-lldb/bin/lldb --wamr wamr-debug/iwasm --verbose
+        working-directory: .
+
       - name: build lldb macos
         if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos')
         run: |

+ 124 - 0
ci/validate_lldb.py

@@ -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)