1
1
forked from 0ad/0ad

remove mmgr and macros that redefine malloc/new/free

(see http://www.wildfiregames.com/forum/index.php?showtopic=11450&hl= )

clean up debug module
. no longer include platform-dependent header (-> less rebuilds)
. DISPLAY_ERROR -> DEBUG_DISPLAY_ERROR
. parts of config.h that don't affect all files moved to config.2 (->
fewer full rebuilds)
. remove creaky symbol cache (no longer needed for mmgr)
. remove TLS thread naming stuff (can use debugger's thread window
instead; no need for platform independence there)

wdbg: remove thread suspension and breakpoint APIs (not needed)

acpi: fix: u64 -> uintptr_t

wutil: fix WinScopedLock, use that instead of direct lock() functions

misc:
. get rid of SAFE_STRCPY, replace with strcpy_s
. remove _getcwd (shouldn't be used)

This was SVN commit r5563.
This commit is contained in:
janwas 2008-01-19 11:33:11 +00:00
parent 3d571150ae
commit 9269be9ee3
52 changed files with 301 additions and 1174 deletions

View File

@ -279,7 +279,7 @@ void CInternalCGUIAccessorBase::HandleMessage(IGUIObject *pObject, const SGUIMes
{ \
/* Abort now, to avoid corrupting everything by invalidly \
casting pointers */ \
DISPLAY_ERROR(L"FATAL ERROR: Inconsistent types in GUI"); \
DEBUG_DISPLAY_ERROR(L"FATAL ERROR: Inconsistent types in GUI"); \
} \
}
#include "GUItypes.h"

View File

@ -13,6 +13,7 @@
#include <map>
#include "lib/config2.h" // CONFIG2_ALLOCATORS_OVERRUN_PROTECTION
#include "lib/posix/posix_mman.h" // PROT_*
#include "lib/sysdep/cpu.h" // cpu_CAS
@ -215,7 +216,7 @@ notify us when done; memory access permission is temporarily granted.
(similar in principle to Software Transaction Memory).
since this is quite slow, the protection is disabled unless
CONFIG_OVERRUN_PROTECTION == 1; this avoids having to remove the
CONFIG2_ALLOCATORS_OVERRUN_PROTECTION == 1; this avoids having to remove the
wrapper code in release builds and re-write when looking for overruns.
example usage:
@ -228,9 +229,6 @@ doSomethingWith(yc); // read/write access
your_class_wrapper.lock(); // disallow further access until next .get()
..
**/
#ifdef REDEFINED_NEW
# include "lib/nommgr.h"
#endif
template<class T> class OverrunProtector
{
public:
@ -257,7 +255,7 @@ public:
void lock()
{
#if CONFIG_OVERRUN_PROTECTION
#if CONFIG2_ALLOCATORS_OVERRUN_PROTECTION
mprotect(object, sizeof(T), PROT_NONE);
#endif
}
@ -265,16 +263,13 @@ public:
private:
void unlock()
{
#if CONFIG_OVERRUN_PROTECTION
#if CONFIG2_ALLOCATORS_OVERRUN_PROTECTION
mprotect(object, sizeof(T), PROT_READ|PROT_WRITE);
#endif
}
T* object;
};
#ifdef REDEFINED_NEW
# include "lib/mmgr.h"
#endif
//-----------------------------------------------------------------------------

View File

@ -388,10 +388,8 @@ public:
FreedBlock* WriteTags(u8* p, size_t size)
{
#include "lib/nommgr.h"
FreedBlock* freedBlock = new(p) FreedBlock(s_headerId, size);
(void)new(Footer(freedBlock)) FreedBlock(s_footerId, size);
#include "lib/mmgr.h"
m_freeBlocks++;
m_freeBytes += size;

View File

@ -2,7 +2,7 @@
* =========================================================================
* File : config.h
* Project : 0 A.D.
* Description : user-specified compile-time configuration.
* Description : compile-time configuration for the entire project
* =========================================================================
*/
@ -11,74 +11,33 @@
#ifndef INCLUDED_CONFIG
#define INCLUDED_CONFIG
// the config macros are always defined; their values (1 or 0) are
// tested with #if instead of #ifdef.
// this protects user code from typos such as #ifdef _MSC_VEER, which
// would silently remove code. instead, we will at least get "test of
// undefined macro" warnings here. not including this header also triggers
// such warnings, but won't happen often because we're included from PCH.
//
// allow override via compiler settings by checking #ifndef.
// notes:
// - this file is included in the PCH and thus affects the entire project.
// to avoid unnecessary full rebuilds, place settings of more limited
// applicability in config2.h and explicitly include that header.
// - config macros are always defined; their values (1 or 0) are tested
// with #if instead of #ifdef. this protects against typos by at least
// causing a warning if the tested macro is undefined.
// - allow override via compiler settings by checking #ifndef.
// omit frame pointers - stack frames will not be generated, which
// improves performance but makes walking the stack harder.
// this is acted upon by #pragmas in sysdep.h.
// pre-compiled headers
#ifndef CONFIG_ENABLE_PCH
# define CONFIG_ENABLE_PCH 1 // improve build performance
#endif
// frame pointers
#ifndef CONFIG_OMIT_FP
# ifdef NDEBUG
# define CONFIG_OMIT_FP 1
# define CONFIG_OMIT_FP 1 // improve performance
# else
# define CONFIG_OMIT_FP 0
# define CONFIG_OMIT_FP 0 // enable use of ia32's fast stack walk
# endif
#endif
// (only applicable if ARCH_IA32) 64-bit values will be returned in EDX:EAX.
// this chiefly affects ia32_rdtsc. if not set, a safer but slower fallback
// will be used that doesn't assume anything about return convention.
#ifndef CONFIG_RETURN64_EDX_EAX
# define CONFIG_RETURN64_EDX_EAX 1
#endif
// allow use of RDTSC for raw tick counts (otherwise, the slower but
// more reliable on MP systems wall-clock will be used).
#ifndef CONFIG_TIMER_ALLOW_RDTSC
# define CONFIG_TIMER_ALLOW_RDTSC 1
#endif
// this enables/disables the actual checking done by OverrunProtector-s
// (quite slow, entailing mprotect() before/after each access).
// define to 1 here or in the relevant module if you suspect mem corruption.
// we provide this option because OverrunProtector requires some changes to
// the object being wrapped, and we want to leave those intact but not
// significantly slow things down except when needed.
#ifndef CONFIG_OVERRUN_PROTECTION
# define CONFIG_OVERRUN_PROTECTION 0
#endif
// zero-copy IO means all clients share the cached buffer; changing their
// contents is forbidden. this flag causes the buffers to be marked as
// read-only via MMU (writes would cause an exception), which takes a
// bit of extra time.
#ifndef CONFIG_READ_ONLY_CACHE
#define CONFIG_READ_ONLY_CACHE 1
#endif
// enable memory tracking (slow). see mmgr.cpp.
#ifndef CONFIG_USE_MMGR
# define CONFIG_USE_MMGR 0
#endif
// enable the wsdl emulator in Windows builds.
//
// NOTE: the official SDL distribution has two problems on Windows:
// - it specifies "/defaultlib:msvcrt.lib". this is troublesome because
// multiple heaps are active; errors result when allocated blocks are
// (for reasons unknown) passed to a different heap to be freed.
// one workaround is to add "/nodefaultlib:msvcrt.lib" to the linker
// command line in debug configurations.
// - it doesn't support color hardware mouse cursors and clashes with
// cursor.cpp's efforts by resetting the mouse cursor after movement.
#ifndef CONFIG_USE_WSDL
# define CONFIG_USE_WSDL 1
// try to prevent any exceptions from being thrown - even by the C++
// standard library. useful only for performance tests.
#ifndef CONFIG_DISABLE_EXCEPTIONS
# define CONFIG_DISABLE_EXCEPTIONS 0
#endif
// enable additional debug checks (very slow).
@ -91,22 +50,4 @@
# define CONFIG_FINAL 0
#endif
// enable trace output for low-level code - various functions will
// debug_printf when they are entered/exited. note that the appropriate
// TRACEn tags must be debug_filter_add-ed for this to have any effect.
#ifndef CONFIG_TRACE
# define CONFIG_TRACE 0
#endif
// try to prevent any exceptions from being thrown - even by the C++
// standard library. useful only for performance tests.
#ifndef CONFIG_DISABLE_EXCEPTIONS
# define CONFIG_DISABLE_EXCEPTIONS 0
#endif
// precompiled headers (affects what precompiled.h pulls in; see there)
#ifndef CONFIG_ENABLE_PCH
# define CONFIG_ENABLE_PCH 1
#endif
#endif // #ifndef INCLUDED_CONFIG

64
source/lib/config2.h Normal file
View File

@ -0,0 +1,64 @@
/**
* =========================================================================
* File : config2.h
* Project : 0 A.D.
* Description : compile-time configuration for isolated spots
* =========================================================================
*/
// license: GPL; see lib/license.txt
#ifndef INCLUDED_CONFIG2
#define INCLUDED_CONFIG2
// rationale: a centralized header makes it much easier to see what all
// can be changed. it is assumed that only a few modules will need
// configuration choices, so rebuilding them all is acceptable.
// use config.h when settings must apply to the entire project.
// (only applicable if ARCH_IA32) 64-bit values will be returned in EDX:EAX.
// this chiefly affects ia32_rdtsc. if not set, a safer but slower fallback
// will be used that doesn't assume anything about return convention.
#ifndef CONFIG2_IA32_RETURN64_EDX_EAX
# define CONFIG2_IA32_RETURN64_EDX_EAX 1
#endif
// allow use of RDTSC for raw tick counts (otherwise, the slower but
// more reliable on MP systems wall-clock will be used).
#ifndef CONFIG2_TIMER_ALLOW_RDTSC
# define CONFIG2_TIMER_ALLOW_RDTSC 1
#endif
// this enables/disables the actual checking done by OverrunProtector
// (quite slow, entailing mprotect() before/after each access).
// define to 1 here or in the relevant module if you suspect mem corruption.
// we provide this option because OverrunProtector requires some changes to
// the object being wrapped, and we want to leave those intact but not
// significantly slow things down except when needed.
#ifndef CONFIG2_ALLOCATORS_OVERRUN_PROTECTION
# define CONFIG2_ALLOCATORS_OVERRUN_PROTECTION 0
#endif
// zero-copy IO means all clients share the cached buffer; changing their
// contents is forbidden. this flag causes the buffers to be marked as
// read-only via MMU (writes would cause an exception), which takes a
// bit of extra time.
#ifndef CONFIG2_CACHE_READ_ONLY
#define CONFIG2_CACHE_READ_ONLY 1
#endif
// enable the wsdl emulator in Windows builds.
//
// NOTE: the official SDL distribution has two problems on Windows:
// - it specifies "/defaultlib:msvcrt.lib". this is troublesome because
// multiple heaps are active; errors result when allocated blocks are
// (for reasons unknown) passed to a different heap to be freed.
// one workaround is to add "/nodefaultlib:msvcrt.lib" to the linker
// command line in debug configurations.
// - it doesn't support color hardware mouse cursors and clashes with
// cursor.cpp's efforts by resetting the mouse cursor after movement.
#ifndef CONFIG2_WSDL
# define CONFIG2_WSDL 1
#endif
#endif // #ifndef INCLUDED_CONFIG2

View File

@ -17,17 +17,10 @@
#include "app_hooks.h"
#include "os_path.h"
#include "path_util.h"
#include "debug_stl.h"
#include "lib/allocators/allocators.h" // page_aligned_alloc
#include "fnv_hash.h"
#include "lib/posix/posix_pthread.h"
#include "lib/sysdep/cpu.h" // cpu_CAS
#include "lib/sysdep/sysdep.h"
// some functions here are called from within mmgr; disable its hooks
// so that our allocations don't cause infinite recursion.
#ifdef REDEFINED_NEW
# include "lib/nommgr.h"
#endif
ERROR_ASSOCIATE(ERR::SYM_NO_STACK_FRAMES_FOUND, "No stack frames found", -1);
@ -139,8 +132,7 @@ void debug_filter_remove(const char* tag)
void debug_filter_clear()
{
for(uint i = 0; i < MAX_TAGS; i++)
tags[i] = 0;
std::fill(tags, tags+MAX_TAGS, 0);
}
bool debug_filter_allows(const char* text)
@ -248,200 +240,6 @@ LibError debug_write_crashlog(const wchar_t* text)
}
//////////////////////////////////////////////////////////////////////////////
//
// storage for and construction of strings describing a symbol
//
//////////////////////////////////////////////////////////////////////////////
// tightly pack strings within one large buffer. we never need to free them,
// since the program structure / addresses can never change.
static const size_t STRING_BUF_SIZE = 64*KiB;
static char* string_buf;
static char* string_buf_pos;
static const char* symbol_string_build(void* symbol, const char* name, const char* file, int line)
{
// maximum bytes allowed per string (arbitrary).
// needed to prevent possible overflows.
const size_t STRING_MAX = 1000;
if(!string_buf)
{
string_buf = new char[STRING_BUF_SIZE];
string_buf_pos = string_buf;
}
// make sure there's enough space for a new string
char* string = string_buf_pos;
if(string + STRING_MAX >= string_buf + STRING_BUF_SIZE)
{
WARN_ERR(ERR::LIMIT);
return 0;
}
// user didn't know name/file/line. attempt to resolve from debug info.
char name_buf[DBG_SYMBOL_LEN];
char file_buf[DBG_FILE_LEN];
if(!name || !file || !line)
{
int line_buf;
(void)debug_resolve_symbol(symbol, name_buf, file_buf, &line_buf);
// only override the original parameters if value is meaningful;
// otherwise, stick with what we got, even if 0.
// (obviates test of return value; correctly handles partial failure).
if(name_buf[0])
name = name_buf;
if(file_buf[0])
file = file_buf;
if(line_buf)
line = line_buf;
}
// file and line are available: write them
int len;
if(file && line)
{
// strip path from filename (long and irrelevant)
const char* fn_only = path_name_only(file);
len = snprintf(string, STRING_MAX-1, "%s:%05d ", fn_only, line);
}
// only address is known
else
len = snprintf(string, STRING_MAX-1, "%p ", symbol);
// append symbol name
if(name)
{
snprintf(string+len, STRING_MAX-1-len, "%s", name);
debug_stl_simplify_name(string+len);
}
return string;
}
//////////////////////////////////////////////////////////////////////////////
//
// cache, mapping symbol address to its description string.
//
//////////////////////////////////////////////////////////////////////////////
// note: we don't want to allocate a new string for every symbol -
// that would waste lots of memory. instead, when a new address is first
// encountered, allocate a string describing it, and store for later use.
// hash table entry; valid iff symbol != 0. the string pointer must remain
// valid until the cache is shut down.
struct Symbol
{
void* symbol;
const char* string;
};
static const uint MAX_SYMBOLS = 2048;
static Symbol* symbols;
static uint total_symbols;
static uint hash_jumps;
// strip off lower 2 bits, since it's unlikely that 2 symbols are
// within 4 bytes of one another.
static uint hash(void* symbol)
{
const uintptr_t address = (uintptr_t)symbol;
return (uint)( (address >> 2) % MAX_SYMBOLS );
}
// algorithm: hash lookup with linear probing.
static const char* symbol_string_from_cache(void* symbol)
{
// hash table not initialized yet, nothing to find
if(!symbols)
return 0;
uint idx = hash(symbol);
for(;;)
{
Symbol* c = &symbols[idx];
// not in table
if(!c->symbol)
return 0;
// found
if(c->symbol == symbol)
return c->string;
idx = (idx+1) % MAX_SYMBOLS;
}
}
// associate <string> (must remain valid) with <symbol>, for
// later calls to symbol_string_from_cache.
static void symbol_string_add_to_cache(const char* string, void* symbol)
{
if(!symbols)
{
// note: must be zeroed to set each Symbol to "invalid"
symbols = (Symbol*)calloc(MAX_SYMBOLS, sizeof(Symbol));
debug_assert(symbols);
}
// hash table is completely full (guard against infinite loop below).
// if this happens, the string won't be cached - nothing serious.
if(total_symbols >= MAX_SYMBOLS)
WARN_ERR_RETURN(ERR::LIMIT);
total_symbols++;
// find Symbol slot in hash table
Symbol* c;
uint idx = hash(symbol);
for(;;)
{
c = &symbols[idx];
// found an empty slot
if(!c->symbol)
break;
idx = (idx+1) % MAX_SYMBOLS;
hash_jumps++;
}
// commit Symbol information
c->symbol = symbol;
c->string = string;
string_buf_pos += strlen(string)+1;
}
const char* debug_get_symbol_string(void* symbol, const char* name, const char* file, int line)
{
// return it if already in cache
const char* string = symbol_string_from_cache(symbol);
if(string)
return string;
// try to build a new string
string = symbol_string_build(symbol, name, file, line);
if(!string)
return 0;
symbol_string_add_to_cache(string, symbol);
return string;
}
//-----------------------------------------------------------------------------
// output
//-----------------------------------------------------------------------------
@ -598,14 +396,7 @@ static ErrorReaction carry_out_ErrorReaction(ErrorReaction er, uint flags, u8* s
case ER_EXIT:
exit_requested = true; // see declaration
// disable memory-leak reporting to avoid a flood of warnings
// (lots of stuff will leak since we exit abnormally).
debug_heap_enable(DEBUG_HEAP_NONE);
#if CONFIG_USE_MMGR
mmgr_set_options(0);
#endif
exit(EXIT_FAILURE);
abort();
}
return er;
@ -730,76 +521,3 @@ ErrorReaction debug_warn_err(LibError err, u8* suppress,
swprintf(buf, ARRAY_SIZE(buf), L"Function call failed: return value was %d (%hs)", err, err_buf);
return debug_display_error(buf, DE_MANUAL_BREAK, skip,context, file,line,func, suppress);
}
//-----------------------------------------------------------------------------
// thread naming
//-----------------------------------------------------------------------------
// when debugging multithreading problems, logging the currently running
// thread is helpful; a user-specified name is easier to remember than just
// the thread handle. to that end, we provide a robust TLS mechanism that is
// much safer than the previous method of hijacking TIB.pvArbitrary.
//
// note: on Win9x thread "IDs" are pointers to the TIB xor-ed with an
// obfuscation value calculated at boot-time.
//
// __declspec(thread) et al. are now available on VC and newer GCC but we
// implement TLS manually (via pthread_setspecific) to ensure compatibility.
static pthread_key_t tls_key;
static pthread_once_t tls_once = PTHREAD_ONCE_INIT;
// provided for completeness and to avoid displaying bogus resource leaks.
static void tls_shutdown()
{
WARN_ERR(pthread_key_delete(tls_key));
tls_key = 0;
}
// (called via pthread_once from debug_set_thread_name)
static void tls_init()
{
WARN_ERR(pthread_key_create(&tls_key, 0)); // no dtor
// note: do not use atexit; this may be called before _cinit.
}
// set the current thread's name; it will be returned by subsequent calls to
// debug_get_thread_name.
//
// the string pointed to by <name> MUST remain valid throughout the
// entire program; best to pass a string literal. allocating a copy
// would be quite a bit more work due to cleanup issues.
//
// if supported on this platform, the debugger is notified of the new name;
// it will be displayed there instead of just the handle.
void debug_set_thread_name(const char* name)
{
WARN_ERR(pthread_once(&tls_once, tls_init));
WARN_ERR(pthread_setspecific(tls_key, name));
#if OS_WIN
wdbg_set_thread_name(name);
#endif
}
// return the pointer assigned by debug_set_thread_name or 0 if
// that hasn't been done yet for this thread.
const char* debug_get_thread_name()
{
return (const char*)pthread_getspecific(tls_key);
}
void debug_shutdown()
{
tls_shutdown();
}

View File

@ -11,103 +11,45 @@
#ifndef INCLUDED_DEBUG
#define INCLUDED_DEBUG
#if OS_WIN
# include "lib/sysdep/win/wdbg.h"
#else
# include "lib/sysdep/unix/udbg.h"
#endif
// this module provides platform-independent debug facilities, useful for
// diagnosing and reporting program errors.
// - a symbol engine provides access to compiler-generated debug information and
// can also give a stack trace including local variables;
// - hooks into the memory allocator improve its leak detection;
// - our more powerful assert() replacement gives a stack trace so
// that the underlying problem becomes apparent;
// - the output routines make for platform-independent logging and
// crashlogs with "last-known activity" reporting.
/**
* trigger a breakpoint when reached/"called".
* if defined as a macro, the debugger can break directly into the
* target function instead of one frame below it as with a conventional
* call-based implementation.
**/
#if MSC_VERSION
# define debug_break() __asm { int 3 }
#else
extern void debug_break();
#endif
overview
--------
this module provides platform-independent debug facilities, useful for
diagnosing and reporting program errors.
- a symbol engine provides access to compiler-generated debug information and
can also give a stack trace including local variables;
- the breakpoint API enables stopping when a given address is
executed, read or written to (as specified);
- a hook into the system's memory allocator can optionally check for and
report heap corruption;
- our more powerful assert() replacement gives a stack trace so
that the underlying problem becomes apparent;
- the output routines make for platform-independent logging and
crashlogs with "last-known activity" reporting.
usage
-----
please see the detailed comments below on how to use the individual features.
much of this is only helpful if you explicity ask for it!
rationale
---------
much of this functionality already exists within the VC7 IDE/debugger.
motivation for this code is as follows:
- we want a consistent interface for all platforms;
- limitations(*) in the VC variants should be fixed;
- make debugging as easy as possible.
* mostly pertaining to Release mode - e.g. symbols cannot be resolved
even if debug information is present and assert dialogs are useless.
**/
//-----------------------------------------------------------------------------
// debug memory allocator
//-----------------------------------------------------------------------------
/**
* check heap integrity (independently of mmgr).
* check heap integrity.
* errors are reported by the CRT or via debug_display_error.
**/
LIB_API void debug_heap_check(void);
enum DebugHeapChecks
{
/**
* no automatic checks. (default)
**/
DEBUG_HEAP_NONE = 0,
/**
* basic automatic checks when deallocating.
**/
DEBUG_HEAP_NORMAL = 1,
/**
* all automatic checks on every memory API call. this is really
* slow (x100), but reports errors closer to where they occurred.
**/
DEBUG_HEAP_ALL = 2
};
/**
* call at any time; from then on, the specified checks will be performed.
* if not called, the default is DEBUG_HEAP_NONE, i.e. do nothing.
**/
LIB_API void debug_heap_enable(DebugHeapChecks what);
//-----------------------------------------------------------------------------
// output
//-----------------------------------------------------------------------------
enum DebugLevel
{
DEBUG_LEVEL_NONE = 0,
DEBUG_LEVEL_BRIEF = 2,
DEBUG_LEVEL_DETAILED = 5,
DEBUG_LEVEL_FULL = 9
};
#define DEBUG_PRINTF_BRIEF if(debug_level >= DEBUG_LEVEL_BRIEF) debug_printf
#define DEBUG_PRINTF_DETAILED if(debug_level >= DEBUG_LEVEL_DETAILED) debug_printf
#define DEBUG_PRINTF_FULL if(debug_level >= DEBUG_LEVEL_FULL ) debug_printf
/**
* write a formatted string to the debug channel, subject to filtering
* (see below). implemented via debug_puts - see performance note there.
@ -228,7 +170,7 @@ LIB_API ErrorReaction debug_display_error(const wchar_t* description,
* convenience version, in case the advanced parameters aren't needed.
* macro instead of providing overload/default values for C compatibility.
**/
#define DISPLAY_ERROR(text) debug_display_error(text, 0, 0,0, __FILE__,__LINE__,__func__, 0)
#define DEBUG_DISPLAY_ERROR(text) debug_display_error(text, 0, 0,0, __FILE__,__LINE__,__func__, 0)
//
@ -438,59 +380,6 @@ LIB_API void debug_skip_next_err(LibError err);
LIB_API void debug_skip_assert();
//-----------------------------------------------------------------------------
// breakpoints
//-----------------------------------------------------------------------------
/**
* trigger a breakpoint when reached/"called".
* defined as a macro by the platform-specific header above; this allows
* breaking directly into the target function, instead of one frame
* below it as with a conventional call-based implementation.
**/
//#define debug_break() // not defined here; see above
/**
* sometimes mmgr's 'fences' (making sure padding before and after the
* allocation remains intact) aren't enough to catch hard-to-find
* memory corruption bugs. another tool is to trigger a debug exception
* when the later to be corrupted variable is accessed; the problem should
* then become apparent.
* the VC++ IDE provides such 'breakpoints', but can only detect write access.
* additionally, it can't resolve symbols in Release mode (where this would
* be most useful), so we provide a breakpoint API.
* (values chosen to match IA-32 bit defs, so compiler can optimize.
* this isn't required; it'll work regardless.)
**/
enum DbgBreakType
{
DBG_BREAK_CODE = 0, /// execute
DBG_BREAK_DATA_WRITE = 1, /// write
DBG_BREAK_DATA = 3 /// read or write
};
/**
* arrange for a debug exception to be raised when the
* indicated memory is accessed.
*
* @param addr memory address
* for simplicity, the length (range of bytes to be checked) is derived
* from addr's alignment, and is typically 1 machine word.
* @param type the type of access to watch for (see DbgBreakType)
* @return LibError; ERR::LIMIT if no more breakpoints are available
* (they are a limited resource - only 4 on IA-32).
**/
LIB_API LibError debug_set_break(void* addr, DbgBreakType type);
/**
* remove all breakpoints that were set by debug_set_break.
* important, since these are a limited resource.
**/
LIB_API LibError debug_remove_all_breaks();
//-----------------------------------------------------------------------------
// symbol access
//-----------------------------------------------------------------------------
@ -564,8 +453,6 @@ LIB_API LibError debug_resolve_symbol(void* ptr_of_interest, char* sym_name, cha
**/
LIB_API LibError debug_dump_stack(wchar_t* buf, size_t max_chars, uint skip, void* context);
LIB_API const char* debug_get_symbol_string(void* symbol, const char* name, const char* file, int line);
//-----------------------------------------------------------------------------
// helper functions (used by implementation)
@ -581,14 +468,13 @@ LIB_API void debug_puts(const char* text);
/**
* return address of the Nth function on the call stack.
*
* used by mmgr to determine what function requested each allocation;
* this is fast enough to allow that.
*
* @param skip number of stack frames (i.e. functions on call stack) to skip.
* @param context platform-specific representation of execution state
* (e.g. Win32 CONTEXT). if not NULL, tracing starts there; this is useful
* for exceptions. otherwise, tracing starts from the current call stack.
* @return address of Nth function
*
* note: this does not access debug symbols and is therefore quite fast.
**/
LIB_API void* debug_get_nth_caller(uint skip, void* context);
@ -611,26 +497,13 @@ LIB_API bool debug_is_stack_ptr(void* p);
/**
* set the current thread's name; it will be returned by subsequent calls to
* debug_get_thread_name.
* inform the debugger of the current thread's name.
*
* if supported on this platform, the debugger is notified of the new name;
* it will be displayed there instead of just the handle.
*
* @param name identifier string for thread. MUST remain valid throughout
* the entire program; best to pass a string literal. allocating a copy
* would be quite a bit more work due to cleanup issues.
* (threads are easier to keep apart when they are identified by
* name rather than TID.)
**/
LIB_API void debug_set_thread_name(const char* name);
/**
* return current thread's name.
*
* @return thread name, or NULL if one hasn't been assigned yet
* via debug_set_thread_name.
**/
LIB_API const char* debug_get_thread_name();
/**
* holds memory for an error message.
@ -677,11 +550,4 @@ LIB_API const wchar_t* debug_error_message_build(
uint skip, void* context,
ErrorMessageMem* emm);
/**
* call at exit to avoid some leaks.
* not strictly necessary.
**/
LIB_API void debug_shutdown();
#endif // #ifndef INCLUDED_DEBUG

View File

@ -572,9 +572,7 @@ template<class T> bool get_container_info(const T& t, size_t size, size_t el_siz
// construct a copy of begin() at it_mem. placement new is necessary
// because VC8's secure copy ctor apparently otherwise complains about
// invalid values in the (uninitialized) destination memory.
#include "lib/nommgr.h"
new(it_mem) const_iterator(t.begin());
#include "lib/mmgr.h"
return true;
}

View File

@ -12,8 +12,9 @@
#define INCLUDED_SDL
#include "sdl_fwd.h"
#include "lib/config2.h" // CONFIG2_WSDL
#if OS_WIN && CONFIG_USE_WSDL
#if OS_WIN && CONFIG2_WSDL
# include "lib/sysdep/win/wsdl.h"
#else

View File

@ -13,7 +13,6 @@
#include "lib/allocators/pool.h"
#include "lib/timer.h" // timer_Time
#include "lib/nommgr.h" // placement new
/*virtual*/ ITrace::~ITrace()
{

View File

@ -11,6 +11,7 @@
#include "precompiled.h"
#include "block_cache.h"
#include "lib/config2.h" // CONFIG2_CACHE_READ_ONLY
#include "lib/file/common/file_stats.h"
#include "lib/lockfree.h"
#include "lib/allocators/pool.h"
@ -79,13 +80,13 @@ public:
{
if(m_blocks.size() > m_maxBlocks)
{
#if CONFIG_READ_ONLY_CACHE
#if CONFIG2_CACHE_READ_ONLY
mprotect((void*)m_blocks.front().buf.get(), BLOCK_SIZE, PROT_READ);
#endif
m_blocks.pop_front(); // evict oldest block
}
#if CONFIG_READ_ONLY_CACHE
#if CONFIG2_CACHE_READ_ONLY
mprotect((void*)buf.get(), BLOCK_SIZE, PROT_WRITE|PROT_READ);
#endif
m_blocks.push_back(Block(id, buf));

View File

@ -54,7 +54,7 @@ public:
*
* call this when the block's IO has completed; its data will
* satisfy subsequent Retrieve calls for the same id.
* if CONFIG_READ_ONLY_CACHE, the memory is made read-only.
* if CONFIG2_CACHE_READ_ONLY, the memory is made read-only.
**/
void Add(BlockId id, shared_ptr<u8> buf);

View File

@ -53,7 +53,7 @@ public:
* Add a file's contents to the cache.
*
* the cache will be able to satisfy subsequent Retrieve() calls by
* returning this data; if CONFIG_READ_ONLY_CACHE, the buffer is made
* returning this data; if CONFIG2_CACHE_READ_ONLY, the buffer is made
* read-only. if need be and no references are currently attached to it,
* the memory can also be commandeered by Reserve().
*

View File

@ -10,6 +10,7 @@
#include "precompiled.h"
#if 0
ERROR_ASSOCIATE(ERR::MEM_ALLOC_NOT_FOUND, "Not a valid allocated address", -1);
ERROR_ASSOCIATE(ERR::MEM_OVERWRITTEN, "Wrote to memory outside valid allocation", -1);
@ -1418,3 +1419,5 @@ void operator delete[](void* p, const char* file, int line, const char* func) th
}
#endif // #if CONFIG_USE_MMGR
#endif

View File

@ -1,3 +1,5 @@
#if 0
/**
* =========================================================================
* File : mmgr.h
@ -290,3 +292,5 @@ extern void operator delete[](void* p, const char* file, int line, const char* f
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif // #if CONFIG_USE_MMGR
#endif

View File

@ -9,14 +9,7 @@
// license: GPL; see lib/license.txt
// if PCHs are supported and enabled, we make an effort to include all
// system headers. otherwise, only a few headers (e.g. memory tracker)
// are pulled in and source files must include all the system headers
// they use. this policy ensures good compile performance whether or not
// PCHs are being used.
#include "lib/config.h" // CONFIG_ENABLE_PCH
#include "lib/sysdep/compiler.h" // HAVE_PCH
#include "lib/sysdep/compiler.h" // MSC_VERSION, HAVE_PCH
// disable some common and annoying warnings
// (done as soon as possible so that headers below are covered)
@ -43,9 +36,8 @@
// headers made available everywhere for convenience
//
#include "lib/sysdep/compiler.h"
#include "lib/sysdep/stl.h"
#include "lib/sysdep/os.h"
#include "lib/sysdep/stl.h"
#include "lib/sysdep/arch.h"
#include "lib/lib_api.h"
@ -80,6 +72,15 @@ namespace fs = boost::filesystem;
// precompiled headers
//
// if PCHs are supported and enabled, we make an effort to include all
// system headers. otherwise, only a few central headers (e.g. types)
// are pulled in and source files must include all the system headers
// they use. this policy ensures good compile performance whether or not
// PCHs are being used.
#include "lib/config.h" // CONFIG_ENABLE_PCH
#include "lib/sysdep/compiler.h" // HAVE_PCH
#if CONFIG_ENABLE_PCH && HAVE_PCH
// anything placed here won't need to be compiled in each translation unit,
@ -140,7 +141,7 @@ namespace fs = boost::filesystem;
#include <string>
#include <sstream>
#include <typeinfo>
#include <valarray>
#include <valarray>
// STL extensions
#if GCC_VERSION
@ -157,7 +158,3 @@ namespace fs = boost::filesystem;
#if MSC_VERSION
# pragma warning(default:4702)
#endif
// (this must be included from every file to make sure all allocations
// are tracked; placing it in the PCH is a convenient means of doing so)
#include "mmgr.h"

View File

@ -223,7 +223,7 @@ static GLint choose_int_fmt(GLenum fmt, uint q_flags)
{
wchar_t buf[100];
swprintf(buf, ARRAY_SIZE(buf), L"choose_int_fmt: fmt 0x%x isn't covered! please add it", fmt);
DISPLAY_ERROR(buf);
DEBUG_DISPLAY_ERROR(buf);
debug_assert(0); // given fmt isn't covered! please add it.
// fall back to a reasonable default
return half_bpp? GL_RGB4 : GL_RGB8;
@ -683,7 +683,7 @@ static void detect_gl_upload_caps()
// warn if more-or-less essential features are missing
if(!have_s3tc)
DISPLAY_ERROR(L"Performance warning: your graphics card does not support compressed textures. The game will try to continue anyway, but may be slower than expected. Please try updating your graphics drivers; if that doesn't help, please try upgrading your hardware.");
DEBUG_DISPLAY_ERROR(L"Performance warning: your graphics card does not support compressed textures. The game will try to continue anyway, but may be slower than expected. Please try updating your graphics drivers; if that doesn't help, please try upgrading your hardware.");
}

View File

@ -191,11 +191,9 @@ static HDATA* h_data_from_idx(const i32 idx)
if(!page)
return 0;
#include "lib/nommgr.h" // placement new
// Initialise all the VfsPath members
for(uint i = 0; i < hdata_per_page; ++i)
new (&page[i].pathname) VfsPath;
#include "lib/mmgr.h"
}
// note: VC7.1 optimizes the divides to shift and mask.
@ -620,9 +618,7 @@ static LibError h_free_idx(i32 idx, HDATA* hd)
hd->pathname.~VfsPath(); // FIXME: ugly hack, but necessary to reclaim std::string memory
memset(hd, 0, sizeof(*hd));
#include "lib/nommgr.h" // placement new
new (&hd->pathname) VfsPath; // FIXME too: necessary because otherwise it'll break if we reuse this page
#include "lib/mmgr.h"
free_idx(idx);

View File

@ -115,7 +115,7 @@ For further details, see below.
// macro magic (stringize+prepend L) and we already display file+line.
#define TEST(condition) STMT(\
if(!(condition))\
DISPLAY_ERROR(L"Self-test failed");\
debug_display_error(L"Self-test failed");\
)

View File

@ -51,7 +51,7 @@ static inline void* CallWithSafetyBlanket(UnsafeFunction func, PCV_u8 mem, size_
#endif
}
static void* TransactPhysicalMemory(u64 physicalAddress, size_t numBytes, UnsafeFunction func, void* arg = 0)
static void* TransactPhysicalMemory(uintptr_t physicalAddress, size_t numBytes, UnsafeFunction func, void* arg = 0)
{
PCV_u8 mem = (PCV_u8)mahaf_MapPhysicalMemory(physicalAddress, numBytes);
if(!mem)
@ -168,7 +168,7 @@ static inline void* UnsafeAllocateCopyOfTable(PCV_u8 mem, size_t numBytes, void*
// caller is responsible for verifying the table is valid and using
// DeallocateTable to free it.
static const AcpiTable* AllocateCopyOfTable(u64 physicalAddress)
static const AcpiTable* AllocateCopyOfTable(uintptr_t physicalAddress)
{
// ACPI table sizes are not known until they've been mapped. since that
// is slow, we don't always want to do it twice. the solution is to map
@ -229,7 +229,7 @@ static bool VerifyTable(const AcpiTable* table, const char* signature = 0)
}
static const AcpiTable* GetTable(u64 physicalAddress, const char* signature = 0)
static const AcpiTable* GetTable(uintptr_t physicalAddress, const char* signature = 0)
{
const AcpiTable* table = AllocateCopyOfTable(physicalAddress);
if(VerifyTable(table, signature))

View File

@ -202,7 +202,7 @@ public:
}
};
static void DetectIdentifierString(char* identifierString)
static void DetectIdentifierString(char* identifierString, size_t maxChars)
{
// get brand string (if available)
// note: ia32_asm_cpuid writes 4 u32s directly to identifierString -
@ -214,9 +214,6 @@ static void DetectIdentifierString(char* identifierString)
ia32_asm_cpuid(0x80000004, u32_string+8))
have_brand_string = true;
// note: we previously verified max_chars is long enough, so copying
// short literals into it is safe.
// fall back to manual detect of CPU type because either:
// - CPU doesn't support brand string (we use a flag to indicate this
// rather than comparing against a default value because it is safer);
@ -235,15 +232,15 @@ static void DetectIdentifierString(char* identifierString)
if(family == 6)
{
if(model == 3 || model == 7)
SAFE_STRCPY(identifierString, "AMD Duron");
strcpy_s(identifierString, maxChars, "AMD Duron");
else if(model <= 5)
SAFE_STRCPY(identifierString, "AMD Athlon");
strcpy_s(identifierString, maxChars, "AMD Athlon");
else
{
if(ia32_cap(IA32_CAP_AMD_MP))
SAFE_STRCPY(identifierString, "AMD Athlon MP");
strcpy_s(identifierString, maxChars, "AMD Athlon MP");
else
SAFE_STRCPY(identifierString, "AMD Athlon XP");
strcpy_s(identifierString, maxChars, "AMD Athlon XP");
}
}
break;
@ -253,13 +250,13 @@ static void DetectIdentifierString(char* identifierString)
if(family == 6)
{
if(model == 1)
SAFE_STRCPY(identifierString, "Intel Pentium Pro");
strcpy_s(identifierString, maxChars, "Intel Pentium Pro");
else if(model == 3 || model == 5)
SAFE_STRCPY(identifierString, "Intel Pentium II");
strcpy_s(identifierString, maxChars, "Intel Pentium II");
else if(model == 6)
SAFE_STRCPY(identifierString, "Intel Celeron");
strcpy_s(identifierString, maxChars, "Intel Celeron");
else
SAFE_STRCPY(identifierString, "Intel Pentium III");
strcpy_s(identifierString, maxChars, "Intel Pentium III");
}
break;
}
@ -282,7 +279,7 @@ const char* cpu_IdentifierString()
// 3 calls x 4 registers x 4 bytes = 48
static char identifierString[48+1] = {'\0'};
if(identifierString[0] == '\0')
DetectIdentifierString(identifierString);
DetectIdentifierString(identifierString, ARRAY_SIZE(identifierString));
return identifierString;
}

View File

@ -16,6 +16,7 @@
#endif
#include "ia32_asm.h"
#include "lib/config2.h" // CONFIG2_IA32_RETURN64_EDX_EAX
/**
@ -113,7 +114,7 @@ LIB_API u64 ia32_rdtsc_safe(void);
* but potentially differs between multiple CPUs)
**/
LIB_API u64 ia32_rdtsc(); // only for CppDoc's benefit
#if CONFIG_RETURN64_EDX_EAX
#if CONFIG2_IA32_RETURN64_EDX_EAX
# define ia32_rdtsc ia32_asm_rdtsc_edx_eax
#else
# define ia32_rdtsc ia32_rdtsc_safe

View File

@ -30,7 +30,7 @@ LibError udbg_resolve_symbol(void* UNUSED(ptr_of_interest), char* UNUSED(sym_nam
}
void unix_debug_break()
void debug_break()
{
kill(getpid(), SIGTRAP);
}

View File

@ -3,10 +3,6 @@
#ifndef INCLUDED_UDBG
#define INCLUDED_UDBG
#define debug_break unix_debug_break
extern void unix_debug_break(void);
extern void udbg_launch_debugger();
#endif // #ifndef INCLUDED_UDBG

View File

@ -47,7 +47,7 @@ class TestWdbgSym : public CxxTest::TestSuite
// note: prefer simple error (which also generates stack trace) to
// exception, because it is guaranteed to work (no issues with the
// debugger swallowing exceptions).
//DISPLAY_ERROR(L"wdbg_sym self test: check if stack trace below is ok.");
//DEBUG_DISPLAY_ERROR(L"wdbg_sym self test: check if stack trace below is ok.");
//RaiseException(0xf001,0,0,0);
// note: we don't want any kind of dialog to be raised, because

View File

@ -2,30 +2,21 @@
* =========================================================================
* File : wdbg.cpp
* Project : 0 A.D.
* Description : Win32 debug support code and exception handler.
* Description : Win32 debug support code.
* =========================================================================
*/
// license: GPL; see lib/license.txt
#include "precompiled.h"
#include "wdbg.h"
#include "lib/debug.h"
#include "lib/bits.h"
#include "win.h"
#include "wutil.h"
#include "winit.h"
// protects the breakpoint helper thread.
static void lock()
{
win_lock(WDBG_CS);
}
static void unlock()
{
win_unlock(WDBG_CS);
}
WINIT_REGISTER_CRITICAL_INIT(wdbg_Init);
static NT_TIB* get_tib()
@ -45,17 +36,30 @@ static NT_TIB* get_tib()
//-----------------------------------------------------------------------------
// debug memory allocator
// debug heap
//-----------------------------------------------------------------------------
// check heap integrity (independently of mmgr).
// errors are reported by the CRT or via debug_display_error.
static void debug_heap_init()
{
uint flags = 0;
flags |= _CRTDBG_ALLOC_MEM_DF; // enable checks at deallocation time
flags |= _CRTDBG_LEAK_CHECK_DF; // report leaks at exit
#if CONFIG_PARANOIA
flags |= _CRTDBG_CHECK_ALWAYS_DF; // check during every heap operation (slow!)
flags |= _CRTDBG_DELAY_FREE_MEM_DF; // blocks cannot be reused
#endif
_CrtSetDbgFlag(flags);
}
void debug_heap_check()
{
int ret;
__try
{
ret = _heapchk();
// NB: this is a no-op if !_CRTDBG_ALLOC_MEM_DF.
// we could call _heapchk but that would catch fewer errors.
ret = _CrtCheckMemory();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
@ -63,288 +67,7 @@ void debug_heap_check()
}
if(ret != _HEAPOK)
DISPLAY_ERROR(L"debug_heap_check: heap is corrupt");
}
// call at any time; from then on, the specified checks will be performed.
// if not called, the default is DEBUG_HEAP_NONE, i.e. do nothing.
void debug_heap_enable(DebugHeapChecks what)
{
// note: if mmgr is enabled, crtdbg.h will not have been included.
// in that case, we do nothing here - this interface is too basic to
// control mmgr; use its API instead.
#if !CONFIG_USE_MMGR && HAVE_VC_DEBUG_ALLOC
uint flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
switch(what)
{
case DEBUG_HEAP_NONE:
// note: do not set flags to zero because we might trash some
// important flag value.
flags &= ~(_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_DELAY_FREE_MEM_DF |
_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
break;
case DEBUG_HEAP_NORMAL:
flags |= _CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF;
break;
case DEBUG_HEAP_ALL:
flags |= (_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_DELAY_FREE_MEM_DF |
_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
break;
default:
debug_assert("debug_heap_enable: invalid what");
}
_CrtSetDbgFlag(flags);
#else
UNUSED2(what);
#endif // HAVE_DEBUGALLOC
}
//-----------------------------------------------------------------------------
// thread suspension
// suspend a thread, execute a user callback, revive the thread.
// to avoid deadlock, be VERY CAREFUL to avoid anything that may block,
// including locks taken by the OS (e.g. malloc, GetProcAddress).
typedef LibError (*WhileSuspendedFunc)(HANDLE hThread, void* user_arg);
struct WhileSuspendedParam
{
HANDLE hThread;
WhileSuspendedFunc func;
void* user_arg;
};
static void* while_suspended_thread_func(void* user_arg)
{
debug_set_thread_name("suspender");
WhileSuspendedParam* param = (WhileSuspendedParam*)user_arg;
DWORD err = SuspendThread(param->hThread);
// abort, since GetThreadContext only works if the target is suspended.
if(err == (DWORD)-1)
{
debug_assert(0); // while_suspended_thread_func: SuspendThread failed
return (void*)(intptr_t)-1;
}
// target is now guaranteed to be suspended,
// since the Windows counter never goes negative.
LibError ret = param->func(param->hThread, param->user_arg);
WARN_IF_FALSE(ResumeThread(param->hThread));
return (void*)(intptr_t)ret;
}
static LibError call_while_suspended(WhileSuspendedFunc func, void* user_arg)
{
int err;
// we need a real HANDLE to the target thread for use with
// Suspend|ResumeThread and GetThreadContext.
// alternative: DuplicateHandle on the current thread pseudo-HANDLE.
// this way is a bit more obvious/simple.
const DWORD access = THREAD_GET_CONTEXT|THREAD_SET_CONTEXT|THREAD_SUSPEND_RESUME;
HANDLE hThread = OpenThread(access, FALSE, GetCurrentThreadId());
if(hThread == INVALID_HANDLE_VALUE)
WARN_RETURN(ERR::FAIL);
WhileSuspendedParam param = { hThread, func, user_arg };
pthread_t thread;
WARN_ERR(pthread_create(&thread, 0, while_suspended_thread_func, &param));
void* ret;
err = pthread_join(thread, &ret);
debug_assert(err == 0 && ret == 0);
return (LibError)(intptr_t)ret;
}
//-----------------------------------------------------------------------------
// breakpoints
//-----------------------------------------------------------------------------
// breakpoints are set by storing the address of interest in a
// debug register and marking it 'enabled'.
//
// the first problem is, they are only accessible from Ring0;
// we get around this by updating their values via SetThreadContext.
// that in turn requires we suspend the current thread,
// spawn a helper to change the registers, and resume.
// parameter passing to helper thread. currently static storage,
// but the struct simplifies switching to a queue later.
struct BreakInfo
{
uintptr_t addr;
DbgBreakType type;
// determines what brk_thread_func will do.
// set/reset by debug_remove_all_breaks.
bool want_all_disabled;
};
static BreakInfo brk_info;
// Local Enable bits of all registers we enabled (used when restoring all).
static DWORD brk_all_local_enables;
// IA-32 limit; will need to update brk_enable_in_ctx if this changes.
static const uint MAX_BREAKPOINTS = 4;
// remove all breakpoints enabled by debug_set_break from <context>.
// called while target is suspended.
static LibError brk_disable_all_in_ctx(BreakInfo* UNUSED(bi), CONTEXT* context)
{
context->Dr7 &= ~brk_all_local_enables;
return INFO::OK;
}
// find a free register, set type according to <bi> and
// mark it as enabled in <context>.
// called while target is suspended.
static LibError brk_enable_in_ctx(BreakInfo* bi, CONTEXT* context)
{
uint reg; // index (0..3) of first free reg
uint LE; // local enable bit for <reg>
// find free debug register.
for(reg = 0; reg < MAX_BREAKPOINTS; reg++)
{
LE = BIT(reg*2);
// .. this one is currently not in use.
if((context->Dr7 & LE) == 0)
goto have_reg;
}
WARN_RETURN(ERR::LIMIT);
have_reg:
// store breakpoint address in debug register.
DWORD addr = (DWORD)bi->addr;
// .. note: treating Dr0..Dr3 as an array is unsafe due to
// possible struct member padding.
switch(reg)
{
case 0: context->Dr0 = addr; break;
case 1: context->Dr1 = addr; break;
case 2: context->Dr2 = addr; break;
case 3: context->Dr3 = addr; break;
NODEFAULT;
}
// choose breakpoint settings:
// .. type
uint rw = 0;
switch(bi->type)
{
case DBG_BREAK_CODE:
rw = 0; break;
case DBG_BREAK_DATA:
rw = 1; break;
case DBG_BREAK_DATA_WRITE:
rw = 3; break;
NODEFAULT;
}
// .. length (determine from addr's alignment).
// note: IA-32 requires len=0 for code breakpoints.
uint len = 0;
if(bi->type != DBG_BREAK_CODE)
{
const uint alignment = (uint)(bi->addr % 4);
// assume 2 byte range
if(alignment == 2)
len = 1;
// assume 4 byte range
else if(alignment == 0)
len = 3;
// else: 1 byte range; len already set to 0
}
// update Debug Control register
const uint shift = (16 + reg*4);
// .. clear previous contents of this reg's field
// (in case the previous user didn't do so on disabling).
context->Dr7 &= ~(0xFu << shift);
// .. write settings
context->Dr7 |= ((len << 2)|rw) << shift;
// .. mark as enabled
context->Dr7 |= LE;
brk_all_local_enables |= LE;
return INFO::OK;
}
// carry out the request stored in the BreakInfo* parameter.
// called while target is suspended.
static LibError brk_do_request(HANDLE hThread, void* arg)
{
LibError ret;
BreakInfo* bi = (BreakInfo*)arg;
CONTEXT context;
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
if(!GetThreadContext(hThread, &context))
WARN_RETURN(ERR::FAIL);
#if ARCH_IA32
if(bi->want_all_disabled)
ret = brk_disable_all_in_ctx(bi, &context);
else
ret = brk_enable_in_ctx (bi, &context);
#else
#error "port"
#endif
if(!SetThreadContext(hThread, &context))
WARN_RETURN(ERR::FAIL);
RETURN_ERR(ret);
return INFO::OK;
}
// arrange for a debug exception to be raised when <addr> is accessed
// according to <type>.
// for simplicity, the length (range of bytes to be checked) is
// derived from addr's alignment, and is typically 1 machine word.
// breakpoints are a limited resource (4 on IA-32); abort and
// return ERR::LIMIT if none are available.
LibError debug_set_break(void* p, DbgBreakType type)
{
lock();
brk_info.addr = (uintptr_t)p;
brk_info.type = type;
LibError ret = call_while_suspended(brk_do_request, &brk_info);
unlock();
return ret;
}
// remove all breakpoints that were set by debug_set_break.
// important, since these are a limited resource.
LibError debug_remove_all_breaks()
{
lock();
brk_info.want_all_disabled = true;
LibError ret = call_while_suspended(brk_do_request, &brk_info);
brk_info.want_all_disabled = false;
unlock();
return ret;
DEBUG_DISPLAY_ERROR(L"debug_heap_check: heap is corrupt");
}
@ -417,7 +140,7 @@ void debug_puts(const char* text)
// 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 wdbg_set_thread_name(const char* name)
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
@ -444,3 +167,10 @@ void wdbg_set_thread_name(const char* name)
debug_assert(0); // thread name hack doesn't work under this debugger
}
}
static LibError wdbg_Init()
{
debug_heap_init();
return INFO::OK;
}

View File

@ -1,23 +0,0 @@
/**
* =========================================================================
* File : wdbg.h
* Project : 0 A.D.
* Description : Win32 debug support code and exception handler.
* =========================================================================
*/
// license: GPL; see lib/license.txt
#ifndef INCLUDED_WDBG
#define INCLUDED_WDBG
#if MSC_VERSION
# define debug_break() __asm { int 3 }
#else
# error "port this or define to implementation function"
#endif
extern void wdbg_set_thread_name(const char* name);
#endif // #ifndef INCLUDED_WDBG

View File

@ -46,18 +46,6 @@ WINIT_REGISTER_MAIN_SHUTDOWN(wdbg_sym_Shutdown);
// nested stack traces are ignored and only the error is displayed.
// protects the non-reentrant dbghelp library.
static void lock()
{
win_lock(WDBG_SYM_CS);
}
static void unlock()
{
win_unlock(WDBG_SYM_CS);
}
//----------------------------------------------------------------------------
// dbghelp
//----------------------------------------------------------------------------
@ -162,7 +150,7 @@ static LibError debug_resolve_symbol_lk(void* ptr_of_interest, char* sym_name, c
SYMBOL_INFOW* sym = &sp.si;
if(SymFromAddrW(hProcess, addr, 0, sym))
{
snprintf(sym_name, DBG_SYMBOL_LEN, "%ws", sym->Name);
sprintf_s(sym_name, DBG_SYMBOL_LEN, "%ws", sym->Name);
successes++;
}
}
@ -184,7 +172,7 @@ static LibError debug_resolve_symbol_lk(void* ptr_of_interest, char* sym_name, c
// problem and is balanced by not having to do this from every
// call site (full path is too long to display nicely).
const char* base_name = path_name_only(line_info.FileName);
snprintf(file, DBG_FILE_LEN, "%s", base_name);
sprintf_s(file, DBG_FILE_LEN, "%s", base_name);
successes++;
}
@ -208,10 +196,8 @@ static LibError debug_resolve_symbol_lk(void* ptr_of_interest, char* sym_name, c
// the PDB implementation is rather slow (~500µs).
LibError debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char* file, int* line)
{
lock();
LibError ret = debug_resolve_symbol_lk(ptr_of_interest, sym_name, file, line);
unlock();
return ret;
WinScopedLock lock(WDBG_SYM_CS);
return debug_resolve_symbol_lk(ptr_of_interest, sym_name, file, line);
}
@ -468,34 +454,20 @@ static LibError nth_caller_cb(const STACKFRAME64* sf, void* user_arg)
return INFO::OK;
}
// return address of the Nth function on the call stack.
// if <context> is nonzero, it is assumed to be a platform-specific
// representation of execution state (e.g. Win32 CONTEXT) and tracing
// starts there; this is useful for exceptions.
// otherwise, tracing starts at the current stack position, and the given
// number of stack frames (i.e. functions) above the caller are skipped.
// used by mmgr to determine what function requested each allocation;
// this is fast enough to allow that.
void* debug_get_nth_caller(uint skip, void* pcontext)
{
lock();
WinScopedLock lock(WDBG_SYM_CS);
void* func;
skip_this_frame(skip, pcontext);
LibError err = walk_stack(nth_caller_cb, &func, skip, (const CONTEXT*)pcontext);
unlock();
return (err == INFO::OK)? func : 0;
LibError ret = walk_stack(nth_caller_cb, &func, skip, (const CONTEXT*)pcontext);
return (ret == INFO::OK)? func : 0;
}
//////////////////////////////////////////////////////////////////////////////
//
//-----------------------------------------------------------------------------
// helper routines for symbol value dump
//
//////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// overflow is impossible in practice, but check for robustness.
// keep in sync with DumpState.
@ -1444,7 +1416,7 @@ static LibError udt_dump_std(const wchar_t* wtype_name, const u8* p, size_t size
// convert to char since debug_stl doesn't support wchar_t.
char ctype_name[DBG_SYMBOL_LEN];
snprintf(ctype_name, ARRAY_SIZE(ctype_name), "%ws", wtype_name);
sprintf_s(ctype_name, ARRAY_SIZE(ctype_name), "%ws", wtype_name);
// display contents of STL containers
// .. get element type
@ -1481,7 +1453,7 @@ not_valid_container:
// .. some other error encountered
else
{
snprintf(buf, ARRAY_SIZE(buf), "error %d while analyzing ", err);
sprintf_s(buf, ARRAY_SIZE(buf), "error %d while analyzing ", err);
text = buf;
}
out(L"(%hs%hs)", text, debug_stl_simplify_name(ctype_name));
@ -1771,35 +1743,9 @@ static LibError dump_sym(DWORD type_id, const u8* p, DumpState state)
}
//////////////////////////////////////////////////////////////////////////////
//
//-----------------------------------------------------------------------------
// stack trace
//
//////////////////////////////////////////////////////////////////////////////
// output the symbol's name and value via dump_sym*.
// called from dump_frame_cb for each local symbol; lock is held.
static BOOL CALLBACK dump_sym_cb(SYMBOL_INFO* sym, ULONG UNUSED(size), void* UNUSED(ctx))
{
out_latch_pos(); // see decl
mod_base = sym->ModBase;
const u8* p = (const u8*)sym->Address;
DumpState state;
INDENT;
LibError err = dump_sym(sym->Index, p, state);
dump_error(err, p);
if(err == INFO::SYM_SUPPRESS_OUTPUT)
UNINDENT;
else
out(L"\r\n");
return TRUE; // continue
}
//////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
struct IMAGEHLP_STACK_FRAME2 : public IMAGEHLP_STACK_FRAME
{
@ -1821,6 +1767,26 @@ struct IMAGEHLP_STACK_FRAME2 : public IMAGEHLP_STACK_FRAME
}
};
// output the symbol's name and value via dump_sym*.
// called from dump_frame_cb for each local symbol; lock is held.
static BOOL CALLBACK dump_sym_cb(SYMBOL_INFO* sym, ULONG UNUSED(size), void* UNUSED(ctx))
{
out_latch_pos(); // see decl
mod_base = sym->ModBase;
const u8* p = (const u8*)sym->Address;
DumpState state;
INDENT;
LibError err = dump_sym(sym->Index, p, state);
dump_error(err, p);
if(err == INFO::SYM_SUPPRESS_OUTPUT)
UNINDENT;
else
out(L"\r\n");
return TRUE; // continue
}
// called by walk_stack for each stack frame
static LibError dump_frame_cb(const STACKFRAME64* sf, void* UNUSED(user_arg))
{
@ -1869,23 +1835,21 @@ return INFO::OK;
static uintptr_t already_in_progress;
if(!cpu_CAS(&already_in_progress, 0, 1))
return ERR::REENTERED; // NOWARN
lock();
out_init(buf, max_chars);
ptr_reset_visited();
WinScopedLock lock(WDBG_SYM_CS);
skip_this_frame(skip, pcontext);
LibError ret = walk_stack(dump_frame_cb, 0, skip, (const CONTEXT*)pcontext);
unlock();
already_in_progress = 0;
return ret;
}
//-----------------------------------------------------------------------------
// write out a "minidump" containing register and stack state; this enables
// examining the crash in a debugger. called by wdbg_exception_filter.
@ -1893,12 +1857,15 @@ return INFO::OK;
// lock must be held.
void wdbg_sym_write_minidump(EXCEPTION_POINTERS* exception_pointers)
{
lock();
WinScopedLock lock(WDBG_SYM_CS);
OsPath path = OsPath(ah_get_log_dir())/"crashlog.dmp";
HANDLE hFile = CreateFile(path.string().c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
if(hFile == INVALID_HANDLE_VALUE)
goto fail;
{
DEBUG_DISPLAY_ERROR(L"wdbg_sym_write_minidump: unable to create crashlog.dmp.");
return;
}
MINIDUMP_EXCEPTION_INFORMATION mei;
mei.ThreadId = GetCurrentThreadId();
@ -1912,16 +1879,13 @@ void wdbg_sym_write_minidump(EXCEPTION_POINTERS* exception_pointers)
HANDLE hProcess = GetCurrentProcess(); DWORD pid = GetCurrentProcessId();
if(!MiniDumpWriteDump(hProcess, pid, hFile, MiniDumpNormal, &mei, 0, 0))
{
fail:
DISPLAY_ERROR(L"Unable to generate minidump.");
}
DEBUG_DISPLAY_ERROR(L"wdbg_sym_write_minidump: unable to generate minidump.");
CloseHandle(hFile);
unlock();
}
//-----------------------------------------------------------------------------
static LibError wdbg_sym_Init()
{

View File

@ -159,13 +159,11 @@ static Events* pending_events;
static void AllocStaticObjects()
{
STATIC_STORAGE(ss, 200);
#include "lib/nommgr.h"
void* addr1 = static_calloc(&ss, sizeof(Watches));
watches = new(addr1) Watches;
void* addr2 = static_calloc(&ss, sizeof(Events));
pending_events = new(addr2) Events;
#include "lib/mmgr.h"
}
static void FreeStaticObjects()

View File

@ -181,8 +181,6 @@ CountOfImports(PCImgThunkData pitdBase) {
extern "C" PUnloadInfo __puiHead = 0;
#include "lib/nommgr.h"
struct ULI : public UnloadInfo
{
ULI(PCImgDelayDescr pidd_)
@ -213,8 +211,6 @@ struct ULI : public UnloadInfo
}
};
#include "lib/mmgr.h"
// For our own internal use, we convert to the old
// format for convenience.
@ -354,9 +350,7 @@ extern "C" FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd, FARPROC* ppfn
if (hmodT != hmod) {
// add lib to unload list if we have unload data
if (pidd->rvaUnloadIAT) {
#include "lib/nommgr.h"
new ULI(pidd);
#include "lib/mmgr.h"
}
}
else {

View File

@ -35,8 +35,6 @@ static ICounter* ConstructCounterAt(uint id, void* address, size_t size)
{
// rationale for placement new: see call site.
#include "lib/nommgr.h" // MMGR interferes with placement new
// counters are chosen according to the following order. rationale:
// - TSC must come before QPC and PMT to make sure a bug in the latter on
// Pentium systems doesn't come up.
@ -63,8 +61,6 @@ static ICounter* ConstructCounterAt(uint id, void* address, size_t size)
default:
return 0;
}
#include "lib/mmgr.h"
}

View File

@ -22,7 +22,7 @@
#define __STDC__ 1
#include <io.h> // _open etc.
#include <direct.h> // _getcwd, _rmdir
#include <direct.h> // _rmdir
#undef __STDC__
#define __STDC__ 0

View File

@ -51,14 +51,14 @@ public:
debug_assert(fd > 2);
debug_assert(GetFileSize(hFile, 0) != INVALID_FILE_SIZE);
WinScopedLock lock;
WinScopedLock lock(WAIO_CS);
std::pair<Map::iterator, bool> ret = m_map.insert(std::make_pair(fd, hFile));
debug_assert(ret.second); // fd better not already have been associated
}
void Dissociate(int fd)
{
WinScopedLock lock;
WinScopedLock lock(WAIO_CS);
const size_t numRemoved = m_map.erase(fd);
debug_assert(numRemoved == 1);
}
@ -69,7 +69,7 @@ public:
**/
HANDLE Get(int fd) const
{
WinScopedLock lock;
WinScopedLock lock(WAIO_CS);
Map::const_iterator it = m_map.find(fd);
if(it == m_map.end())
return INVALID_HANDLE_VALUE;

View File

@ -12,7 +12,6 @@
#include "wposix.h"
#include "wposix_internal.h"
#include "crt_posix.h" // _getcwd
#include "lib/bits.h"
WINIT_REGISTER_CRITICAL_INIT(wposix_Init); // wposix -> error handling
@ -104,20 +103,6 @@ long sysconf(int name)
}
//-----------------------------------------------------------------------------
#ifdef REDEFINED_NEW
# include "lib/nommgr.h"
#endif
char* getcwd(char* buf, size_t buf_size)
{
return _getcwd(buf, (int)buf_size);
}
#ifdef REDEFINED_NEW
# include "lib/mmgr.h"
#endif
//-----------------------------------------------------------------------------
static LibError wposix_Init()

View File

@ -35,8 +35,6 @@
// misc routines
extern char* getcwd(char*, size_t);
// user tests if available via #ifdef; can't use enum.
#define _SC_PAGESIZE 1
#define _SC_PAGE_SIZE 1

View File

@ -231,9 +231,8 @@ again:
// initializer returns pthread_mutex_t directly and CRITICAL_SECTIONS
// shouldn't be copied.
//
// note: must not use new/malloc to allocate the critical section
// because mmgr.cpp uses a mutex and must not be called to allocate
// anything before it is initialized.
// note: we use win_alloc instead of new because the (no longer extant)
// memory manager used a pthread_mutex.
pthread_mutex_t pthread_mutex_initializer()
{

View File

@ -11,7 +11,7 @@
#include "precompiled.h"
#include "lib/external_libraries/sdl.h"
#if CONFIG_USE_WSDL
#if CONFIG2_WSDL
#include <stdio.h>
#include <math.h>
@ -1230,4 +1230,4 @@ static LibError wsdl_Shutdown()
return INFO::OK;
}
#endif // #if CONFIG_USE_WSDL
#endif // #if CONFIG2_WSDL

View File

@ -9,7 +9,7 @@
// license: GPL; see lib/license.txt
#include "precompiled.h"
#include "wdbg.h"
#include "wseh.h"
#include "lib/byte_order.h" // FOURCC
#include "lib/sysdep/cpu.h"
@ -217,7 +217,7 @@ static void GetExceptionLocus(const EXCEPTION_POINTERS* ep,
//
// note: keep memory allocs and locking to an absolute minimum, because
// they may deadlock the process!
LONG WINAPI wseh_ExceptionFilter(EXCEPTION_POINTERS* ep)
long __stdcall wseh_ExceptionFilter(struct _EXCEPTION_POINTERS* ep)
{
// OutputDebugString raises an exception, which OUGHT to be swallowed
// by WaitForDebugEvent but sometimes isn't. if we see it, ignore it.
@ -241,7 +241,7 @@ LONG WINAPI wseh_ExceptionFilter(EXCEPTION_POINTERS* ep)
// we'll report this problem first and then try to display the
// exception info regardless (maybe dbghelp won't blow up).
if(win_is_locked(WDBG_SYM_CS) == 1)
DISPLAY_ERROR(L"Exception raised while critical section is held - may deadlock..");
DEBUG_DISPLAY_ERROR(L"Exception raised while critical section is held - may deadlock..");
// extract details from ExceptionRecord.
wchar_t descriptionBuf[150];

View File

@ -11,7 +11,8 @@
#ifndef INCLUDED_WSEH
#define INCLUDED_WSEH
extern LONG WINAPI wseh_ExceptionFilter(EXCEPTION_POINTERS* ep);
struct _EXCEPTION_POINTERS;
extern long __stdcall wseh_ExceptionFilter(_EXCEPTION_POINTERS* ep);
EXTERN_C int wseh_EntryPoint();

View File

@ -55,29 +55,29 @@ void win_free(void* p)
static CRITICAL_SECTION cs[NUM_CS];
static bool cs_valid;
void win_lock(uint idx)
void win_lock(WinLockId id)
{
debug_assert(idx < NUM_CS && "win_lock: invalid critical section index");
if(cs_valid)
EnterCriticalSection(&cs[idx]);
}
void win_unlock(uint idx)
{
debug_assert(idx < NUM_CS && "win_unlock: invalid critical section index");
if(cs_valid)
LeaveCriticalSection(&cs[idx]);
}
int win_is_locked(uint idx)
{
debug_assert(idx < NUM_CS && "win_is_locked: invalid critical section index");
if(!cs_valid)
return -1;
BOOL got_it = TryEnterCriticalSection(&cs[idx]);
if(got_it)
LeaveCriticalSection(&cs[idx]);
return !got_it;
return;
EnterCriticalSection(&cs[id]);
}
void win_unlock(WinLockId id)
{
if(!cs_valid)
return;
LeaveCriticalSection(&cs[id]);
}
bool win_is_locked(WinLockId id)
{
if(!cs_valid)
return false;
const BOOL successfullyEntered = TryEnterCriticalSection(&cs[id]);
if(!successfullyEntered)
return true; // still locked
LeaveCriticalSection(&cs[id]);
return false; // probably not locked
}
@ -270,16 +270,6 @@ static void FreeUser32Dll()
//-----------------------------------------------------------------------------
// memory
// note: has no effect if config.h's HAVE_VC_DEBUG_ALLOC is 0.
static void EnableMemoryTracking()
{
#if CONFIG_PARANOIA
debug_heap_enable(DEBUG_HEAP_ALL);
#elif !defined(NDEBUG)
debug_heap_enable(DEBUG_HEAP_NORMAL);
#endif
}
static void EnableLowFragmentationHeap()
{
#if WINVER >= 0x0501
@ -488,8 +478,6 @@ static LibError wutil_Init()
ForciblyLoadUser32Dll();
EnableMemoryTracking();
EnableLowFragmentationHeap();
ReadCommandLine();

View File

@ -31,46 +31,36 @@ extern void win_free(void* p);
//
// critical sections used by win-specific code
enum
enum WinLockId
{
ONCE_CS,
WAIO_CS,
WDBG_CS,
WDBG_SYM_CS,
WDBG_SYM_CS, // protects (non-reentrant) dbghelp.dll
NUM_CS
};
extern void win_lock(uint idx);
extern void win_unlock(uint idx);
extern void win_lock(WinLockId id);
extern void win_unlock(WinLockId id);
// used in a desperate attempt to avoid deadlock in wdbg_exception_handler.
extern int win_is_locked(uint idx);
// used in a desperate attempt to avoid deadlock in wseh.
extern bool win_is_locked(WinLockId id);
// thread safe, usable in constructors
#define WIN_ONCE(code)\
{\
win_lock(ONCE_CS);\
static bool ONCE_init_; /* avoid name conflict */\
if(!ONCE_init_)\
{\
ONCE_init_ = true;\
code;\
}\
win_unlock(ONCE_CS);\
}
struct WinScopedLock
class WinScopedLock
{
WinScopedLock()
public:
WinScopedLock(WinLockId id)
: m_id(id)
{
win_lock(WAIO_CS);
win_lock(m_id);
}
~WinScopedLock()
{
win_unlock(WAIO_CS);
win_unlock(m_id);
}
private:
WinLockId m_id;
};

View File

@ -24,7 +24,8 @@
#if OS_UNIX
# include <unistd.h>
#endif
#if ARCH_IA32 && CONFIG_TIMER_ALLOW_RDTSC
#include "lib/config2.h" // CONFIG2_TIMER_ALLOW_RDTSC
#if ARCH_IA32 && CONFIG2_TIMER_ALLOW_RDTSC
# include "lib/sysdep/ia32/ia32.h" // ia32_rdtsc
#endif
@ -162,12 +163,12 @@ ScopeTimer::~ScopeTimer()
// therefore, on systems with SpeedStep active, measurements of I/O or other
// non-CPU bound activity may be skewed. this is ok because the timer is
// only used for profiling; just be aware of the issue.
// if this is a problem, disable CONFIG_TIMER_ALLOW_RDTSC.
// if this is a problem, disable CONFIG2_TIMER_ALLOW_RDTSC.
//
// note that overflow isn't an issue either way (63 bit cycle counts
// at 10 GHz cover intervals of 29 years).
#if ARCH_IA32 && CONFIG_TIMER_ALLOW_RDTSC
#if ARCH_IA32 && CONFIG2_TIMER_ALLOW_RDTSC
void TimerUnit::SetToZero()
{

View File

@ -107,7 +107,7 @@ return false;
// nothing to do; will return false below
}
else if(ret < 0)
DISPLAY_ERROR(L"Archive build failed");
DEBUG_DISPLAY_ERROR(L"Archive build failed");
else if(ret == INFO::OK)
g_GUI.SendEventToAll("archivebuildercomplete");
// in progress

View File

@ -14,7 +14,7 @@ DllLoader atlas_dll("AtlasUI");
enum AtlasRunFlags
{
// used by ATLAS_RunIfOnCmdLine; makes any error output go through
// DISPLAY_ERROR rather than a GUI dialog box (because GUI init was
// DEBUG_DISPLAY_ERROR rather than a GUI dialog box (because GUI init was
// skipped to reduce load time).
ATLAS_NO_GUI = 1
};
@ -26,9 +26,9 @@ static void ATLAS_Run(const CmdLineArgs& args, int flags = 0)
if(!atlas_dll.LoadDLL())
{
if(flags & ATLAS_NO_GUI)
DISPLAY_ERROR(L"The Atlas UI was not successfully loaded and therefore cannot be started as requested.");
DEBUG_DISPLAY_ERROR(L"The Atlas UI was not successfully loaded and therefore cannot be started as requested.");
else
DISPLAY_ERROR(L"The Atlas UI was not successfully loaded and therefore cannot be started as requested.");// TODO: implement GUI error message
DEBUG_DISPLAY_ERROR(L"The Atlas UI was not successfully loaded and therefore cannot be started as requested.");// TODO: implement GUI error message
return;
}

View File

@ -863,7 +863,6 @@ void Shutdown(uint flags)
timer_DisplayClientTotals();
// should be last, since the above use them
debug_shutdown();
SAFE_DELETE(g_Logger);
delete &g_Profiler;
delete &g_ProfileViewer;
@ -1013,13 +1012,13 @@ void Init(const CmdLineArgs& args, uint flags)
L" The game may still work, though - you are welcome to try at your own risk."
L" If not or it doesn't look right, upgrade your graphics card.";
swprintf(buf, ARRAY_SIZE(buf), fmt, missing);
DISPLAY_ERROR(buf);
DEBUG_DISPLAY_ERROR(buf);
// TODO: i18n
}
if (!ogl_HaveExtension("GL_ARB_texture_env_crossbar"))
{
DISPLAY_ERROR(
DEBUG_DISPLAY_ERROR(
L"The GL_ARB_texture_env_crossbar extension doesn't appear to be available on your computer."
L" Shadows are not available and overall graphics quality might suffer."
L" You are advised to try installing newer drivers and/or upgrade your graphics card.");
@ -1071,12 +1070,6 @@ void Init(const CmdLineArgs& args, uint flags)
// Register a few Game/Network JS globals
g_ScriptingHost.SetGlobal("g_GameAttributes", OBJECT_TO_JSVAL(g_GameAttributes.GetScript()));
}
// Check for heap corruption after every allocation. Very, very slowly.
// (And it highlights the allocation just after the one you care about,
// so you need to run it again and tell it to break on the one before.)
// debug_heap_enable(DEBUG_HEAP_ALL);
InitInput();

View File

@ -20,9 +20,6 @@
#ifndef INCLUDED_XML
#define INCLUDED_XML
// Temporarily undefine new, because the Xerces headers don't like it
#include "lib/nommgr.h"
// temporarily go down to W3 because Xerces (in addition to all its other
// failings) isn't W4-clean.
#if MSC_VERSION
@ -52,8 +49,6 @@
#pragma warning(pop) // back to W4
#endif
#include "lib/mmgr.h" // restore malloc/new macros
#include "XercesErrorHandler.h"
#include "ps/CStr.h"
#include "lib/file/vfs/vfs_path.h"

View File

@ -71,9 +71,7 @@ BinInputStream *CVFSInputSource::makeStream() const
if(!m_pBuffer)
return 0;
#include "lib/nommgr.h" // BinMemInputStream has its own operator new
return new BinMemInputStream((XMLByte *)m_pBuffer.get(), (unsigned int)m_BufferSize, BinMemInputStream::BufOpt_Reference);
#include "lib/mmgr.h"
}
#define IS_PATH_SEP(_chr) (_chr == '/' || _chr == '\\')
@ -91,9 +89,7 @@ const char *prevpathcomp(const char *end, const char *beginning)
InputSource *CVFSEntityResolver::resolveEntity(const XMLCh *const UNUSED(publicId),
const XMLCh *const systemId)
{
#include "lib/nommgr.h"
CVFSInputSource *ret=new CVFSInputSource();
#include "lib/mmgr.h"
char *path=XMLString::transcode(systemId);
char *orgpath=path;

View File

@ -7,7 +7,6 @@ Xerces Error Handler for Pyrogenesis (and the GUI)
// ---------------------------------------------------------------------------
#include "precompiled.h"
#include "lib/nommgr.h"
#include "XercesErrorHandler.h"
#include <iostream>

View File

@ -1574,7 +1574,7 @@ ogl_tex_transform_to(textures[i], flags & ~TEX_DXT);
}
// .. not first: make sure texture size matches
else if(base != this_width || bpp != this_bpp)
DISPLAY_ERROR(L"Alpha maps are not identically sized (including pixel depth)");
DEBUG_DISPLAY_ERROR(L"Alpha maps are not identically sized (including pixel depth)");
}
//

View File

@ -940,9 +940,7 @@ void CJSComplex<T, ReadOnly>::AddProperty( const CStrW& PropertyName, jsval Valu
{
DeletePreviouslyAssignedProperty( PropertyName );
void* mem = jscomplexproperty_suballoc();
#include "lib/nommgr.h"
CJSDynamicComplexProperty* newProp = new(mem) CJSValComplexProperty( Value, false );
#include "lib/mmgr.h"
m_Properties[PropertyName] = newProp;
ReflectorTable::iterator it;
@ -1091,9 +1089,7 @@ void MemberAddPropertyImpl( IJSComplex* obj, const CStrW& PropertyName, PropType
{
((T*)obj)->DeletePreviouslyAssignedProperty( PropertyName );
void* mem = jscomplexproperty_suballoc();
#include "lib/nommgr.h"
obj->m_Properties[PropertyName] = new(mem) CJSComplexProperty<PropType, ReadOnly>( Native, PropAllowInheritance, Update, Refresh );
#include "lib/mmgr.h"
}
// PropertyName must not already exist! (verified in debug build)
@ -1102,9 +1098,7 @@ void MemberAddReadOnlyPropertyImpl( IJSComplex* obj, const CStrW& PropertyName,
{
((T*)obj)->DeletePreviouslyAssignedProperty( PropertyName );
void* mem = jscomplexproperty_suballoc();
#include "lib/nommgr.h"
obj->m_Properties[PropertyName] = new(mem) CJSComplexProperty<PropType, true>( Native, PropAllowInheritance, Update, Refresh );
#include "lib/mmgr.h"
}
#endif

View File

@ -45,17 +45,9 @@ after their definition.
#include <vector>
#include <string>
// We want to use placement new, which breaks when compiling Debug configurations
// in the game and in wx, and they both need different workarounds.
// we want to use placement new without grief
// (Duplicated in SharedMemory.h)
#ifdef new
# define SHAREABLE_USED_NOMMGR
# ifdef __WXWINDOWS__
# undef new
# else
# include "lib/nommgr.h"
# endif
#endif
#undef new
namespace AtlasMessage
{
@ -295,13 +287,4 @@ public:
}
#ifdef SHAREABLE_USED_NOMMGR
# ifdef __WXWINDOWS__ // TODO: portability to non-Windows wx
# define new new( _NORMAL_BLOCK, __FILE__, __LINE__)
# else
# include "mmgr.h"
# endif
# undef SHAREABLE_USED_NOMMGR
#endif
#endif // INCLUDED_SHAREABLE

View File

@ -1,17 +1,9 @@
#ifndef INCLUDED_SHAREDMEMORY
#define INCLUDED_SHAREDMEMORY
// We want to use placement new, which breaks when compiling Debug configurations
// in the game and in wx, and they both need different workarounds.
// we want to use placement new without grief
// (Duplicated in Shareable.h)
#ifdef new
# define SHAREABLE_USED_NOMMGR
# ifdef __WXWINDOWS__
# undef new
# else
# include "lib/nommgr.h"
# endif
#endif
#undef new
namespace AtlasMessage
{
@ -40,25 +32,4 @@ template<typename T> void ShareableDelete(T* p)
}
#ifdef SHAREABLE_USED_NOMMGR
// # ifdef __WXWINDOWS__ // TODO: portability to non-Windows wx
// # define new new( _NORMAL_BLOCK, __FILE__, __LINE__)
// # else
// # include "mmgr.h"
// # endif
// Actually, we don't want to redefine 'new', because it conflicts with all users
// of SHAREABLE_NEW. So just leave it undefined, and put up with the less
// informative leak messages.
# undef SHAREABLE_USED_NOMMGR
// Oh, but we don't want other game headers to include mmgr.h again.
// So let's just cheat horribly and remove the options which cause it to
// redefine new.
# undef HAVE_VC_DEBUG_ALLOC
# define HAVE_VC_DEBUG_ALLOC 0
# undef CONFIG_USE_MMGR
# define CONFIG_USE_MMGR 0
#endif
#endif // INCLUDED_SHAREDMEMORY