wdbg, wposix, wsdl: fix some VC2005 warnings

wdbg_sym: prevent nested trees/arrays from hogging too much buffer space

This was SVN commit r2471.
This commit is contained in:
janwas 2005-07-04 17:09:28 +00:00
parent 3d23b2d9f5
commit 9bf5316b72
4 changed files with 115 additions and 43 deletions

View File

@ -146,15 +146,22 @@ void debug_wprintf(const wchar_t* fmt, ...)
// debug memory allocator
//-----------------------------------------------------------------------------
// check heap integrity (independently of mmgr).
// errors are reported by the CRT or via display_error.
void debug_heap_check()
{
int ret;
__try
{
_heapchk();
ret = _heapchk();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
ret = _HEAPBADNODE;
}
if(ret != _HEAPOK)
DISPLAY_ERROR(L"debug_heap_check: heap is corrupt");
}
@ -746,7 +753,7 @@ static int screwaround()
//
// storage for strings built by get_SEH_exception_description and get_cpp_exception_description.
static wchar_t description[128];
static wchar_t description_buf[128];
// VC++ exception handling internals.
// see http://www.codeproject.com/cpp/exceptionhandler.asp
@ -841,8 +848,8 @@ static const wchar_t* get_cpp_exception_description(const EXCEPTION_RECORD* er)
// we got meaningful data; format and return it.
if(type_name[0] != '\0' || what[0] != '\0')
{
swprintf(description, ARRAY_SIZE(description), L"%hs(\"%hs\")", type_name, what);
return description;
swprintf(description_buf, ARRAY_SIZE(description_buf), L"%hs(\"%hs\")", type_name, what);
return description_buf;
}
// not a C++ exception; we can't say anything about it.
@ -862,8 +869,8 @@ static const wchar_t* get_SEH_exception_description(const EXCEPTION_RECORD* er)
{
const wchar_t* op = (ei[0])? L"writing" : L"reading";
const wchar_t* fmt = L"Access violation %s 0x%08X";
swprintf(description, ARRAY_SIZE(description), translate(fmt), translate(op), ei[1]);
return description;
swprintf(description_buf, ARRAY_SIZE(description_buf), translate(fmt), translate(op), ei[1]);
return description_buf;
}
// rationale: we don't use FormatMessage because it is unclear whether
@ -900,8 +907,8 @@ static const wchar_t* get_SEH_exception_description(const EXCEPTION_RECORD* er)
// anything else => unknown; display its exception code.
// we don't punt to get_exception_description because anything
// we get called for will actually be a SEH exception.
swprintf(description, ARRAY_SIZE(description), L"Unknown (0x%08X)", code);
return description;
swprintf(description_buf, ARRAY_SIZE(description_buf), L"Unknown (0x%08X)", code);
return description_buf;
}
@ -928,7 +935,8 @@ static const wchar_t* get_exception_locus(const EXCEPTION_POINTERS* ep)
// points to kernel32!RaiseException. we use debug_dump_stack to determine the
// real location.
wchar_t buf[32000]; // Maybe TODO: "warning C6262: Function uses '64016' bytes of stack: exceeds /analysis:stacksize'16384'. Consider moving some data to heap"
wchar_t buf[1000];
// we only want the beginning and this is guarded against overflow.
const wchar_t* stack_trace = debug_dump_stack(buf, ARRAY_SIZE(buf), 1, ep->ContextRecord);
const size_t MAX_LOCUS_CHARS = 256;

View File

