blob: 4b798b9df37e33e1636f3b02a12c58b996318771 [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
70baremetal_build_gcc()
71{
72 echo "Cleanup..."
73 make clean
74
75 echo "Create 32-bit library-only baremetal build (GCC, config: $BAREMETAL_CONFIG)"
76 gcc_ver=$($GCC_CC --version | head -n 1 | sed -n 's/^.*\([0-9]\.[0-9]\.[0-9]\).*$/\1/p')
77
78 CFLAGS_BAREMETAL="-Os -mthumb -mcpu=cortex-m0plus"
79 CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG"
80
81 $GCC_CC --version
82
83 echo "GCC version: $gcc_ver"
84 echo "Flags: $CFLAGS_BAREMETAL"
85 make CC=$GCC_CC AR=$GCC_AR CFLAGS="$CFLAGS" lib -j > /dev/null
86
87 ROM_OUT_FILE="rom_files__${date}__${NAME}__gcc_${gcc_ver}"
88 ROM_OUT_SYMS="rom_syms__${date}__${NAME}__gcc_${gcc_ver}"
89 echo "Generate file statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +010090 ./scripts/extract_codesize_stats.sh --info "gcc_${gcc_ver}" --name $NAME --files > $ROM_OUT_FILE
Hanno Becker43fa8d62019-03-18 17:12:05 +000091 echo "Generate symbol statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +010092 ./scripts/extract_codesize_stats.sh --info "gcc_${gcc_ver}" --name $NAME --syms > $ROM_OUT_SYMS
Hanno Becker43fa8d62019-03-18 17:12:05 +000093
94 echo "ROM statistics written to:"
95 echo "* $ROM_OUT_FILE"
96 echo "* $ROM_OUT_SYMS"
Hanno Becker7cc9ca82019-06-07 10:39:34 +010097
98 # Print summary
99 cat $ROM_OUT_FILE | grep "libmbedtls.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
100 cat $ROM_OUT_FILE | grep "libmbedcrypto.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
101 cat $ROM_OUT_FILE | grep "libmbedx509.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
Hanno Becker43fa8d62019-03-18 17:12:05 +0000102}
103
104baremetal_build_armc5()
105{
106 echo "Cleanup..."
107 make clean
108
109 echo "Create 32-bit library-only baremetal build (ARMC5, Config: $BAREMETAL_CONFIG)"
110 armc5_ver=$($ARMC5_CC | sed -n 's/.*ARM Compiler \([^ ]*\)$/\1/p')
111
112 CFLAGS_BAREMETAL="-Ospace --thumb --cpu Cortex-m0plus"
113 CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG"
114 WARNING_CFLAGS="--strict --c99"
115
116 echo "ARMC5 version: $armc5_ver"
117 echo "Flags: $WARNING_CFLAGS $CFLAGS_BAREMETAL"
118 make WARNING_CFLAGS="$WARNING_CFLAGS" CC=$ARMC5_CC AR=$ARMC5_AR CFLAGS="$CFLAGS" lib -j > /dev/null
119
120 ROM_OUT_FILE="rom_files__${date}__${NAME}__armc5_${armc5_ver}"
121 ROM_OUT_SYMS="rom_syms__${date}__${NAME}__armc5_${armc5_ver}"
122 echo "Generate file statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100123 ./scripts/extract_codesize_stats.sh --info "armc5_${armc5_ver}" --name $NAME --files > $ROM_OUT_FILE
Hanno Becker43fa8d62019-03-18 17:12:05 +0000124 echo "Generate symbol statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100125 ./scripts/extract_codesize_stats.sh --info "armc5_${armc5_ver}" --name $NAME --syms > $ROM_OUT_SYMS
Hanno Becker43fa8d62019-03-18 17:12:05 +0000126
127 echo "ROM statistics written to:"
128 echo "* $ROM_OUT_FILE"
129 echo "* $ROM_OUT_SYMS"
Hanno Becker7cc9ca82019-06-07 10:39:34 +0100130
131 # Print summary
132 cat $ROM_OUT_FILE | grep "libmbedtls.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
133 cat $ROM_OUT_FILE | grep "libmbedcrypto.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
134 cat $ROM_OUT_FILE | grep "libmbedx509.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
Hanno Becker43fa8d62019-03-18 17:12:05 +0000135}
136
137baremetal_build_armc6()
138{
139 echo "Cleanup..."
140 make clean
141
142 echo "Create 32-bit library-only baremetal build (ARMC6, Config: $BAREMETAL_CONFIG)"
143 armc6_ver=$($ARMC6_CC --version | sed -n 's/.*ARM Compiler \([^ ]*\)$/\1/p')
144
145 CFLAGS_BAREMETAL="-Os --target=arm-arm-none-eabi -mthumb -mcpu=cortex-m0plus"
146 CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG"
147 WARNING_CFLAGS="-xc -std=c99"
148
149 echo "ARMC6 version: $armc6_ver"
150 echo "Flags: $WARNING_CFLAGS $CFLAGS_BAREMETAL"
151 make WARNING_CFLAGS="$WARNING_CFLAGS" CC=$ARMC6_CC AR=$ARMC6_AR CFLAGS="$CFLAGS" lib -j > /dev/null
152
153 ROM_OUT_FILE="rom_files__${date}__${NAME}__armc6_${armc6_ver}"
154 ROM_OUT_SYMS="rom_syms__${date}__${NAME}__armc6_${armc6_ver}"
155 echo "Generate file statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100156 ./scripts/extract_codesize_stats.sh --info "armc6_${armc6_ver}" --name $NAME --files > $ROM_OUT_FILE
Hanno Becker43fa8d62019-03-18 17:12:05 +0000157 echo "Generate symbol statistics..."
Hanno Beckerb4d8fab2019-04-03 13:41:28 +0100158 ./scripts/extract_codesize_stats.sh --info "armc6_${armc6_ver}" --name $NAME --syms > $ROM_OUT_SYMS
Hanno Becker43fa8d62019-03-18 17:12:05 +0000159
160 echo "ROM statistics written to:"
161 echo "* $ROM_OUT_FILE"
162 echo "* $ROM_OUT_SYMS"
Hanno Becker7cc9ca82019-06-07 10:39:34 +0100163
164 # Print summary
165 cat $ROM_OUT_FILE | grep "libmbedtls.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
166 cat $ROM_OUT_FILE | grep "libmbedcrypto.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
167 cat $ROM_OUT_FILE | grep "libmbedx509.a" | awk '{printf( "%15s: %s Bytes\n", $4, $5)}'
Hanno Becker43fa8d62019-03-18 17:12:05 +0000168}
169
170# 32-bit host-build of library, tests and example programs,
171# + heap usage measurements.
172baremetal_ram_build() {
Hanno Beckerc7c20812019-04-03 11:55:57 +0100173 : ${BASE_CFLAGS:="-g -m32 -fstack-usage"}
Hanno Becker43fa8d62019-03-18 17:12:05 +0000174 echo "Create 32-bit host-build (Config: $BAREMETAL_CONFIG + $BAREMETAL_USER_CONFIG)"
175
176 echo "Cleanup..."
177 make clean
178
179 CFLAGS="$BASE_CFLAGS $CFLAGS_CONFIG $CFLAGS_USER_CONFIG"
180
181 echo "Modifications: $BAREMETAL_USER_CONFIG"
182 cat $BAREMETAL_USER_CONFIG | grep "^#define" | awk '{print "* " $0 }'
183
184 echo "Build (flags: $CFLAGS)..."
185 make CFLAGS="$CFLAGS" -j > /dev/null
186 echo ""
187}
188
Hanno Becker5541e4e2019-04-03 11:31:43 +0100189# usage:
190# - `baremetal_ram_heap 0` for heap usage only
191# - `baremetal_ram_heap 1` for heap and stack usage
Hanno Becker43fa8d62019-03-18 17:12:05 +0000192baremetal_ram_heap() {
193
194 : ${CLI:=./programs/ssl/ssl_client2}
Hanno Becker4ce06042019-04-30 14:18:25 +0100195 : ${CLI_PARAMS:="dtls=1 cid=1 cid_val=beef"}
Hanno Becker43fa8d62019-03-18 17:12:05 +0000196 : ${SRV:=./programs/ssl/ssl_server2}
Hanno Becker4ce06042019-04-30 14:18:25 +0100197 : ${SRV_PARAMS:="dtls=1 renegotiation=1 auth_mode=required cid=1 cid_val=dead"}
Hanno Becker43fa8d62019-03-18 17:12:05 +0000198 : ${VALGRIND:=valgrind}
199 : ${VALGRIND_MASSIF_PARAMS="--time-unit=B --threshold=0.01 --detailed-freq=1"}
200
201 if [ $1 -eq 1 ]; then
202 RAM_HEAP_OUT="ram_heap_stack__${date}__$NAME"
203 VALGRIND_MASSIF_PARAMS="--stacks=yes $VALGRIND_MASSIF_PARAMS"
204 else
205 RAM_HEAP_OUT="ram_heap__${date}__$NAME"
206 fi
207
208 SRV_CMD="$SRV server_addr=127.0.0.1 server_port=4433 debug_level=4 $SRV_PARAMS"
209 CLI_CMD="$CLI server_addr=127.0.0.1 server_port=4433 $CLI_PARAMS"
210
211 # Piece together valgrind cmd line
212 VALGRIND_BASE="$VALGRIND --tool=massif $VALGRIND_MASSIF_PARAMS"
213
214 FUNC_IGNORE=""
Hanno Becker43fa8d62019-03-18 17:12:05 +0000215 FUNC_IGNORE="__fopen_internal $FUNC_IGNORE"
216 FUNC_IGNORE="_IO_file_doallocate $FUNC_IGNORE"
217 FUNC_IGNORE="strdup $FUNC_IGNORE"
218 FUNC_IGNORE="__tzstring_len $FUNC_IGNORE"
219 FUNC_IGNORE="__tzfile_read $FUNC_IGNORE"
220
221 VALGRIND_IGNORE=""
222 for func in $FUNC_IGNORE; do
223 echo "* Valgrind ignore: $func"
224 VALGRIND_IGNORE="--ignore-fn=$func $VALGRIND_IGNORE"
225 done
226
227 VALGRIND_CMD="$VALGRIND_BASE $VALGRIND_IGNORE --massif-out-file=${RAM_HEAP_OUT} -- $CLI_CMD"
228
229 $SRV_CMD > /dev/null 2>&1 &
230 SRV_PID=$!
231 echo "Server started, PID $SRV_PID"
232
233 $VALGRIND_CMD > /dev/null 2>&1 &
234 VAL_PID=$!
235 echo "Valgrind massif started, PID $VAL_PID"
236
237 wait $VAL_PID
238 echo "Valgrind done, killing server"
239 kill $SRV_PID
240 echo "Done"
241
242 if `cat $RAM_HEAP_OUT | grep '???'` >/dev/null 2>&1; then
243 echo "Warning: Unrecognized symbols in massif output file - does your version of `valgrind` support 32-bit builds?"
244 fi
245
246 printf "Max heap usage: "
247 ./scripts/massif_max.pl $RAM_HEAP_OUT
248 echo "SUCCESS - Heap usage statistics written to: $RAM_HEAP_OUT\n"
249}
250
251baremetal_ram_stack() {
252 : ${CLI:=./programs/ssl/ssl_client2}
253 : ${CLI_PARAMS:="dtls=1"}
254 : ${SRV:=./programs/ssl/ssl_server2}
255 : ${SRV_PARAMS:="dtls=1 renegotiation=1 auth_mode=required"}
256 : ${VALGRIND:=valgrind}
257 : ${VALGRIND_CALLGRIND_PARAMS:="--separate-callers=100"}
258
Hanno Beckerc7c20812019-04-03 11:55:57 +0100259 RAM_CALLGRIND_OUT="ram_callgrind__${date}__$NAME"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000260 RAM_STACK_OUT="ram_stack__${date}__$NAME"
261
262 SRV_CMD="$SRV server_addr=127.0.0.1 server_port=4433 debug_level=4 $SRV_PARAMS"
263 CLI_CMD="$CLI server_addr=127.0.0.1 server_port=4433 $CLI_PARAMS"
264
265 VALGRIND_BASE="$VALGRIND --tool=callgrind $VALGRIND_CALLGRIND_PARAMS"
Hanno Beckerc7c20812019-04-03 11:55:57 +0100266 VALGRIND_CMD="$VALGRIND_BASE --callgrind-out-file=${RAM_CALLGRIND_OUT} $CLI_CMD"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000267
268 $SRV_CMD > /dev/null 2>&1 &
269 SRV_PID=$!
270 echo "Server started, PID $SRV_PID"
271
272 $VALGRIND_CMD > /dev/null 2>&1 &
273 VAL_PID=$!
274 echo "Valgrind callgrind started, PID $VAL_PID"
275
276 wait $VAL_PID
277 echo "Valgrind done, killing server"
278 kill $SRV_PID
279 echo "Done"
280
Hanno Becker13737242019-04-03 12:17:20 +0100281 # Extract callgraphs from source files directly
Hanno Becker7f6e8082019-04-03 13:48:09 +0100282 RAM_CALLGRAPH_OUT=""
Hanno Becker13737242019-04-03 12:17:20 +0100283 if [ -x "$(command -v cflow)" ]; then
284 RAM_CALLGRAPH_OUT="ram_cflow__${date}__$NAME"
285 cflow library/*.c > $RAM_CALLGRAPH_OUT 2> /dev/null
286 fi
287
Hanno Beckerc7c20812019-04-03 11:55:57 +0100288 # Merge stack usage files
289 cat library/*.su > ${RAM_STACK_OUT}_unsorted
290 sort -r -k2 -n ${RAM_STACK_OUT}_unsorted > $RAM_STACK_OUT
291 rm ${RAM_STACK_OUT}_unsorted
292
Hanno Becker13737242019-04-03 12:17:20 +0100293 echo "SUCCESS"
294 echo "* Stack usage statistics written to $RAM_STACK_OUT"
295 echo "* Callgrind output written to $RAM_CALLGRIND_OUT"
296 if [ -n $RAM_CALLGRAPH_OUT ]; then
297 echo "* Static call graph written to $RAM_CALLGRAPH_OUT"
298 fi
Hanno Becker43fa8d62019-03-18 17:12:05 +0000299}
300
301show_usage() {
Hanno Becker7a097852019-04-03 11:55:40 +0100302 echo "Usage: $0 [--rom [--gcc] [--armc5] [--armc6]|--ram [--stack] [--heap]]"
Hanno Becker43fa8d62019-03-18 17:12:05 +0000303}
304
305test_build=0
306raw_build=0
307
308build_gcc=0
309build_armc5=0
310build_armc6=0
311
312measure_heap=0
313measure_stack=0
314
315while [ $# -gt 0 ]; do
316 case "$1" in
317 --gcc) build_gcc=1;;
318 --armc5) build_armc5=1;;
319 --armc6) build_armc6=1;;
320 --ram) test_build=1;;
321 --rom) raw_build=1;;
322 --heap) measure_heap=1;;
323 --stack) measure_stack=1;;
324 -*)
325 echo >&2 "Unknown option: $1"
326 show_usage
327 exit 1
328 ;;
329 esac
330 shift
331done
332
333if [ "$test_build" -eq 0 ] &&
334 [ "$raw_build" -eq 0 ]; then
335 echo "Need to set either --ram or --rom"
336 show_usage
337 exit 1
338fi
339
340if [ "$test_build" -eq 1 ]; then
341
342 if [ "$measure_heap" -eq 0 ] &&
343 [ "$measure_stack" -eq 0 ]; then
344 echo "Need to set either --heap or --stack with --ram"
345 show_usage
346 exit 1
347 fi
348
349 baremetal_ram_build
350
351 if [ "$measure_heap" -eq 1 ]; then
352 baremetal_ram_heap 0
353 baremetal_ram_heap 1
354 fi
355
356 if [ "$measure_stack" -eq 1 ]; then
357 baremetal_ram_stack
358 fi
359
360fi
361
362if [ "$raw_build" -eq 1 ]; then
363
364 if [ "$build_gcc" -eq 0 ] &&
365 [ "$build_armc5" -eq 0 ] &&
366 [ "$build_armc6" -eq 0 ]; then
367 echo "Need to set either --gcc, --armc5 or --armc6 with --rom"
368 show_usage
369 exit 1
370 fi
371
372 if [ "$build_gcc" -eq 1 ]; then
373 baremetal_build_gcc
374 fi
375 if [ "$build_armc5" -eq 1 ]; then
376 baremetal_build_armc5
377 fi
378 if [ "$build_armc6" -eq 1 ]; then
379 baremetal_build_armc6
380 fi
381fi