1
0
Fork 0

DBG: basic of the type system working

This commit is contained in:
mrexodia 2016-10-01 18:46:24 +02:00
parent 16bf75a15b
commit 022bceb8f7
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
10 changed files with 1079 additions and 9 deletions

View File

@ -25,13 +25,12 @@
#include <unordered_map>
#include <unordered_set>
#include <tlhelp32.h>
#include "..\dbg_types.h"
#include "..\dbg_assert.h"
#include "..\bridge\bridgemain.h"
#include "jansson\jansson.h"
#include "jansson\jansson_x64dbg.h"
#include "yara\yara.h"
#include "DeviceNameResolver\DeviceNameResolver.h"
#include "../dbg_types.h"
#include "../dbg_assert.h"
#include "../bridge\bridgemain.h"
#include "jansson/jansson.h"
#include "jansson/jansson_x64dbg.h"
#include "DeviceNameResolver/DeviceNameResolver.h"
#include "handle.h"
#include "stringutils.h"
#include "dbghelp_safe.h"

View File

@ -7,6 +7,7 @@
#include "debugger.h"
#include "filehelper.h"
#include "label.h"
#include "yara/yara.h"
static int maxFindResults = 5000;

View File

@ -2,6 +2,10 @@
#include "console.h"
#include "encodemap.h"
#include "value.h"
#include "types.h"
#include "memory.h"
using namespace Types;
static CMDRESULT cbInstrDataGeneric(ENCODETYPE type, int argc, char* argv[])
{
@ -120,4 +124,470 @@ CMDRESULT cbInstrDataJunk(int argc, char* argv[])
CMDRESULT cbInstrDataMiddle(int argc, char* argv[])
{
return cbInstrDataGeneric(enc_middle, argc, argv);
}
}
#define towner "cmd"
CMDRESULT cbInstrAddType(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 3))
return STATUS_ERROR;
if(!AddType(towner, argv[1], argv[2]))
{
dputs(QT_TRANSLATE_NOOP("DBG", "AddType failed"));
return STATUS_ERROR;
}
dprintf_untranslated("typedef %s %s;\n", argv[2], argv[1]);
return STATUS_CONTINUE;
}
CMDRESULT cbInstrAddStruct(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 2))
return STATUS_ERROR;
if(!AddStruct(towner, argv[1]))
{
dputs(QT_TRANSLATE_NOOP("DBG", "AddStruct failed"));
return STATUS_ERROR;
}
dprintf_untranslated("struct %s;\n", argv[1]);
return STATUS_CONTINUE;
}
CMDRESULT cbInstrAddUnion(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 2))
return STATUS_ERROR;
if(!AddUnion(towner, argv[1]))
{
dputs(QT_TRANSLATE_NOOP("DBG", "AddUnion failed"));
return STATUS_ERROR;
}
dprintf_untranslated("union %s;\n", argv[1]);
return STATUS_CONTINUE;
}
CMDRESULT cbInstrAddMember(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 4))
return STATUS_ERROR;
auto parent = argv[1];
auto type = argv[2];
auto name = argv[3];
int arrsize = 0, offset = -1;
if(argc > 3)
{
duint value;
if(!valfromstring(argv[4], &value, false))
return STATUS_ERROR;
arrsize = int(value);
if(argc > 4)
{
if(!valfromstring(argv[5], &value, false))
return STATUS_ERROR;
offset = int(value);
}
}
if(!AddMember(parent, type, name, arrsize, offset))
{
dputs(QT_TRANSLATE_NOOP("DBG", "AddMember failed"));
return STATUS_ERROR;
}
dprintf_untranslated("%s: %s %s", parent, type, name);
if(arrsize > 0)
dprintf_untranslated("[%d]", arrsize);
if(offset >= 0)
dprintf_untranslated(" (offset: %d)", offset);
dputs_untranslated(";");
return STATUS_CONTINUE;
}
CMDRESULT cbInstrAppendMember(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 3))
return STATUS_ERROR;
auto type = argv[1];
auto name = argv[2];
int arrsize = 0, offset = -1;
if(argc > 3)
{
duint value;
if(!valfromstring(argv[3], &value, false))
return STATUS_ERROR;
arrsize = int(value);
if(argc > 4)
{
if(!valfromstring(argv[4], &value, false))
return STATUS_ERROR;
offset = int(value);
}
}
if(!AppendMember(type, name, arrsize, offset))
{
dputs(QT_TRANSLATE_NOOP("DBG", "AppendMember failed"));
return STATUS_ERROR;
}
dprintf_untranslated("%s %s", type, name);
if(arrsize > 0)
dprintf_untranslated("[%d]", arrsize);
if(offset >= 0)
dprintf_untranslated(" (offset: %d)", offset);
dputs_untranslated(";");
return STATUS_CONTINUE;
}
CMDRESULT cbInstrAddFunction(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 3))
return STATUS_ERROR;
auto name = argv[1];
auto rettype = argv[2];
auto callconv = Cdecl;
auto noreturn = false;
if(argc > 3)
{
if(scmp(argv[3], "cdecl"))
callconv = Cdecl;
else if(scmp(argv[3], "stdcall"))
callconv = Stdcall;
else if(scmp(argv[3], "thiscall"))
callconv = Thiscall;
else if(scmp(argv[3], "delphi"))
callconv = Delphi;
else
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Unknown calling convention \"%s\"\n"), argv[3]);
return STATUS_ERROR;
}
if(argc > 4)
{
duint value;
if(!valfromstring(argv[4], &value, false))
return STATUS_ERROR;
noreturn = value != 0;
}
}
if(!AddFunction(towner, name, rettype, callconv, noreturn))
{
dputs(QT_TRANSLATE_NOOP("DBG", "AddFunction failed"));
return STATUS_ERROR;
}
dprintf_untranslated("%s %s();\n", rettype, name);
return STATUS_CONTINUE;
}
CMDRESULT cbInstrAddArg(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 4))
return STATUS_ERROR;
if(!AddArg(argv[1], argv[2], argv[3]))
{
dputs(QT_TRANSLATE_NOOP("DBG", "AddArg failed"));
return STATUS_ERROR;
}
dprintf_untranslated("%s: %s %s;\n", argv[1], argv[2], argv[3]);
return STATUS_CONTINUE;
}
CMDRESULT cbInstrAppendArg(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 3))
return STATUS_ERROR;
if(!AppendArg(argv[1], argv[2]))
{
dputs(QT_TRANSLATE_NOOP("DBG", "AppendArg failed"));
return STATUS_ERROR;
}
dprintf_untranslated("%s %s;\n", argv[1], argv[2]);
return STATUS_CONTINUE;
}
CMDRESULT cbInstrSizeofType(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 2))
return STATUS_ERROR;
auto size = SizeofType(argv[1]);
if(!size)
{
dputs(QT_TRANSLATE_NOOP("DBG", "SizeofType failed"));
return STATUS_ERROR;
}
dprintf_untranslated("sizeof(%s) = %d\n", argv[1], size);
return STATUS_CONTINUE;
}
struct PrintVisitor : TypeManager::Visitor
{
explicit PrintVisitor(duint data = 0, int maxPtrDepth = 0)
: mAddr(data), mMaxPtrDepth(maxPtrDepth) { }
template<typename T>
static String basicPrint(void* data, const char* format)
{
return StringUtils::sprintf(format, *(T*)data);
}
bool visitType(const Member & member, const Type & type) override
{
String valueStr;
Memory<unsigned char*> data(type.size);
if(mAddr)
{
if(MemRead(mAddr + mOffset, data(), data.size()))
{
valueStr.assign(" = ");
switch(type.primitive)
{
case Int8:
valueStr += basicPrint<char>(data(), "%c");
break;
case Uint8:
valueStr += basicPrint<unsigned char>(data(), "0x%02X");
break;
case Int16:
valueStr += basicPrint<short>(data(), "%d");
break;
case Uint16:
valueStr += basicPrint<short>(data(), "%u");
break;
case Int32:
valueStr += basicPrint<int>(data(), "%d");
break;
case Uint32:
valueStr += basicPrint<unsigned int>(data(), "%u");
break;
case Int64:
valueStr += basicPrint<long long>(data(), "%lld");
break;
case Uint64:
valueStr += basicPrint<unsigned long long>(data(), "%llu");
break;
case Dsint:
#ifdef _WIN64
valueStr += basicPrint<dsint>(data(), "%lld");
#else
valueStr += basicPrint<dsint>(data(), "%d");
#endif //_WIN64
break;
case Duint:
#ifdef _WIN64
valueStr += basicPrint<duint>(data(), "%llu");
#else
valueStr += basicPrint<duint>(data(), "%u");
#endif //_WIN64
break;
case Float:
valueStr += basicPrint<float>(data(), "%f");
break;
case Double:
valueStr += basicPrint<double>(data(), "%f");
break;
case Pointer:
valueStr += basicPrint<void*>(data(), "0x%p");
break;
case PtrString:
{
valueStr += basicPrint<char*>(data(), "0x%p");
Memory<char*> strdata(MAX_STRING_SIZE + 1);
if(MemRead(*(duint*)data(), strdata(), strdata.size() - 1))
{
valueStr += " \"";
valueStr += strdata();
valueStr.push_back('\"');
}
else
valueStr += " ???";
}
break;
case PtrWString:
{
valueStr += basicPrint<wchar_t*>(data(), "0x%p");
Memory<wchar_t*> strdata(MAX_STRING_SIZE * 2 + 2);
if(MemRead(*(duint*)data(), strdata(), strdata.size() - 2))
{
valueStr += " L\"";
valueStr += StringUtils::Utf16ToUtf8(strdata());
valueStr.push_back('\"');
}
else
valueStr += " ???";
}
break;
default:
return false;
}
}
else
valueStr = " ???";
}
indent();
auto ptype = mParents.empty() ? Parent::Struct : parent().type;
if(ptype == Parent::Array)
dprintf_untranslated("%s[%u]%s;", member.name.c_str(), parent().index++, valueStr.c_str());
else
dprintf_untranslated("%s %s%s;", type.name.c_str(), member.name.c_str(), valueStr.c_str());
dputs_untranslated(type.pointto.empty() || mPtrDepth >= mMaxPtrDepth ? "" : " {");
if(ptype != Parent::Union)
mOffset += type.size;
return true;
}
bool visitStructUnion(const Member & member, const StructUnion & type) override
{
indent();
dprintf_untranslated("%s %s {\n", type.isunion ? "union" : "struct", type.name.c_str());
mParents.push_back(Parent(type.isunion ? Parent::Union : Parent::Struct));
return true;
}
bool visitArray(const Member & member) override
{
indent();
dprintf_untranslated("%s %s[%d] {\n", member.type.c_str(), member.name.c_str(), member.arrsize);
mParents.push_back(Parent(Parent::Array));
return true;
}
bool visitPtr(const Member & member, const Type & type) override
{
auto offset = mOffset;
auto res = visitType(member, type); //print the pointer value
if(mPtrDepth >= mMaxPtrDepth)
return false;
duint value = 0;
if(!mAddr || !MemRead(mAddr + offset, &value, sizeof(value)))
return false;
mParents.push_back(Parent(Parent::Pointer));
parent().offset = mOffset;
parent().addr = mAddr;
mOffset = 0;
mAddr = value;
mPtrDepth++;
return res;
}
bool visitBack(const Member & member) override
{
if(parent().type == Parent::Pointer)
{
mOffset = parent().offset;
mAddr = parent().addr;
mPtrDepth--;
}
mParents.pop_back();
indent();
if(parent().type == Parent::Array)
dprintf_untranslated("};\n");
else
dprintf_untranslated("} %s;\n", member.name.c_str());
return true;
}
private:
struct Parent
{
enum Type
{
Struct,
Union,
Array,
Pointer
};
Type type;
unsigned int index = 0;
duint addr = 0;
duint offset = 0;
explicit Parent(Type type)
: type(type) { }
};
Parent & parent()
{
return mParents[mParents.size() - 1];
}
void indent() const
{
if(mAddr)
dprintf_untranslated("%p ", mAddr + mOffset);
for(auto i = 0; i < int(mParents.size()) * 2; i++)
dprintf_untranslated(" ");
}
std::vector<Parent> mParents;
duint mOffset = 0;
duint mAddr = 0;
int mPtrDepth = 0;
int mMaxPtrDepth = 0;
};
CMDRESULT cbInstrVisitType(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 2))
return STATUS_ERROR;
auto type = argv[1];
auto name = "visit";
duint addr = 0;
auto maxPtrDepth = 0;
if(argc > 2)
{
if(!valfromstring(argv[2], &addr, false))
return STATUS_ERROR;
if(argc > 3)
{
duint value;
if(!valfromstring(argv[3], &value, false))
return STATUS_ERROR;
maxPtrDepth = int(value);
if(argc > 4)
name = argv[4];
}
}
PrintVisitor visitor(addr, maxPtrDepth);
if(!VisitType(type, name, visitor))
{
dputs(QT_TRANSLATE_NOOP("DBG", "VisitType failed"));
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
CMDRESULT cbInstrClearTypes(int argc, char* argv[])
{
auto owner = towner;
if(argc > 1)
owner = argv[1];
ClearTypes(owner);
return STATUS_CONTINUE;
}
CMDRESULT cbInstrRemoveType(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 2))
return STATUS_ERROR;
if(!RemoveType(argv[1]))
{
dputs(QT_TRANSLATE_NOOP("DBG", "RemoveType failed"));
return STATUS_ERROR;
}
dprintf(QT_TRANSLATE_NOOP("DBG", "Type %s removed\n"), argv[1]);
return STATUS_CONTINUE;
}
CMDRESULT cbInstrEnumTypes(int argc, char* argv[])
{
std::vector<TypeManager::Summary> typeList;
EnumTypes(typeList);
for(auto & type : typeList)
{
if(type.owner.empty())
type.owner.assign("x64dbg");
dprintf_untranslated("%s: %s %s, sizeof(%s) = %d\n", type.owner.c_str(), type.kind.c_str(), type.name.c_str(), type.name.c_str(), type.size);
}
return STATUS_CONTINUE;
}

