Using GCC Undefined Behavior Sanitizer
Asked Answered
H

2

28

Today I have read an article about GCC Undefined Behavior Sanitizer (ubsan). However, when I follow steps there (add -fsanitize=undefined to my code), the compiler (GCC 4.9.2 on Ubuntu 15.04) says that some references are not defined:

||=== Build: Debug in Project (compiler: GNU GCC Compiler) ===|
obj/Debug/App.o||In function `App::OnInit()':|
/home/ilya/Project/App.cpp|31|undefined reference to `__ubsan_handle_type_mismatch'|
/home/ilya/Project/App.cpp|31|undefined reference to `__ubsan_handle_load_invalid_value'|
...
obj/Debug/App.o||In function `wxObjectEventFunctor::operator()(wxEvtHandler*, wxEvent&)':|
/usr/include/wx-3.0/wx/event.h|3757|undefined reference to `__ubsan_handle_add_overflow'|
obj/Debug/App.o||In function `std::_Vector_base<unsigned long long, std::allocator<unsigned long long> >::~_Vector_base()':|
/usr/include/c++/4.9/bits/stl_vector.h|161|undefined reference to `__ubsan_handle_sub_overflow'|
...
||More errors follow but not being shown.|
||Edit the max errors limit in compiler options...|
||=== Build failed: 50 error(s), 0 warning(s) (0 minute(s), 23 second(s)) ===|

How can I fix this?

Highkeyed answered 4/8, 2015 at 7:57 Comment(3)
Give this a try. From a comment on the page you linked to: "Note, libubsan may not be installed on your system by default. On fedora 21+ install as follows: yum install libubsan"Poach
I have installed libubsan0 and lib64ubsan0, but nothing changed. Maybe I should link it somehow?Highkeyed
Yes, I've added a -lubsan option, and it worked! (^_^)Highkeyed
F
27

The article you cited, as seen at its new home, already provides the answer, but you didn't notice it :-) With bold mine:

GCC recently (version 4.9) gained Undefined Behavior Sanitizer (ubsan), a run-time checker for the C and C++ languages. In order to check your program with ubsan, compile and link the program with -fsanitize=undefined option.

I think the correct way to solve this is not to manually link with ubsan, but instead to simply also pass -fsanitize=undefined to the linker, not just the compiler. Sure, reinventing the wheel might work for you, but it's not needed, and there might be a reason that there is a specific linker flag for this, instead.

Certainly, that works: I was suddenly getting piles of undefined reference errors and, after giving up and just not using it for months, yugr's answer here pointed me in the right direction: I was only passing -fsanitize=undefined to meson.add_project_arguments(), but those only go to the compiler; I also needed to pass it to meson.add_project_link_arguments(). After adding that, the errors are gone, and the program links.

Ferri answered 13/10, 2018 at 13:33 Comment(3)
It's been a general rule for ages that all compilation flags should be passed in the link phase and the compiler/linker driver will ignore any that are not needed, so if meson does not just pass everything from project arguments to project link arguments, I'd tend to call it a bug.Diena
@JanHudec You might want to search Meson's issue tracker for such a bug then, or file it if there isn't one ;-) What I said is straight out of Meson's reference manual. Specifically, add_project_arguments() is documented in terms of add_global_arguments(), which "Adds the positional arguments to the compiler command line." - whereas add_global_link_arguments() and add_project_link_arguments() are documented as "Like add_global|project_arguments but the arguments are passed to the linker." - and tbh I have no opinion on it either wayFerri
Use b_sanitize=undefined instead of adding to both: mesonbuild.com/Builtin-options.html#base-optionsWhiz
H
16

I have installed libubsan0 and lib64ubsan0 and added -lubsan option, and my application compiled successfully!

Highkeyed answered 4/8, 2015 at 8:42 Comment(8)
I tried to add add_definitions("-fsanitize=undefined -lubsan") to my cmake, but still get the undefined reference error, even after installing the above two mentioned libraries, any ideas?Glenda
How did you install?Mersey
UBsan developers have always suggested (e.g. here) to avoid explicit -lubsan/-lasan/etc. and simply use -fsanitize=undefined both when compiling and linking code. One reason is that in case of clang UBSan runtime library consists of several different libraries with different names (not libubsan.so). Thus the underscore_d's answer is the correct one.Hamachi
@Hamachi what should I do if my compile and link steps are separate? how can I pass "-fsanitize=undefined" to ld? I would have to just pass "-lubsan_lib.so" right? where ubsan_lib.so is a file I would download and put somewhere that ld can find it?Chadwickchae
@ElliotGorokhovsky in general you should avoid explicit usage of ld (as it's not portable) and use gcc/clang driver for linking instead. To link with Asan/UBsan just add -fsanitize=... to LDFLAGS.Hamachi
@Hamachi Thanks. Unfortunately I am trying to get this to work in a large project where the link step is separate from the compile step: zephyrproject.org. Hopefully the LDFLAGS method will work.Chadwickchae
@ElliotGorokhovsky that's interesting. In that case I suggest to run gcc -v -fsanitize=... on a dummy file and see what flags ld is run with. On my system it's libasan_preinit.o --push-state --no-as-needed -lasan --pop-state (I told you, it's ugly).Hamachi
thanks, I'll try that and let you know what happens!Chadwickchae

© 2022 - 2024 — McMap. All rights reserved.