aboutsummaryrefslogtreecommitdiff
path: root/scripts/extsymsize.sh
blob: d7f2572e5b1fee17aaae885d9deec626862cf7ee (plain)
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
#!/bin/bash
## \file
# \brief Process the standard input to extract the desired fields from readelf
#	output. Use \c do_symsize.sh to generate the tables for all targets.

# The number of symbol tables. Should be 1 but multiple symbol tables may exist.
NB_SYMTABS=0
# The headers of the fields to extract in the order they should appear in the
# output.
declare -a FMT_HEADERS
FMT_HEADERS=(
	"size"
	"type"
	"name"
)

##
# \brief Skip to the line that matches the regular expression
# \param 1 The regular expression of the line to skip to
# \retval 0 if a line that mathces the regular expression has been processed and
#	the pending standard input data is now the line that follows.
# \retval 1 if no match has been found and the standard input has reached EOF.
skip_to () {
	while read l; do
		if echo "$l" | egrep -q "$1"; then
			return 0
		fi
	done
	return 1
}

##
# \brief This is just like \c echo, except that it outputs to the standard
#	error, not output.
echo_err () {
	echo $@ >&2
}

##
# \brief Exit with error code and message.
# \param 1 (optional)The error message. No output is generated if empty string.
# \param 2 (optional)The exit code. Must be a numeric value that's accepted by
#	the OS. The default value 1 is used if empty string.
die () {
	local ec

	if [ ! -z "$1" ]; then
		echo_err "$1" >&2
	fi
	if [ -z "$2" ]; then
		ec=1
	else
		ec="$2"
	fi
	exit $ec
}

# For each symbol table
while skip_to "^[Ss]ymbol table '(\\.|\\w)+' contains [0-9]+ entries:\$"; do
	unset idx_map name_map
	declare -A idx_map name_map

	# Read the header line
	if ! read l; then
		die "Unexpected EOF"
	fi
	let 'NB_SYMTABS += 1'

	# Map the fields
	i=0
	for h in $l; do
		h="${h,,}"

		case "$h" in
		"num") idx_map["$h"]=$i ;;
		"value") idx_map["$h"]=$i ;;
		"size") idx_map["$h"]=$i ;;
		"type") idx_map["$h"]=$i ;;
		"bind") idx_map["$h"]=$i ;;
		"vis") idx_map["$h"]=$i ;;
		"ndx") idx_map["$h"]=$i ;;
		"name") idx_map["$h"]=$i ;;
		esac
		name_map["$i"]="$h"
		let 'i += 1'
	done

	# Check if all the fields desired are there
	for i in ${FMT_HEADERS[@]}; do
		if [ -z ${idx_map["$i"]} ]; then
			echo_err "Missing header in symbol table: ${FMT_HEADERS["$i"]}"
			die "Headers required in symbol table: ${FMT_HEADERS[*]}"
		fi
	done

	# For each entry line
	# Assume that the table ends with an empty line
	while read l && [ ! -z "$l" ]; do
		unset size type name

		i=0
		for w in $l; do
			case "${name_map[$i]}" in
			"size") size="$w" ;;
			"type") type="$w" ;;
			"name") name="$w" ;;
			"") die "Format error." ;;
			esac
			let 'i += 1'
		done

		if [ "$size" -eq 0 ]; then
			continue
		fi
		printf "%10u %c %s\n" $size ${type:0:1} $name
	done
done

# Treat input data with no symbol table as error
if [ $NB_SYMTABS -eq 0 ]; then
	die "No symbol table found."
fi
exit 0