Advanced Operating Systems
COMP9242 2012/S2 |
UNSW
CRICOS Provider Number: 00098G |
Printer-Friendly
Version
|
backtrace_symbol.sh#!/bin/bash #This script matches the program counter values returned by #backtrace() in sos to the function names. #the argument could be: -l -S for objdump extra options #-w width for print out line width #-f filename for get the input from the file BACKTRACE_PC="" LEVEL=0 OBJDUMP_OPTIONS="-d" WIDTH=4 #help function for the backtrace_symbol script print_help() { echo "USEAGE: backtrace_symbol [OPTIONS] <<EOF" echo " PCs" echo " <<EOF" echo "OPTIONS: -l printout line number for disassembly" echo " -S printout source code for disassembly" echo " -w WIDTH extra lines of disassembly for each side of the target PC, between 4 and 10 (default is 4)" echo " --start-address=0xADDR only process data whose address is >= ADDR" echo " --stop-address=0xADDR only process data whose address is <= ADDR" echo " --help printout this message" echo "Format: the PCs should be started with a new line each" echo " PCs are hex numbers, start with \"0x\"" exit 0 return } #process options for the script process_options() { #no options to process, return if [ $# -eq 0 ] then return fi #if the argument list is not empty while [ -n "$1" ] do if [ "$1" = "-l" ] then #add -l to the objdump options OBJDUMP_OPTIONS="$OBJDUMP_OPTIONS -l" elif [ "$1" = "-S" ] then #add -S to the objdump options OBJDUMP_OPTIONS="$OBJDUMP_OPTIONS -S" elif [ "$1" = "-w" ] then #resovle the line number surround each pc,[4-10] if [ $2 -lt 11 ] && [ $2 -gt 3 ]; then WIDTH=$2 shift else #call the help function print_help fi elif [ `expr "$1" : '--start-address=0x'` -eq 18 ] then #passing start address address to the objdump OBJDUMP_OPTIONS="$OBJDUMP_OPTIONS $1" elif [ `expr "$1" : '--stop-address=0x'` -eq 17 ] then #passing stop address to the objdump OBJDUMP_OPTIONS="$OBJDUMP_OPTIONS $1" elif [ "$1" = "--help" ] then print_help else #wrong option, printout help message print_help fi #shift the arguement right to one position shift done return } #process stdin process_stdin() { #read in the line if there is one available while read var1 var2 do if [ "$var2" != "" ] then #maximum variables in each line is two print_help elif [ ${#var1} -le 10 ] && [ `expr "$var1" : '0x'` -eq 2 ] && [[ "$var1" -gt "0x0" ]] && [[ "$var1" -lt "0xffffffff" ]] then #record the backtrace pc if it is in the right range 0-0xffffffff #the string is less than 10, start with "0x" BACKTRACE_PC="$BACKTRACE_PC $var1" else #wrong input, print out help function print_help fi done return } #get the input from stdin, call function process_options $@ process_stdin #if the backtrace_pc list is null, print out the help function and exit if [ "$BACKTRACE_PC" = "" ] then echo "ERROR: empty PC list" print_help fi #list the symbol in increasing order armeb-oe-linux-gnueabi-nm -n build/arm/nslu2/sos/sos.bin > sos.nm if [ $? -ne 0 ] then print_help fi armeb-oe-linux-gnueabi-objdump $OBJDUMP_OPTIONS build/arm/nslu2/sos/sos.bin > sos.dis if [ $? -ne 0 ] then print_help fi #for each address in the back trace pc list, do the search for ADDRESS in $BACKTRACE_PC do echo "--------------------------------------------------------------------------------" #search the function name with a given PC awk -v searchadd=$ADDRESS -v le=$LEVEL ' BEGIN { target = searchadd + 0 #numeric the searchadd resolve = 0 } { #the first string in each line is an 8 digits hex number if (length($1) != 8) next a1 = ("0x" $1) + 0 #numeric the string if (a1 < target) { pervious_name = $3 pervious_add = a1 } else if (a1 == target) { #printout the name in this line #target find at the start of the function resolve = 1 printf " #%2d 0x%08x in %-30s\n", le, target, $3 exit 1 } else { #printout the pervious recorded name resolve = 1 printf " #%2d 0x%08x in %-30s\n",le,target, pervious_name exit 1 }} END { if (resolve == 0) { #the address can not be resolved printf " #%2d: can not resolve 0x%08x\n",le,target exit 2 }} ' sos.nm #printout the relative disassembled code if the pc is resolved EXIT_STATUS=$? if [ $EXIT_STATUS -eq 1 ]; then echo "" awk -v searchadd=$ADDRESS -v width=$WIDTH ' BEGIN { add = searchadd + 0 #numeric the search address start = add - width * 4 end = add + width * 4 flag = 0 } { #for a correct disassembly line, the second string should be the machine code if (length($2) == 8 && $2 ~ /^[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/) { #the first line should be the address of the pc, in the form hex: if (length($1) > 9) next a1 = ("0x" $1) + 0 #numeric the pc string if (a1 == end) { print $0 exit #print finish } if (a1 == start) { flag = 1 #set the print flag } } #print out the line if the flag is set if (flag == 1) { print $0 } }' sos.dis fi echo "--------------------------------------------------------------------------------" #increase the stack frame number by one LEVEL=`expr $LEVEL + 1` done #remove the temp files #rm -f sos.nm #rm -f sos.dis |