backtrace 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #!/bin/bash
  2. ADDR2LINE=${ADDR2LINE:-riscv64-unknown-elf-addr2line}
  3. ksym=build/riscv64gc-unknown-none-elf/debug/eonix_kernel
  4. usage() {
  5. cat <<EOF
  6. Usage: $0 [options] [--] [addr2line options]
  7. Filter and translate backtrace addresses into human readable line numbers.
  8. Options:
  9. -s, --ksym <symbol file> Use the given kernel symbol file
  10. -o, --only-gbos Show kernel function calls only
  11. -h, --help Show this message
  12. EOF
  13. exit "$1"
  14. }
  15. # $1: instruction address
  16. parse_pos() {
  17. addr="$1"
  18. shift
  19. "$ADDR2LINE" -e "$ksym" -i "$addr" "$@" 2>/dev/null
  20. }
  21. filter_col() {
  22. [ "$1" -eq 0 ] || awk "{ print \$$1; }"
  23. }
  24. str_contains() {
  25. grep -E "$1" >/dev/null 2>&1
  26. }
  27. filter_stacktrace() {
  28. NL=$'\n'
  29. _state=nonstart
  30. _out=
  31. while [ $_state != "end" ]; do
  32. read -r _line
  33. case $_state in
  34. nonstart)
  35. str_contains "8< CUT HERE" <<< "$_line" && _state=save
  36. ;;
  37. save)
  38. if str_contains "8< CUT HERE" <<< "$_line"; then
  39. _state=end
  40. else
  41. _out="$_out$_line$NL"
  42. fi
  43. ;;
  44. esac
  45. done
  46. echo "$_out"
  47. }
  48. while [ "$#" -gt 0 ]; do
  49. case "$1" in
  50. -s|--ksym)
  51. shift
  52. ksym="$1"
  53. ;;
  54. -o|--only-gbos)
  55. only_gb=y
  56. ;;
  57. --)
  58. shift
  59. break
  60. ;;
  61. -h|--help)
  62. usage 0
  63. ;;
  64. *)
  65. usage 1
  66. ;;
  67. esac
  68. shift
  69. done
  70. stacktrace="$(filter_stacktrace)"
  71. i=1
  72. for addr in $(filter_col 3 <<< "$stacktrace"); do
  73. pos="$(parse_pos "$addr" "$@")"
  74. if [ -n "$only_gb" ]; then
  75. if ! str_contains "greatbridf_os" <<< "$pos"; then
  76. continue
  77. fi
  78. fi
  79. printf "========== %4d ==========\n" "$i"
  80. parse_pos "$addr" "$@"
  81. i=$((i + 1))
  82. done