DBG+GUI+BRIDGE: various fixes with regards to the disassembly view
This commit is contained in:
parent
89017073a6
commit
72888177b3
|
@ -253,6 +253,7 @@ BRIDGE_IMPEXP bool DbgMemRead(duint va, unsigned char* dest, duint size)
|
|||
if(IsBadWritePtr(dest, size))
|
||||
{
|
||||
GuiAddLogMessage("DbgMemRead with invalid boundaries!\n");
|
||||
__debugbreak();
|
||||
return false;
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
@ -273,6 +274,7 @@ BRIDGE_IMPEXP bool DbgMemWrite(duint va, const unsigned char* src, duint size)
|
|||
if(IsBadReadPtr(src, size))
|
||||
{
|
||||
GuiAddLogMessage("DbgMemWrite with invalid boundaries!\n");
|
||||
__debugbreak();
|
||||
return false;
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit cc82f1970cf6062ca0b50cd8f31202a410688082
|
||||
Subproject commit 9dec3d7e8b8f3c3fa9ceeb09fef7e6f03b141603
|
|
@ -300,6 +300,9 @@ void TraceRecordManager::saveToDb(JSON root)
|
|||
}
|
||||
if(json_array_size(jsonTraceRecords))
|
||||
json_object_set_new(root, "tracerecord", jsonTraceRecords);
|
||||
|
||||
// Notify garbage collector
|
||||
json_decref(jsonTraceRecords);
|
||||
}
|
||||
|
||||
void TraceRecordManager::loadFromDb(JSON root)
|
||||
|
|
|
@ -1095,7 +1095,7 @@ extern "C" DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* pa
|
|||
case DBG_GET_STRING_AT:
|
||||
{
|
||||
auto addr = duint(param1);
|
||||
if(!MemIsValidReadPtr(addr, true))
|
||||
if(!MemIsValidReadPtrUnsafe(addr, true))
|
||||
return false;
|
||||
|
||||
auto dest = (char*)param2;
|
||||
|
@ -1103,7 +1103,7 @@ extern "C" DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* pa
|
|||
char string[MAX_STRING_SIZE];
|
||||
duint addrPtr;
|
||||
STRING_TYPE strtype;
|
||||
if(MemReadUnsafe(addr, &addrPtr, sizeof(addr)) && MemIsValidReadPtr(addrPtr, true))
|
||||
if(MemReadUnsafe(addr, &addrPtr, sizeof(addr)) && MemIsValidReadPtrUnsafe(addrPtr, true))
|
||||
{
|
||||
if(disasmgetstringat(addrPtr, &strtype, string, string, MAX_STRING_SIZE - 3))
|
||||
{
|
||||
|
|
|
@ -1260,8 +1260,6 @@ CMDRESULT cbDebugDisasm(int argc, char* argv[])
|
|||
{
|
||||
addr = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
}
|
||||
if(!MemIsValidReadPtr(addr))
|
||||
return STATUS_CONTINUE;
|
||||
DebugUpdateGui(addr, false);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ bool disasmgetstringat(duint addr, STRING_TYPE* type, char* ascii, char* unicode
|
|||
{
|
||||
if(type)
|
||||
*type = str_none;
|
||||
if(!MemIsValidReadPtr(addr, true) || !disasmispossiblestring(addr))
|
||||
if(!MemIsValidReadPtrUnsafe(addr, true) || !disasmispossiblestring(addr))
|
||||
return false;
|
||||
Memory<unsigned char*> data((maxlen + 1) * 2, "disasmgetstringat:data");
|
||||
if(!MemReadUnsafe(addr, data(), (maxlen + 1) * 2)) //TODO: use safe version?
|
||||
|
|
|
@ -423,6 +423,14 @@ bool MemPatch(duint BaseAddress, const void* Buffer, duint Size, duint* NumberOf
|
|||
}
|
||||
|
||||
bool MemIsValidReadPtr(duint Address, bool cache)
|
||||
{
|
||||
if(cache)
|
||||
return MemFindBaseAddr(Address, nullptr) != 0;
|
||||
unsigned char ch;
|
||||
return MemRead(Address, &ch, sizeof(ch));
|
||||
}
|
||||
|
||||
bool MemIsValidReadPtrUnsafe(duint Address, bool cache)
|
||||
{
|
||||
if(cache)
|
||||
return MemFindBaseAddr(Address, nullptr) != 0;
|
||||
|
|
|
@ -29,6 +29,7 @@ bool MemReadUnsafe(duint BaseAddress, void* Buffer, duint Size, duint* NumberOfB
|
|||
bool MemWrite(duint BaseAddress, const void* Buffer, duint Size, duint* NumberOfBytesWritten = nullptr);
|
||||
bool MemPatch(duint BaseAddress, const void* Buffer, duint Size, duint* NumberOfBytesWritten = nullptr);
|
||||
bool MemIsValidReadPtr(duint Address, bool cache = false);
|
||||
bool MemIsValidReadPtrUnsafe(duint Address, bool cache = false);
|
||||
bool MemIsCanonicalAddress(duint Address);
|
||||
bool MemIsCodePage(duint Address, bool Refresh);
|
||||
duint MemAllocRemote(duint Address, duint Size, DWORD Type = MEM_RESERVE | MEM_COMMIT, DWORD Protect = PAGE_EXECUTE_READWRITE);
|
||||
|
|
|
@ -14,7 +14,8 @@ std::unordered_map<duint, PATCHINFO> patches;
|
|||
|
||||
bool PatchSet(duint Address, unsigned char OldByte, unsigned char NewByte)
|
||||
{
|
||||
ASSERT_DEBUGGING("Export call");
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// Address must be valid
|
||||
if(!MemIsValidReadPtr(Address))
|
||||
|
@ -62,7 +63,8 @@ bool PatchSet(duint Address, unsigned char OldByte, unsigned char NewByte)
|
|||
|
||||
bool PatchGet(duint Address, PATCHINFO* Patch)
|
||||
{
|
||||
ASSERT_DEBUGGING("Export call");
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
SHARED_ACQUIRE(LockPatches);
|
||||
|
||||
// Find this specific address in the list
|
||||
|
@ -84,7 +86,8 @@ bool PatchGet(duint Address, PATCHINFO* Patch)
|
|||
|
||||
bool PatchDelete(duint Address, bool Restore)
|
||||
{
|
||||
ASSERT_DEBUGGING("Export call");
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
EXCLUSIVE_ACQUIRE(LockPatches);
|
||||
|
||||
// Do a list lookup with hash
|
||||
|
@ -104,7 +107,8 @@ bool PatchDelete(duint Address, bool Restore)
|
|||
|
||||
void PatchDelRange(duint Start, duint End, bool Restore)
|
||||
{
|
||||
ASSERT_DEBUGGING("Export call");
|
||||
if(!DbgIsDebugging())
|
||||
return;
|
||||
|
||||
// Are all bookmarks going to be deleted?
|
||||
// 0x00000000 - 0xFFFFFFFF
|
||||
|
|
|
@ -575,7 +575,6 @@ QString Disassembly::paintContent(QPainter* painter, dsint rowBase, int rowOffse
|
|||
return "";
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
Mouse Management
|
||||
************************************************************************************/
|
||||
|
@ -633,7 +632,6 @@ void Disassembly::mouseMoveEvent(QMouseEvent* event)
|
|||
AbstractTableView::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This method has been reimplemented. It manages the following actions:
|
||||
* - Multi-rows selection
|
||||
|
@ -714,7 +712,6 @@ void Disassembly::mousePressEvent(QMouseEvent* event)
|
|||
AbstractTableView::mousePressEvent(event);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This method has been reimplemented. It manages the following actions:
|
||||
* - Multi-rows selection
|
||||
|
@ -743,7 +740,6 @@ void Disassembly::mouseReleaseEvent(QMouseEvent* event)
|
|||
AbstractTableView::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
Keyboard Management
|
||||
************************************************************************************/
|
||||
|
@ -1160,7 +1156,6 @@ int Disassembly::paintFunctionGraphic(QPainter* painter, int x, int y, Function_
|
|||
return x_add + line_width + end_add;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
Instructions Management
|
||||
***********************************************************************************/
|
||||
|
@ -1194,16 +1189,15 @@ dsint Disassembly::getPreviousInstructionRVA(dsint rva, duint count)
|
|||
wMaxByteCountToRead = wVirtualRVA + 1 + 16;
|
||||
wBuffer.resize(wMaxByteCountToRead);
|
||||
|
||||
mMemPage->read(reinterpret_cast<byte_t*>(wBuffer.data()), wBottomByteRealRVA, wMaxByteCountToRead);
|
||||
mMemPage->read(wBuffer.data(), wBottomByteRealRVA, wBuffer.size());
|
||||
|
||||
dsint addr = mDisasm->DisassembleBack(reinterpret_cast<byte_t*>(wBuffer.data()), rvaToVa(wBottomByteRealRVA), wMaxByteCountToRead, wVirtualRVA , count, mTmpCodeCount, mTmpCodeList);
|
||||
dsint addr = mDisasm->DisassembleBack((byte_t*)wBuffer.data(), rvaToVa(wBottomByteRealRVA), wBuffer.size(), wVirtualRVA , count, mTmpCodeCount, mTmpCodeList);
|
||||
|
||||
addr += rva - wVirtualRVA;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns the RVA of count-th instructions after the given instruction RVA.
|
||||
*
|
||||
|
@ -1229,16 +1223,15 @@ dsint Disassembly::getNextInstructionRVA(dsint rva, duint count)
|
|||
wMaxByteCountToRead = wRemainingBytes > wMaxByteCountToRead ? wMaxByteCountToRead : wRemainingBytes;
|
||||
wBuffer.resize(wMaxByteCountToRead);
|
||||
|
||||
mMemPage->read(reinterpret_cast<byte_t*>(wBuffer.data()), rva, wMaxByteCountToRead);
|
||||
mMemPage->read(wBuffer.data(), rva, wBuffer.size());
|
||||
|
||||
wNewRVA = mDisasm->DisassembleNext(reinterpret_cast<byte_t*>(wBuffer.data()), rvaToVa(rva), wMaxByteCountToRead, 0, count, mTmpCodeCount, mTmpCodeList);
|
||||
wNewRVA = mDisasm->DisassembleNext((byte_t*)wBuffer.data(), rvaToVa(rva), wBuffer.size(), 0, count, mTmpCodeCount, mTmpCodeList);
|
||||
|
||||
wNewRVA += rva;
|
||||
|
||||
return wNewRVA;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns the RVA of count-th instructions before/after (depending on the sign) the given instruction RVA.
|
||||
*
|
||||
|
@ -1267,7 +1260,6 @@ dsint Disassembly::getInstructionRVA(dsint index, dsint count)
|
|||
return wAddr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disassembles the instruction at the given RVA.
|
||||
*
|
||||
|
@ -1278,29 +1270,25 @@ dsint Disassembly::getInstructionRVA(dsint index, dsint count)
|
|||
Instruction_t Disassembly::DisassembleAt(dsint rva)
|
||||
{
|
||||
QByteArray wBuffer;
|
||||
dsint base = mMemPage->getBase();
|
||||
dsint wMaxByteCountToRead = 16 * 2;
|
||||
duint base = mMemPage->getBase();
|
||||
duint wMaxByteCountToRead = 16 * 2;
|
||||
|
||||
// Bounding
|
||||
//TODO: fix problems with negative sizes
|
||||
dsint size = getSize();
|
||||
auto size = getSize();
|
||||
if(!size)
|
||||
size = rva;
|
||||
size = rva + wMaxByteCountToRead * 2;
|
||||
|
||||
wMaxByteCountToRead = wMaxByteCountToRead > (size - rva) ? (size - rva) : wMaxByteCountToRead;
|
||||
if(mCodeFoldingManager)
|
||||
wMaxByteCountToRead += mCodeFoldingManager->getFoldedSize(rvaToVa(rva), rvaToVa(rva + wMaxByteCountToRead));
|
||||
|
||||
wMaxByteCountToRead = wMaxByteCountToRead > (size - rva) ? (size - rva) : wMaxByteCountToRead;
|
||||
wBuffer.resize(wMaxByteCountToRead);
|
||||
|
||||
if(!wMaxByteCountToRead)
|
||||
wMaxByteCountToRead = 1;
|
||||
mMemPage->read(wBuffer.data(), rva, wBuffer.size());
|
||||
|
||||
mMemPage->read(reinterpret_cast<byte_t*>(wBuffer.data()), rva, wMaxByteCountToRead);
|
||||
|
||||
return mDisasm->DisassembleAt(reinterpret_cast<byte_t*>(wBuffer.data()), wMaxByteCountToRead, 0, base, rva, mTmpCodeCount, mTmpCodeList);
|
||||
return mDisasm->DisassembleAt((byte_t*)wBuffer.data(), wBuffer.size(), base, rva, mTmpCodeCount, mTmpCodeList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disassembles the instruction count instruction afterc the instruction at the given RVA.
|
||||
* Count can be positive or negative.
|
||||
|
@ -1316,7 +1304,6 @@ Instruction_t Disassembly::DisassembleAt(dsint rva, dsint count)
|
|||
return DisassembleAt(rva);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
Selection Management
|
||||
************************************************************************************/
|
||||
|
@ -1528,9 +1515,7 @@ void Disassembly::prepareData()
|
|||
wAddr = getNextInstructionRVA(wAddr, 1);
|
||||
|
||||
if(wAddr == wAddrPrev)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
wCount++;
|
||||
}
|
||||
|
@ -1557,8 +1542,8 @@ duint Disassembly::rvaToVa(dsint rva)
|
|||
|
||||
void Disassembly::disassembleAt(dsint parVA, dsint parCIP, bool history, dsint newTableOffset)
|
||||
{
|
||||
dsint wBase = DbgMemFindBaseAddr(parVA, 0);
|
||||
dsint wSize = DbgMemGetPageSize(wBase);
|
||||
duint wSize;
|
||||
auto wBase = DbgMemFindBaseAddr(parVA, &wSize);
|
||||
|
||||
if(!wBase || !wSize)
|
||||
return;
|
||||
|
@ -1595,7 +1580,6 @@ void Disassembly::disassembleAt(dsint parVA, dsint parCIP, bool history, dsint n
|
|||
|
||||
bool cipChanged = rvaToVa(mCipRva) != parCIP;
|
||||
|
||||
|
||||
if(mRvaDisplayEnabled && mMemPage->getBase() != mRvaDisplayPageBase)
|
||||
mRvaDisplayEnabled = false;
|
||||
|
||||
|
@ -1696,7 +1680,6 @@ void Disassembly::disassembleAt(dsint parVA, dsint parCIP, bool history, dsint n
|
|||
*/
|
||||
emit disassembledAt(parVA, parCIP, history, newTableOffset);
|
||||
reloadData();
|
||||
|
||||
}
|
||||
|
||||
QList<Instruction_t>* Disassembly::instructionsBuffer()
|
||||
|
|
|
@ -86,8 +86,8 @@ void HexDump::copySelectionSlot()
|
|||
|
||||
void HexDump::printDumpAt(dsint parVA, bool select, bool repaint, bool updateTableOffset)
|
||||
{
|
||||
dsint wBase = DbgMemFindBaseAddr(parVA, 0); //get memory base
|
||||
dsint wSize = DbgMemGetPageSize(wBase); //get page size
|
||||
duint wSize;
|
||||
auto wBase = DbgMemFindBaseAddr(parVA, &wSize); //get memory base
|
||||
if(!wBase || !wSize)
|
||||
return;
|
||||
dsint wRVA = parVA - wBase; //calculate rva
|
||||
|
|
|
@ -177,30 +177,28 @@ ulong QBeaEngine::DisassembleNext(byte_t* data, duint base, duint size, duint ip
|
|||
*
|
||||
* @param[in] data Pointer to memory data (Can be either a buffer or the original data memory)
|
||||
* @param[in] size Size of the memory pointed by data (Can be the memory page size if data points to the original memory page base address)
|
||||
* @param[in] instIndex Offset to reach the instruction data from the data pointer
|
||||
* @param[in] origBase Original base address of the memory page (Required to disassemble destination addresses)
|
||||
* @param[in] origInstRVA Original Instruction RVA of the instruction to disassemble
|
||||
*
|
||||
* @return Return the disassembled instruction
|
||||
*/
|
||||
|
||||
Instruction_t QBeaEngine::DisassembleAt(byte_t* data, duint size, duint instIndex, duint origBase, duint origInstRVA, duint tmpcodecount, duint* tmpcodelist)
|
||||
Instruction_t QBeaEngine::DisassembleAt(byte_t* data, duint size, duint origBase, duint origInstRVA, duint tmpcodecount, duint* tmpcodelist)
|
||||
{
|
||||
//tokenize
|
||||
CapstoneTokenizer::InstructionToken cap;
|
||||
_tokenizer.Tokenize(origBase + origInstRVA, data + instIndex, size, cap);
|
||||
_tokenizer.Tokenize(origBase + origInstRVA, data, size, cap);
|
||||
int len = _tokenizer.Size();
|
||||
|
||||
const auto & cp = _tokenizer.GetCapstone();
|
||||
bool success = cp.Success();
|
||||
|
||||
|
||||
ENCODETYPE type = enc_code;
|
||||
|
||||
type = mEncodeMap->getDataType(origBase + origInstRVA, cp.Success() ? len : 1, tmpcodecount, tmpcodelist);
|
||||
|
||||
if(type != enc_unknown && type != enc_code && type != enc_middle)
|
||||
return DecodeDataAt(data, size, instIndex, origBase, origInstRVA, type);
|
||||
return DecodeDataAt(data, size, origBase, origInstRVA, type);
|
||||
|
||||
auto branchType = Instruction_t::None;
|
||||
if(success && (cp.InGroup(CS_GRP_JUMP) || cp.IsLoop()))
|
||||
|
@ -218,7 +216,7 @@ Instruction_t QBeaEngine::DisassembleAt(byte_t* data, duint size, duint instInde
|
|||
|
||||
Instruction_t wInst;
|
||||
wInst.instStr = QString(cp.InstructionText().c_str());
|
||||
wInst.dump = QByteArray((const char*)data + instIndex, len);
|
||||
wInst.dump = QByteArray((const char*)data, len);
|
||||
wInst.rva = origInstRVA;
|
||||
if(mCodeFoldingManager && mCodeFoldingManager->isFolded(origInstRVA))
|
||||
wInst.length = mCodeFoldingManager->getFoldEnd(origInstRVA + origBase) - (origInstRVA + origBase) + 1;
|
||||
|
@ -232,7 +230,7 @@ Instruction_t QBeaEngine::DisassembleAt(byte_t* data, duint size, duint instInde
|
|||
}
|
||||
|
||||
|
||||
Instruction_t QBeaEngine::DecodeDataAt(byte_t* data, duint size, duint instIndex, duint origBase, duint origInstRVA, ENCODETYPE type, duint tmpcodecount, duint* tmpcodelist)
|
||||
Instruction_t QBeaEngine::DecodeDataAt(byte_t* data, duint size, duint origBase, duint origInstRVA, ENCODETYPE type, duint tmpcodecount, duint* tmpcodelist)
|
||||
{
|
||||
//tokenize
|
||||
CapstoneTokenizer::InstructionToken cap;
|
||||
|
|
|
@ -41,8 +41,8 @@ public:
|
|||
~QBeaEngine();
|
||||
ulong DisassembleBack(byte_t* data, duint base, duint size, duint ip, int n, duint tmpcodecount = 0, duint* tmpcodelist = nullptr);
|
||||
ulong DisassembleNext(byte_t* data, duint base, duint size, duint ip, int n, duint tmpcodecount = 0, duint* tmpcodelist = nullptr);
|
||||
Instruction_t DisassembleAt(byte_t* data, duint size, duint instIndex, duint origBase, duint origInstRVA, duint tmpcodecount = 0, duint* tmpcodelist = nullptr);
|
||||
Instruction_t DecodeDataAt(byte_t* data, duint size, duint instIndex, duint origBase, duint origInstRVA, ENCODETYPE type, duint tmpcodecount = 0, duint* tmpcodelist = nullptr);
|
||||
Instruction_t DisassembleAt(byte_t* data, duint size, duint origBase, duint origInstRVA, duint tmpcodecount = 0, duint* tmpcodelist = nullptr);
|
||||
Instruction_t DecodeDataAt(byte_t* data, duint size, duint origBase, duint origInstRVA, ENCODETYPE type, duint tmpcodecount = 0, duint* tmpcodelist = nullptr);
|
||||
void setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager);
|
||||
void UpdateConfig();
|
||||
EncodeMap* getEncodeMap() { return mEncodeMap; }
|
||||
|
|
|
@ -48,3 +48,8 @@ void MemoryPage::setAttributes(duint base, duint size)
|
|||
mBase = base;
|
||||
mSize = size;
|
||||
}
|
||||
|
||||
bool MemoryPage::inRange(duint va) const
|
||||
{
|
||||
return va >= mBase && va < mBase + mSize;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ public:
|
|||
duint getBase() const;
|
||||
duint va(dsint rva) const;
|
||||
void setAttributes(duint base, duint size);
|
||||
bool inRange(duint va) const;
|
||||
|
||||
private:
|
||||
duint mBase;
|
||||
|
|
Loading…
Reference in New Issue