blob: cde0d9001eeef6a43a03925f2f5f545d6865d990 [file] [log] [blame]
Hanno Becker43fa8d62019-03-18 17:12:05 +00001#!/bin/sh
2
3# baremetal.sh
4#
5# This file is part of mbed TLS (https://tls.mbed.org)
6#
7# Copyright (c) 2019, ARM Limited, All Rights Reserved
8#
9# Purpose
10#
11# * Create a baremetal library-only build (omitting the tests and
12# example programs, which have stronger configuration requirements)
13# for a Cortex-M target in a minimal configuration, and generate
14# code-size statistics.
15# By default, the script uses configs/baremetal.h and targets Cortex-M0+,
16# and outputs the code-size statistics as `rom.COMMIT_HASH`.
17#
18# * Create a 32-bit host-build of library, tests and example programs
19# in a 'baremetal' base configuration minimally modified to allow
20# running tests and example programs, and obtain heap usage statistics
21# of a test run of ssl_client2 and ssl_server2. This can be used as
22# an estimate for heap usage of 32-bit baremetal applications using Mbed TLS.
23#
24# By default, the script uses configs/baremetal.h as the base configuration
25# modified by configs/baremetal_test.h, and emits the heap usage statistics
26# as `massif.COMMIT_HASH`.
27#
28
29set -eu
30
31if [ -d include/mbedtls ]; then :; else
32 echo "$0: must be run from root" >&2
33 exit 1
34fi
35
36if grep -i cmake Makefile >/dev/null; then
37 echo "$0: not compatible with cmake" >&2
38 exit 1
39fi
40
41# The 'baremetal' configuration to test
42: ${BAREMETAL_CONFIG:=./configs/baremetal.h}
43CFLAGS_CONFIG="-DMBEDTLS_CONFIG_FILE='\"../$BAREMETAL_CONFIG\"'"
44
45# The modifications to the 'baremetal' configuration which allows
46# tests and example programs to build and execute.
47: ${BAREMETAL_USER_CONFIG:=./configs/baremetal_test.h}
48CFLAGS_USER_CONFIG="-DMBEDTLS_USER_CONFIG_FILE='\"../$BAREMETAL_USER_CONFIG\"'"
49
50: ${ARMC5_BIN_DIR:=""}
51: ${ARMC6_BIN_DIR:=""}
52if [ -n "$ARMC5_BIN_DIR" ]; then
53 ARMC5_BIN_DIR="$ARMC5_BIN_DIR/"
54fi
55
56if [ -n "$ARMC6_BIN_DIR" ]; then
57 ARMC6_BIN_DIR="$ARMC6_BIN_DIR/"
58fi
59
60: ${NAME:=$(git rev-parse HEAD)}
61: ${GCC_CC:=arm-none-eabi-gcc}
62: ${GCC_AR:=arm-none-eabi-ar}
63: ${ARMC6_CC:="${ARMC6_BIN_DIR}armclang"}
64: ${ARMC6_AR:="${ARMC6_BIN_DIR}armar"}
65: ${ARMC5_CC:="${ARMC5_BIN_DIR}armcc"}
66: ${ARMC5_AR:="${ARMC5_BIN_DIR}armar"}
67
68date=$( date +%Y-%m-%d-%H-%M-%S )
69
Manuel Pégourié-Gonnard15be0ee2019-09-20 10:25:29 +020070print_rom_report()
71{
72 echo "ROM statistics written to:"
73 echo "* $ROM_OUT_FILE"
74 echo "* $ROM_OUT_SYMS"
75
76 cat $ROM_OUT_FILE | grep "libmbedtls.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
77 cat $ROM_OUT_FILE | grep "libmbedcrypto.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
78 cat $ROM_OUT_FILE | grep "libmbedx509.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
79}
80
Hanno Becker43fa8d62019-03-18 17:12:05 +000081baremetal_build_gcc()
82{
83 echo "Cleanup..."
84 make clean
85
86 echo "Create 32-bit library-only baremetal build (GCC, config: $BAREMETAL_CONFIG)"
87 gcc_ver=$($GCC_CC --version | head -n 1 | sed -n 's/^.*\([0-9]\.[0-9]\.[0-9]\).*$/\1/p')
88
Hanno Becker0a4c78f2019-07-25 14:55:47 +010089 if [ $debug -eq 0 ]; then
90 OPTIM_CFLAGS_GCC="-Os"
91 else
92 OPTIM_CFLAGS_GCC="-g"
93 fi
94
95 CFLAGS_BAREMETAL="$OPTIM_CFLAGS_GCC -mthumb -mcpu=cortex-m0plus --std=c99"
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +020096 if [ $check -ne 0 ]; then
97 CFLAGS_BAREMETAL="$CFLAGS_BAREMETAL -Werror"
98 fi
Hanno Becker43fa8d62019-03-18 17:12:05 +000099 CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG"
100
Hanno Becker43fa8d62019-03-18 17:12:05 +0000101 echo "GCC version: $gcc_ver"
102 echo "Flags: $CFLAGS_BAREMETAL"
103 make CC=$GCC_CC AR=$GCC_AR CFLAGS="$CFLAGS" lib -j > /dev/null
104
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200105 if [ $check -ne 0 ]; then
106 return
107 fi
108
Hanno Becker43fa8d62019-03-18 17:12:05 +0000109 ROM_OUT_FILE="rom_files__${date}__${NAME}__gcc_${gcc_ver}"
110 ROM_OUT_SYMS="rom_syms__${date}__${NAME}__gcc_${gcc_ver}"
111 echo "Generate file statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100112 ./scripts/extract_codesize_stats.sh --info "gcc_${gcc_ver}" --name $NAME --files > $ROM_OUT_FILE
Hanno Becker43fa8d62019-03-18 17:12:05 +0000113 echo "Generate symbol statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100114 ./scripts/extract_codesize_stats.sh --info "gcc_${gcc_ver}" --name $NAME --syms > $ROM_OUT_SYMS
Hanno Becker43fa8d62019-03-18 17:12:05 +0000115
Manuel Pégourié-Gonnard15be0ee2019-09-20 10:25:29 +0200116 print_rom_report
Hanno Becker43fa8d62019-03-18 17:12:05 +0000117}
118
119baremetal_build_armc5()
120{
121 echo "Cleanup..."
122 make clean
123
124 echo "Create 32-bit library-only baremetal build (ARMC5, Config: $BAREMETAL_CONFIG)"
125 armc5_ver=$($ARMC5_CC | sed -n 's/.*ARM Compiler \([^ ]*\)$/\1/p')
126
Hanno Becker0a4c78f2019-07-25 14:55:47 +0100127 if [ $debug -eq 0 ]; then
128 OPTIM_CFLAGS_ARMC5="-Ospace"
129 else
130 OPTIM_CFLAGS_ARMC5="-g"
131 fi
132
133 CFLAGS_BAREMETAL="$OPTIM_CFLAGS_ARMC5 --thumb --cpu Cortex-m0plus"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000134 CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG"
135 WARNING_CFLAGS="--strict --c99"
136
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200137 if [ $check -ne 0 ]; then
138 WARNING_CFLAGS="$WARNING_CFLAGS --diag_error=warning"
139 fi
140
Hanno Becker43fa8d62019-03-18 17:12:05 +0000141 echo "ARMC5 version: $armc5_ver"
142 echo "Flags: $WARNING_CFLAGS $CFLAGS_BAREMETAL"
143 make WARNING_CFLAGS="$WARNING_CFLAGS" CC=$ARMC5_CC AR=$ARMC5_AR CFLAGS="$CFLAGS" lib -j > /dev/null
144
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200145 if [ $check -ne 0 ]; then
146 return
147 fi
148
Hanno Becker43fa8d62019-03-18 17:12:05 +0000149 ROM_OUT_FILE="rom_files__${date}__${NAME}__armc5_${armc5_ver}"
150 ROM_OUT_SYMS="rom_syms__${date}__${NAME}__armc5_${armc5_ver}"
151 echo "Generate file statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100152 ./scripts/extract_codesize_stats.sh --info "armc5_${armc5_ver}" --name $NAME --files > $ROM_OUT_FILE
Hanno Becker43fa8d62019-03-18 17:12:05 +0000153 echo "Generate symbol statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100154 ./scripts/extract_codesize_stats.sh --info "armc5_${armc5_ver}" --name $NAME --syms > $ROM_OUT_SYMS
Hanno Becker43fa8d62019-03-18 17:12:05 +0000155
Manuel Pégourié-Gonnard15be0ee2019-09-20 10:25:29 +0200156 print_rom_report
Hanno Becker43fa8d62019-03-18 17:12:05 +0000157}
158
159baremetal_build_armc6()
160{
161 echo "Cleanup..."
162 make clean
163
164 echo "Create 32-bit library-only baremetal build (ARMC6, Config: $BAREMETAL_CONFIG)"
165 armc6_ver=$($ARMC6_CC --version | sed -n 's/.*ARM Compiler \([^ ]*\)$/\1/p')
166
Hanno Becker0a4c78f2019-07-25 14:55:47 +0100167 if [ $debug -eq 0 ]; then
168 OPTIM_CFLAGS_ARMC6="-Oz"
169 else
170 OPTIM_CFLAGS_ARMC6="-g"
171 fi
172
173 CFLAGS_BAREMETAL="$OPTIM_CFLAGS_ARMC6 --target=arm-arm-none-eabi -mthumb -mcpu=cortex-m0plus -xc --std=c99"
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200174 if [ $check -ne 0 ]; then
175 CFLAGS_BAREMETAL="$CFLAGS_BAREMETAL -Werror"
176 fi
Hanno Becker43fa8d62019-03-18 17:12:05 +0000177 CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000178
179 echo "ARMC6 version: $armc6_ver"
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200180 echo "Flags: $CFLAGS_BAREMETAL"
181 make CC=$ARMC6_CC AR=$ARMC6_AR CFLAGS="$CFLAGS" lib -j > /dev/null
182
183 if [ $check -ne 0 ]; then
184 return
185 fi
Hanno Becker43fa8d62019-03-18 17:12:05 +0000186
187 ROM_OUT_FILE="rom_files__${date}__${NAME}__armc6_${armc6_ver}"
188 ROM_OUT_SYMS="rom_syms__${date}__${NAME}__armc6_${armc6_ver}"
189 echo "Generate file statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100190 ./scripts/extract_codesize_stats.sh --info "armc6_${armc6_ver}" --name $NAME --files > $ROM_OUT_FILE
Hanno Becker43fa8d62019-03-18 17:12:05 +0000191 echo "Generate symbol statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100192 ./scripts/extract_codesize_stats.sh --info "armc6_${armc6_ver}" --name $NAME --syms > $ROM_OUT_SYMS
Hanno Becker43fa8d62019-03-18 17:12:05 +0000193
Manuel Pégourié-Gonnard15be0ee2019-09-20 10:25:29 +0200194 print_rom_report
Hanno Becker43fa8d62019-03-18 17:12:05 +0000195}
196
197# 32-bit host-build of library, tests and example programs,
198# + heap usage measurements.
199baremetal_ram_build() {
Hanno Beckerc7c20812019-04-03 11:55:57 +0100200 : ${BASE_CFLAGS:="-g -m32 -fstack-usage"}
Hanno Becker43fa8d62019-03-18 17:12:05 +0000201 echo "Create 32-bit host-build (Config: $BAREMETAL_CONFIG + $BAREMETAL_USER_CONFIG)"
202
203 echo "Cleanup..."
204 make clean
205
206 CFLAGS="$BASE_CFLAGS $CFLAGS_CONFIG $CFLAGS_USER_CONFIG"
Manuel Pégourié-Gonnardd64a2f72019-07-30 14:54:50 +0200207 if [ "$build_only" -eq 1 ]; then
208 CFLAGS="$CFLAGS -Werror"
209 fi
Hanno Becker43fa8d62019-03-18 17:12:05 +0000210
211 echo "Modifications: $BAREMETAL_USER_CONFIG"
212 cat $BAREMETAL_USER_CONFIG | grep "^#define" | awk '{print "* " $0 }'
213
214 echo "Build (flags: $CFLAGS)..."
215 make CFLAGS="$CFLAGS" -j > /dev/null
216 echo ""
217}
218
Hanno Becker5541e4e2019-04-03 11:31:43 +0100219# usage:
220# - `baremetal_ram_heap 0` for heap usage only
221# - `baremetal_ram_heap 1` for heap and stack usage
Hanno Becker43fa8d62019-03-18 17:12:05 +0000222baremetal_ram_heap() {
223
224 : ${CLI:=./programs/ssl/ssl_client2}
Hanno Becker4ce06042019-04-30 14:18:25 +0100225 : ${CLI_PARAMS:="dtls=1 cid=1 cid_val=beef"}
Hanno Becker43fa8d62019-03-18 17:12:05 +0000226 : ${SRV:=./programs/ssl/ssl_server2}
Hanno Becker3b876ac2019-06-21 15:51:19 +0100227 : ${SRV_PARAMS:="dtls=1 cid=1 cid_val=dead"} # renegotiation=1 auth_mode=required implicit
228 # compile-time hardcoding of configuration
Hanno Becker43fa8d62019-03-18 17:12:05 +0000229 : ${VALGRIND:=valgrind}
230 : ${VALGRIND_MASSIF_PARAMS="--time-unit=B --threshold=0.01 --detailed-freq=1"}
231
232 if [ $1 -eq 1 ]; then
233 RAM_HEAP_OUT="ram_heap_stack__${date}__$NAME"
234 VALGRIND_MASSIF_PARAMS="--stacks=yes $VALGRIND_MASSIF_PARAMS"
235 else
236 RAM_HEAP_OUT="ram_heap__${date}__$NAME"
237 fi
238
239 SRV_CMD="$SRV server_addr=127.0.0.1 server_port=4433 debug_level=4 $SRV_PARAMS"
240 CLI_CMD="$CLI server_addr=127.0.0.1 server_port=4433 $CLI_PARAMS"
241
242 # Piece together valgrind cmd line
243 VALGRIND_BASE="$VALGRIND --tool=massif $VALGRIND_MASSIF_PARAMS"
244
245 FUNC_IGNORE=""
Hanno Becker43fa8d62019-03-18 17:12:05 +0000246 FUNC_IGNORE="__fopen_internal $FUNC_IGNORE"
247 FUNC_IGNORE="_IO_file_doallocate $FUNC_IGNORE"
248 FUNC_IGNORE="strdup $FUNC_IGNORE"
249 FUNC_IGNORE="__tzstring_len $FUNC_IGNORE"
250 FUNC_IGNORE="__tzfile_read $FUNC_IGNORE"
251
252 VALGRIND_IGNORE=""
253 for func in $FUNC_IGNORE; do
254 echo "* Valgrind ignore: $func"
255 VALGRIND_IGNORE="--ignore-fn=$func $VALGRIND_IGNORE"
256 done
257
258 VALGRIND_CMD="$VALGRIND_BASE $VALGRIND_IGNORE --massif-out-file=${RAM_HEAP_OUT} -- $CLI_CMD"
259
260 $SRV_CMD > /dev/null 2>&1 &
261 SRV_PID=$!
262 echo "Server started, PID $SRV_PID"
263
264 $VALGRIND_CMD > /dev/null 2>&1 &
265 VAL_PID=$!
266 echo "Valgrind massif started, PID $VAL_PID"
267
268 wait $VAL_PID
269 echo "Valgrind done, killing server"
270 kill $SRV_PID
271 echo "Done"
272
273 if `cat $RAM_HEAP_OUT | grep '???'` >/dev/null 2>&1; then
274 echo "Warning: Unrecognized symbols in massif output file - does your version of `valgrind` support 32-bit builds?"
275 fi
276
277 printf "Max heap usage: "
278 ./scripts/massif_max.pl $RAM_HEAP_OUT
279 echo "SUCCESS - Heap usage statistics written to: $RAM_HEAP_OUT\n"
280}
281
282baremetal_ram_stack() {
283 : ${CLI:=./programs/ssl/ssl_client2}
284 : ${CLI_PARAMS:="dtls=1"}
285 : ${SRV:=./programs/ssl/ssl_server2}
Hanno Becker3b876ac2019-06-21 15:51:19 +0100286 : ${SRV_PARAMS:="dtls=1"} # renegotiation=1 auth_mode=required implicit
287 # compile-time hardcoding of configuration
Hanno Becker43fa8d62019-03-18 17:12:05 +0000288 : ${VALGRIND:=valgrind}
289 : ${VALGRIND_CALLGRIND_PARAMS:="--separate-callers=100"}
290
Hanno Beckerc7c20812019-04-03 11:55:57 +0100291 RAM_CALLGRIND_OUT="ram_callgrind__${date}__$NAME"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000292 RAM_STACK_OUT="ram_stack__${date}__$NAME"
293
294 SRV_CMD="$SRV server_addr=127.0.0.1 server_port=4433 debug_level=4 $SRV_PARAMS"
295 CLI_CMD="$CLI server_addr=127.0.0.1 server_port=4433 $CLI_PARAMS"
296
297 VALGRIND_BASE="$VALGRIND --tool=callgrind $VALGRIND_CALLGRIND_PARAMS"
Hanno Beckerc7c20812019-04-03 11:55:57 +0100298 VALGRIND_CMD="$VALGRIND_BASE --callgrind-out-file=${RAM_CALLGRIND_OUT} $CLI_CMD"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000299
300 $SRV_CMD > /dev/null 2>&1 &
301 SRV_PID=$!
302 echo "Server started, PID $SRV_PID"
303
304 $VALGRIND_CMD > /dev/null 2>&1 &
305 VAL_PID=$!
306 echo "Valgrind callgrind started, PID $VAL_PID"
307
308 wait $VAL_PID
309 echo "Valgrind done, killing server"
310 kill $SRV_PID
311 echo "Done"
312
Hanno Becker13737242019-04-03 12:17:20 +0100313 # Extract callgraphs from source files directly
Hanno Becker7f6e8082019-04-03 13:48:09 +0100314 RAM_CALLGRAPH_OUT=""
Hanno Becker13737242019-04-03 12:17:20 +0100315 if [ -x "$(command -v cflow)" ]; then
316 RAM_CALLGRAPH_OUT="ram_cflow__${date}__$NAME"
317 cflow library/*.c > $RAM_CALLGRAPH_OUT 2> /dev/null
318 fi
319
Hanno Beckerc7c20812019-04-03 11:55:57 +0100320 # Merge stack usage files
321 cat library/*.su > ${RAM_STACK_OUT}_unsorted
322 sort -r -k2 -n ${RAM_STACK_OUT}_unsorted > $RAM_STACK_OUT
323 rm ${RAM_STACK_OUT}_unsorted
324
Hanno Becker13737242019-04-03 12:17:20 +0100325 echo "SUCCESS"
326 echo "* Stack usage statistics written to $RAM_STACK_OUT"
327 echo "* Callgrind output written to $RAM_CALLGRIND_OUT"
328 if [ -n $RAM_CALLGRAPH_OUT ]; then
329 echo "* Static call graph written to $RAM_CALLGRAPH_OUT"
330 fi
Hanno Becker43fa8d62019-03-18 17:12:05 +0000331}
332
333show_usage() {
Hanno Beckera1f3c522019-07-22 12:37:21 +0100334 echo "Usage: $0 [--rom [--check] [--gcc] [--armc5] [--armc6]|--ram [--build-only] [--stack] [--heap]]"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000335}
336
337test_build=0
338raw_build=0
339
340build_gcc=0
341build_armc5=0
342build_armc6=0
343
344measure_heap=0
345measure_stack=0
346
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200347check=0
Manuel Pégourié-Gonnardd64a2f72019-07-30 14:54:50 +0200348build_only=0
Hanno Becker0a4c78f2019-07-25 14:55:47 +0100349debug=0
350
Hanno Becker43fa8d62019-03-18 17:12:05 +0000351while [ $# -gt 0 ]; do
352 case "$1" in
353 --gcc) build_gcc=1;;
354 --armc5) build_armc5=1;;
355 --armc6) build_armc6=1;;
356 --ram) test_build=1;;
357 --rom) raw_build=1;;
Hanno Beckera1f3c522019-07-22 12:37:21 +0100358 --build-only) build_only=1;;
Hanno Becker43fa8d62019-03-18 17:12:05 +0000359 --heap) measure_heap=1;;
360 --stack) measure_stack=1;;
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200361 --check) check=1;;
Hanno Becker0a4c78f2019-07-25 14:55:47 +0100362 --debug) debug=1;;
Hanno Becker43fa8d62019-03-18 17:12:05 +0000363 -*)
364 echo >&2 "Unknown option: $1"
365 show_usage
366 exit 1
367 ;;
368 esac
369 shift
370done
371
372if [ "$test_build" -eq 0 ] &&
373 [ "$raw_build" -eq 0 ]; then
374 echo "Need to set either --ram or --rom"
375 show_usage
376 exit 1
377fi
378
379if [ "$test_build" -eq 1 ]; then
380
381 if [ "$measure_heap" -eq 0 ] &&
Hanno Beckera1f3c522019-07-22 12:37:21 +0100382 [ "$measure_stack" -eq 0 ] &&
383 [ "$build_only" -eq 0 ]; then
384 echo "Need to set either --build-only, --heap or --stack with --ram"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000385 show_usage
386 exit 1
387 fi
388
389 baremetal_ram_build
390
391 if [ "$measure_heap" -eq 1 ]; then
392 baremetal_ram_heap 0
393 baremetal_ram_heap 1
394 fi
395
396 if [ "$measure_stack" -eq 1 ]; then
397 baremetal_ram_stack
398 fi
399
400fi
401
402if [ "$raw_build" -eq 1 ]; then
403
404 if [ "$build_gcc" -eq 0 ] &&
405 [ "$build_armc5" -eq 0 ] &&
406 [ "$build_armc6" -eq 0 ]; then
407 echo "Need to set either --gcc, --armc5 or --armc6 with --rom"
408 show_usage
409 exit 1
410 fi
411
412 if [ "$build_gcc" -eq 1 ]; then
413 baremetal_build_gcc
414 fi
415 if [ "$build_armc5" -eq 1 ]; then
416 baremetal_build_armc5
417 fi
418 if [ "$build_armc6" -eq 1 ]; then
419 baremetal_build_armc6
420 fi
421fi