| #!/usr/bin/env bash |
| ############################################################################ |
| # tools/btdecode.sh |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. The |
| # ASF licenses this file to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance with the |
| # License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations |
| # under the License. |
| # |
| ############################################################################ |
| |
| # This script can be used to decode the backtrace that's dumped on assertions. |
| # |
| # On assertions we can find the raw backtrace dump similar to: |
| # ... |
| # sched_dumpstack: backtrace| 0: 0x400e1a2a 0x40082912 |
| # sched_dumpstack: backtrace| 1: 0x400e39ac 0x400ef7c3 0x400ef7fc 0x400e8116 0x400e7910 0x400e7be8 0x400e6c5c 0x400e6ad6 |
| # sched_dumpstack: backtrace| 1: 0x400e6a99 0x400e4005 0x400e2754 |
| # sched_dumpstack: backtrace| 2: 0x400f13ee 0x400e4005 0x400e2754 |
| # ... |
| # |
| # Copy that to a file and call this script as: |
| # ./tools/btdecode.sh esp32 backtrace_file |
| # |
| # The result should be similar to the following: |
| # 0x400e1a2a: function_name at file.c:line |
| # 0x40082912: function_name at file.c:line |
| |
| USAGE="USAGE: ${0} chip|toolchain-addr2line backtrace_file [elf_file] |
| If the first argument contains 'addr2line', it will be used as the toolchain's addr2line tool. |
| Otherwise, the script will try to identify the toolchain based on the chip name." |
| |
| GREP=${GREP:-grep} |
| |
| VALID_CHIPS=( |
| "esp32" |
| "esp32s2" |
| "esp32s3" |
| "esp32c3" |
| "esp32c6" |
| "esp32h2" |
| ) |
| |
| # Make sure we have the required argument(s) |
| |
| if [ -z "$2" ]; then |
| echo "No backtrace supplied!" |
| echo "$USAGE" |
| exit 1 |
| fi |
| |
| elf_file="nuttx" |
| |
| if [ -n "$3" ]; then |
| elf_file=$3 |
| fi |
| |
| # Check if the first argument is an addr2line tool or a chip |
| |
| chip_or_tool=$1 |
| if [[ $chip_or_tool == *addr2line* ]]; then |
| ADDR2LINE_TOOL=$chip_or_tool |
| else |
| chip=$chip_or_tool |
| if [[ ! " ${VALID_CHIPS[@]} " =~ " ${chip} " ]]; then |
| echo "Invalid chip specified! Valid options are: ${VALID_CHIPS[*]}" |
| echo "$USAGE" |
| exit 4 |
| fi |
| |
| # Set the appropriate addr2line tool based on the chip |
| case $chip in |
| esp32) |
| ADDR2LINE_TOOL="xtensa-esp32-elf-addr2line" |
| ;; |
| esp32s2) |
| ADDR2LINE_TOOL="xtensa-esp32s2-elf-addr2line" |
| ;; |
| esp32s3) |
| ADDR2LINE_TOOL="xtensa-esp32s3-elf-addr2line" |
| ;; |
| esp32c3) |
| ADDR2LINE_TOOL="riscv-none-elf-addr2line" |
| ;; |
| esp32c6) |
| ADDR2LINE_TOOL="riscv-none-elf-addr2line" |
| ;; |
| esp32h2) |
| ADDR2LINE_TOOL="riscv-none-elf-addr2line" |
| ;; |
| esac |
| fi |
| |
| # Make sure the elf file is accessible |
| |
| if [ ! -f ${elf_file} ]; then |
| echo "NuttX binaries not found!" |
| exit 2 |
| fi |
| |
| # Check that the toolchain is in the PATH |
| |
| if [ ! -x "$(command -v $ADDR2LINE_TOOL)" ]; then |
| echo "Toolchain for $chip_or_tool not found!" |
| exit 3 |
| fi |
| |
| # Decode backtrace |
| |
| declare -A backtraces_before |
| declare -A backtraces_after |
| in_dump_tasks_section=false |
| |
| while read -r line; do |
| if [[ $line =~ (\[CPU[0-9]+\]\ )?dump_tasks: ]]; then |
| in_dump_tasks_section=true |
| fi |
| |
| if [[ $line =~ (\[CPU[0-9]+\]\ )?sched_dumpstack: ]]; then |
| task_id=$(echo $line | ${GREP} -oP 'backtrace\|\s*\K\d+') |
| addresses=$(echo $line | ${GREP} -oP '0x[0-9a-fA-F]+') |
| if $in_dump_tasks_section; then |
| if [[ -n "${backtraces_after[$task_id]}" ]]; then |
| backtraces_after[$task_id]="${backtraces_after[$task_id]} $addresses" |
| else |
| backtraces_after[$task_id]="$addresses" |
| fi |
| else |
| if [[ -n "${backtraces_before[$task_id]}" ]]; then |
| backtraces_before[$task_id]="${backtraces_before[$task_id]} $addresses" |
| else |
| backtraces_before[$task_id]="$addresses" |
| fi |
| fi |
| fi |
| done < "$2" |
| |
| for task_id in "${!backtraces_before[@]}"; do |
| echo "Backtrace for task $task_id:" |
| for bt in ${backtraces_before[$task_id]}; do |
| $ADDR2LINE_TOOL -pfiaCs -e ${elf_file} $bt |
| done |
| echo "" |
| done |
| |
| if $in_dump_tasks_section; then |
| echo "Backtrace dump for all tasks:" |
| echo "" |
| for task_id in "${!backtraces_after[@]}"; do |
| echo "Backtrace for task $task_id:" |
| for bt in ${backtraces_after[$task_id]}; do |
| $ADDR2LINE_TOOL -pfiaCs -e ${elf_file} $bt |
| done |
| echo "" |
| done |
| fi |