Implement DebugFlags command
This commit is contained in:
parent
16cc39b331
commit
306449fa6b
|
|
@ -520,4 +520,17 @@ bool cbInstrDbdecompress(int argc, char* argv[])
|
|||
}
|
||||
dprintf_untranslated("Decompressed '%s'\n", argv[1]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool cbInstrDebugFlags(int argc, char* argv[])
|
||||
{
|
||||
if(argc < 2)
|
||||
{
|
||||
dprintf_untranslated("Usage: DebugFlags 0xFFFFFFFF\n");
|
||||
return false;
|
||||
}
|
||||
auto debugFlags = DbgValFromString(argv[1]);
|
||||
dbgsetdebugflags(debugFlags);
|
||||
dprintf_untranslated("DebugFlags = 0x%08X\n", debugFlags);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,4 +14,5 @@ bool cbInstrBriefcheck(int argc, char* argv[]);
|
|||
bool cbInstrFocusinfo(int argc, char* argv[]);
|
||||
bool cbInstrFlushlog(int argc, char* argv[]);
|
||||
bool cbInstrAnimateWait(int argc, char* argv[]);
|
||||
bool cbInstrDbdecompress(int argc, char* argv[]);
|
||||
bool cbInstrDbdecompress(int argc, char* argv[]);
|
||||
bool cbInstrDebugFlags(int argc, char* argv[]);
|
||||
|
|
@ -21,6 +21,7 @@ static void GuiAddLogMessageAsync(_In_z_ const char* msg)
|
|||
*/
|
||||
void dputs(_In_z_ const char* Text)
|
||||
{
|
||||
dprintf_untranslated("[%llu] ", (unsigned long long)time(nullptr));
|
||||
// Only append the newline if the caller didn't
|
||||
const char* TranslatedText = GuiTranslateText(Text);
|
||||
size_t textlen = strlen(TranslatedText);
|
||||
|
|
@ -58,6 +59,29 @@ void dprintf_untranslated(_In_z_ _Printf_format_string_ const char* Format, ...)
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
static double getTimeInMilliseconds()
|
||||
{
|
||||
static LARGE_INTEGER freq;
|
||||
static bool isInitialized = false;
|
||||
|
||||
if(isInitialized == false)
|
||||
{
|
||||
// Expensive crap.
|
||||
QueryPerformanceFrequency(&freq);
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
LARGE_INTEGER ct;
|
||||
QueryPerformanceCounter(&ct);
|
||||
|
||||
return ((double)ct.QuadPart * 1000.0) / (double)freq.QuadPart;
|
||||
}
|
||||
|
||||
static double getTimeInSeconds()
|
||||
{
|
||||
return getTimeInMilliseconds() / 1000.0;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Print a formatted string to the console.
|
||||
\param format The printf format to use (see documentation of printf for more information).
|
||||
|
|
@ -65,8 +89,15 @@ void dprintf_untranslated(_In_z_ _Printf_format_string_ const char* Format, ...)
|
|||
*/
|
||||
void dprintf_args(_In_z_ _Printf_format_string_ const char* Format, va_list Args)
|
||||
{
|
||||
static double startupTime = getTimeInSeconds();
|
||||
double dElapsed = getTimeInSeconds() - startupTime;
|
||||
int64_t elapsed = (int64_t)dElapsed;
|
||||
int64_t minutes = elapsed / 60;
|
||||
int64_t ms = (int64_t)((dElapsed - elapsed) * 1000.0);
|
||||
|
||||
char buffer[16384];
|
||||
vsnprintf_s(buffer, _TRUNCATE, GuiTranslateText(Format), Args);
|
||||
auto len = sprintf_s(buffer, "[%llu] ", (unsigned long long)time(nullptr));
|
||||
vsnprintf_s(buffer + len, _countof(buffer) - len, _TRUNCATE, GuiTranslateText(Format), Args);
|
||||
|
||||
GuiAddLogMessageAsync(buffer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ static duint pCreateProcessBase = 0;
|
|||
static duint pDebuggedEntry = 0;
|
||||
static bool bRepeatIn = false;
|
||||
static duint stepRepeat = 0;
|
||||
static bool isDetachedByUser = false;
|
||||
static bool bIsAttached = false;
|
||||
static bool bSkipExceptions = false;
|
||||
static duint skipExceptionCount = 0;
|
||||
|
|
@ -95,6 +94,7 @@ HANDLE mProcHandle;
|
|||
HANDLE mForegroundHandle;
|
||||
duint mRtrPreviousCSP = 0;
|
||||
HANDLE hDebugLoopThread = nullptr;
|
||||
DWORD dwDebugFlags = 0;
|
||||
|
||||
static duint dbgcleartracestate()
|
||||
{
|
||||
|
|
@ -326,11 +326,6 @@ void dbgsetsteprepeat(bool steppingIn, duint repeat)
|
|||
stepRepeat = repeat;
|
||||
}
|
||||
|
||||
void dbgsetisdetachedbyuser(bool b)
|
||||
{
|
||||
isDetachedByUser = b;
|
||||
}
|
||||
|
||||
void dbgsetfreezestack(bool freeze)
|
||||
{
|
||||
bFreezeStack = freeze;
|
||||
|
|
@ -402,6 +397,11 @@ bool dbgdeletedllbreakpoint(const char* mod, DWORD type)
|
|||
return true;
|
||||
}
|
||||
|
||||
void dbgsetdebugflags(DWORD flags)
|
||||
{
|
||||
dwDebugFlags = flags;
|
||||
}
|
||||
|
||||
bool dbghandledllbreakpoint(const char* mod, bool loadDll)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockDllBreakpoints);
|
||||
|
|
@ -1730,6 +1730,34 @@ static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll)
|
|||
cookie.HandleNtdllLoad(bIsAttached);
|
||||
if(settingboolget("Misc", "TransparentExceptionStepping"))
|
||||
exceptionDispatchAddr = DbgValFromString("ntdll:KiUserExceptionDispatcher");
|
||||
|
||||
//set debug flags
|
||||
if(dwDebugFlags != 0)
|
||||
{
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
auto info = ModInfoFromAddr(duint(base));
|
||||
if(info->symbols->isOpen())
|
||||
{
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Waiting until ntdll.dll symbols are loaded...\n"));
|
||||
info->symbols->waitUntilLoaded();
|
||||
SymbolInfo LdrpDebugFlags;
|
||||
if(info->symbols->findSymbolByName("LdrpDebugFlags", LdrpDebugFlags, true))
|
||||
{
|
||||
if(MemWrite(info->base + LdrpDebugFlags.rva, &dwDebugFlags, sizeof(dwDebugFlags)))
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Set LdrpDebugFlags to 0x%08X successfully!\n"), dwDebugFlags);
|
||||
else
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to write to LdrpDebugFlags\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Symbol 'LdrpDebugFlags' not found!\n"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to find LdrpDebugFlags (you need to load symbols for ntdll.dll)\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "DLL Loaded: %p %s\n"), base, DLLDebugFileName);
|
||||
|
|
@ -1866,20 +1894,6 @@ static void cbOutputDebugString(OUTPUT_DEBUG_STRING_INFO* DebugString)
|
|||
}
|
||||
}
|
||||
|
||||
static bool dbgdetachDisableAllBreakpoints(const BREAKPOINT* bp)
|
||||
{
|
||||
if(bp->enabled)
|
||||
{
|
||||
if(bp->type == BPNORMAL)
|
||||
DeleteBPX(bp->addr);
|
||||
else if(bp->type == BPMEMORY)
|
||||
RemoveMemoryBPX(bp->addr, 0);
|
||||
else if(bp->type == BPHARDWARE && TITANDRXVALID(bp->titantype))
|
||||
DeleteHardwareBreakPoint(TITANGETDRX(bp->titantype));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cbException(EXCEPTION_DEBUG_INFO* ExceptionData)
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
|
|
@ -1900,24 +1914,7 @@ static void cbException(EXCEPTION_DEBUG_INFO* ExceptionData)
|
|||
return;
|
||||
}
|
||||
}
|
||||
if(ExceptionData->ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
|
||||
{
|
||||
if(isDetachedByUser)
|
||||
{
|
||||
PLUG_CB_DETACH detachInfo;
|
||||
detachInfo.fdProcessInfo = fdProcessInfo;
|
||||
plugincbcall(CB_DETACH, &detachInfo);
|
||||
BpEnumAll(dbgdetachDisableAllBreakpoints); // Disable all software breakpoints before detaching.
|
||||
if(!DetachDebuggerEx(fdProcessInfo->dwProcessId))
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "DetachDebuggerEx failed..."));
|
||||
else
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Detached!"));
|
||||
isDetachedByUser = false;
|
||||
_dbg_animatestop(); // Stop animating
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(ExceptionData->ExceptionRecord.ExceptionCode == MS_VC_EXCEPTION) //SetThreadName exception
|
||||
if(ExceptionData->ExceptionRecord.ExceptionCode == MS_VC_EXCEPTION) //SetThreadName exception
|
||||
{
|
||||
THREADNAME_INFO nameInfo; //has no valid local pointers
|
||||
memcpy(&nameInfo, ExceptionData->ExceptionRecord.ExceptionInformation, sizeof(THREADNAME_INFO));
|
||||
|
|
@ -1996,21 +1993,6 @@ static void cbAttachDebugger()
|
|||
varset("$pid", fdProcessInfo->dwProcessId, true);
|
||||
}
|
||||
|
||||
void cbDetach()
|
||||
{
|
||||
if(!isDetachedByUser)
|
||||
return;
|
||||
PLUG_CB_DETACH detachInfo;
|
||||
detachInfo.fdProcessInfo = fdProcessInfo;
|
||||
plugincbcall(CB_DETACH, &detachInfo);
|
||||
BpEnumAll(dbgdetachDisableAllBreakpoints); // Disable all software breakpoints before detaching.
|
||||
if(!DetachDebuggerEx(fdProcessInfo->dwProcessId))
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "DetachDebuggerEx failed..."));
|
||||
else
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Detached!"));
|
||||
return;
|
||||
}
|
||||
|
||||
cmdline_qoutes_placement_t getqoutesplacement(const char* cmdline)
|
||||
{
|
||||
cmdline_qoutes_placement_t quotesPos;
|
||||
|
|
@ -2815,7 +2797,6 @@ static void debugLoopFunction(void* lpParameter, bool attach)
|
|||
pDebuggedEntry = 0;
|
||||
pDebuggedBase = 0;
|
||||
pCreateProcessBase = 0;
|
||||
isDetachedByUser = false;
|
||||
hActiveThread = nullptr;
|
||||
if(!gDllLoader.empty()) //Delete the DLL loader (#1496)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ void DebugSetBreakpoints();
|
|||
void GuiSetDebugStateAsync(DBGSTATE state);
|
||||
void dbgsetskipexceptions(bool skip);
|
||||
void dbgsetsteprepeat(bool steppingIn, duint repeat);
|
||||
void dbgsetisdetachedbyuser(bool b);
|
||||
void dbgsetfreezestack(bool freeze);
|
||||
void dbgclearignoredexceptions();
|
||||
void dbgaddignoredexception(ExceptionRange range);
|
||||
|
|
@ -81,6 +80,7 @@ bool dbggetwintext(std::vector<std::string>* winTextList, const DWORD dwProcessI
|
|||
void dbgtracebrowserneedsupdate();
|
||||
bool dbgsetdllbreakpoint(const char* mod, DWORD type, bool singleshoot);
|
||||
bool dbgdeletedllbreakpoint(const char* mod, DWORD type);
|
||||
void dbgsetdebugflags(DWORD flags);
|
||||
|
||||
void cbStep();
|
||||
void cbRtrStep();
|
||||
|
|
@ -99,7 +99,6 @@ void cbTraceIntoIntoTraceRecordStep();
|
|||
void cbTraceOverIntoTraceRecordStep();
|
||||
void cbRunToUserCodeBreakpoint(void* ExceptionAddress);
|
||||
DWORD WINAPI threadAttachLoop(void* lpParameter);
|
||||
void cbDetach();
|
||||
bool cbSetModuleBreakpoints(const BREAKPOINT* bp);
|
||||
EXCEPTION_DEBUG_INFO & getLastExceptionInfo();
|
||||
bool dbgrestartadmin();
|
||||
|
|
|
|||
|
|
@ -124,7 +124,12 @@ public:
|
|||
|
||||
virtual bool cancelLoading()
|
||||
{
|
||||
return false;
|
||||
return false; // Stub
|
||||
}
|
||||
|
||||
virtual void waitUntilLoaded()
|
||||
{
|
||||
// Stub
|
||||
}
|
||||
|
||||
// Get the symbol at the specified address, will return false if not found.
|
||||
|
|
|
|||
|
|
@ -97,6 +97,12 @@ bool SymbolSourceDIA::cancelLoading()
|
|||
return true;
|
||||
}
|
||||
|
||||
void SymbolSourceDIA::waitUntilLoaded()
|
||||
{
|
||||
while(isLoading())
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
template<size_t Count>
|
||||
static bool startsWith(const char* str, const char(&prefix)[Count])
|
||||
{
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ public:
|
|||
|
||||
virtual bool cancelLoading() override;
|
||||
|
||||
virtual void waitUntilLoaded() override;
|
||||
|
||||
virtual bool findSymbolExact(duint rva, SymbolInfo & symInfo) override;
|
||||
|
||||
virtual bool findSymbolExactOrLower(duint rva, SymbolInfo & symInfo) override;
|
||||
|
|
|
|||
|
|
@ -444,6 +444,7 @@ static void registercommands()
|
|||
dbgcmdnew("flushlog", cbInstrFlushlog, false); //flush the log
|
||||
dbgcmdnew("AnimateWait", cbInstrAnimateWait, true); //Wait for the debuggee to pause.
|
||||
dbgcmdnew("dbdecompress", cbInstrDbdecompress, false); //Decompress a database.
|
||||
dbgcmdnew("DebugFlags", cbInstrDebugFlags, false); //Set ntdll LdrpDebugFlags
|
||||
};
|
||||
|
||||
bool cbCommandProvider(char* cmd, int maxlen)
|
||||
|
|
|
|||
Loading…
Reference in New Issue