This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 8c0850b0bd5d9ce55e7ceaf4021ffc43ac663c56
Author: dongjiuzhu1 <[email protected]>
AuthorDate: Wed Dec 31 14:46:25 2025 +0800

    toos/scipts: add script to find symbol caller
    
    Usage: ./tools/find_symbol_callers.sh <elf_file> <symbol_name> [source_root]
    
    Examples:
      ./tools/find_symbol_callers.sh nuttx __aeabi_f2d
      ./tools/find_symbol_callers.sh nuttx malloc
    
    Signed-off-by: dongjiuzhu1 <[email protected]>
---
 tools/find_symbol_callers.sh | 257 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 257 insertions(+)

diff --git a/tools/find_symbol_callers.sh b/tools/find_symbol_callers.sh
new file mode 100755
index 00000000000..dd4fa0a96a0
--- /dev/null
+++ b/tools/find_symbol_callers.sh
@@ -0,0 +1,257 @@
+#!/usr/bin/env bash
+# find_symbol_callers.sh
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+#
+
+# find_symbol_callers.sh - Find all call sites of specified symbols
+#
+# Usage: ./find_symbol_callers.sh <elf_file> <symbol_name> [source_root]
+#
+# Examples:
+#   ./find_symbol_callers.sh nuttx __aeabi_f2d
+#   ./find_symbol_callers.sh nuttx "__aeabi_.*" ../
+#
+
+set -e
+
+# Color definitions
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[0;33m'
+BLUE='\033[0;34m'
+MAGENTA='\033[0;35m'
+CYAN='\033[0;36m'
+NC='\033[0m' # No Color
+
+# Check arguments
+if [ $# -lt 2 ]; then
+    echo "Usage: $0 <elf_file> <symbol_name> [source_root]"
+    echo ""
+    echo "Examples:"
+    echo "  $0 nuttx __aeabi_f2d"
+    echo "  $0 nuttx __aeabi_f2d ./"
+    echo "  $0 nuttx malloc"
+    echo ""
+    exit 1
+fi
+
+ELF_FILE="$1"
+SYMBOL_NAME="$2"
+SRC_ROOT="${3:-.}"
+
+# Check toolchain prefix
+if command -v arm-none-eabi-objdump &> /dev/null; then
+    TOOLCHAIN_PREFIX="arm-none-eabi-"
+elif command -v objdump &> /dev/null; then
+    TOOLCHAIN_PREFIX=""
+else
+    echo -e "${RED}Error: objdump tool not found${NC}"
+    exit 1
+fi
+
+OBJDUMP="${TOOLCHAIN_PREFIX}objdump"
+NM="${TOOLCHAIN_PREFIX}nm"
+ADDR2LINE="${TOOLCHAIN_PREFIX}addr2line"
+
+# Check if ELF file exists
+if [ ! -f "$ELF_FILE" ]; then
+    echo -e "${RED}Error: ELF file not found: $ELF_FILE${NC}"
+    exit 1
+fi
+
+echo -e "${CYAN}========================================${NC}"
+echo -e "${CYAN}Symbol Call Analysis Tool${NC}"
+echo -e "${CYAN}========================================${NC}"
+echo -e "ELF File: ${GREEN}$ELF_FILE${NC}"
+echo -e "Symbol: ${GREEN}$SYMBOL_NAME${NC}"
+echo -e "Source Root: ${GREEN}$SRC_ROOT${NC}"
+echo ""
+
+# Create temporary file
+DISASM_FILE=$(mktemp /tmp/disasm_XXXXXX.txt)
+trap "rm -f $DISASM_FILE" EXIT
+
+echo -e "${YELLOW}[1/5] Generating disassembly...${NC}"
+$OBJDUMP -d "$ELF_FILE" > "$DISASM_FILE"
+echo -e "${GREEN}✓ Disassembly complete${NC}"
+echo ""
+
+# Find symbol addresses
+echo -e "${YELLOW}[2/5] Finding symbol addresses...${NC}"
+SYMBOL_ADDRS=$($NM "$ELF_FILE" | grep -E " [TtWw] " | grep -E "$SYMBOL_NAME" | 
awk '{print $1, $3}')
+
+if [ -z "$SYMBOL_ADDRS" ]; then
+    echo -e "${RED}Error: Symbol '$SYMBOL_NAME' not found${NC}"
+    echo ""
+    echo "Hint: Use the following command to view all available symbols:"
+    echo "  $NM $ELF_FILE | grep -i '$SYMBOL_NAME'"
+    exit 1
+fi
+
+echo -e "${GREEN}Found symbols:${NC}"
+echo "$SYMBOL_ADDRS" | while read addr name; do
+    echo -e "  ${BLUE}0x$addr${NC} - ${MAGENTA}$name${NC}"
+done
+echo ""
+
+# Find all call sites
+echo -e "${YELLOW}[3/5] Finding call sites...${NC}"
+
+# Build address regex pattern
+ADDR_PATTERN=$(echo "$SYMBOL_ADDRS" | awk '{print $1}' | sed 's/^0*//' | paste 
-sd '|')
+
+if [ -z "$ADDR_PATTERN" ]; then
+    echo -e "${RED}Error: Cannot build address pattern${NC}"
+    exit 1
+fi
+
+# Find all bl/b/jmp instructions to these addresses
+CALL_SITES=$(grep -E "bl|b\.w|jmp" "$DISASM_FILE" | grep -E "($ADDR_PATTERN)" 
| \
+    sed 's/^[[:space:]]*//' | awk '{print $1}' | sed 's/://')
+
+if [ -z "$CALL_SITES" ]; then
+    echo -e "${YELLOW}No direct call sites found (possibly inlined or 
unused)${NC}"
+    echo ""
+    exit 0
+fi
+
+CALL_COUNT=$(echo "$CALL_SITES" | wc -l)
+echo -e "${GREEN}Found $CALL_COUNT call site(s)${NC}"
+echo ""
+
+# Analyze each call site
+echo -e "${YELLOW}[4/5] Analyzing caller functions...${NC}"
+echo ""
+
+declare -A CALLER_FUNCS
+CALLER_COUNT=0
+
+for call_addr in $CALL_SITES; do
+    # Find the containing function from disassembly
+    FUNC_INFO=$(awk -v addr="$call_addr" '
+        /^[0-9a-f]+ <.*>:$/ { 
+            funcname=$0
+            funcaddr=$1
+        }
+        $1 == addr":" { 
+            print funcaddr "|" funcname
+            exit
+        }
+    ' "$DISASM_FILE")
+    
+    if [ -n "$FUNC_INFO" ]; then
+        FUNC_ADDR=$(echo "$FUNC_INFO" | cut -d'|' -f1)
+        FUNC_NAME=$(echo "$FUNC_INFO" | cut -d'|' -f2)
+        
+        # Deduplicate and count
+        if [ -z "${CALLER_FUNCS[$FUNC_NAME]}" ]; then
+            CALLER_FUNCS[$FUNC_NAME]="$FUNC_ADDR|1"
+            CALLER_COUNT=$((CALLER_COUNT + 1))
+        else
+            OLD_COUNT=$(echo "${CALLER_FUNCS[$FUNC_NAME]}" | cut -d'|' -f2)
+            NEW_COUNT=$((OLD_COUNT + 1))
+            CALLER_FUNCS[$FUNC_NAME]="$FUNC_ADDR|$NEW_COUNT"
+        fi
+    fi
+done
+
+echo -e "${GREEN}Found $CALLER_COUNT distinct caller function(s):${NC}"
+echo ""
+
+# Print caller function list
+for func in "${!CALLER_FUNCS[@]}"; do
+    INFO="${CALLER_FUNCS[$func]}"
+    ADDR=$(echo "$INFO" | cut -d'|' -f1)
+    COUNT=$(echo "$INFO" | cut -d'|' -f2)
+    echo -e "${CYAN}$func${NC}"
+    echo -e "  Address: ${BLUE}0x$ADDR${NC}"
+    echo -e "  Call count: ${MAGENTA}$COUNT${NC}"
+done
+echo ""
+
+# Find source code locations
+echo -e "${YELLOW}[5/5] Finding source code locations...${NC}"
+echo ""
+
+for func in "${!CALLER_FUNCS[@]}"; do
+    INFO="${CALLER_FUNCS[$func]}"
+    ADDR=$(echo "$INFO" | cut -d'|' -f1)
+    
+    # Extract function name (remove address and brackets)
+    FUNC_SIMPLE=$(echo "$func" | sed 's/^[0-9a-f]* <//' | sed 's/>:.*//')
+    
+    echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
+    echo -e "${CYAN}Function: ${MAGENTA}$FUNC_SIMPLE${NC}"
+    echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
+    
+    # Try using addr2line
+    LINE_INFO=$($ADDR2LINE -e "$ELF_FILE" -f -i "0x$ADDR" 2>/dev/null || echo 
"")
+    
+    if [ -n "$LINE_INFO" ] && ! echo "$LINE_INFO" | grep -q "^?"; then
+        echo -e "${GREEN}Debug info:${NC}"
+        echo "$LINE_INFO" | head -2
+    fi
+    
+    # Search for function definition in source code
+    if [ -d "$SRC_ROOT" ]; then
+        SRC_FILES=$(grep -rl "$FUNC_SIMPLE" "$SRC_ROOT" --include="*.c" 
--include="*.cpp" 2>/dev/null | head -5)
+        
+        if [ -n "$SRC_FILES" ]; then
+            echo -e "${GREEN}Possible source files:${NC}"
+            echo "$SRC_FILES" | while read file; do
+                # Find function definition line
+                LINE_NUM=$(grep -n "^\(static \)\?.*$FUNC_SIMPLE\s*(" "$file" 
2>/dev/null | head -1 | cut -d':' -f1)
+                if [ -n "$LINE_NUM" ]; then
+                    echo -e "  ${BLUE}$file:$LINE_NUM${NC}"
+                else
+                    echo -e "  ${BLUE}$file${NC}"
+                fi
+            done
+        else
+            echo -e "${YELLOW}Function definition not found in source 
code${NC}"
+        fi
+    fi
+    
+    # Show disassembly code at call sites
+    echo -e "${GREEN}Disassembly snippet:${NC}"
+    for call_addr in $CALL_SITES; do
+        CALL_FUNC=$(awk -v addr="$call_addr" '
+            /^[0-9a-f]+ <.*>:$/ { funcname=$0 }
+            $1 == addr":" { print funcname; exit }
+        ' "$DISASM_FILE")
+        
+        if [ "$CALL_FUNC" = "$func" ]; then
+            # Show 5 lines before and after call site
+            grep -A5 -B5 "^[[:space:]]*$call_addr:" "$DISASM_FILE" | \
+                sed "s/^[[:space:]]*$call_addr:/  >>> $call_addr:/" | head -11
+            echo ""
+        fi
+    done
+    
+    echo ""
+done
+
+echo -e "${CYAN}========================================${NC}"
+echo -e "${GREEN}Analysis complete!${NC}"
+echo -e "${CYAN}========================================${NC}"
+echo ""
+echo -e "${YELLOW}Summary:${NC}"
+echo -e "  • Symbol called ${MAGENTA}$CALL_COUNT${NC} time(s)"
+echo -e "  • Involves ${MAGENTA}$CALLER_COUNT${NC} distinct function(s)"
+echo ""

Reply via email to