aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2020-09-13 13:47:30 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2020-09-14 00:18:49 +0300
commit418e850b2b1f76b204af87a5d930f5129055e09a (patch)
tree470f40f91b500ca1de712689d171433d9dd4d0d5
parentcall_stack: try to fix __declspec(noinline) #3 (diff)
downloadwinapi-debug-418e850b2b1f76b204af87a5d930f5129055e09a.tar.gz
winapi-debug-418e850b2b1f76b204af87a5d930f5129055e09a.zip
call_stack: can't noinline w/ MSVC, let's try a DLL
-rw-r--r--.appveyor.yml6
-rw-r--r--.clang-format12
-rw-r--r--test/CMakeLists.txt20
-rw-r--r--test/call_stack.cpp37
-rw-r--r--test/symbols.cpp21
-rw-r--r--test/test_lib.cpp44
-rw-r--r--test/test_lib.hpp19
-rw-r--r--test/test_lib_api.hpp7
-rw-r--r--test/unit_tests/dbghelp.cpp14
9 files changed, 101 insertions, 79 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index 2215bfb..3d881b0 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -38,9 +38,9 @@ after_build:
test_script:
- '"%install_dir%\bin\test\unit_tests.exe" --log_level=all'
- '"%install_dir%\bin\test\call_stack.exe"'
- - ps: '$(& "$env:install_dir\bin\test\call_stack.exe" | Select-String -Pattern "[call_stack!test::baz" -SimpleMatch -Quiet) -or $(throw "test::baz not found in the call stack")'
- - ps: '$(& "$env:install_dir\bin\test\call_stack.exe" | Select-String -Pattern "[call_stack!test::bar" -SimpleMatch -Quiet) -or $(throw "test::bar not found in the call stack")'
- - ps: '$(& "$env:install_dir\bin\test\call_stack.exe" | Select-String -Pattern "[call_stack!test::foo" -SimpleMatch -Quiet) -or $(throw "test::foo not found in the call stack")'
+ - ps: '$(& "$env:install_dir\bin\test\call_stack.exe" | Select-String -Pattern "[test_lib!test::baz" -SimpleMatch -Quiet) -or $(throw "test::baz not found in the call stack")'
+ - ps: '$(& "$env:install_dir\bin\test\call_stack.exe" | Select-String -Pattern "[test_lib!test::bar" -SimpleMatch -Quiet) -or $(throw "test::bar not found in the call stack")'
+ - ps: '$(& "$env:install_dir\bin\test\call_stack.exe" | Select-String -Pattern "[test_lib!test::foo" -SimpleMatch -Quiet) -or $(throw "test::foo not found in the call stack")'
for:
# Only build Release builds on master to speed things up:
diff --git a/.clang-format b/.clang-format
index ea7323d..fb0d2f6 100644
--- a/.clang-format
+++ b/.clang-format
@@ -12,14 +12,16 @@ SpacesBeforeTrailingComments: 1
IncludeCategories:
- Regex: '^".*'
Priority: 1
- - Regex: '^<pdb/'
+ - Regex: '^<test_lib.*'
Priority: 2
- - Regex: '^<boost/'
+ - Regex: '^<pdb/'
Priority: 3
- - Regex: '^<SafeInt.hpp>$'
+ - Regex: '^<boost/'
Priority: 4
- - Regex: '^<.*\.h>$'
+ - Regex: '^<SafeInt.hpp>$'
Priority: 5
- - Regex: '.*'
+ - Regex: '^<.*\.h>$'
Priority: 6
+ - Regex: '.*'
+ Priority: 7
...
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index c4406c8..8851856 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,17 +1,21 @@
-add_executable(call_stack call_stack.cpp)
-target_link_libraries(call_stack PRIVATE pdb_repo)
-target_link_libraries(call_stack PRIVATE Boost::nowide)
+add_library(test_lib SHARED test_lib.cpp)
+target_link_libraries(test_lib PRIVATE pdb_repo)
+target_link_libraries(test_lib PRIVATE Boost::nowide)
+target_include_directories(test_lib PUBLIC .)
+target_compile_definitions(test_lib PRIVATE TEST_LIB_EXPORTS)
-install(TARGETS call_stack RUNTIME DESTINATION bin/test)
+install(TARGETS test_lib RUNTIME DESTINATION bin/test)
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
- install(FILES "$<TARGET_PDB_FILE:call_stack>" DESTINATION bin/test OPTIONAL)
+ install(FILES "$<TARGET_PDB_FILE:test_lib>" DESTINATION bin/test OPTIONAL)
endif()
-add_executable(symbols symbols.cpp)
+add_executable(call_stack call_stack.cpp)
+target_link_libraries(call_stack PRIVATE test_lib)
+target_link_libraries(call_stack PRIVATE Boost::nowide)
-install(TARGETS symbols RUNTIME DESTINATION bin/test)
+install(TARGETS call_stack RUNTIME DESTINATION bin/test)
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
- install(FILES "$<TARGET_PDB_FILE:symbols>" DESTINATION bin/test OPTIONAL)
+ install(FILES "$<TARGET_PDB_FILE:call_stack>" DESTINATION bin/test OPTIONAL)
endif()
add_subdirectory(unit_tests)
diff --git a/test/call_stack.cpp b/test/call_stack.cpp
index 25f3985..e14f744 100644
--- a/test/call_stack.cpp
+++ b/test/call_stack.cpp
@@ -1,45 +1,12 @@
-#include "pdb/all.hpp"
+#include <test_lib.hpp>
-#include <boost/config.hpp>
#include <boost/nowide/iostream.hpp>
#include <exception>
-namespace test {
-
-typedef void (*F)();
-
-void call_stack() {
- const auto dbghelp = pdb::DbgHelp::current_process();
- const auto call_stack = pdb::CallStack::capture();
- call_stack.dump(boost::nowide::cout, dbghelp);
-}
-
-// Some tricks to prevent the functions from being inlined follow...
-void baz() {
- boost::nowide::cout << "baz " << &baz << '\n';
- F f = &call_stack;
- f();
-}
-
-void bar() {
- boost::nowide::cout << "bar " << &bar << '\n';
- F f = &baz;
- f();
-}
-
-void foo() {
- boost::nowide::cout << "foo " << &foo << '\n';
- F f = &bar;
- f();
-}
-
-} // namespace test
-
int main() {
try {
- test::F f = &test::foo;
- f();
+ test::print_call_stack();
} catch (const std::exception& e) {
boost::nowide::cerr << e.what() << '\n';
return 1;
diff --git a/test/symbols.cpp b/test/symbols.cpp
deleted file mode 100644
index 7ace3bb..0000000
--- a/test/symbols.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace foobar_ns {
-
-int exit_code = 1;
-
-int __declspec(noinline) baz() {
- return exit_code;
-}
-
-int __declspec(noinline) bar() {
- return baz() * 2;
-}
-
-int __declspec(noinline) foo() {
- return bar() * 2;
-}
-
-} // namespace foobar_ns
-
-int main() {
- return foobar_ns::foo() * 2;
-}
diff --git a/test/test_lib.cpp b/test/test_lib.cpp
new file mode 100644
index 0000000..19c0d32
--- /dev/null
+++ b/test/test_lib.cpp
@@ -0,0 +1,44 @@
+#include "test_lib.hpp"
+
+#include <pdb/all.hpp>
+
+#include <boost/nowide/iostream.hpp>
+
+// Prevent frame pointer omission (FPO) and/or inlining.
+#ifdef _MSC_VER
+#pragma optimize("", off)
+#endif
+
+namespace test {
+namespace {
+
+void do_print_call_stack() {
+ const auto dbghelp = pdb::DbgHelp::current_process();
+ const auto call_stack = pdb::CallStack::capture();
+ call_stack.dump(boost::nowide::cout, dbghelp);
+}
+
+} // namespace
+
+volatile int var = 42;
+
+void baz(F f) {
+ boost::nowide::cout << "baz\n";
+ f();
+}
+
+void bar(F f) {
+ boost::nowide::cout << "bar\n";
+ baz(f);
+}
+
+void foo(F f) {
+ boost::nowide::cout << "foo\n";
+ bar(f);
+}
+
+void print_call_stack() {
+ foo(&do_print_call_stack);
+}
+
+} // namespace test
diff --git a/test/test_lib.hpp b/test/test_lib.hpp
new file mode 100644
index 0000000..f5fa017
--- /dev/null
+++ b/test/test_lib.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+// This is dumb library which exports a bunch of symbols.
+
+#include "test_lib_api.hpp"
+
+namespace test {
+
+typedef void (*F)();
+
+TEST_LIB_API extern volatile int var;
+
+TEST_LIB_API void foo(F);
+TEST_LIB_API void bar(F);
+TEST_LIB_API void baz(F);
+
+TEST_LIB_API void print_call_stack();
+
+} // namespace test
diff --git a/test/test_lib_api.hpp b/test/test_lib_api.hpp
new file mode 100644
index 0000000..6404200
--- /dev/null
+++ b/test/test_lib_api.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#ifdef TEST_LIB_EXPORTS
+#define TEST_LIB_API __declspec(dllexport)
+#else
+#define TEST_LIB_API __declspec(dllimport)
+#endif
diff --git a/test/unit_tests/dbghelp.cpp b/test/unit_tests/dbghelp.cpp
index 86cf1ff..13d22b8 100644
--- a/test/unit_tests/dbghelp.cpp
+++ b/test/unit_tests/dbghelp.cpp
@@ -36,10 +36,10 @@ Set<T> join(Set<T>&& xs, Set<T>&& ys) {
class DbgHelpWithSymbols : public DbgHelp {
public:
- DbgHelpWithSymbols() { load_symbols_pdb(); }
+ DbgHelpWithSymbols() { load_test_lib_pdb(); }
static const std::string& get_namespace() {
- static const std::string name{"foobar_ns"};
+ static const std::string name{"test"};
return name;
}
@@ -47,7 +47,7 @@ public:
static SymbolList expected_functions() { return make_qualified({"foo", "bar", "baz"}); }
- static SymbolList expected_variables() { return make_qualified({"exit_code"}); }
+ static SymbolList expected_variables() { return make_qualified({"var"}); }
static SymbolList expected_symbols() {
return join(expected_functions(), expected_variables());
@@ -62,14 +62,14 @@ private:
return qualified;
}
- void load_symbols_pdb() {
- const auto pdb_path = get_symbols_pdb_path().string();
+ void load_test_lib_pdb() {
+ const auto pdb_path = get_test_lib_pdb_path().string();
BOOST_TEST_MESSAGE("Loading PDB: " << pdb_path);
dbghelp.load_pdb(pdb_path);
}
- static boost::filesystem::path get_symbols_pdb_path() {
- return Paths::get().exe_dir / "symbols.pdb";
+ static boost::filesystem::path get_test_lib_pdb_path() {
+ return Paths::get().exe_dir / "test_lib.pdb";
}
};