-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ASAN #1394
base: main
Are you sure you want to change the base?
Add ASAN #1394
Conversation
On MacOS running an AVM shows a warning "malloc: nano zone abandoned due to inability to reserve vm space.". To avoid this warning, set MallocNanoZone=0 env variable. Also adds debug symbols when compiling with Clang. Signed-off-by: Jakub Gonet <[email protected]>
I do use ASAN in a stash as well. |
...or we can ignore for the time being, running |
@@ -35,6 +35,7 @@ option(AVM_RELEASE "Build an AtomVM release" OFF) | |||
option(AVM_CREATE_STACKTRACES "Create stacktraces" ON) | |||
option(AVM_BUILD_RUNTIME_ONLY "Only build the AtomVM runtime" OFF) | |||
option(COVERAGE "Build for code coverage" OFF) | |||
option(ENABLE_ASAN "Use Address Sanitizer" ON) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this should be the default: it is very useful during development, but it should be off during release.
Also I'm not sure how interacts with platforms that do not properly support -fsanitize=address
such as ESP32.
So maybe it should be manually enabled (and we might suggest it in our documentation) and of course we should add a job in our CI that enables it. After all what really matter is not merging code that fails those checks.
I think we should have jobs and options for undefined behavior sanitizer, thread sanitizer and memory sanitizer and they should be part of our CI as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. I don't have means to test embedded platforms so most of my testing comes from unix and WASM port.
What do you think about adding
set(SANITIZER none) # available values: address, memory, undefined, none
and corresponding ifs in libAtomVM CMakeList?
Is there any way to create local CMakeLists or you need to use env variables when running CMake to set those options?
@@ -120,7 +120,7 @@ target_compile_features(libAtomVM PUBLIC c_std_11) | |||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU") | |||
target_compile_options(libAtomVM PUBLIC -Wall ${MAYBE_PEDANTIC_FLAG} ${MAYBE_WERROR_FLAG} -Wextra -ggdb -Werror=incompatible-pointer-types) | |||
elseif (CMAKE_C_COMPILER_ID MATCHES "Clang") | |||
target_compile_options(libAtomVM PUBLIC -Wall --extra-warnings -Werror=incompatible-pointer-types ${MAYBE_WERROR_FLAG}) | |||
target_compile_options(libAtomVM PUBLIC -Wall --extra-warnings -Werror=incompatible-pointer-types -g ${MAYBE_WERROR_FLAG}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that -g
is already the default when building with cmake in Debug mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is build mode dictated by DEBUG env variable? I couldn't find reference to debug/release in the code.
@@ -132,6 +132,11 @@ if (ADVANCED_TRACING) | |||
target_compile_definitions(libAtomVM PUBLIC ENABLE_ADVANCED_TRACE) | |||
endif() | |||
|
|||
if(ENABLE_ASAN) | |||
target_compile_options(libAtomVM PUBLIC -fsanitize=address -fno-omit-frame-pointer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is -fno-omit-frame-pointer
cross platform? I remember that was something quite common on i386 that has few available registers, but I think it is not the default on several platforms (and maybe it is not even available as an option on other archs).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. Logically, omitting frame pointer is an optimization so every platform should support that (making one less available register if disabled) but from reading GCC docs it's noop on archs that don't benefit from it.
https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Optimize-Options.html
look for -fomit-frame-pointer
I'm not a huge fan of this workaround, I would rather go for the clean way. By the way, isn't adding free() on that loop an option? |
From reading the code, we malloc ASAN does report it as a violation even at exit (typically OS collects unfreed memory by then) and I didn't find any way to skip reporting exit-freed allocations. |
I tried [1] but then it started crashing on my PC with sanitize=memory. Also I feel like we are leaking file descriptors too. [1] --- a/tools/packbeam/packbeam.c
+++ b/tools/packbeam/packbeam.c
@@ -271,6 +271,8 @@ static int do_pack(int argc, char **argv, int is_archive, bool include_lines)
char *filename = basename(argv[i]);
pack_beam_file(pack, file_data, file_size, filename, !is_archive && i == 1, include_lines);
}
+
+ free(file_data);
}
add_module_header(pack, "end", END_OF_FILE); |
I spent ~2h on this draft, this is how I'd rewrite the file (I didn't run it at all, so expect errors if you want to work on it further). It isn't the most readable code but I'm not a C expert. Bubbling the errors up is really painful. Related: what's your opinion on Zig? :P We leak descriptors and memory mostly when checking if files are AVM or BEAM ones. We also do a bit of unnecessary full file reads. I think it would be nice to mmap all of them instead of doing a mix of mmap and fopens. |
It was immensely helpful when developing so I'm opting to run it by default. Open to discussion, though.
On MacOS running an AVM shows a warning "malloc: nano zone abandoned due to inability to reserve vm space.". To avoid this warning, set
MallocNanoZone=0
env variable before running the VM.Also adds debug symbols when compiling with Clang.
These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later