View File

@ -20,4 +20,18 @@ CMDRESULT cbInstrDataAscii(int argc, char* argv[]);
CMDRESULT cbInstrDataUnicode(int argc, char* argv[]);
CMDRESULT cbInstrDataCode(int argc, char* argv[]);
CMDRESULT cbInstrDataJunk(int argc, char* argv[]);
CMDRESULT cbInstrDataMiddle(int argc, char* argv[]);
CMDRESULT cbInstrDataMiddle(int argc, char* argv[]);
CMDRESULT cbInstrAddType(int argc, char* argv[]);
CMDRESULT cbInstrAddStruct(int argc, char* argv[]);
CMDRESULT cbInstrAddUnion(int argc, char* argv[]);
CMDRESULT cbInstrAddMember(int argc, char* argv[]);
CMDRESULT cbInstrAppendMember(int argc, char* argv[]);
CMDRESULT cbInstrAddFunction(int argc, char* argv[]);
CMDRESULT cbInstrAddArg(int argc, char* argv[]);
CMDRESULT cbInstrAppendArg(int argc, char* argv[]);
CMDRESULT cbInstrSizeofType(int argc, char* argv[]);
CMDRESULT cbInstrVisitType(int argc, char* argv[]);
CMDRESULT cbInstrClearTypes(int argc, char* argv[]);
CMDRESULT cbInstrRemoveType(int argc, char* argv[]);
CMDRESULT cbInstrEnumTypes(int argc, char* argv[]);

