Mercurial > projects > ddbg_continued
view src/util.d @ 1:4a9dcbd9e54f
-files of 0.13 beta
-fixes so that it now compiles with the current dmd version
author | marton@basel.hu |
---|---|
date | Tue, 05 Apr 2011 20:44:01 +0200 |
parents | |
children |
line wrap: on
line source
/* Ddbg - Win32 Debugger for the D programming language * Copyright (c) 2007 Jascha Wetzel * All rights reserved. See LICENSE.TXT for details. */ import std.ctype; import std.stdio; import std.string; import std.c.string; import std.c.stdio; import std.format; import std.date : getUTCtime, d_time, TicksPerSecond; import std.demangle; import win32.winbase; import win32.windef; import std.typeinfo.ti_AC; import std.typeinfo.ti_Acdouble; import std.typeinfo.ti_Acfloat; import std.typeinfo.ti_Acreal; import std.typeinfo.ti_Adouble; import std.typeinfo.ti_Afloat; import std.typeinfo.ti_Ag; import std.typeinfo.ti_Aint; import std.typeinfo.ti_Along; import std.typeinfo.ti_Areal; import std.typeinfo.ti_Ashort; import std.typeinfo.ti_byte; import std.typeinfo.ti_C; import std.typeinfo.ti_cdouble; import std.typeinfo.ti_cfloat; import std.typeinfo.ti_char; import std.typeinfo.ti_creal; import std.typeinfo.ti_dchar; import std.typeinfo.ti_delegate; import std.typeinfo.ti_double; import std.typeinfo.ti_float; import std.typeinfo.ti_idouble; import std.typeinfo.ti_ifloat; import std.typeinfo.ti_int; import std.typeinfo.ti_ireal; import std.typeinfo.ti_long; import std.typeinfo.ti_ptr; import std.typeinfo.ti_real; import std.typeinfo.ti_short; import std.typeinfo.ti_ubyte; import std.typeinfo.ti_uint; import std.typeinfo.ti_ulong; import std.typeinfo.ti_ushort; import std.typeinfo.ti_void; import std.typeinfo.ti_wchar; /************************************************************************************************** **************************************************************************************************/ T dmax(T)(T a, T b) { return a<b?b:a; } T dmin(T)(T a, T b) { return a>b?b:a; } /************************************************************************************************** **************************************************************************************************/ uint intFromStr(string str) { uint i; foreach_reverse ( c; str ) i = i<<8 | c; return i; } /************************************************************************************************** **************************************************************************************************/ string itoa(uint i) { if ( i == 0 ) return "0"; string str; for ( ; i > 0; i /= 10 ) str = "0123456789"[i%10] ~ str; return str; } /************************************************************************************************** **************************************************************************************************/ string TODO(string file, uint line, string msg) { return "TODO - "~file~"("~itoa(line)~"): "~msg~""; } /************************************************************************************************** **************************************************************************************************/ string formatTicks(ulong ticks) { SYSTEMTIME stime; if ( !FileTimeToSystemTime(cast(FILETIME*)&ticks, &stime) ) return "invalid"; string str = format("%02d:%02d:%02d.%03d", stime.wHour, stime.wMinute, stime.wSecond, stime.wMilliseconds); return str; } /************************************************************************************************** Name lookup for win32 DebugEventCodes. **************************************************************************************************/ string getEventName(uint event) { switch ( event ) { case EXCEPTION_DEBUG_EVENT : return "EXCEPTION_DEBUG_EVENT"; case CREATE_THREAD_DEBUG_EVENT : return "CREATE_THREAD_DEBUG_EVENT"; case CREATE_PROCESS_DEBUG_EVENT : return "CREATE_PROCESS_DEBUG_EVENT"; case EXIT_THREAD_DEBUG_EVENT : return "EXIT_THREAD_DEBUG_EVENT"; case EXIT_PROCESS_DEBUG_EVENT : return "EXIT_PROCESS_DEBUG_EVENT"; case LOAD_DLL_DEBUG_EVENT : return "LOAD_DLL_DEBUG_EVENT"; case UNLOAD_DLL_DEBUG_EVENT : return "UNLOAD_DLL_DEBUG_EVENT"; case OUTPUT_DEBUG_STRING_EVENT : return "OUTPUT_DEBUG_STRING_EVENT"; case RIP_EVENT: return "RIP_EVENT"; default : break; } return ""; } /************************************************************************************************** Name lookup for win32 ExceptionCodes. **************************************************************************************************/ string getExceptionName(uint excpt) { switch ( excpt ) { case EXCEPTION_ACCESS_VIOLATION : return "EXCEPTION_ACCESS_VIOLATION"; case EXCEPTION_ARRAY_BOUNDS_EXCEEDED : return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; case EXCEPTION_BREAKPOINT : return "EXCEPTION_BREAKPOINT"; case EXCEPTION_DATATYPE_MISALIGNMENT : return "EXCEPTION_DATATYPE_MISALIGNMENT"; case EXCEPTION_FLT_DENORMAL_OPERAND : return "EXCEPTION_FLT_DENORMAL_OPERAND"; case EXCEPTION_FLT_DIVIDE_BY_ZERO : return "EXCEPTION_FLT_DIVIDE_BY_ZERO"; case EXCEPTION_FLT_INEXACT_RESULT : return "EXCEPTION_FLT_INEXACT_RESULT"; case EXCEPTION_FLT_INVALID_OPERATION : return "EXCEPTION_FLT_INVALID_OPERATION"; case EXCEPTION_FLT_OVERFLOW : return "EXCEPTION_FLT_OVERFLOW"; case EXCEPTION_FLT_STACK_CHECK : return "EXCEPTION_FLT_STACK_CHECK"; case EXCEPTION_FLT_UNDERFLOW : return "EXCEPTION_FLT_UNDERFLOW"; case EXCEPTION_ILLEGAL_INSTRUCTION : return "EXCEPTION_ILLEGAL_INSTRUCTION"; case EXCEPTION_IN_PAGE_ERROR : return "EXCEPTION_IN_PAGE_ERROR"; case EXCEPTION_INT_DIVIDE_BY_ZERO : return "EXCEPTION_INT_DIVIDE_BY_ZERO"; case EXCEPTION_INT_OVERFLOW : return "EXCEPTION_INT_OVERFLOW"; case EXCEPTION_INVALID_DISPOSITION : return "EXCEPTION_INVALID_DISPOSITION"; case EXCEPTION_NONCONTINUABLE_EXCEPTION : return "EXCEPTION_NONCONTINUABLE_EXCEPTION"; case EXCEPTION_PRIV_INSTRUCTION : return "EXCEPTION_PRIV_INSTRUCTION"; case EXCEPTION_SINGLE_STEP : return "EXCEPTION_SINGLE_STEP"; case EXCEPTION_STACK_OVERFLOW : return "EXCEPTION_STACK_OVERFLOW"; default : break; } return ""; } /************************************************************************************************** Wrapper for Win32 GetLastError. **************************************************************************************************/ string lastError() { char[4096] msg; FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, null, GetLastError(), 0, msg.ptr, msg.length, null); return msg[0..strlen(msg.ptr)]; } /************************************************************************************************** Simplified number parser for prefixes. Returns: number represented by the prefix of name, 0 else **************************************************************************************************/ uint parseNumber(inout string name) { uint res; int i; while ( name.length > 0 ) { if ( !isdigit(name[0]) ) break; res = res*10+(name[0]-'0'); name = name[1..$]; } return res; } /************************************************************************************************** **************************************************************************************************/ string typeFromMangled(string mangled) { if ( mangled is null || mangled.length < 4 || mangled[0..2] != "_D" || !isdigit(mangled[2]) ) return null; string type = mangled[1..$]; // skip symbol name while ( type.length > 1 && type[0] == 'D' && isdigit(type[1]) ) { type = type[1..$]; uint len = parseNumber(type); type = type[len..$]; } return type; } /************************************************************************************************** **************************************************************************************************/ string mangleName(string name) { string mangled; string[] idents = split(name, "."); foreach ( string id; idents ) mangled ~= .toString(id.length)~id; return mangled; } /************************************************************************************************** **************************************************************************************************/ string demangleType(string mangled) { return demangle("_D0"~mangled); } /************************************************************************************************** **************************************************************************************************/ string demangleNameSkip(inout string mangled) { string name; do { uint len = parseNumber(mangled); if ( len <= 0 || len > mangled.length ) return null; if ( name.length > 0 ) name ~= "."; name ~= mangled[0..len]; mangled = mangled[len..$]; } while ( mangled.length > 0 ); return name; } /************************************************************************************************** **************************************************************************************************/ string demangleName(string mangled) { string name; if ( mangled.length > 2 && mangled[0..2] == "_D" && isNumeric(mangled[2]) ) mangled = mangled[2..$]; else return mangled; do { uint len = parseNumber(mangled); while ( len <= 0 && mangled.length > 0 ) { mangled = mangled[1..$]; len = parseNumber(mangled); } if ( len <= 0 || len > mangled.length ) return name; if ( name.length > 0 ) name ~= "."; name ~= mangled[0..len]; mangled = mangled[len..$]; } while ( mangled.length > 0 ); return name; } /************************************************************************************************** Wraps win32 stdio functions. Respects io redirection into pipes. **************************************************************************************************/ class DbgIO { static HANDLE ddb_read, ddb_write; static string buffer; /********************************************************************************************** **********************************************************************************************/ static this() { ddb_read = GetStdHandle(STD_INPUT_HANDLE); ddb_write = GetStdHandle(STD_OUTPUT_HANDLE); } /********************************************************************************************** **********************************************************************************************/ static string readln() { char[128] buf; uint read; int nl_index; do { ReadFile(ddb_read, buf.ptr, buf.length, &read, null); buffer ~= buf[0..read]; nl_index = find(buffer, '\n'); } while ( nl_index < 0 ); string ret = buffer[0..nl_index]; buffer = buffer[nl_index+1..$]; return ret; } /********************************************************************************************** **********************************************************************************************/ static void print(...) { string str; void putc(dchar c) { str ~= c; } doFormat(&putc, _arguments, _argptr); uint written; WriteFile(ddb_write, str.ptr, str.length, &written, null); } /********************************************************************************************** **********************************************************************************************/ static void println(...) { string str; void putc(dchar c) { str ~= c; } doFormat(&putc, _arguments, _argptr); uint written; str ~= '\n'; WriteFile(ddb_write, str.ptr, str.length, &written, null); } /********************************************************************************************** **********************************************************************************************/ static void write(string str) { uint written; WriteFile(ddb_write, str.ptr, str.length, &written, null); } /********************************************************************************************** **********************************************************************************************/ static void writeln(string str) { uint written; str ~= "\n"; WriteFile(ddb_write, str.ptr, str.length, &written, null); } } /************************************************************************************************** **************************************************************************************************/ TypeInfo TypeInfoFromMangled(string mangled) { TypeInfo res; TypeInfo* ti = &res; for ( uint i=0; ti !is null && i < mangled.length; ++i ) { switch ( mangled[i] ) { case 'C': debug DbgIO.println("TypeInfoFromMangled: classinfos not supported, yet"); return null; case 'P': TypeInfo_Pointer tip = new TypeInfo_Pointer; *ti = tip; ti = &tip.m_next; break; case 'G': TypeInfo_StaticArray tia = new TypeInfo_StaticArray; *ti = tia; ti = &tia.value; break; case 'A': switch ( mangled[i+1] ) { case 'v': *ti = new TypeInfo_Av; ti = null; break; case 'x': case 'b': *ti = new TypeInfo_Ab; ti = null; break; case 'g': *ti = new TypeInfo_Ag; ti = null; break; case 'h': *ti = new TypeInfo_Ah; ti = null; break; case 's': *ti = new TypeInfo_As; ti = null; break; case 't': *ti = new TypeInfo_At; ti = null; break; case 'i': *ti = new TypeInfo_Ai; ti = null; break; case 'k': *ti = new TypeInfo_Ak; ti = null; break; case 'l': *ti = new TypeInfo_Al; ti = null; break; case 'm': *ti = new TypeInfo_Am; ti = null; break; case 'f': *ti = new TypeInfo_Af; ti = null; break; case 'd': *ti = new TypeInfo_Ad; ti = null; break; case 'e': *ti = new TypeInfo_Ae; ti = null; break; case 'o': *ti = new TypeInfo_Ao; ti = null; break; case 'p': *ti = new TypeInfo_Ap; ti = null; break; case 'j': *ti = new TypeInfo_Aj; ti = null; break; case 'q': *ti = new TypeInfo_Aq; ti = null; break; case 'r': *ti = new TypeInfo_Ar; ti = null; break; case 'c': *ti = new TypeInfo_Ac; ti = null; break; case 'a': *ti = new TypeInfo_Aa; ti = null; break; case 'u': *ti = new TypeInfo_Au; ti = null; break; case 'w': *ti = new TypeInfo_Aw; ti = null; break; default: TypeInfo_Array tia = new TypeInfo_Array; *ti = tia; ti = &tia.value; } break; case 'v': *ti = new TypeInfo_v; ti = null; break; case 'x': case 'b': *ti = new TypeInfo_b; ti = null; break; case 'g': *ti = new TypeInfo_g; ti = null; break; case 'h': *ti = new TypeInfo_h; ti = null; break; case 's': *ti = new TypeInfo_s; ti = null; break; case 't': *ti = new TypeInfo_t; ti = null; break; case 'i': *ti = new TypeInfo_i; ti = null; break; case 'k': *ti = new TypeInfo_k; ti = null; break; case 'l': *ti = new TypeInfo_l; ti = null; break; case 'm': *ti = new TypeInfo_m; ti = null; break; case 'f': *ti = new TypeInfo_f; ti = null; break; case 'd': *ti = new TypeInfo_d; ti = null; break; case 'e': *ti = new TypeInfo_e; ti = null; break; case 'o': *ti = new TypeInfo_o; ti = null; break; case 'p': *ti = new TypeInfo_p; ti = null; break; case 'j': *ti = new TypeInfo_j; ti = null; break; case 'q': *ti = new TypeInfo_q; ti = null; break; case 'r': *ti = new TypeInfo_r; ti = null; break; case 'c': *ti = new TypeInfo_c; ti = null; break; case 'a': *ti = new TypeInfo_a; ti = null; break; case 'u': *ti = new TypeInfo_u; ti = null; break; case 'w': *ti = new TypeInfo_w; ti = null; break; default: debug DbgIO.println("unknown mangled type "~mangled[i]); assert(0); } } return res; } /************************************************************************************************** **************************************************************************************************/ class DataReader { ubyte[] data; uint cursor; /********************************************************************************************** **********************************************************************************************/ this(ubyte[] d) { data = d; } /********************************************************************************************** **********************************************************************************************/ void alignCursor(ubyte num) { cursor += (num + cursor) % num; assert(cursor<=data.length); } /********************************************************************************************** **********************************************************************************************/ bool available() { return cursor<data.length; } /********************************************************************************************** **********************************************************************************************/ void seek(uint offset) { cursor=offset; if ( cursor > data.length ) throw new Exception("DataReader.seek beyond end of data offset="~.toString(cursor)~", $="~.toString(data.length)); } /********************************************************************************************** **********************************************************************************************/ void relseek(int offset) { cursor+=offset; if ( cursor > data.length ) throw new Exception("DataReader.seek beyond end of data offset="~.toString(cursor)~", $="~.toString(data.length)); } /********************************************************************************************** **********************************************************************************************/ void peek(out ubyte val) { assert(cursor<data.length); val = data[cursor]; } /********************************************************************************************** **********************************************************************************************/ void read(out ubyte val) { assert(cursor<data.length); val = data[cursor]; ++cursor; } void read(out char val) { read(*cast(ubyte*)&val); } /********************************************************************************************** **********************************************************************************************/ void read(out ushort val) { assert(cursor+1<data.length); val = (cast(ushort[])(data[cursor..cursor+2]))[0]; cursor+=2; } void read(out short val) { read(*cast(ushort*)&val); } /********************************************************************************************** **********************************************************************************************/ void read(out uint val) { assert(cursor+3<data.length); val = (cast(uint[])(data[cursor..cursor+4]))[0]; cursor+=4; } void read(out int val) { read(*cast(uint*)&val); } void read(out float val) { read(*cast(uint*)&val); } /********************************************************************************************** **********************************************************************************************/ void read(out ulong val) { assert(cursor+7<data.length); val = (cast(ulong[])(data[cursor..cursor+8]))[0]; cursor+=8; } void read(out long val) { read(*cast(ulong*)&val); } void read(out double val) { read(*cast(ulong*)&val); } void read(out cfloat val) { read(*cast(ulong*)&val); } /********************************************************************************************** **********************************************************************************************/ void read(out real val) { assert(cursor+9<data.length); val = (cast(real[])(data[cursor..cursor+10]))[0]; cursor+=10; } /********************************************************************************************** **********************************************************************************************/ void read(out string str) { assert(cursor<data.length); ushort len = data[cursor++]; if ( len >= 0xff && data[cursor] == 0 ) { ++cursor; read(len); } assert(cursor+len<=data.length, "dr cursor="~.toString(cursor)~" len="~.toString(len)); str = (cast(string)data)[cursor..cursor+len]; cursor+=len; } /********************************************************************************************** **********************************************************************************************/ void readA(T)(out T[] array, uint length) { uint size = length*T.sizeof; assert(cursor<=data.length-size); array = cast(T[])(data[cursor..cursor+size]); cursor+=size; } } /************************************************************************************************** **************************************************************************************************/ string getFullPath(string filename) { char[] fullpath; char* filepart; fullpath.length = 4096; int len = GetFullPathName( toStringz(filename), fullpath.length, fullpath.ptr, &filepart ); if ( len <= 0 ) return null; fullpath.length = len; char[] longfullpath; longfullpath.length = 4096; len = GetLongPathName( toStringz(fullpath), longfullpath.ptr, longfullpath.length ); longfullpath.length = len; return longfullpath; } /************************************************************************************************** **************************************************************************************************/ struct DbgTimer { d_time time; void start() { time = getUTCtime; } string finish() { time = getUTCtime - time; return format("%d'%03d", time / TicksPerSecond, time % TicksPerSecond); } }