1
0
Fork 0

Merge branch 'development' into patch00000092

This commit is contained in:
torusrxxx 2018-10-12 20:50:28 +08:00
commit cf1498786c
22 changed files with 261 additions and 134 deletions

View File

@ -66,3 +66,6 @@
0xC0150010 STATUS_SXS_INVALID_DEACTIVATION
0xE0434352 CLR_EXCEPTION
0xE06D7363 CPP_EH_EXCEPTION
0xC06D0057 VCPP_EXCEPTION_ERROR_INVALID_PARAMETER
0xC06D007E VCPP_EXCEPTION_ERROR_MOD_NOT_FOUND
0xC06D007F VCPP_EXCEPTION_ERROR_PROC_NOT_FOUND

View File

@ -199,8 +199,10 @@ void TraceRecordManager::TraceExecute(duint address, duint size)
}
}
//See https://www.felixcloutier.com/x86/FXSAVE.html, max 512 bytes
#define memoryContentSize 512
static void HandleCapstoneOperand(const Zydis & cp, int opindex, DISASM_ARGTYPE* argType, duint* value, unsigned char* memoryContent, unsigned char* memorySize)
static void HandleCapstoneOperand(const Zydis & cp, int opindex, DISASM_ARGTYPE* argType, duint* value, unsigned char memoryContent[memoryContentSize], unsigned char* memorySize)
{
*value = cp.ResolveOpValue(opindex, [&cp](ZydisRegister reg)
{
@ -231,7 +233,7 @@ static void HandleCapstoneOperand(const Zydis & cp, int opindex, DISASM_ARGTYPE*
*value += ThreadGetLocalBase(ThreadGetId(hActiveThread));
}
*memorySize = op.size / 8;
if(DbgMemIsValidReadPtr(*value))
if(*memorySize <= memoryContentSize && DbgMemIsValidReadPtr(*value))
{
MemRead(*value, memoryContent, max(op.size / 8, sizeof(duint)));
}
@ -253,23 +255,27 @@ void TraceRecordManager::TraceExecuteRecord(const Zydis & newInstruction)
REGDUMPWORD newContext;
//DISASM_INSTR newInstruction;
DWORD newThreadId;
duint newMemory[32];
duint newMemoryAddress[32];
duint oldMemory[32];
const size_t memoryArrayCount = 32;
duint newMemory[memoryArrayCount];
duint newMemoryAddress[memoryArrayCount];
duint oldMemory[memoryArrayCount];
unsigned char newMemoryArrayCount = 0;
DbgGetRegDumpEx(&newContext.registers, sizeof(REGDUMP));
newThreadId = ThreadGetId(hActiveThread);
// Don't try to resolve memory values for lea and nop instructions
if(!(newInstruction.IsNop() || newInstruction.GetId() == ZYDIS_MNEMONIC_LEA))
// Don't try to resolve memory values for invalid/lea/nop instructions
if(newInstruction.Success() && !newInstruction.IsNop() && newInstruction.GetId() != ZYDIS_MNEMONIC_LEA)
{
DISASM_ARGTYPE argType;
duint value;
unsigned char memoryContent[128];
unsigned char memoryContent[memoryContentSize];
unsigned char memorySize;
for(int i = 0; i < newInstruction.OpCount(); i++)
{
memset(memoryContent, 0, sizeof(memoryContent));
HandleCapstoneOperand(newInstruction, i, &argType, &value, memoryContent, &memorySize);
// check for overflow of the memory buffer
if(newMemoryArrayCount * sizeof(duint) + memorySize > memoryArrayCount * sizeof(duint))
continue;
// TODO: Implicit memory access by push and pop instructions
// TODO: Support memory value of ??? for invalid memory access
if(argType == arg_memory)
@ -305,7 +311,7 @@ void TraceRecordManager::TraceExecuteRecord(const Zydis & newInstruction)
newMemoryArrayCount++;
}
//TODO: PUSHAD/POPAD
assert(newMemoryArrayCount < 32);
assert(newMemoryArrayCount < memoryArrayCount);
}
if(rtPrevInstAvailable)
{

View File

@ -31,7 +31,18 @@ downslib_error downslib_download(const char* url,
{
DWORD dwLastError = GetLastError();
if(hFile != INVALID_HANDLE_VALUE)
{
bool doDelete = false;
LARGE_INTEGER fileSize;
if(dwLastError != ERROR_SUCCESS || (GetFileSizeEx(hFile, &fileSize) && fileSize.QuadPart == 0))
{
// an error occurred and now there is an empty or incomplete file that didn't exist before we came in
doDelete = true;
}
CloseHandle(hFile);
if(doDelete)
DeleteFileW(filename);
}
if(hUrl != NULL)
InternetCloseHandle(hUrl);
if(hInternet != NULL)
@ -39,7 +50,7 @@ downslib_error downslib_download(const char* url,
SetLastError(dwLastError);
});
hFile = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
hFile = CreateFileW(filename, GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return downslib_error::createfile;
@ -102,7 +113,10 @@ downslib_error downslib_download(const char* url,
// Call the callback to report progress and cancellation
if(cb && !cb(read_bytes, total_bytes))
{
SetLastError(ERROR_OPERATION_ABORTED);
return downslib_error::cancel;
}
// Exit if nothing more to read
if(dwRead == 0)
@ -112,7 +126,11 @@ downslib_error downslib_download(const char* url,
}
if(total_bytes > 0 && read_bytes != total_bytes)
{
SetLastError(ERROR_IO_INCOMPLETE);
return downslib_error::incomplete;
}
SetLastError(ERROR_SUCCESS);
return downslib_error::ok;
}

View File

@ -392,7 +392,10 @@ static int SymAutoComplete(const char* Search, char** Buffer, int MaxSymbols)
SHARED_ACQUIRE(LockModules);
auto modInfo = ModInfoFromAddr(base);
if(modInfo && modInfo->symbols->isOpen())
if(!modInfo)
continue;
if(modInfo->symbols->isOpen())
{
modInfo->symbols->findSymbolsByPrefix(prefix, [Buffer, MaxSymbols, &count](const SymbolInfo & symInfo)
{

View File

@ -1010,6 +1010,7 @@ extern "C" DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* pa
bVerboseExceptionLogging = settingboolget("Engine", "VerboseExceptionLogging");
bNoWow64SingleStepWorkaround = settingboolget("Engine", "NoWow64SingleStepWorkaround");
bQueryWorkingSet = settingboolget("Misc", "QueryWorkingSet");
bForceLoadSymbols = settingboolget("Misc", "ForceLoadSymbols");
stackupdatesettings();
duint setting;

View File

@ -364,6 +364,7 @@ bool cbInstrExhandlers(int argc, char* argv[])
bool cbInstrExinfo(int argc, char* argv[])
{
const unsigned int MASK_FACILITY_VISUALCPP = 0x006D0000;
auto info = getLastExceptionInfo();
const auto & record = info.ExceptionRecord;
dputs_untranslated("EXCEPTION_DEBUG_INFO:");
@ -373,6 +374,14 @@ bool cbInstrExinfo(int argc, char* argv[])
exceptionName = ErrorCodeToName(record.ExceptionCode);
if(exceptionName.size())
dprintf_untranslated(" ExceptionCode: %08X (%s)\n", record.ExceptionCode, exceptionName.c_str());
else if((record.ExceptionCode & MASK_FACILITY_VISUALCPP) == MASK_FACILITY_VISUALCPP) //delayhlp.cpp
{
auto possibleError = record.ExceptionCode & 0xFFFF;
exceptionName = ErrorCodeToName(possibleError);
if(!exceptionName.empty())
exceptionName = StringUtils::sprintf(" (Visual C++ %s)", exceptionName.c_str());
dprintf_untranslated(" ExceptionCode: %08X%s\n", record.ExceptionCode, exceptionName.c_str());
}
else
dprintf_untranslated(" ExceptionCode: %08X\n", record.ExceptionCode);
dprintf_untranslated(" ExceptionFlags: %08X\n", record.ExceptionFlags);

View File

@ -86,6 +86,7 @@ bool bNoForegroundWindow = false;
bool bVerboseExceptionLogging = true;
bool bNoWow64SingleStepWorkaround = false;
bool bTraceBrowserNeedsUpdate = false;
bool bForceLoadSymbols = false;
duint DbgEvents = 0;
duint maxSkipExceptionCount = 10000;
HANDLE mProcHandle;

View File

@ -123,6 +123,7 @@ extern bool bIgnoreInconsistentBreakpoints;
extern bool bNoForegroundWindow;
extern bool bVerboseExceptionLogging;
extern bool bNoWow64SingleStepWorkaround;
extern bool bForceLoadSymbols;
extern duint maxSkipExceptionCount;
extern HANDLE mProcHandle;
extern HANDLE mForegroundHandle;

View File

@ -114,13 +114,18 @@ static void ReadExportDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
// Note that we're loading this file because the debuggee did; that makes it at least somewhat plausible that we will also survive
for(DWORD i = 0; i < exportDir->NumberOfFunctions; i++)
{
// It is possible the AddressOfFunctions contain zero RVAs. GetProcAddress for these ordinals returns zero.
// "The reason for it is to assign a particular ordinal to a function." - NTCore
if(!addressOfFunctions[i])
continue;
Info.exports.emplace_back();
auto & entry = Info.exports.back();
entry.ordinal = i + exportDir->Base;
entry.rva = addressOfFunctions[i];
const auto entryVa = RvaToVa(FileMapVA, Info.headers, entry.rva);
entry.forwarded = entryVa >= (ULONG64)exportDir;
if(entry.forwarded && entryVa < (ULONG64)exportDir + exportDirSize)
entry.forwarded = entryVa >= (ULONG64)exportDir && entryVa < (ULONG64)exportDir + exportDirSize;
if(entry.forwarded)
{
auto forwardNameOffset = rva2offset(entry.rva);
if(forwardNameOffset) // Silent ignore (1) by ntdll loader: invalid forward names or addresses of forward names
@ -139,6 +144,13 @@ static void ReadExportDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
}
}
// give some kind of name to ordinal functions
for(size_t i = 0; i < Info.exports.size(); i++)
{
if(Info.exports[i].name.empty())
Info.exports[i].name = "Ordinal#" + std::to_string(Info.exports[i].ordinal);
}
// prepare sorted vectors
Info.exportsByName.resize(Info.exports.size());
Info.exportsByRva.resize(Info.exports.size());
@ -571,8 +583,6 @@ void ReadDebugDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
strncat_s(pdbPath, ".pdb", _TRUNCATE);
Info.pdbPaths.push_back(pdbPath);
}
}
}
@ -1119,7 +1129,7 @@ bool MODINFO::loadSymbols()
{
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] Skipping non-existent PDB: %s\n", pdbPath.c_str()).c_str());
}
else if(symSource->loadPDB(pdbPath, base, size, &validationData))
else if(symSource->loadPDB(pdbPath, base, size, bForceLoadSymbols ? nullptr : &validationData))
{
symSource->resizeSymbolBitmap(size);

View File

@ -146,26 +146,16 @@ private:
public:
ScopedDiaType() : _sym(nullptr) {}
ScopedDiaType(T* sym) : _sym(sym) {}
~ScopedDiaType()
{
if(_sym != nullptr)
{
_sym->Release();
}
}
~ScopedDiaType() { if(_sym != nullptr) _sym->Release(); }
T** ref() { return &_sym; }
T* operator->()
{
return _sym;
}
operator T* ()
{
return _sym;
}
T** operator&() { return ref(); }
T* operator->() { return _sym; }
operator T* () { return _sym; }
void Attach(T* sym) { _sym = sym; }
};
typedef ScopedDiaType<IDiaSymbol> ScopedDiaSymbol;
typedef ScopedDiaType<IDiaEnumSymbols> ScopedDiaEnumSymbols;
template<typename T>
using CComPtr = ScopedDiaType<T>;
PDBDiaFile::PDBDiaFile() :
m_stream(nullptr),
@ -234,6 +224,13 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
GuiSymbolLogAdd("Unable to open PDB file.\n");
return false;
}
/*std::vector<unsigned char> pdbData;
if (!FileHelper::ReadAllData(StringUtils::Utf16ToUtf8(file), pdbData))
{
GuiSymbolLogAdd("Unable to open PDB file.\n");
return false;
}
m_stream = SHCreateMemStream(pdbData.data(), pdbData.size());*/
if(validationData != nullptr)
{
@ -277,8 +274,8 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
if(validationData != nullptr)
{
ScopedDiaType<IDiaSymbol> globalSym;
hr = m_session->get_globalScope(globalSym.ref());
CComPtr<IDiaSymbol> globalSym;
hr = m_session->get_globalScope(&globalSym);
if(testError(hr))
{
//??
@ -320,6 +317,10 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
}
}
}
else
{
GuiSymbolLogAdd("Skipping PDB validation, expect invalid results!\n");
}
if(loadAddress != 0)
{
@ -338,19 +339,25 @@ bool PDBDiaFile::close()
{
if(m_session)
{
m_session->Release();
auto refcount = m_session->Release();
if(refcount != 0)
dprintf("Memory leaks in IDiaSession (refcount: %u)\n", refcount);
m_session = nullptr;
}
if(m_dataSource)
{
m_dataSource->Release();
auto refcount = m_dataSource->Release();
if(refcount != 0)
dprintf("Memory leaks in IDiaDataSource (refcount: %u)\n", refcount);
m_dataSource = nullptr;
}
if(m_stream)
{
m_stream->Release();
auto refcount = m_stream->Release();
if(refcount != 0)
dprintf("Memory leaks in IStream (refcount: %u)\n", refcount);
m_stream = nullptr;
}
@ -419,15 +426,15 @@ std::string PDBDiaFile::getSymbolUndecoratedNameString(IDiaSymbol* sym)
return result;
}
bool PDBDiaFile::getFunctionLineNumbers(DWORD rva, ULONGLONG size, uint64_t imageBase, std::map<uint64_t, DiaLineInfo_t> & lines)
bool PDBDiaFile::enumerateLineNumbers(uint32_t rva, uint32_t size, std::vector<DiaLineInfo_t> & lines, std::map<DWORD, std::string> & files)
{
HRESULT hr;
DWORD lineNumber = 0;
DWORD relativeVirtualAddress = 0;
DWORD lineNumberEnd = 0;
ScopedDiaType<IDiaEnumLineNumbers> lineNumbersEnum;
hr = m_session->findLinesByRVA(rva, static_cast<DWORD>(size), lineNumbersEnum.ref());
CComPtr<IDiaEnumLineNumbers> lineNumbersEnum;
hr = m_session->findLinesByRVA(rva, size, &lineNumbersEnum);
if(!SUCCEEDED(hr))
return false;
@ -439,57 +446,50 @@ bool PDBDiaFile::getFunctionLineNumbers(DWORD rva, ULONGLONG size, uint64_t imag
if(lineCount == 0)
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(LONG n = 0; n < fetched; n++)
for(ULONG n = 0; n < fetched; n++)
{
ScopedDiaType<IDiaLineNumber> lineNumberInfo(lineNumbers[n]);
CComPtr<IDiaLineNumber> lineNumberInfo;
lineNumberInfo.Attach(lineNumbers[n]);
ScopedDiaType<IDiaSourceFile> sourceFile;
hr = lineNumberInfo->get_sourceFile(sourceFile.ref());
DWORD sourceFileId = 0;
hr = lineNumberInfo->get_sourceFileId(&sourceFileId);
if(!SUCCEEDED(hr))
continue;
hr = lineNumberInfo->get_lineNumber(&lineNumber);
if(!SUCCEEDED(hr))
continue;
if(!files.count(sourceFileId))
{
CComPtr<IDiaSourceFile> sourceFile;
hr = lineNumberInfo->get_sourceFile(&sourceFile);
if(!SUCCEEDED(hr))
continue;
hr = lineNumberInfo->get_relativeVirtualAddress(&relativeVirtualAddress);
if(!SUCCEEDED(hr))
continue;
BSTR fileName = nullptr;
hr = sourceFile->get_fileName(&fileName);
if(!SUCCEEDED(hr))
continue;
hr = lineNumberInfo->get_lineNumberEnd(&lineNumberEnd);
if(!SUCCEEDED(hr))
continue;
DWORD segment = -1;
hr = lineNumberInfo->get_addressSection(&segment);
if(!SUCCEEDED(hr))
continue;
DWORD offset = -1;
hr = lineNumberInfo->get_addressOffset(&offset);
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.fileName = StringUtils::Utf16ToUtf8(fileName);
lineInfo.lineNumber = lineNumber;
lineInfo.offset = offset;
lineInfo.segment = segment;
lineInfo.virtualAddress = relativeVirtualAddress;
lineInfo.sourceFileId = sourceFileId;
lines.emplace(lineInfo.virtualAddress, lineInfo);
hr = lineNumberInfo->get_lineNumber(&lineInfo.lineNumber);
if(!SUCCEEDED(hr))
continue;
SysFreeString(fileName);
hr = lineNumberInfo->get_relativeVirtualAddress(&lineInfo.rva);
if(!SUCCEEDED(hr))
continue;
lines.push_back(lineInfo);
}
return true;
@ -504,14 +504,14 @@ uint32_t getSymbolId(IDiaSymbol* sym)
bool PDBDiaFile::enumerateLexicalHierarchy(const Query_t & query)
{
ScopedDiaSymbol globalScope;
CComPtr<IDiaSymbol> globalScope;
IDiaSymbol* symbol = nullptr;
ULONG celt = 0;
HRESULT hr;
DiaSymbol_t symbolInfo;
bool res = true;
hr = m_session->get_globalScope(globalScope.ref());
hr = m_session->get_globalScope(&globalScope);
if(hr != S_OK)
return false;
@ -525,14 +525,14 @@ bool PDBDiaFile::enumerateLexicalHierarchy(const Query_t & query)
// Enumerate compilands.
{
ScopedDiaEnumSymbols enumSymbols;
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = globalScope->findChildren(SymTagCompiland, nullptr, nsNone, enumSymbols.ref());
hr = globalScope->findChildren(SymTagCompiland, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
if(!enumerateCompilandScope(sym, context))
{
return false;
@ -543,14 +543,14 @@ bool PDBDiaFile::enumerateLexicalHierarchy(const Query_t & query)
// Enumerate publics.
{
ScopedDiaEnumSymbols enumSymbols;
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = globalScope->findChildren(SymTagPublicSymbol, nullptr, nsNone, enumSymbols.ref());
hr = globalScope->findChildren(SymTagPublicSymbol, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
if(convertSymbolInfo(symbol, symbolInfo, context))
{
if(!context.callback(symbolInfo))
@ -564,14 +564,14 @@ bool PDBDiaFile::enumerateLexicalHierarchy(const Query_t & query)
// Enumerate global functions.
{
ScopedDiaEnumSymbols enumSymbols;
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = globalScope->findChildren(SymTagFunction, nullptr, nsNone, enumSymbols.ref());
hr = globalScope->findChildren(SymTagFunction, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
if(convertSymbolInfo(sym, symbolInfo, context))
{
if(!context.callback(symbolInfo))
@ -585,14 +585,14 @@ bool PDBDiaFile::enumerateLexicalHierarchy(const Query_t & query)
// Enumerate global data.
{
ScopedDiaEnumSymbols enumSymbols;
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = globalScope->findChildren(SymTagData, nullptr, nsNone, enumSymbols.ref());
hr = globalScope->findChildren(SymTagData, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
if(convertSymbolInfo(sym, symbolInfo, context))
{
if(!context.callback(symbolInfo))
@ -635,11 +635,11 @@ bool PDBDiaFile::findSymbolRVA(uint64_t address, DiaSymbol_t & sym, DiaSymbolTyp
}
long disp = 0;
hr = m_session->findSymbolByRVAEx(address, tag, &symbol, &disp);
hr = m_session->findSymbolByRVAEx((DWORD)address, tag, &symbol, &disp);
if(hr != S_OK)
return false;
ScopedDiaSymbol scopedSym(symbol);
CComPtr<IDiaSymbol> scopedSym(symbol);
sym.disp = disp;
@ -665,14 +665,14 @@ bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, InternalQueryCon
uint32_t symId = getSymbolId(compiland);
{
ScopedDiaEnumSymbols enumSymbols;
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = compiland->findChildren(SymTagFunction, nullptr, nsNone, enumSymbols.ref());
hr = compiland->findChildren(SymTagFunction, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
hr = sym->get_symTag(&symTagType);
@ -689,14 +689,14 @@ bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, InternalQueryCon
}
{
ScopedDiaEnumSymbols enumSymbols;
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = compiland->findChildren(SymTagData, nullptr, nsNone, enumSymbols.ref());
hr = compiland->findChildren(SymTagData, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
hr = sym->get_symTag(&symTagType);
@ -715,14 +715,14 @@ bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, InternalQueryCon
}
{
ScopedDiaEnumSymbols enumSymbols;
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = compiland->findChildren(SymTagBlock, nullptr, nsNone, enumSymbols.ref());
hr = compiland->findChildren(SymTagBlock, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
hr = sym->get_symTag(&symTagType);
@ -741,14 +741,14 @@ bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, InternalQueryCon
}
{
ScopedDiaEnumSymbols enumSymbols;
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = compiland->findChildren(SymTagLabel, nullptr, nsNone, enumSymbols.ref());
hr = compiland->findChildren(SymTagLabel, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
hr = sym->get_symTag(&symTagType);
@ -793,13 +793,13 @@ bool PDBDiaFile::processFunctionSymbol(IDiaSymbol* functionSym, InternalQueryCon
}
{
ScopedDiaEnumSymbols enumSymbols;
hr = functionSym->findChildren(SymTagData, nullptr, nsNone, enumSymbols.ref());
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = functionSym->findChildren(SymTagData, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
hr = sym->get_symTag(&symTagType);
@ -821,13 +821,13 @@ bool PDBDiaFile::processFunctionSymbol(IDiaSymbol* functionSym, InternalQueryCon
}
{
ScopedDiaEnumSymbols enumSymbols;
hr = functionSym->findChildren(SymTagBlock, nullptr, nsNone, enumSymbols.ref());
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = functionSym->findChildren(SymTagBlock, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
hr = sym->get_symTag(&symTagType);
@ -846,13 +846,13 @@ bool PDBDiaFile::processFunctionSymbol(IDiaSymbol* functionSym, InternalQueryCon
}
{
ScopedDiaEnumSymbols enumSymbols;
hr = functionSym->findChildren(SymTagLabel, nullptr, nsNone, enumSymbols.ref());
CComPtr<IDiaEnumSymbols> enumSymbols;
hr = functionSym->findChildren(SymTagLabel, nullptr, nsNone, &enumSymbols);
if(hr == S_OK)
{
while((hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
CComPtr<IDiaSymbol> sym(symbol);
hr = sym->get_symTag(&symTagType);
@ -882,8 +882,8 @@ bool PDBDiaFile::resolveSymbolSize(IDiaSymbol* symbol, uint64_t & size, uint32_t
if(symTag == SymTagData)
{
ScopedDiaSymbol symType;
hr = symbol->get_type(symType.ref());
CComPtr<IDiaSymbol> symType;
hr = symbol->get_type(&symType);
if(hr == S_OK && symType != nullptr)
{

View File

@ -50,7 +50,7 @@ public:
bool close();
bool getFunctionLineNumbers(DWORD rva, ULONGLONG size, uint64_t imageBase, std::map<uint64_t, DiaLineInfo_t> & lines);
bool enumerateLineNumbers(uint32_t rva, uint32_t size, std::vector<DiaLineInfo_t> & lines, std::map<DWORD, std::string> & files);
bool enumerateLexicalHierarchy(const Query_t & query);

View File

@ -75,11 +75,9 @@ struct DiaSymbol_t
struct DiaLineInfo_t
{
std::string fileName;
DWORD sourceFileId;
DWORD lineNumber;
uint32_t offset;
uint32_t segment;
uint64_t virtualAddress;
DWORD rva;
};
#endif // PDBDIATYPES_H_

View File

@ -195,6 +195,8 @@ static void stackgetsuspectedcallstack(duint csp, std::vector<CALLSTACKENTRY> &
{
duint size;
duint base = MemFindBaseAddr(csp, &size);
if(!base)
return;
duint end = base + size;
size = end - csp;
Memory<duint*> stackdata(size);

View File

@ -121,7 +121,7 @@ bool SymbolSourceDIA::loadSymbolsAsync()
PDBDiaFile::Query_t query;
query.collectSize = true;
query.collectUndecoratedNames = true;
query.callback = [&](DiaSymbol_t & sym)->bool
query.callback = [&](DiaSymbol_t & sym) -> bool
{
if(_requiresShutdown)
return false;
@ -243,37 +243,41 @@ bool SymbolSourceDIA::loadSourceLinesAsync()
DWORD lineLoadStart = GetTickCount();
const size_t rangeSize = 1024 * 1024;
const uint32_t rangeSize = 1024 * 1024 * 10;
std::map<DWORD, String> files;
for(duint rva = 0; rva < _imageSize; rva += rangeSize)
{
if(_requiresShutdown)
return false;
std::map<uint64_t, DiaLineInfo_t> lines;
std::vector<DiaLineInfo_t> lines;
bool res = pdb.getFunctionLineNumbers(rva, rangeSize, _imageBase, lines);
bool res = pdb.enumerateLineNumbers(uint32_t(rva), rangeSize, lines, files);
for(const auto & line : lines)
{
if(_requiresShutdown)
return false;
const auto & info = line.second;
auto it = _lines.find(info.virtualAddress);
const auto & info = line;
auto it = _lines.find(info.rva);
if(it != _lines.end())
continue;
CachedLineInfo lineInfo;
lineInfo.rva = info.virtualAddress;
lineInfo.rva = info.rva;
lineInfo.lineNumber = info.lineNumber;
auto idx = findSourceFile(info.fileName);
if(idx == -1)
auto sourceFileId = info.sourceFileId;
auto found = _sourceIdMap.find(sourceFileId);
if(found == _sourceIdMap.end())
{
idx = _sourceFiles.size();
_sourceFiles.push_back(info.fileName);
auto idx = _sourceFiles.size();
_sourceFiles.push_back(files[sourceFileId]);
found = _sourceIdMap.insert({ sourceFileId, uint32_t(idx) }).first;
}
lineInfo.sourceFileIdx = idx;
lineInfo.sourceFileIdx = found->second;
_lockLines.lock();
@ -312,7 +316,7 @@ uint32_t SymbolSourceDIA::findSourceFile(const std::string & fileName) const
for(uint32_t n = 0; n < _sourceFiles.size(); n++)
{
const String & str = _sourceFiles[n];
if(stricmp(str.c_str(), fileName.c_str()) == 0)
if(_stricmp(str.c_str(), fileName.c_str()) == 0)
{
idx = n;
break;

View File

@ -94,7 +94,8 @@ private: //line info
//TODO: make this source file stuff smarter
std::vector<CachedLineInfo> _linesData;
std::map<duint, size_t> _lines; //addr -> line
std::vector<String> _sourceFiles;
std::vector<String> _sourceFiles; // uniqueId + name
std::map<DWORD, uint32_t> _sourceIdMap; //uniqueId -> index in _sourceFiles
std::vector<std::map<int, size_t>> _sourceLines; //uses index in _sourceFiles
private: //general

View File

@ -1,5 +1,29 @@
#pragma once
/*
MIT License
Copyright (c) 2018 Duncan Ogilvie
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <stdlib.h>
#include <string>

View File

@ -1,6 +1,7 @@
#ifndef APPEARANCEDIALOG_H
#define APPEARANCEDIALOG_H
#include <QAction>
#include <QDialog>
#include <QMap>

View File

@ -502,6 +502,7 @@ RegistersView::RegistersView(CPUWidget* parent) : QScrollArea(parent), mVScrollO
wCM_ToggleValue = setupAction(DIcon("register_toggle.png"), tr("Toggle"), this);
wCM_Undo = setupAction(DIcon("undo.png"), tr("Undo"), this);
wCM_CopyToClipboard = setupAction(DIcon("copy.png"), tr("Copy value to clipboard"), this);
wCM_CopyFloatingPointValueToClipboard = setupAction(DIcon("copy.png"), tr("Copy floating point value to clipboard"), this);
wCM_CopySymbolToClipboard = setupAction(DIcon("pdb.png"), tr("Copy Symbol Value to Clipboard"), this);
wCM_CopyAll = setupAction(DIcon("copy-alt.png"), tr("Copy all registers"), this);
wCM_FollowInDisassembly = new QAction(DIcon(QString("processor%1.png").arg(ArchValue("32", "64"))), tr("Follow in Disassembler"), this);
@ -1346,6 +1347,7 @@ RegistersView::RegistersView(CPUWidget* parent) : QScrollArea(parent), mVScrollO
connect(wCM_ToggleValue, SIGNAL(triggered()), this, SLOT(onToggleValueAction()));
connect(wCM_Undo, SIGNAL(triggered()), this, SLOT(onUndoAction()));
connect(wCM_CopyToClipboard, SIGNAL(triggered()), this, SLOT(onCopyToClipboardAction()));
connect(wCM_CopyFloatingPointValueToClipboard, SIGNAL(triggered()), this, SLOT(onCopyFloatingPointToClipboardAction()));
connect(wCM_CopySymbolToClipboard, SIGNAL(triggered()), this, SLOT(onCopySymbolToClipboardAction()));
connect(wCM_CopyAll, SIGNAL(triggered()), this, SLOT(onCopyAllAction()));
connect(wCM_FollowInDisassembly, SIGNAL(triggered()), this, SLOT(onFollowInDisassembly()));
@ -2855,6 +2857,12 @@ void RegistersView::onCopyToClipboardAction()
clipboard->setText(GetRegStringValueFromValue(mSelected, registerValue(&wRegDumpStruct, mSelected)));
}
void RegistersView::onCopyFloatingPointToClipboardAction()
{
QClipboard* clipboard = QApplication::clipboard();
clipboard->setText(ToLongDoubleString(((X87FPUREGISTER*) registerValue(&wRegDumpStruct, mSelected))->data));
}
void RegistersView::onCopySymbolToClipboardAction()
{
if(mLABELDISPLAY.contains(mSelected))
@ -3205,6 +3213,10 @@ void RegistersView::displayCustomContextMenuSlot(QPoint pos)
}
wMenu.addAction(wCM_CopyToClipboard);
if(mFPUx87_80BITSDISPLAY.contains(mSelected))
{
wMenu.addAction(wCM_CopyFloatingPointValueToClipboard);
}
wMenu.addAction(wCM_CopyAll);
if(mLABELDISPLAY.contains(mSelected))
{

View File

@ -165,6 +165,7 @@ protected slots:
void onToggleValueAction();
void onUndoAction();
void onCopyToClipboardAction();
void onCopyFloatingPointToClipboardAction();
void onCopySymbolToClipboardAction();
void onCopyAllAction();
void onFollowInDisassembly();
@ -274,6 +275,7 @@ private:
QAction* wCM_ToggleValue;
QAction* wCM_Undo;
QAction* wCM_CopyToClipboard;
QAction* wCM_CopyFloatingPointValueToClipboard;
QAction* wCM_CopySymbolToClipboard;
QAction* wCM_CopyAll;
QAction* wCM_FollowInDisassembly;

View File

@ -1,6 +1,7 @@
#ifndef WORDEDITDIALOG_H
#define WORDEDITDIALOG_H
#include <QValidator>
#include <QDialog>
#include <QPushButton>
#include "Imports.h"

View File

@ -31,6 +31,8 @@ TraceBrowser::TraceBrowser(QWidget* parent) : AbstractTableView(parent)
mRvaDisplayBase = 0;
mRvaDisplayEnabled = false;
mAutoDisassemblyFollowSelection = false;
int maxModuleSize = (int)ConfigUint("Disassembler", "MaxModuleSize");
mDisasm = new QBeaEngine(maxModuleSize);
mHighlightingMode = false;
@ -564,6 +566,19 @@ void TraceBrowser::setupRightClickContextMenu()
return true;
});
mMenuBuilder->addMenu(makeMenu(tr("Information")), infoMenu);
QAction* toggleAutoDisassemblyFollowSelection = makeAction(tr("Toggle Auto Disassembly Scroll (off)"), SLOT(toggleAutoDisassemblyFollowSelection()));
mMenuBuilder->addAction(toggleAutoDisassemblyFollowSelection, [this, toggleAutoDisassemblyFollowSelection](QMenu*)
{
if(!DbgIsDebugging())
return false;
if(mAutoDisassemblyFollowSelection)
toggleAutoDisassemblyFollowSelection->setText(tr("Toggle Auto Disassembly Scroll (on)"));
else
toggleAutoDisassemblyFollowSelection->setText(tr("Toggle Auto Disassembly Scroll (off)"));
return true;
});
}
void TraceBrowser::contextMenuEvent(QContextMenuEvent* event)
@ -628,6 +643,10 @@ void TraceBrowser::mousePressEvent(QMouseEvent* event)
setSingleSelection(index);
mHistory.addVaToHistory(index);
updateViewport();
if(mAutoDisassemblyFollowSelection)
followDisassemblySlot();
return;
}
break;
@ -756,6 +775,9 @@ void TraceBrowser::keyPressEvent(QKeyEvent* event)
makeVisible(visibleindex);
mHistory.addVaToHistory(visibleindex);
updateViewport();
if(mAutoDisassemblyFollowSelection)
followDisassemblySlot();
}
else
AbstractTableView::keyPressEvent(event);
@ -1373,3 +1395,8 @@ void TraceBrowser::updateSlot()
reloadData();
}
}
void TraceBrowser::toggleAutoDisassemblyFollowSelectionSlot()
{
mAutoDisassemblyFollowSelection = !mAutoDisassemblyFollowSelection;
}

View File

@ -59,6 +59,7 @@ private:
CapstoneTokenizer::SingleToken mHighlightToken;
bool mHighlightingMode;
bool mPermanentHighlightingMode;
bool mAutoDisassemblyFollowSelection;
TraceFileReader* mTraceFile;
QBeaEngine* mDisasm;
@ -131,6 +132,8 @@ public slots:
void searchMemRefSlot();
void updateSlot(); //debug
void toggleAutoDisassemblyFollowSelectionSlot();
};
#endif //TRACEBROWSER_H