View File

@ -69,6 +69,7 @@ enum SectionLock
LockHistory,
LockSymbolCache,
LockLineCache,
LockTypeManager,
// Number of elements in this enumeration. Must always be the last
// index.

427
src/dbg/types.cpp Normal file
View File

@ -0,0 +1,427 @@
#include "types.h"
#include "stringutils.h"
#include "threading.h"
using namespace Types;
static TypeManager typeManager;
TypeManager::TypeManager()
{
auto p = [this](const std::string & n, Primitive p, int size)
{
primitivesizes[p] = size;
auto splits = StringUtils::Split(n, ',');
for(const auto & split : splits)
addType("", p, split);
};
p("int8_t,int8,char,byte,bool,signed char", Int8, sizeof(char));
p("uint8_t,uint8,uchar,unsigned char,ubyte", Uint8, sizeof(unsigned char));
p("int16_t,int16,wchar_t,char16_t,short", Int16, sizeof(short));
p("uint16_t,uint16,ushort,unsigned short", Int16, sizeof(unsigned short));
p("int32_t,int32,int,long", Int32, sizeof(int));
p("uint32_t,uint32,unsigned int,unsigned long", Uint32, sizeof(unsigned int));
p("int64_t,int64,long long", Int64, sizeof(long long));
p("uint64_t,uint64,unsigned long long", Uint64, sizeof(unsigned long long));
p("dsint", Dsint, sizeof(void*));
p("duint,size_t", Duint, sizeof(void*));
p("float", Float, sizeof(float));
p("double", Double, sizeof(double));
p("ptr,void*", Pointer, sizeof(void*));
p("char*,const char*", PtrString, sizeof(char*));
p("wchar_t*,const wchar_t*", PtrWString, sizeof(wchar_t*));
}
bool TypeManager::AddType(const std::string & owner, const std::string & type, const std::string & name)
{
if(owner.empty())
return false;
validPtr(type);
auto found = types.find(type);
if(found == types.end())
return false;
return addType(owner, found->second.primitive, name);
}
bool TypeManager::AddStruct(const std::string & owner, const std::string & name)
{
StructUnion s;
s.name = name;
s.owner = owner;
return addStructUnion(s);
}
bool TypeManager::AddUnion(const std::string & owner, const std::string & name)
{
StructUnion u;
u.owner = owner;
u.name = name;
u.isunion = true;
return addStructUnion(u);
}
bool TypeManager::AddMember(const std::string & parent, const std::string & type, const std::string & name, int arrsize, int offset)
{
if(!isDefined(type) && !validPtr(type))
return false;
auto found = structs.find(parent);
if(arrsize < 0 || found == structs.end() || !isDefined(type) || name.empty() || type.empty() || type == parent)
return false;
auto & s = found->second;
for(const auto & member : s.members)
if(member.name == name)
return false;
auto typeSize = Sizeof(type);
if(arrsize)
typeSize *= arrsize;
Member m;
m.name = name;
m.arrsize = arrsize;
m.type = type;
if(offset >= 0) //user-defined offset
{
if(offset < s.size)
return false;
if(offset > s.size)
{
Member pad;
pad.type = "char";
pad.arrsize = offset - s.size;
char padname[32] = "";
sprintf_s(padname, "padding%d", pad.arrsize);
pad.name = padname;
s.members.push_back(m);
s.size += pad.arrsize;
}
}
s.members.push_back(m);
if(s.isunion)
{
if(typeSize > s.size)
s.size = typeSize;
}
else
{
s.size += typeSize;
}
return true;
}
bool TypeManager::AppendMember(const std::string & type, const std::string & name, int arrsize, int offset)
{
return AddMember(laststruct, type, name, arrsize, offset);
}
bool TypeManager::AddFunction(const std::string & owner, const std::string & name, const std::string & rettype, CallingConvention callconv, bool noreturn)
{
auto found = functions.find(name);
if(found != functions.end() || name.empty() || owner.empty())
return false;
lastfunction = name;
Function f;
f.owner = owner;
f.name = name;
f.rettype = rettype;
f.callconv = callconv;
f.noreturn = noreturn;
functions.insert({f.name, f});
return true;
}
bool TypeManager::AddArg(const std::string & function, const std::string & type, const std::string & name)
{
if(!isDefined(type) && !validPtr(type))
return false;
auto found = functions.find(function);
if(found == functions.end() || function.empty() || name.empty() || !isDefined(type))
return false;
lastfunction = function;
Member arg;
arg.name = name;
arg.type = type;
found->second.args.push_back(arg);
return true;
}
bool TypeManager::AppendArg(const std::string & type, const std::string & name)
{
return AddArg(lastfunction, type, name);
}
int TypeManager::Sizeof(const std::string & type) const
{
auto foundT = types.find(type);
if(foundT != types.end())
return foundT->second.size;
auto foundS = structs.find(type);
if(foundS != structs.end())
return foundS->second.size;
auto foundF = functions.find(type);
if(foundF != functions.end())
{
const auto foundP = primitivesizes.find(Pointer);
if(foundP != primitivesizes.end())
return foundP->second;
return sizeof(void*);
}
return 0;
}
bool TypeManager::Visit(const std::string & type, const std::string & name, Visitor & visitor) const
{
Member m;
m.name = name;
m.type = type;
return visitMember(m, visitor);
}
template<typename K, typename V>
static void filterOwnerMap(std::unordered_map<K, V> & map, const std::string & owner)
{
for(auto i = map.begin(); i != map.end();)
{
auto j = i++;
if(j->second.owner.empty())
continue;
if(owner.empty() || j->second.owner == owner)
map.erase(j);
}
}
void TypeManager::Clear(const std::string & owner)
{
laststruct.clear();
lastfunction.clear();
filterOwnerMap(types, owner);
filterOwnerMap(structs, owner);
filterOwnerMap(functions, owner);
}
template<typename K, typename V>
static bool removeType(std::unordered_map<K, V> & map, const std::string & type)
{
auto found = map.find(type);
if(found == map.end())
return false;
if(found->second.owner.empty())
return false;
map.erase(found);
return true;
}
bool TypeManager::RemoveType(const std::string & type)
{
return removeType(types, type) || removeType(structs, type) || removeType(functions, type);
}
template<typename K, typename V>
static void enumType(const std::unordered_map<K, V> & map, const std::string & kind, std::vector<TypeManager::Summary> & types)
{
for(auto i = map.begin(); i != map.end(); ++i)
{
TypeManager::Summary s;
s.kind = kind;
s.name = i->second.name;
s.owner = i->second.owner;
s.size = SizeofType(s.name);
types.push_back(s);
}
}
void TypeManager::Enum(std::vector<Summary> & typeList) const
{
typeList.clear();
enumType(types, "typedef", typeList);
enumType(structs, "structunion", typeList);
enumType(functions, "function", typeList);
}
template<typename K, typename V>
static bool mapContains(const std::unordered_map<K, V> & map, const K & k)
{
return map.find(k) != map.end();
}
bool TypeManager::isDefined(const std::string & id) const
{
return mapContains(types, id) || mapContains(structs, id);
}
bool TypeManager::validPtr(const std::string & id)
{
if(id[id.length() - 1] == '*')
{
auto type = id.substr(0, id.length() - 1);
if(!isDefined(type))
return false;
std::string owner("ptr");
auto foundT = types.find(type);
if(foundT != types.end())
owner = foundT->second.owner;
auto foundS = structs.find(type);
if(foundS != structs.end())
owner = foundS->second.owner;
return addType(owner, Pointer, id, type);
}
return false;
}
bool TypeManager::addStructUnion(const StructUnion & s)
{
laststruct = s.name;
if(s.owner.empty() || s.name.empty() || isDefined(s.name))
return false;
structs.insert({s.name, s});
return true;
}
bool TypeManager::addType(const Type & t)
{
if(t.name.empty() || isDefined(t.name))
return false;
types.insert({t.name, t});
return true;
}
bool TypeManager::addType(const std::string & owner, Primitive primitive, const std::string & name, const std::string & pointto)
{
if(name.empty() || isDefined(name))
return false;
Type t;
t.owner = owner;
t.name = name;
t.primitive = primitive;
t.size = primitivesizes[primitive];
t.pointto = pointto;
return addType(t);
}
bool TypeManager::visitMember(const Member & root, Visitor & visitor) const
{
auto foundT = types.find(root.type);
if(foundT != types.end())
{
const auto & t = foundT->second;
if(!t.pointto.empty())
{
if(!isDefined(t.pointto))
return false;
if(visitor.visitPtr(root, t)) //allow the visitor to bail out
{
if(!Visit(t.pointto, "*" + root.name, visitor))
return false;
return visitor.visitBack(root);
}
return true;
}
return visitor.visitType(root, t);
}
auto foundS = structs.find(root.type);
if(foundS != structs.end())
{
const auto & s = foundS->second;
if(!visitor.visitStructUnion(root, s))
return false;
for(const auto & child : s.members)
{
if(child.arrsize)
{
if(!visitor.visitArray(child))
return false;
for(auto i = 0; i < child.arrsize; i++)
if(!visitMember(child, visitor))
return false;
if(!visitor.visitBack(child))
return false;
}
else if(!visitMember(child, visitor))
return false;
}
return visitor.visitBack(root);
}
return false;
}
bool AddType(const std::string & owner, const std::string & type, const std::string & name)
{
EXCLUSIVE_ACQUIRE(LockTypeManager);
return typeManager.AddType(owner, type, name);
}
bool AddStruct(const std::string & owner, const std::string & name)
{
EXCLUSIVE_ACQUIRE(LockTypeManager);
return typeManager.AddStruct(owner, name);
}
bool AddUnion(const std::string & owner, const std::string & name)
{
EXCLUSIVE_ACQUIRE(LockTypeManager);
return typeManager.AddUnion(owner, name);
}
bool AddMember(const std::string & parent, const std::string & type, const std::string & name, int arrsize, int offset)
{
EXCLUSIVE_ACQUIRE(LockTypeManager);
return typeManager.AddMember(parent, type, name, arrsize, offset);
}
bool AppendMember(const std::string & type, const std::string & name, int arrsize, int offset)
{
EXCLUSIVE_ACQUIRE(LockTypeManager);
return typeManager.AppendMember(type, name, arrsize, offset);
}
bool AddFunction(const std::string & owner, const std::string & name, const std::string & rettype, Types::CallingConvention callconv, bool noreturn)
{
EXCLUSIVE_ACQUIRE(LockTypeManager);
return typeManager.AddFunction(owner, name, rettype, callconv, noreturn);
}
bool AddArg(const std::string & function, const std::string & type, const std::string & name)
{
EXCLUSIVE_ACQUIRE(LockTypeManager);
return typeManager.AddArg(function, type, name);
}
bool AppendArg(const std::string & type, const std::string & name)
{
EXCLUSIVE_ACQUIRE(LockTypeManager);
return typeManager.AppendArg(type, name);
}
int SizeofType(const std::string & type)
{
SHARED_ACQUIRE(LockTypeManager);
return typeManager.Sizeof(type);
}
bool VisitType(const std::string & type, const std::string & name, Types::TypeManager::Visitor & visitor)
{
SHARED_ACQUIRE(LockTypeManager);
return typeManager.Visit(type, name, visitor);
}
void ClearTypes(const std::string & owner)
{
EXCLUSIVE_ACQUIRE(LockTypeManager);
return typeManager.Clear(owner);
}
bool RemoveType(const std::string & type)
{
EXCLUSIVE_ACQUIRE(LockTypeManager);
return typeManager.RemoveType(type);
}
void EnumTypes(std::vector<Types::TypeManager::Summary> & typeList)
{
SHARED_ACQUIRE(LockTypeManager);
return typeManager.Enum(typeList);
}

