diff --git a/.devcontainer/install-deps.sh b/.devcontainer/install-deps.sh index e2ff43e6..043c5c44 100755 --- a/.devcontainer/install-deps.sh +++ b/.devcontainer/install-deps.sh @@ -18,6 +18,7 @@ sudo apt-get install -y --no-install-recommends \ build-essential \ device-tree-compiler \ gperf g++-multilib gcc-multilib \ + gdb-multiarch \ libnl-3-dev libdbus-1-dev libelf-dev libmpc-dev dwarves \ bc openssl flex bison libssl-dev python3 python-is-python3 texinfo kmod cmake \ wget zstd \ diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..710996cc --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,28 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "GDB Debug - Native (binary)", + "type": "cppdbg", + "request": "launch", + "program": "internal/native/cgo/build/jknative-bin", + "args": [], + "stopAtEntry": true, + "cwd": "${workspaceFolder}", + "environment": [], + "MIMode": "gdb", + "miDebuggerPath": "/usr/bin/gdb-multiarch", + "miDebuggerServerAddress": "${config:TARGET_IP}:${config:DEBUG_PORT}", + "targetArchitecture": "arm", + "preLaunchTask": "deploy", + "setupCommands": [ + { + "description": "Pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "externalConsole": true + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 6ac6925b..118dd5ed 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,5 +14,12 @@ "cmake.ignoreCMakeListsMissing": true, "C_Cpp.inlayHints.autoDeclarationTypes.enabled": true, "C_Cpp.inlayHints.parameterNames.enabled": true, - "C_Cpp.inlayHints.referenceOperator.enabled": true + "C_Cpp.inlayHints.referenceOperator.enabled": true, + "files.associations": { + "*.yml": "yaml", + "*.libsonet": "jsonnet", + "rk_comm_mb.h": "c" + }, + "TARGET_IP": "192.168.0.199", + "DEBUG_PORT": "2345", } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..e1f9accc --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,30 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "deploy", + "isBackground": true, + "type": "shell", + "command": "bash", + "args": [ + "dev_deploy.sh", + "-r", + "${config:TARGET_IP}", + "--gdb-port", + "${config:DEBUG_PORT}", + "--native-binary", + "--disable-docker" + ], + "problemMatcher": { + "base": "$gcc", + "background": { + "activeOnStart": true, + "beginsPattern": "${config:BINARY}", + "endsPattern": "Listening on port [0-9]{4}" + } + } + }, + ] +} diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 0ab65c4f..9d3a4b62 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -208,6 +208,12 @@ rm /userdata/kvm_config.json systemctl restart jetkvm ``` +### Debug native code with gdbserver + +Change the `TARGET_IP` in `.vscode/settings.json` to your JetKVM device IP, then set breakpoints in your native code and start the `Debug Native` configuration in VSCode. + +The code and GDB server will be deployed automatically. + --- ## Testing Your Changes diff --git a/Makefile b/Makefile index e519a75a..525114e3 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,8 @@ SKIP_NATIVE_IF_EXISTS ?= 0 SKIP_UI_BUILD ?= 0 ENABLE_SYNC_TRACE ?= 0 +CMAKE_BUILD_TYPE ?= Release + GO_BUILD_ARGS := -tags netgo,timetzdata,nomsgpack ifeq ($(ENABLE_SYNC_TRACE), 1) GO_BUILD_ARGS := $(GO_BUILD_ARGS),synctrace @@ -52,6 +54,7 @@ build_native: echo "Building native..."; \ CC="$(BUILDKIT_PATH)/bin/$(BUILDKIT_FLAVOR)-gcc" \ LD="$(BUILDKIT_PATH)/bin/$(BUILDKIT_FLAVOR)-ld" \ + CMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \ ./scripts/build_cgo.sh; \ fi diff --git a/scripts/build_cgo.sh b/scripts/build_cgo.sh index 87577e39..d67fa7cd 100755 --- a/scripts/build_cgo.sh +++ b/scripts/build_cgo.sh @@ -4,6 +4,8 @@ set -e SCRIPT_PATH=$(realpath "$(dirname $(realpath "${BASH_SOURCE[0]}"))") source ${SCRIPT_PATH}/build_utils.sh +CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-Release} + CGO_PATH=$(realpath "${SCRIPT_PATH}/../internal/native/cgo") BUILD_DIR=${CGO_PATH}/build @@ -31,7 +33,7 @@ VERBOSE=1 cmake -B "${BUILD_DIR}" \ -DCONFIG_LV_BUILD_EXAMPLES=OFF \ -DCONFIG_LV_BUILD_DEMOS=OFF \ -DSKIP_GLIBC_NAMES=ON \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \ -DCMAKE_INSTALL_PREFIX="${TMP_DIR}" msg_info "▶ Copying built library and header files" diff --git a/scripts/dev_deploy.sh b/scripts/dev_deploy.sh index 519206ea..96e7cf60 100755 --- a/scripts/dev_deploy.sh +++ b/scripts/dev_deploy.sh @@ -12,6 +12,7 @@ show_help() { echo echo "Optional:" echo " -u, --user Remote username (default: root)" + echo " --gdb-port GDB debug port (default: 2345)" echo " --run-go-tests Run go tests" echo " --run-go-tests-only Run go tests and exit" echo " --skip-ui-build Skip frontend/UI build" @@ -59,6 +60,7 @@ REMOTE_PATH="/userdata/jetkvm/bin" SKIP_UI_BUILD=false SKIP_UI_BUILD_RELEASE=0 SKIP_NATIVE_BUILD=0 +GDB_DEBUG_PORT=2345 BUILD_NATIVE_BINARY=false ENABLE_SYNC_TRACE=0 RESET_USB_HID_DEVICE=false @@ -81,6 +83,10 @@ while [[ $# -gt 0 ]]; do REMOTE_USER="$2" shift 2 ;; + --gdb-port) + GDB_DEBUG_PORT="$2" + shift 2 + ;; --skip-ui-build) SKIP_UI_BUILD=true shift @@ -148,7 +154,8 @@ fi check_ping "${REMOTE_HOST}" check_ssh "${REMOTE_USER}" "${REMOTE_HOST}" function sshdev() { - ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "${REMOTE_USER}@${REMOTE_HOST}" $@ + ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "${REMOTE_USER}@${REMOTE_HOST}" "$@" + return $? } # check if the current CPU architecture is x86_64 @@ -163,10 +170,17 @@ fi if [ "$BUILD_NATIVE_BINARY" = true ]; then msg_info "▶ Building native binary" - make build_native - sshdev "killall -9 jetkvm_app jetkvm_app_debug jetkvm_native_debug || true" + CMAKE_BUILD_TYPE=Debug make build_native + msg_info "▶ Checking if GDB is available on remote host" + if ! sshdev "command -v gdbserver > /dev/null 2>&1"; then + msg_warn "Error: gdbserver is not installed on the remote host" + tar -czf - -C /opt/jetkvm-native-buildkit/gdb/ . | sshdev "tar -xzf - -C /usr/bin" + msg_info "✓ gdbserver installed on remote host" + fi + msg_info "▶ Stopping any existing instances of jetkvm_native_debug on remote host" + sshdev "killall -9 jetkvm_app jetkvm_app_debug jetkvm_native_debug gdbserver || true >> /dev/null 2>&1" sshdev "cat > ${REMOTE_PATH}/jetkvm_native_debug" < internal/native/cgo/build/jknative-bin - sshdev ash << EOF + sshdev -t ash << EOF set -e # Set the library path to include the directory where librockit.so is located @@ -177,7 +191,7 @@ killall -9 jetkvm_app jetkvm_app_debug jetkvm_native_debug || true sleep 5 echo 'V' > /dev/watchdog chmod +x jetkvm_native_debug -./jetkvm_native_debug +gdbserver localhost:${GDB_DEBUG_PORT} ./jetkvm_native_debug EOF exit 0 fi