Skip to content

ODR Violation Checker

Script & CMake toolchain file for detecting violations of the One Definition Rule.

Given a command-line which includes object files and static libraries, compares the type, size and content of global symbols and reports discrepancies which indicate that the binary will have different definitions of the same symbol linked in.

If the first non-flag argument to odr-checker.py is the path to an executable or the name of an executable in PATH, and the ODR check succeeds, ODR checker will execute the program with the rest of the arguments.

For example, the command-line:

odr-checker.py -v g++ -o a.out main.o foo.o

Will first check for ODR violations between main.o and foo.o, and if none are found, execute g++ -o a.out main.o foo.o

Usage

Use with CMake

Simply use one of the provided toolchain files in your CMake command-line:

cmake -S somewhere -B __build -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=$PWD/components/sanitizers/odr-violation/enable-odr-checker.cmake

This will automatically pass linker command-lines to odr-checker.py, which will exit with an error status and halt the build process if there are ODR violations.

Note: CMAKE_PROJECT_TOP_LEVEL_INCLUDES is available from CMake 3.24 and newer versions.

Use as a standalone tool

The script can be used as a standalone tool:

usage: odr-checker.py [-h] [-v] [-vv] [-s] ...

positional arguments:
  command

optional arguments:
  -h, --help  show this help message and exit
  -v          show informational messages
  -vv         show debug messages
  -s          Suppress warning. Pass 0 or more times. May be comma separated. Choose from: ZeroSize (100), NoContent (101), TypeMismatch (102), SizeMismatch (103)

Exit status:
    * 255 in the case of user or internal error, or
    * The number of ODR violations up to a maximum of 254, or
    * The exit status of the executed program, if any

Example:
    odr-checker.py foo.o bar.o
    Scan foo.o and bar.o, then exit.

Example:
    odr-checker.py -vv gcc -o foobar main.o foo.o bar.o
    Enable verbose logging, scan main.o, foo.o and bar.o, then execute the gcc command.