1. 概述
github项目地址:https://github.com/superwujc
尊重原创,欢迎转载,注明出处:https://my.oschina.net/superwjc/blog/1827736
阅读内核源码的过程中,经常需要查看变量的定义与赋值情况,虽然有诸如elixir.bootlin.com与source insight等工具,但不够快速与直观:全局变量的值经常在多个文件中被引用与更改,需要跨文件查找,且变量为结构体成员时,elixir通常无法查看该变量的定义与引用情况;本例基于awk与bash实现了一个简单的功能,以字符串(通常为全局变量或结构体实例)为关键字作为输入,输出为该字符串所在的函数名称,便于快速定位变量的位置,以及跟踪变量的赋值情况。
2. 示例程序
awk规则用于关键字查找以及相应的函数定位
search_rules.awk
#! /usr/bin/env awk
# search_rules.awk
BEGIN {
if (str == "") {
print "invalid string to search"
exit;
}
}
{ lines[NR] = $0; }
END {
for (i = 1; i <= NR; i++) {
if (index(lines[i], str) == 0) { continue; }
for (j = i - 1; j >= 1; j--) {
if (match(lines[j], /^{/) == 0) { continue; }
for (k = j - 1; k >= 1; k--) {
if (match(lines[k], /^\s+/)) { continue; }
split(lines[k], temp, "(");
split(temp[1], tokens, /[* ]/);
printf("\n%s: %-6d %s: %d", str, i, tokens[length(tokens)], k);
fflush();
break;
}
break;
}
}
print "\n"
}
通过shell脚本向awk传递参数,包括需要查找的字符串(-s/--string),以及文件名(-f/--file)
funcsearch.sh
#! /bin/bash
# funcsearch.sh
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :
set -o errexit
set -o nounset
if [[ $# != 4 ]]; then
echo -ne "Usage: \n"
echo -ne " -s|--string the string to search\n"
echo -ne " -f|--file the filename to contains the string\n\n"
fi
TEMP=$(getopt -o f:s: -l file:,string: -n 'bash.getopt(1)' -- "$@")
s_rules="./search_rules.awk"
unset s_file
unset s_str
if [ $? != 0 ] ; then echo "Error occurred, abort." >&2 ; exit 1 ; fi
eval set -- "$TEMP"
while true ; do
case "$1" in
-f|--file) s_file=$2; shift 2 ;;
-s|--string) s_str=$2; shift 2 ;;
--) shift; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
echo "string: \"${s_str}\""
echo "file: \"${s_file}\""
echo "rules: \"${s_rules}\":"
awk -v str="${s_str}" -f "${s_rules}" "${s_file}"
例如,在sock.c文件中查找->sk_sndbuf
# ./funcsearch.sh -s "->sk_sndbuf" -f sock.c
string: "->sk_sndbuf"
file: "sock.c"
rules: "./search_rules.awk":
->sk_sndbuf: 717 sock_setsockopt: 657
->sk_sndbuf: 1010 sock_getsockopt: 975
->sk_sndbuf: 1725 sock_wmalloc: 1722
->sk_sndbuf: 1798 sock_wait_for_wmem: 1786
->sk_sndbuf: 1833 sock_alloc_send_pskb: 1815
->sk_sndbuf: 2070 __sk_mem_raise_allocated: 2012
->sk_sndbuf: 2296 sock_def_write_space: 2287
->sk_sndbuf: 2297 sock_def_write_space: 2287
->sk_sndbuf: 2351 sock_init_data: 2339
输出的格式为字符串或变量的行号,以及所在函数的行号