blob: bad8ae7f9b11da9cc25261066590c987a2449771 [file] [log] [blame]
/*
* Copyright 2015 Valve Software
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Author: Jon Ashburn <jon@lunarg.com>
* Author: Peter Lohrmann <peterl@valvesoftware.com>
*/
#include "vktrace_common.h"
#include "vktrace_filelike.h"
#include "vktrace_interconnect.h"
#include "vktrace_vk_vk.h"
#ifdef __cplusplus
extern "C" {
#endif
VKTRACER_LEAVE _Unload(void);
#ifdef PLATFORM_LINUX
static void vktrace_sighandler(int signum, siginfo_t *info, void *ptr)
{
vktrace_LogVerbose("vktrace_lib library handle signal %d.", signum);
_Unload();
kill(0, signum);
}
#endif
VKTRACER_EXIT TrapExit(void)
{
vktrace_LogVerbose("vktrace_lib TrapExit.");
}
void loggingCallback(VktraceLogLevel level, const char* pMessage)
{
switch(level)
{
case VKTRACE_LOG_ALWAYS: printf("%s\n", pMessage); break;
case VKTRACE_LOG_DEBUG: printf("Debug: %s\n", pMessage); break;
case VKTRACE_LOG_ERROR: printf("Error: %s\n", pMessage); break;
case VKTRACE_LOG_WARNING: printf("Warning: %s\n", pMessage); break;
case VKTRACE_LOG_VERBOSE: printf("Verbose: %s\n", pMessage); break;
default:
printf("%s\n", pMessage); break;
}
if (vktrace_trace_get_trace_file() != NULL)
{
uint32_t requiredLength = (uint32_t) strlen(pMessage) + 1;
vktrace_trace_packet_header* pHeader = vktrace_create_trace_packet(VKTRACE_TID_VULKAN, VKTRACE_TPI_MESSAGE, sizeof(vktrace_trace_packet_message), requiredLength);
vktrace_trace_packet_message* pPacket = vktrace_interpret_body_as_trace_packet_message(pHeader);
pPacket->type = level;
pPacket->length = requiredLength;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&pPacket->message, requiredLength, pMessage);
vktrace_finalize_buffer_address(pHeader, (void**)&pPacket->message);
vktrace_set_packet_entrypoint_end_time(pHeader);
vktrace_finalize_trace_packet(pHeader);
vktrace_write_trace_packet(pHeader, vktrace_trace_get_trace_file());
vktrace_delete_trace_packet(&pHeader);
}
#if defined(WIN32)
#if _DEBUG
OutputDebugString(pMessage);
#endif
#endif
}
extern
VKTRACER_ENTRY _Load(void)
{
// only do the hooking and networking if the tracer is NOT loaded by vktrace
if (vktrace_is_loaded_into_vktrace() == FALSE)
{
vktrace_LogSetCallback(loggingCallback);
vktrace_LogSetLevel(VKTRACE_LOG_LEVEL_MAXIMUM);
vktrace_LogVerbose("vktrace_lib library loaded into PID %d", vktrace_get_pid());
atexit(TrapExit);
// If you need to debug startup, build with this set to true, then attach and change it to false.
#ifdef _DEBUG
{
BOOL debugStartup = FALSE;
while (debugStartup);
}
#endif
#ifdef PLATFORM_LINUX
struct sigaction act;
memset(&act, 0 , sizeof(act));
act.sa_sigaction = vktrace_sighandler;
act.sa_flags = SA_SIGINFO | SA_RESETHAND;
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
sigaction(SIGABRT, &act, NULL);
#endif
}
}
VKTRACER_LEAVE _Unload(void)
{
// only do the hooking and networking if the tracer is NOT loaded by vktrace
if (vktrace_is_loaded_into_vktrace() == FALSE)
{
if (vktrace_trace_get_trace_file() != NULL) {
vktrace_trace_packet_header* pHeader = vktrace_create_trace_packet(VKTRACE_TID_VULKAN, VKTRACE_TPI_MARKER_TERMINATE_PROCESS, 0, 0);
vktrace_finalize_trace_packet(pHeader);
vktrace_write_trace_packet(pHeader, vktrace_trace_get_trace_file());
vktrace_delete_trace_packet(&pHeader);
vktrace_free(vktrace_trace_get_trace_file());
vktrace_trace_set_trace_file(NULL);
}
if (gMessageStream != NULL)
{
vktrace_MessageStream_destroy(&gMessageStream);
}
vktrace_LogVerbose("vktrace_lib library unloaded from PID %d", vktrace_get_pid());
}
}
#if defined(WIN32)
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
hModule;
lpReserved;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
_Load();
break;
}
case DLL_PROCESS_DETACH:
{
_Unload();
break;
}
default:
break;
}
return TRUE;
}
#endif
#ifdef __cplusplus
}
#endif