-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpstack_gdb.sh
149 lines (131 loc) · 3.7 KB
/
pstack_gdb.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/bin/bash
dir=$(dirname $0)
function print_usage()
{
echo "Usage: $(basename $0) [OPTION]... [EXECUTABLE] CORE_FILE"
echo
echo " -f force the pstack to be generated even if the executable"
echo " does not match the core file"
echo " -o FILE write the output to FILE (default: <CORE_FILE>.pstack)"
echo
echo "Note: The EXECUTABLE argument is optional. If no EXECUTABLE is"
echo "provided, then the program will find the name of the executable"
echo "from the core and try to locate that executable on the PATH."
echo "If the executable cannot be found, then the pstack will not be"
echo "generated."
echo
echo "If the core file is generated by an nqsserver process, then the"
echo "SQL statements extracted from the NQSRequest::Execute calls will"
echo "be appended to the stack trace."
}
function error()
{
echo "$(basename $0): $@" >&2
}
executable=
force=false
pstack_file=
print_sql_script=/tmp/print_sql_$$.gdb
while getopts :fo: OPT; do
case $OPT in
f)
force=true
;;
o)
pstack_file="$OPTARG"
;;
*)
print_usage >&2
exit 2
esac
done
shift $(( OPTIND - 1 ))
OPTIND=1
if [ $# -gt 2 ] ; then
print_usage >&2
exit 2
elif [ $# -eq 2 ] ; then
executable="$1"
shift
fi
core_file="$1"
shift
core_executable=$(file $core_file | sed -e "s/.*'\\([^']*\\)'$/\\1/")
echo "Core file executable is '$core_executable'"
if [ -z "$executable" ] ; then
executable=$(type -p $core_executable)
if [ -n "$executable" ] ; then
echo "Using $executable as the full path to the executable."
else
error "Cannot find the core file executable ($core_executable) in the PATH"
error "Specify the full path to the executable on command line"
exit 1
fi
elif [ "$force" != true ] ; then
if ! expr "$executable" : ".*/$core_executable" > /dev/null ; then
error "Core file executable ($core_executable) does not match executable argument:"
error "$executable"
error "Specify the correct executable or use -f to force the pstack to be created"
exit 1
fi
fi
if [ -z "$pstack_file" ] ; then
pstack_file=$core_file.pstack
fi
function write_print_sql_script()
{
local tid
local frame
local -a map
while read line; do
if [[ $line =~ "^Thread [0-9]" ]] ; then
tid=$(echo $line | sed 's/^Thread \([0-9]*\).*/\1/')
fi
if [[ $line =~ "NQSRequest::Execute" ]] ; then
frame=$(echo $line | sed 's/^#\([0-9]*\)* .*/\1/')
map[$tid]=$frame
fi
done < $pstack_file
cat > $print_sql_script <<EOF
define wc_print
echo "
set \$c = (wchar_t*)\$arg0
while ( *\$c )
if ( *\$c > 0x7f )
printf "[%x]", *\$c
else
printf "%c", *\$c
end
set \$c++
end
echo "\n
end
set logging file $pstack_file
set logging on
set pagination off
EOF
for entry in "${!map[@]}" ; do
key=$entry
value=${map[$entry]}
echo "thread $key" >> $print_sql_script
echo "frame $value" >> $print_sql_script
echo "wc_print &sqlStatement_.m_tState.member.m_pStart" >> $print_sql_script
echo "wc_print sqlStatement_._M_tree_ptr._M_data._M_c_string" >> $print_sql_script
done
}
function capture_pstack()
{
gdb "$executable" "$core_file" <<EOF
set logging file $pstack_file
set logging overwrite on
set logging on
set pagination off
thread apply all bt
EOF
if [ "$core_executable" = "nqsserver" ] ; then
write_print_sql_script
gdb "$executable" "$core_file" < $print_sql_script
rm -f $print_sql_script
fi
}
capture_pstack