mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-07-05 22:45:48 -07:00
. dbghelp is now pulled in by a separate external_libraries header . disable _SECURE_SCL (improves perf) . amd64: initial implementation of essential functions, not yet complete . manifest: disabled on ICC because its IPO module incorrectly interprets /manifestdependency . wdbg_sym: no longer support stack walks on non-ia32 win2k (avoids trouble due to mixing SEH and dtors) . winit and wstartup: had to remove forced symbol include - does not link otherwise on ICC (for reasons unknown). function pointers are actually included and called on x64 windows (compiling with MSC) This was SVN commit r5895.
125 lines
3.1 KiB
C++
125 lines
3.1 KiB
C++
/**
|
|
* =========================================================================
|
|
* File : wdbg.cpp
|
|
* Project : 0 A.D.
|
|
* Description : Win32 debug support code.
|
|
* =========================================================================
|
|
*/
|
|
|
|
// license: GPL; see lib/license.txt
|
|
|
|
#include "precompiled.h"
|
|
#include "lib/debug.h"
|
|
|
|
#include "lib/bits.h"
|
|
#include "win.h"
|
|
#include "wutil.h"
|
|
|
|
|
|
// return 1 if the pointer appears to be totally bogus, otherwise 0.
|
|
// this check is not authoritative (the pointer may be "valid" but incorrect)
|
|
// but can be used to filter out obviously wrong values in a portable manner.
|
|
int debug_is_pointer_bogus(const void* p)
|
|
{
|
|
#if ARCH_IA32
|
|
if(p < (void*)0x10000)
|
|
return true;
|
|
if(p >= (void*)(uintptr_t)0x80000000)
|
|
return true;
|
|
#endif
|
|
|
|
// notes:
|
|
// - we don't check alignment because nothing can be assumed about a
|
|
// string pointer and we mustn't reject any actually valid pointers.
|
|
// - nor do we bother checking the address against known stack/heap areas
|
|
// because that doesn't cover everything (e.g. DLLs, VirtualAlloc).
|
|
// - cannot use IsBadReadPtr because it accesses the mem
|
|
// (false alarm for reserved address space).
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool debug_is_code_ptr(void* p)
|
|
{
|
|
uintptr_t addr = (uintptr_t)p;
|
|
// totally invalid pointer
|
|
if(debug_is_pointer_bogus(p))
|
|
return false;
|
|
// comes before load address
|
|
static const HMODULE base = GetModuleHandle(0);
|
|
if(addr < (uintptr_t)base)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool debug_is_stack_ptr(void* p)
|
|
{
|
|
uintptr_t addr = (uintptr_t)p;
|
|
// totally invalid pointer
|
|
if(debug_is_pointer_bogus(p))
|
|
return false;
|
|
// not aligned
|
|
if(addr % sizeof(void*))
|
|
return false;
|
|
// out of bounds (note: IA-32 stack grows downwards)
|
|
NT_TIB* tib = (NT_TIB*)NtCurrentTeb();
|
|
if(!(tib->StackLimit < p && p < tib->StackBase))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void debug_puts(const char* text)
|
|
{
|
|
OutputDebugStringA(text);
|
|
}
|
|
|
|
|
|
void wdbg_printf(const char* fmt, ...)
|
|
{
|
|
char buf[1024]; // as required by wvsprintf
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
wvsprintf(buf, fmt, ap);
|
|
va_end(ap);
|
|
|
|
debug_puts(buf);
|
|
}
|
|
|
|
|
|
// inform the debugger of the current thread's description, which it then
|
|
// displays instead of just the thread handle.
|
|
//
|
|
// see "Setting a Thread Name (Unmanaged)": http://msdn2.microsoft.com/en-us/library/xcb2z8hs(vs.71).aspx
|
|
void debug_set_thread_name(const char* name)
|
|
{
|
|
// we pass information to the debugger via a special exception it
|
|
// swallows. if not running under one, bail now to avoid
|
|
// "first chance exception" warnings.
|
|
if(!IsDebuggerPresent())
|
|
return;
|
|
|
|
// presented by Jay Bazuzi (from the VC debugger team) at TechEd 1999.
|
|
const struct ThreadNameInfo
|
|
{
|
|
DWORD type;
|
|
const char* name;
|
|
DWORD thread_id; // any valid ID or -1 for current thread
|
|
DWORD flags;
|
|
}
|
|
info = { 0x1000, name, (DWORD)-1, 0 };
|
|
__try
|
|
{
|
|
RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
// if we get here, the debugger didn't handle the exception.
|
|
// this happens if profiling with Dependency Walker; debug_assert
|
|
// must not be called because we may be in critical init.
|
|
}
|
|
}
|