diff --git a/cmake/sca/eclair/ECL/adopted_code.ecl b/cmake/sca/eclair/ECL/adopted_code.ecl new file mode 100644 index 0000000000000..efd884e844f4c --- /dev/null +++ b/cmake/sca/eclair/ECL/adopted_code.ecl @@ -0,0 +1,7 @@ +-doc_begin="This header file is automatically generated by Autoconf." +-file_tag+={adopted,"^zephyr/build/zephyr/include/generated/autoconf\\.h$"} +-doc_end + +-doc_begin="These files are automatically generated by gperf." +-file_tag+={adopted,"^zephyr/build/zephyr/kobject_.*\\.c$"} +-doc_end diff --git a/cmake/sca/eclair/ECL/adopted_deviations.ecl b/cmake/sca/eclair/ECL/adopted_deviations.ecl new file mode 100644 index 0000000000000..7279c2de3bd36 --- /dev/null +++ b/cmake/sca/eclair/ECL/adopted_deviations.ecl @@ -0,0 +1,43 @@ +-setq=CPP_MANUAL,"https://gcc.gnu.org/onlinedocs/gcc-10.3.0/cpp.pdf" + +-doc="Selection for reports that are fully contained in adopted code." +-report_selector+={adopted_report,"all_area(!kind(culprit||evidence)||all_loc(all_exp(adopted||pseudo)))"} + +-doc_begin="Adopted code is not meant to be read, reviewed or modified by human programmers:no developers' confusion is not possible. In addition, adopted code is assumed to work as is. Reports that are fully contained in adopted code are hidden/tagged with the 'adopted' tag." +-config=MC3R1.R7.2,reports+={relied,adopted_report} +-config=MC3R1.R10.3,reports+={relied,adopted_report} +-config=MC3R1.R10.6,reports+={relied,adopted_report} +-config=MC3R1.R12.1,reports+={relied,adopted_report} +-doc_end + +-doc_begin="Macro LOAPIC_BASE_ADDRESS, automatically generated by Autoconf, expands to an implicitly unsigned literal lacking the 'u' or 'U' suffix." +-config=MC3R1.R7.2,reports+={safe,"all_area(all_loc(any_exp(macro(^assert$))))"} +-doc_end + +-doc="#include_next is a documented GNU preprocessing directive. See section \"2.7 Wrapper Headers\" of "CPP_MANUAL"" +-config=STD.prepdirc,directives+={safe,"^include_next$"} +-doc="#warning is a documented GNU preprocessing directive. See section \"5 Diagnostics\" of "CPP_MANUAL"" +-config=STD.prepdirc,directives+={safe,"^warning$"} + +-doc="The declarations in files tagged with api:public define a public API of Zephyr. +Declarations in these files not necessarily have to be referenced." +-config=MC3R1.R2.3,declarations+={safe,"loc(top(public()))"} + +-doc="Library entry points not necessarily have to be referenced." +-config=MC3R1.R2.1,declarations+={safe,"loc(top(public()))"} + +-doc="Library entry points not necessarily have to be referenced in more than one translation units." +-config=MC3R1.R8.7,declarations+={safe,"loc(top(public()))"} + +-doc="Syscall declarations are automatically generated all with the extern qualifier. For the ones with internal linkage the use of the extern qualifier is a violation of rule 8.8." +-config=MC3R1.R8.8,declarations={relied, "^z_vrfy_.*$||^z_impl_.*$"} + +-doc="Function hash, that is automatically generated, does not use the parameter \"len\" in all its definitions." +-config=MC3R1.R2.7,declarations+={relied,"context(^hash\\(const char\\*, size_t\\)$)&&name(len)"} + +-doc="Function \"z_object_lookup\", that is automatically generated, uses single-statement bodies not enclosed in braces." +-config=MC3R1.R15.6,reports={relied, "all_area(context(^z_object_lookup\\(const char\\*, size_t\\)$))"} + +-doc="The following declarations are in generated files: not in all configuration they are implemented. + Chainging the generators could be dangerous and the advantages in enforcing the rule do not outweight these dangers." +-config=MC3R1.R8.6,declarations+={safe, "loc(top(file(^zephyr/build/zephyr/include/generated/.*$)))"} diff --git a/cmake/sca/eclair/ECL/analysis.ecl b/cmake/sca/eclair/ECL/analysis.ecl new file mode 100644 index 0000000000000..ddca224e2b024 --- /dev/null +++ b/cmake/sca/eclair/ECL/analysis.ecl @@ -0,0 +1,11 @@ +-setq=data_dir,getenv("ECLAIR_DATA_DIR") +-setq=set,getenv("ECLAIR_RULESET") + +-enable=B.REPORT.ECB +-config=B.REPORT.ECB,output=join_paths(data_dir,"FRAME.@FRAME@.ecb") +-config=B.REPORT.ECB,preprocessed=show +-config=B.REPORT.ECB,macros=10 + +-enable=B.EXPLAIN + +-eval_file=toolchain.ecl diff --git a/cmake/sca/eclair/ECL/analysis_HIS.ecl b/cmake/sca/eclair/ECL/analysis_HIS.ecl new file mode 100644 index 0000000000000..9ef829f8b92ce --- /dev/null +++ b/cmake/sca/eclair/ECL/analysis_HIS.ecl @@ -0,0 +1,21 @@ +# This file must be named analyze_.ecl, where is the first +# argument of analyze.sh. +# +# The aim of this file is to define the analysis configuration for . +# +# The essential portions of this file are marked with "# NEEDED": +# they may be adapted of course. + +# Enable the desired metrics. +-enable=MET.HIS.COMF +-enable=MET.HIS.PATH +-enable=MET.HIS.GOTO +-enable=MET.HIS.v_G +-enable=MET.HIS.CALLING +-enable=MET.HIS.CALLS +-enable=MET.HIS.PARAM +-enable=MET.HIS.STMT +-enable=MET.HIS.LEVEL +-enable=MET.HIS.RETURN +-enable=MET.HIS.VOCF +-enable=MET.HIS.ap_cg_cycle diff --git a/cmake/sca/eclair/ECL/analysis_STU.ecl b/cmake/sca/eclair/ECL/analysis_STU.ecl new file mode 100644 index 0000000000000..ce205b0c8c156 --- /dev/null +++ b/cmake/sca/eclair/ECL/analysis_STU.ecl @@ -0,0 +1,115 @@ +# This file must be named analyze_.ecl, where is the first +# argument of analyze.sh. +# +# The aim of this file is to define the analysis configuration for . +# +# The essential portions of this file are marked with "# NEEDED": +# they may be adapted of course. + +-eval_file=zephyr_common_config.ecl + +-doc_begin="Selection of guidelines from +https://docs.zephyrproject.org/latest/guides/coding_guidelines/index.html" +-enable=MC3R1.D4.13 +-enable=MC3R1.D4.2 +-enable=MC3R1.D4.4 +-enable=MC3R1.D4.5 +-enable=MC3R1.D4.8 +-enable=MC3R1.D4.11 +-enable=MC3R1.D4.12 +-enable=MC3R1.D4.14 +-enable=MC3R1.D4.7 +-enable=MC3R1.R10.5 +-enable=MC3R1.R10.2 +-enable=MC3R1.R10.6 +-enable=MC3R1.R10.7 +-enable=MC3R1.R10.8 +-enable=MC3R1.R1.2 +-enable=MC3R1.R1.3 +-enable=MC3R1.R12.4 +-enable=MC3R1.R12.5 +-enable=MC3R1.R12.2 +-enable=MC3R1.R13.4 +-enable=MC3R1.R13.1 +-enable=MC3R1.R13.2 +-enable=MC3R1.R13.5 +-enable=MC3R1.R13.6 +-enable=MC3R1.R18.5 +-enable=MC3R1.R18.1 +-enable=MC3R1.R18.2 +-enable=MC3R1.R18.3 +-enable=MC3R1.R18.6 +-enable=MC3R1.R18.8 +-enable=MC3R1.R21.11 +-enable=MC3R1.R21.13 +-enable=MC3R1.R21.17 +-enable=MC3R1.R21.18 +-enable=MC3R1.R21.19 +-enable=MC3R1.R21.20 +-enable=MC3R1.R2.7 +-enable=MC3R1.R2.2 +-enable=MC3R1.R4.2 +-enable=MC3R1.R4.1 +-enable=MC3R1.R17.3 +-enable=MC3R1.R17.4 +-enable=MC3R1.R17.6 +-enable=MC3R1.R17.1 +-enable=MC3R1.R17.5 +-enable=MC3R1.R19.1 +-enable=MC3R1.R22.2 +-enable=MC3R1.R22.5 +-enable=MC3R1.R22.6 +-enable=MC3R1.R9.1 +-enable=MC3R1.R9.2 +-enable=MC3R1.R9.3 +-enable=MC3R1.R9.4 +-enable=MC3R1.R9.5 +-enable=MC3R1.D2.1 +-enable=MC3R1.R11.2 +-enable=MC3R1.R11.6 +-enable=MC3R1.R11.7 +-enable=MC3R1.R11.8 +-enable=MC3R1.R11.9 +-enable=MC3R1.R14.1 +-enable=MC3R1.R14.2 +-enable=MC3R1.R14.3 +-enable=MC3R1.R15.2 +-enable=MC3R1.R15.3 +-enable=MC3R1.R15.6 +-enable=MC3R1.R15.7 +-enable=MC3R1.R16.1 +-enable=MC3R1.R16.2 +-enable=MC3R1.R16.3 +-enable=MC3R1.R16.4 +-enable=MC3R1.R16.5 +-enable=MC3R1.R16.6 +-enable=MC3R1.R16.7 +-enable=MC3R1.R20.11 +-enable=MC3R1.R20.12 +-enable=MC3R1.R20.13 +-enable=MC3R1.R20.14 +-enable=MC3R1.R20.2 +-enable=MC3R1.R20.3 +-enable=MC3R1.R20.4 +-enable=MC3R1.R20.8 +-enable=MC3R1.R20.9 +-enable=MC3R1.R3.1 +-enable=MC3R1.R3.2 +-enable=MC3R1.R5.2 +-enable=MC3R1.R5.3 +-enable=MC3R1.R5.4 +-enable=MC3R1.R5.5 +-enable=MC3R1.R6.1 +-enable=MC3R1.R6.2 +-enable=MC3R1.R7.1 +-enable=MC3R1.R7.2 +-enable=MC3R1.R7.3 +-enable=MC3R1.R7.4 +-enable=MC3R1.R8.1 +-enable=MC3R1.R8.10 +-enable=MC3R1.R8.12 +-enable=MC3R1.R8.14 +-enable=MC3R1.R8.2 +-enable=MC3R1.R8.4 +-enable=MC3R1.R8.8 +-doc_end diff --git a/cmake/sca/eclair/ECL/analysis_WP.ecl b/cmake/sca/eclair/ECL/analysis_WP.ecl new file mode 100644 index 0000000000000..eec57e979f70d --- /dev/null +++ b/cmake/sca/eclair/ECL/analysis_WP.ecl @@ -0,0 +1,32 @@ +# This file must be named analyze_.ecl, where is the first +# argument of analyze.sh. +# +# The aim of this file is to define the analysis configuration for . +# +# The essential portions of this file are marked with "# NEEDED": +# they may be adapted of course. + +-eval_file=zephyr_common_config.ecl + +-doc_begin="Selection of guidelines from +https://docs.zephyrproject.org/latest/guides/coding_guidelines/index.html" +-enable=MC3R1.R2.3 +-enable=MC3R1.R2.1 +-enable=MC3R1.R5.9 +-enable=MC3R1.R5.1 +-enable=MC3R1.R5.6 +-enable=MC3R1.R5.7 +-enable=MC3R1.R5.8 +-enable=MC3R1.R8.9 +-enable=MC3R1.R8.3 +-enable=MC3R1.R8.5 +-enable=MC3R1.R8.6 +-enable=MC3R1.R22.4 +-enable=MC3R1.R22.3 +-enable=MC3R1.D1.1 +-enable=MC3R1.D3.1 +-enable=MC3R1.D4.1 +-enable=MC3R1.D4.10 +-enable=MC3R1.R17.2 +-enable=MC3R1.R17.7 +-doc_end diff --git a/cmake/sca/eclair/ECL/analysis_first_analysis.ecl b/cmake/sca/eclair/ECL/analysis_first_analysis.ecl new file mode 100644 index 0000000000000..cab0da1225e12 --- /dev/null +++ b/cmake/sca/eclair/ECL/analysis_first_analysis.ecl @@ -0,0 +1,21 @@ +# This file must be named analyze_.ecl, where is the first +# argument of analyze.sh. +# +# The aim of this file is to define the analysis configuration for . +# +# The essential portions of this file are marked with "# NEEDED": +# they may be adapted of course. + +-eval_file=zephyr_common_config.ecl + +-doc_begin="Selection of guidelines from +https://docs.zephyrproject.org/latest/guides/coding_guidelines/index.html" +-enable=MC3R1.R8.2 +-enable=MC3R1.R10.2 +-enable=MC3R1.R10.5 +-enable=MC3R1.R10.6 +-enable=MC3R1.R11.2 +-enable=MC3R1.R12.4 +-enable=MC3R1.R13.4 +-enable=MC3R1.R16.1 +-doc_end diff --git a/cmake/sca/eclair/ECL/analysis_heavy_STU.ecl b/cmake/sca/eclair/ECL/analysis_heavy_STU.ecl new file mode 100644 index 0000000000000..126becb391f4c --- /dev/null +++ b/cmake/sca/eclair/ECL/analysis_heavy_STU.ecl @@ -0,0 +1,23 @@ +# This file must be named analyze_.ecl, where is the first +# argument of analyze.sh. +# +# The aim of this file is to define the analysis configuration for . +# +# The essential portions of this file are marked with "# NEEDED": +# they may be adapted of course. + +-eval_file=zephyr_common_config.ecl + +-doc_begin="Selection of guidelines from +https://docs.zephyrproject.org/latest/guides/coding_guidelines/index.html" +-enable=MC3R1.D4.6 +-enable=MC3R1.D4.9 +-enable=MC3R1.R12.1 +-enable=MC3R1.R13.3 +-enable=MC3R1.R2.6 +-enable=MC3R1.R10.1 +-enable=MC3R1.R10.3 +-enable=MC3R1.R10.4 +-enable=MC3R1.R14.4 +-enable=MC3R1.R20.7 +-doc_end diff --git a/cmake/sca/eclair/ECL/analysis_std_lib.ecl b/cmake/sca/eclair/ECL/analysis_std_lib.ecl new file mode 100644 index 0000000000000..5fb6263910b83 --- /dev/null +++ b/cmake/sca/eclair/ECL/analysis_std_lib.ecl @@ -0,0 +1,28 @@ +# This file must be named analyze_.ecl, where is the first +# argument of analyze.sh. +# +# The aim of this file is to define the analysis configuration for . +# +# The essential portions of this file are marked with "# NEEDED": +# they may be adapted of course. +-eval_file=zephyr_common_config.ecl + +-doc_begin="Selection of guidelines from +https://docs.zephyrproject.org/latest/guides/coding_guidelines/index.html" +-enable=MC3R1.R21.1 +-enable=MC3R1.R21.12 +-enable=MC3R1.R21.14 +-enable=MC3R1.R21.15 +-enable=MC3R1.R21.16 +-enable=MC3R1.R21.2 +-enable=MC3R1.R21.3 +-enable=MC3R1.R21.4 +-enable=MC3R1.R21.6 +-enable=MC3R1.R21.7 +-enable=MC3R1.R21.9 +-enable=MC3R1.R22.1 +-enable=MC3R1.R22.10 +-enable=MC3R1.R22.7 +-enable=MC3R1.R22.8 +-enable=MC3R1.R22.9 +-doc_end diff --git a/cmake/sca/eclair/ECL/call_properties.ecl b/cmake/sca/eclair/ECL/call_properties.ecl new file mode 100644 index 0000000000000..8e1c7a2e5dd0b --- /dev/null +++ b/cmake/sca/eclair/ECL/call_properties.ecl @@ -0,0 +1,81 @@ + +-call_properties+={"name(z_phys_map)", {"pointee_read(1=never)","pointee_write(1=always)","taken()"}} +-call_properties+={"name(pcie_get_mbar)", {"pointee_read(3=never)","pointee_write(3=maybe)","taken()"}} +-call_properties+={"name(k_mem_region_align)", { + "pointee_read(1..2=never)", + "pointee_write(1..2=always)","taken()" + }} +-call_properties+={"name(pentry_get)", { + "pointee_read(1..2=never&&3..4=always)", + "pointee_write(1..2=maybe&&3..4=never)" + }} +-call_properties+={"name(z_phys_unmap)", {"pointee_read(1=never)","pointee_write(1=never)"}} +-call_properties+={"name(check_sum)", {"pointee_read(1=always)","pointee_write(1=never)"}} +-call_properties+={"name(z_impl_device_get_binding)", {"pointee_read(1=maybe)","pointee_write(1=maybe)","taken()"}} +-call_properties+={"name(z_setup_new_thread)", {"pointee_read(10=maybe)","pointee_write(10=never)","taken()"}} +-call_properties+={"name(mbox_message_put)", {"pointee_read(3=always)","pointee_write(3=always)"}} +-doc_begin="The functions can be implemented using the GCC built-in functions. + See Section \"6.62.13 6.56 Built-in Functions to Perform Arithmetic with Overflow Checking\" of "GCC_MANUAL"." +-call_properties+={"name(size_mul_overflow)", {"pointee_read(3=never)","pointee_write(3=always)","taken()"}} +-call_properties+={"name(size_add_overflow)", {"pointee_read(3=never)","pointee_write(3=always)","taken()"}} +-call_properties+={"name(__builtin_mul_overflow)", {"pointee_read(3=never)","pointee_write(3=always)","taken()"}} +-call_properties+={"name(__builtin_add_overflow)", {"pointee_read(3=never)","pointee_write(3=always)","taken()"}} +-doc_end + +-call_properties+={"name(__builtin_va_end)", {"taken()"}} # Not documented in gcc.pdf +-call_properties+={"name(arch_page_phys_get)", {"pointee_read(2=never)","pointee_write(2=maybe)","taken()"}} +-call_properties+={"name(cbvprintf)", {"taken()"}} +-call_properties+={"name(cbvprintf)", {"taken()"}} +-call_properties+={"name(char2hex)", {"pointee_read(2=never)","pointee_write(2=maybe)"}} +-call_properties+={"name(find_and_stack)", {"pointee_read(3=never)","pointee_write(3=always)"}} +-call_properties+={"name(fix_missing_black)", {"pointee_read(1=always)","pointee_write(1=maybe)"}} +-call_properties+={"name(__get_cpuid)", {"pointee_read(2..5=never)","pointee_write(2..5=always)"}} +-call_properties+={"name(k_mutex_init)", {"pointee_read(1=never)","pointee_write(1=always)"}} +-call_properties+={"name(k_sem_init)", {"pointee_read(1=never)","pointee_write(1=maybe)"}} +-call_properties+={"name(k_work_init)", {"pointee_read(1=never)","pointee_write(1=always)"}} +-call_properties+={"name(k_work_init_delayable)", {"pointee_read(1=never)","pointee_write(1=always)"}} +-call_properties+={"name(k_work_queue_start)", {"taken()"}} +-call_properties+={"name(log_from_user)", {"pointee_write(1..=never)", "taken()"}} +-call_properties+={"name(log_n)", {"taken()"}} +-call_properties+={"name(log_string_sync)", {"pointee_write(1..=never)", "taken()"}} +-call_properties+={"name(match_region)", {"pointee_read(5..6=never)","pointee_write(5=always&&6=maybe)"}} +-call_properties+={"name(mbox_async_alloc)", {"pointee_read(1=never)","pointee_write(1=maybe)"}} +-call_properties+={"name(pipe_xfer_prepare)", {"pointee_read(2=never)","pointee_write(2=always)"}} +-call_properties+={"name(printk)", {"pointee_write(1..=never)", "taken()"}} +-call_properties+={"name(snprintk)", {"pointee_read(1=never)","pointee_write(1=always)", "taken()"}} # to check +-call_properties+={"name(snprintk)", {"taken()"}} +-call_properties+={"name(sys_bitarray_alloc)", {"pointee_read(3=never)","pointee_write(3=maybe)","taken()"}} +-call_properties+={"name(sys_slist_init)", {"pointee_read(1=never)","pointee_write(1=always)"}} +-call_properties+={"name(vprintk)", {"taken()"}} +-call_properties+={"name(z_dummy_thread_init)", {"pointee_read(1=never)","pointee_write(1=always)"}} # the function does not initialize all the fields +-call_properties+={"name(z_impl_k_stack_pop)", {"taken()"}} +-call_properties+={"name(z_impl_z_log_msg2_runtime_vcreate)", {"taken()"}} +-call_properties+={"name(z_log_minimal_printk)", {"pointee_write(1..=never)", "taken()"}} +-call_properties+={"name(z_log_msg2_runtime_create)", {"pointee_write(1..=never)", "taken()"}} +-call_properties+={"name(z_log_printk)", {"taken()"}} +-call_properties+={"name(z_log_printf_arg_checker)", {"pointee_write(1..=never)", "taken()"}} +-call_properties+={"name(z_log_strdup)", {"taken()"}} +-call_properties+={"name(z_rb_foreach_next)", {"taken()"}} +-call_properties+={"name(z_user_string_copy)", {"pointee_read(1=never)","pointee_write(1=maybe)","taken()"}} + +-doc_begin="These macros are designed to evaluate to either 0 or 1." +-call_properties+={"macro(name(UTIL_NOT))",{"data_kind(0=int_bool)"}} +-call_properties+={"macro(name(IS_ENABLED))",{"data_kind(0=int_bool)"}} +-call_properties+={"decl(name(isspace))",{"data_kind(0=int_bool)"}} +-call_properties+={"macro(name(isdigit))",{"data_kind(0=int_bool)"}} +-call_properties+={"decl(name(isdigit))",{"data_kind(0=int_bool)"}} +-call_properties+={"macro(name(isalpha))",{"data_kind(0=int_bool)"}} +-call_properties+={"decl(name(isalpha))",{"data_kind(0=int_bool)"}} +-call_properties+={"macro(name(isupper))",{"data_kind(0=int_bool)"}} +-call_properties+={"decl(name(isupper))",{"data_kind(0=int_bool)"}} +-doc_end + +-doc="__builtin_alloca cannot interfere with other effects." +-call_properties+={"decl(name(__builtin_alloca))",{"noeffect"}} + +-doc="log_strdup cannot interfere with other effects." +-call_properties+={"decl(name(log_strdup))",{"noeffect"}} + + +# Not documented functions +# device_map diff --git a/cmake/sca/eclair/ECL/db_generation.ecl b/cmake/sca/eclair/ECL/db_generation.ecl new file mode 100644 index 0000000000000..e10fa67448105 --- /dev/null +++ b/cmake/sca/eclair/ECL/db_generation.ecl @@ -0,0 +1,28 @@ +# eclair_report + +# NEEDED: set the variable for the binary output directory from the environment +# variable. +setq(data_dir,getenv("ECLAIR_DATA_DIR")) + +# NEEDED: set the variable for the ECLAIR project database from the environment +# variable. +setq(ecd_file,getenv("ECLAIR_PROJECT_ECD")) + +# NEEDED: set the variable for the output directory from the environment +# variable. +setq(output_dir,getenv("ECLAIR_OUTPUT_DIR")) + +if(file_exists(ecd_file), + db(ecd_file), + create_db(ecd_file)) + +setq(loaded_dir,join_paths(data_dir,"loaded")) +make_dirs(loaded_dir) + +# NEEDED: generate the ecd from frame files +strings_map("load_ecb",500,"",".+\\.ecb",0,setq(ecb,join_paths(data_dir,$0)),load(ecb),rename(ecb,join_paths(loaded_dir,$0))) +strings_map("load_ecb",500,"",".*",0) + +loading() +map_strings("load_ecb", dir_entries(data_dir)) +loaded() diff --git a/cmake/sca/eclair/ECL/extra.ecl b/cmake/sca/eclair/ECL/extra.ecl new file mode 100644 index 0000000000000..cab2a4e723600 --- /dev/null +++ b/cmake/sca/eclair/ECL/extra.ecl @@ -0,0 +1,74 @@ +-doc_begin="The following entities are defined in assembly files" +-extra_definitions+="name(x86_ap_start)" +-extra_definitions+="^z_x86_(exception|nmi|trampoline)_stack[1-3]?$" +-extra_definitions+="name(x86_sse_init)" +-extra_definitions+="name(z_x86_kernel_ptables)" +-extra_definitions+="name(z_x86_switch)" +-extra_definitions+="name(z_x86_syscall_entry_stub)" +-extra_definitions+="^(z_x86_user_string_nlen)_(fault_start|fault_end|fixup)\\(void\\)$" +-extra_definitions+="name(z_x86_userspace_enter)" +-extra_definitions+="name(arch_user_string_nlen)" +-doc_end + +-doc_begin="The following entities are defined from the linker." +-extra_definitions+="name(_locore_start)" +-extra_definitions+="name(_locore_end)" +-extra_definitions+="name(__kernel_ram_start)" +-extra_definitions+="name(__kernel_ram_end)" +-extra_definitions+="name(__kernel_ram_size)" +-extra_definitions+="name(_app_smem_start)" +-extra_definitions+="name(_app_smem_end)" +-extra_definitions+="name(_app_smem_size)" +-extra_definitions+="name(_app_smem_rom_start)" +-extra_definitions+="name(_app_smem_num_words)" +-extra_definitions+="name(__bss_start)" +-extra_definitions+="name(__bss_end)" +-extra_definitions+="name(__rom_region_start)" +-extra_definitions+="name(__rom_region_end)" +-extra_definitions+="name(__rom_region_size)" +-extra_definitions+="name(_flash_used)" +-extra_definitions+="name(_image_ram_start)" +-extra_definitions+="name(_image_ram_end)" +-extra_definitions+="name(__text_region_start)" +-extra_definitions+="name(__text_region_end)" +-extra_definitions+="name(__text_region_size)" +-extra_definitions+="name(__rodata_region_start)" +-extra_definitions+="name(__rodata_region_end)" +-extra_definitions+="name(__rodata_region_size)" +-extra_definitions+="name(_vector_start)" +-extra_definitions+="name(_vector_end)" +-extra_definitions+="name(_end)" +-extra_definitions+="name(__log_backends_start)" +-extra_definitions+="name(__log_backends_end)" +-extra_definitions+="name(__log_const_start)" +-extra_definitions+="name(__log_const_end)" +-extra_definitions+="name(__log_dynamic_start)" +-extra_definitions+="name(__log_dynamic_end)" +-extra_definitions+="name(__device_start)" +-extra_definitions+="name(__device_end)" +-extra_definitions+="name(__init_start)" +-extra_definitions+="name(__init_end)" +-extra_definitions+="name(z_shared_kernel_page_start)" +-extra_definitions+="name(z_priv_stacks_ram_start)" +-extra_definitions+="name(z_priv_stacks_ram_end)" +-extra_definitions+="name(z_user_stacks_start)" +-extra_definitions+="name(z_user_stacks_end)" +-extra_definitions+="name(z_kobject_data_begin)" +-extra_definitions+="name(__app_shmem_regions_start)" +-extra_definitions+="name(__app_shmem_regions_end)" +-extra_definitions+="name(_thread_idx_map)" +-extra_definitions+="name(z_data_smem_footprint_mem_partition_part_start)" +-extra_definitions+="name(z_data_smem_footprint_mem_partition_part_size)" +-extra_definitions+="name(z_data_smem_footprint_mem_partition_bss_start)" +-extra_definitions+="name(z_data_smem_footprint_mem_partition_bss_size)" +-extra_definitions+="name(z_object_gperf_find)" +-extra_definitions+="name(z_object_gperf_wordlist_foreach)" +-extra_definitions+="name(_z_object_assignment_list_start)" +-extra_definitions+="name(_z_object_assignment_list_end)" +-doc_end + +-doc="Entities created with Z_LINK_ITERABLE in linker.ld" +-extra_definitions+="^_(_static_thread_data|k_timer|k_mem_slab|k_mem_pool|k_heap|k_mutex|k_stack|k_msgq|k_mbox|k_pipe|k_sem|k_queue)_list_(start|end)$" + +-extra_definitions+="^z_mapped_(start|end)$" +-extra_definitions+="^__init_(PRE_KERNEL_[12]|POST_KERNEL|APPLICATION|SMP)_start$" diff --git a/cmake/sca/eclair/ECL/language_extensions.ecl b/cmake/sca/eclair/ECL/language_extensions.ecl new file mode 100644 index 0000000000000..f00bfca7c6ab6 --- /dev/null +++ b/cmake/sca/eclair/ECL/language_extensions.ecl @@ -0,0 +1,7 @@ +-doc_begin="The following extension have been approved." +-config=MC3R1.R1.2,behaviors+={hide,"service(STD.tokenext)&&category(^(__asm__|__attribute__|__typeof__|__builtin_types_compatible_p|__volatile__|__alignof|__alignof__|__const__|__inline|_Generic|_Static_assert|__auto_type)$)"} +-config=MC3R1.R1.2,behaviors+={hide,"service(^STD.(stmtexpr|vptrarth|emptinit|emptrecd|arayzero|funojptr)$)"} +-config=MC3R1.R1.2,behaviors+={hide,"service(STD.nonstdc)&&category(^GCC diagnostic (push|pop|ignored \"-W.*\")$)"} +-config=MC3R1.R1.2,behaviors+={hide,"service(STD.freestlb)&&category(^(string|fcntl|time|errno|ctype|stdio|inttypes|stdlib).h$)"} +-config=MC3R1.R1.2,behaviors+={hide,"service(STD.diag)&&category(^(ext_missing_varargs_arg|ext_paste_comma|ext_flexible_array_in_array|ext_auto_type)$)"} +-doc_end diff --git a/cmake/sca/eclair/ECL/out_of_initial_scope.ecl b/cmake/sca/eclair/ECL/out_of_initial_scope.ecl new file mode 100644 index 0000000000000..637d09522569d --- /dev/null +++ b/cmake/sca/eclair/ECL/out_of_initial_scope.ecl @@ -0,0 +1,12 @@ +-doc_begin="Derived from Flavio Ceolin email of July 23rd, 2021." +-file_tag+={out_of_initial_scope, "^zephyr/samples/.*$"} +-file_tag+={out_of_initial_scope, "^.*\\.cpp$"} +-file_tag+={out_of_initial_scope, "^zephyr/tests/.*$"} +-file_tag+={out_of_initial_scope, "^zephyr/build/zephyr/include/generated/autoconf\\.h$"} +-file_tag+={out_of_initial_scope, "^zephyr/drivers/.*/.*$"} +-file_tag+={out_of_initial_scope, "^zephyr/lib/libc/.*$"} +-file_tag+={out_of_initial_scope, "^zephyr/lib/crc/.*$"} +-file_tag+={out_of_initial_scope, "^zephyr/subsys/(fb|fs|app_memory|fs|blueooth|console|cpp|debug|dfu|disk|fb|fs|mgmt|net|random|settings|shell|stats|storage|usb)/.*$"} +-file_tag+={out_of_initial_scope, "^zephyr/build/CMakeFiles/.*$"} +-file_tag+={external,out_of_initial_scope} +-doc_end diff --git a/cmake/sca/eclair/ECL/toolchain.ecl b/cmake/sca/eclair/ECL/toolchain.ecl new file mode 100644 index 0000000000000..9b8393e30a3ae --- /dev/null +++ b/cmake/sca/eclair/ECL/toolchain.ecl @@ -0,0 +1,85 @@ +# get the toolchain compiler and version from the environment +-setq=used_compiler,getenv("CC_ALIASES") + +# Compilers. +-file_tag+={GCC,"^used_compiler$"} +# -file_tag+={GXX,"^/opt/zephyr-sdk-0\\.13\\.2/arm-zephyr-eabi/bin/arm-zephyr-eabi-g\\+\\+$"} + +# Manuals. +-setq=GCC_MANUAL,"https://gcc.gnu.org/onlinedocs/gcc-10.3.0/gcc.pdf" +-setq=CPP_MANUAL,"https://gcc.gnu.org/onlinedocs/gcc-10.3.0/cpp.pdf" +-setq=C99_STD,"ISO/IEC 9899:1999" + +-doc_begin=" + See Chapter \"6 Extensions to the C Language Family\" of "GCC_MANUAL": + __auto_type: see \"6.7 Referring to a Type with typeof\"; + __asm__: see \"6.48 Alternate Keywords\", and \"6.47 How to Use Inline Assembly Language in C Code\"; + __attribute__: see \"6.39 Attribute Syntax\"; + __typeof__: see \"6.7 Referring to a Type with typeof\"; + __builtin_types_compatible_p: see \"6.59 Other Built-in Functions Provided by GCC\"; + __volatile__: see \"6.48 Alternate Keywords\" and \"6.47.2.1 Volatile\"; + __alignof: see \"6.48 Alternate Keywords\" and \"6.44 Determining the Alignment of Functions, Types or +Variables\"; + __alignof__: see \"6.48 Alternate Keywords\" and \"6.44 Determining the Alignment of Functions, Types or +Variables\"; + __const__: see \"6.48 Alternate Keywords\"; + __inline: see \"6.48 Alternate Keywords\"; + _Generic: see description of option \"-Wc99-c11-compat\" in \"3.8 Options to Request or Suppress Warnings\". The compiler allows to C11 features in C99 mode; + _Static_assert: see descriptions of options \"-Wc99-c11-compat\" and \"-Wc99-c2x-compat\" in \"3.8 Options to Request or Suppress Warnings\". The compiler allows to use C11 and C2x features in C99 mode. +" +-config=STD.tokenext,behavior+={c99, GCC, "^(__auto_type|__asm__|__attribute__|__typeof__|__builtin_types_compatible_p|__volatile__|__alignof|__alignof__|__const__|__inline|_Generic|_Static_assert)$"} +-config=STD.tokenext,behavior+={c18, GCC, "^(__attribute__|__asm__|__const__|__volatile__|__inline)$"} +-doc_end + +-doc="See Chapter \"6.7 Referring to a Type with typeof\". of "GCC_MANUAL"." +-config=STD.diag,diagnostics={safe,"^ext_auto_type$"} +-doc="See Chapter \"6.1 Statements and Declarations in Expressions\" of "GCC_MANUAL"." +-config=STD.stmtexpr,behavior+={c99,GCC,specified} +-doc="See Chapter \"6.24 Arithmetic on void- and Function-Pointers\" of "GCC_MANUAL"." +-config=STD.vptrarth,behavior={c99,GCC,specified} +-doc_begin=" + ext_missing_varargs_arg: non-documented GCC extension. + ext_paste_comma: see Chapter \"6.21 Macros with a Variable Number of Arguments.\" of "GCC_MANUAL". + ext_flexible_array_in_array: see Chapter \"6.18 Arrays of Length Zero\" of "GCC_MANUAL". +" +-config=STD.diag,behavior+={c99,GCC,"^(ext_missing_varargs_arg|ext_paste_comma|ext_flexible_array_in_array)$"} +-config=STD.diag,behavior+={c18,GCC,"^(ext_missing_varargs_arg)$"} +-doc_end +-doc_begin="Non-documented GCC extension" +-config=STD.emptinit,behavior={c99,GCC,specified} +-config=STD.emptinit,behavior={c18,GCC,specified} +-doc_end +-doc_begin="See Chapter \"6.19 Structures with No Members\" of "GCC_MANUAL"." +-config=STD.emptrecd,behavior={c99,GCC,specified} +-config=STD.emptrecd,behavior={c18,GCC,specified} +-doc_end +-doc="See Chapter \"6.18 Arrays of Length Zero\" of "GCC_MANUAL"." +-config=STD.arayzero,behavior={c99,GCC,specified} + +-config=STD.inclnest,behavior+={c99, GCC, 24} +-config=STD.ppifnest,behavior+={c99, GCC, 32} +-config=STD.macident,behavior+={c99, GCC, 4096} + +-doc_begin="Allowed headers in freestanding mode." +-config=STD.freestlb,behavior+={c99,GCC,"^(string|fcntl|time|errno|ctype|stdio|inttypes|stdlib).h$"} +-config=STD.freestlb,behavior+={c18,GCC,"^(string|errno|inttypes).h$"} +-doc_end + +-doc_begin="See Annex \"J.5.7 Function pointer casts\" of "C99_STD"." +-config=STD.funojptr,behavior={c99,GCC,specified} +-doc_end + +-doc_begin="The maximum size of an object is defined in the MAX_SIZE macro, and for a 32 bit architecture is 8MB. + The maximum size for an array is defined in the PTRDIFF_MAX and in a 32 bit architecture is 2^30-1." +-config=STD.byteobjt,behavior={c99, GCC, 8388608} +-doc_end + +-doc_begin="See Section \"6.62.13 Diagnostic Pragmas\" of "GCC_MANUAL"." +-config=STD.nonstdc,behavior+={c99, GCC, "^GCC diagnostic (push|pop|ignored \"-W.*\")$"} +-config=STD.nonstdc,behavior+={c18, GCC, "^GCC diagnostic (push|pop|ignored \"-W.*\")$"} +-doc_end + +-doc_begin="See Section \"4.9 Structures, Unions, Enumerations, and Bit-Fields\" of "GCC_MANUAL". Other integer types, such as long int, and enumerated types are permitted even in strictly conforming mode." +-config=STD.bitfldtp,behavior+={c99, GCC, "unsigned char||unsigned short"} +-config=STD.bitfldtp,behavior+={c18, GCC, "unsigned char||unsigned short"} +-doc_end diff --git a/cmake/sca/eclair/ECL/zephyr_common_config.ecl b/cmake/sca/eclair/ECL/zephyr_common_config.ecl new file mode 100644 index 0000000000000..38168274cdf6a --- /dev/null +++ b/cmake/sca/eclair/ECL/zephyr_common_config.ecl @@ -0,0 +1,121 @@ +-eval_file=out_of_initial_scope.ecl +-eval_file=language_extensions.ecl +-eval_file=call_properties.ecl +-eval_file=extra.ecl + +-doc="Hides all reports that have all areas out of scope." +-reports+={hide,all_exp_external} + +-doc="The API interface files are allowed to contain unused macros." +-config=MC3R1.R2.5,reports+={hide, "any_area(macro(loc(top(public()||kind(pseudo)))))"} + +-doc="Several header files are meant to be included in C as well as in C++ translation units." +-config=MC3R1.R20.1,exception=extern_C + +-default_call_properties+="pointee_read(1..=never)" +-default_call_properties+="pointee_write(1..=always)" +-default_call_properties+="taken()" + +-doc_begin="These macros pass its first argument in a safe way to related compiler intrinsics." +-config=MC3R1.R20.7,macros={safe,"^(va_start||va_arg)$"} +-doc_end + +-doc_begin="The value-preserving conversions of integer constants are safe" +-config=MC3R1.R10.1,etypes={safe,"any()","preserved_integer_constant()"} +-config=MC3R1.R10.3,etypes={safe,"any()","preserved_integer_constant()"} +-config=MC3R1.R10.4,etypes={safe,"any()","preserved_integer_constant()||sibling(rhs,preserved_integer_constant())"} +-doc_end + +-doc_begin="Some macros are deliberately compile-time constants due to project configurability." +-macro_selector={const_wrapper_macros,"name(CONSTEXPR)"} +-config=MC3R1.R14.3,statements={safe, "node(if_stmt||conditional_operator)&&child(cond,wrapped(node(paren_expr)&&!macro(const_wrapper_macros), macro(const_wrapper_macros)))"} +-doc_end + +-doc="Casts to log_arg_t in logging macros are safe and expected." +-config=MC3R1.R11.6,reports+={deliberate,"any_area(any_loc(any_exp(macro(name(__LOG_ARG_CAST)))))"} + +-doc_begin="The following function-like macros are not writable as inline functions." +-config=MC3R1.D4.9,macros+={deliberate,"name(ARG_UNUSED)"} +-config=MC3R1.D4.9,macros+={deliberate,"name(CONSTEXPR)"} +-config=MC3R1.D4.9,macros+={deliberate,"name(compiler_barrier)"} +-config=MC3R1.D4.9,macros+={deliberate,"name(likely)"} +-config=MC3R1.D4.9,macros+={deliberate,"name(unlikely)"} +-doc_end + +-doc_begin="For the following function-like macros it should be decided whether substitution with equivalent static inline functions is wanted and feasible." +-config=MC3R1.D4.9,macros+={questionable,"name(ATOMIC_ELEM)"} +-config=MC3R1.D4.9,macros+={questionable,"name(ATOMIC_MASK)"} +-config=MC3R1.D4.9,macros+={questionable,"name(BIT32)"} +-config=MC3R1.D4.9,macros+={questionable,"name(BIT64)"} +-config=MC3R1.D4.9,macros+={questionable,"name(BIT64_MASK)"} +-config=MC3R1.D4.9,macros+={questionable,"name(BIT_MASK)"} +-config=MC3R1.D4.9,macros+={questionable,"name(DEVICE_MMIO_GET)"} +-config=MC3R1.D4.9,macros+={questionable,"name(DEVICE_MMIO_MAP)"} +-config=MC3R1.D4.9,macros+={questionable,"name(DEVICE_MMIO_RAM_PTR)"} +-config=MC3R1.D4.9,macros+={questionable,"name(IN)"} +-config=MC3R1.D4.9,macros+={questionable,"name(LOG_CORE_INIT)"} +-config=MC3R1.D4.9,macros+={questionable,"name(MAX)"} +-config=MC3R1.D4.9,macros+={questionable,"name(MB)"} +-config=MC3R1.D4.9,macros+={questionable,"name(MIN)"} +-config=MC3R1.D4.9,macros+={questionable,"name(OUT)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_BDF)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_BDF_TO_BUS)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_BAR_64)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_BAR_ADDR)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_BAR_INVAL_FLAGS)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_BAR_IO)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_BAR_MEM)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_CAPPTR_FIRST)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_CAP_ID)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_CAP_NEXT)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_EXT_CAP_ID)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_EXT_CAP_NEXT)"} +-config=MC3R1.D4.9,macros+={questionable,"name(PCIE_CONF_INTR_IRQ)"} +-config=MC3R1.D4.9,macros+={questionable,"name(POINTER_TO_UINT)"} +-config=MC3R1.D4.9,macros+={questionable,"name(ROUND_DOWN)"} +-config=MC3R1.D4.9,macros+={questionable,"name(ROUND_UP)"} +-config=MC3R1.D4.9,macros+={questionable,"name(UINT_TO_POINTER)"} +-config=MC3R1.D4.9,macros+={questionable,"name(Z_BOOT_VIRT_TO_PHYS)"} +-config=MC3R1.D4.9,macros+={questionable,"name(Z_IRQ_TO_INTERRUPT_VECTOR)"} +-config=MC3R1.D4.9,macros+={questionable,"name(Z_KERNEL_STACK_SIZE_ADJUST)"} +-config=MC3R1.D4.9,macros+={questionable,"name(Z_LOG_MSG2_ALIGNED_WLEN)"} +-config=MC3R1.D4.9,macros+={questionable,"name(Z_MEM_PHYS_ADDR)"} +-config=MC3R1.D4.9,macros+={questionable,"name(Z_MEM_VIRT_ADDR)"} +-config=MC3R1.D4.9,macros+={questionable,"name(Z_STACK_PTR_ALIGN)"} +-config=MC3R1.D4.9,macros+={questionable,"name(Z_THREAD_STACK_SIZE_ADJUST)"} +-config=MC3R1.D4.9,macros+={questionable,"name(Z_TICK_ABS)"} +-config=MC3R1.D4.9,macros+={questionable,"name(ceiling_fraction)"} +-config=MC3R1.D4.9,macros+={questionable,"name(irq_enable)"} +-config=MC3R1.D4.9,macros+={questionable,"name(irq_lock)"} +-config=MC3R1.D4.9,macros+={questionable,"name(irq_unlock)"} +-config=MC3R1.D4.9,macros+={questionable,"name(k_panic)"} +-doc_end + +-doc="Use of CODE_UNREACHABLE is defensive programming." +-config=MC3R1.R2.1,reports+={safe,"any_area(any_loc(any_exp(macro(name(CODE_UNREACHABLE)))))"} + +-doc_begin="Identifers beginning with _ are tolerated." +-config=MC3R1.R21.1,macros={relied,"^_.*$"} +-config=MC3R1.R21.2,declarations={relied,"^(.*::)?_.*$"} +-doc_end + +-eval_file=adopted_code.ecl +-eval_file=adopted_deviations.ecl + +-doc="Hide reports marked as compliant." +-remap_rtag={compliant,hide} + +-doc="Hide reports marked as safe." +-remap_rtag={safe,hide} + +-doc="Hide reports marked as relied." +-remap_rtag={relied,hide} + +-doc="Hide reports marked as questionable." +-remap_rtag={questionable,hide} + +-doc="Hide reports marked as deliberate." +-remap_rtag={deliberate,hide} + +-doc="Hide reports marked as disapplied." +-remap_rtag={disapplied,hide} diff --git a/cmake/sca/eclair/eclair.template b/cmake/sca/eclair/eclair.template new file mode 100644 index 0000000000000..fd7b0fe8b77d3 --- /dev/null +++ b/cmake/sca/eclair/eclair.template @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2024, Baumer (www.baumer.com) + +# Everything before `--` are arguments for cmake invocation, those must be ignored. +# The first argument after `--` is the start of the compiler call, which is +# what we want to get to invoke ECLAIR with the compiler call which is used in the zephyr +# environment +foreach(i RANGE ${CMAKE_ARGC}) + if("${CMAKE_ARGV${i}}" STREQUAL "--") + math(EXPR end_of_options "${i} + 1") + break() + endif() +endforeach() + +foreach(i RANGE ${end_of_options} ${CMAKE_ARGC}) + list(APPEND ZEPHYR_COMPILER_CALL ${CMAKE_ARGV${i}}) +endforeach() + +list(APPEND ECLAIR_ARGS +incremental + -project_name=@ECLAIR_PROJECT_NAME@ -project_root=@ZEPHYR_BASE@ + -eval_file=@ECLAIR_ECL_DIR@/analysis.ecl + -eval_file=@ECLAIR_ANALYSIS_ECL_DIR@/analysis_@ECLAIR_RULESET@.ecl + @ECLAIR_ENV_ADDITIONAL_OPTIONS@) + +execute_process( + COMMAND @CMAKE_COMMAND@ -E env + ECLAIR_DIAGNOSTICS_OUTPUT=@ECLAIR_DIAGNOSTICS_OUTPUT@ + ECLAIR_DATA_DIR=@ECLAIR_ANALYSIS_DATA_DIR@ + CC_ALIASES=@CC_ALIASES@ + CXX_ALIASES=@CXX_ALIASES@ + AS_ALIASES=@AS_ALIASES@ + LD_ALIASES=@LD_ALIASES@ + AR_ALIASES=@AR_ALIASES@ + @ECLAIR_ENV@ ${ECLAIR_ARGS} -- ${ZEPHYR_COMPILER_CALL} + COMMAND_ERROR_IS_FATAL ANY +) diff --git a/cmake/sca/eclair/sca.cmake b/cmake/sca/eclair/sca.cmake new file mode 100644 index 0000000000000..8dbc8a42f976a --- /dev/null +++ b/cmake/sca/eclair/sca.cmake @@ -0,0 +1,141 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023, BUGSENG Srl + +find_program(ECLAIR_ENV eclair_env REQUIRED) +message(STATUS "Found eclair_env: ${ECLAIR_ENV}") + +find_program(ECLAIR_REPORT eclair_report REQUIRED) +message(STATUS "Found eclair_report: ${ECLAIR_REPORT}") + +if(ECLAIR_OPTIONS_FILE) + if(IS_ABSOLUTE ${ECLAIR_OPTIONS_FILE}) + set(ECLAIR_OPTIONS ${ECLAIR_OPTIONS_FILE}) + else() + set(ECLAIR_OPTIONS ${APPLICATION_CONFIG_DIR}/${ECLAIR_OPTIONS_FILE}) + endif() + include(${ECLAIR_OPTIONS}) +else() + include(${CMAKE_CURRENT_LIST_DIR}/sca_options.cmake) +endif() + +# ECLAIR Settings +set(ECLAIR_PROJECT_NAME "Zephyr-${BOARD}${BOARD_QUALIFIERS}") +set(ECLAIR_OUTPUT_DIR "${CMAKE_BINARY_DIR}/sca/eclair") +set(ECLAIR_ECL_DIR "${ZEPHYR_BASE}/cmake/sca/eclair/ECL") +set(ECLAIR_ANALYSIS_ECL_DIR "${ZEPHYR_BASE}/cmake/sca/eclair/ECL") +set(ECLAIR_DIAGNOSTICS_OUTPUT "${ECLAIR_OUTPUT_DIR}/DIAGNOSTIC.txt") +set(ECLAIR_ANALYSIS_DATA_DIR "${ECLAIR_OUTPUT_DIR}/analysis_data") +set(ECLAIR_PROJECT_ECD "${ECLAIR_OUTPUT_DIR}/PROJECT.ecd") +set(CC_ALIASES "${CMAKE_C_COMPILER}") +set(CXX_ALIASES "${CMAKE_CXX_COMPILER}") +set(AS_ALIASES "${CMAKE_AS}") +set(LD_ALIASES "${CMAKE_LINKER}") +set(AR_ALIASES "${CMAKE_ASM_COMPILER_AR} ${CMAKE_C_COMPILER_AR} ${CMAKE_CXX_COMPILER_AR}") + +set(ECLAIR_ENV_ADDITIONAL_OPTIONS "") +set(ECLAIR_REPORT_ADDITIONAL_OPTIONS "") + +# Default value +set(ECLAIR_RULESET first_analysis) + +# ECLAIR env +if(ECLAIR_RULESET_FIRST_ANALYSIS) + set(ECLAIR_RULESET first_analysis) +elseif(ECLAIR_RULESET_STU) + set(ECLAIR_RULESET STU) +elseif(ECLAIR_RULESET_STU_HEAVY) + set(ECLAIR_RULESET STU_heavy) +elseif(ECLAIR_RULESET_WP) + set(ECLAIR_RULESET WP) +elseif(ECLAIR_RULESET_STD_LIB) + set(ECLAIR_RULESET std_lib) +elseif(ECLAIR_RULESET_USER) + set(ECLAIR_RULESET ${ECLAIR_USER_RULESET_NAME}) + if(IS_ABSOLUTE ${ECLAIR_USER_RULESET_PATH}) + set(ECLAIR_ANALYSIS_ECL_DIR ${ECLAIR_USER_RULESET_PATH}) + else() + set(ECLAIR_ANALYSIS_ECL_DIR ${APPLICATION_CONFIG_DIR}/${ECLAIR_USER_RULESET_PATH}) + endif() +endif() + +# ECLAIR report +if (ECLAIR_METRICS_TAB) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-metrics_tab=${ECLAIR_OUTPUT_DIR}/metrics") +endif() +if (ECLAIR_REPORTS_TAB) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-reports_tab=${ECLAIR_OUTPUT_DIR}/reports") +endif() +if (ECLAIR_REPORTS_SARIF) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-reports_sarif=${ECLAIR_OUTPUT_DIR}/reports.sarif") +endif() +if (ECLAIR_SUMMARY_TXT) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-summary_txt=${ECLAIR_OUTPUT_DIR}/summary_txt") +endif() +if (ECLAIR_SUMMARY_DOC) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-summary_doc=${ECLAIR_OUTPUT_DIR}/summary_doc") +endif() +if (ECLAIR_SUMMARY_ODT) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-summary_odt=${ECLAIR_OUTPUT_DIR}/summary_odt") +endif() +if (ECLAIR_FULL_TXT_ALL_AREAS) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-setq=report_areas,areas") +endif() +if (ECLAIR_FULL_TXT_FIRST_AREA) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-setq=report_areas,first_area") +endif() +if (ECLAIR_FULL_TXT) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-full_txt=${ECLAIR_OUTPUT_DIR}/report_full_txt") +endif() +if (ECLAIR_FULL_DOC_ALL_AREAS) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-setq=report_areas,areas") +endif() +if (ECLAIR_FULL_DOC_FIRST_AREA) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-setq=report_areas,first_area") +endif() +if (ECLAIR_FULL_DOC) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-full_doc=${ECLAIR_OUTPUT_DIR}/report_full_doc") +endif() +if (ECLAIR_FULL_ODT) + list(APPEND ECLAIR_REPORT_ADDITIONAL_OPTIONS "-full_odt=${ECLAIR_OUTPUT_DIR}/report_full_odt") +endif() + +message(STATUS "ECLAIR outputs have been written to: ${ECLAIR_OUTPUT_DIR}") +message(STATUS "ECLAIR ECB files have been written to: ${ECLAIR_ANALYSIS_DATA_DIR}") + +add_custom_target(eclair_setup_analysis_dir ALL + COMMAND ${CMAKE_COMMAND} -E remove_directory ${ECLAIR_ANALYSIS_DATA_DIR} + COMMAND ${CMAKE_COMMAND} -E make_directory ${ECLAIR_ANALYSIS_DATA_DIR} + VERBATIM + USES_TERMINAL +) + +# configure the camke script which will be used to replace the compiler call with the eclair_env +# call which calls the compiler and to generate analysis files. +configure_file(${CMAKE_CURRENT_LIST_DIR}/eclair.template ${ECLAIR_OUTPUT_DIR}/eclair.cmake @ONLY) + +set(launch_environment ${CMAKE_COMMAND} -P ${ECLAIR_OUTPUT_DIR}/eclair.cmake --) +set(CMAKE_C_COMPILER_LAUNCHER ${launch_environment} CACHE INTERNAL "") + +# This target is used to generate the ECLAIR database when all the compilation is done and the +# elf file was generated with this we cane make sure that the analysis is completed. +add_custom_target(eclair_report ALL + COMMAND ${CMAKE_COMMAND} -E env + ECLAIR_DATA_DIR=${ECLAIR_ANALYSIS_DATA_DIR} + ECLAIR_OUTPUT_DIR=${ECLAIR_OUTPUT_DIR} + ECLAIR_PROJECT_ECD=${ECLAIR_PROJECT_ECD} + ${ECLAIR_REPORT} -quiet -eval_file=${ECLAIR_ECL_DIR}/db_generation.ecl + DEPENDS ${CMAKE_BINARY_DIR}/zephyr/zephyr.elf + VERBATIM + USES_TERMINAL + COMMAND_EXPAND_LISTS +) + +# This command is used to generate the final reports from the database and print the overall results +add_custom_target(eclair_summary_print ALL + COMMAND ${ECLAIR_REPORT} + -db=${ECLAIR_PROJECT_ECD} ${ECLAIR_REPORT_ADDITIONAL_OPTIONS} + -overall_txt=${ECLAIR_OUTPUT_DIR}/summary_overall.txt + COMMAND ${CMAKE_COMMAND} -E cat ${ECLAIR_OUTPUT_DIR}/summary_overall.txt +) +add_dependencies(eclair_summary_print eclair_report) diff --git a/cmake/sca/eclair/sca_options.cmake b/cmake/sca/eclair/sca_options.cmake new file mode 100644 index 0000000000000..2402b0e8446c8 --- /dev/null +++ b/cmake/sca/eclair/sca_options.cmake @@ -0,0 +1,34 @@ +include(CMakeDependentOption) + +option(ECLAIR_RULESET_FIRST_ANALYSIS "A tiny selection of the projects coding guideline rules to + verify that everything is correctly working" ON) + +option(ECLAIR_RULESET_STU "Selection of the projects coding guidelines, which can be verified + by analysing the single translation units independently." OFF) + +option(ECLAIR_RULESET_STU_HEAVY "Selection of complex STU project coding guidelines that + require a significant amount of time" OFF) +option(ECLAIR_RULESET_WP "All whole program project coding guidelines ('system' in MISRA's + parlance)." OFF) +option(ECLAIR_RULESET_STD_LIB "Project coding guidelines about the C Standard Library" OFF) +option(ECLAIR_RULESET_USER "User defined ruleset" OFF) + +option(ECLAIR_METRICS_TAB "Metrics in a spreadsheet format" OFF) +option(ECLAIR_REPORTS_TAB "Findings in a spreadsheet format" OFF) +option(ECLAIR_REPORTS_SARIF "Findings in sarif JSON format" ON) +option(ECLAIR_SUMMARY_TXT "Plain textual summary format" OFF) +option(ECLAIR_SUMMARY_DOC "DOC summary format" OFF) +option(ECLAIR_SUMMARY_ODT "ODT summary format" OFF) +option(ECLAIR_FULL_TXT "Detailed plain textual format" ON) +option(ECLAIR_FULL_DOC "Detailed DOC format" OFF) +option(ECLAIR_FULL_ODT "Detailed ODT format" OFF) + +cmake_dependent_option(ECLAIR_FULL_DOC_ALL_AREAS "Show all areas in a full doc report" + OFF "ECLAIR_FULL_DOC OR ECLAIR_FULL_ODT" OFF) +cmake_dependent_option(ECLAIR_FULL_DOC_FIRST_AREA "Show only the first area in a full doc report" + ON "ECLAIR_FULL_DOC OR ECLAIR_FULL_ODT" OFF) + +cmake_dependent_option(ECLAIR_FULL_TXT_ALL_AREAS "Show all areas in a full text report" + OFF "ECLAIR_FULL_TXT" OFF) +cmake_dependent_option(ECLAIR_FULL_TXT_FIRST_AREA "Show only the first area in a full text report" + ON "ECLAIR_FULL_TXT" OFF) diff --git a/doc/develop/sca/eclair.rst b/doc/develop/sca/eclair.rst new file mode 100644 index 0000000000000..f47d861d7650a --- /dev/null +++ b/doc/develop/sca/eclair.rst @@ -0,0 +1,155 @@ +.. _eclair: + +ECLAIR support +############## + +Bugseng `ECLAIR `__ is a certified +static analysis tool and platform for software verification. +Applications range from coding rule validation, with a +particular emphasis on the MISRA and BARR-C coding standards, to the +computation of software metrics, to the checking of independence and +freedom from interference among software components, to the automatic +detection of important classes of software errors. + +.. important:: + + ECLAIR is a commercial tool, and it is not free software. + You need to have a valid license to use it. + +Running ECLAIR +************** + +To run ECLAIR, :ref:`west build ` should be +called with a ``-DZEPHYR_SCA_VARIANT=eclair`` parameter. + +.. code-block:: shell + + west build -b mimxrt1064_evk samples/basic/blinky -- -DZEPHYR_SCA_VARIANT=eclair + +.. note:: + This will only invoke the ECLAIR analysis with the predefined ruleset ``first_analysis``. If you + want to use a different ruleset, you need to provide a configuration file. See the next section + for more information. + +Configurations +************** + +The configure of the ECLAIR SCA environment can either be done via a cmake options file or with +adapted options as command line arguments. + +To invoke a cmake options file into the ECLAIR call, you can define the ``ECLAIR_OPTIONS_FILE`` +variable, for example: + +.. code-block:: shell + + west build -b mimxrt1064_evk samples/basic/blinky -- -DZEPHYR_SCA_VARIANT=eclair -DECLAIR_OPTIONS_FILE=my_options.cmake + +The default (if no config file is given) configuration is always ``first_analysis``, +which is a tiny selection of rules to verify that everything is correctly working. + +If the default configuration wants to be overwritten via the command line and not via a options +file, that can be achived by giving the argument ``-DOption=ON|OFF``. + +For example: + +.. code-block:: shell + + west build -b mimxrt1064_evk samples/basic/blinky -- -DZEPHYR_SCA_VARIANT=eclair -DECLAIR_REPORTS_SARIF=ON + +Zephyr is a large and complex project, so the configuration sets are split the +Zephyr's guidelines selection +(taken from https://docs.zephyrproject.org/latest/contribute/coding_guidelines/index.html) +in five sets to make it more digestible to use on a private machine: + +* first_analysis (default): a tiny selection of the projects coding guidelines to verify that + everything is correctly working. + +* STU: Selection of the projects coding guidelines, which can be verified by analysing the single + translation units independently. + +* STU_heavy: Selection of complex STU project coding guidelines that require a significant amount + of time. + +* WP: All whole program project coding guidelines ("system" in MISRA's parlance). + +* std_lib: Project coding guidelines about the C Standard Library. + +Related cmake options: + +* ``ECLAIR_RULESET_FIRST_ANALYSIS`` +* ``ECLAIR_RULESET_STU`` +* ``ECLAIR_RULESET_STU_HEAVY`` +* ``ECLAIR_RULESET_WP`` +* ``ECLAIR_RULESET_STD_LIB`` + +User defined ruleset +==================== + +If you want to use your own defined ruleset instead of the predefined zephyr coding guidelines +rulesets. You can do so by setting :code:`ECLAIR_RULESET_USER=ON`. +Created your own rulset file for ECLAIR with the following naming format: +``analysis_.ecl``. After creating the file define the name of the ruleset for ECLAIR +with the cmake variable :code:`ECLAIR_USER_RULESET_NAME`. +If the ruleset file is not in the application source directory, you can define the path to the +ruleset file with the cmake variable :code:`ECLAIR_USER_RULESET_PATH`. This configuration takes +relative paths and absolute paths. + +Related cmake options and variables: + +* ``ECLAIR_RULESET_USER`` +* ``ECLAIR_USER_RULESET_NAME`` +* ``ECLAIR_USER_RULESET_PATH`` + +Generate additional report formats +********************************** + +ECLAIR can generate additional report formats (e.g. DOC, ODT, XLSX) and +different variants of repots in addition to the +default ecd file. Following additional reports and report formats can be generated: + +* Metrics in spreadsheet format. + +* Findings in spreadsheet format. + +* Findings in SARIF format. + +* Summary report in plain textual format. + +* Summary report in DOC format. + +* Summary report in ODT format. + +* Detailed reports in txt format. + +* Detailed report in DOC format. + +* Detailed report in ODT format. + +Related cmake options: + +* ``ECLAIR_METRICS_TAB`` +* ``ECLAIR_REPORTS_TAB`` +* ``ECLAIR_REPORTS_SARIF`` +* ``ECLAIR_SUMMARY_TXT`` +* ``ECLAIR_SUMMARY_DOC`` +* ``ECLAIR_SUMMARY_ODT`` +* ``ECLAIR_FULL_TXT`` +* ``ECLAIR_FULL_DOC`` +* ``ECLAIR_FULL_ODT`` + +Detail level of full reports +============================ + +The detail level of the txt and doc full reports can also be adapted by a configuration. +In this case the following configurations are avilable: + +* Show all areas + +* Show only the first area + +Related cmake options: + +* ``ECLAIR_FULL_DOC_ALL_AREAS`` +* ``ECLAIR_FULL_DOC_FIRST_AREA`` +* ``ECLAIR_FULL_TXT_ALL_AREAS`` +* ``ECLAIR_FULL_TXT_FIRST_AREA`` diff --git a/doc/develop/sca/index.rst b/doc/develop/sca/index.rst index 0a47143923507..f06bc8e43cd25 100644 --- a/doc/develop/sca/index.rst +++ b/doc/develop/sca/index.rst @@ -65,3 +65,4 @@ The following is a list of SCA tools natively supported by Zephyr build system. sparse gcc cpptest + eclair