blob: e2c0338d18ebdfff7f11d43db3155bd9feec613f [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
Manuel Pégourié-Gonnardd2c24862019-09-20 10:29:29 +020076 <$ROM_OUT_FILE awk '$4 ~ /libmbedcrypto/ {printf("%15s: %5s Bytes\n", $4, $5)}'
77 <$ROM_OUT_FILE awk '$4 ~ /libmbedx509/ {printf("%15s: %5s Bytes\n", $4, $5)}'
78 <$ROM_OUT_FILE awk '$4 ~ /libmbedtls/ {printf("%15s: %5s Bytes\n", $4, $5)}'
79 <$ROM_OUT_FILE awk '$4 ~ /libmbed/ {sum += $5} END {printf("%15s: %5d Bytes\n", "total", sum)}'
Manuel Pégourié-Gonnard15be0ee2019-09-20 10:25:29 +020080}
81
Hanno Becker43fa8d62019-03-18 17:12:05 +000082baremetal_build_gcc()
83{
84 echo "Cleanup..."
85 make clean
86
87 echo "Create 32-bit library-only baremetal build (GCC, config: $BAREMETAL_CONFIG)"
88 gcc_ver=$($GCC_CC --version | head -n 1 | sed -n 's/^.*\([0-9]\.[0-9]\.[0-9]\).*$/\1/p')
89
Hanno Becker0a4c78f2019-07-25 14:55:47 +010090 if [ $debug -eq 0 ]; then
91 OPTIM_CFLAGS_GCC="-Os"
92 else
93 OPTIM_CFLAGS_GCC="-g"
94 fi
95
96 CFLAGS_BAREMETAL="$OPTIM_CFLAGS_GCC -mthumb -mcpu=cortex-m0plus --std=c99"
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +020097 if [ $check -ne 0 ]; then
98 CFLAGS_BAREMETAL="$CFLAGS_BAREMETAL -Werror"
99 fi
Andrzej Kurek3e80b1a2020-12-07 07:01:22 -0500100 CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG -DENABLE_TESTS"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000101
Hanno Becker43fa8d62019-03-18 17:12:05 +0000102 echo "GCC version: $gcc_ver"
103 echo "Flags: $CFLAGS_BAREMETAL"
104 make CC=$GCC_CC AR=$GCC_AR CFLAGS="$CFLAGS" lib -j > /dev/null
105
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200106 if [ $check -ne 0 ]; then
107 return
108 fi
109
Hanno Becker43fa8d62019-03-18 17:12:05 +0000110 ROM_OUT_FILE="rom_files__${date}__${NAME}__gcc_${gcc_ver}"
111 ROM_OUT_SYMS="rom_syms__${date}__${NAME}__gcc_${gcc_ver}"
112 echo "Generate file statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100113 ./scripts/extract_codesize_stats.sh --info "gcc_${gcc_ver}" --name $NAME --files > $ROM_OUT_FILE
Hanno Becker43fa8d62019-03-18 17:12:05 +0000114 echo "Generate symbol statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100115 ./scripts/extract_codesize_stats.sh --info "gcc_${gcc_ver}" --name $NAME --syms > $ROM_OUT_SYMS
Hanno Becker43fa8d62019-03-18 17:12:05 +0000116
Manuel Pégourié-Gonnard15be0ee2019-09-20 10:25:29 +0200117 print_rom_report
Hanno Becker43fa8d62019-03-18 17:12:05 +0000118}
119
120baremetal_build_armc5()
121{
122 echo "Cleanup..."
123 make clean
124
125 echo "Create 32-bit library-only baremetal build (ARMC5, Config: $BAREMETAL_CONFIG)"
126 armc5_ver=$($ARMC5_CC | sed -n 's/.*ARM Compiler \([^ ]*\)$/\1/p')
127
Hanno Becker0a4c78f2019-07-25 14:55:47 +0100128 if [ $debug -eq 0 ]; then
129 OPTIM_CFLAGS_ARMC5="-Ospace"
130 else
131 OPTIM_CFLAGS_ARMC5="-g"
132 fi
133
134 CFLAGS_BAREMETAL="$OPTIM_CFLAGS_ARMC5 --thumb --cpu Cortex-m0plus"
Andrzej Kurek3e80b1a2020-12-07 07:01:22 -0500135 CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG -DENABLE_TESTS"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000136 WARNING_CFLAGS="--strict --c99"
137
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200138 if [ $check -ne 0 ]; then
139 WARNING_CFLAGS="$WARNING_CFLAGS --diag_error=warning"
140 fi
141
Hanno Becker43fa8d62019-03-18 17:12:05 +0000142 echo "ARMC5 version: $armc5_ver"
143 echo "Flags: $WARNING_CFLAGS $CFLAGS_BAREMETAL"
144 make WARNING_CFLAGS="$WARNING_CFLAGS" CC=$ARMC5_CC AR=$ARMC5_AR CFLAGS="$CFLAGS" lib -j > /dev/null
145
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200146 if [ $check -ne 0 ]; then
147 return
148 fi
149
Hanno Becker43fa8d62019-03-18 17:12:05 +0000150 ROM_OUT_FILE="rom_files__${date}__${NAME}__armc5_${armc5_ver}"
151 ROM_OUT_SYMS="rom_syms__${date}__${NAME}__armc5_${armc5_ver}"
152 echo "Generate file statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100153 ./scripts/extract_codesize_stats.sh --info "armc5_${armc5_ver}" --name $NAME --files > $ROM_OUT_FILE
Hanno Becker43fa8d62019-03-18 17:12:05 +0000154 echo "Generate symbol statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100155 ./scripts/extract_codesize_stats.sh --info "armc5_${armc5_ver}" --name $NAME --syms > $ROM_OUT_SYMS
Hanno Becker43fa8d62019-03-18 17:12:05 +0000156
Manuel Pégourié-Gonnard15be0ee2019-09-20 10:25:29 +0200157 print_rom_report
Hanno Becker43fa8d62019-03-18 17:12:05 +0000158}
159
160baremetal_build_armc6()
161{
162 echo "Cleanup..."
163 make clean
164
165 echo "Create 32-bit library-only baremetal build (ARMC6, Config: $BAREMETAL_CONFIG)"
166 armc6_ver=$($ARMC6_CC --version | sed -n 's/.*ARM Compiler \([^ ]*\)$/\1/p')
167
Hanno Becker0a4c78f2019-07-25 14:55:47 +0100168 if [ $debug -eq 0 ]; then
169 OPTIM_CFLAGS_ARMC6="-Oz"
170 else
171 OPTIM_CFLAGS_ARMC6="-g"
172 fi
173
174 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 +0200175 if [ $check -ne 0 ]; then
176 CFLAGS_BAREMETAL="$CFLAGS_BAREMETAL -Werror"
177 fi
Andrzej Kurek3e80b1a2020-12-07 07:01:22 -0500178 CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG -DENABLE_TESTS"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000179
180 echo "ARMC6 version: $armc6_ver"
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200181 echo "Flags: $CFLAGS_BAREMETAL"
182 make CC=$ARMC6_CC AR=$ARMC6_AR CFLAGS="$CFLAGS" lib -j > /dev/null
183
184 if [ $check -ne 0 ]; then
185 return
186 fi
Hanno Becker43fa8d62019-03-18 17:12:05 +0000187
188 ROM_OUT_FILE="rom_files__${date}__${NAME}__armc6_${armc6_ver}"
189 ROM_OUT_SYMS="rom_syms__${date}__${NAME}__armc6_${armc6_ver}"
190 echo "Generate file statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100191 ./scripts/extract_codesize_stats.sh --info "armc6_${armc6_ver}" --name $NAME --files > $ROM_OUT_FILE
Hanno Becker43fa8d62019-03-18 17:12:05 +0000192 echo "Generate symbol statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100193 ./scripts/extract_codesize_stats.sh --info "armc6_${armc6_ver}" --name $NAME --syms > $ROM_OUT_SYMS
Hanno Becker43fa8d62019-03-18 17:12:05 +0000194
Manuel Pégourié-Gonnard15be0ee2019-09-20 10:25:29 +0200195 print_rom_report
Hanno Becker43fa8d62019-03-18 17:12:05 +0000196}
197
198# 32-bit host-build of library, tests and example programs,
199# + heap usage measurements.
200baremetal_ram_build() {
Hanno Beckerc7c20812019-04-03 11:55:57 +0100201 : ${BASE_CFLAGS:="-g -m32 -fstack-usage"}
Hanno Becker43fa8d62019-03-18 17:12:05 +0000202 echo "Create 32-bit host-build (Config: $BAREMETAL_CONFIG + $BAREMETAL_USER_CONFIG)"
203
204 echo "Cleanup..."
205 make clean
206
Andrzej Kurek3e80b1a2020-12-07 07:01:22 -0500207 CFLAGS="$BASE_CFLAGS $CFLAGS_CONFIG $CFLAGS_USER_CONFIG -DENABLE_TESTS"
Manuel Pégourié-Gonnardd64a2f72019-07-30 14:54:50 +0200208 if [ "$build_only" -eq 1 ]; then
209 CFLAGS="$CFLAGS -Werror"
210 fi
Hanno Becker43fa8d62019-03-18 17:12:05 +0000211
212 echo "Modifications: $BAREMETAL_USER_CONFIG"
213 cat $BAREMETAL_USER_CONFIG | grep "^#define" | awk '{print "* " $0 }'
214
215 echo "Build (flags: $CFLAGS)..."
216 make CFLAGS="$CFLAGS" -j > /dev/null
217 echo ""
218}
219
Hanno Becker5541e4e2019-04-03 11:31:43 +0100220# usage:
221# - `baremetal_ram_heap 0` for heap usage only
222# - `baremetal_ram_heap 1` for heap and stack usage
Hanno Becker43fa8d62019-03-18 17:12:05 +0000223baremetal_ram_heap() {
224
225 : ${CLI:=./programs/ssl/ssl_client2}
Hanno Becker4ce06042019-04-30 14:18:25 +0100226 : ${CLI_PARAMS:="dtls=1 cid=1 cid_val=beef"}
Hanno Becker43fa8d62019-03-18 17:12:05 +0000227 : ${SRV:=./programs/ssl/ssl_server2}
Hanno Becker3b876ac2019-06-21 15:51:19 +0100228 : ${SRV_PARAMS:="dtls=1 cid=1 cid_val=dead"} # renegotiation=1 auth_mode=required implicit
229 # compile-time hardcoding of configuration
Hanno Becker43fa8d62019-03-18 17:12:05 +0000230 : ${VALGRIND:=valgrind}
231 : ${VALGRIND_MASSIF_PARAMS="--time-unit=B --threshold=0.01 --detailed-freq=1"}
232
233 if [ $1 -eq 1 ]; then
234 RAM_HEAP_OUT="ram_heap_stack__${date}__$NAME"
235 VALGRIND_MASSIF_PARAMS="--stacks=yes $VALGRIND_MASSIF_PARAMS"
236 else
237 RAM_HEAP_OUT="ram_heap__${date}__$NAME"
238 fi
239
240 SRV_CMD="$SRV server_addr=127.0.0.1 server_port=4433 debug_level=4 $SRV_PARAMS"
241 CLI_CMD="$CLI server_addr=127.0.0.1 server_port=4433 $CLI_PARAMS"
242
243 # Piece together valgrind cmd line
244 VALGRIND_BASE="$VALGRIND --tool=massif $VALGRIND_MASSIF_PARAMS"
245
246 FUNC_IGNORE=""
Hanno Becker43fa8d62019-03-18 17:12:05 +0000247 FUNC_IGNORE="__fopen_internal $FUNC_IGNORE"
248 FUNC_IGNORE="_IO_file_doallocate $FUNC_IGNORE"
249 FUNC_IGNORE="strdup $FUNC_IGNORE"
250 FUNC_IGNORE="__tzstring_len $FUNC_IGNORE"
251 FUNC_IGNORE="__tzfile_read $FUNC_IGNORE"
252
253 VALGRIND_IGNORE=""
254 for func in $FUNC_IGNORE; do
255 echo "* Valgrind ignore: $func"
256 VALGRIND_IGNORE="--ignore-fn=$func $VALGRIND_IGNORE"
257 done
258
259 VALGRIND_CMD="$VALGRIND_BASE $VALGRIND_IGNORE --massif-out-file=${RAM_HEAP_OUT} -- $CLI_CMD"
260
261 $SRV_CMD > /dev/null 2>&1 &
262 SRV_PID=$!
263 echo "Server started, PID $SRV_PID"
264
265 $VALGRIND_CMD > /dev/null 2>&1 &
266 VAL_PID=$!
267 echo "Valgrind massif started, PID $VAL_PID"
268
269 wait $VAL_PID
270 echo "Valgrind done, killing server"
271 kill $SRV_PID
272 echo "Done"
273
274 if `cat $RAM_HEAP_OUT | grep '???'` >/dev/null 2>&1; then
275 echo "Warning: Unrecognized symbols in massif output file - does your version of `valgrind` support 32-bit builds?"
276 fi
277
278 printf "Max heap usage: "
279 ./scripts/massif_max.pl $RAM_HEAP_OUT
280 echo "SUCCESS - Heap usage statistics written to: $RAM_HEAP_OUT\n"
281}
282
283baremetal_ram_stack() {
284 : ${CLI:=./programs/ssl/ssl_client2}
285 : ${CLI_PARAMS:="dtls=1"}
286 : ${SRV:=./programs/ssl/ssl_server2}
Hanno Becker3b876ac2019-06-21 15:51:19 +0100287 : ${SRV_PARAMS:="dtls=1"} # renegotiation=1 auth_mode=required implicit
288 # compile-time hardcoding of configuration
Hanno Becker43fa8d62019-03-18 17:12:05 +0000289 : ${VALGRIND:=valgrind}
290 : ${VALGRIND_CALLGRIND_PARAMS:="--separate-callers=100"}
291
Hanno Beckerc7c20812019-04-03 11:55:57 +0100292 RAM_CALLGRIND_OUT="ram_callgrind__${date}__$NAME"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000293 RAM_STACK_OUT="ram_stack__${date}__$NAME"
294
295 SRV_CMD="$SRV server_addr=127.0.0.1 server_port=4433 debug_level=4 $SRV_PARAMS"
296 CLI_CMD="$CLI server_addr=127.0.0.1 server_port=4433 $CLI_PARAMS"
297
298 VALGRIND_BASE="$VALGRIND --tool=callgrind $VALGRIND_CALLGRIND_PARAMS"
Hanno Beckerc7c20812019-04-03 11:55:57 +0100299 VALGRIND_CMD="$VALGRIND_BASE --callgrind-out-file=${RAM_CALLGRIND_OUT} $CLI_CMD"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000300
301 $SRV_CMD > /dev/null 2>&1 &
302 SRV_PID=$!
303 echo "Server started, PID $SRV_PID"
304
305 $VALGRIND_CMD > /dev/null 2>&1 &
306 VAL_PID=$!
307 echo "Valgrind callgrind started, PID $VAL_PID"
308
309 wait $VAL_PID
310 echo "Valgrind done, killing server"
311 kill $SRV_PID
312 echo "Done"
313
Hanno Becker13737242019-04-03 12:17:20 +0100314 # Extract callgraphs from source files directly
Hanno Becker7f6e8082019-04-03 13:48:09 +0100315 RAM_CALLGRAPH_OUT=""
Hanno Becker13737242019-04-03 12:17:20 +0100316 if [ -x "$(command -v cflow)" ]; then
317 RAM_CALLGRAPH_OUT="ram_cflow__${date}__$NAME"
318 cflow library/*.c > $RAM_CALLGRAPH_OUT 2> /dev/null
319 fi
320
Hanno Beckerc7c20812019-04-03 11:55:57 +0100321 # Merge stack usage files
322 cat library/*.su > ${RAM_STACK_OUT}_unsorted
323 sort -r -k2 -n ${RAM_STACK_OUT}_unsorted > $RAM_STACK_OUT
324 rm ${RAM_STACK_OUT}_unsorted
325
Hanno Becker13737242019-04-03 12:17:20 +0100326 echo "SUCCESS"
327 echo "* Stack usage statistics written to $RAM_STACK_OUT"
328 echo "* Callgrind output written to $RAM_CALLGRIND_OUT"
329 if [ -n $RAM_CALLGRAPH_OUT ]; then
330 echo "* Static call graph written to $RAM_CALLGRAPH_OUT"
331 fi
Hanno Becker43fa8d62019-03-18 17:12:05 +0000332}
333
334show_usage() {
Hanno Beckera1f3c522019-07-22 12:37:21 +0100335 echo "Usage: $0 [--rom [--check] [--gcc] [--armc5] [--armc6]|--ram [--build-only] [--stack] [--heap]]"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000336}
337
338test_build=0
339raw_build=0
340
341build_gcc=0
342build_armc5=0
343build_armc6=0
344
345measure_heap=0
346measure_stack=0
347
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200348check=0
Manuel Pégourié-Gonnardd64a2f72019-07-30 14:54:50 +0200349build_only=0
Hanno Becker0a4c78f2019-07-25 14:55:47 +0100350debug=0
351
Hanno Becker43fa8d62019-03-18 17:12:05 +0000352while [ $# -gt 0 ]; do
353 case "$1" in
354 --gcc) build_gcc=1;;
355 --armc5) build_armc5=1;;
356 --armc6) build_armc6=1;;
357 --ram) test_build=1;;
358 --rom) raw_build=1;;
Hanno Beckera1f3c522019-07-22 12:37:21 +0100359 --build-only) build_only=1;;
Hanno Becker43fa8d62019-03-18 17:12:05 +0000360 --heap) measure_heap=1;;
361 --stack) measure_stack=1;;
Manuel Pégourié-Gonnard070f1072019-06-18 11:17:17 +0200362 --check) check=1;;
Hanno Becker0a4c78f2019-07-25 14:55:47 +0100363 --debug) debug=1;;
Hanno Becker43fa8d62019-03-18 17:12:05 +0000364 -*)
365 echo >&2 "Unknown option: $1"
366 show_usage
367 exit 1
368 ;;
369 esac
370 shift
371done
372
373if [ "$test_build" -eq 0 ] &&
374 [ "$raw_build" -eq 0 ]; then
375 echo "Need to set either --ram or --rom"
376 show_usage
377 exit 1
378fi
379
380if [ "$test_build" -eq 1 ]; then
381
382 if [ "$measure_heap" -eq 0 ] &&
Hanno Beckera1f3c522019-07-22 12:37:21 +0100383 [ "$measure_stack" -eq 0 ] &&
384 [ "$build_only" -eq 0 ]; then
385 echo "Need to set either --build-only, --heap or --stack with --ram"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000386 show_usage
387 exit 1
388 fi
389
390 baremetal_ram_build
391
392 if [ "$measure_heap" -eq 1 ]; then
393 baremetal_ram_heap 0
394 baremetal_ram_heap 1
395 fi
396
397 if [ "$measure_stack" -eq 1 ]; then
398 baremetal_ram_stack
399 fi
400
401fi
402
403if [ "$raw_build" -eq 1 ]; then
404
405 if [ "$build_gcc" -eq 0 ] &&
406 [ "$build_armc5" -eq 0 ] &&
407 [ "$build_armc6" -eq 0 ]; then
408 echo "Need to set either --gcc, --armc5 or --armc6 with --rom"
409 show_usage
410 exit 1
411 fi
412
413 if [ "$build_gcc" -eq 1 ]; then
414 baremetal_build_gcc
415 fi
416 if [ "$build_armc5" -eq 1 ]; then
417 baremetal_build_armc5
418 fi
419 if [ "$build_armc6" -eq 1 ]; then
420 baremetal_build_armc6
421 fi
422fi