Add Valgrind stack instrumentation

Our coroutine system can make debugging memory issues harder by not
following a standard stack allocation system.  We can get around this by
using valgrind's built-in stack instrumentation.  Each coroutine
registers a stack allocation allowing memcheck to recognize when
accesses are bounded.
This commit is contained in:
Seth Hillbrand 2019-08-10 08:26:23 -07:00
parent c836cc9cf8
commit 0b80c00678
2 changed files with 28 additions and 2 deletions

View File

@ -125,6 +125,10 @@ option( KICAD_BUILD_PARALLEL_CL_MP
"Build in parallel using the /MP compiler option (default OFF for safety reasons)" "Build in parallel using the /MP compiler option (default OFF for safety reasons)"
OFF ) OFF )
option( KICAD_USE_VALGRIND
"Build KiCad with valgrind stack tracking enabled."
OFF )
# when option KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES is enabled: # when option KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES is enabled:
# PYTHON_EXECUTABLE can be defined when invoking cmake # PYTHON_EXECUTABLE can be defined when invoking cmake
# ( use -DPYTHON_EXECUTABLE=<python path>/python.exe or python2 ) # ( use -DPYTHON_EXECUTABLE=<python path>/python.exe or python2 )
@ -161,6 +165,10 @@ set( CMAKE_POSITION_INDEPENDENT_CODE ON )
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Enable additional valgrind instrumentation for stack tracking in libcontext
if( KICAD_USE_VALGRIND )
add_definitions( -DKICAD_USE_VALGRIND )
endif()
# CMP0063: CMake < 3.3 does not handle hidden visibility for static libraries, # CMP0063: CMake < 3.3 does not handle hidden visibility for static libraries,
# and 3.3 is backwards compatible when the minimum version is smaller than 3.3. # and 3.3 is backwards compatible when the minimum version is smaller than 3.3.

View File

@ -31,6 +31,10 @@
#include <type_traits> #include <type_traits>
#ifdef KICAD_USE_VALGRIND
#include <valgrind/valgrind.h>
#endif
#include <system/libcontext.h> #include <system/libcontext.h>
#include <memory> #include <memory>
@ -65,8 +69,8 @@ private:
{ {
enum enum
{ {
FROM_ROOT, // a stub was called/a corutine was resumed from the main-stack context FROM_ROOT, // a stub was called/a coroutine was resumed from the main-stack context
FROM_ROUTINE, // a stub was called/a coroutine was resumed fron a coroutine context FROM_ROUTINE, // a stub was called/a coroutine was resumed from a coroutine context
CONTINUE_AFTER_ROOT // a function sent a request to invoke a function on the main CONTINUE_AFTER_ROOT // a function sent a request to invoke a function on the main
// stack context // stack context
} type; // invocation type } type; // invocation type
@ -140,11 +144,17 @@ public:
m_callContext( nullptr ), m_callContext( nullptr ),
m_callee( nullptr ), m_callee( nullptr ),
m_retVal( 0 ) m_retVal( 0 )
#ifdef KICAD_USE_VALGRIND
,valgrind_stack( 0 )
#endif
{ {
} }
~COROUTINE() ~COROUTINE()
{ {
#ifdef KICAD_USE_VALGRIND
VALGRIND_STACK_DEREGISTER( valgrind_stack );
#endif
} }
public: public:
@ -306,6 +316,10 @@ private:
// correct the stack size // correct the stack size
stackSize -= size_t( ( (ptrdiff_t) m_stack.get() + stackSize ) - (ptrdiff_t) sp ); stackSize -= size_t( ( (ptrdiff_t) m_stack.get() + stackSize ) - (ptrdiff_t) sp );
#ifdef KICAD_USE_VALGRIND
valgrind_stack = VALGRIND_STACK_REGISTER( sp, m_stack.get() );
#endif
#endif #endif
m_callee = libcontext::make_fcontext( sp, stackSize, callerStub ); m_callee = libcontext::make_fcontext( sp, stackSize, callerStub );
@ -389,6 +403,10 @@ private:
CALLEE_STORAGE m_callee; CALLEE_STORAGE m_callee;
ReturnType m_retVal; ReturnType m_retVal;
#ifdef KICAD_USE_VALGRIND
uint32_t valgrind_stack;
#endif
}; };
#endif #endif