diff --git a/demos/README.md b/demos/README.md index 3933dcb8..b3da3869 100644 --- a/demos/README.md +++ b/demos/README.md @@ -23,5 +23,6 @@ This set of demos shows how real-world apps can be easily run inside SGX enclave ## Other demos -* `remote_attestation/`: This project demonstrates how an app running upon Occlum can perform SGX remote attestation. * `embedded_mode/`: A cross-enclave memory throughput benchmark enabled by the embedded mode of Occlum. +* `gdb_support/`: This demo explains the technical detail of GDB support and demonstrates how to debug an app running upon Occlum with GDB. +* `remote_attestation/`: This project demonstrates how an app running upon Occlum can perform SGX remote attestation. diff --git a/demos/gdb_support/.gitignore b/demos/gdb_support/.gitignore new file mode 100644 index 00000000..486f2cc1 --- /dev/null +++ b/demos/gdb_support/.gitignore @@ -0,0 +1,2 @@ +sample +occlum_context diff --git a/demos/gdb_support/README.md b/demos/gdb_support/README.md new file mode 100644 index 00000000..0ab6d038 --- /dev/null +++ b/demos/gdb_support/README.md @@ -0,0 +1,26 @@ +# GDB support for apps running upon Occlum + +## GDB support + +We modified the GDB SGX plugin to support debugging the apps running upon Occlum. After Occlum loaded app's executable file and its dependencies(e.g. libc) from the secure FS, it notifies GDB to load the symbols from elf file to the correct address allocated by Occlum, so GDB can find all the symbols of the running app. + +Currently, GDB cannot unload the app's symbols after running by Occlum, `gdb attach` command is not supported, and the backtrace cannot link the app with Occlum, we will support these features in the later version. + +## How to use + +Step 1: Build the sample app with debugging symbols, add `-g` flags generally +``` +./build_sample_with_symbols.sh +``` + +Step 2: Debug the sample app running on Occlum via `occlum gdb` +``` +./gdb_sample_on_occlum.sh +``` +When completed, shell changes to GDB. + +Step 3: Type `run` in the GDB shell to run the sample app +``` +(gdb) run +``` +GDB will stop at the `divide_by_zero` function because of the arithmetic exception. diff --git a/demos/gdb_support/build_sample_with_symbols.sh b/demos/gdb_support/build_sample_with_symbols.sh new file mode 100755 index 00000000..4cb08baf --- /dev/null +++ b/demos/gdb_support/build_sample_with_symbols.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +rm -rf sample +occlum-gcc -g sample.c -o sample diff --git a/demos/gdb_support/gdb_sample_on_occlum.sh b/demos/gdb_support/gdb_sample_on_occlum.sh new file mode 100755 index 00000000..fa6e57be --- /dev/null +++ b/demos/gdb_support/gdb_sample_on_occlum.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +rm -rf occlum_context && mkdir -p occlum_context +cd occlum_context +# 1. Initialize a directory as the Occlum context +occlum init + +# 2. Generate a secure Occlum FS image and Occlum SGX enclave +cp ../sample image/bin +occlum build + +# 3. Debug the user program inside an SGX enclave with GDB +occlum gdb /bin/sample diff --git a/demos/gdb_support/sample.c b/demos/gdb_support/sample.c new file mode 100644 index 00000000..f83a518e --- /dev/null +++ b/demos/gdb_support/sample.c @@ -0,0 +1,18 @@ +#include + +// GDB will stop here +int divide_by_zero(int num) { + int result; + int zero = 0; + + result = num / zero; + return result; +} + +int main() { + int ret; + + printf("Start to calculate\n"); + ret = divide_by_zero(1); + return 0; +} diff --git a/src/libos/src/process/spawn/mod.rs b/src/libos/src/process/spawn/mod.rs index 06c5cfbd..2aad2736 100644 --- a/src/libos/src/process/spawn/mod.rs +++ b/src/libos/src/process/spawn/mod.rs @@ -41,6 +41,10 @@ pub fn do_spawn_without_exec( Ok(new_tid) } +// This function is used to provide information to debugger, so it is empty. Please do not remove it. +#[no_mangle] +pub extern "C" fn occlum_gdb_hook_load_elf(elf_base: u64, elf_path: &str, elf_path_len: usize) {} + fn new_process( elf_path: &str, argv: &[CString], @@ -63,6 +67,13 @@ fn new_process( let cwd = parent_ref.lock().unwrap().get_cwd().to_owned(); let vm = init_vm::do_init(&exec_elf_file, &ldso_elf_file)?; let auxtbl = init_auxtbl(&vm, &exec_elf_file)?; + + // Notify debugger to load the symbols from elf file + let ldso_elf_base = vm.get_elf_ranges()[1].start() as u64; + occlum_gdb_hook_load_elf(ldso_elf_base, ldso_path, ldso_path.len()); + let exec_elf_base = vm.get_elf_ranges()[0].start() as u64; + occlum_gdb_hook_load_elf(exec_elf_base, elf_path, elf_path.len()); + let task = { let ldso_entry = { let ldso_range = vm.get_elf_ranges()[1]; diff --git a/tools/occlum b/tools/occlum index 1c153ef8..aaba9589 100755 --- a/tools/occlum +++ b/tools/occlum @@ -7,6 +7,7 @@ working_dir=`pwd` context_dir="$working_dir/.occlum" SGX_SDK="${SGX_SDK:-/opt/intel/sgxsdk}" +SGX_GDB="$SGX_SDK/bin/sgx-gdb" ENCLAVE_SIGN_TOOL="$SGX_SDK/bin/x64/sgx_sign" ENCLAVE_SIGN_KEY="$occlum_dir/etc/template/Enclave.pem" @@ -18,13 +19,22 @@ exit_error() { report_arg_error() { echo $1 >&2 echo "" - echo "Usage:" - echo " occlum init" - echo " occlum build [--sign-key ] [--sign-tool ]" - echo " occlum run " - echo "" - echo " Run enclave in sgx release mode:" - echo " OCCLUM_RELEASE_ENCLAVE=1 occlum run " + cat <] [--sign-tool ] + Generate a secure Occlum FS image and Occlum SGX enclave. + + occlum run + Run the user program inside an SGX enclave. + To run the enclave in SGX hardware release mode, use: + OCCLUM_RELEASE_ENCLAVE=1 occlum run + + occlum gdb + Debug the program running inside an SGX enclave with GDB. +EOF } get_conf_default_stack_size() { @@ -180,6 +190,15 @@ cmd_run() { echo "built" > "$context_dir/status" } +cmd_gdb() { + cd "$working_dir" + echo "debugging" > "$context_dir/status" + + OCCLUM_GDB=1 LD_LIBRARY_PATH="$context_dir/build/lib" $SGX_GDB --args "$context_dir/build/bin/occlum-run" "$@" + + echo "built" > "$context_dir/status" +} + cmd_status() { cat "$context_dir/status" } @@ -202,6 +221,9 @@ case "$cmd" in run) cmd_run "${@:2}" ;; + gdb) + cmd_gdb "${@:2}" + ;; status) cmd_status ;;