135
src/dbg/types.h Normal file
View File

@ -0,0 +1,135 @@
#pragma once
#include <string>
#include <vector>
#include <unordered_map>
namespace Types
{
enum Primitive
{
Int8,
Uint8,
Int16,
Uint16,
Int32,
Uint32,
Int64,
Uint64,
Dsint,
Duint,
Float,
Double,
Pointer,
PtrString, //char* (null-terminated)
PtrWString //wchar_t* (null-terminated)
};
struct Type
{
std::string owner; //Type owner
std::string name; //Type identifier.
std::string pointto; //Type identifier of *Type
Primitive primitive; //Primitive type.
int size = 0; //Size in bytes.
};
struct Member
{
std::string name; //Member identifier
std::string type; //Type.name
int arrsize = 0; //Number of elements if Member is an array
};
struct StructUnion
{
std::string owner; //StructUnion owner
std::string name; //StructUnion identifier
std::vector<Member> members; //StructUnion members
bool isunion = false; //Is this a union?
int size = 0;
};
enum CallingConvention
{
Cdecl,
Stdcall,
Thiscall,
Delphi
};
struct Function
{
std::string owner; //Function owner
std::string name; //Function identifier
std::string rettype; //Function return type
CallingConvention callconv; //Function calling convention
bool noreturn; //Function does not return (ExitProcess, _exit)
std::vector<Member> args; //Function arguments
};
struct TypeManager
{
struct Visitor
{
virtual ~Visitor() { }
virtual bool visitType(const Member & member, const Type & type) = 0;
virtual bool visitStructUnion(const Member & member, const StructUnion & type) = 0;
virtual bool visitArray(const Member & member) = 0;
virtual bool visitPtr(const Member & member, const Type & type) = 0;
virtual bool visitBack(const Member & member) = 0;
};
struct Summary
{
std::string kind;
std::string name;
std::string owner;
int size;
};
explicit TypeManager();
bool AddType(const std::string & owner, const std::string & type, const std::string & name);
bool AddStruct(const std::string & owner, const std::string & name);
bool AddUnion(const std::string & owner, const std::string & name);
bool AddMember(const std::string & parent, const std::string & type, const std::string & name, int arrsize = 0, int offset = -1);
bool AppendMember(const std::string & type, const std::string & name, int arrsize = 0, int offset = -1);
bool AddFunction(const std::string & owner, const std::string & name, const std::string & rettype, CallingConvention callconv = Cdecl, bool noreturn = false);
bool AddArg(const std::string & function, const std::string & type, const std::string & name);
bool AppendArg(const std::string & type, const std::string & name);
int Sizeof(const std::string & type) const;
bool Visit(const std::string & type, const std::string & name, Visitor & visitor) const;
void Clear(const std::string & owner = "");
bool RemoveType(const std::string & type);
void Enum(std::vector<Summary> & typeList) const;
private:
std::unordered_map<Primitive, int> primitivesizes;
std::unordered_map<std::string, Type> types;
std::unordered_map<std::string, StructUnion> structs;
std::unordered_map<std::string, Function> functions;
std::string laststruct;
std::string lastfunction;
bool isDefined(const std::string & id) const;
bool validPtr(const std::string & id);
bool addStructUnion(const StructUnion & s);
bool addType(const std::string & owner, Primitive primitive, const std::string & name, const std::string & pointto = "");
bool addType(const Type & t);
bool visitMember(const Member & root, Visitor & visitor) const;
};
};
bool AddType(const std::string & owner, const std::string & type, const std::string & name);
bool AddStruct(const std::string & owner, const std::string & name);
bool AddUnion(const std::string & owner, const std::string & name);
bool AddMember(const std::string & parent, const std::string & type, const std::string & name, int arrsize = 0, int offset = -1);
bool AppendMember(const std::string & type, const std::string & name, int arrsize = 0, int offset = -1);
bool AddFunction(const std::string & owner, const std::string & name, const std::string & rettype, Types::CallingConvention callconv = Types::Cdecl, bool noreturn = false);
bool AddArg(const std::string & function, const std::string & type, const std::string & name);
bool AppendArg(const std::string & type, const std::string & name);
int SizeofType(const std::string & type);
bool VisitType(const std::string & type, const std::string & name, Types::TypeManager::Visitor & visitor);
void ClearTypes(const std::string & owner = "");
bool RemoveType(const std::string & type);
void EnumTypes(std::vector<Types::TypeManager::Summary> & typeList);

