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
|
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-or-later
set -o pipefail -o errexit
if [ "$2" != types ] && [ "$2" != functions ] && [ "$2" != variables ]; then
echo "Usage: $0 libkres (types|functions|variables)" >&2
echo " and input identifiers, one per line." >&2
echo " You need debug symbols in the library." >&2
echo
echo " If you call this on a type that's a typedef, it gets expanded." >&2
echo " To avoid that, prefix the identifier with 'typedef '." >&2
exit 1
fi
if ! command -v gdb >/dev/null; then
echo "Failed to find gdb" >&2
exit 1
fi
if ! command -v sed >/dev/null; then
echo "Failed to find GNU sed" >&2
exit 1
fi
if ! sed --version | head -1 | grep -q "GNU sed"; then
echo "GNU sed required to run this script" >&2
fi
# be very precise with the directories for libraries to not pick wrong library
case "$1" in
libknot) library="$(PATH="$(pkg-config libknot --variable=libdir)" command -v "$1.so")" ;;
libzscanner) library="$(PATH="$(pkg-config libzscanner --variable=libdir)" command -v "$1.so")" ;;
*) library="$(command -v "$1")" # use absolute path to library
esac
if [ -z "$library" ]; then
echo "$1 not found. Note: only .so platforms work currently." >&2
exit 1
fi
# Let's use an array to hold command-line arguments, to simplify quoting.
GDB=(gdb)
GDB+=(-n -quiet -batch "-symbols=$library")
GDB+=(-iex "set width unlimited" -iex "set max-value-size unlimited")
grep -v '^#\|^$' | while read -r ident; do
if [ "$2" = functions ]; then
output="$("${GDB[@]}" --ex "info functions ^$ident\$" \
| sed '0,/^All functions/ d; /^File .*:$/ d')"
elif [ "$2" = types ]; then
case "$ident" in
struct\ *|union\ *|enum\ *)
output="$("${GDB[@]}" --ex "ptype $ident" \
| sed '0,/^type = /s/^type = /\n/; $ s/$/;/')"
;;
typedef\ *) # typedef that shouldn't be expanded
output="$("${GDB[@]}" --ex "info types ^"$(echo "$ident" | sed 's/^typedef //')"\$" \
| sed -e '0,/^File .*:$/ d' -e '/^File .*:$/,$ d')"
# we need to stop early to remove ^^ multiple matches
;;
*) # we assume it's a typedef that should be expanded
output="$("${GDB[@]}" --ex "ptype $ident" \
| sed "0,/^type = /s/^type = /typedef /; $ s/$/ $ident;/")"
;;
esac
elif [ "$2" = variables ]; then
output="$("${GDB[@]}" --ex "info variables -q ^$ident\$" \
| sed -e '0,/^File .*:$/ d' -e '/^File .*:$/,$ d')"
else
exit 1
fi
# LuaJIT FFI blows up on "uint" type
output="$(echo "$output" | sed 's/\buint\b/unsigned int/g')"
# GDB 8.2+ added source line prefix to output
output="$(echo "$output" | sed 's/^[0-9]\+:[[:space:]]*//g')"
# use tabs instead of spaces
output="$(echo "$output" | sed 's/ /\t/g')"
# abort on empty output
if [ -z "$(echo "$output" | tr -d "\n;")" ]; then
echo "Failed to find cdef of $ident" >&2
exit 1
fi
echo "$output" | grep -v '^$'
done
exit 0
|