@ -90,6 +90,11 @@ enum WdbgError
// we abort to make sure we don't recurse infinitely.
WDBG_NESTING_LIMIT = -100103,
// too much output has been produced by this top-level symbol;
// we must terminate recursion lest it hog all buffer space.
// dump will continue with the next top-level symbol.
WDBG_SINGLE_SYMBOL_LIMIT = -100104,
// exception raised while processing the symbol.
WDBG_INTERNAL_ERROR = -100200,
@ -479,9 +484,26 @@ struct DumpState
static ssize_t out_chars_left;
static wchar_t* out_pos;
static bool out_have_warned_of_overflow;
// only do so once until next out_init to avoid flood of messages.
static wchar_t* out_pos;
// some top-level (*) symbols cause tons of output - so much that they may
// single-handedly overflow the buffer (e.g. pointer to a tree of huge UDTs).
// we can't have that, so there is a limit in place as to how much a
// single top-level symbol can output. after that is reached, dumping is
// aborted for that symbol but continues for the subsequent top-level symbols.
//
// this is implemented as follows: dump_sym_cb latches the current output
// position; each dump_sym (through which all symbols go) checks if the
// new position exceeds the limit and aborts if so.
// slight wrinkle: since we don't want each level of UDTs to successively
// realize the limit has been hit and display the error message, we
// return WDBG_SINGLE_SYMBOL_LIMIT once and thereafter WDBG_SUPPRESS_OUTPUT.
//
// * example: local variables, as opposed to child symbols in a UDT.
static wchar_t* out_latched_pos;
static bool out_have_warned_of_limit;
static void out_init(wchar_t* buf, size_t max_chars)
{
@ -534,6 +556,30 @@ static void out_erase(size_t num_chars)
}
// (see above)
static void out_latch_pos()
{
out_have_warned_of_limit = false;
out_latched_pos = out_pos;
}
// (see above)
static int out_check_limit()
{
if(out_have_warned_of_limit)
return WDBG_SUPPRESS_OUTPUT;
if(out_pos - out_latched_pos > 3000) // ~30 lines
{
out_have_warned_of_limit = true;
return WDBG_SINGLE_SYMBOL_LIMIT;
}
// no limit hit, proceed normally
return 0;
}
#define INDENT STMT(for(uint i = 0; i <= state.level; i++) out(L" ");)
#define UNINDENT STMT(out_erase((state.level+1)*4);)
@ -633,6 +679,9 @@ static void dump_error(int err, const u8* p)
case 0:
// no error => no output
break;
case WDBG_SINGLE_SYMBOL_LIMIT:
out(L"(too much output; skipping to next top-level symbol)");
break;
case WDBG_UNRETRIEVABLE_STATIC:
out(L"(unavailable - located in another module)");
break;
@ -745,26 +794,32 @@ static int dump_sequence(DebugIterator el_iterator, void* internal,
INDENT;
int err = dump_sym(el_type_id, el_p, state);
dump_error(err, el_p);
el_p = el_iterator(internal, el_size);
// there was no output for this child; undo its indentation (if any),
// skip everything below and proceed with the next child.
if(err == WDBG_SUPPRESS_OUTPUT)
{
if(!fits_on_one_line)
UNINDENT;
continue;
}
else
{
// add separator unless this is the last element (can't just
// erase below due to additional "...").
if(i != num_elements_to_show-1)
out(fits_on_one_line? L", " : L"\r\n");
}
}
// we truncated some
dump_error(err, el_p); // nop if err == 0
// add separator unless this is the last element (can't just
// erase below due to additional "...").
if(i != num_elements_to_show-1)
out(fits_on_one_line? L", " : L"\r\n");
if(err == WDBG_SINGLE_SYMBOL_LIMIT)
break;
} // for each child
// indicate some elements were skipped
if(el_count != num_elements_to_show)
out(L" ...");
state.level--;
if(fits_on_one_line)
out(L" }");
return 0;
@ -1499,19 +1554,23 @@ static int udt_dump_normal(const wchar_t* type_name, const u8* p, size_t size,
const u8* el_p = p+ofs;
int err = dump_sym(child_id, el_p, state);
dump_error(err, el_p);
// there was no output for this child; undo its indentation (if any),
// skip everything below and proceed with the next child.
if(err == WDBG_SUPPRESS_OUTPUT)
{
if(!fits_on_one_line)
UNINDENT;
continue;
}
else
{
out(fits_on_one_line? L", " : L"\r\n");
displayed_anything = true;
}
}
displayed_anything = true;
dump_error(err, el_p); // nop if err == 0
out(fits_on_one_line? L", " : L"\r\n");
if(err == WDBG_SINGLE_SYMBOL_LIMIT)
break;
} // for each child
state.level--;
@ -1611,6 +1670,10 @@ static int dump_sym_unknown(DWORD type_id, const u8* p, DumpState state)
// delegates to dump_sym_* depending on the symbol's tag.
static int dump_sym(DWORD type_id, const u8* p, DumpState state)
{
int ret = out_check_limit();
if(ret != 0)
return ret;
DWORD type_tag;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_SYMTAG, &type_tag))
return WDBG_TYPE_INFO_UNAVAILABLE;
@ -1654,6 +1717,7 @@ static int dump_sym(DWORD type_id, const u8* p, DumpState state)
// called from dump_frame_cb for each local symbol; lock is held.
static BOOL CALLBACK dump_sym_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
{
out_latch_pos(); // see decl
mod_base = sym->ModBase;
const u8* p = (const u8*)sym->Address;
DumpState state;

View File

@ -218,8 +218,9 @@ static void detect_filesystem()
// if this fails, no problem - we have the default from above.
root_path[3] = '\0'; // cut off after "c:\"
char fs_name[32];
char fs_name[32] = {0};
BOOL ret = GetVolumeInformation(root_path, 0,0,0,0,0, fs_name, sizeof(fs_name));
fs_name[ARRAY_SIZE(fs_name)-1] = '\0';
debug_assert(ret != 0);
// if this fails, no problem - we really only care if fs is FAT,
// and will assume that's not the case (since fs_name != "FAT").

View File

@ -268,11 +268,13 @@ static void init_vkmap(SDLKey (&VK_keymap)[256])
inline SDLKey vkmap(int vk)
{
static SDLKey VK_SDLKMap[256]; // VK_SDLKMap[vk] == SDLK
ONCE( init_vkmap(VK_SDLKMap); );
debug_assert(vk >= 0 && vk < 256);
if(!(0 <= vk && vk < 256))
{
debug_warn("vkmap: invalid vk");
return SDLK_UNKNOWN;
}
return VK_SDLKMap[vk];
}
@ -1010,28 +1012,25 @@ int SDL_SemWait(SDL_sem* sem)
// threads
//
// users don't need to allocate SDL_Thread variables, so type = void
// API returns SDL_Thread*, which is the HANDLE value itself.
union pthread_sdl
{
pthread_t p;
SDL_Thread* s;
};
//
// we go through hoops to avoid type cast warnings;
// a simple union { pthread_t; SDL_Thread* } yields "uninitialized"
// warnings in VC2005, so we coerce values directly.
cassert(sizeof(pthread_t) == sizeof(SDL_Thread*));
SDL_Thread* SDL_CreateThread(int(*func)(void*), void* param)
{
pthread_sdl u;
if(pthread_create(&u.p, 0, (void*(*)(void*))func, param) < 0)
pthread_t thread = 0;
if(pthread_create(&thread, 0, (void*(*)(void*))func, param) < 0)
return 0;
return u.s; // TODO: uninitialised value?
return *(SDL_Thread**)&thread;
}
int SDL_KillThread(SDL_Thread* thread)
{
pthread_sdl u;
u.s = thread;
pthread_cancel(u.p);
pthread_cancel(*(pthread_t*)&thread);
return 0;
}