
Only effective together with --rom, makes two changes: - abort in case of build warnings - skip writing statistics The goal is to make sure we build cleanly in the configuration used for measuring code size, with all the compilers we use, both because we care about that configuration and those compilers, and because any warnings would cast a shadow on the code size measurements. Currently the build fails with armc5 due to a pre-existing warning in PK, this will be fixed in the next commit. The next commit will also add an all.sh component to make sure we have no regression in the future. (Which is the motivation for --check skipping statistics: an all.sh component should probably not leave files around.) While at it, fix two things: 1. The call to gcc --version was redundant with the echo line below 2. WARNING_CFLAGS shouldn't be overriden with armclang, as it would remove the -Wall -Wextra and any directory-specific warning (such as -Wdeclaration-after-statement in library). It's meant to be overriden only with compilers that don't accept the default value (namely armc5 here).
388 lines
12 KiB
Bash
Executable file
388 lines
12 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
# baremetal.sh
|
|
#
|
|
# This file is part of mbed TLS (https://tls.mbed.org)
|
|
#
|
|
# Copyright (c) 2019, ARM Limited, All Rights Reserved
|
|
#
|
|
# Purpose
|
|
#
|
|
# * Create a baremetal library-only build (omitting the tests and
|
|
# example programs, which have stronger configuration requirements)
|
|
# for a Cortex-M target in a minimal configuration, and generate
|
|
# code-size statistics.
|
|
# By default, the script uses configs/baremetal.h and targets Cortex-M0+,
|
|
# and outputs the code-size statistics as `rom.COMMIT_HASH`.
|
|
#
|
|
# * Create a 32-bit host-build of library, tests and example programs
|
|
# in a 'baremetal' base configuration minimally modified to allow
|
|
# running tests and example programs, and obtain heap usage statistics
|
|
# of a test run of ssl_client2 and ssl_server2. This can be used as
|
|
# an estimate for heap usage of 32-bit baremetal applications using Mbed TLS.
|
|
#
|
|
# By default, the script uses configs/baremetal.h as the base configuration
|
|
# modified by configs/baremetal_test.h, and emits the heap usage statistics
|
|
# as `massif.COMMIT_HASH`.
|
|
#
|
|
|
|
set -eu
|
|
|
|
if [ -d include/mbedtls ]; then :; else
|
|
echo "$0: must be run from root" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if grep -i cmake Makefile >/dev/null; then
|
|
echo "$0: not compatible with cmake" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# The 'baremetal' configuration to test
|
|
: ${BAREMETAL_CONFIG:=./configs/baremetal.h}
|
|
CFLAGS_CONFIG="-DMBEDTLS_CONFIG_FILE='\"../$BAREMETAL_CONFIG\"'"
|
|
|
|
# The modifications to the 'baremetal' configuration which allows
|
|
# tests and example programs to build and execute.
|
|
: ${BAREMETAL_USER_CONFIG:=./configs/baremetal_test.h}
|
|
CFLAGS_USER_CONFIG="-DMBEDTLS_USER_CONFIG_FILE='\"../$BAREMETAL_USER_CONFIG\"'"
|
|
|
|
: ${ARMC5_BIN_DIR:=""}
|
|
: ${ARMC6_BIN_DIR:=""}
|
|
if [ -n "$ARMC5_BIN_DIR" ]; then
|
|
ARMC5_BIN_DIR="$ARMC5_BIN_DIR/"
|
|
fi
|
|
|
|
if [ -n "$ARMC6_BIN_DIR" ]; then
|
|
ARMC6_BIN_DIR="$ARMC6_BIN_DIR/"
|
|
fi
|
|
|
|
: ${NAME:=$(git rev-parse HEAD)}
|
|
: ${GCC_CC:=arm-none-eabi-gcc}
|
|
: ${GCC_AR:=arm-none-eabi-ar}
|
|
: ${ARMC6_CC:="${ARMC6_BIN_DIR}armclang"}
|
|
: ${ARMC6_AR:="${ARMC6_BIN_DIR}armar"}
|
|
: ${ARMC5_CC:="${ARMC5_BIN_DIR}armcc"}
|
|
: ${ARMC5_AR:="${ARMC5_BIN_DIR}armar"}
|
|
|
|
date=$( date +%Y-%m-%d-%H-%M-%S )
|
|
|
|
baremetal_build_gcc()
|
|
{
|
|
echo "Cleanup..."
|
|
make clean
|
|
|
|
echo "Create 32-bit library-only baremetal build (GCC, config: $BAREMETAL_CONFIG)"
|
|
gcc_ver=$($GCC_CC --version | head -n 1 | sed -n 's/^.*\([0-9]\.[0-9]\.[0-9]\).*$/\1/p')
|
|
|
|
CFLAGS_BAREMETAL="-Os -mthumb -mcpu=cortex-m0plus --std=c99"
|
|
if [ $check -ne 0 ]; then
|
|
CFLAGS_BAREMETAL="$CFLAGS_BAREMETAL -Werror"
|
|
fi
|
|
CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG"
|
|
|
|
echo "GCC version: $gcc_ver"
|
|
echo "Flags: $CFLAGS_BAREMETAL"
|
|
make CC=$GCC_CC AR=$GCC_AR CFLAGS="$CFLAGS" lib -j > /dev/null
|
|
|
|
if [ $check -ne 0 ]; then
|
|
return
|
|
fi
|
|
|
|
ROM_OUT_FILE="rom_files__${date}__${NAME}__gcc_${gcc_ver}"
|
|
ROM_OUT_SYMS="rom_syms__${date}__${NAME}__gcc_${gcc_ver}"
|
|
echo "Generate file statistics..."
|
|
./scripts/extract_codesize_stats.sh --info "gcc_${gcc_ver}" --name $NAME --files > $ROM_OUT_FILE
|
|
echo "Generate symbol statistics..."
|
|
./scripts/extract_codesize_stats.sh --info "gcc_${gcc_ver}" --name $NAME --syms > $ROM_OUT_SYMS
|
|
|
|
echo "ROM statistics written to:"
|
|
echo "* $ROM_OUT_FILE"
|
|
echo "* $ROM_OUT_SYMS"
|
|
}
|
|
|
|
baremetal_build_armc5()
|
|
{
|
|
echo "Cleanup..."
|
|
make clean
|
|
|
|
echo "Create 32-bit library-only baremetal build (ARMC5, Config: $BAREMETAL_CONFIG)"
|
|
armc5_ver=$($ARMC5_CC | sed -n 's/.*ARM Compiler \([^ ]*\)$/\1/p')
|
|
|
|
CFLAGS_BAREMETAL="-Ospace --thumb --cpu Cortex-m0plus"
|
|
CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG"
|
|
WARNING_CFLAGS="--strict --c99"
|
|
|
|
if [ $check -ne 0 ]; then
|
|
WARNING_CFLAGS="$WARNING_CFLAGS --diag_error=warning"
|
|
fi
|
|
|
|
echo "ARMC5 version: $armc5_ver"
|
|
echo "Flags: $WARNING_CFLAGS $CFLAGS_BAREMETAL"
|
|
make WARNING_CFLAGS="$WARNING_CFLAGS" CC=$ARMC5_CC AR=$ARMC5_AR CFLAGS="$CFLAGS" lib -j > /dev/null
|
|
|
|
if [ $check -ne 0 ]; then
|
|
return
|
|
fi
|
|
|
|
ROM_OUT_FILE="rom_files__${date}__${NAME}__armc5_${armc5_ver}"
|
|
ROM_OUT_SYMS="rom_syms__${date}__${NAME}__armc5_${armc5_ver}"
|
|
echo "Generate file statistics..."
|
|
./scripts/extract_codesize_stats.sh --info "armc5_${armc5_ver}" --name $NAME --files > $ROM_OUT_FILE
|
|
echo "Generate symbol statistics..."
|
|
./scripts/extract_codesize_stats.sh --info "armc5_${armc5_ver}" --name $NAME --syms > $ROM_OUT_SYMS
|
|
|
|
echo "ROM statistics written to:"
|
|
echo "* $ROM_OUT_FILE"
|
|
echo "* $ROM_OUT_SYMS"
|
|
}
|
|
|
|
baremetal_build_armc6()
|
|
{
|
|
echo "Cleanup..."
|
|
make clean
|
|
|
|
echo "Create 32-bit library-only baremetal build (ARMC6, Config: $BAREMETAL_CONFIG)"
|
|
armc6_ver=$($ARMC6_CC --version | sed -n 's/.*ARM Compiler \([^ ]*\)$/\1/p')
|
|
|
|
CFLAGS_BAREMETAL="-Os --target=arm-arm-none-eabi -mthumb -mcpu=cortex-m0plus -xc --std=c99"
|
|
if [ $check -ne 0 ]; then
|
|
CFLAGS_BAREMETAL="$CFLAGS_BAREMETAL -Werror"
|
|
fi
|
|
CFLAGS="$CFLAGS_BAREMETAL $CFLAGS_CONFIG"
|
|
|
|
echo "ARMC6 version: $armc6_ver"
|
|
echo "Flags: $CFLAGS_BAREMETAL"
|
|
make CC=$ARMC6_CC AR=$ARMC6_AR CFLAGS="$CFLAGS" lib -j > /dev/null
|
|
|
|
if [ $check -ne 0 ]; then
|
|
return
|
|
fi
|
|
|
|
ROM_OUT_FILE="rom_files__${date}__${NAME}__armc6_${armc6_ver}"
|
|
ROM_OUT_SYMS="rom_syms__${date}__${NAME}__armc6_${armc6_ver}"
|
|
echo "Generate file statistics..."
|
|
./scripts/extract_codesize_stats.sh --info "armc6_${armc6_ver}" --name $NAME --files > $ROM_OUT_FILE
|
|
echo "Generate symbol statistics..."
|
|
./scripts/extract_codesize_stats.sh --info "armc6_${armc6_ver}" --name $NAME --syms > $ROM_OUT_SYMS
|
|
|
|
echo "ROM statistics written to:"
|
|
echo "* $ROM_OUT_FILE"
|
|
echo "* $ROM_OUT_SYMS"
|
|
}
|
|
|
|
# 32-bit host-build of library, tests and example programs,
|
|
# + heap usage measurements.
|
|
baremetal_ram_build() {
|
|
: ${BASE_CFLAGS:="-g -m32 -fstack-usage"}
|
|
echo "Create 32-bit host-build (Config: $BAREMETAL_CONFIG + $BAREMETAL_USER_CONFIG)"
|
|
|
|
echo "Cleanup..."
|
|
make clean
|
|
|
|
CFLAGS="$BASE_CFLAGS $CFLAGS_CONFIG $CFLAGS_USER_CONFIG"
|
|
|
|
echo "Modifications: $BAREMETAL_USER_CONFIG"
|
|
cat $BAREMETAL_USER_CONFIG | grep "^#define" | awk '{print "* " $0 }'
|
|
|
|
echo "Build (flags: $CFLAGS)..."
|
|
make CFLAGS="$CFLAGS" -j > /dev/null
|
|
echo ""
|
|
}
|
|
|
|
# usage:
|
|
# - `baremetal_ram_heap 0` for heap usage only
|
|
# - `baremetal_ram_heap 1` for heap and stack usage
|
|
baremetal_ram_heap() {
|
|
|
|
: ${CLI:=./programs/ssl/ssl_client2}
|
|
: ${CLI_PARAMS:="dtls=1 cid=1 cid_val=beef"}
|
|
: ${SRV:=./programs/ssl/ssl_server2}
|
|
: ${SRV_PARAMS:="dtls=1 renegotiation=1 auth_mode=required cid=1 cid_val=dead"}
|
|
: ${VALGRIND:=valgrind}
|
|
: ${VALGRIND_MASSIF_PARAMS="--time-unit=B --threshold=0.01 --detailed-freq=1"}
|
|
|
|
if [ $1 -eq 1 ]; then
|
|
RAM_HEAP_OUT="ram_heap_stack__${date}__$NAME"
|
|
VALGRIND_MASSIF_PARAMS="--stacks=yes $VALGRIND_MASSIF_PARAMS"
|
|
else
|
|
RAM_HEAP_OUT="ram_heap__${date}__$NAME"
|
|
fi
|
|
|
|
SRV_CMD="$SRV server_addr=127.0.0.1 server_port=4433 debug_level=4 $SRV_PARAMS"
|
|
CLI_CMD="$CLI server_addr=127.0.0.1 server_port=4433 $CLI_PARAMS"
|
|
|
|
# Piece together valgrind cmd line
|
|
VALGRIND_BASE="$VALGRIND --tool=massif $VALGRIND_MASSIF_PARAMS"
|
|
|
|
FUNC_IGNORE=""
|
|
FUNC_IGNORE="__fopen_internal $FUNC_IGNORE"
|
|
FUNC_IGNORE="_IO_file_doallocate $FUNC_IGNORE"
|
|
FUNC_IGNORE="strdup $FUNC_IGNORE"
|
|
FUNC_IGNORE="__tzstring_len $FUNC_IGNORE"
|
|
FUNC_IGNORE="__tzfile_read $FUNC_IGNORE"
|
|
|
|
VALGRIND_IGNORE=""
|
|
for func in $FUNC_IGNORE; do
|
|
echo "* Valgrind ignore: $func"
|
|
VALGRIND_IGNORE="--ignore-fn=$func $VALGRIND_IGNORE"
|
|
done
|
|
|
|
VALGRIND_CMD="$VALGRIND_BASE $VALGRIND_IGNORE --massif-out-file=${RAM_HEAP_OUT} -- $CLI_CMD"
|
|
|
|
$SRV_CMD > /dev/null 2>&1 &
|
|
SRV_PID=$!
|
|
echo "Server started, PID $SRV_PID"
|
|
|
|
$VALGRIND_CMD > /dev/null 2>&1 &
|
|
VAL_PID=$!
|
|
echo "Valgrind massif started, PID $VAL_PID"
|
|
|
|
wait $VAL_PID
|
|
echo "Valgrind done, killing server"
|
|
kill $SRV_PID
|
|
echo "Done"
|
|
|
|
if `cat $RAM_HEAP_OUT | grep '???'` >/dev/null 2>&1; then
|
|
echo "Warning: Unrecognized symbols in massif output file - does your version of `valgrind` support 32-bit builds?"
|
|
fi
|
|
|
|
printf "Max heap usage: "
|
|
./scripts/massif_max.pl $RAM_HEAP_OUT
|
|
echo "SUCCESS - Heap usage statistics written to: $RAM_HEAP_OUT\n"
|
|
}
|
|
|
|
baremetal_ram_stack() {
|
|
: ${CLI:=./programs/ssl/ssl_client2}
|
|
: ${CLI_PARAMS:="dtls=1"}
|
|
: ${SRV:=./programs/ssl/ssl_server2}
|
|
: ${SRV_PARAMS:="dtls=1 renegotiation=1 auth_mode=required"}
|
|
: ${VALGRIND:=valgrind}
|
|
: ${VALGRIND_CALLGRIND_PARAMS:="--separate-callers=100"}
|
|
|
|
RAM_CALLGRIND_OUT="ram_callgrind__${date}__$NAME"
|
|
RAM_STACK_OUT="ram_stack__${date}__$NAME"
|
|
|
|
SRV_CMD="$SRV server_addr=127.0.0.1 server_port=4433 debug_level=4 $SRV_PARAMS"
|
|
CLI_CMD="$CLI server_addr=127.0.0.1 server_port=4433 $CLI_PARAMS"
|
|
|
|
VALGRIND_BASE="$VALGRIND --tool=callgrind $VALGRIND_CALLGRIND_PARAMS"
|
|
VALGRIND_CMD="$VALGRIND_BASE --callgrind-out-file=${RAM_CALLGRIND_OUT} $CLI_CMD"
|
|
|
|
$SRV_CMD > /dev/null 2>&1 &
|
|
SRV_PID=$!
|
|
echo "Server started, PID $SRV_PID"
|
|
|
|
$VALGRIND_CMD > /dev/null 2>&1 &
|
|
VAL_PID=$!
|
|
echo "Valgrind callgrind started, PID $VAL_PID"
|
|
|
|
wait $VAL_PID
|
|
echo "Valgrind done, killing server"
|
|
kill $SRV_PID
|
|
echo "Done"
|
|
|
|
# Extract callgraphs from source files directly
|
|
RAM_CALLGRAPH_OUT=""
|
|
if [ -x "$(command -v cflow)" ]; then
|
|
RAM_CALLGRAPH_OUT="ram_cflow__${date}__$NAME"
|
|
cflow library/*.c > $RAM_CALLGRAPH_OUT 2> /dev/null
|
|
fi
|
|
|
|
# Merge stack usage files
|
|
cat library/*.su > ${RAM_STACK_OUT}_unsorted
|
|
sort -r -k2 -n ${RAM_STACK_OUT}_unsorted > $RAM_STACK_OUT
|
|
rm ${RAM_STACK_OUT}_unsorted
|
|
|
|
echo "SUCCESS"
|
|
echo "* Stack usage statistics written to $RAM_STACK_OUT"
|
|
echo "* Callgrind output written to $RAM_CALLGRIND_OUT"
|
|
if [ -n $RAM_CALLGRAPH_OUT ]; then
|
|
echo "* Static call graph written to $RAM_CALLGRAPH_OUT"
|
|
fi
|
|
}
|
|
|
|
show_usage() {
|
|
echo "Usage: $0 [--rom [--check] [--gcc] [--armc5] [--armc6]|--ram [--stack] [--heap]]"
|
|
}
|
|
|
|
test_build=0
|
|
raw_build=0
|
|
|
|
build_gcc=0
|
|
build_armc5=0
|
|
build_armc6=0
|
|
|
|
measure_heap=0
|
|
measure_stack=0
|
|
|
|
check=0
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--gcc) build_gcc=1;;
|
|
--armc5) build_armc5=1;;
|
|
--armc6) build_armc6=1;;
|
|
--ram) test_build=1;;
|
|
--rom) raw_build=1;;
|
|
--heap) measure_heap=1;;
|
|
--stack) measure_stack=1;;
|
|
--check) check=1;;
|
|
-*)
|
|
echo >&2 "Unknown option: $1"
|
|
show_usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ "$test_build" -eq 0 ] &&
|
|
[ "$raw_build" -eq 0 ]; then
|
|
echo "Need to set either --ram or --rom"
|
|
show_usage
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$test_build" -eq 1 ]; then
|
|
|
|
if [ "$measure_heap" -eq 0 ] &&
|
|
[ "$measure_stack" -eq 0 ]; then
|
|
echo "Need to set either --heap or --stack with --ram"
|
|
show_usage
|
|
exit 1
|
|
fi
|
|
|
|
baremetal_ram_build
|
|
|
|
if [ "$measure_heap" -eq 1 ]; then
|
|
baremetal_ram_heap 0
|
|
baremetal_ram_heap 1
|
|
fi
|
|
|
|
if [ "$measure_stack" -eq 1 ]; then
|
|
baremetal_ram_stack
|
|
fi
|
|
|
|
fi
|
|
|
|
if [ "$raw_build" -eq 1 ]; then
|
|
|
|
if [ "$build_gcc" -eq 0 ] &&
|
|
[ "$build_armc5" -eq 0 ] &&
|
|
[ "$build_armc6" -eq 0 ]; then
|
|
echo "Need to set either --gcc, --armc5 or --armc6 with --rom"
|
|
show_usage
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$build_gcc" -eq 1 ]; then
|
|
baremetal_build_gcc
|
|
fi
|
|
if [ "$build_armc5" -eq 1 ]; then
|
|
baremetal_build_armc5
|
|
fi
|
|
if [ "$build_armc6" -eq 1 ]; then
|
|
baremetal_build_armc6
|
|
fi
|
|
fi
|