Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 1 | # |
| 2 | # SPDX-License-Identifier: BSD-3-Clause |
| 3 | # SPDX-FileCopyrightText: Copyright TF-RMM Contributors. |
| 4 | # |
| 5 | |
| 6 | include(FetchContent) |
| 7 | include("${SOURCE_DIR}/tools/cbmc/SummaryHelpers.cmake") |
| 8 | find_program(RMM_CBMC_PATH "cbmc" |
| 9 | DOC "Path to cbmc.") |
| 10 | |
| 11 | # |
| 12 | # Configure and execute CBMC |
| 13 | # |
| 14 | if(NOT (EXISTS "${RMM_CBMC_PATH}")) |
| 15 | message(FATAL_ERROR "cbmc executable not found. (${RMM_CBMC_PATH})") |
| 16 | endif() |
| 17 | |
| 18 | if("${RMM_CBMC_CONFIGURATION}" STREQUAL "COVERAGE") |
| 19 | set(CBMC_RESULT_FILE_SUFFIX "coverage") |
| 20 | set(CBMC_SUMMARY_HEADER "COVERAGE") |
| 21 | set(CBMC_SUMMARY_PATTERN "covered") |
| 22 | elseif("${RMM_CBMC_CONFIGURATION}" STREQUAL "ASSERT") |
| 23 | set(CBMC_RESULT_FILE_SUFFIX "assert") |
| 24 | set(CBMC_SUMMARY_HEADER "ASSERT") |
| 25 | set(CBMC_SUMMARY_PATTERN "failed") |
| 26 | elseif("${RMM_CBMC_CONFIGURATION}" STREQUAL "ANALYSIS") |
| 27 | set(CBMC_RESULT_FILE_SUFFIX "analysis") |
| 28 | set(CBMC_SUMMARY_HEADER "ANALYSIS") |
| 29 | set(CBMC_SUMMARY_PATTERN "failed") |
| 30 | else() |
| 31 | message(FATAL_ERROR "Invalid RMM_CBMC_CONFIGURATION '${RMM_CBMC_CONFIGURATION}'") |
| 32 | endif() |
| 33 | |
| 34 | |
| 35 | set(RMM_TESTBENCH_RESULT_DIR "${BINARY_DIR}/cbmc_${CBMC_RESULT_FILE_SUFFIX}_results") |
| 36 | set(SUMMARY_FILE "SUMMARY.${CBMC_RESULT_FILE_SUFFIX}") |
| 37 | set(RMM_CBMC_SUMMARY_FIELD_WIDTH 38) |
| 38 | |
| 39 | # Configurations for the initial state. |
| 40 | set(GRANULE_SHIFT "7") |
| 41 | set(MAX_NUM_OF_GRANULE "8") |
| 42 | set(HOST_MEM_SIZE "1024UL") |
| 43 | |
| 44 | set(MAX_RTT_UNWIND "6") |
| 45 | set(MAX_AUX_REC "2") |
| 46 | set(MAX_ROOT_RTT "3") |
| 47 | set(MAX_UNWIND_FLAGS "") |
| 48 | |
| 49 | # |
| 50 | # Set up cbmc command line |
| 51 | # |
| 52 | set(cbmc_unwinds_list |
| 53 | "--unwindset;find_lock_rd_granules.0:${MAX_RTT_UNWIND}" |
| 54 | "--unwindset;find_lock_rd_granules.1:${MAX_RTT_UNWIND}" |
| 55 | "--unwindset;smc_realm_create.0:${MAX_RTT_UNWIND}" |
| 56 | "--unwindset;total_root_rtt_refcount.0:${MAX_RTT_UNWIND}" |
| 57 | "--unwindset;free_sl_rtts.0:${MAX_RTT_UNWIND}" |
| 58 | "--unwindset;rtt_walk_lock_unlock.0:${MAX_RTT_UNWIND}" |
| 59 | "--unwindset;RttWalk.0:${MAX_RTT_UNWIND}" |
| 60 | "--unwindset;init_walk_path.0:${MAX_RTT_UNWIND}" |
| 61 | "--unwindset;smc_rec_create.0:${MAX_AUX_REC}" |
| 62 | "--unwindset;free_rec_aux_granules.0:${MAX_AUX_REC}" |
| 63 | "--unwindset;find_lock_granules.3:${MAX_ROOT_RTT}" |
| 64 | "--unwindset;RealmIsLive.0:${MAX_ROOT_RTT}" |
| 65 | "--unwindset;init_rtt_root_page.0:${MAX_ROOT_RTT}" |
| 66 | "--unwindset;init_rec.0:${MAX_AUX_REC}" |
| 67 | "--unwindset;RealmIsLive.2:${MAX_ROOT_RTT}" |
| 68 | "--unwindset;init_realm_descriptor_page.0:${MAX_ROOT_RTT}" |
| 69 | "--unwindset;init_rec.0:${MAX_AUX_REC}" |
| 70 | "--unwindset;lock_order_invariable.0:21" |
| 71 | "--unwindset;lock_order_invariable.1:11" |
| 72 | "--unwindset;lock_order_invariable.2:" |
| 73 | ) |
| 74 | |
| 75 | set(cbmc_defines_list |
| 76 | "-DCBMC" |
| 77 | "-DDISABLE_COMPILER_ASSERT" |
| 78 | "-DDISABLE_SET_MEMBER" |
| 79 | "-DGRANULE_SHIFT=${GRANULE_SHIFT}" |
| 80 | "-DXLAT_GRANULARITY_SIZE_SHIFT=${GRANULE_SHIFT}" |
| 81 | "-DRMM_MAX_GRANULES=${MAX_NUM_OF_GRANULE}" |
| 82 | "-DMAX_CPUS=1" |
| 83 | "-DMAX_RTT_LEVEL=${MAX_RTT_UNWIND}" |
| 84 | "-DHOST_MEM_SIZE=${HOST_MEM_SIZE}" |
| 85 | "-DNAME=\"RMM\"" |
| 86 | "-DVERSION=\"CBMC\"" |
| 87 | "-DCOMMIT_INFO=\"CBMC\"" |
| 88 | ) |
| 89 | |
| 90 | # CBMC flags for memory safety analysis and undefined behaviour analysis. |
| 91 | set(cbmc_analysis_flags_list |
| 92 | "--bounds-check" |
| 93 | "--pointer-check" |
| 94 | "--div-by-zero-check" |
| 95 | "--signed-overflow-check" |
| 96 | "--unsigned-overflow-check" |
| 97 | "--pointer-overflow-check" |
| 98 | "--conversion-check" |
| 99 | "--undefined-shift-check" |
| 100 | "--float-overflow-check" |
| 101 | "--nan-check" |
| 102 | "--enum-range-check" |
| 103 | "--pointer-primitive-check" |
| 104 | "--memory-leak-check") |
| 105 | |
| 106 | set(cbmc_flags_list |
| 107 | "--c11" |
| 108 | "--timestamp;wall" |
| 109 | "--verbosity;9" |
| 110 | # Optimisation flags: |
| 111 | "--drop-unused-functions" |
| 112 | "--reachability-slice" |
| 113 | ) |
| 114 | |
| 115 | if("${RMM_CBMC_CONFIGURATION}" STREQUAL "COVERAGE") |
| 116 | list(APPEND cbmc_flags_list |
| 117 | "--cover;cover" |
| 118 | "--no-assertions") |
| 119 | elseif("${RMM_CBMC_CONFIGURATION}" STREQUAL "ASSERT") |
| 120 | list(APPEND cbmc_flags_list |
| 121 | "--unwinding-assertions" |
| 122 | "--trace" |
| 123 | "--trace-show-function-calls") |
| 124 | elseif("${RMM_CBMC_CONFIGURATION}" STREQUAL "ANALYSIS") |
| 125 | list(APPEND cbmc_flags_list |
| 126 | "--unwinding-assertions" |
| 127 | "${cbmc_analysis_flags_list}") |
| 128 | else() |
| 129 | message(FATAL_ERROR "Invalid RMM_CBMC_CONFIGURATION '${RMM_CBMC_CONFIGURATION}'") |
| 130 | endif() |
| 131 | |
| 132 | file(GLOB_RECURSE TESTBENCH_FILES "${TESTBENCH_DIR}/*.c") |
| 133 | |
| 134 | # |
| 135 | # Create semi-colon separated list from white-space seperated ones. |
| 136 | # |
| 137 | separate_arguments(RMM_IMP_SRCS) |
| 138 | separate_arguments(RMM_IMP_INCS) |
| 139 | |
| 140 | # |
| 141 | # Execute CBMC on the testbench files |
| 142 | # |
| 143 | rmm_cbmc_write_summary_header(${RMM_CBMC_SUMMARY_FIELD_WIDTH} |
| 144 | ${RMM_TESTBENCH_RESULT_DIR} ${SUMMARY_FILE} ${CBMC_SUMMARY_HEADER}) |
| 145 | |
| 146 | foreach(testbench_file ${TESTBENCH_FILES}) |
| 147 | |
| 148 | string(REPLACE ${TESTBENCH_DIR}/ "" testbench_filename ${testbench_file}) |
| 149 | string(REGEX REPLACE "\\.[^\\.]*$" "" entry_point "${testbench_filename}") |
| 150 | |
| 151 | set(cmd |
| 152 | ${RMM_CBMC_PATH} |
| 153 | ${cbmc_flags_list} |
| 154 | "--function;${entry_point}" |
| 155 | ${RMM_IMP_INCS} |
| 156 | ${cbmc_unwinds_list} |
| 157 | ${cbmc_defines_list} |
| 158 | ${RMM_IMP_SRCS} |
| 159 | ${testbench_file}) |
| 160 | |
| 161 | # Set the names of output files |
| 162 | string(REPLACE ${TESTBENCH_DIR} ${RMM_TESTBENCH_RESULT_DIR} output_file ${testbench_file}) |
| 163 | set(error_file ${output_file}) |
| 164 | set(cmd_file ${output_file}) |
| 165 | string(APPEND output_file ".${CBMC_RESULT_FILE_SUFFIX}" ".output") |
| 166 | string(APPEND error_file ".${CBMC_RESULT_FILE_SUFFIX}" ".error") |
| 167 | string(APPEND cmd_file ".${CBMC_RESULT_FILE_SUFFIX}" ".cmd") |
| 168 | |
| 169 | # remove the absolute path making it relative |
| 170 | string (REPLACE "${SOURCE_DIR}/" "" cmd "${cmd}") |
| 171 | # replace the ; with space |
| 172 | string (REPLACE ";" " " CMD_STR "${cmd}") |
| 173 | # add double quotes |
| 174 | string (REPLACE "\"" "\\\"" CMD_STR "${CMD_STR}") |
| 175 | # escape parentheses |
| 176 | string (REPLACE "(" "\"(" CMD_STR "${CMD_STR}") |
| 177 | string (REPLACE ")" ")\"" CMD_STR "${CMD_STR}") |
| 178 | file(WRITE ${cmd_file} "${CMD_STR}") |
| 179 | |
| 180 | execute_process(COMMAND ${CMAKE_COMMAND} -E echo_append "CBMC: ${testbench_file}... ") |
| 181 | execute_process( |
| 182 | COMMAND ${cmd} |
| 183 | RESULT_VARIABLE res_var |
| 184 | OUTPUT_FILE ${output_file} |
| 185 | ERROR_FILE ${error_file} |
| 186 | ) |
| 187 | |
| 188 | execute_process(COMMAND ${CMAKE_COMMAND} -E echo "DONE") |
| 189 | |
| 190 | rmm_cbmc_append_summary("${testbench_filename}" "${output_file}" |
| 191 | ${RMM_CBMC_SUMMARY_FIELD_WIDTH} ${RMM_TESTBENCH_RESULT_DIR} ${SUMMARY_FILE} |
| 192 | ${CBMC_SUMMARY_PATTERN}) |
| 193 | |
| 194 | endforeach() |
| 195 | message(STATUS "Result in ${RMM_TESTBENCH_RESULT_DIR}") |