1
0
Fork 0

Implement DebugFlags command

This commit is contained in:
Duncan Ogilvie 2020-10-11 20:57:09 +02:00
parent 16cc39b331
commit 306449fa6b
9 changed files with 99 additions and 60 deletions

View File

@ -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;
}

View File

@ -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[]);

View File

@ -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);
}

View File

@ -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)
{

View File

@ -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();

View File

@ -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.

View File

@ -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])
{

View File

@ -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;

View File

@ -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)