Skip to content

Commit

Permalink
build: support Undefined Behavior Sanitizer
Browse files Browse the repository at this point in the history
Enable UBSan in GHA.

Building with debugoptimized forces -O2 and consumes too much memory
with UBSan, prefer -O0.

FIXME: the tracepoint framework has an issue in the registering code
(casting trace point callbacks as (void)(void) functions).

Signed-off-by: David Marchand <[email protected]>
  • Loading branch information
david-marchand committed Dec 20, 2024
1 parent 07604f2 commit 2b083d8
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 3 deletions.
25 changes: 23 additions & 2 deletions .ci/linux-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ catch_coredump() {
return 1
}

catch_ubsan() {
[ "$UBSAN" = "true" ] || return 0
grep -q UndefinedBehaviorSanitizer $2 2>/dev/null || return 0
grep -E "($1|UndefinedBehaviorSanitizer)" $2
return 1
}

cross_file=

if [ "$AARCH64" = "true" ]; then
Expand Down Expand Up @@ -92,7 +99,6 @@ fi

OPTS="$OPTS -Dplatform=generic"
OPTS="$OPTS -Ddefault_library=$DEF_LIB"
OPTS="$OPTS -Dbuildtype=$buildtype"
if [ "$STDATOMIC" = "true" ]; then
OPTS="$OPTS -Denable_stdatomic=true"
else
Expand All @@ -109,13 +115,27 @@ else
fi
OPTS="$OPTS -Dlibdir=lib"

buildtype=debugoptimized
sanitizer=
if [ "$ASAN" = "true" ]; then
OPTS="$OPTS -Db_sanitize=address"
sanitizer=${sanitizer:+$sanitizer,}address
fi

if [ "$UBSAN" = "true" ]; then
sanitizer=${sanitizer:+$sanitizer,}undefined
# UBSan takes too much memory with -O2
buildtype=plain
export UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=false
fi

if [ -n "$sanitizer" ]; then
OPTS="$OPTS -Db_sanitize=$sanitizer"
if [ "${CC%%clang}" != "$CC" ]; then
OPTS="$OPTS -Db_lundef=false"
fi
fi

OPTS="$OPTS -Dbuildtype=$buildtype"
OPTS="$OPTS -Dwerror=true"

if [ -d build ]; then
Expand Down Expand Up @@ -173,6 +193,7 @@ if [ "$RUN_TESTS" = "true" ]; then
configure_coredump
sudo meson test -C build --suite fast-tests -t 3 || failed="true"
catch_coredump
catch_ubsan DPDK:fast-tests build/meson-logs/testlog.txt
[ "$failed" != "true" ]
fi

Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jobs:
RISCV64: ${{ matrix.config.cross == 'riscv64' }}
RUN_TESTS: ${{ contains(matrix.config.checks, 'tests') }}
STDATOMIC: ${{ contains(matrix.config.checks, 'stdatomic') }}
UBSAN: ${{ contains(matrix.config.checks, 'ubsan') }}

strategy:
fail-fast: false
Expand All @@ -74,6 +75,10 @@ jobs:
compiler: clang
checks: asan+doc+tests
- os: ubuntu-22.04
compiler: clang
library: shared
checks: tests+ubsan
- os: ubuntu-20.04
compiler: gcc
library: static
cross: i386
Expand Down
16 changes: 16 additions & 0 deletions config/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,22 @@ if get_option('b_sanitize') == 'address' or get_option('b_sanitize') == 'address
endif
endif

if get_option('b_sanitize') == 'undefined' or get_option('b_sanitize') == 'address,undefined'
if is_windows
error('UBSan is not supported on windows')
endif

if cc.get_id() == 'gcc'
ubsan_dep = cc.find_library('ubsan', required: true)
if (not cc.links('int main(int argc, char *argv[]) { return 0; }',
dependencies: ubsan_dep))
error('broken dependency, "libubsan"')
endif
add_project_link_arguments('-lubsan', language: 'c')
dpdk_extra_ldflags += '-lubsan'
endif
endif

if get_option('default_library') == 'both'
error( '''
Unsupported value "both" for "default_library" option.
Expand Down
1 change: 1 addition & 0 deletions devtools/words-case.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ TSO
TTL
Tx
uAPI
UBSan
UDM
UDP
ULP
Expand Down
9 changes: 9 additions & 0 deletions lib/eal/include/rte_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,15 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
#define __rte_no_asan
#endif

/**
* Disable UndefinedBehaviorSanitizer on some code
*/
#ifdef RTE_CC_CLANG
#define __rte_no_ubsan __attribute__((no_sanitize("undefined")))
#else
#define __rte_no_ubsan
#endif

/*********** Macros for pointer arithmetic ********/

/**
Expand Down
8 changes: 7 additions & 1 deletion lib/eal/include/rte_trace_point.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,16 @@ typedef RTE_ATOMIC(uint64_t) rte_trace_point_t;
*/
#define RTE_TRACE_POINT_ARGS

#ifdef _RTE_TRACE_POINT_REGISTER_H_
#define __rte_trace_point_no_ubsan __rte_no_ubsan
#else
#define __rte_trace_point_no_ubsan
#endif

/** @internal Helper macro to support RTE_TRACE_POINT and RTE_TRACE_POINT_FP */
#define __RTE_TRACE_POINT(_mode, _tp, _args, ...) \
extern rte_trace_point_t __##_tp; \
static __rte_always_inline void \
static __rte_trace_point_no_ubsan __rte_always_inline void \
_tp _args \
{ \
__rte_trace_point_emit_header_##_mode(&__##_tp); \
Expand Down

0 comments on commit 2b083d8

Please sign in to comment.