Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 55 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ set(CMKR_ROOT_PROJECT OFF)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CMKR_ROOT_PROJECT ON)

# Bootstrap cmkr
include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
if(CMKR_INCLUDE_RESULT)
cmkr()
endif()
# include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
# if(CMKR_INCLUDE_RESULT)
# cmkr()
# endif()

# Enable folder support
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
Expand Down Expand Up @@ -227,3 +226,54 @@ set_target_properties(TestTitanEngine PROPERTIES
unset(CMKR_TARGET)
unset(CMKR_SOURCES)

# Target TestDeletionRace
set(CMKR_TARGET TestDeletionRace)
set(TestDeletionRace_SOURCES "")

list(APPEND TestDeletionRace_SOURCES
"src/TestDeletionRace/TestDeletionRace.cpp"
"src/TestDeletionRace/TitanEngine.h"
)

list(APPEND TestDeletionRace_SOURCES
cmake.toml
)

set(CMKR_SOURCES ${TestDeletionRace_SOURCES})
add_executable(TestDeletionRace)

if(TestDeletionRace_SOURCES)
target_sources(TestDeletionRace PRIVATE ${TestDeletionRace_SOURCES})
endif()

get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT)
if(NOT CMKR_VS_STARTUP_PROJECT)
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT TestDeletionRace)
endif()

source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${TestDeletionRace_SOURCES})

target_link_directories(TestDeletionRace PRIVATE
"src/TestDeletionRace"
)

if(CMAKE_SIZEOF_VOID_P EQUAL 8) # x64
target_link_libraries(TestDeletionRace PRIVATE
TitanEngine_x64
)
endif()

if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x32
target_link_libraries(TestDeletionRace PRIVATE
TitanEngine_x86
)
endif()

set_target_properties(TestDeletionRace PROPERTIES
VS_DEBUGGER_COMMAND_ARGUMENTS
"\"$<TARGET_FILE:DebugMe>\""
)

unset(CMKR_TARGET)
unset(CMKR_SOURCES)

10 changes: 10 additions & 0 deletions cmake.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,13 @@ x32.link-libraries = ["TitanEngine_x86"]

[target.TestTitanEngine.properties]
VS_DEBUGGER_COMMAND_ARGUMENTS = "\"$<TARGET_FILE:DebugMe>\""

[target.TestDeletionRace]
type = "executable"
sources = ["src/TestDeletionRace/*.cpp", "src/TestDeletionRace/*.h"]
link-directories = ["src/TestDeletionRace"]
x64.link-libraries = ["TitanEngine_x64"]
x32.link-libraries = ["TitanEngine_x86"]

[target.TestDeletionRace.properties]
VS_DEBUGGER_COMMAND_ARGUMENTS = "\"$<TARGET_FILE:DebugMe>\""
91 changes: 91 additions & 0 deletions src/TestDeletionRace/TestDeletionRace.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include <cstdio>
#include <cstdlib>
#include "TitanEngine.h"

static PROCESS_INFORMATION g_pi;
static ULONG_PTR g_raceFunction = 0;
static ULONG_PTR g_raceCounter = 0;
static bool g_deleted = false;
static unsigned int g_hits = 0;
static unsigned int g_finalCount = 0;

static const unsigned int DELETE_AFTER = 10;

static void cbBreakpoint()
{
g_hits++;

if (!g_deleted && g_hits >= DELETE_AFTER)
{
printf("hit #%u, deleting breakpoint\n", g_hits);
DeleteBPX(g_raceFunction);
g_deleted = true;
}
}

static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* info)
{
wchar_t path[MAX_PATH] = L"";
GetFinalPathNameByHandleW(info->hFile, path, MAX_PATH, VOLUME_NAME_DOS);

auto base = (ULONG_PTR)info->lpBaseOfImage;
auto hLib = LoadLibraryExW(path, nullptr, DONT_RESOLVE_DLL_REFERENCES);
if (hLib)
{
auto addr = (ULONG_PTR)GetProcAddress(hLib, "RaceFunction");
if (addr)
g_raceFunction = addr - (ULONG_PTR)hLib + base;

addr = (ULONG_PTR)GetProcAddress(hLib, "RaceCounter");
if (addr)
g_raceCounter = addr - (ULONG_PTR)hLib + base;

FreeLibrary(hLib);
}

if (g_raceFunction)
{
printf("RaceFunction: %p\n", (void*)g_raceFunction);
SetBPX(g_raceFunction, UE_BREAKPOINT, (void*)cbBreakpoint);
}
}

static void cbExitProcess(EXIT_PROCESS_DEBUG_INFO* info)
{
if (g_raceCounter)
{
SIZE_T n;
ReadProcessMemory(g_pi.hProcess, (LPVOID)g_raceCounter, &g_finalCount, sizeof(g_finalCount), &n);
}

printf("\nRaceCounter: %u (expected 5001)\n", g_finalCount);
printf("Exit code: %u\n", info->dwExitCode);
printf("BP hits: %u\n", g_hits);

bool ok = (g_finalCount == 5001) && (info->dwExitCode == 0);
printf("Result: %s\n", ok ? "PASS" : "FAIL");
}

int wmain(int argc, wchar_t** argv)
{
if (argc < 2)
{
puts("Usage: TestDeletionRace <DebugMe.exe>");
return 1;
}

auto pi = (PROCESS_INFORMATION*)InitDebugW(argv[1], nullptr, nullptr);
if (!pi)
{
puts("InitDebugW failed");
return 1;
}
g_pi = *pi;

SetCustomHandler(UE_CH_CREATEPROCESS, (void*)cbCreateProcess);
SetCustomHandler(UE_CH_EXITPROCESS, (void*)cbExitProcess);

DebugLoop();

return (g_finalCount == 5001) ? 0 : 1;
}
Loading