DBG: better heuristics for detecting the debuggee did not terminate after 10 seconds
This commit is contained in:
parent
8a07bd2d7e
commit
7212e853fb
|
@ -161,6 +161,7 @@ bool cbDebugStop(int argc, char* argv[])
|
|||
//history
|
||||
HistoryClear();
|
||||
DWORD BeginTick = GetTickCount();
|
||||
bool shownWarning = false;
|
||||
|
||||
while(true)
|
||||
{
|
||||
|
@ -174,15 +175,24 @@ bool cbDebugStop(int argc, char* argv[])
|
|||
{
|
||||
unlock(WAITID_RUN);
|
||||
DWORD CurrentTick = GetTickCount();
|
||||
if(CurrentTick - BeginTick > 10000)
|
||||
DWORD TimeElapsed = CurrentTick - BeginTick;
|
||||
if(TimeElapsed >= 10000)
|
||||
{
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "The debuggee does not stop after 10 seconds. The debugger state may be corrupted."));
|
||||
DbSave(DbLoadSaveType::All);
|
||||
TerminateThread(hDebugLoopThreadCopy, 1); // TODO: this will lose state and cause possible corruption if a critical section is still owned
|
||||
CloseHandle(hDebugLoopThreadCopy);
|
||||
return false;
|
||||
if(!shownWarning)
|
||||
{
|
||||
shownWarning = true;
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Finalizing the debugger thread took more than 10 seconds. This can happen if you are loading large symbol files or saving a large database."));
|
||||
}
|
||||
if(IsFileBeingDebugged() || TimeElapsed >= 100000)
|
||||
{
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "The debuggee did not stop after 10 seconds of requesting termination. The debugger state may be corrupted. It is recommended to restart x64dbg."));
|
||||
DbSave(DbLoadSaveType::All);
|
||||
TerminateThread(hDebugLoopThreadCopy, 1); // TODO: this will lose state and cause possible corruption if a critical section is still owned
|
||||
CloseHandle(hDebugLoopThreadCopy);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(CurrentTick - BeginTick >= 300)
|
||||
if(TimeElapsed >= 300)
|
||||
TerminateProcess(fdProcessInfo->hProcess, -1);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -444,7 +444,7 @@ std::string PDBDiaFile::getSymbolUndecoratedNameString(IDiaSymbol* sym)
|
|||
return result;
|
||||
}
|
||||
|
||||
bool PDBDiaFile::enumerateLineNumbers(uint32_t rva, uint32_t size, std::vector<DiaLineInfo_t> & lines, std::map<DWORD, std::string> & files)
|
||||
bool PDBDiaFile::enumerateLineNumbers(uint32_t rva, uint32_t size, std::vector<DiaLineInfo_t> & lines, std::map<DWORD, std::string> & files, const std::atomic<bool> & cancelled)
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD lineNumber = 0;
|
||||
|
@ -465,49 +465,69 @@ bool PDBDiaFile::enumerateLineNumbers(uint32_t rva, uint32_t size, std::vector<D
|
|||
return true;
|
||||
|
||||
lines.reserve(lines.size() + lineCount);
|
||||
std::vector<IDiaLineNumber*> lineNumbers;
|
||||
lineNumbers.resize(lineCount);
|
||||
|
||||
ULONG fetched = 0;
|
||||
hr = lineNumbersEnum->Next(lineCount, lineNumbers.data(), &fetched);
|
||||
for(ULONG n = 0; n < fetched; n++)
|
||||
const ULONG bucket = 10000;
|
||||
ULONG steps = lineCount / bucket + (lineCount % bucket != 0);
|
||||
for(ULONG step = 0; step < steps; step++)
|
||||
{
|
||||
CComPtr<IDiaLineNumber> lineNumberInfo;
|
||||
lineNumberInfo.Attach(lineNumbers[n]);
|
||||
ULONG begin = step * bucket;
|
||||
ULONG end = min(lineCount, (step + 1) * bucket);
|
||||
|
||||
DWORD sourceFileId = 0;
|
||||
hr = lineNumberInfo->get_sourceFileId(&sourceFileId);
|
||||
if(!SUCCEEDED(hr))
|
||||
continue;
|
||||
if(cancelled)
|
||||
return false;
|
||||
|
||||
if(!files.count(sourceFileId))
|
||||
std::vector<IDiaLineNumber*> lineNumbers;
|
||||
ULONG lineCountStep = end - begin;
|
||||
lineNumbers.resize(lineCountStep);
|
||||
|
||||
ULONG fetched = 0;
|
||||
hr = lineNumbersEnum->Next((ULONG)lineNumbers.size(), lineNumbers.data(), &fetched);
|
||||
for(ULONG n = 0; n < fetched; n++)
|
||||
{
|
||||
CComPtr<IDiaSourceFile> sourceFile;
|
||||
hr = lineNumberInfo->get_sourceFile(&sourceFile);
|
||||
if(cancelled)
|
||||
{
|
||||
for(ULONG m = n; m < fetched; m++)
|
||||
lineNumbers[m]->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
CComPtr<IDiaLineNumber> lineNumberInfo;
|
||||
lineNumberInfo.Attach(lineNumbers[n]);
|
||||
|
||||
DWORD sourceFileId = 0;
|
||||
hr = lineNumberInfo->get_sourceFileId(&sourceFileId);
|
||||
if(!SUCCEEDED(hr))
|
||||
continue;
|
||||
|
||||
BSTR fileName = nullptr;
|
||||
hr = sourceFile->get_fileName(&fileName);
|
||||
if(!files.count(sourceFileId))
|
||||
{
|
||||
CComPtr<IDiaSourceFile> sourceFile;
|
||||
hr = lineNumberInfo->get_sourceFile(&sourceFile);
|
||||
if(!SUCCEEDED(hr))
|
||||
continue;
|
||||
|
||||
BSTR fileName = nullptr;
|
||||
hr = sourceFile->get_fileName(&fileName);
|
||||
if(!SUCCEEDED(hr))
|
||||
continue;
|
||||
|
||||
files.insert({ sourceFileId, StringUtils::Utf16ToUtf8(fileName) });
|
||||
SysFreeString(fileName);
|
||||
}
|
||||
|
||||
DiaLineInfo_t lineInfo;
|
||||
lineInfo.sourceFileId = sourceFileId;
|
||||
|
||||
hr = lineNumberInfo->get_lineNumber(&lineInfo.lineNumber);
|
||||
if(!SUCCEEDED(hr))
|
||||
continue;
|
||||
|
||||
files.insert({ sourceFileId, StringUtils::Utf16ToUtf8(fileName) });
|
||||
SysFreeString(fileName);
|
||||
hr = lineNumberInfo->get_relativeVirtualAddress(&lineInfo.rva);
|
||||
if(!SUCCEEDED(hr))
|
||||
continue;
|
||||
|
||||
lines.push_back(lineInfo);
|
||||
}
|
||||
|
||||
DiaLineInfo_t lineInfo;
|
||||
lineInfo.sourceFileId = sourceFileId;
|
||||
|
||||
hr = lineNumberInfo->get_lineNumber(&lineInfo.lineNumber);
|
||||
if(!SUCCEEDED(hr))
|
||||
continue;
|
||||
|
||||
hr = lineNumberInfo->get_relativeVirtualAddress(&lineInfo.rva);
|
||||
if(!SUCCEEDED(hr))
|
||||
continue;
|
||||
|
||||
lines.push_back(lineInfo);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <atomic>
|
||||
|
||||
struct IDiaDataSource;
|
||||
struct IDiaSession;
|
||||
|
@ -50,7 +51,7 @@ public:
|
|||
|
||||
bool close();
|
||||
|
||||
bool enumerateLineNumbers(uint32_t rva, uint32_t size, std::vector<DiaLineInfo_t> & lines, std::map<DWORD, std::string> & files);
|
||||
bool enumerateLineNumbers(uint32_t rva, uint32_t size, std::vector<DiaLineInfo_t> & lines, std::map<DWORD, std::string> & files, const std::atomic<bool> & cancelled);
|
||||
|
||||
bool enumerateLexicalHierarchy(const Query_t & query);
|
||||
|
||||
|
|
|
@ -99,10 +99,6 @@ bool SymbolSourceDIA::cancelLoading()
|
|||
return true;
|
||||
}
|
||||
|
||||
void SymbolSourceDIA::loadPDBAsync()
|
||||
{
|
||||
}
|
||||
|
||||
template<size_t Count>
|
||||
static bool startsWith(const char* str, const char(&prefix)[Count])
|
||||
{
|
||||
|
@ -257,12 +253,12 @@ bool SymbolSourceDIA::loadSourceLinesAsync()
|
|||
std::vector<DiaLineInfo_t> lines;
|
||||
std::map<DWORD, String> files;
|
||||
|
||||
if(!pdb.enumerateLineNumbers(0, uint32_t(_imageSize), lines, files))
|
||||
if(!pdb.enumerateLineNumbers(0, uint32_t(_imageSize), lines, files, _requiresShutdown))
|
||||
return false;
|
||||
|
||||
if(files.size() == 1)
|
||||
{
|
||||
GuiSymbolLogAdd(StringUtils::sprintf("[%p, %s] Since there is only one file, attempting line overflow detection..\n", _imageBase, _modname.c_str()).c_str());
|
||||
GuiSymbolLogAdd(StringUtils::sprintf("[%p, %s] Since there is only one file, attempting line overflow detection (%ums)..\n", _imageBase, _modname.c_str(), GetTickCount() - lineLoadStart).c_str());
|
||||
|
||||
// This is a super hack to adjust for the (undocumented) limit of 16777215 lines (unsigned 24 bits maximum).
|
||||
// It is unclear at this point if yasm/coff/link/pdb is causing this issue.
|
||||
|
@ -271,6 +267,9 @@ bool SymbolSourceDIA::loadSourceLinesAsync()
|
|||
uint32_t maxLine = 0, maxRva = 0, lineOverflows = 0;
|
||||
for(auto & line : lines)
|
||||
{
|
||||
if(_requiresShutdown)
|
||||
return false;
|
||||
|
||||
uint32_t overflowValue = 0x1000000 * (lineOverflows + 1) - 1; //0xffffff, 0x1ffffff, 0x2ffffff, etc
|
||||
if((line.lineNumber & 0xfffff0) == 0 && (maxLine & 0xfffffff0) == (overflowValue & 0xfffffff0)) // allow 16 lines of play, perhaps there is a label/comment on line 0xffffff+1
|
||||
{
|
||||
|
@ -294,6 +293,7 @@ bool SymbolSourceDIA::loadSourceLinesAsync()
|
|||
|
||||
_linesData.reserve(lines.size());
|
||||
_sourceFiles.reserve(files.size());
|
||||
|
||||
for(const auto & line : lines)
|
||||
{
|
||||
if(_requiresShutdown)
|
||||
|
|
|
@ -147,7 +147,6 @@ public:
|
|||
bool loadPDB(const std::string & path, const std::string & modname, duint imageBase, duint imageSize, DiaValidationData_t* validationData);
|
||||
|
||||
private:
|
||||
void loadPDBAsync();
|
||||
bool loadSymbolsAsync();
|
||||
bool loadSourceLinesAsync();
|
||||
uint32_t findSourceFile(const std::string & fileName) const;
|
||||
|
|
Loading…
Reference in New Issue