]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - debian/scripts/retpoline-extract-one
UBUNTU: Ubuntu-4.15.0-96.97
[mirror_ubuntu-bionic-kernel.git] / debian / scripts / retpoline-extract-one
CommitLineData
1e390209
AW
1#!/bin/bash
2
3exec </dev/null
4
5object="$1"
6src="$2"
7bit16="$3"
8
9SECTION=".discard.retpoline_safe"
10
11# Form an associative lookup for the symbol numbers in the ELF symbol table.
12# Uses 8 character 0 expanded hexadecimal key for ease of consumption.
13__symbolmap_init()
14{
15 readelf -W --syms "$1" |
16 awk '($4 == "SECTION" && $1 ~ /^[0-9]*:/) { printf("%08x %08x\n", int($1), int($7)); }' | \
17 while read symbol_num section_num
18 do
19 echo "symbolmap_$symbol_num='$section_num'"
20 done
21}
22symbolmap_init()
23{
24 eval $(__symbolmap_init "$1")
25}
26symbolmap()
27{
28 eval RET="\$symbolmap_$1"
29 if [ "$RET" = '' ]; then
30 echo "symbolmap: $1: invalid section" 1>&2
31 exit 1
32 fi
33}
34
35# Form an associative lookup for the section numbers in the ELF symbol table.
36# Uses 8 character 0 expanded hexadecimal key for ease of consumption.
37__sectionmap_init()
38{
39 readelf -W --headers "$1" | \
40 awk '
41 { sub("\\[", ""); sub("\\]", ""); }
42 ($1 ~ /^[0-9][0-9]*/) { printf("%08x %s %s %s\n", int($1), $2, $3, $4); }
43 ' | \
44 {
45 while read section_num section_name section_type section_vma
46 do
47 echo "sectionmap_$section_num='$section_name'"
48 echo "sectionvma_$section_num='$section_vma'"
49 case "$section_type" in
50 REL|RELA) section_relocation="$section_type" ;;
51 esac
52 done
53 echo "section_relocation='$section_relocation'"
54 }
55}
56sectionmap_init()
57{
58 eval $(__sectionmap_init "$1")
59}
60sectionmap()
61{
62 eval RET="\$sectionmap_$1"
63 if [ "$RET" = '' ]; then
64 echo "sectionmap: $1: invalid section" 1>&2
65 exit 1
66 fi
67}
68sectionvma()
69{
70 eval RET="\$sectionvma_$1"
71 if [ "$RET" = '' ]; then
72 echo "sectionvma: $1: invalid section" 1>&2
73 exit 1
74 fi
75}
76
77# Read and parse the hex-dump output.
78hex="[0-9a-f]"
79hex_8="$hex$hex$hex$hex$hex$hex$hex$hex"
80hexspc="[0-9a-f ]"
81hexspc_8="$hexspc$hexspc$hexspc$hexspc$hexspc$hexspc$hexspc$hexspc"
82
83raw32()
84{
85 readelf --hex-dump "$2" "$1" 2>/dev/null |
86 sed \
87 -e '/^Hex/d' -e '/^$/d' -e '/^ *NOTE/d' \
88 -e 's/ *[^ ][^ ]* *\('"$hex_8"'\) \('"$hexspc_8"'\) \('"$hexspc_8"'\) \('"$hexspc_8"'\) .*/\1 \2 \3 \4 /' \
89 -e 's/\('"$hex$hex"'\)\('"$hex$hex"'\)\('"$hex$hex"'\)\('"$hex$hex"'\) /\4\3\2\1 /g' \
90 -e 's/ $//g' -e 's/ /\n/g'
91}
92#-e 's/\([^ ][^ ][^ ][^ ][^ ][^ ][^ ][^ ]\) \([^ ][^ ][^ ][^ ][^ ][^ ][^ ][^ ]\) /\2\1 /g' \
93
94rela()
95{
96 #file="$(basename "$1")"
97 file="$1"
98
99 # Read relocation information for a 64bit binary. Each relocation entry
100 # is 3 long longs so we collect 6 quads here. Note that the dump is in
101 # listed in increasing byte order not withstanding the quad split.
102 #
103 # The record says to take the value of <symbol> add <symbol offset> and
104 # shove that into <write offset> in the segment of the <symbol>.
105 #
106 # Format:
107 # <write offset> 64 bits
108 # <symbol number> 32 bits
109 # <relocation type> 32 bits
110 # <symbol offset> 64 bits
111 raw32 "$1" ".rela$SECTION" | \
112 {
113 a1=''; a2=''; a3=''; a4=''; a5=''
114 while read a6
115 do
116 [ "$a1" = '' ] && { a1="$a6"; continue; }
117 [ "$a2" = '' ] && { a2="$a6"; continue; }
118 [ "$a3" = '' ] && { a3="$a6"; continue; }
119 [ "$a4" = '' ] && { a4="$a6"; continue; }
120 [ "$a5" = '' ] && { a5="$a6"; continue; }
121
122 #echo ">$a1< >$a2< >$a3< >$a4< >$a5< >$a6<" 1>&2
123 #echo "type<$a3> symbol<$a4> offset<$a2$a1> addr<$a6a5>" 1>&2
124
125 symbolmap "$a4"; section_num="$RET"
126 #echo "section_num<$section_num>" 1>&2
127
128 sectionmap "$section_num"; section="$RET"
129 sectionvma "$section_num"; vma="$RET"
130 #echo "section<$section> vma<$vma>" 1>&2
131
132 # Adjust the segment addressing by the segment offset.
133 printf -v addr "%u" "0x$a6$a5"
134 printf -v vma "%u" "0x$vma"
135 let offset="$addr + $vma"
136 printf -v offset "%x" "$offset"
137
138 echo "$file-$section-$offset"
139
140 a1=''; a2=''; a3=''; a4=''; a5=''
141 done
142 } | sed -e 's/-00*\([0-9a-f]\)/-\1/'
143}
144
145# Form an associative lookup for the raw contents for an ELF section.
146# Uses 8 character 0 expanded hexadecimal key for ease of consumption.
147contentmap_init()
148{
7d21b076 149 raw32 "$1" "$2" >"$tmp"
1e390209
AW
150 let offset=0
151 while read value
152 do
153 printf -v offset_hex "%08x" $offset
154 eval contentmap_$offset_hex=\'$value\'
155
156 let offset="$offset + 4"
7d21b076
KE
157 done <"$tmp"
158 rm -f "$tmp"
1e390209
AW
159}
160contentmap()
161{
162 eval RET="\$contentmap_$1"
163 if [ "$RET" = '' ]; then
164 echo "contentmap: $1: invalid offset" 1>&2
165 exit 1
166 fi
167}
168
169rel()
170{
171 # Load up the current contents of the $SECTION segment
172 # as the offsets (see below) are recorded there and we will need
173 # those to calculate the actuall address.
174 contentmap_init "$1" "$SECTION"
175
176 #file="$(basename "$1")"
177 file="$1"
178
179 # Read relocation information for a 32bit binary. Each relocation entry
180 # is 3 longs so we collect 3 quads here. Note that the dump is in
181 # listed in increasing byte order not withstanding the quad split.
182 #
183 # The record says to take the value of <symbol> and add that to the
184 # existing contents of <write offset> in the segment of the <symbol>.
185 #
186 # Format:
187 # <write offset> 32 bits
188 # <symbol number> 24 bits
189 # <relocation type> 8 bits
190 raw32 "$1" ".rel$SECTION" | \
191 {
192 a1=''
193 while read a2
194 do
195 [ "$a1" = '' ] && { a1="$a2"; continue; }
196
197 #echo ">$a1< >$a2<"
198 contentmap "$a1"; offset="$RET"
199 symbolmap "00${a2%??}"; section_num="$RET"
200
201 sectionmap "$section_num"; section="$RET"
202 sectionvma "$section_num"; vma="$RET"
203 #echo ">$a1< >$a2< >$offset< >$section<"
204
205 echo "$file-$section-$offset"
206
207 a1=''
208 done
209 } | sed -e 's/-00*\([0-9a-f]\)/-\1/'
210}
211
7d21b076 212tmp=$(mktemp --tmpdir "retpoline-extract-XXXXXX")
1e390209 213
88c426b4
AW
214disassemble()
215{
216 local object="$1"
217 local src="$2"
218 local options="$3"
219 local selector="$4"
220
221 objdump $options --disassemble --no-show-raw-insn "$object" | \
222 awk -F' ' '
223 BEGIN { file="'"$object"'"; src="'"$src"'"; }
224 /Disassembly of section/ { segment=$4; sub(":", "", segment); }
225 /^[0-9a-f][0-9a-f]* <.*>:/ { tag=$0; sub(".*<", "", tag); sub(">.*", "", tag); }
e0602aaa
AW
226 $0 ~ /(call|jmp)q? *\*0x[0-9a-f]*\(%rip\)/ {
227 next
228 }
88c426b4
AW
229 $0 ~ /(call|jmp)q? *\*.*%/ {
230 sub(":", "", $1);
231 if ('"$selector"') {
232 offset=$1
233 $1=tag
234 print(file "-" segment "-" offset " " src " " segment " " $0);
235 }
236 }
237 '
238}
239
1e390209
AW
240# Accumulate potentially vunerable indirect call/jmp sequences. We do this
241# by examining the raw disassembly for affected forms, recording the location
242# of each.
243case "$bit16" in
88c426b4
AW
244'') disassemble "$object" "$src" '' 'segment != ".init.text"' ;;
245*) disassemble "$object" "$src" '--disassembler-options=i8086' 'segment != ".init.text" && segment != ".text32" && segment != ".text64"'
246 disassemble "$object" "$src" '--disassembler-options=i386' 'segment == ".text32"'
247 disassemble "$object" "$src" '--disassembler-options=x86-64' 'segment == ".text64"'
248 ;;
249esac | sort -k 1b,1 >"$object.ur-detected"
1e390209
AW
250[ ! -s "$object.ur-detected" ] && rm -f "$object.ur-detected"
251
252# Load up the symbol table and section mappings.
253symbolmap_init "$object"
254sectionmap_init "$object"
255
256# Accumulate annotated safe indirect call/jmp sequences. We do this by examining
257# the $SECTION sections (and their associated relocation information),
258# each entry represents the address of an instruction which has been marked
259# as ok.
260case "$section_relocation" in
261REL) rel "$object" ;;
262RELA) rela "$object" ;;
263esac | sort -k 1b,1 >"$object.ur-safe"
264[ ! -s "$object.ur-safe" ] && rm -f "$object.ur-safe"
265
266# We will perform the below join on the summarised and sorted fragments
267# formed above. This is performed in retpoline-check.
268#join -v 1 -j 1 "$tmp.extracted" "$tmp.safe" | sed -s 's/[^ ]* *//'
269
7d21b076 270rm -f "$tmp"