View File

@ -24,6 +24,7 @@
#include "datainst_helper.h"
#include "exception.h"
#include "expressionfunctions.h"
#include "yara/yara.h"
static MESSAGE_STACK* gMsgStack = 0;
static HANDLE hCommandLoopThread = 0;
@ -341,6 +342,20 @@ static void registercommands()
dbgcmdnew("DataJunk", cbInstrDataJunk, true); //mark as Junk
dbgcmdnew("DataMiddle", cbInstrDataMiddle, true); //mark as Middle
dbgcmdnew("AddType", cbInstrAddType, false); //AddType
dbgcmdnew("AddStruct", cbInstrAddStruct, false); //AddStruct
dbgcmdnew("AddUnion", cbInstrAddUnion, false); //AddUnion
dbgcmdnew("AddMember", cbInstrAddMember, false); //AddMember
dbgcmdnew("AppendMember", cbInstrAppendMember, false); //AppendMember
dbgcmdnew("AddFunction", cbInstrAddFunction, false); //AddFunction
dbgcmdnew("AddArg", cbInstrAddArg, false); //AddArg
dbgcmdnew("AppendArg", cbInstrAppendArg, false); //AppendArg
dbgcmdnew("SizeofType", cbInstrSizeofType, false); //SizeofType
dbgcmdnew("VisitType", cbInstrVisitType, false); //VisitType
dbgcmdnew("ClearTypes", cbInstrClearTypes, false); //ClearTypes
dbgcmdnew("RemoveType", cbInstrRemoveType, false); //RemoveType
dbgcmdnew("EnumTypes", cbInstrEnumTypes, false); //EnumTypes
//plugins
dbgcmdnew("StartScylla\1scylla\1imprec", cbDebugStartScylla, false); //start scylla
dbgcmdnew("plugload\1pluginload\1loadplugin", cbInstrPluginLoad, false); //load plugin

View File

@ -100,6 +100,7 @@
<ClCompile Include="thread.cpp" />
<ClCompile Include="threading.cpp" />
<ClCompile Include="TraceRecord.cpp" />
<ClCompile Include="types.cpp" />
<ClCompile Include="value.cpp" />
<ClCompile Include="variable.cpp" />
<ClCompile Include="watch.cpp" />
@ -223,6 +224,7 @@
<ClInclude Include="taskthread.h" />
<ClInclude Include="tcpconnections.h" />
<ClInclude Include="TraceRecord.h" />
<ClInclude Include="types.h" />
<ClInclude Include="watch.h" />
<ClInclude Include="xrefs.h" />
<ClInclude Include="yara\yara\integers.h" />

View File

@ -407,6 +407,9 @@
<ClCompile Include="x64dbg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="types.cpp">
<Filter>Source Files\Core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="dbghelp\dbghelp.h">
@ -907,5 +910,8 @@
<ClInclude Include="x64dbg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="types.h">
<Filter>Header Files\Core</Filter>
</ClInclude>
</ItemGroup>
</Project>