1 /* Copyright (c) 2010 Wildfire Games
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * Win32 debug support code.
27 #include "precompiled.h"
28 #include "lib/debug.h"
31 #include "lib/sysdep/os/win/win.h"
32 #include "lib/sysdep/os/win/wutil.h"
35 // return 1 if the pointer appears to be totally bogus, otherwise 0.
36 // this check is not authoritative (the pointer may be "valid" but incorrect)
37 // but can be used to filter out obviously wrong values in a portable manner.
38 int debug_IsPointerBogus(const void* p
)
40 if(p
< (void*)0x10000)
43 if(p
== (const void*)(uintptr_t)0xCCCCCCCCCCCCCCCCull
)
46 if(p
== (const void*)(uintptr_t)0xCCCCCCCCul
)
51 // - we don't check alignment because nothing can be assumed about a
52 // string pointer and we mustn't reject any actually valid pointers.
53 // - nor do we bother checking the address against known stack/heap areas
54 // because that doesn't cover everything (e.g. DLLs, VirtualAlloc).
55 // - cannot use IsBadReadPtr because it accesses the mem
56 // (false alarm for reserved address space).
62 bool debug_IsCodePointer(void* p
)
64 uintptr_t addr
= (uintptr_t)p
;
65 // totally invalid pointer
66 if(debug_IsPointerBogus(p
))
68 // comes before load address
69 static const HMODULE base
= GetModuleHandle(0);
70 if(addr
< (uintptr_t)base
)
77 bool debug_IsStackPointer(void* p
)
79 uintptr_t addr
= (uintptr_t)p
;
80 // totally invalid pointer
81 if(debug_IsPointerBogus(p
))
84 if(addr
% sizeof(void*))
86 // out of bounds (note: IA-32 stack grows downwards)
87 NT_TIB
* tib
= (NT_TIB
*)NtCurrentTeb();
88 if(!(tib
->StackLimit
< p
&& p
< tib
->StackBase
))
95 void debug_puts(const char* text
)
97 OutputDebugStringW(wstring_from_utf8(text
).c_str());
101 void wdbg_printf(const wchar_t* fmt
, ...)
103 wchar_t buf
[1024+1]; // wvsprintfW will truncate to this size
106 wvsprintfW(buf
, fmt
, ap
); // (return value doesn't indicate whether truncation occurred)
109 OutputDebugStringW(buf
);
113 // inform the debugger of the current thread's description, which it then
114 // displays instead of just the thread handle.
116 // see "Setting a Thread Name (Unmanaged)": http://msdn2.microsoft.com/en-us/library/xcb2z8hs(vs.71).aspx
117 void debug_SetThreadName(const char* name
)
119 // we pass information to the debugger via a special exception it
120 // swallows. if not running under one, bail now to avoid
121 // "first chance exception" warnings.
122 if(!IsDebuggerPresent())
125 // presented by Jay Bazuzi (from the VC debugger team) at TechEd 1999.
126 const struct ThreadNameInfo
130 DWORD thread_id
; // any valid ID or -1 for current thread
133 info
= { 0x1000, name
, (DWORD
)-1, 0 };
136 RaiseException(0x406D1388, 0, sizeof(info
)/sizeof(DWORD
), (ULONG_PTR
*)&info
);
138 __except(EXCEPTION_EXECUTE_HANDLER
)
140 // if we get here, the debugger didn't handle the exception.
141 // this happens if profiling with Dependency Walker; ENSURE
142 // must not be called because we may be in critical init.