From d8edd1a7dbeb0b1d75063472ded016ccc85678c0 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 8 Jan 2019 11:04:39 +0800 Subject: [PATCH 01/10] Implement backtrace support for AArch64 --- kernel/src/backtrace.rs | 48 +++++++++++++++++++++++++++++++++++++ kernel/src/lang.rs | 2 ++ kernel/src/lib.rs | 1 + kernel/targets/aarch64.json | 3 ++- 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 kernel/src/backtrace.rs diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs new file mode 100644 index 0000000..6243474 --- /dev/null +++ b/kernel/src/backtrace.rs @@ -0,0 +1,48 @@ +extern "C" { + fn stext(); + fn etext(); +} + +/// Returns the current frame pointer. +#[inline(always)] +#[cfg(target_arch = "aarch64")] +pub fn fp() -> usize { + let ptr: usize; + unsafe { + asm!("mov $0, x29" : "=r"(ptr)); + } + + ptr +} + +/// Returns the current link register. +#[inline(always)] +#[cfg(target_arch = "aarch64")] +pub fn lr() -> usize { + let ptr: usize; + unsafe { + asm!("mov $0, x30" : "=r"(ptr)); + } + + ptr +} + +// Print the backtrace starting from the caller +pub fn backtrace() { + #[cfg(target_arch = "aarch64")] + unsafe { + let mut current_pc = lr(); + let mut current_fp = fp(); + let mut stack_num = 0; + println!("pc {:#018X} fp {:#018X}", current_pc, current_fp); + while current_pc >= stext as usize && current_pc <= etext as usize && current_fp as usize != 0 { + println!("#{} {:#018X}", stack_num, current_pc); + stack_num = stack_num + 1; + current_fp = *(current_fp as *const usize); + if current_fp as usize != 0 { + current_pc = *(current_fp as *const usize).offset(1); + } + println!("pc {:#018X} fp {:#018X}", current_pc, current_fp); + } + } +} diff --git a/kernel/src/lang.rs b/kernel/src/lang.rs index 27b0d21..903e137 100644 --- a/kernel/src/lang.rs +++ b/kernel/src/lang.rs @@ -3,6 +3,7 @@ use core::panic::PanicInfo; use core::alloc::Layout; use log::*; +use crate::backtrace; #[lang = "eh_personality"] extern fn eh_personality() { @@ -13,6 +14,7 @@ fn panic(info: &PanicInfo) -> ! { let location = info.location().unwrap(); let message = info.message().unwrap(); error!("\n\nPANIC in {} at line {}\n {}", location.file(), location.line(), message); + backtrace::backtrace(); loop { crate::arch::cpu::halt() } } diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index ab18c1c..29e5ce0 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -28,6 +28,7 @@ mod fs; mod sync; mod trap; mod shell; +mod backtrace; #[allow(dead_code)] #[cfg(target_arch = "x86_64")] diff --git a/kernel/targets/aarch64.json b/kernel/targets/aarch64.json index b0c24dc..149246a 100644 --- a/kernel/targets/aarch64.json +++ b/kernel/targets/aarch64.json @@ -31,5 +31,6 @@ "target-endian": "little", "target-pointer-width": "64", "target-family": "unix", - "disable-redzone": true + "disable-redzone": true, + "eliminate-frame-pointer": false } From 7d6856ceab8d7d3f1c0a66e0f21c6050671f8ff5 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 8 Jan 2019 11:33:31 +0800 Subject: [PATCH 02/10] Implement backtrace support for RISCV64 --- kernel/src/backtrace.rs | 34 +++++++++++++++++++++++++--------- kernel/targets/riscv64.json | 3 ++- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index 6243474..798327d 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -5,44 +5,60 @@ extern "C" { /// Returns the current frame pointer. #[inline(always)] -#[cfg(target_arch = "aarch64")] +#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] pub fn fp() -> usize { let ptr: usize; + #[cfg(target_arch = "aarch64")] unsafe { asm!("mov $0, x29" : "=r"(ptr)); } + #[cfg(target_arch = "riscv64")] + unsafe { + asm!("mv $0, s0" : "=r"(ptr)); + } ptr } /// Returns the current link register. #[inline(always)] -#[cfg(target_arch = "aarch64")] +#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] pub fn lr() -> usize { let ptr: usize; + #[cfg(target_arch = "aarch64")] unsafe { asm!("mov $0, x30" : "=r"(ptr)); } + #[cfg(target_arch = "riscv64")] + unsafe { + asm!("mv $0, ra" : "=r"(ptr)); + } ptr } // Print the backtrace starting from the caller pub fn backtrace() { - #[cfg(target_arch = "aarch64")] + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] unsafe { let mut current_pc = lr(); let mut current_fp = fp(); let mut stack_num = 0; - println!("pc {:#018X} fp {:#018X}", current_pc, current_fp); while current_pc >= stext as usize && current_pc <= etext as usize && current_fp as usize != 0 { - println!("#{} {:#018X}", stack_num, current_pc); + println!("#{} {:#018X} fp {:#18X}", stack_num, current_pc - 4, current_fp); stack_num = stack_num + 1; - current_fp = *(current_fp as *const usize); - if current_fp as usize != 0 { - current_pc = *(current_fp as *const usize).offset(1); + #[cfg(target_arch = "riscv64")] + { + current_fp = *((current_fp - 16) as *const usize); + current_pc = *(current_fp as *const usize).offset(-1); + } + #[cfg(target_arch = "aarch64")] + { + current_fp = *(current_fp as *const usize); + if current_fp != 0 { + current_pc = *(current_fp as *const usize).offset(1); + } } - println!("pc {:#018X} fp {:#018X}", current_pc, current_fp); } } } diff --git a/kernel/targets/riscv64.json b/kernel/targets/riscv64.json index 4742c08..7cf840a 100644 --- a/kernel/targets/riscv64.json +++ b/kernel/targets/riscv64.json @@ -31,5 +31,6 @@ "ptx-kernel", "msp430-interrupt", "x86-interrupt" - ] + ], + "eliminate-frame-pointer": false } From 090796d3f0e91b8442dc8a52f85da64f46b32531 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 8 Jan 2019 12:05:29 +0800 Subject: [PATCH 03/10] Implement backtrace support for RISCV32 --- kernel/src/backtrace.rs | 16 ++++++++-------- kernel/targets/riscv32.json | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index 798327d..1c6f865 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -5,14 +5,14 @@ extern "C" { /// Returns the current frame pointer. #[inline(always)] -#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] +#[cfg(any(target_arch = "aarch64", target_arch = "riscv32", target_arch = "riscv64"))] pub fn fp() -> usize { let ptr: usize; #[cfg(target_arch = "aarch64")] unsafe { asm!("mov $0, x29" : "=r"(ptr)); } - #[cfg(target_arch = "riscv64")] + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] unsafe { asm!("mv $0, s0" : "=r"(ptr)); } @@ -22,14 +22,14 @@ pub fn fp() -> usize { /// Returns the current link register. #[inline(always)] -#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] +#[cfg(any(target_arch = "aarch64", target_arch = "riscv32", target_arch = "riscv64"))] pub fn lr() -> usize { let ptr: usize; #[cfg(target_arch = "aarch64")] unsafe { asm!("mov $0, x30" : "=r"(ptr)); } - #[cfg(target_arch = "riscv64")] + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] unsafe { asm!("mv $0, ra" : "=r"(ptr)); } @@ -39,17 +39,17 @@ pub fn lr() -> usize { // Print the backtrace starting from the caller pub fn backtrace() { - #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] + #[cfg(any(target_arch = "aarch64", target_arch = "riscv32", target_arch = "riscv64"))] unsafe { let mut current_pc = lr(); let mut current_fp = fp(); let mut stack_num = 0; while current_pc >= stext as usize && current_pc <= etext as usize && current_fp as usize != 0 { - println!("#{} {:#018X} fp {:#18X}", stack_num, current_pc - 4, current_fp); + println!("#{} {:#018X} fp {:#018X}", stack_num, current_pc - 4, current_fp); stack_num = stack_num + 1; - #[cfg(target_arch = "riscv64")] + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { - current_fp = *((current_fp - 16) as *const usize); + current_fp = *(current_fp as *const usize).offset(-2); current_pc = *(current_fp as *const usize).offset(-1); } #[cfg(target_arch = "aarch64")] diff --git a/kernel/targets/riscv32.json b/kernel/targets/riscv32.json index ca35687..9430baf 100644 --- a/kernel/targets/riscv32.json +++ b/kernel/targets/riscv32.json @@ -31,5 +31,6 @@ "ptx-kernel", "msp430-interrupt", "x86-interrupt" - ] + ], + "eliminate-frame-pointer": false } From 66cdbd07139db67b5c4c8e40e611dcd553683cbd Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 8 Jan 2019 12:45:25 +0800 Subject: [PATCH 04/10] Update aarch64 toolchain location --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index dc99b3c..b7692f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,8 +40,8 @@ install: fi - if [ $ARCH = aarch64 ]; then if [ $TRAVIS_OS_NAME = linux ]; then - wget https://web.stanford.edu/class/cs140e/files/aarch64-none-elf-linux-x64.tar.gz; - tar -xzvf aarch64-none-elf-linux-x64.tar.gz; + wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2018.11/gcc-arm-8.2-2018.11-x86_64-aarch64-elf.tar.xz?revision=90d1fe0a-42d7-439c-8ea6-bb7234b2f540&la=en -O aarch64-none-elf-linux-x64.tar.xz; + tar -xvf aarch64-none-elf-linux-x64.tar.xz; export PATH=$PATH:$PWD/aarch64-none-elf/bin; elif [ $TRAVIS_OS_NAME = osx ]; then brew tap SergioBenitez/osxct; From 4beb865d324b1ecc1d5511172e15b71e1fbf57bc Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 8 Jan 2019 12:57:24 +0800 Subject: [PATCH 05/10] Update toolchain location and detection --- .travis.yml | 6 +++--- kernel/Makefile | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b7692f7..3c6f1f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,9 +40,9 @@ install: fi - if [ $ARCH = aarch64 ]; then if [ $TRAVIS_OS_NAME = linux ]; then - wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2018.11/gcc-arm-8.2-2018.11-x86_64-aarch64-elf.tar.xz?revision=90d1fe0a-42d7-439c-8ea6-bb7234b2f540&la=en -O aarch64-none-elf-linux-x64.tar.xz; - tar -xvf aarch64-none-elf-linux-x64.tar.xz; - export PATH=$PATH:$PWD/aarch64-none-elf/bin; + wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2018.11/gcc-arm-8.2-2018.11-x86_64-aarch64-elf.tar.xz?revision=90d1fe0a-42d7-439c-8ea6-bb7234b2f540&la=en -O gcc-arm-8.2-2018.11-x86_64-aarch64-elf.tar.xz; + tar -xvf gcc-arm-8.2-2018.11-x86_64-aarch64-elf.tar.xz; + export PATH=$PATH:$PWD/gcc-arm-8.2-2018.11-x86_64-aarch64-elf/bin; elif [ $TRAVIS_OS_NAME = osx ]; then brew tap SergioBenitez/osxct; brew install aarch64-none-elf; diff --git a/kernel/Makefile b/kernel/Makefile index a14b5cd..93d0428 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -141,6 +141,7 @@ else ifeq ($(arch), riscv64) prefix := riscv64-unknown-elf- else ifeq ($(arch), aarch64) prefix ?= aarch64-none-elf- +hash $(prefix)ld 2>/dev/null || {prefix := aarch64-elf- } endif ld := $(prefix)ld @@ -258,4 +259,4 @@ ifeq ($(board), k210) install: $(bin) ## baudrate no more than 600000 @python3 ../tools/k210/kflash.py $(bin) -b 600000 -endif \ No newline at end of file +endif From 74dea5836f01532ecf7700dd35f52460dcd960ac Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 8 Jan 2019 13:05:34 +0800 Subject: [PATCH 06/10] Fix toolchain download link --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3c6f1f6..98fb352 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ install: fi - if [ $ARCH = aarch64 ]; then if [ $TRAVIS_OS_NAME = linux ]; then - wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2018.11/gcc-arm-8.2-2018.11-x86_64-aarch64-elf.tar.xz?revision=90d1fe0a-42d7-439c-8ea6-bb7234b2f540&la=en -O gcc-arm-8.2-2018.11-x86_64-aarch64-elf.tar.xz; + wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2018.11/gcc-arm-8.2-2018.11-x86_64-aarch64-elf.tar.xz; tar -xvf gcc-arm-8.2-2018.11-x86_64-aarch64-elf.tar.xz; export PATH=$PATH:$PWD/gcc-arm-8.2-2018.11-x86_64-aarch64-elf/bin; elif [ $TRAVIS_OS_NAME = osx ]; then From e3262698bec2125f2361f0c6a03c15a1ee341377 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 8 Jan 2019 13:27:53 +0800 Subject: [PATCH 07/10] Fix aarch64 toolchain detection and add missing compiler_builtins v0.1.5 --- kernel/Makefile | 4 +++- kernel/build-rv64 | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/Makefile b/kernel/Makefile index 93d0428..38df128 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -141,7 +141,9 @@ else ifeq ($(arch), riscv64) prefix := riscv64-unknown-elf- else ifeq ($(arch), aarch64) prefix ?= aarch64-none-elf- -hash $(prefix)ld 2>/dev/null || {prefix := aarch64-elf- } +ifeq (,$(shell which $(prefix)ld)) + prefix := aarch64-elf- +endif endif ld := $(prefix)ld diff --git a/kernel/build-rv64 b/kernel/build-rv64 index 733c905..42fcb7d 100755 --- a/kernel/build-rv64 +++ b/kernel/build-rv64 @@ -102,6 +102,9 @@ then elif [[ -d $CARGO_PATH/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.4 ]] then COMPILER_BUILTINS_PATH=$CARGO_PATH/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.4 + elif [[ -d $CARGO_PATH/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.5 ]] + then + COMPILER_BUILTINS_PATH=$CARGO_PATH/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.5 else echo "Cannot find compiler_builtins crate! Please file an issue report" fi From 5350ecb09f89bd9c9bb1691c699b8847cb9a557a Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 8 Jan 2019 19:04:34 +0800 Subject: [PATCH 08/10] Add addr2line tool for annotating backtrace --- kernel/Makefile | 5 +++++ tools/addr2line.py | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tools/addr2line.py diff --git a/kernel/Makefile b/kernel/Makefile index 38df128..6014788 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -5,6 +5,7 @@ # make doc Generate docs # make asm Open the deassemble file of the last build # make header Open 'objdump -h' of the last build +# make addr2line Use addr2line to recover line info in backtrace # make clean Clean # # Options: @@ -262,3 +263,7 @@ install: $(bin) ## baudrate no more than 600000 @python3 ../tools/k210/kflash.py $(bin) -b 600000 endif + +.PHONY: +addr2line: + @python3 ../tools/addr2line.py $(prefix)addr2line $(arch) diff --git a/tools/addr2line.py b/tools/addr2line.py new file mode 100644 index 0000000..fa84228 --- /dev/null +++ b/tools/addr2line.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +import sys +import re +import subprocess + +print('Paste backtrace here, and then input EOF(Ctrl-D or Ctrl-Z) to get annotated backtrace.') +lines = sys.stdin.readlines() +addrline = sys.argv[1] +arch = sys.argv[2] +print('--------------------------------------') +for line in lines: + match = re.search('(#[0-9]+ )(0x[0-9A-F]+)( fp 0x[0-9A-F]+)', line) + if match: + addr = match.group(2) + process = subprocess.run([addrline, '-e', 'target/{0}/debug/rcore'.format(arch), '-f', '-C', addr], capture_output=True) + res = process.stdout.decode('utf-8') + print('{0}{1}{3} {2}'.format(match.group(1), match.group(2), res.strip(), match.group(3))) + else: + print(line, end='') From 6e887d55053e040226e9b11786e72617e828623f Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 8 Jan 2019 19:08:17 +0800 Subject: [PATCH 09/10] Replace hardcoded instruction length with size_of in backtrace --- kernel/src/backtrace.rs | 4 +++- kernel/src/lib.rs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index 1c6f865..0c45cc7 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -1,3 +1,5 @@ +use core::intrinsics::size_of; + extern "C" { fn stext(); fn etext(); @@ -45,7 +47,7 @@ pub fn backtrace() { let mut current_fp = fp(); let mut stack_num = 0; while current_pc >= stext as usize && current_pc <= etext as usize && current_fp as usize != 0 { - println!("#{} {:#018X} fp {:#018X}", stack_num, current_pc - 4, current_fp); + println!("#{} {:#018X} fp {:#018X}", stack_num, current_pc - size_of::(), current_fp); stack_num = stack_num + 1; #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 29e5ce0..d059360 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -6,6 +6,7 @@ #![feature(optin_builtin_traits)] #![feature(panic_info_message)] #![feature(global_asm)] +#![feature(core_intrinsics)] #![no_std] // just keep it ... From b1d01928c3a760d0abd6dae6c3322cb7308b133e Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 8 Jan 2019 22:10:51 +0800 Subject: [PATCH 10/10] Use core::mem::size_of instead of core:intrinsics::size_of. Thanks @wangrunji0408 --- kernel/src/backtrace.rs | 2 +- kernel/src/lib.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index 0c45cc7..abf95fb 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -1,4 +1,4 @@ -use core::intrinsics::size_of; +use core::mem::size_of; extern "C" { fn stext(); diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index d059360..29e5ce0 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -6,7 +6,6 @@ #![feature(optin_builtin_traits)] #![feature(panic_info_message)] #![feature(global_asm)] -#![feature(core_intrinsics)] #![no_std] // just keep it ...