PROJECT: RESTRUCTURE
This commit is contained in:
parent
cb173d28a1
commit
2297a92935
BIN
AStyle.dll
BIN
AStyle.dll
Binary file not shown.
BIN
AStyleWhore.exe
BIN
AStyleWhore.exe
Binary file not shown.
|
|
@ -1,2 +0,0 @@
|
|||
# this file is only for the people who have serious mental issues (USE WITH CAUTION, THIS DOESN'T WORK)
|
||||
/\s*([\^+\-*=&|<>\/%!]|<<|>>)?\s*=\s*/ -> / \1= /
|
||||
|
|
@ -4,13 +4,13 @@
|
|||
#
|
||||
|
||||
#check if the formatter is present
|
||||
if [ ! -f ./AStyleWhore.exe ]; then
|
||||
if [ ! -f ./hooks/AStyleWhore.exe ]; then
|
||||
echo "AStyleWhore not found!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#format the code
|
||||
"./AStyleWhore.exe" Silent
|
||||
"./hooks/AStyleWhore.exe" Silent
|
||||
|
||||
#exit when nothing needs to be done
|
||||
if [ $? == 0 ]; then
|
||||
|
|
@ -28,6 +28,6 @@ fi
|
|||
#cancel commit if the changes were undone by the formatting
|
||||
gitFiles=$(git diff-index --name-only --cached HEAD)
|
||||
if [ -z "$gitFiles" ]; then
|
||||
"./AStyleWhore.exe" "After formatting, no files were staged..."
|
||||
"./hooks/AStyleWhore.exe" "After formatting, no files were staged..."
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,326 +1,326 @@
|
|||
#ifndef _UTF8INI_H
|
||||
#define _UTF8INI_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class Utf8Ini
|
||||
{
|
||||
public:
|
||||
/**
|
||||
\brief Serialize to the INI file format.
|
||||
*/
|
||||
inline std::string Serialize() const
|
||||
{
|
||||
std::string output;
|
||||
for(const auto & section : _sections)
|
||||
{
|
||||
if(output.length())
|
||||
appendLine(output, "");
|
||||
appendLine(output, makeSectionText(section.first));
|
||||
for(const auto & keyvalue : section.second)
|
||||
if(keyvalue.first.length())
|
||||
appendLine(output, makeKeyValueText(keyvalue.first, keyvalue.second));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Deserialize from the INI file format.
|
||||
\param data The INI data.
|
||||
\param [out] errorLine The error line (only has a meaning when this function failed).
|
||||
\return true if it succeeds, false if it fails.
|
||||
*/
|
||||
inline bool Deserialize(const std::string & data, int & errorLine)
|
||||
{
|
||||
//initialize
|
||||
errorLine = 0;
|
||||
Clear();
|
||||
|
||||
//read lines
|
||||
std::vector<std::string> lines;
|
||||
std::string curLine;
|
||||
for(auto ch : data)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case '\r':
|
||||
break;
|
||||
case '\n':
|
||||
lines.push_back(trim(curLine));
|
||||
curLine.clear();
|
||||
break;
|
||||
default:
|
||||
curLine += ch;
|
||||
}
|
||||
}
|
||||
if(curLine.length())
|
||||
lines.push_back(trim(curLine));
|
||||
|
||||
//parse lines
|
||||
std::string section = "";
|
||||
for(const auto & line : lines)
|
||||
{
|
||||
errorLine++;
|
||||
switch(getLineType(line))
|
||||
{
|
||||
case LineType::Invalid:
|
||||
MessageBoxA(0, line.c_str(), "line", 0);
|
||||
return false;
|
||||
|
||||
case LineType::Comment:
|
||||
case LineType::Empty:
|
||||
continue;
|
||||
|
||||
case LineType::KeyValue:
|
||||
{
|
||||
std::string key;
|
||||
std::string value;
|
||||
if(!section.length() ||
|
||||
!parseKeyValueLine(line, key, value) ||
|
||||
!SetValue(section, key, value))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LineType::Section:
|
||||
if(!parseSectionLine(line, section))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Sets a value. This will overwrite older values.
|
||||
\param section The section. Must have a length greater than one.
|
||||
\param key The key. Must have a length greater than one.
|
||||
\param value The value. Can be empty (effectively removing the value).
|
||||
\return true if the value was set successfully, false otherwise.
|
||||
*/
|
||||
inline bool SetValue(const std::string & section, const std::string & key, const std::string & value)
|
||||
{
|
||||
auto trimmedSection = trim(section);
|
||||
auto trimmedKey = trim(key);
|
||||
if(!trimmedSection.length() || !trimmedKey.length())
|
||||
return false;
|
||||
auto found = _sections.find(trimmedSection);
|
||||
if(found != _sections.end())
|
||||
found->second[trimmedKey] = value;
|
||||
else
|
||||
{
|
||||
KeyValueMap keyValueMap;
|
||||
keyValueMap[trimmedKey] = value;
|
||||
_sections[trimmedSection] = keyValueMap;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Removes all key/value pairs from a section.
|
||||
\param section The section to clear.
|
||||
\return true if it succeeds, false otherwise.
|
||||
*/
|
||||
inline bool ClearSection(const std::string & section)
|
||||
{
|
||||
auto trimmedSection = trim(section);
|
||||
if(!trimmedSection.length())
|
||||
return false;
|
||||
auto found = _sections.find(trimmedSection);
|
||||
if(found == _sections.end())
|
||||
return false;
|
||||
_sections.erase(found);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Removes all sections.
|
||||
*/
|
||||
inline void Clear()
|
||||
{
|
||||
_sections.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets a value.
|
||||
\param section The section.
|
||||
\param key The key.
|
||||
\param [in,out] value The value.
|
||||
\return The value. Empty string when the value was not found or empty.
|
||||
*/
|
||||
inline std::string GetValue(const std::string & section, const std::string & key) const
|
||||
{
|
||||
auto trimmedSection = trim(section);
|
||||
auto trimmedKey = trim(key);
|
||||
if(!trimmedSection.length() || !trimmedKey.length())
|
||||
return "";
|
||||
auto sectionFound = _sections.find(trimmedSection);
|
||||
if(sectionFound == _sections.end())
|
||||
return "";
|
||||
const auto & keyValueMap = sectionFound->second;
|
||||
auto keyFound = keyValueMap.find(trimmedKey);
|
||||
if(keyFound == keyValueMap.end())
|
||||
return "";
|
||||
return keyFound->second;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::map<std::string, std::string> KeyValueMap;
|
||||
std::map<std::string, KeyValueMap> _sections;
|
||||
|
||||
enum class LineType
|
||||
{
|
||||
Invalid,
|
||||
Empty,
|
||||
Section,
|
||||
KeyValue,
|
||||
Comment
|
||||
};
|
||||
|
||||
static inline LineType getLineType(const std::string & line)
|
||||
{
|
||||
auto len = line.length();
|
||||
if(!len)
|
||||
return LineType::Empty;
|
||||
if(line[0] == '[' && line[len - 1] == ']')
|
||||
return LineType::Section;
|
||||
if(line[0] == ';')
|
||||
return LineType::Comment;
|
||||
if(line.find('=') != std::string::npos)
|
||||
return LineType::KeyValue;
|
||||
return LineType::Invalid;
|
||||
}
|
||||
|
||||
static inline std::string trim(const std::string & str)
|
||||
{
|
||||
auto len = str.length();
|
||||
if(!len)
|
||||
return "";
|
||||
size_t pre = 0;
|
||||
while(str[pre] == ' ')
|
||||
pre++;
|
||||
size_t post = 0;
|
||||
while(str[len - post - 1] == ' ' && post < len)
|
||||
post++;
|
||||
auto sublen = len - post - pre;
|
||||
return sublen > 0 ? str.substr(pre, len - post - pre) : "";
|
||||
}
|
||||
|
||||
static inline bool parseKeyValueLine(const std::string & line, std::string & key, std::string & value)
|
||||
{
|
||||
auto pos = line.find('=');
|
||||
key = trim(line.substr(0, pos));
|
||||
value = trim(line.substr(pos + 1));
|
||||
auto len = value.length();
|
||||
if(len && value[0] == '\"' && value[len - 1] == '\"')
|
||||
value = unescapeValue(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool parseSectionLine(const std::string & line, std::string & section)
|
||||
{
|
||||
section = trim(line.substr(1, line.length() - 2));
|
||||
return section.length() > 0;
|
||||
}
|
||||
|
||||
static inline void appendLine(std::string & output, const std::string & line)
|
||||
{
|
||||
if(output.length())
|
||||
output += "\r\n";
|
||||
output += line;
|
||||
}
|
||||
|
||||
static inline std::string makeSectionText(const std::string & section)
|
||||
{
|
||||
return "[" + section + "]";
|
||||
}
|
||||
|
||||
static inline std::string makeKeyValueText(const std::string & key, const std::string & value)
|
||||
{
|
||||
return key + "=" + escapeValue(value);
|
||||
}
|
||||
|
||||
static inline bool needsEscaping(const std::string & value)
|
||||
{
|
||||
auto len = value.length();
|
||||
return len && (value[0] == ' ' || value[len - 1] == ' ' ||
|
||||
value.find('\n') != std::string::npos ||
|
||||
value.find('\"') != std::string::npos);
|
||||
}
|
||||
|
||||
static inline std::string escapeValue(const std::string & value)
|
||||
{
|
||||
if(!needsEscaping(value))
|
||||
return value;
|
||||
std::string escaped = "\"";
|
||||
for(auto ch : value)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case '\"':
|
||||
escaped += "\\\"";
|
||||
break;
|
||||
case '\\':
|
||||
escaped += "\\\\";
|
||||
break;
|
||||
case '\r':
|
||||
escaped += "\\r";
|
||||
break;
|
||||
case '\n':
|
||||
escaped += "\\n";
|
||||
break;
|
||||
case '\t':
|
||||
escaped += "\\t";
|
||||
default:
|
||||
escaped += ch;
|
||||
}
|
||||
}
|
||||
return escaped + "\"";
|
||||
}
|
||||
|
||||
static inline std::string unescapeValue(const std::string & str)
|
||||
{
|
||||
std::string result;
|
||||
bool bEscaped = false;
|
||||
for(auto ch : str)
|
||||
{
|
||||
if(!bEscaped)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case '\"':
|
||||
break;
|
||||
case '\\':
|
||||
bEscaped = true;
|
||||
break;
|
||||
default:
|
||||
result += ch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case 'r':
|
||||
result += '\r';
|
||||
break;
|
||||
case 'n':
|
||||
result += '\n';
|
||||
break;
|
||||
case 't':
|
||||
result += '\t';
|
||||
break;
|
||||
default:
|
||||
result += ch;
|
||||
}
|
||||
bEscaped = false;
|
||||
}
|
||||
}
|
||||
if(bEscaped)
|
||||
result += '\\';
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef _UTF8INI_H
|
||||
#define _UTF8INI_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class Utf8Ini
|
||||
{
|
||||
public:
|
||||
/**
|
||||
\brief Serialize to the INI file format.
|
||||
*/
|
||||
inline std::string Serialize() const
|
||||
{
|
||||
std::string output;
|
||||
for(const auto & section : _sections)
|
||||
{
|
||||
if(output.length())
|
||||
appendLine(output, "");
|
||||
appendLine(output, makeSectionText(section.first));
|
||||
for(const auto & keyvalue : section.second)
|
||||
if(keyvalue.first.length())
|
||||
appendLine(output, makeKeyValueText(keyvalue.first, keyvalue.second));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Deserialize from the INI file format.
|
||||
\param data The INI data.
|
||||
\param [out] errorLine The error line (only has a meaning when this function failed).
|
||||
\return true if it succeeds, false if it fails.
|
||||
*/
|
||||
inline bool Deserialize(const std::string & data, int & errorLine)
|
||||
{
|
||||
//initialize
|
||||
errorLine = 0;
|
||||
Clear();
|
||||
|
||||
//read lines
|
||||
std::vector<std::string> lines;
|
||||
std::string curLine;
|
||||
for(auto ch : data)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case '\r':
|
||||
break;
|
||||
case '\n':
|
||||
lines.push_back(trim(curLine));
|
||||
curLine.clear();
|
||||
break;
|
||||
default:
|
||||
curLine += ch;
|
||||
}
|
||||
}
|
||||
if(curLine.length())
|
||||
lines.push_back(trim(curLine));
|
||||
|
||||
//parse lines
|
||||
std::string section = "";
|
||||
for(const auto & line : lines)
|
||||
{
|
||||
errorLine++;
|
||||
switch(getLineType(line))
|
||||
{
|
||||
case LineType::Invalid:
|
||||
MessageBoxA(0, line.c_str(), "line", 0);
|
||||
return false;
|
||||
|
||||
case LineType::Comment:
|
||||
case LineType::Empty:
|
||||
continue;
|
||||
|
||||
case LineType::KeyValue:
|
||||
{
|
||||
std::string key;
|
||||
std::string value;
|
||||
if(!section.length() ||
|
||||
!parseKeyValueLine(line, key, value) ||
|
||||
!SetValue(section, key, value))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LineType::Section:
|
||||
if(!parseSectionLine(line, section))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Sets a value. This will overwrite older values.
|
||||
\param section The section. Must have a length greater than one.
|
||||
\param key The key. Must have a length greater than one.
|
||||
\param value The value. Can be empty (effectively removing the value).
|
||||
\return true if the value was set successfully, false otherwise.
|
||||
*/
|
||||
inline bool SetValue(const std::string & section, const std::string & key, const std::string & value)
|
||||
{
|
||||
auto trimmedSection = trim(section);
|
||||
auto trimmedKey = trim(key);
|
||||
if(!trimmedSection.length() || !trimmedKey.length())
|
||||
return false;
|
||||
auto found = _sections.find(trimmedSection);
|
||||
if(found != _sections.end())
|
||||
found->second[trimmedKey] = value;
|
||||
else
|
||||
{
|
||||
KeyValueMap keyValueMap;
|
||||
keyValueMap[trimmedKey] = value;
|
||||
_sections[trimmedSection] = keyValueMap;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Removes all key/value pairs from a section.
|
||||
\param section The section to clear.
|
||||
\return true if it succeeds, false otherwise.
|
||||
*/
|
||||
inline bool ClearSection(const std::string & section)
|
||||
{
|
||||
auto trimmedSection = trim(section);
|
||||
if(!trimmedSection.length())
|
||||
return false;
|
||||
auto found = _sections.find(trimmedSection);
|
||||
if(found == _sections.end())
|
||||
return false;
|
||||
_sections.erase(found);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Removes all sections.
|
||||
*/
|
||||
inline void Clear()
|
||||
{
|
||||
_sections.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets a value.
|
||||
\param section The section.
|
||||
\param key The key.
|
||||
\param [in,out] value The value.
|
||||
\return The value. Empty string when the value was not found or empty.
|
||||
*/
|
||||
inline std::string GetValue(const std::string & section, const std::string & key) const
|
||||
{
|
||||
auto trimmedSection = trim(section);
|
||||
auto trimmedKey = trim(key);
|
||||
if(!trimmedSection.length() || !trimmedKey.length())
|
||||
return "";
|
||||
auto sectionFound = _sections.find(trimmedSection);
|
||||
if(sectionFound == _sections.end())
|
||||
return "";
|
||||
const auto & keyValueMap = sectionFound->second;
|
||||
auto keyFound = keyValueMap.find(trimmedKey);
|
||||
if(keyFound == keyValueMap.end())
|
||||
return "";
|
||||
return keyFound->second;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::map<std::string, std::string> KeyValueMap;
|
||||
std::map<std::string, KeyValueMap> _sections;
|
||||
|
||||
enum class LineType
|
||||
{
|
||||
Invalid,
|
||||
Empty,
|
||||
Section,
|
||||
KeyValue,
|
||||
Comment
|
||||
};
|
||||
|
||||
static inline LineType getLineType(const std::string & line)
|
||||
{
|
||||
auto len = line.length();
|
||||
if(!len)
|
||||
return LineType::Empty;
|
||||
if(line[0] == '[' && line[len - 1] == ']')
|
||||
return LineType::Section;
|
||||
if(line[0] == ';')
|
||||
return LineType::Comment;
|
||||
if(line.find('=') != std::string::npos)
|
||||
return LineType::KeyValue;
|
||||
return LineType::Invalid;
|
||||
}
|
||||
|
||||
static inline std::string trim(const std::string & str)
|
||||
{
|
||||
auto len = str.length();
|
||||
if(!len)
|
||||
return "";
|
||||
size_t pre = 0;
|
||||
while(str[pre] == ' ')
|
||||
pre++;
|
||||
size_t post = 0;
|
||||
while(str[len - post - 1] == ' ' && post < len)
|
||||
post++;
|
||||
auto sublen = len - post - pre;
|
||||
return sublen > 0 ? str.substr(pre, len - post - pre) : "";
|
||||
}
|
||||
|
||||
static inline bool parseKeyValueLine(const std::string & line, std::string & key, std::string & value)
|
||||
{
|
||||
auto pos = line.find('=');
|
||||
key = trim(line.substr(0, pos));
|
||||
value = trim(line.substr(pos + 1));
|
||||
auto len = value.length();
|
||||
if(len && value[0] == '\"' && value[len - 1] == '\"')
|
||||
value = unescapeValue(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool parseSectionLine(const std::string & line, std::string & section)
|
||||
{
|
||||
section = trim(line.substr(1, line.length() - 2));
|
||||
return section.length() > 0;
|
||||
}
|
||||
|
||||
static inline void appendLine(std::string & output, const std::string & line)
|
||||
{
|
||||
if(output.length())
|
||||
output += "\r\n";
|
||||
output += line;
|
||||
}
|
||||
|
||||
static inline std::string makeSectionText(const std::string & section)
|
||||
{
|
||||
return "[" + section + "]";
|
||||
}
|
||||
|
||||
static inline std::string makeKeyValueText(const std::string & key, const std::string & value)
|
||||
{
|
||||
return key + "=" + escapeValue(value);
|
||||
}
|
||||
|
||||
static inline bool needsEscaping(const std::string & value)
|
||||
{
|
||||
auto len = value.length();
|
||||
return len && (value[0] == ' ' || value[len - 1] == ' ' ||
|
||||
value.find('\n') != std::string::npos ||
|
||||
value.find('\"') != std::string::npos);
|
||||
}
|
||||
|
||||
static inline std::string escapeValue(const std::string & value)
|
||||
{
|
||||
if(!needsEscaping(value))
|
||||
return value;
|
||||
std::string escaped = "\"";
|
||||
for(auto ch : value)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case '\"':
|
||||
escaped += "\\\"";
|
||||
break;
|
||||
case '\\':
|
||||
escaped += "\\\\";
|
||||
break;
|
||||
case '\r':
|
||||
escaped += "\\r";
|
||||
break;
|
||||
case '\n':
|
||||
escaped += "\\n";
|
||||
break;
|
||||
case '\t':
|
||||
escaped += "\\t";
|
||||
default:
|
||||
escaped += ch;
|
||||
}
|
||||
}
|
||||
return escaped + "\"";
|
||||
}
|
||||
|
||||
static inline std::string unescapeValue(const std::string & str)
|
||||
{
|
||||
std::string result;
|
||||
bool bEscaped = false;
|
||||
for(auto ch : str)
|
||||
{
|
||||
if(!bEscaped)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case '\"':
|
||||
break;
|
||||
case '\\':
|
||||
bEscaped = true;
|
||||
break;
|
||||
default:
|
||||
result += ch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case 'r':
|
||||
result += '\r';
|
||||
break;
|
||||
case 'n':
|
||||
result += '\n';
|
||||
break;
|
||||
case 't':
|
||||
result += '\t';
|
||||
break;
|
||||
default:
|
||||
result += ch;
|
||||
}
|
||||
bEscaped = false;
|
||||
}
|
||||
}
|
||||
if(bEscaped)
|
||||
result += '\\';
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //_UTF8INI_H
|
||||
|
|
@ -1,26 +1,26 @@
|
|||
#include "_global.h"
|
||||
|
||||
GUIGUIINIT _gui_guiinit;
|
||||
GUISENDMESSAGE _gui_sendmessage;
|
||||
GUISENDMESSAGEASYNC _gui_sendmessageasync;
|
||||
|
||||
DBGDBGINIT _dbg_dbginit;
|
||||
DBGMEMFINDBASEADDR _dbg_memfindbaseaddr;
|
||||
DBGMEMREAD _dbg_memread;
|
||||
DBGMEMWRITE _dbg_memwrite;
|
||||
DBGDBGCMDEXEC _dbg_dbgcmdexec;
|
||||
DBGMEMMAP _dbg_memmap;
|
||||
DBGDBGEXITSIGNAL _dbg_dbgexitsignal;
|
||||
DBGVALFROMSTRING _dbg_valfromstring;
|
||||
DBGISDEBUGGING _dbg_isdebugging;
|
||||
DBGISJUMPGOINGTOEXECUTE _dbg_isjumpgoingtoexecute;
|
||||
DBGADDRINFOGET _dbg_addrinfoget;
|
||||
DBGADDRINFOSET _dbg_addrinfoset;
|
||||
DBGBPGETTYPEAT _dbg_bpgettypeat;
|
||||
DBGGETREGDUMP _dbg_getregdump;
|
||||
DBGVALTOSTRING _dbg_valtostring;
|
||||
DBGMEMISVALIDREADPTR _dbg_memisvalidreadptr;
|
||||
DBGGETBPLIST _dbg_getbplist;
|
||||
DBGDBGCMDEXECDIRECT _dbg_dbgcmddirectexec;
|
||||
DBGGETBRANCHDESTINATION _dbg_getbranchdestination;
|
||||
DBGSENDMESSAGE _dbg_sendmessage;
|
||||
#include "_global.h"
|
||||
|
||||
GUIGUIINIT _gui_guiinit;
|
||||
GUISENDMESSAGE _gui_sendmessage;
|
||||
GUISENDMESSAGEASYNC _gui_sendmessageasync;
|
||||
|
||||
DBGDBGINIT _dbg_dbginit;
|
||||
DBGMEMFINDBASEADDR _dbg_memfindbaseaddr;
|
||||
DBGMEMREAD _dbg_memread;
|
||||
DBGMEMWRITE _dbg_memwrite;
|
||||
DBGDBGCMDEXEC _dbg_dbgcmdexec;
|
||||
DBGMEMMAP _dbg_memmap;
|
||||
DBGDBGEXITSIGNAL _dbg_dbgexitsignal;
|
||||
DBGVALFROMSTRING _dbg_valfromstring;
|
||||
DBGISDEBUGGING _dbg_isdebugging;
|
||||
DBGISJUMPGOINGTOEXECUTE _dbg_isjumpgoingtoexecute;
|
||||
DBGADDRINFOGET _dbg_addrinfoget;
|
||||
DBGADDRINFOSET _dbg_addrinfoset;
|
||||
DBGBPGETTYPEAT _dbg_bpgettypeat;
|
||||
DBGGETREGDUMP _dbg_getregdump;
|
||||
DBGVALTOSTRING _dbg_valtostring;
|
||||
DBGMEMISVALIDREADPTR _dbg_memisvalidreadptr;
|
||||
DBGGETBPLIST _dbg_getbplist;
|
||||
DBGDBGCMDEXECDIRECT _dbg_dbgcmddirectexec;
|
||||
DBGGETBRANCHDESTINATION _dbg_getbranchdestination;
|
||||
DBGSENDMESSAGE _dbg_sendmessage;
|
||||
|
|
@ -1,61 +1,61 @@
|
|||
#ifndef _GLOBAL_H
|
||||
#define _GLOBAL_H
|
||||
|
||||
#include <windows.h>
|
||||
#include "bridgemain.h"
|
||||
|
||||
//GUI typedefs
|
||||
typedef int (*GUIGUIINIT)(int, char**);
|
||||
typedef void* (*GUISENDMESSAGE)(GUIMSG type, void* param1, void* param2);
|
||||
typedef void (*GUISENDMESSAGEASYNC)(GUIMSG type, void* param1, void* param2);
|
||||
|
||||
//GUI functions
|
||||
extern GUIGUIINIT _gui_guiinit;
|
||||
extern GUISENDMESSAGE _gui_sendmessage;
|
||||
extern GUISENDMESSAGEASYNC _gui_sendmessageasync;
|
||||
|
||||
//DBG typedefs
|
||||
typedef const char* (*DBGDBGINIT)();
|
||||
typedef duint (*DBGMEMFINDBASEADDR)(duint addr, duint* size);
|
||||
typedef bool (*DBGMEMREAD)(duint addr, unsigned char* dest, duint size, duint* read);
|
||||
typedef bool (*DBGMEMWRITE)(duint addr, const unsigned char* src, duint size, duint* written);
|
||||
typedef bool (*DBGDBGCMDEXEC)(const char* cmd);
|
||||
typedef bool (*DBGMEMMAP)(MEMMAP* memmap);
|
||||
typedef void (*DBGDBGEXITSIGNAL)();
|
||||
typedef bool (*DBGVALFROMSTRING)(const char* string, duint* value);
|
||||
typedef bool (*DBGISDEBUGGING)();
|
||||
typedef bool (*DBGISJUMPGOINGTOEXECUTE)(duint addr);
|
||||
typedef bool (*DBGADDRINFOGET)(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo);
|
||||
typedef bool (*DBGADDRINFOSET)(duint addr, ADDRINFO* addrinfo);
|
||||
typedef BPXTYPE (*DBGBPGETTYPEAT)(duint addr);
|
||||
typedef bool (*DBGGETREGDUMP)(REGDUMP* regdump);
|
||||
typedef bool (*DBGVALTOSTRING)(const char* string, duint value);
|
||||
typedef bool (*DBGMEMISVALIDREADPTR)(duint addr);
|
||||
typedef int (*DBGGETBPLIST)(BPXTYPE type, BPMAP* bplist);
|
||||
typedef bool (*DBGDBGCMDEXECDIRECT)(const char* cmd);
|
||||
typedef duint (*DBGGETBRANCHDESTINATION)(duint addr);
|
||||
typedef duint (*DBGSENDMESSAGE)(DBGMSG type, void* param1, void* param2);
|
||||
|
||||
//DBG functions
|
||||
extern DBGDBGINIT _dbg_dbginit;
|
||||
extern DBGMEMFINDBASEADDR _dbg_memfindbaseaddr;
|
||||
extern DBGMEMREAD _dbg_memread;
|
||||
extern DBGMEMWRITE _dbg_memwrite;
|
||||
extern DBGDBGCMDEXEC _dbg_dbgcmdexec;
|
||||
extern DBGMEMMAP _dbg_memmap;
|
||||
extern DBGDBGEXITSIGNAL _dbg_dbgexitsignal;
|
||||
extern DBGVALFROMSTRING _dbg_valfromstring;
|
||||
extern DBGISDEBUGGING _dbg_isdebugging;
|
||||
extern DBGISJUMPGOINGTOEXECUTE _dbg_isjumpgoingtoexecute;
|
||||
extern DBGADDRINFOGET _dbg_addrinfoget;
|
||||
extern DBGADDRINFOSET _dbg_addrinfoset;
|
||||
extern DBGBPGETTYPEAT _dbg_bpgettypeat;
|
||||
extern DBGGETREGDUMP _dbg_getregdump;
|
||||
extern DBGVALTOSTRING _dbg_valtostring;
|
||||
extern DBGMEMISVALIDREADPTR _dbg_memisvalidreadptr;
|
||||
extern DBGGETBPLIST _dbg_getbplist;
|
||||
extern DBGDBGCMDEXECDIRECT _dbg_dbgcmddirectexec;
|
||||
extern DBGGETBRANCHDESTINATION _dbg_getbranchdestination;
|
||||
extern DBGSENDMESSAGE _dbg_sendmessage;
|
||||
|
||||
#endif // _GLOBAL_H
|
||||
#ifndef _GLOBAL_H
|
||||
#define _GLOBAL_H
|
||||
|
||||
#include <windows.h>
|
||||
#include "bridgemain.h"
|
||||
|
||||
//GUI typedefs
|
||||
typedef int (*GUIGUIINIT)(int, char**);
|
||||
typedef void* (*GUISENDMESSAGE)(GUIMSG type, void* param1, void* param2);
|
||||
typedef void (*GUISENDMESSAGEASYNC)(GUIMSG type, void* param1, void* param2);
|
||||
|
||||
//GUI functions
|
||||
extern GUIGUIINIT _gui_guiinit;
|
||||
extern GUISENDMESSAGE _gui_sendmessage;
|
||||
extern GUISENDMESSAGEASYNC _gui_sendmessageasync;
|
||||
|
||||
//DBG typedefs
|
||||
typedef const char* (*DBGDBGINIT)();
|
||||
typedef duint (*DBGMEMFINDBASEADDR)(duint addr, duint* size);
|
||||
typedef bool (*DBGMEMREAD)(duint addr, unsigned char* dest, duint size, duint* read);
|
||||
typedef bool (*DBGMEMWRITE)(duint addr, const unsigned char* src, duint size, duint* written);
|
||||
typedef bool (*DBGDBGCMDEXEC)(const char* cmd);
|
||||
typedef bool (*DBGMEMMAP)(MEMMAP* memmap);
|
||||
typedef void (*DBGDBGEXITSIGNAL)();
|
||||
typedef bool (*DBGVALFROMSTRING)(const char* string, duint* value);
|
||||
typedef bool (*DBGISDEBUGGING)();
|
||||
typedef bool (*DBGISJUMPGOINGTOEXECUTE)(duint addr);
|
||||
typedef bool (*DBGADDRINFOGET)(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo);
|
||||
typedef bool (*DBGADDRINFOSET)(duint addr, ADDRINFO* addrinfo);
|
||||
typedef BPXTYPE (*DBGBPGETTYPEAT)(duint addr);
|
||||
typedef bool (*DBGGETREGDUMP)(REGDUMP* regdump);
|
||||
typedef bool (*DBGVALTOSTRING)(const char* string, duint value);
|
||||
typedef bool (*DBGMEMISVALIDREADPTR)(duint addr);
|
||||
typedef int (*DBGGETBPLIST)(BPXTYPE type, BPMAP* bplist);
|
||||
typedef bool (*DBGDBGCMDEXECDIRECT)(const char* cmd);
|
||||
typedef duint (*DBGGETBRANCHDESTINATION)(duint addr);
|
||||
typedef duint (*DBGSENDMESSAGE)(DBGMSG type, void* param1, void* param2);
|
||||
|
||||
//DBG functions
|
||||
extern DBGDBGINIT _dbg_dbginit;
|
||||
extern DBGMEMFINDBASEADDR _dbg_memfindbaseaddr;
|
||||
extern DBGMEMREAD _dbg_memread;
|
||||
extern DBGMEMWRITE _dbg_memwrite;
|
||||
extern DBGDBGCMDEXEC _dbg_dbgcmdexec;
|
||||
extern DBGMEMMAP _dbg_memmap;
|
||||
extern DBGDBGEXITSIGNAL _dbg_dbgexitsignal;
|
||||
extern DBGVALFROMSTRING _dbg_valfromstring;
|
||||
extern DBGISDEBUGGING _dbg_isdebugging;
|
||||
extern DBGISJUMPGOINGTOEXECUTE _dbg_isjumpgoingtoexecute;
|
||||
extern DBGADDRINFOGET _dbg_addrinfoget;
|
||||
extern DBGADDRINFOSET _dbg_addrinfoset;
|
||||
extern DBGBPGETTYPEAT _dbg_bpgettypeat;
|
||||
extern DBGGETREGDUMP _dbg_getregdump;
|
||||
extern DBGVALTOSTRING _dbg_valtostring;
|
||||
extern DBGMEMISVALIDREADPTR _dbg_memisvalidreadptr;
|
||||
extern DBGGETBPLIST _dbg_getbplist;
|
||||
extern DBGDBGCMDEXECDIRECT _dbg_dbgcmddirectexec;
|
||||
extern DBGGETBRANCHDESTINATION _dbg_getbranchdestination;
|
||||
extern DBGSENDMESSAGE _dbg_sendmessage;
|
||||
|
||||
#endif // _GLOBAL_H
|
||||
|
|
@ -1,129 +1,129 @@
|
|||
#ifndef _LIST_H
|
||||
#define _LIST_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int count; //Number of element in the list.
|
||||
size_t size; //Size of list in bytes (used for type checking).
|
||||
void* data; //Pointer to the list contents. Must be deleted by the caller using BridgeFree (or List::Free).
|
||||
} ListInfo;
|
||||
|
||||
#define ListOf(Type) ListInfo*
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
\brief A list object. This object is NOT thread safe.
|
||||
\tparam Type List contents type.
|
||||
*/
|
||||
template<typename Type>
|
||||
class List
|
||||
{
|
||||
public:
|
||||
/**
|
||||
\brief List constructor.
|
||||
\param _freeData (Optional) the free function.
|
||||
*/
|
||||
explicit inline List()
|
||||
{
|
||||
memset(&_listInfo, 0, sizeof(_listInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief List destructor.
|
||||
*/
|
||||
inline ~List()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets the list data.
|
||||
\return Returns ListInfo->data. Can be null if the list was never initialized. Will be destroyed once this object goes out of scope!
|
||||
*/
|
||||
inline Type* data() const
|
||||
{
|
||||
return reinterpret_cast<Type*>(_listInfo.data);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets the number of elements in the list. This will crash the program if the data is not consistent with the specified template argument.
|
||||
\return The number of elements in the list.
|
||||
*/
|
||||
inline int count() const
|
||||
{
|
||||
if(_listInfo.size != _listInfo.count * sizeof(Type)) //make sure the user is using the correct type.
|
||||
__debugbreak();
|
||||
return _listInfo.count;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Cleans up the list, freeing the list data when it is not null.
|
||||
*/
|
||||
inline void cleanup()
|
||||
{
|
||||
if(_listInfo.data)
|
||||
{
|
||||
BridgeFree(_listInfo.data);
|
||||
_listInfo.data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Reference operator (cleans up the previous list)
|
||||
\return Pointer to the ListInfo.
|
||||
*/
|
||||
inline ListInfo* operator&()
|
||||
{
|
||||
cleanup();
|
||||
return &_listInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Array indexer operator. This will crash if you try to access out-of-bounds.
|
||||
\param index Zero-based index of the item you want to get.
|
||||
\return Reference to a value at that index.
|
||||
*/
|
||||
inline Type & operator[](size_t index) const
|
||||
{
|
||||
if(index >= size_t(count())) //make sure the out-of-bounds access is caught as soon as possible.
|
||||
__debugbreak();
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Copies data to a ListInfo structure..
|
||||
\param [out] listInfo If non-null, information describing the list.
|
||||
\param listData Data to copy in the ListInfo structure.
|
||||
\return true if it succeeds, false if it fails.
|
||||
*/
|
||||
static inline bool CopyData(ListInfo* listInfo, const std::vector<Type> & listData)
|
||||
{
|
||||
if(!listInfo)
|
||||
return false;
|
||||
listInfo->count = int(listData.size());
|
||||
listInfo->size = listInfo->count * sizeof(Type);
|
||||
if(listInfo->count)
|
||||
{
|
||||
listInfo->data = BridgeAlloc(listInfo->size);
|
||||
Type* curItem = reinterpret_cast<Type*>(listInfo->data);
|
||||
for(const auto & item : listData)
|
||||
{
|
||||
*curItem = item;
|
||||
++curItem;
|
||||
}
|
||||
}
|
||||
else
|
||||
listInfo->data = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
ListInfo _listInfo;
|
||||
};
|
||||
|
||||
#endif //__cplusplus
|
||||
|
||||
#ifndef _LIST_H
|
||||
#define _LIST_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int count; //Number of element in the list.
|
||||
size_t size; //Size of list in bytes (used for type checking).
|
||||
void* data; //Pointer to the list contents. Must be deleted by the caller using BridgeFree (or List::Free).
|
||||
} ListInfo;
|
||||
|
||||
#define ListOf(Type) ListInfo*
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
\brief A list object. This object is NOT thread safe.
|
||||
\tparam Type List contents type.
|
||||
*/
|
||||
template<typename Type>
|
||||
class List
|
||||
{
|
||||
public:
|
||||
/**
|
||||
\brief List constructor.
|
||||
\param _freeData (Optional) the free function.
|
||||
*/
|
||||
explicit inline List()
|
||||
{
|
||||
memset(&_listInfo, 0, sizeof(_listInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief List destructor.
|
||||
*/
|
||||
inline ~List()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets the list data.
|
||||
\return Returns ListInfo->data. Can be null if the list was never initialized. Will be destroyed once this object goes out of scope!
|
||||
*/
|
||||
inline Type* data() const
|
||||
{
|
||||
return reinterpret_cast<Type*>(_listInfo.data);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets the number of elements in the list. This will crash the program if the data is not consistent with the specified template argument.
|
||||
\return The number of elements in the list.
|
||||
*/
|
||||
inline int count() const
|
||||
{
|
||||
if(_listInfo.size != _listInfo.count * sizeof(Type)) //make sure the user is using the correct type.
|
||||
__debugbreak();
|
||||
return _listInfo.count;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Cleans up the list, freeing the list data when it is not null.
|
||||
*/
|
||||
inline void cleanup()
|
||||
{
|
||||
if(_listInfo.data)
|
||||
{
|
||||
BridgeFree(_listInfo.data);
|
||||
_listInfo.data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Reference operator (cleans up the previous list)
|
||||
\return Pointer to the ListInfo.
|
||||
*/
|
||||
inline ListInfo* operator&()
|
||||
{
|
||||
cleanup();
|
||||
return &_listInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Array indexer operator. This will crash if you try to access out-of-bounds.
|
||||
\param index Zero-based index of the item you want to get.
|
||||
\return Reference to a value at that index.
|
||||
*/
|
||||
inline Type & operator[](size_t index) const
|
||||
{
|
||||
if(index >= size_t(count())) //make sure the out-of-bounds access is caught as soon as possible.
|
||||
__debugbreak();
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Copies data to a ListInfo structure..
|
||||
\param [out] listInfo If non-null, information describing the list.
|
||||
\param listData Data to copy in the ListInfo structure.
|
||||
\return true if it succeeds, false if it fails.
|
||||
*/
|
||||
static inline bool CopyData(ListInfo* listInfo, const std::vector<Type> & listData)
|
||||
{
|
||||
if(!listInfo)
|
||||
return false;
|
||||
listInfo->count = int(listData.size());
|
||||
listInfo->size = listInfo->count * sizeof(Type);
|
||||
if(listInfo->count)
|
||||
{
|
||||
listInfo->data = BridgeAlloc(listInfo->size);
|
||||
Type* curItem = reinterpret_cast<Type*>(listInfo->data);
|
||||
for(const auto & item : listData)
|
||||
{
|
||||
*curItem = item;
|
||||
++curItem;
|
||||
}
|
||||
}
|
||||
else
|
||||
listInfo->data = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
ListInfo _listInfo;
|
||||
};
|
||||
|
||||
#endif //__cplusplus
|
||||
|
||||
#endif //_LIST_H
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,157 +1,157 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="bridgemain.cpp" />
|
||||
<ClCompile Include="_global.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="bridgemain.h" />
|
||||
<ClInclude Include="bridgelist.h" />
|
||||
<ClInclude Include="Utf8Ini.h" />
|
||||
<ClInclude Include="_global.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{944D9923-CB1A-6F6C-BCBC-9E00A71954C1}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\x32\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>x32bridge</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\x32\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>x32bridge</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\x64\</OutDir>
|
||||
<TargetName>x64bridge</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\x64\</OutDir>
|
||||
<TargetName>x64bridge</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="bridgemain.cpp" />
|
||||
<ClCompile Include="_global.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="bridgemain.h" />
|
||||
<ClInclude Include="bridgelist.h" />
|
||||
<ClInclude Include="Utf8Ini.h" />
|
||||
<ClInclude Include="_global.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{944D9923-CB1A-6F6C-BCBC-9E00A71954C1}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>..\..\bin\x32\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>x32bridge</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>..\..\bin\x32\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>x32bridge</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>..\..\bin\x64\</OutDir>
|
||||
<TargetName>x64bridge</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>..\..\bin\x64\</OutDir>
|
||||
<TargetName>x64bridge</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
|
|
@ -1,35 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="_global.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bridgemain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="_global.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="bridgemain.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Utf8Ini.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="bridgelist.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="_global.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bridgemain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="_global.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="bridgemain.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Utf8Ini.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="bridgelist.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
|
@ -1,22 +1,22 @@
|
|||
#ifndef _DEVICENAMERESOLVER_H
|
||||
#define _DEVICENAMERESOLVER_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
__declspec(dllexport) bool DevicePathToPathW(const wchar_t* szDevicePath, wchar_t* szPath, size_t nSize);
|
||||
__declspec(dllexport) bool DevicePathToPathA(const char* szDevicePath, char* szPath, size_t nSize);
|
||||
__declspec(dllexport) bool DevicePathFromFileHandleW(HANDLE hFile, wchar_t* szDevicePath, size_t nSize);
|
||||
__declspec(dllexport) bool DevicePathFromFileHandleA(HANDLE hFile, char* szDevicePath, size_t nSize);
|
||||
__declspec(dllexport) bool PathFromFileHandleW(HANDLE hFile, wchar_t* szPath, size_t nSize);
|
||||
__declspec(dllexport) bool PathFromFileHandleA(HANDLE hFile, char* szPath, size_t nSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _DEVICENAMERESOLVER_H
|
||||
#ifndef _DEVICENAMERESOLVER_H
|
||||
#define _DEVICENAMERESOLVER_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
__declspec(dllexport) bool DevicePathToPathW(const wchar_t* szDevicePath, wchar_t* szPath, size_t nSize);
|
||||
__declspec(dllexport) bool DevicePathToPathA(const char* szDevicePath, char* szPath, size_t nSize);
|
||||
__declspec(dllexport) bool DevicePathFromFileHandleW(HANDLE hFile, wchar_t* szDevicePath, size_t nSize);
|
||||
__declspec(dllexport) bool DevicePathFromFileHandleA(HANDLE hFile, char* szDevicePath, size_t nSize);
|
||||
__declspec(dllexport) bool PathFromFileHandleW(HANDLE hFile, wchar_t* szPath, size_t nSize);
|
||||
__declspec(dllexport) bool PathFromFileHandleA(HANDLE hFile, char* szPath, size_t nSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _DEVICENAMERESOLVER_H
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,53 +1,53 @@
|
|||
#ifndef _XEDPARSE_H
|
||||
#define _XEDPARSE_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
//XEDParse defines
|
||||
#ifdef XEDPARSE_BUILD
|
||||
#define XEDPARSE_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define XEDPARSE_EXPORT __declspec(dllimport)
|
||||
#endif //XEDPARSE_BUILD
|
||||
|
||||
#define XEDPARSE_CALL //calling convention
|
||||
|
||||
#define XEDPARSE_MAXBUFSIZE 256
|
||||
#define XEDPARSE_MAXASMSIZE 16
|
||||
|
||||
//typedefs
|
||||
typedef bool (XEDPARSE_CALL* CBXEDPARSE_UNKNOWN)(const char* text, ULONGLONG* value);
|
||||
|
||||
//XEDParse enums
|
||||
enum XEDPARSE_STATUS
|
||||
{
|
||||
XEDPARSE_ERROR = 0,
|
||||
XEDPARSE_OK = 1
|
||||
};
|
||||
|
||||
//XEDParse structs
|
||||
#pragma pack(push,8)
|
||||
struct XEDPARSE
|
||||
{
|
||||
bool x64; // use 64-bit instructions
|
||||
ULONGLONG cip; //instruction pointer (for relative addressing)
|
||||
unsigned int dest_size; //destination size (returned by XEDParse)
|
||||
CBXEDPARSE_UNKNOWN cbUnknown; //unknown operand callback
|
||||
unsigned char dest[XEDPARSE_MAXASMSIZE]; //destination buffer
|
||||
char instr[XEDPARSE_MAXBUFSIZE]; //instruction text
|
||||
char error[XEDPARSE_MAXBUFSIZE]; //error text (in case of an error)
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
XEDPARSE_EXPORT XEDPARSE_STATUS XEDPARSE_CALL XEDParseAssemble(XEDPARSE* XEDParse);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _XEDPARSE_H
|
||||
#ifndef _XEDPARSE_H
|
||||
#define _XEDPARSE_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
//XEDParse defines
|
||||
#ifdef XEDPARSE_BUILD
|
||||
#define XEDPARSE_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define XEDPARSE_EXPORT __declspec(dllimport)
|
||||
#endif //XEDPARSE_BUILD
|
||||
|
||||
#define XEDPARSE_CALL //calling convention
|
||||
|
||||
#define XEDPARSE_MAXBUFSIZE 256
|
||||
#define XEDPARSE_MAXASMSIZE 16
|
||||
|
||||
//typedefs
|
||||
typedef bool (XEDPARSE_CALL* CBXEDPARSE_UNKNOWN)(const char* text, ULONGLONG* value);
|
||||
|
||||
//XEDParse enums
|
||||
enum XEDPARSE_STATUS
|
||||
{
|
||||
XEDPARSE_ERROR = 0,
|
||||
XEDPARSE_OK = 1
|
||||
};
|
||||
|
||||
//XEDParse structs
|
||||
#pragma pack(push,8)
|
||||
struct XEDPARSE
|
||||
{
|
||||
bool x64; // use 64-bit instructions
|
||||
ULONGLONG cip; //instruction pointer (for relative addressing)
|
||||
unsigned int dest_size; //destination size (returned by XEDParse)
|
||||
CBXEDPARSE_UNKNOWN cbUnknown; //unknown operand callback
|
||||
unsigned char dest[XEDPARSE_MAXASMSIZE]; //destination buffer
|
||||
char instr[XEDPARSE_MAXBUFSIZE]; //instruction text
|
||||
char error[XEDPARSE_MAXBUFSIZE]; //error text (in case of an error)
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
XEDPARSE_EXPORT XEDPARSE_STATUS XEDPARSE_CALL XEDParseAssemble(XEDPARSE* XEDParse);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _XEDPARSE_H
|
||||
|
|
@ -1,238 +1,238 @@
|
|||
/**
|
||||
@file _dbgfunctions.cpp
|
||||
|
||||
@brief Implements the dbgfunctions class.
|
||||
*/
|
||||
|
||||
#include "_global.h"
|
||||
#include "_dbgfunctions.h"
|
||||
#include "assemble.h"
|
||||
#include "debugger.h"
|
||||
#include "patches.h"
|
||||
#include "memory.h"
|
||||
#include "disasm_fast.h"
|
||||
#include "stackinfo.h"
|
||||
#include "symbolinfo.h"
|
||||
#include "module.h"
|
||||
|
||||
static DBGFUNCTIONS _dbgfunctions;
|
||||
|
||||
const DBGFUNCTIONS* dbgfunctionsget()
|
||||
{
|
||||
return &_dbgfunctions;
|
||||
}
|
||||
|
||||
static bool _assembleatex(duint addr, const char* instruction, char* error, bool fillnop)
|
||||
{
|
||||
return assembleat(addr, instruction, nullptr, error, fillnop);
|
||||
}
|
||||
|
||||
static bool _sectionfromaddr(duint addr, char* section)
|
||||
{
|
||||
HMODULE hMod = (HMODULE)ModBaseFromAddr(addr);
|
||||
if(!hMod)
|
||||
return false;
|
||||
wchar_t curModPath[MAX_PATH] = L"";
|
||||
if(!GetModuleFileNameExW(fdProcessInfo->hProcess, hMod, curModPath, MAX_PATH))
|
||||
return false;
|
||||
HANDLE FileHandle;
|
||||
DWORD LoadedSize;
|
||||
HANDLE FileMap;
|
||||
ULONG_PTR FileMapVA;
|
||||
if(StaticFileLoadW(curModPath, UE_ACCESS_READ, false, &FileHandle, &LoadedSize, &FileMap, &FileMapVA))
|
||||
{
|
||||
uint rva = addr - (uint)hMod;
|
||||
int sectionNumber = GetPE32SectionNumberFromVA(FileMapVA, GetPE32DataFromMappedFile(FileMapVA, 0, UE_IMAGEBASE) + rva);
|
||||
if(sectionNumber >= 0)
|
||||
{
|
||||
const char* name = (const char*)GetPE32DataFromMappedFile(FileMapVA, sectionNumber, UE_SECTIONNAME);
|
||||
if(section)
|
||||
strcpy_s(section, MAX_SECTION_SIZE, name); //maxi
|
||||
StaticFileUnloadW(curModPath, false, FileHandle, LoadedSize, FileMap, FileMapVA);
|
||||
return true;
|
||||
}
|
||||
StaticFileUnloadW(curModPath, false, FileHandle, LoadedSize, FileMap, FileMapVA);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool _patchget(duint addr)
|
||||
{
|
||||
return PatchGet(addr, nullptr);
|
||||
}
|
||||
|
||||
static bool _patchinrange(duint start, duint end)
|
||||
{
|
||||
if(start > end)
|
||||
std::swap(start, end);
|
||||
|
||||
for(duint i = start; i <= end; i++)
|
||||
{
|
||||
if(_patchget(i))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool _mempatch(duint va, const unsigned char* src, duint size)
|
||||
{
|
||||
return MemPatch(va, src, size, nullptr);
|
||||
}
|
||||
|
||||
static void _patchrestorerange(duint start, duint end)
|
||||
{
|
||||
if(start > end)
|
||||
std::swap(start, end);
|
||||
|
||||
for(duint i = start; i <= end; i++)
|
||||
PatchDelete(i, true);
|
||||
|
||||
GuiUpdatePatches();
|
||||
}
|
||||
|
||||
static bool _patchrestore(duint addr)
|
||||
{
|
||||
return PatchDelete(addr, true);
|
||||
}
|
||||
|
||||
static void _getcallstack(DBGCALLSTACK* callstack)
|
||||
{
|
||||
stackgetcallstack(GetContextDataEx(hActiveThread, UE_CSP), (CALLSTACK*)callstack);
|
||||
}
|
||||
|
||||
static bool _getjitauto(bool* jit_auto)
|
||||
{
|
||||
return dbggetjitauto(jit_auto, notfound, NULL, NULL);
|
||||
}
|
||||
|
||||
static bool _getcmdline(char* cmd_line, size_t* cbsize)
|
||||
{
|
||||
if(!cmd_line && !cbsize)
|
||||
return false;
|
||||
char* cmdline;
|
||||
if(!dbggetcmdline(&cmdline, NULL))
|
||||
return false;
|
||||
if(!cmd_line && cbsize)
|
||||
*cbsize = strlen(cmdline) + sizeof(char);
|
||||
else if(cmd_line)
|
||||
strcpy(cmd_line, cmdline);
|
||||
efree(cmdline, "_getcmdline:cmdline");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _setcmdline(const char* cmd_line)
|
||||
{
|
||||
return dbgsetcmdline(cmd_line, nullptr);
|
||||
}
|
||||
|
||||
static bool _getjit(char* jit, bool jit64)
|
||||
{
|
||||
arch dummy;
|
||||
char jit_tmp[JIT_ENTRY_MAX_SIZE] = "";
|
||||
if(jit != NULL)
|
||||
{
|
||||
if(!dbggetjit(jit_tmp, jit64 ? x64 : x32, &dummy, NULL))
|
||||
return false;
|
||||
strcpy_s(jit, MAX_SETTING_SIZE, jit_tmp);
|
||||
}
|
||||
else // if jit input == NULL: it returns false if there are not an OLD JIT STORED.
|
||||
{
|
||||
char oldjit[MAX_SETTING_SIZE] = "";
|
||||
if(!BridgeSettingGet("JIT", "Old", (char*) & oldjit))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _getprocesslist(DBGPROCESSINFO** entries, int* count)
|
||||
{
|
||||
std::vector<PROCESSENTRY32> list;
|
||||
if(!dbglistprocesses(&list))
|
||||
return false;
|
||||
*count = (int)list.size();
|
||||
if(!*count)
|
||||
return false;
|
||||
*entries = (DBGPROCESSINFO*)BridgeAlloc(*count * sizeof(DBGPROCESSINFO));
|
||||
for(int i = 0; i < *count; i++)
|
||||
{
|
||||
(*entries)[*count - i - 1].dwProcessId = list.at(i).th32ProcessID;
|
||||
strcpy_s((*entries)[*count - i - 1].szExeFile, list.at(i).szExeFile);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _memupdatemap()
|
||||
{
|
||||
dbggetprivateusage(fdProcessInfo->hProcess, true);
|
||||
MemUpdateMap();
|
||||
GuiUpdateMemoryView();
|
||||
}
|
||||
|
||||
static duint _getaddrfromline(const char* szSourceFile, int line)
|
||||
{
|
||||
LONG displacement = 0;
|
||||
IMAGEHLP_LINE64 lineData;
|
||||
memset(&lineData, 0, sizeof(lineData));
|
||||
lineData.SizeOfStruct = sizeof(lineData);
|
||||
if(!SymGetLineFromName64(fdProcessInfo->hProcess, NULL, szSourceFile, line, &displacement, &lineData))
|
||||
return 0;
|
||||
return (duint)lineData.Address;
|
||||
}
|
||||
|
||||
static bool _getsourcefromaddr(duint addr, char* szSourceFile, int* line)
|
||||
{
|
||||
char sourceFile[MAX_STRING_SIZE] = "";
|
||||
if(!SymGetSourceLine(addr, sourceFile, line))
|
||||
return false;
|
||||
if(!FileExists(sourceFile))
|
||||
return false;
|
||||
if(szSourceFile)
|
||||
strcpy_s(szSourceFile, MAX_STRING_SIZE, sourceFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _valfromstring(const char* string, duint* value)
|
||||
{
|
||||
return valfromstring(string, value);
|
||||
}
|
||||
|
||||
void dbgfunctionsinit()
|
||||
{
|
||||
_dbgfunctions.AssembleAtEx = _assembleatex;
|
||||
_dbgfunctions.SectionFromAddr = _sectionfromaddr;
|
||||
_dbgfunctions.ModNameFromAddr = ModNameFromAddr;
|
||||
_dbgfunctions.ModBaseFromAddr = ModBaseFromAddr;
|
||||
_dbgfunctions.ModBaseFromName = ModBaseFromName;
|
||||
_dbgfunctions.ModSizeFromAddr = ModSizeFromAddr;
|
||||
_dbgfunctions.Assemble = assemble;
|
||||
_dbgfunctions.PatchGet = _patchget;
|
||||
_dbgfunctions.PatchInRange = _patchinrange;
|
||||
_dbgfunctions.MemPatch = _mempatch;
|
||||
_dbgfunctions.PatchRestoreRange = _patchrestorerange;
|
||||
_dbgfunctions.PatchEnum = (PATCHENUM)PatchEnum;
|
||||
_dbgfunctions.PatchRestore = _patchrestore;
|
||||
_dbgfunctions.PatchFile = (PATCHFILE)PatchFile;
|
||||
_dbgfunctions.ModPathFromAddr = ModPathFromAddr;
|
||||
_dbgfunctions.ModPathFromName = ModPathFromName;
|
||||
_dbgfunctions.DisasmFast = disasmfast;
|
||||
_dbgfunctions.MemUpdateMap = _memupdatemap;
|
||||
_dbgfunctions.GetCallStack = _getcallstack;
|
||||
_dbgfunctions.SymbolDownloadAllSymbols = SymDownloadAllSymbols;
|
||||
_dbgfunctions.GetJit = _getjit;
|
||||
_dbgfunctions.GetJitAuto = _getjitauto;
|
||||
_dbgfunctions.GetDefJit = dbggetdefjit;
|
||||
_dbgfunctions.GetProcessList = _getprocesslist;
|
||||
_dbgfunctions.GetPageRights = MemGetPageRights;
|
||||
_dbgfunctions.SetPageRights = MemSetPageRights;
|
||||
_dbgfunctions.PageRightsToString = MemPageRightsToString;
|
||||
_dbgfunctions.IsProcessElevated = IsProcessElevated;
|
||||
_dbgfunctions.GetCmdline = _getcmdline;
|
||||
_dbgfunctions.SetCmdline = _setcmdline;
|
||||
_dbgfunctions.FileOffsetToVa = valfileoffsettova;
|
||||
_dbgfunctions.VaToFileOffset = valvatofileoffset;
|
||||
_dbgfunctions.GetAddrFromLine = _getaddrfromline;
|
||||
_dbgfunctions.GetSourceFromAddr = _getsourcefromaddr;
|
||||
_dbgfunctions.ValFromString = _valfromstring;
|
||||
}
|
||||
/**
|
||||
@file _dbgfunctions.cpp
|
||||
|
||||
@brief Implements the dbgfunctions class.
|
||||
*/
|
||||
|
||||
#include "_global.h"
|
||||
#include "_dbgfunctions.h"
|
||||
#include "assemble.h"
|
||||
#include "debugger.h"
|
||||
#include "patches.h"
|
||||
#include "memory.h"
|
||||
#include "disasm_fast.h"
|
||||
#include "stackinfo.h"
|
||||
#include "symbolinfo.h"
|
||||
#include "module.h"
|
||||
|
||||
static DBGFUNCTIONS _dbgfunctions;
|
||||
|
||||
const DBGFUNCTIONS* dbgfunctionsget()
|
||||
{
|
||||
return &_dbgfunctions;
|
||||
}
|
||||
|
||||
static bool _assembleatex(duint addr, const char* instruction, char* error, bool fillnop)
|
||||
{
|
||||
return assembleat(addr, instruction, nullptr, error, fillnop);
|
||||
}
|
||||
|
||||
static bool _sectionfromaddr(duint addr, char* section)
|
||||
{
|
||||
HMODULE hMod = (HMODULE)ModBaseFromAddr(addr);
|
||||
if(!hMod)
|
||||
return false;
|
||||
wchar_t curModPath[MAX_PATH] = L"";
|
||||
if(!GetModuleFileNameExW(fdProcessInfo->hProcess, hMod, curModPath, MAX_PATH))
|
||||
return false;
|
||||
HANDLE FileHandle;
|
||||
DWORD LoadedSize;
|
||||
HANDLE FileMap;
|
||||
ULONG_PTR FileMapVA;
|
||||
if(StaticFileLoadW(curModPath, UE_ACCESS_READ, false, &FileHandle, &LoadedSize, &FileMap, &FileMapVA))
|
||||
{
|
||||
uint rva = addr - (uint)hMod;
|
||||
int sectionNumber = GetPE32SectionNumberFromVA(FileMapVA, GetPE32DataFromMappedFile(FileMapVA, 0, UE_IMAGEBASE) + rva);
|
||||
if(sectionNumber >= 0)
|
||||
{
|
||||
const char* name = (const char*)GetPE32DataFromMappedFile(FileMapVA, sectionNumber, UE_SECTIONNAME);
|
||||
if(section)
|
||||
strcpy_s(section, MAX_SECTION_SIZE, name); //maxi
|
||||
StaticFileUnloadW(curModPath, false, FileHandle, LoadedSize, FileMap, FileMapVA);
|
||||
return true;
|
||||
}
|
||||
StaticFileUnloadW(curModPath, false, FileHandle, LoadedSize, FileMap, FileMapVA);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool _patchget(duint addr)
|
||||
{
|
||||
return PatchGet(addr, nullptr);
|
||||
}
|
||||
|
||||
static bool _patchinrange(duint start, duint end)
|
||||
{
|
||||
if(start > end)
|
||||
std::swap(start, end);
|
||||
|
||||
for(duint i = start; i <= end; i++)
|
||||
{
|
||||
if(_patchget(i))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool _mempatch(duint va, const unsigned char* src, duint size)
|
||||
{
|
||||
return MemPatch(va, src, size, nullptr);
|
||||
}
|
||||
|
||||
static void _patchrestorerange(duint start, duint end)
|
||||
{
|
||||
if(start > end)
|
||||
std::swap(start, end);
|
||||
|
||||
for(duint i = start; i <= end; i++)
|
||||
PatchDelete(i, true);
|
||||
|
||||
GuiUpdatePatches();
|
||||
}
|
||||
|
||||
static bool _patchrestore(duint addr)
|
||||
{
|
||||
return PatchDelete(addr, true);
|
||||
}
|
||||
|
||||
static void _getcallstack(DBGCALLSTACK* callstack)
|
||||
{
|
||||
stackgetcallstack(GetContextDataEx(hActiveThread, UE_CSP), (CALLSTACK*)callstack);
|
||||
}
|
||||
|
||||
static bool _getjitauto(bool* jit_auto)
|
||||
{
|
||||
return dbggetjitauto(jit_auto, notfound, NULL, NULL);
|
||||
}
|
||||
|
||||
static bool _getcmdline(char* cmd_line, size_t* cbsize)
|
||||
{
|
||||
if(!cmd_line && !cbsize)
|
||||
return false;
|
||||
char* cmdline;
|
||||
if(!dbggetcmdline(&cmdline, NULL))
|
||||
return false;
|
||||
if(!cmd_line && cbsize)
|
||||
*cbsize = strlen(cmdline) + sizeof(char);
|
||||
else if(cmd_line)
|
||||
strcpy(cmd_line, cmdline);
|
||||
efree(cmdline, "_getcmdline:cmdline");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _setcmdline(const char* cmd_line)
|
||||
{
|
||||
return dbgsetcmdline(cmd_line, nullptr);
|
||||
}
|
||||
|
||||
static bool _getjit(char* jit, bool jit64)
|
||||
{
|
||||
arch dummy;
|
||||
char jit_tmp[JIT_ENTRY_MAX_SIZE] = "";
|
||||
if(jit != NULL)
|
||||
{
|
||||
if(!dbggetjit(jit_tmp, jit64 ? x64 : x32, &dummy, NULL))
|
||||
return false;
|
||||
strcpy_s(jit, MAX_SETTING_SIZE, jit_tmp);
|
||||
}
|
||||
else // if jit input == NULL: it returns false if there are not an OLD JIT STORED.
|
||||
{
|
||||
char oldjit[MAX_SETTING_SIZE] = "";
|
||||
if(!BridgeSettingGet("JIT", "Old", (char*) & oldjit))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _getprocesslist(DBGPROCESSINFO** entries, int* count)
|
||||
{
|
||||
std::vector<PROCESSENTRY32> list;
|
||||
if(!dbglistprocesses(&list))
|
||||
return false;
|
||||
*count = (int)list.size();
|
||||
if(!*count)
|
||||
return false;
|
||||
*entries = (DBGPROCESSINFO*)BridgeAlloc(*count * sizeof(DBGPROCESSINFO));
|
||||
for(int i = 0; i < *count; i++)
|
||||
{
|
||||
(*entries)[*count - i - 1].dwProcessId = list.at(i).th32ProcessID;
|
||||
strcpy_s((*entries)[*count - i - 1].szExeFile, list.at(i).szExeFile);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _memupdatemap()
|
||||
{
|
||||
dbggetprivateusage(fdProcessInfo->hProcess, true);
|
||||
MemUpdateMap();
|
||||
GuiUpdateMemoryView();
|
||||
}
|
||||
|
||||
static duint _getaddrfromline(const char* szSourceFile, int line)
|
||||
{
|
||||
LONG displacement = 0;
|
||||
IMAGEHLP_LINE64 lineData;
|
||||
memset(&lineData, 0, sizeof(lineData));
|
||||
lineData.SizeOfStruct = sizeof(lineData);
|
||||
if(!SymGetLineFromName64(fdProcessInfo->hProcess, NULL, szSourceFile, line, &displacement, &lineData))
|
||||
return 0;
|
||||
return (duint)lineData.Address;
|
||||
}
|
||||
|
||||
static bool _getsourcefromaddr(duint addr, char* szSourceFile, int* line)
|
||||
{
|
||||
char sourceFile[MAX_STRING_SIZE] = "";
|
||||
if(!SymGetSourceLine(addr, sourceFile, line))
|
||||
return false;
|
||||
if(!FileExists(sourceFile))
|
||||
return false;
|
||||
if(szSourceFile)
|
||||
strcpy_s(szSourceFile, MAX_STRING_SIZE, sourceFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _valfromstring(const char* string, duint* value)
|
||||
{
|
||||
return valfromstring(string, value);
|
||||
}
|
||||
|
||||
void dbgfunctionsinit()
|
||||
{
|
||||
_dbgfunctions.AssembleAtEx = _assembleatex;
|
||||
_dbgfunctions.SectionFromAddr = _sectionfromaddr;
|
||||
_dbgfunctions.ModNameFromAddr = ModNameFromAddr;
|
||||
_dbgfunctions.ModBaseFromAddr = ModBaseFromAddr;
|
||||
_dbgfunctions.ModBaseFromName = ModBaseFromName;
|
||||
_dbgfunctions.ModSizeFromAddr = ModSizeFromAddr;
|
||||
_dbgfunctions.Assemble = assemble;
|
||||
_dbgfunctions.PatchGet = _patchget;
|
||||
_dbgfunctions.PatchInRange = _patchinrange;
|
||||
_dbgfunctions.MemPatch = _mempatch;
|
||||
_dbgfunctions.PatchRestoreRange = _patchrestorerange;
|
||||
_dbgfunctions.PatchEnum = (PATCHENUM)PatchEnum;
|
||||
_dbgfunctions.PatchRestore = _patchrestore;
|
||||
_dbgfunctions.PatchFile = (PATCHFILE)PatchFile;
|
||||
_dbgfunctions.ModPathFromAddr = ModPathFromAddr;
|
||||
_dbgfunctions.ModPathFromName = ModPathFromName;
|
||||
_dbgfunctions.DisasmFast = disasmfast;
|
||||
_dbgfunctions.MemUpdateMap = _memupdatemap;
|
||||
_dbgfunctions.GetCallStack = _getcallstack;
|
||||
_dbgfunctions.SymbolDownloadAllSymbols = SymDownloadAllSymbols;
|
||||
_dbgfunctions.GetJit = _getjit;
|
||||
_dbgfunctions.GetJitAuto = _getjitauto;
|
||||
_dbgfunctions.GetDefJit = dbggetdefjit;
|
||||
_dbgfunctions.GetProcessList = _getprocesslist;
|
||||
_dbgfunctions.GetPageRights = MemGetPageRights;
|
||||
_dbgfunctions.SetPageRights = MemSetPageRights;
|
||||
_dbgfunctions.PageRightsToString = MemPageRightsToString;
|
||||
_dbgfunctions.IsProcessElevated = IsProcessElevated;
|
||||
_dbgfunctions.GetCmdline = _getcmdline;
|
||||
_dbgfunctions.SetCmdline = _setcmdline;
|
||||
_dbgfunctions.FileOffsetToVa = valfileoffsettova;
|
||||
_dbgfunctions.VaToFileOffset = valvatofileoffset;
|
||||
_dbgfunctions.GetAddrFromLine = _getaddrfromline;
|
||||
_dbgfunctions.GetSourceFromAddr = _getsourcefromaddr;
|
||||
_dbgfunctions.ValFromString = _valfromstring;
|
||||
}
|
||||
|
|
@ -1,118 +1,118 @@
|
|||
#ifndef _DBGFUNCTIONS_H
|
||||
#define _DBGFUNCTIONS_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char mod[MAX_MODULE_SIZE];
|
||||
duint addr;
|
||||
unsigned char oldbyte;
|
||||
unsigned char newbyte;
|
||||
} DBGPATCHINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
duint addr;
|
||||
duint from;
|
||||
duint to;
|
||||
char comment[MAX_COMMENT_SIZE];
|
||||
} DBGCALLSTACKENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int total;
|
||||
DBGCALLSTACKENTRY* entries;
|
||||
} DBGCALLSTACK;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwProcessId;
|
||||
char szExeFile[MAX_PATH];
|
||||
} DBGPROCESSINFO;
|
||||
|
||||
typedef bool (*ASSEMBLEATEX)(duint addr, const char* instruction, char* error, bool fillnop);
|
||||
typedef bool (*SECTIONFROMADDR)(duint addr, char* section);
|
||||
typedef bool (*MODNAMEFROMADDR)(duint addr, char* modname, bool extension);
|
||||
typedef duint (*MODBASEFROMADDR)(duint addr);
|
||||
typedef duint (*MODBASEFROMNAME)(const char* modname);
|
||||
typedef duint (*MODSIZEFROMADDR)(duint addr);
|
||||
typedef bool (*ASSEMBLE)(duint addr, unsigned char* dest, int* size, const char* instruction, char* error);
|
||||
typedef bool (*PATCHGET)(duint addr);
|
||||
typedef bool (*PATCHINRANGE)(duint start, duint end);
|
||||
typedef bool (*MEMPATCH)(duint va, const unsigned char* src, duint size);
|
||||
typedef void (*PATCHRESTORERANGE)(duint start, duint end);
|
||||
typedef bool (*PATCHENUM)(DBGPATCHINFO* patchlist, size_t* cbsize);
|
||||
typedef bool (*PATCHRESTORE)(duint addr);
|
||||
typedef int (*PATCHFILE)(DBGPATCHINFO* patchlist, int count, const char* szFileName, char* error);
|
||||
typedef int (*MODPATHFROMADDR)(duint addr, char* path, int size);
|
||||
typedef int (*MODPATHFROMNAME)(const char* modname, char* path, int size);
|
||||
typedef bool (*DISASMFAST)(unsigned char* data, duint addr, BASIC_INSTRUCTION_INFO* basicinfo);
|
||||
typedef void (*MEMUPDATEMAP)();
|
||||
typedef void (*GETCALLSTACK)(DBGCALLSTACK* callstack);
|
||||
typedef void (*SYMBOLDOWNLOADALLSYMBOLS)(const char* szSymbolStore);
|
||||
typedef bool (*GETJIT)(char* jit, bool x64);
|
||||
typedef bool (*GETJITAUTO)(bool* jitauto);
|
||||
typedef bool (*GETDEFJIT)(char* defjit);
|
||||
typedef bool (*GETPROCESSLIST)(DBGPROCESSINFO** entries, int* count);
|
||||
typedef bool (*GETPAGERIGHTS)(duint addr, char* rights);
|
||||
typedef bool (*SETPAGERIGHTS)(duint addr, const char* rights);
|
||||
typedef bool (*PAGERIGHTSTOSTRING)(DWORD protect, char* rights);
|
||||
typedef bool (*ISPROCESSELEVATED)();
|
||||
typedef bool (*GETCMDLINE)(char* cmdline, size_t* cbsize);
|
||||
typedef bool (*SETCMDLINE)(const char* cmdline);
|
||||
typedef duint (*FILEOFFSETTOVA)(const char* modname, duint offset);
|
||||
typedef duint (*VATOFILEOFFSET)(duint va);
|
||||
typedef duint (*GETADDRFROMLINE)(const char* szSourceFile, int line);
|
||||
typedef bool (*GETSOURCEFROMADDR)(duint addr, char* szSourceFile, int* line);
|
||||
typedef bool (*VALFROMSTRING)(const char* string, duint* value);
|
||||
|
||||
typedef struct DBGFUNCTIONS_
|
||||
{
|
||||
ASSEMBLEATEX AssembleAtEx;
|
||||
SECTIONFROMADDR SectionFromAddr;
|
||||
MODNAMEFROMADDR ModNameFromAddr;
|
||||
MODBASEFROMADDR ModBaseFromAddr;
|
||||
MODBASEFROMNAME ModBaseFromName;
|
||||
MODSIZEFROMADDR ModSizeFromAddr;
|
||||
ASSEMBLE Assemble;
|
||||
PATCHGET PatchGet;
|
||||
PATCHINRANGE PatchInRange;
|
||||
MEMPATCH MemPatch;
|
||||
PATCHRESTORERANGE PatchRestoreRange;
|
||||
PATCHENUM PatchEnum;
|
||||
PATCHRESTORE PatchRestore;
|
||||
PATCHFILE PatchFile;
|
||||
MODPATHFROMADDR ModPathFromAddr;
|
||||
MODPATHFROMNAME ModPathFromName;
|
||||
DISASMFAST DisasmFast;
|
||||
MEMUPDATEMAP MemUpdateMap;
|
||||
GETCALLSTACK GetCallStack;
|
||||
SYMBOLDOWNLOADALLSYMBOLS SymbolDownloadAllSymbols;
|
||||
GETJITAUTO GetJitAuto;
|
||||
GETJIT GetJit;
|
||||
GETDEFJIT GetDefJit;
|
||||
GETPROCESSLIST GetProcessList;
|
||||
GETPAGERIGHTS GetPageRights;
|
||||
SETPAGERIGHTS SetPageRights;
|
||||
PAGERIGHTSTOSTRING PageRightsToString;
|
||||
ISPROCESSELEVATED IsProcessElevated;
|
||||
GETCMDLINE GetCmdline;
|
||||
SETCMDLINE SetCmdline;
|
||||
FILEOFFSETTOVA FileOffsetToVa;
|
||||
VATOFILEOFFSET VaToFileOffset;
|
||||
GETADDRFROMLINE GetAddrFromLine;
|
||||
GETSOURCEFROMADDR GetSourceFromAddr;
|
||||
VALFROMSTRING ValFromString;
|
||||
} DBGFUNCTIONS;
|
||||
|
||||
#ifdef BUILD_DBG
|
||||
|
||||
const DBGFUNCTIONS* dbgfunctionsget();
|
||||
void dbgfunctionsinit();
|
||||
|
||||
#endif //BUILD_DBG
|
||||
|
||||
#endif //_DBGFUNCTIONS_H
|
||||
#ifndef _DBGFUNCTIONS_H
|
||||
#define _DBGFUNCTIONS_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char mod[MAX_MODULE_SIZE];
|
||||
duint addr;
|
||||
unsigned char oldbyte;
|
||||
unsigned char newbyte;
|
||||
} DBGPATCHINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
duint addr;
|
||||
duint from;
|
||||
duint to;
|
||||
char comment[MAX_COMMENT_SIZE];
|
||||
} DBGCALLSTACKENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int total;
|
||||
DBGCALLSTACKENTRY* entries;
|
||||
} DBGCALLSTACK;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwProcessId;
|
||||
char szExeFile[MAX_PATH];
|
||||
} DBGPROCESSINFO;
|
||||
|
||||
typedef bool (*ASSEMBLEATEX)(duint addr, const char* instruction, char* error, bool fillnop);
|
||||
typedef bool (*SECTIONFROMADDR)(duint addr, char* section);
|
||||
typedef bool (*MODNAMEFROMADDR)(duint addr, char* modname, bool extension);
|
||||
typedef duint (*MODBASEFROMADDR)(duint addr);
|
||||
typedef duint (*MODBASEFROMNAME)(const char* modname);
|
||||
typedef duint (*MODSIZEFROMADDR)(duint addr);
|
||||
typedef bool (*ASSEMBLE)(duint addr, unsigned char* dest, int* size, const char* instruction, char* error);
|
||||
typedef bool (*PATCHGET)(duint addr);
|
||||
typedef bool (*PATCHINRANGE)(duint start, duint end);
|
||||
typedef bool (*MEMPATCH)(duint va, const unsigned char* src, duint size);
|
||||
typedef void (*PATCHRESTORERANGE)(duint start, duint end);
|
||||
typedef bool (*PATCHENUM)(DBGPATCHINFO* patchlist, size_t* cbsize);
|
||||
typedef bool (*PATCHRESTORE)(duint addr);
|
||||
typedef int (*PATCHFILE)(DBGPATCHINFO* patchlist, int count, const char* szFileName, char* error);
|
||||
typedef int (*MODPATHFROMADDR)(duint addr, char* path, int size);
|
||||
typedef int (*MODPATHFROMNAME)(const char* modname, char* path, int size);
|
||||
typedef bool (*DISASMFAST)(unsigned char* data, duint addr, BASIC_INSTRUCTION_INFO* basicinfo);
|
||||
typedef void (*MEMUPDATEMAP)();
|
||||
typedef void (*GETCALLSTACK)(DBGCALLSTACK* callstack);
|
||||
typedef void (*SYMBOLDOWNLOADALLSYMBOLS)(const char* szSymbolStore);
|
||||
typedef bool (*GETJIT)(char* jit, bool x64);
|
||||
typedef bool (*GETJITAUTO)(bool* jitauto);
|
||||
typedef bool (*GETDEFJIT)(char* defjit);
|
||||
typedef bool (*GETPROCESSLIST)(DBGPROCESSINFO** entries, int* count);
|
||||
typedef bool (*GETPAGERIGHTS)(duint addr, char* rights);
|
||||
typedef bool (*SETPAGERIGHTS)(duint addr, const char* rights);
|
||||
typedef bool (*PAGERIGHTSTOSTRING)(DWORD protect, char* rights);
|
||||
typedef bool (*ISPROCESSELEVATED)();
|
||||
typedef bool (*GETCMDLINE)(char* cmdline, size_t* cbsize);
|
||||
typedef bool (*SETCMDLINE)(const char* cmdline);
|
||||
typedef duint (*FILEOFFSETTOVA)(const char* modname, duint offset);
|
||||
typedef duint (*VATOFILEOFFSET)(duint va);
|
||||
typedef duint (*GETADDRFROMLINE)(const char* szSourceFile, int line);
|
||||
typedef bool (*GETSOURCEFROMADDR)(duint addr, char* szSourceFile, int* line);
|
||||
typedef bool (*VALFROMSTRING)(const char* string, duint* value);
|
||||
|
||||
typedef struct DBGFUNCTIONS_
|
||||
{
|
||||
ASSEMBLEATEX AssembleAtEx;
|
||||
SECTIONFROMADDR SectionFromAddr;
|
||||
MODNAMEFROMADDR ModNameFromAddr;
|
||||
MODBASEFROMADDR ModBaseFromAddr;
|
||||
MODBASEFROMNAME ModBaseFromName;
|
||||
MODSIZEFROMADDR ModSizeFromAddr;
|
||||
ASSEMBLE Assemble;
|
||||
PATCHGET PatchGet;
|
||||
PATCHINRANGE PatchInRange;
|
||||
MEMPATCH MemPatch;
|
||||
PATCHRESTORERANGE PatchRestoreRange;
|
||||
PATCHENUM PatchEnum;
|
||||
PATCHRESTORE PatchRestore;
|
||||
PATCHFILE PatchFile;
|
||||
MODPATHFROMADDR ModPathFromAddr;
|
||||
MODPATHFROMNAME ModPathFromName;
|
||||
DISASMFAST DisasmFast;
|
||||
MEMUPDATEMAP MemUpdateMap;
|
||||
GETCALLSTACK GetCallStack;
|
||||
SYMBOLDOWNLOADALLSYMBOLS SymbolDownloadAllSymbols;
|
||||
GETJITAUTO GetJitAuto;
|
||||
GETJIT GetJit;
|
||||
GETDEFJIT GetDefJit;
|
||||
GETPROCESSLIST GetProcessList;
|
||||
GETPAGERIGHTS GetPageRights;
|
||||
SETPAGERIGHTS SetPageRights;
|
||||
PAGERIGHTSTOSTRING PageRightsToString;
|
||||
ISPROCESSELEVATED IsProcessElevated;
|
||||
GETCMDLINE GetCmdline;
|
||||
SETCMDLINE SetCmdline;
|
||||
FILEOFFSETTOVA FileOffsetToVa;
|
||||
VATOFILEOFFSET VaToFileOffset;
|
||||
GETADDRFROMLINE GetAddrFromLine;
|
||||
GETSOURCEFROMADDR GetSourceFromAddr;
|
||||
VALFROMSTRING ValFromString;
|
||||
} DBGFUNCTIONS;
|
||||
|
||||
#ifdef BUILD_DBG
|
||||
|
||||
const DBGFUNCTIONS* dbgfunctionsget();
|
||||
void dbgfunctionsinit();
|
||||
|
||||
#endif //BUILD_DBG
|
||||
|
||||
#endif //_DBGFUNCTIONS_H
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,33 +1,33 @@
|
|||
#ifndef _EXPORTS_H
|
||||
#define _EXPORTS_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
DLL_EXPORT duint _dbg_memfindbaseaddr(duint addr, duint* size);
|
||||
DLL_EXPORT bool _dbg_memread(duint addr, unsigned char* dest, duint size, duint* read);
|
||||
DLL_EXPORT bool _dbg_memwrite(duint addr, const unsigned char* src, duint size, duint* written);
|
||||
DLL_EXPORT bool _dbg_memmap(MEMMAP* memmap);
|
||||
DLL_EXPORT bool _dbg_memisvalidreadptr(duint addr);
|
||||
DLL_EXPORT bool _dbg_valfromstring(const char* string, duint* value);
|
||||
DLL_EXPORT bool _dbg_isdebugging();
|
||||
DLL_EXPORT bool _dbg_isjumpgoingtoexecute(duint addr);
|
||||
DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo);
|
||||
DLL_EXPORT bool _dbg_addrinfoset(duint addr, ADDRINFO* addrinfo);
|
||||
DLL_EXPORT int _dbg_bpgettypeat(duint addr);
|
||||
DLL_EXPORT bool _dbg_getregdump(REGDUMP* regdump);
|
||||
DLL_EXPORT bool _dbg_valtostring(const char* string, duint value);
|
||||
DLL_EXPORT int _dbg_getbplist(BPXTYPE type, BPMAP* list);
|
||||
DLL_EXPORT uint _dbg_getbranchdestination(uint addr);
|
||||
DLL_EXPORT bool _dbg_functionoverlaps(uint start, uint end);
|
||||
DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* param2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _EXPORTS_H
|
||||
#ifndef _EXPORTS_H
|
||||
#define _EXPORTS_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
DLL_EXPORT duint _dbg_memfindbaseaddr(duint addr, duint* size);
|
||||
DLL_EXPORT bool _dbg_memread(duint addr, unsigned char* dest, duint size, duint* read);
|
||||
DLL_EXPORT bool _dbg_memwrite(duint addr, const unsigned char* src, duint size, duint* written);
|
||||
DLL_EXPORT bool _dbg_memmap(MEMMAP* memmap);
|
||||
DLL_EXPORT bool _dbg_memisvalidreadptr(duint addr);
|
||||
DLL_EXPORT bool _dbg_valfromstring(const char* string, duint* value);
|
||||
DLL_EXPORT bool _dbg_isdebugging();
|
||||
DLL_EXPORT bool _dbg_isjumpgoingtoexecute(duint addr);
|
||||
DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo);
|
||||
DLL_EXPORT bool _dbg_addrinfoset(duint addr, ADDRINFO* addrinfo);
|
||||
DLL_EXPORT int _dbg_bpgettypeat(duint addr);
|
||||
DLL_EXPORT bool _dbg_getregdump(REGDUMP* regdump);
|
||||
DLL_EXPORT bool _dbg_valtostring(const char* string, duint value);
|
||||
DLL_EXPORT int _dbg_getbplist(BPXTYPE type, BPMAP* list);
|
||||
DLL_EXPORT uint _dbg_getbranchdestination(uint addr);
|
||||
DLL_EXPORT bool _dbg_functionoverlaps(uint start, uint end);
|
||||
DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* param2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _EXPORTS_H
|
||||
|
|
@ -1,364 +1,364 @@
|
|||
/**
|
||||
\file _global.cpp
|
||||
\brief Implements the global class.
|
||||
*/
|
||||
|
||||
#include "_global.h"
|
||||
#include <objbase.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
/**
|
||||
\brief x64dbg library instance.
|
||||
*/
|
||||
HINSTANCE hInst;
|
||||
|
||||
/**
|
||||
\brief Directory where program databases are stored (usually in \db). UTF-8 encoding.
|
||||
*/
|
||||
char dbbasepath[deflen] = "";
|
||||
|
||||
/**
|
||||
\brief Path of the current program database. UTF-8 encoding.
|
||||
*/
|
||||
char dbpath[3 * deflen] = "";
|
||||
|
||||
/**
|
||||
\brief Number of allocated buffers by emalloc(). This should be 0 when x64dbg ends.
|
||||
*/
|
||||
static int emalloc_count = 0;
|
||||
|
||||
/**
|
||||
\brief Path for debugging, used to create an allocation trace file on emalloc() or efree(). Not used.
|
||||
*/
|
||||
static char alloctrace[MAX_PATH] = "";
|
||||
|
||||
/**
|
||||
\brief Allocates a new buffer.
|
||||
\param size The size of the buffer to allocate (in bytes).
|
||||
\param reason The reason for allocation (can be used for memory allocation tracking).
|
||||
\return Always returns a valid pointer to the buffer you requested. Will quit the application on errors.
|
||||
*/
|
||||
void* emalloc(size_t size, const char* reason)
|
||||
{
|
||||
unsigned char* a = (unsigned char*)GlobalAlloc(GMEM_FIXED, size);
|
||||
if(!a)
|
||||
{
|
||||
MessageBoxA(0, "Could not allocate memory", "Error", MB_ICONERROR);
|
||||
ExitProcess(1);
|
||||
}
|
||||
memset(a, 0, size);
|
||||
emalloc_count++;
|
||||
/*
|
||||
FILE* file = fopen(alloctrace, "a+");
|
||||
fprintf(file, "DBG%.5d: alloc:" fhex ":%s:" fhex "\n", emalloc_count, a, reason, size);
|
||||
fclose(file);
|
||||
*/
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Reallocates a buffer allocated with emalloc().
|
||||
\param [in] Pointer to memory previously allocated with emalloc(). When NULL a new buffer will be allocated by emalloc().
|
||||
\param size The new memory size.
|
||||
\param reason The reason for allocation (can be used for memory allocation tracking).
|
||||
\return Always returns a valid pointer to the buffer you requested. Will quit the application on errors.
|
||||
*/
|
||||
void* erealloc(void* ptr, size_t size, const char* reason)
|
||||
{
|
||||
if(!ptr)
|
||||
return emalloc(size, reason);
|
||||
unsigned char* a = (unsigned char*)GlobalReAlloc(ptr, size, GMEM_ZEROINIT | GMEM_MOVEABLE);
|
||||
if(!a)
|
||||
{
|
||||
MessageBoxA(0, "Could not reallocate memory", "Error", MB_ICONERROR);
|
||||
ExitProcess(1);
|
||||
}
|
||||
memset(a, 0, size);
|
||||
/*
|
||||
FILE* file = fopen(alloctrace, "a+");
|
||||
fprintf(file, "DBG%.5d:realloc:" fhex ":%s:" fhex "\n", emalloc_count, a, reason, size);
|
||||
fclose(file);
|
||||
*/
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Free memory previously allocated with emalloc().
|
||||
\param [in] Pointer to the memory to free.
|
||||
\param reason The reason for freeing, should be the same as the reason for allocating.
|
||||
*/
|
||||
void efree(void* ptr, const char* reason)
|
||||
{
|
||||
emalloc_count--;
|
||||
/*
|
||||
FILE* file = fopen(alloctrace, "a+");
|
||||
fprintf(file, "DBG%.5d: free:" fhex ":%s\n", emalloc_count, ptr, reason);
|
||||
fclose(file);
|
||||
*/
|
||||
GlobalFree(ptr);
|
||||
}
|
||||
|
||||
void* json_malloc(size_t size)
|
||||
{
|
||||
return emalloc(size, "json:ptr");
|
||||
}
|
||||
|
||||
void json_free(void* ptr)
|
||||
{
|
||||
efree(ptr, "json:ptr");
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets the number of memory leaks. This number is only valid in _dbg_dbgexitsignal().
|
||||
\return The number of memory leaks.
|
||||
*/
|
||||
int memleaks()
|
||||
{
|
||||
return emalloc_count;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Sets the path for the allocation trace file.
|
||||
\param file UTF-8 filepath.
|
||||
*/
|
||||
void setalloctrace(const char* file)
|
||||
{
|
||||
strcpy_s(alloctrace, file);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief A function to determine if a string is contained in a specifically formatted 'array string'.
|
||||
\param cmd_list Array of strings separated by '\1'.
|
||||
\param cmd The string to look for.
|
||||
\return true if \p cmd is contained in \p cmd_list.
|
||||
*/
|
||||
bool arraycontains(const char* cmd_list, const char* cmd)
|
||||
{
|
||||
//TODO: fix this function a little
|
||||
if(!cmd_list || !cmd)
|
||||
return false;
|
||||
char temp[deflen] = "";
|
||||
strcpy_s(temp, cmd_list);
|
||||
int len = (int)strlen(cmd_list);
|
||||
if(len >= deflen)
|
||||
return false;
|
||||
for(int i = 0; i < len; i++)
|
||||
if(temp[i] == 1)
|
||||
temp[i] = 0;
|
||||
if(!_stricmp(temp, cmd))
|
||||
return true;
|
||||
for(int i = (int)strlen(temp); i < len; i++)
|
||||
{
|
||||
if(!temp[i])
|
||||
{
|
||||
if(!_stricmp(temp + i + 1, cmd))
|
||||
return true;
|
||||
i += (int)strlen(temp + i + 1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Compares two strings without case-sensitivity.
|
||||
\param a The first string.
|
||||
\param b The second string.
|
||||
\return true if the strings are equal (case-insensitive).
|
||||
*/
|
||||
bool scmp(const char* a, const char* b)
|
||||
{
|
||||
if(_stricmp(a, b))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Formats a string to hexadecimal format (removes all non-hex characters).
|
||||
\param [in,out] String to format.
|
||||
*/
|
||||
void formathex(char* string)
|
||||
{
|
||||
int len = (int)strlen(string);
|
||||
_strupr(string);
|
||||
Memory<char*> new_string(len + 1, "formathex:new_string");
|
||||
for(int i = 0, j = 0; i < len; i++)
|
||||
if(isxdigit(string[i]))
|
||||
j += sprintf(new_string() + j, "%c", string[i]);
|
||||
strcpy_s(string, len + 1, new_string());
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Formats a string to decimal format (removed all non-numeric characters).
|
||||
\param [in,out] String to format.
|
||||
*/
|
||||
void formatdec(char* string)
|
||||
{
|
||||
int len = (int)strlen(string);
|
||||
_strupr(string);
|
||||
Memory<char*> new_string(len + 1, "formatdec:new_string");
|
||||
for(int i = 0, j = 0; i < len; i++)
|
||||
if(isdigit(string[i]))
|
||||
j += sprintf(new_string() + j, "%c", string[i]);
|
||||
strcpy_s(string, len + 1, new_string());
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Queries if a given file exists.
|
||||
\param file Path to the file to check (UTF-8).
|
||||
\return true if the file exists on the hard drive.
|
||||
*/
|
||||
bool FileExists(const char* file)
|
||||
{
|
||||
DWORD attrib = GetFileAttributesW(StringUtils::Utf8ToUtf16(file).c_str());
|
||||
return (attrib != INVALID_FILE_ATTRIBUTES && !(attrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Queries if a given directory exists.
|
||||
\param dir Path to the directory to check (UTF-8).
|
||||
\return true if the directory exists.
|
||||
*/
|
||||
bool DirExists(const char* dir)
|
||||
{
|
||||
DWORD attrib = GetFileAttributesW(StringUtils::Utf8ToUtf16(dir).c_str());
|
||||
return (attrib == FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets file path from a file handle.
|
||||
\param hFile File handle to get the path from.
|
||||
\param [in,out] szFileName Buffer of size MAX_PATH.
|
||||
\return true if it succeeds, false if it fails.
|
||||
*/
|
||||
bool GetFileNameFromHandle(HANDLE hFile, char* szFileName)
|
||||
{
|
||||
wchar_t wszFileName[MAX_PATH] = L"";
|
||||
if(!PathFromFileHandleW(hFile, wszFileName, sizeof(wszFileName)))
|
||||
return false;
|
||||
strcpy_s(szFileName, MAX_PATH, StringUtils::Utf16ToUtf8(wszFileName).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get a boolean setting from the configuration file.
|
||||
\param section The section of the setting (UTF-8).
|
||||
\param name The name of the setting (UTF-8).
|
||||
\return true if the setting was set and equals to true, otherwise returns false.
|
||||
*/
|
||||
bool settingboolget(const char* section, const char* name)
|
||||
{
|
||||
uint setting;
|
||||
if(!BridgeSettingGetUint(section, name, &setting))
|
||||
return false;
|
||||
if(setting)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets file architecture.
|
||||
\param szFileName UTF-8 encoded file path.
|
||||
\return The file architecture (::arch).
|
||||
*/
|
||||
arch GetFileArchitecture(const char* szFileName)
|
||||
{
|
||||
arch retval = notfound;
|
||||
Handle hFile = CreateFileW(StringUtils::Utf8ToUtf16(szFileName).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
unsigned char data[0x1000];
|
||||
DWORD read = 0;
|
||||
DWORD fileSize = GetFileSize(hFile, 0);
|
||||
DWORD readSize = sizeof(data);
|
||||
if(readSize > fileSize)
|
||||
readSize = fileSize;
|
||||
if(ReadFile(hFile, data, readSize, &read, 0))
|
||||
{
|
||||
retval = invalid;
|
||||
IMAGE_DOS_HEADER* pdh = (IMAGE_DOS_HEADER*)data;
|
||||
if(pdh->e_magic == IMAGE_DOS_SIGNATURE && (size_t)pdh->e_lfanew < readSize)
|
||||
{
|
||||
IMAGE_NT_HEADERS* pnth = (IMAGE_NT_HEADERS*)(data + pdh->e_lfanew);
|
||||
if(pnth->Signature == IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) //x32
|
||||
retval = x32;
|
||||
else if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) //x64
|
||||
retval = x64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Query if x64dbg is running in Wow64 mode.
|
||||
\return true if running in Wow64, false otherwise.
|
||||
*/
|
||||
bool IsWow64()
|
||||
{
|
||||
BOOL bIsWow64Process = FALSE;
|
||||
//x64dbg supports WinXP SP3 and later only, so ignore the GetProcAddress crap :D
|
||||
IsWow64Process(GetCurrentProcess(), &bIsWow64Process);
|
||||
return !!bIsWow64Process;
|
||||
}
|
||||
|
||||
//Taken from: http://www.cplusplus.com/forum/windows/64088/
|
||||
bool ResolveShortcut(HWND hwnd, const wchar_t* szShortcutPath, char* szResolvedPath, size_t nSize)
|
||||
{
|
||||
if(szResolvedPath == NULL)
|
||||
return SUCCEEDED(E_INVALIDARG);
|
||||
|
||||
//Initialize COM stuff
|
||||
CoInitialize(NULL);
|
||||
|
||||
//Get a pointer to the IShellLink interface.
|
||||
IShellLink* psl = NULL;
|
||||
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
|
||||
if(SUCCEEDED(hres))
|
||||
{
|
||||
//Get a pointer to the IPersistFile interface.
|
||||
IPersistFile* ppf = NULL;
|
||||
hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
|
||||
if(SUCCEEDED(hres))
|
||||
{
|
||||
//Load the shortcut.
|
||||
hres = ppf->Load(szShortcutPath, STGM_READ);
|
||||
|
||||
if(SUCCEEDED(hres))
|
||||
{
|
||||
//Resolve the link.
|
||||
hres = psl->Resolve(hwnd, 0);
|
||||
|
||||
if(SUCCEEDED(hres))
|
||||
{
|
||||
//Get the path to the link target.
|
||||
char szGotPath[MAX_PATH] = {0};
|
||||
hres = psl->GetPath(szGotPath, _countof(szGotPath), NULL, SLGP_SHORTPATH);
|
||||
|
||||
if(SUCCEEDED(hres))
|
||||
{
|
||||
strcpy_s(szResolvedPath, nSize, szGotPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Release the pointer to the IPersistFile interface.
|
||||
ppf->Release();
|
||||
}
|
||||
|
||||
//Release the pointer to the IShellLink interface.
|
||||
psl->Release();
|
||||
}
|
||||
|
||||
//Uninitialize COM stuff
|
||||
CoUninitialize();
|
||||
return SUCCEEDED(hres);
|
||||
}
|
||||
|
||||
void WaitForThreadTermination(HANDLE hThread)
|
||||
{
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
/**
|
||||
\file _global.cpp
|
||||
\brief Implements the global class.
|
||||
*/
|
||||
|
||||
#include "_global.h"
|
||||
#include <objbase.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
/**
|
||||
\brief x64dbg library instance.
|
||||
*/
|
||||
HINSTANCE hInst;
|
||||
|
||||
/**
|
||||
\brief Directory where program databases are stored (usually in \db). UTF-8 encoding.
|
||||
*/
|
||||
char dbbasepath[deflen] = "";
|
||||
|
||||
/**
|
||||
\brief Path of the current program database. UTF-8 encoding.
|
||||
*/
|
||||
char dbpath[3 * deflen] = "";
|
||||
|
||||
/**
|
||||
\brief Number of allocated buffers by emalloc(). This should be 0 when x64dbg ends.
|
||||
*/
|
||||
static int emalloc_count = 0;
|
||||
|
||||
/**
|
||||
\brief Path for debugging, used to create an allocation trace file on emalloc() or efree(). Not used.
|
||||
*/
|
||||
static char alloctrace[MAX_PATH] = "";
|
||||
|
||||
/**
|
||||
\brief Allocates a new buffer.
|
||||
\param size The size of the buffer to allocate (in bytes).
|
||||
\param reason The reason for allocation (can be used for memory allocation tracking).
|
||||
\return Always returns a valid pointer to the buffer you requested. Will quit the application on errors.
|
||||
*/
|
||||
void* emalloc(size_t size, const char* reason)
|
||||
{
|
||||
unsigned char* a = (unsigned char*)GlobalAlloc(GMEM_FIXED, size);
|
||||
if(!a)
|
||||
{
|
||||
MessageBoxA(0, "Could not allocate memory", "Error", MB_ICONERROR);
|
||||
ExitProcess(1);
|
||||
}
|
||||
memset(a, 0, size);
|
||||
emalloc_count++;
|
||||
/*
|
||||
FILE* file = fopen(alloctrace, "a+");
|
||||
fprintf(file, "DBG%.5d: alloc:" fhex ":%s:" fhex "\n", emalloc_count, a, reason, size);
|
||||
fclose(file);
|
||||
*/
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Reallocates a buffer allocated with emalloc().
|
||||
\param [in] Pointer to memory previously allocated with emalloc(). When NULL a new buffer will be allocated by emalloc().
|
||||
\param size The new memory size.
|
||||
\param reason The reason for allocation (can be used for memory allocation tracking).
|
||||
\return Always returns a valid pointer to the buffer you requested. Will quit the application on errors.
|
||||
*/
|
||||
void* erealloc(void* ptr, size_t size, const char* reason)
|
||||
{
|
||||
if(!ptr)
|
||||
return emalloc(size, reason);
|
||||
unsigned char* a = (unsigned char*)GlobalReAlloc(ptr, size, GMEM_ZEROINIT | GMEM_MOVEABLE);
|
||||
if(!a)
|
||||
{
|
||||
MessageBoxA(0, "Could not reallocate memory", "Error", MB_ICONERROR);
|
||||
ExitProcess(1);
|
||||
}
|
||||
memset(a, 0, size);
|
||||
/*
|
||||
FILE* file = fopen(alloctrace, "a+");
|
||||
fprintf(file, "DBG%.5d:realloc:" fhex ":%s:" fhex "\n", emalloc_count, a, reason, size);
|
||||
fclose(file);
|
||||
*/
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Free memory previously allocated with emalloc().
|
||||
\param [in] Pointer to the memory to free.
|
||||
\param reason The reason for freeing, should be the same as the reason for allocating.
|
||||
*/
|
||||
void efree(void* ptr, const char* reason)
|
||||
{
|
||||
emalloc_count--;
|
||||
/*
|
||||
FILE* file = fopen(alloctrace, "a+");
|
||||
fprintf(file, "DBG%.5d: free:" fhex ":%s\n", emalloc_count, ptr, reason);
|
||||
fclose(file);
|
||||
*/
|
||||
GlobalFree(ptr);
|
||||
}
|
||||
|
||||
void* json_malloc(size_t size)
|
||||
{
|
||||
return emalloc(size, "json:ptr");
|
||||
}
|
||||
|
||||
void json_free(void* ptr)
|
||||
{
|
||||
efree(ptr, "json:ptr");
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets the number of memory leaks. This number is only valid in _dbg_dbgexitsignal().
|
||||
\return The number of memory leaks.
|
||||
*/
|
||||
int memleaks()
|
||||
{
|
||||
return emalloc_count;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Sets the path for the allocation trace file.
|
||||
\param file UTF-8 filepath.
|
||||
*/
|
||||
void setalloctrace(const char* file)
|
||||
{
|
||||
strcpy_s(alloctrace, file);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief A function to determine if a string is contained in a specifically formatted 'array string'.
|
||||
\param cmd_list Array of strings separated by '\1'.
|
||||
\param cmd The string to look for.
|
||||
\return true if \p cmd is contained in \p cmd_list.
|
||||
*/
|
||||
bool arraycontains(const char* cmd_list, const char* cmd)
|
||||
{
|
||||
//TODO: fix this function a little
|
||||
if(!cmd_list || !cmd)
|
||||
return false;
|
||||
char temp[deflen] = "";
|
||||
strcpy_s(temp, cmd_list);
|
||||
int len = (int)strlen(cmd_list);
|
||||
if(len >= deflen)
|
||||
return false;
|
||||
for(int i = 0; i < len; i++)
|
||||
if(temp[i] == 1)
|
||||
temp[i] = 0;
|
||||
if(!_stricmp(temp, cmd))
|
||||
return true;
|
||||
for(int i = (int)strlen(temp); i < len; i++)
|
||||
{
|
||||
if(!temp[i])
|
||||
{
|
||||
if(!_stricmp(temp + i + 1, cmd))
|
||||
return true;
|
||||
i += (int)strlen(temp + i + 1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Compares two strings without case-sensitivity.
|
||||
\param a The first string.
|
||||
\param b The second string.
|
||||
\return true if the strings are equal (case-insensitive).
|
||||
*/
|
||||
bool scmp(const char* a, const char* b)
|
||||
{
|
||||
if(_stricmp(a, b))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Formats a string to hexadecimal format (removes all non-hex characters).
|
||||
\param [in,out] String to format.
|
||||
*/
|
||||
void formathex(char* string)
|
||||
{
|
||||
int len = (int)strlen(string);
|
||||
_strupr(string);
|
||||
Memory<char*> new_string(len + 1, "formathex:new_string");
|
||||
for(int i = 0, j = 0; i < len; i++)
|
||||
if(isxdigit(string[i]))
|
||||
j += sprintf(new_string() + j, "%c", string[i]);
|
||||
strcpy_s(string, len + 1, new_string());
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Formats a string to decimal format (removed all non-numeric characters).
|
||||
\param [in,out] String to format.
|
||||
*/
|
||||
void formatdec(char* string)
|
||||
{
|
||||
int len = (int)strlen(string);
|
||||
_strupr(string);
|
||||
Memory<char*> new_string(len + 1, "formatdec:new_string");
|
||||
for(int i = 0, j = 0; i < len; i++)
|
||||
if(isdigit(string[i]))
|
||||
j += sprintf(new_string() + j, "%c", string[i]);
|
||||
strcpy_s(string, len + 1, new_string());
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Queries if a given file exists.
|
||||
\param file Path to the file to check (UTF-8).
|
||||
\return true if the file exists on the hard drive.
|
||||
*/
|
||||
bool FileExists(const char* file)
|
||||
{
|
||||
DWORD attrib = GetFileAttributesW(StringUtils::Utf8ToUtf16(file).c_str());
|
||||
return (attrib != INVALID_FILE_ATTRIBUTES && !(attrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Queries if a given directory exists.
|
||||
\param dir Path to the directory to check (UTF-8).
|
||||
\return true if the directory exists.
|
||||
*/
|
||||
bool DirExists(const char* dir)
|
||||
{
|
||||
DWORD attrib = GetFileAttributesW(StringUtils::Utf8ToUtf16(dir).c_str());
|
||||
return (attrib == FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets file path from a file handle.
|
||||
\param hFile File handle to get the path from.
|
||||
\param [in,out] szFileName Buffer of size MAX_PATH.
|
||||
\return true if it succeeds, false if it fails.
|
||||
*/
|
||||
bool GetFileNameFromHandle(HANDLE hFile, char* szFileName)
|
||||
{
|
||||
wchar_t wszFileName[MAX_PATH] = L"";
|
||||
if(!PathFromFileHandleW(hFile, wszFileName, sizeof(wszFileName)))
|
||||
return false;
|
||||
strcpy_s(szFileName, MAX_PATH, StringUtils::Utf16ToUtf8(wszFileName).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Get a boolean setting from the configuration file.
|
||||
\param section The section of the setting (UTF-8).
|
||||
\param name The name of the setting (UTF-8).
|
||||
\return true if the setting was set and equals to true, otherwise returns false.
|
||||
*/
|
||||
bool settingboolget(const char* section, const char* name)
|
||||
{
|
||||
uint setting;
|
||||
if(!BridgeSettingGetUint(section, name, &setting))
|
||||
return false;
|
||||
if(setting)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets file architecture.
|
||||
\param szFileName UTF-8 encoded file path.
|
||||
\return The file architecture (::arch).
|
||||
*/
|
||||
arch GetFileArchitecture(const char* szFileName)
|
||||
{
|
||||
arch retval = notfound;
|
||||
Handle hFile = CreateFileW(StringUtils::Utf8ToUtf16(szFileName).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
unsigned char data[0x1000];
|
||||
DWORD read = 0;
|
||||
DWORD fileSize = GetFileSize(hFile, 0);
|
||||
DWORD readSize = sizeof(data);
|
||||
if(readSize > fileSize)
|
||||
readSize = fileSize;
|
||||
if(ReadFile(hFile, data, readSize, &read, 0))
|
||||
{
|
||||
retval = invalid;
|
||||
IMAGE_DOS_HEADER* pdh = (IMAGE_DOS_HEADER*)data;
|
||||
if(pdh->e_magic == IMAGE_DOS_SIGNATURE && (size_t)pdh->e_lfanew < readSize)
|
||||
{
|
||||
IMAGE_NT_HEADERS* pnth = (IMAGE_NT_HEADERS*)(data + pdh->e_lfanew);
|
||||
if(pnth->Signature == IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) //x32
|
||||
retval = x32;
|
||||
else if(pnth->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) //x64
|
||||
retval = x64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Query if x64dbg is running in Wow64 mode.
|
||||
\return true if running in Wow64, false otherwise.
|
||||
*/
|
||||
bool IsWow64()
|
||||
{
|
||||
BOOL bIsWow64Process = FALSE;
|
||||
//x64dbg supports WinXP SP3 and later only, so ignore the GetProcAddress crap :D
|
||||
IsWow64Process(GetCurrentProcess(), &bIsWow64Process);
|
||||
return !!bIsWow64Process;
|
||||
}
|
||||
|
||||
//Taken from: http://www.cplusplus.com/forum/windows/64088/
|
||||
bool ResolveShortcut(HWND hwnd, const wchar_t* szShortcutPath, char* szResolvedPath, size_t nSize)
|
||||
{
|
||||
if(szResolvedPath == NULL)
|
||||
return SUCCEEDED(E_INVALIDARG);
|
||||
|
||||
//Initialize COM stuff
|
||||
CoInitialize(NULL);
|
||||
|
||||
//Get a pointer to the IShellLink interface.
|
||||
IShellLink* psl = NULL;
|
||||
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
|
||||
if(SUCCEEDED(hres))
|
||||
{
|
||||
//Get a pointer to the IPersistFile interface.
|
||||
IPersistFile* ppf = NULL;
|
||||
hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
|
||||
if(SUCCEEDED(hres))
|
||||
{
|
||||
//Load the shortcut.
|
||||
hres = ppf->Load(szShortcutPath, STGM_READ);
|
||||
|
||||
if(SUCCEEDED(hres))
|
||||
{
|
||||
//Resolve the link.
|
||||
hres = psl->Resolve(hwnd, 0);
|
||||
|
||||
if(SUCCEEDED(hres))
|
||||
{
|
||||
//Get the path to the link target.
|
||||
char szGotPath[MAX_PATH] = {0};
|
||||
hres = psl->GetPath(szGotPath, _countof(szGotPath), NULL, SLGP_SHORTPATH);
|
||||
|
||||
if(SUCCEEDED(hres))
|
||||
{
|
||||
strcpy_s(szResolvedPath, nSize, szGotPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Release the pointer to the IPersistFile interface.
|
||||
ppf->Release();
|
||||
}
|
||||
|
||||
//Release the pointer to the IShellLink interface.
|
||||
psl->Release();
|
||||
}
|
||||
|
||||
//Uninitialize COM stuff
|
||||
CoUninitialize();
|
||||
return SUCCEEDED(hres);
|
||||
}
|
||||
|
||||
void WaitForThreadTermination(HANDLE hThread)
|
||||
{
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
|
|
@ -1,88 +1,88 @@
|
|||
#ifndef _GLOBAL_H
|
||||
#define _GLOBAL_H
|
||||
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define WINVER 0x0501
|
||||
#define _WIN32_IE 0x0500
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <tlhelp32.h>
|
||||
#include "..\x64_dbg_bridge\bridgemain.h"
|
||||
#include "jansson\jansson.h"
|
||||
#include "jansson\jansson_x64dbg.h"
|
||||
#include "yara\yara.h"
|
||||
#include "DeviceNameResolver\DeviceNameResolver.h"
|
||||
#include "handle.h"
|
||||
#include "stringutils.h"
|
||||
#include "dbghelp_safe.h"
|
||||
|
||||
#ifndef DLL_EXPORT
|
||||
#define DLL_EXPORT __declspec(dllexport)
|
||||
#endif //DLL_IMPORT
|
||||
#ifndef DLL_IMPORT
|
||||
#define DLL_IMPORT __declspec(dllimport)
|
||||
#endif //DLL_IMPORT
|
||||
|
||||
//defines
|
||||
#define deflen 1024
|
||||
|
||||
#ifdef _WIN64 //defined by default
|
||||
#define fhex "%.16llX"
|
||||
#define fext "ll"
|
||||
typedef unsigned long long uint;
|
||||
typedef long long sint;
|
||||
#else
|
||||
#define fhex "%.8X"
|
||||
#define fext ""
|
||||
typedef unsigned long uint;
|
||||
typedef long sint;
|
||||
#endif // _WIN64
|
||||
|
||||
enum arch
|
||||
{
|
||||
notfound,
|
||||
invalid,
|
||||
x32,
|
||||
x64
|
||||
};
|
||||
|
||||
//superglobal variables
|
||||
extern HINSTANCE hInst;
|
||||
extern char dbbasepath[deflen];
|
||||
extern char dbpath[3 * deflen];
|
||||
|
||||
//functions
|
||||
void* emalloc(size_t size, const char* reason = "emalloc:???");
|
||||
void* erealloc(void* ptr, size_t size, const char* reason = "erealloc:???");
|
||||
void efree(void* ptr, const char* reason = "efree:???");
|
||||
void* json_malloc(size_t size);
|
||||
void json_free(void* ptr);
|
||||
int memleaks();
|
||||
void setalloctrace(const char* file);
|
||||
bool arraycontains(const char* cmd_list, const char* cmd);
|
||||
bool scmp(const char* a, const char* b);
|
||||
void formathex(char* string);
|
||||
void formatdec(char* string);
|
||||
bool FileExists(const char* file);
|
||||
bool DirExists(const char* dir);
|
||||
bool GetFileNameFromHandle(HANDLE hFile, char* szFileName);
|
||||
bool settingboolget(const char* section, const char* name);
|
||||
arch GetFileArchitecture(const char* szFileName);
|
||||
bool IsWow64();
|
||||
bool ResolveShortcut(HWND hwnd, const wchar_t* szShortcutPath, char* szResolvedPath, size_t nSize);
|
||||
void WaitForThreadTermination(HANDLE hThread);
|
||||
|
||||
#include "dynamicmem.h"
|
||||
|
||||
#endif // _GLOBAL_H
|
||||
#ifndef _GLOBAL_H
|
||||
#define _GLOBAL_H
|
||||
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define WINVER 0x0501
|
||||
#define _WIN32_IE 0x0500
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <tlhelp32.h>
|
||||
#include "..\bridge\bridgemain.h"
|
||||
#include "jansson\jansson.h"
|
||||
#include "jansson\jansson_x64dbg.h"
|
||||
#include "yara\yara.h"
|
||||
#include "DeviceNameResolver\DeviceNameResolver.h"
|
||||
#include "handle.h"
|
||||
#include "stringutils.h"
|
||||
#include "dbghelp_safe.h"
|
||||
|
||||
#ifndef DLL_EXPORT
|
||||
#define DLL_EXPORT __declspec(dllexport)
|
||||
#endif //DLL_IMPORT
|
||||
#ifndef DLL_IMPORT
|
||||
#define DLL_IMPORT __declspec(dllimport)
|
||||
#endif //DLL_IMPORT
|
||||
|
||||
//defines
|
||||
#define deflen 1024
|
||||
|
||||
#ifdef _WIN64 //defined by default
|
||||
#define fhex "%.16llX"
|
||||
#define fext "ll"
|
||||
typedef unsigned long long uint;
|
||||
typedef long long sint;
|
||||
#else
|
||||
#define fhex "%.8X"
|
||||
#define fext ""
|
||||
typedef unsigned long uint;
|
||||
typedef long sint;
|
||||
#endif // _WIN64
|
||||
|
||||
enum arch
|
||||
{
|
||||
notfound,
|
||||
invalid,
|
||||
x32,
|
||||
x64
|
||||
};
|
||||
|
||||
//superglobal variables
|
||||
extern HINSTANCE hInst;
|
||||
extern char dbbasepath[deflen];
|
||||
extern char dbpath[3 * deflen];
|
||||
|
||||
//functions
|
||||
void* emalloc(size_t size, const char* reason = "emalloc:???");
|
||||
void* erealloc(void* ptr, size_t size, const char* reason = "erealloc:???");
|
||||
void efree(void* ptr, const char* reason = "efree:???");
|
||||
void* json_malloc(size_t size);
|
||||
void json_free(void* ptr);
|
||||
int memleaks();
|
||||
void setalloctrace(const char* file);
|
||||
bool arraycontains(const char* cmd_list, const char* cmd);
|
||||
bool scmp(const char* a, const char* b);
|
||||
void formathex(char* string);
|
||||
void formatdec(char* string);
|
||||
bool FileExists(const char* file);
|
||||
bool DirExists(const char* dir);
|
||||
bool GetFileNameFromHandle(HANDLE hFile, char* szFileName);
|
||||
bool settingboolget(const char* section, const char* name);
|
||||
arch GetFileArchitecture(const char* szFileName);
|
||||
bool IsWow64();
|
||||
bool ResolveShortcut(HWND hwnd, const wchar_t* szShortcutPath, char* szResolvedPath, size_t nSize);
|
||||
void WaitForThreadTermination(HANDLE hThread);
|
||||
|
||||
#include "dynamicmem.h"
|
||||
|
||||
#endif // _GLOBAL_H
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
#ifndef _PLUGIN_DATA_H
|
||||
#define _PLUGIN_DATA_H
|
||||
|
||||
#ifdef BUILD_DBG
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include "dbghelp\dbghelp.h"
|
||||
#else
|
||||
#include <dbghelp.h>
|
||||
#endif // __GNUC__
|
||||
|
||||
#ifndef deflen
|
||||
#define deflen 1024
|
||||
#endif // deflen
|
||||
|
||||
#include "bridgemain.h"
|
||||
#include "_dbgfunctions.h"
|
||||
|
||||
#endif // BUILD_DBG
|
||||
|
||||
#endif // _PLUGIN_DATA_H
|
||||
#ifndef _PLUGIN_DATA_H
|
||||
#define _PLUGIN_DATA_H
|
||||
|
||||
#ifdef BUILD_DBG
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include "dbghelp\dbghelp.h"
|
||||
#else
|
||||
#include <dbghelp.h>
|
||||
#endif // __GNUC__
|
||||
|
||||
#ifndef deflen
|
||||
#define deflen 1024
|
||||
#endif // deflen
|
||||
|
||||
#include "bridgemain.h"
|
||||
#include "_dbgfunctions.h"
|
||||
|
||||
#endif // BUILD_DBG
|
||||
|
||||
#endif // _PLUGIN_DATA_H
|
||||
|
|
@ -1,103 +1,103 @@
|
|||
/**
|
||||
@file _plugins.cpp
|
||||
|
||||
@brief Implements the plugins class.
|
||||
*/
|
||||
|
||||
#include "_plugins.h"
|
||||
#include "plugin_loader.h"
|
||||
#include "console.h"
|
||||
#include "debugger.h"
|
||||
#include "threading.h"
|
||||
|
||||
///debugger plugin exports (wrappers)
|
||||
PLUG_IMPEXP void _plugin_registercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin)
|
||||
{
|
||||
pluginregistercallback(pluginHandle, cbType, cbPlugin);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_unregistercallback(int pluginHandle, CBTYPE cbType)
|
||||
{
|
||||
return pluginunregistercallback(pluginHandle, cbType);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_registercommand(int pluginHandle, const char* command, CBPLUGINCOMMAND cbCommand, bool debugonly)
|
||||
{
|
||||
return plugincmdregister(pluginHandle, command, cbCommand, debugonly);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_unregistercommand(int pluginHandle, const char* command)
|
||||
{
|
||||
return plugincmdunregister(pluginHandle, command);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_logprintf(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
dprintf_args(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_logputs(const char* text)
|
||||
{
|
||||
dputs(text);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_debugpause()
|
||||
{
|
||||
GuiSetDebugState(paused);
|
||||
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
|
||||
lock(WAITID_RUN);
|
||||
SetForegroundWindow(GuiGetWindowHandle());
|
||||
dbgsetskipexceptions(false);
|
||||
wait(WAITID_RUN);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_debugskipexceptions(bool skip)
|
||||
{
|
||||
dbgsetskipexceptions(skip);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP int _plugin_menuadd(int hMenu, const char* title)
|
||||
{
|
||||
return pluginmenuadd(hMenu, title);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_menuaddentry(int hMenu, int hEntry, const char* title)
|
||||
{
|
||||
return pluginmenuaddentry(hMenu, hEntry, title);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_menuaddseparator(int hMenu)
|
||||
{
|
||||
return pluginmenuaddseparator(hMenu);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_menuclear(int hMenu)
|
||||
{
|
||||
return pluginmenuclear(hMenu);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_menuseticon(int hMenu, const ICONDATA* icon)
|
||||
{
|
||||
pluginmenuseticon(hMenu, icon);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_menuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon)
|
||||
{
|
||||
pluginmenuentryseticon(pluginHandle, hEntry, icon);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_startscript(CBPLUGINSCRIPT cbScript)
|
||||
{
|
||||
dbgstartscriptthread(cbScript);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_waituntilpaused()
|
||||
{
|
||||
while(DbgIsDebugging() && dbgisrunning()) //wait until the debugger paused
|
||||
Sleep(1);
|
||||
return DbgIsDebugging();
|
||||
/**
|
||||
@file _plugins.cpp
|
||||
|
||||
@brief Implements the plugins class.
|
||||
*/
|
||||
|
||||
#include "_plugins.h"
|
||||
#include "plugin_loader.h"
|
||||
#include "console.h"
|
||||
#include "debugger.h"
|
||||
#include "threading.h"
|
||||
|
||||
///debugger plugin exports (wrappers)
|
||||
PLUG_IMPEXP void _plugin_registercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin)
|
||||
{
|
||||
pluginregistercallback(pluginHandle, cbType, cbPlugin);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_unregistercallback(int pluginHandle, CBTYPE cbType)
|
||||
{
|
||||
return pluginunregistercallback(pluginHandle, cbType);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_registercommand(int pluginHandle, const char* command, CBPLUGINCOMMAND cbCommand, bool debugonly)
|
||||
{
|
||||
return plugincmdregister(pluginHandle, command, cbCommand, debugonly);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_unregistercommand(int pluginHandle, const char* command)
|
||||
{
|
||||
return plugincmdunregister(pluginHandle, command);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_logprintf(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
dprintf_args(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_logputs(const char* text)
|
||||
{
|
||||
dputs(text);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_debugpause()
|
||||
{
|
||||
GuiSetDebugState(paused);
|
||||
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
|
||||
lock(WAITID_RUN);
|
||||
SetForegroundWindow(GuiGetWindowHandle());
|
||||
dbgsetskipexceptions(false);
|
||||
wait(WAITID_RUN);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_debugskipexceptions(bool skip)
|
||||
{
|
||||
dbgsetskipexceptions(skip);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP int _plugin_menuadd(int hMenu, const char* title)
|
||||
{
|
||||
return pluginmenuadd(hMenu, title);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_menuaddentry(int hMenu, int hEntry, const char* title)
|
||||
{
|
||||
return pluginmenuaddentry(hMenu, hEntry, title);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_menuaddseparator(int hMenu)
|
||||
{
|
||||
return pluginmenuaddseparator(hMenu);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_menuclear(int hMenu)
|
||||
{
|
||||
return pluginmenuclear(hMenu);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_menuseticon(int hMenu, const ICONDATA* icon)
|
||||
{
|
||||
pluginmenuseticon(hMenu, icon);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_menuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon)
|
||||
{
|
||||
pluginmenuentryseticon(pluginHandle, hEntry, icon);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP void _plugin_startscript(CBPLUGINSCRIPT cbScript)
|
||||
{
|
||||
dbgstartscriptthread(cbScript);
|
||||
}
|
||||
|
||||
PLUG_IMPEXP bool _plugin_waituntilpaused()
|
||||
{
|
||||
while(DbgIsDebugging() && dbgisrunning()) //wait until the debugger paused
|
||||
Sleep(1);
|
||||
return DbgIsDebugging();
|
||||
}
|
||||
|
|
@ -1,230 +1,230 @@
|
|||
#ifndef _PLUGINS_H
|
||||
#define _PLUGINS_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifndef PLUG_IMPEXP
|
||||
#ifdef BUILD_DBG
|
||||
#define PLUG_IMPEXP __declspec(dllexport)
|
||||
#else
|
||||
#define PLUG_IMPEXP __declspec(dllimport)
|
||||
#endif //BUILD_DBG
|
||||
#endif //PLUG_IMPEXP
|
||||
|
||||
#include "_plugin_types.h"
|
||||
|
||||
//default structure alignments forced
|
||||
#ifdef _WIN64
|
||||
#pragma pack(push, 16)
|
||||
#else //x86
|
||||
#pragma pack(push, 8)
|
||||
#endif //_WIN64
|
||||
|
||||
//defines
|
||||
#define PLUG_SDKVERSION 1
|
||||
|
||||
//structures
|
||||
typedef struct
|
||||
{
|
||||
//provided by the debugger
|
||||
int pluginHandle;
|
||||
//provided by the pluginit function
|
||||
int sdkVersion;
|
||||
int pluginVersion;
|
||||
char pluginName[256];
|
||||
} PLUG_INITSTRUCT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//provided by the debugger
|
||||
HWND hwndDlg; //gui window handle
|
||||
int hMenu; //plugin menu handle
|
||||
int hMenuDisasm; //plugin disasm menu handle
|
||||
int hMenuDump; //plugin dump menu handle
|
||||
int hMenuStack; //plugin stack menu handle
|
||||
} PLUG_SETUPSTRUCT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* data; //user data
|
||||
} PLUG_SCRIPTSTRUCT;
|
||||
|
||||
//callback structures
|
||||
typedef struct
|
||||
{
|
||||
const char* szFileName;
|
||||
} PLUG_CB_INITDEBUG;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* reserved;
|
||||
} PLUG_CB_STOPDEBUG;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo;
|
||||
IMAGEHLP_MODULE64* modInfo;
|
||||
const char* DebugFileName;
|
||||
PROCESS_INFORMATION* fdProcessInfo;
|
||||
} PLUG_CB_CREATEPROCESS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EXIT_PROCESS_DEBUG_INFO* ExitProcess;
|
||||
} PLUG_CB_EXITPROCESS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CREATE_THREAD_DEBUG_INFO* CreateThread;
|
||||
DWORD dwThreadId;
|
||||
} PLUG_CB_CREATETHREAD;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EXIT_THREAD_DEBUG_INFO* ExitThread;
|
||||
DWORD dwThreadId;
|
||||
} PLUG_CB_EXITTHREAD;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* reserved;
|
||||
} PLUG_CB_SYSTEMBREAKPOINT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LOAD_DLL_DEBUG_INFO* LoadDll;
|
||||
IMAGEHLP_MODULE64* modInfo;
|
||||
const char* modname;
|
||||
} PLUG_CB_LOADDLL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UNLOAD_DLL_DEBUG_INFO* UnloadDll;
|
||||
} PLUG_CB_UNLOADDLL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
OUTPUT_DEBUG_STRING_INFO* DebugString;
|
||||
} PLUG_CB_OUTPUTDEBUGSTRING;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EXCEPTION_DEBUG_INFO* Exception;
|
||||
} PLUG_CB_EXCEPTION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BRIDGEBP* breakpoint;
|
||||
} PLUG_CB_BREAKPOINT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* reserved;
|
||||
} PLUG_CB_PAUSEDEBUG;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* reserved;
|
||||
} PLUG_CB_RESUMEDEBUG;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* reserved;
|
||||
} PLUG_CB_STEPPED;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwProcessId;
|
||||
} PLUG_CB_ATTACH;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PROCESS_INFORMATION* fdProcessInfo;
|
||||
} PLUG_CB_DETACH;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DEBUG_EVENT* DebugEvent;
|
||||
} PLUG_CB_DEBUGEVENT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int hEntry;
|
||||
} PLUG_CB_MENUENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MSG* message;
|
||||
long* result;
|
||||
bool retval;
|
||||
} PLUG_CB_WINEVENT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MSG* message;
|
||||
bool retval;
|
||||
} PLUG_CB_WINEVENTGLOBAL;
|
||||
|
||||
//enums
|
||||
typedef enum
|
||||
{
|
||||
CB_INITDEBUG, //PLUG_CB_INITDEBUG
|
||||
CB_STOPDEBUG, //PLUG_CB_STOPDEBUG
|
||||
CB_CREATEPROCESS, //PLUG_CB_CREATEPROCESS
|
||||
CB_EXITPROCESS, //PLUG_CB_EXITPROCESS
|
||||
CB_CREATETHREAD, //PLUG_CB_CREATETHREAD
|
||||
CB_EXITTHREAD, //PLUG_CB_EXITTHREAD
|
||||
CB_SYSTEMBREAKPOINT, //PLUG_CB_SYSTEMBREAKPOINT
|
||||
CB_LOADDLL, //PLUG_CB_LOADDLL
|
||||
CB_UNLOADDLL, //PLUG_CB_UNLOADDLL
|
||||
CB_OUTPUTDEBUGSTRING, //PLUG_CB_OUTPUTDEBUGSTRING
|
||||
CB_EXCEPTION, //PLUG_CB_EXCEPTION
|
||||
CB_BREAKPOINT, //PLUG_CB_BREAKPOINT
|
||||
CB_PAUSEDEBUG, //PLUG_CB_PAUSEDEBUG
|
||||
CB_RESUMEDEBUG, //PLUG_CB_RESUMEDEBUG
|
||||
CB_STEPPED, //PLUG_CB_STEPPED
|
||||
CB_ATTACH, //PLUG_CB_ATTACHED (before attaching, after CB_INITDEBUG)
|
||||
CB_DETACH, //PLUG_CB_DETACH (before detaching, before CB_STOPDEBUG)
|
||||
CB_DEBUGEVENT, //PLUG_CB_DEBUGEVENT (called on any debug event)
|
||||
CB_MENUENTRY, //PLUG_CB_MENUENTRY
|
||||
CB_WINEVENT, //PLUG_CB_WINEVENT
|
||||
CB_WINEVENTGLOBAL //PLUG_CB_WINEVENTGLOBAL
|
||||
} CBTYPE;
|
||||
|
||||
//typedefs
|
||||
typedef void (*CBPLUGIN)(CBTYPE cbType, void* callbackInfo);
|
||||
typedef bool (*CBPLUGINCOMMAND)(int, char**);
|
||||
typedef void (*CBPLUGINSCRIPT)();
|
||||
|
||||
//exports
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
PLUG_IMPEXP void _plugin_registercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin);
|
||||
PLUG_IMPEXP bool _plugin_unregistercallback(int pluginHandle, CBTYPE cbType);
|
||||
PLUG_IMPEXP bool _plugin_registercommand(int pluginHandle, const char* command, CBPLUGINCOMMAND cbCommand, bool debugonly);
|
||||
PLUG_IMPEXP bool _plugin_unregistercommand(int pluginHandle, const char* command);
|
||||
PLUG_IMPEXP void _plugin_logprintf(const char* format, ...);
|
||||
PLUG_IMPEXP void _plugin_logputs(const char* text);
|
||||
PLUG_IMPEXP void _plugin_debugpause();
|
||||
PLUG_IMPEXP void _plugin_debugskipexceptions(bool skip);
|
||||
PLUG_IMPEXP int _plugin_menuadd(int hMenu, const char* title);
|
||||
PLUG_IMPEXP bool _plugin_menuaddentry(int hMenu, int hEntry, const char* title);
|
||||
PLUG_IMPEXP bool _plugin_menuaddseparator(int hMenu);
|
||||
PLUG_IMPEXP bool _plugin_menuclear(int hMenu);
|
||||
PLUG_IMPEXP void _plugin_menuseticon(int hMenu, const ICONDATA* icon);
|
||||
PLUG_IMPEXP void _plugin_menuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon);
|
||||
PLUG_IMPEXP void _plugin_startscript(CBPLUGINSCRIPT cbScript);
|
||||
PLUG_IMPEXP bool _plugin_waituntilpaused();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // _PLUGINS_H
|
||||
#ifndef _PLUGINS_H
|
||||
#define _PLUGINS_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifndef PLUG_IMPEXP
|
||||
#ifdef BUILD_DBG
|
||||
#define PLUG_IMPEXP __declspec(dllexport)
|
||||
#else
|
||||
#define PLUG_IMPEXP __declspec(dllimport)
|
||||
#endif //BUILD_DBG
|
||||
#endif //PLUG_IMPEXP
|
||||
|
||||
#include "_plugin_types.h"
|
||||
|
||||
//default structure alignments forced
|
||||
#ifdef _WIN64
|
||||
#pragma pack(push, 16)
|
||||
#else //x86
|
||||
#pragma pack(push, 8)
|
||||
#endif //_WIN64
|
||||
|
||||
//defines
|
||||
#define PLUG_SDKVERSION 1
|
||||
|
||||
//structures
|
||||
typedef struct
|
||||
{
|
||||
//provided by the debugger
|
||||
int pluginHandle;
|
||||
//provided by the pluginit function
|
||||
int sdkVersion;
|
||||
int pluginVersion;
|
||||
char pluginName[256];
|
||||
} PLUG_INITSTRUCT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//provided by the debugger
|
||||
HWND hwndDlg; //gui window handle
|
||||
int hMenu; //plugin menu handle
|
||||
int hMenuDisasm; //plugin disasm menu handle
|
||||
int hMenuDump; //plugin dump menu handle
|
||||
int hMenuStack; //plugin stack menu handle
|
||||
} PLUG_SETUPSTRUCT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* data; //user data
|
||||
} PLUG_SCRIPTSTRUCT;
|
||||
|
||||
//callback structures
|
||||
typedef struct
|
||||
{
|
||||
const char* szFileName;
|
||||
} PLUG_CB_INITDEBUG;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* reserved;
|
||||
} PLUG_CB_STOPDEBUG;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo;
|
||||
IMAGEHLP_MODULE64* modInfo;
|
||||
const char* DebugFileName;
|
||||
PROCESS_INFORMATION* fdProcessInfo;
|
||||
} PLUG_CB_CREATEPROCESS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EXIT_PROCESS_DEBUG_INFO* ExitProcess;
|
||||
} PLUG_CB_EXITPROCESS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CREATE_THREAD_DEBUG_INFO* CreateThread;
|
||||
DWORD dwThreadId;
|
||||
} PLUG_CB_CREATETHREAD;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EXIT_THREAD_DEBUG_INFO* ExitThread;
|
||||
DWORD dwThreadId;
|
||||
} PLUG_CB_EXITTHREAD;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* reserved;
|
||||
} PLUG_CB_SYSTEMBREAKPOINT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LOAD_DLL_DEBUG_INFO* LoadDll;
|
||||
IMAGEHLP_MODULE64* modInfo;
|
||||
const char* modname;
|
||||
} PLUG_CB_LOADDLL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UNLOAD_DLL_DEBUG_INFO* UnloadDll;
|
||||
} PLUG_CB_UNLOADDLL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
OUTPUT_DEBUG_STRING_INFO* DebugString;
|
||||
} PLUG_CB_OUTPUTDEBUGSTRING;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EXCEPTION_DEBUG_INFO* Exception;
|
||||
} PLUG_CB_EXCEPTION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BRIDGEBP* breakpoint;
|
||||
} PLUG_CB_BREAKPOINT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* reserved;
|
||||
} PLUG_CB_PAUSEDEBUG;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* reserved;
|
||||
} PLUG_CB_RESUMEDEBUG;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* reserved;
|
||||
} PLUG_CB_STEPPED;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwProcessId;
|
||||
} PLUG_CB_ATTACH;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PROCESS_INFORMATION* fdProcessInfo;
|
||||
} PLUG_CB_DETACH;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DEBUG_EVENT* DebugEvent;
|
||||
} PLUG_CB_DEBUGEVENT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int hEntry;
|
||||
} PLUG_CB_MENUENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MSG* message;
|
||||
long* result;
|
||||
bool retval;
|
||||
} PLUG_CB_WINEVENT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MSG* message;
|
||||
bool retval;
|
||||
} PLUG_CB_WINEVENTGLOBAL;
|
||||
|
||||
//enums
|
||||
typedef enum
|
||||
{
|
||||
CB_INITDEBUG, //PLUG_CB_INITDEBUG
|
||||
CB_STOPDEBUG, //PLUG_CB_STOPDEBUG
|
||||
CB_CREATEPROCESS, //PLUG_CB_CREATEPROCESS
|
||||
CB_EXITPROCESS, //PLUG_CB_EXITPROCESS
|
||||
CB_CREATETHREAD, //PLUG_CB_CREATETHREAD
|
||||
CB_EXITTHREAD, //PLUG_CB_EXITTHREAD
|
||||
CB_SYSTEMBREAKPOINT, //PLUG_CB_SYSTEMBREAKPOINT
|
||||
CB_LOADDLL, //PLUG_CB_LOADDLL
|
||||
CB_UNLOADDLL, //PLUG_CB_UNLOADDLL
|
||||
CB_OUTPUTDEBUGSTRING, //PLUG_CB_OUTPUTDEBUGSTRING
|
||||
CB_EXCEPTION, //PLUG_CB_EXCEPTION
|
||||
CB_BREAKPOINT, //PLUG_CB_BREAKPOINT
|
||||
CB_PAUSEDEBUG, //PLUG_CB_PAUSEDEBUG
|
||||
CB_RESUMEDEBUG, //PLUG_CB_RESUMEDEBUG
|
||||
CB_STEPPED, //PLUG_CB_STEPPED
|
||||
CB_ATTACH, //PLUG_CB_ATTACHED (before attaching, after CB_INITDEBUG)
|
||||
CB_DETACH, //PLUG_CB_DETACH (before detaching, before CB_STOPDEBUG)
|
||||
CB_DEBUGEVENT, //PLUG_CB_DEBUGEVENT (called on any debug event)
|
||||
CB_MENUENTRY, //PLUG_CB_MENUENTRY
|
||||
CB_WINEVENT, //PLUG_CB_WINEVENT
|
||||
CB_WINEVENTGLOBAL //PLUG_CB_WINEVENTGLOBAL
|
||||
} CBTYPE;
|
||||
|
||||
//typedefs
|
||||
typedef void (*CBPLUGIN)(CBTYPE cbType, void* callbackInfo);
|
||||
typedef bool (*CBPLUGINCOMMAND)(int, char**);
|
||||
typedef void (*CBPLUGINSCRIPT)();
|
||||
|
||||
//exports
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
PLUG_IMPEXP void _plugin_registercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin);
|
||||
PLUG_IMPEXP bool _plugin_unregistercallback(int pluginHandle, CBTYPE cbType);
|
||||
PLUG_IMPEXP bool _plugin_registercommand(int pluginHandle, const char* command, CBPLUGINCOMMAND cbCommand, bool debugonly);
|
||||
PLUG_IMPEXP bool _plugin_unregistercommand(int pluginHandle, const char* command);
|
||||
PLUG_IMPEXP void _plugin_logprintf(const char* format, ...);
|
||||
PLUG_IMPEXP void _plugin_logputs(const char* text);
|
||||
PLUG_IMPEXP void _plugin_debugpause();
|
||||
PLUG_IMPEXP void _plugin_debugskipexceptions(bool skip);
|
||||
PLUG_IMPEXP int _plugin_menuadd(int hMenu, const char* title);
|
||||
PLUG_IMPEXP bool _plugin_menuaddentry(int hMenu, int hEntry, const char* title);
|
||||
PLUG_IMPEXP bool _plugin_menuaddseparator(int hMenu);
|
||||
PLUG_IMPEXP bool _plugin_menuclear(int hMenu);
|
||||
PLUG_IMPEXP void _plugin_menuseticon(int hMenu, const ICONDATA* icon);
|
||||
PLUG_IMPEXP void _plugin_menuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon);
|
||||
PLUG_IMPEXP void _plugin_startscript(CBPLUGINSCRIPT cbScript);
|
||||
PLUG_IMPEXP bool _plugin_waituntilpaused();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // _PLUGINS_H
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _SCRIPT_API_H
|
||||
#define _SCRIPT_API_H
|
||||
|
||||
#include "_plugins.h"
|
||||
|
||||
#define SCRIPT_EXPORT PLUG_IMPEXP
|
||||
|
||||
#ifndef _SCRIPT_API_H
|
||||
#define _SCRIPT_API_H
|
||||
|
||||
#include "_plugins.h"
|
||||
|
||||
#define SCRIPT_EXPORT PLUG_IMPEXP
|
||||
|
||||
#endif //_SCRIPT_API_H
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
#include "_scriptapi_assembler.h"
|
||||
#include "assemble.h"
|
||||
|
||||
SCRIPT_EXPORT bool Script::Assembler::Assemble(duint addr, unsigned char* dest, int* size, const char* instruction)
|
||||
{
|
||||
return assemble(addr, dest, size, instruction, nullptr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Assembler::AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error)
|
||||
{
|
||||
return assemble(addr, dest, size, instruction, error);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Assembler::AssembleMem(duint addr, const char* instruction)
|
||||
{
|
||||
return assembleat(addr, instruction, nullptr, nullptr, false);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Assembler::AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop)
|
||||
{
|
||||
return assembleat(addr, instruction, size, error, fillnop);
|
||||
#include "_scriptapi_assembler.h"
|
||||
#include "assemble.h"
|
||||
|
||||
SCRIPT_EXPORT bool Script::Assembler::Assemble(duint addr, unsigned char* dest, int* size, const char* instruction)
|
||||
{
|
||||
return assemble(addr, dest, size, instruction, nullptr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Assembler::AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error)
|
||||
{
|
||||
return assemble(addr, dest, size, instruction, error);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Assembler::AssembleMem(duint addr, const char* instruction)
|
||||
{
|
||||
return assembleat(addr, instruction, nullptr, nullptr, false);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Assembler::AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop)
|
||||
{
|
||||
return assembleat(addr, instruction, size, error, fillnop);
|
||||
}
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
#ifndef _SCRIPTAPI_ASSEMBLER_H
|
||||
#define _SCRIPTAPI_ASSEMBLER_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Assembler
|
||||
{
|
||||
SCRIPT_EXPORT bool Assemble(duint addr, unsigned char* dest, int* size, const char* instruction); //dest[16]
|
||||
SCRIPT_EXPORT bool AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error); //dest[16], error[MAX_ERROR_SIZE]
|
||||
SCRIPT_EXPORT bool AssembleMem(duint addr, const char* instruction);
|
||||
SCRIPT_EXPORT bool AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop); //error[MAX_ERROR_SIZE]
|
||||
}; //Assembler
|
||||
}; //Script
|
||||
|
||||
#ifndef _SCRIPTAPI_ASSEMBLER_H
|
||||
#define _SCRIPTAPI_ASSEMBLER_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Assembler
|
||||
{
|
||||
SCRIPT_EXPORT bool Assemble(duint addr, unsigned char* dest, int* size, const char* instruction); //dest[16]
|
||||
SCRIPT_EXPORT bool AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error); //dest[16], error[MAX_ERROR_SIZE]
|
||||
SCRIPT_EXPORT bool AssembleMem(duint addr, const char* instruction);
|
||||
SCRIPT_EXPORT bool AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop); //error[MAX_ERROR_SIZE]
|
||||
}; //Assembler
|
||||
}; //Script
|
||||
|
||||
#endif //_SCRIPTAPI_ASSEMBLER_H
|
||||
|
|
@ -1,71 +1,71 @@
|
|||
#include "_scriptapi_debug.h"
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::Wait()
|
||||
{
|
||||
_plugin_waituntilpaused();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::Run()
|
||||
{
|
||||
DbgCmdExecDirect("run");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::Pause()
|
||||
{
|
||||
DbgCmdExecDirect("pause");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::Stop()
|
||||
{
|
||||
DbgCmdExecDirect("StopDebug");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::StepIn()
|
||||
{
|
||||
DbgCmdExecDirect("StepInto");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::StepOver()
|
||||
{
|
||||
DbgCmdExecDirect("StepOver");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::StepOut()
|
||||
{
|
||||
DbgCmdExecDirect("StepOut");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Debug::SetBreakpoint(duint address)
|
||||
{
|
||||
char command[128] = "";
|
||||
sprintf_s(command, "bp %p", address);
|
||||
return DbgCmdExecDirect(command);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Debug::DeleteBreakpoint(duint address)
|
||||
{
|
||||
char command[128] = "";
|
||||
sprintf_s(command, "bc %p", address);
|
||||
return DbgCmdExecDirect(command);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Debug::SetHardwareBreakpoint(duint address, HardwareType type)
|
||||
{
|
||||
char command[128] = "";
|
||||
const char* types[] = { "rw", "w", "x" };
|
||||
sprintf_s(command, "bphws %p, %s", address, types[type]);
|
||||
return DbgCmdExecDirect(command);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Debug::DeleteHardwareBreakpoint(duint address)
|
||||
{
|
||||
char command[128] = "";
|
||||
sprintf_s(command, "bphwc %p", address);
|
||||
return DbgCmdExecDirect(command);
|
||||
#include "_scriptapi_debug.h"
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::Wait()
|
||||
{
|
||||
_plugin_waituntilpaused();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::Run()
|
||||
{
|
||||
DbgCmdExecDirect("run");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::Pause()
|
||||
{
|
||||
DbgCmdExecDirect("pause");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::Stop()
|
||||
{
|
||||
DbgCmdExecDirect("StopDebug");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::StepIn()
|
||||
{
|
||||
DbgCmdExecDirect("StepInto");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::StepOver()
|
||||
{
|
||||
DbgCmdExecDirect("StepOver");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Debug::StepOut()
|
||||
{
|
||||
DbgCmdExecDirect("StepOut");
|
||||
Wait();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Debug::SetBreakpoint(duint address)
|
||||
{
|
||||
char command[128] = "";
|
||||
sprintf_s(command, "bp %p", address);
|
||||
return DbgCmdExecDirect(command);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Debug::DeleteBreakpoint(duint address)
|
||||
{
|
||||
char command[128] = "";
|
||||
sprintf_s(command, "bc %p", address);
|
||||
return DbgCmdExecDirect(command);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Debug::SetHardwareBreakpoint(duint address, HardwareType type)
|
||||
{
|
||||
char command[128] = "";
|
||||
const char* types[] = { "rw", "w", "x" };
|
||||
sprintf_s(command, "bphws %p, %s", address, types[type]);
|
||||
return DbgCmdExecDirect(command);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Debug::DeleteHardwareBreakpoint(duint address)
|
||||
{
|
||||
char command[128] = "";
|
||||
sprintf_s(command, "bphwc %p", address);
|
||||
return DbgCmdExecDirect(command);
|
||||
}
|
||||
|
|
@ -1,31 +1,31 @@
|
|||
#ifndef _SCRIPTAPI_DEBUG_H
|
||||
#define _SCRIPTAPI_DEBUG_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Debug
|
||||
{
|
||||
enum HardwareType
|
||||
{
|
||||
HardwareAccess,
|
||||
HardwareWrite,
|
||||
HardwareExecute
|
||||
};
|
||||
|
||||
SCRIPT_EXPORT void Wait();
|
||||
SCRIPT_EXPORT void Run();
|
||||
SCRIPT_EXPORT void Pause();
|
||||
SCRIPT_EXPORT void Stop();
|
||||
SCRIPT_EXPORT void StepIn();
|
||||
SCRIPT_EXPORT void StepOver();
|
||||
SCRIPT_EXPORT void StepOut();
|
||||
SCRIPT_EXPORT bool SetBreakpoint(duint address);
|
||||
SCRIPT_EXPORT bool DeleteBreakpoint(duint address);
|
||||
SCRIPT_EXPORT bool SetHardwareBreakpoint(duint address, HardwareType type = HardwareExecute);
|
||||
SCRIPT_EXPORT bool DeleteHardwareBreakpoint(duint address);
|
||||
}; //Debug
|
||||
}; //Script
|
||||
|
||||
#ifndef _SCRIPTAPI_DEBUG_H
|
||||
#define _SCRIPTAPI_DEBUG_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Debug
|
||||
{
|
||||
enum HardwareType
|
||||
{
|
||||
HardwareAccess,
|
||||
HardwareWrite,
|
||||
HardwareExecute
|
||||
};
|
||||
|
||||
SCRIPT_EXPORT void Wait();
|
||||
SCRIPT_EXPORT void Run();
|
||||
SCRIPT_EXPORT void Pause();
|
||||
SCRIPT_EXPORT void Stop();
|
||||
SCRIPT_EXPORT void StepIn();
|
||||
SCRIPT_EXPORT void StepOver();
|
||||
SCRIPT_EXPORT void StepOut();
|
||||
SCRIPT_EXPORT bool SetBreakpoint(duint address);
|
||||
SCRIPT_EXPORT bool DeleteBreakpoint(duint address);
|
||||
SCRIPT_EXPORT bool SetHardwareBreakpoint(duint address, HardwareType type = HardwareExecute);
|
||||
SCRIPT_EXPORT bool DeleteHardwareBreakpoint(duint address);
|
||||
}; //Debug
|
||||
}; //Script
|
||||
|
||||
#endif //_SCRIPTAPI_DEBUG_H
|
||||
|
|
@ -1,116 +1,116 @@
|
|||
#include "_scriptapi_flag.h"
|
||||
#include "value.h"
|
||||
|
||||
static const char* flagTable[] =
|
||||
{
|
||||
"ZF",
|
||||
"OF",
|
||||
"CF",
|
||||
"PF",
|
||||
"SF",
|
||||
"TF",
|
||||
"AF",
|
||||
"DF",
|
||||
"IF"
|
||||
};
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::Get(FlagEnum flag)
|
||||
{
|
||||
duint value;
|
||||
return valfromstring(flagTable[flag], &value) ? !!value : false;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::Set(FlagEnum flag, bool value)
|
||||
{
|
||||
return setflag(flagTable[flag], value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetZF()
|
||||
{
|
||||
return Get(ZF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetZF(bool value)
|
||||
{
|
||||
return Set(ZF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetOF()
|
||||
{
|
||||
return Get(OF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetOF(bool value)
|
||||
{
|
||||
return Set(OF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetCF()
|
||||
{
|
||||
return Get(CF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetCF(bool value)
|
||||
{
|
||||
return Set(CF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetPF()
|
||||
{
|
||||
return Get(PF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetPF(bool value)
|
||||
{
|
||||
return Set(PF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetSF()
|
||||
{
|
||||
return Get(SF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetSF(bool value)
|
||||
{
|
||||
return Set(SF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetTF()
|
||||
{
|
||||
return Get(TF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetTF(bool value)
|
||||
{
|
||||
return Set(TF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetAF()
|
||||
{
|
||||
return Get(AF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetAF(bool value)
|
||||
{
|
||||
return Set(AF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetDF()
|
||||
{
|
||||
return Get(DF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetDF(bool value)
|
||||
{
|
||||
return Set(DF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetIF()
|
||||
{
|
||||
return Get(IF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetIF(bool value)
|
||||
{
|
||||
return Set(IF, value);
|
||||
#include "_scriptapi_flag.h"
|
||||
#include "value.h"
|
||||
|
||||
static const char* flagTable[] =
|
||||
{
|
||||
"ZF",
|
||||
"OF",
|
||||
"CF",
|
||||
"PF",
|
||||
"SF",
|
||||
"TF",
|
||||
"AF",
|
||||
"DF",
|
||||
"IF"
|
||||
};
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::Get(FlagEnum flag)
|
||||
{
|
||||
duint value;
|
||||
return valfromstring(flagTable[flag], &value) ? !!value : false;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::Set(FlagEnum flag, bool value)
|
||||
{
|
||||
return setflag(flagTable[flag], value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetZF()
|
||||
{
|
||||
return Get(ZF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetZF(bool value)
|
||||
{
|
||||
return Set(ZF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetOF()
|
||||
{
|
||||
return Get(OF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetOF(bool value)
|
||||
{
|
||||
return Set(OF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetCF()
|
||||
{
|
||||
return Get(CF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetCF(bool value)
|
||||
{
|
||||
return Set(CF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetPF()
|
||||
{
|
||||
return Get(PF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetPF(bool value)
|
||||
{
|
||||
return Set(PF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetSF()
|
||||
{
|
||||
return Get(SF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetSF(bool value)
|
||||
{
|
||||
return Set(SF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetTF()
|
||||
{
|
||||
return Get(TF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetTF(bool value)
|
||||
{
|
||||
return Set(TF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetAF()
|
||||
{
|
||||
return Get(AF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetAF(bool value)
|
||||
{
|
||||
return Set(AF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetDF()
|
||||
{
|
||||
return Get(DF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetDF(bool value)
|
||||
{
|
||||
return Set(DF, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::GetIF()
|
||||
{
|
||||
return Get(IF);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Flag::SetIF(bool value)
|
||||
{
|
||||
return Set(IF, value);
|
||||
}
|
||||
|
|
@ -1,47 +1,47 @@
|
|||
#ifndef _SCRIPTAPI_FLAG_H
|
||||
#define _SCRIPTAPI_FLAG_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Flag
|
||||
{
|
||||
enum FlagEnum
|
||||
{
|
||||
ZF,
|
||||
OF,
|
||||
CF,
|
||||
PF,
|
||||
SF,
|
||||
TF,
|
||||
AF,
|
||||
DF,
|
||||
IF
|
||||
};
|
||||
|
||||
SCRIPT_EXPORT bool Get(FlagEnum flag);
|
||||
SCRIPT_EXPORT bool Set(FlagEnum flag, bool value);
|
||||
|
||||
SCRIPT_EXPORT bool GetZF();
|
||||
SCRIPT_EXPORT bool SetZF(bool value);
|
||||
SCRIPT_EXPORT bool GetOF();
|
||||
SCRIPT_EXPORT bool SetOF(bool value);
|
||||
SCRIPT_EXPORT bool GetCF();
|
||||
SCRIPT_EXPORT bool SetCF(bool value);
|
||||
SCRIPT_EXPORT bool GetPF();
|
||||
SCRIPT_EXPORT bool SetPF(bool value);
|
||||
SCRIPT_EXPORT bool GetSF();
|
||||
SCRIPT_EXPORT bool SetSF(bool value);
|
||||
SCRIPT_EXPORT bool GetTF();
|
||||
SCRIPT_EXPORT bool SetTF(bool value);
|
||||
SCRIPT_EXPORT bool GetAF();
|
||||
SCRIPT_EXPORT bool SetAF(bool value);
|
||||
SCRIPT_EXPORT bool GetDF();
|
||||
SCRIPT_EXPORT bool SetDF(bool value);
|
||||
SCRIPT_EXPORT bool GetIF();
|
||||
SCRIPT_EXPORT bool SetIF(bool value);
|
||||
};
|
||||
};
|
||||
|
||||
#ifndef _SCRIPTAPI_FLAG_H
|
||||
#define _SCRIPTAPI_FLAG_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Flag
|
||||
{
|
||||
enum FlagEnum
|
||||
{
|
||||
ZF,
|
||||
OF,
|
||||
CF,
|
||||
PF,
|
||||
SF,
|
||||
TF,
|
||||
AF,
|
||||
DF,
|
||||
IF
|
||||
};
|
||||
|
||||
SCRIPT_EXPORT bool Get(FlagEnum flag);
|
||||
SCRIPT_EXPORT bool Set(FlagEnum flag, bool value);
|
||||
|
||||
SCRIPT_EXPORT bool GetZF();
|
||||
SCRIPT_EXPORT bool SetZF(bool value);
|
||||
SCRIPT_EXPORT bool GetOF();
|
||||
SCRIPT_EXPORT bool SetOF(bool value);
|
||||
SCRIPT_EXPORT bool GetCF();
|
||||
SCRIPT_EXPORT bool SetCF(bool value);
|
||||
SCRIPT_EXPORT bool GetPF();
|
||||
SCRIPT_EXPORT bool SetPF(bool value);
|
||||
SCRIPT_EXPORT bool GetSF();
|
||||
SCRIPT_EXPORT bool SetSF(bool value);
|
||||
SCRIPT_EXPORT bool GetTF();
|
||||
SCRIPT_EXPORT bool SetTF(bool value);
|
||||
SCRIPT_EXPORT bool GetAF();
|
||||
SCRIPT_EXPORT bool SetAF(bool value);
|
||||
SCRIPT_EXPORT bool GetDF();
|
||||
SCRIPT_EXPORT bool SetDF(bool value);
|
||||
SCRIPT_EXPORT bool GetIF();
|
||||
SCRIPT_EXPORT bool SetIF(bool value);
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_SCRIPTAPI_FLAG_H
|
||||
|
|
@ -1,152 +1,152 @@
|
|||
#include "_scriptapi_gui.h"
|
||||
#include "_scriptapi_misc.h"
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionGet(duint* start, duint* end)
|
||||
{
|
||||
return Gui::SelectionGet(DisassemblyWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionSet(duint start, duint end)
|
||||
{
|
||||
return Gui::SelectionSet(DisassemblyWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Disassembly::SelectionGetStart()
|
||||
{
|
||||
return Gui::SelectionGetStart(DisassemblyWindow);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Disassembly::SelectionGetEnd()
|
||||
{
|
||||
return Gui::SelectionGetEnd(DisassemblyWindow);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Dump::SelectionGet(duint* start, duint* end)
|
||||
{
|
||||
return Gui::SelectionGet(DumpWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Dump::SelectionSet(duint start, duint end)
|
||||
{
|
||||
return Gui::SelectionSet(DumpWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Dump::SelectionGetStart()
|
||||
{
|
||||
return Gui::SelectionGetStart(DumpWindow);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Dump::SelectionGetEnd()
|
||||
{
|
||||
return Gui::SelectionGetEnd(DumpWindow);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Stack::SelectionGet(duint* start, duint* end)
|
||||
{
|
||||
return Gui::SelectionGet(StackWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Stack::SelectionSet(duint start, duint end)
|
||||
{
|
||||
return Gui::SelectionSet(StackWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetStart()
|
||||
{
|
||||
return Gui::SelectionGetStart(StackWindow);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetEnd()
|
||||
{
|
||||
return Gui::SelectionGetEnd(StackWindow);
|
||||
}
|
||||
|
||||
static inline int windowToBridge(Script::Gui::Window window)
|
||||
{
|
||||
switch(window)
|
||||
{
|
||||
case Script::Gui::DisassemblyWindow:
|
||||
return GUI_DISASSEMBLY;
|
||||
case Script::Gui::DumpWindow:
|
||||
return GUI_DUMP;
|
||||
case Script::Gui::StackWindow:
|
||||
return GUI_STACK;
|
||||
default:
|
||||
return GUI_DISASSEMBLY;
|
||||
}
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::SelectionGet(Script::Gui::Window window, duint* start, duint* end)
|
||||
{
|
||||
SELECTIONDATA selection;
|
||||
if(!GuiSelectionGet(windowToBridge(window), &selection))
|
||||
return false;
|
||||
if(start)
|
||||
*start = selection.start;
|
||||
if(end)
|
||||
*end = selection.end;
|
||||
return true;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::SelectionSet(Script::Gui::Window window, duint start, duint end)
|
||||
{
|
||||
SELECTIONDATA selection;
|
||||
selection.start = start;
|
||||
selection.end = end;
|
||||
return GuiSelectionSet(windowToBridge(window), &selection);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::SelectionGetStart(Script::Gui::Window window)
|
||||
{
|
||||
duint start;
|
||||
return Gui::SelectionGet(window, &start, nullptr) ? start : 0;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::SelectionGetEnd(Script::Gui::Window window)
|
||||
{
|
||||
duint end;
|
||||
return Gui::SelectionGet(window, nullptr, &end) ? end : 0;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Gui::Message(const char* message)
|
||||
{
|
||||
GuiScriptMessage(message);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::MessageYesNo(const char* message)
|
||||
{
|
||||
return !!GuiScriptMsgyn(message);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::InputLine(const char* title, char* text)
|
||||
{
|
||||
return GuiGetLineWindow(title, text);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::InputValue(const char* title, duint* value)
|
||||
{
|
||||
Memory<char*> line(GUI_MAX_LINE_SIZE);
|
||||
if(!GuiGetLineWindow(title, line()))
|
||||
return false;
|
||||
return Misc::ParseExpression(line(), value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Gui::Refresh()
|
||||
{
|
||||
GuiUpdateAllViews();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Gui::AddQWidgetTab(void* qWidget)
|
||||
{
|
||||
GuiAddQWidgetTab(qWidget);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Gui::ShowQWidgetTab(void* qWidget)
|
||||
{
|
||||
GuiShowQWidgetTab(qWidget);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Gui::CloseQWidgetTab(void* qWidget)
|
||||
{
|
||||
GuiCloseQWidgetTab(qWidget);
|
||||
#include "_scriptapi_gui.h"
|
||||
#include "_scriptapi_misc.h"
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionGet(duint* start, duint* end)
|
||||
{
|
||||
return Gui::SelectionGet(DisassemblyWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionSet(duint start, duint end)
|
||||
{
|
||||
return Gui::SelectionSet(DisassemblyWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Disassembly::SelectionGetStart()
|
||||
{
|
||||
return Gui::SelectionGetStart(DisassemblyWindow);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Disassembly::SelectionGetEnd()
|
||||
{
|
||||
return Gui::SelectionGetEnd(DisassemblyWindow);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Dump::SelectionGet(duint* start, duint* end)
|
||||
{
|
||||
return Gui::SelectionGet(DumpWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Dump::SelectionSet(duint start, duint end)
|
||||
{
|
||||
return Gui::SelectionSet(DumpWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Dump::SelectionGetStart()
|
||||
{
|
||||
return Gui::SelectionGetStart(DumpWindow);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Dump::SelectionGetEnd()
|
||||
{
|
||||
return Gui::SelectionGetEnd(DumpWindow);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Stack::SelectionGet(duint* start, duint* end)
|
||||
{
|
||||
return Gui::SelectionGet(StackWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::Stack::SelectionSet(duint start, duint end)
|
||||
{
|
||||
return Gui::SelectionSet(StackWindow, start, end);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetStart()
|
||||
{
|
||||
return Gui::SelectionGetStart(StackWindow);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetEnd()
|
||||
{
|
||||
return Gui::SelectionGetEnd(StackWindow);
|
||||
}
|
||||
|
||||
static inline int windowToBridge(Script::Gui::Window window)
|
||||
{
|
||||
switch(window)
|
||||
{
|
||||
case Script::Gui::DisassemblyWindow:
|
||||
return GUI_DISASSEMBLY;
|
||||
case Script::Gui::DumpWindow:
|
||||
return GUI_DUMP;
|
||||
case Script::Gui::StackWindow:
|
||||
return GUI_STACK;
|
||||
default:
|
||||
return GUI_DISASSEMBLY;
|
||||
}
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::SelectionGet(Script::Gui::Window window, duint* start, duint* end)
|
||||
{
|
||||
SELECTIONDATA selection;
|
||||
if(!GuiSelectionGet(windowToBridge(window), &selection))
|
||||
return false;
|
||||
if(start)
|
||||
*start = selection.start;
|
||||
if(end)
|
||||
*end = selection.end;
|
||||
return true;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::SelectionSet(Script::Gui::Window window, duint start, duint end)
|
||||
{
|
||||
SELECTIONDATA selection;
|
||||
selection.start = start;
|
||||
selection.end = end;
|
||||
return GuiSelectionSet(windowToBridge(window), &selection);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::SelectionGetStart(Script::Gui::Window window)
|
||||
{
|
||||
duint start;
|
||||
return Gui::SelectionGet(window, &start, nullptr) ? start : 0;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Gui::SelectionGetEnd(Script::Gui::Window window)
|
||||
{
|
||||
duint end;
|
||||
return Gui::SelectionGet(window, nullptr, &end) ? end : 0;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Gui::Message(const char* message)
|
||||
{
|
||||
GuiScriptMessage(message);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::MessageYesNo(const char* message)
|
||||
{
|
||||
return !!GuiScriptMsgyn(message);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::InputLine(const char* title, char* text)
|
||||
{
|
||||
return GuiGetLineWindow(title, text);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Gui::InputValue(const char* title, duint* value)
|
||||
{
|
||||
Memory<char*> line(GUI_MAX_LINE_SIZE);
|
||||
if(!GuiGetLineWindow(title, line()))
|
||||
return false;
|
||||
return Misc::ParseExpression(line(), value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Gui::Refresh()
|
||||
{
|
||||
GuiUpdateAllViews();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Gui::AddQWidgetTab(void* qWidget)
|
||||
{
|
||||
GuiAddQWidgetTab(qWidget);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Gui::ShowQWidgetTab(void* qWidget)
|
||||
{
|
||||
GuiShowQWidgetTab(qWidget);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Gui::CloseQWidgetTab(void* qWidget)
|
||||
{
|
||||
GuiCloseQWidgetTab(qWidget);
|
||||
}
|
||||
|
|
@ -1,60 +1,60 @@
|
|||
#ifndef _SCRIPTAPI_GUI_H
|
||||
#define _SCRIPTAPI_GUI_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Gui
|
||||
{
|
||||
namespace Disassembly
|
||||
{
|
||||
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
|
||||
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
|
||||
SCRIPT_EXPORT duint SelectionGetStart();
|
||||
SCRIPT_EXPORT duint SelectionGetEnd();
|
||||
}; //Disassembly
|
||||
|
||||
namespace Dump
|
||||
{
|
||||
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
|
||||
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
|
||||
SCRIPT_EXPORT duint SelectionGetStart();
|
||||
SCRIPT_EXPORT duint SelectionGetEnd();
|
||||
}; //Dump
|
||||
|
||||
namespace Stack
|
||||
{
|
||||
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
|
||||
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
|
||||
SCRIPT_EXPORT duint SelectionGetStart();
|
||||
SCRIPT_EXPORT duint SelectionGetEnd();
|
||||
}; //Stack
|
||||
}; //Gui
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
enum Window
|
||||
{
|
||||
DisassemblyWindow,
|
||||
DumpWindow,
|
||||
StackWindow
|
||||
};
|
||||
|
||||
SCRIPT_EXPORT bool SelectionGet(Window window, duint* start, duint* end);
|
||||
SCRIPT_EXPORT bool SelectionSet(Window window, duint start, duint end);
|
||||
SCRIPT_EXPORT duint SelectionGetStart(Window window);
|
||||
SCRIPT_EXPORT duint SelectionGetEnd(Window window);
|
||||
SCRIPT_EXPORT void Message(const char* message);
|
||||
SCRIPT_EXPORT bool MessageYesNo(const char* message);
|
||||
SCRIPT_EXPORT bool InputLine(const char* title, char* text); //text[GUI_MAX_LINE_SIZE]
|
||||
SCRIPT_EXPORT bool InputValue(const char* title, duint* value);
|
||||
SCRIPT_EXPORT void Refresh();
|
||||
SCRIPT_EXPORT void AddQWidgetTab(void* qWidget);
|
||||
SCRIPT_EXPORT void ShowQWidgetTab(void* qWidget);
|
||||
SCRIPT_EXPORT void CloseQWidgetTab(void* qWidget);
|
||||
|
||||
}; //Gui
|
||||
}; //Script
|
||||
|
||||
#ifndef _SCRIPTAPI_GUI_H
|
||||
#define _SCRIPTAPI_GUI_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Gui
|
||||
{
|
||||
namespace Disassembly
|
||||
{
|
||||
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
|
||||
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
|
||||
SCRIPT_EXPORT duint SelectionGetStart();
|
||||
SCRIPT_EXPORT duint SelectionGetEnd();
|
||||
}; //Disassembly
|
||||
|
||||
namespace Dump
|
||||
{
|
||||
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
|
||||
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
|
||||
SCRIPT_EXPORT duint SelectionGetStart();
|
||||
SCRIPT_EXPORT duint SelectionGetEnd();
|
||||
}; //Dump
|
||||
|
||||
namespace Stack
|
||||
{
|
||||
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
|
||||
SCRIPT_EXPORT bool SelectionSet(duint start, duint end);
|
||||
SCRIPT_EXPORT duint SelectionGetStart();
|
||||
SCRIPT_EXPORT duint SelectionGetEnd();
|
||||
}; //Stack
|
||||
}; //Gui
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
enum Window
|
||||
{
|
||||
DisassemblyWindow,
|
||||
DumpWindow,
|
||||
StackWindow
|
||||
};
|
||||
|
||||
SCRIPT_EXPORT bool SelectionGet(Window window, duint* start, duint* end);
|
||||
SCRIPT_EXPORT bool SelectionSet(Window window, duint start, duint end);
|
||||
SCRIPT_EXPORT duint SelectionGetStart(Window window);
|
||||
SCRIPT_EXPORT duint SelectionGetEnd(Window window);
|
||||
SCRIPT_EXPORT void Message(const char* message);
|
||||
SCRIPT_EXPORT bool MessageYesNo(const char* message);
|
||||
SCRIPT_EXPORT bool InputLine(const char* title, char* text); //text[GUI_MAX_LINE_SIZE]
|
||||
SCRIPT_EXPORT bool InputValue(const char* title, duint* value);
|
||||
SCRIPT_EXPORT void Refresh();
|
||||
SCRIPT_EXPORT void AddQWidgetTab(void* qWidget);
|
||||
SCRIPT_EXPORT void ShowQWidgetTab(void* qWidget);
|
||||
SCRIPT_EXPORT void CloseQWidgetTab(void* qWidget);
|
||||
|
||||
}; //Gui
|
||||
}; //Script
|
||||
|
||||
#endif //_SCRIPTAPI_GUI_H
|
||||
|
|
@ -1,89 +1,89 @@
|
|||
#include "_scriptapi_memory.h"
|
||||
#include "memory.h"
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::Read(duint addr, void* data, duint size, duint* sizeRead)
|
||||
{
|
||||
return MemRead(addr, data, size, sizeRead);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::Write(duint addr, const void* data, duint size, duint* sizeWritten)
|
||||
{
|
||||
return MemWrite(addr, (void*)data, size, sizeWritten);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::IsValidPtr(duint addr)
|
||||
{
|
||||
return MemIsValidReadPtr(addr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Memory::RemoteAlloc(duint addr, duint size)
|
||||
{
|
||||
return (duint)MemAllocRemote(addr, size);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::RemoteFree(duint addr)
|
||||
{
|
||||
return MemFreeRemote(addr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT unsigned char Script::Memory::ReadByte(duint addr)
|
||||
{
|
||||
unsigned char data;
|
||||
Read(addr, &data, sizeof(data), nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::WriteByte(duint addr, unsigned char data)
|
||||
{
|
||||
return Write(addr, &data, sizeof(data), nullptr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT unsigned short Script::Memory::ReadWord(duint addr)
|
||||
{
|
||||
unsigned short data;
|
||||
Read(addr, &data, sizeof(data), nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::WriteWord(duint addr, unsigned short data)
|
||||
{
|
||||
return Write(addr, &data, sizeof(data), nullptr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT unsigned int Script::Memory::ReadDword(duint addr)
|
||||
{
|
||||
unsigned int data;
|
||||
Read(addr, &data, sizeof(data), nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::WriteDword(duint addr, unsigned int data)
|
||||
{
|
||||
return Write(addr, &data, sizeof(data), nullptr);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
SCRIPT_EXPORT unsigned long long Script::Memory::ReadQword(duint addr)
|
||||
{
|
||||
unsigned long long data;
|
||||
Read(addr, &data, sizeof(data), nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::WriteQword(duint addr, unsigned long long data)
|
||||
{
|
||||
return Write(addr, &data, sizeof(data), nullptr);
|
||||
}
|
||||
#endif //_WIN64
|
||||
|
||||
SCRIPT_EXPORT duint Script::Memory::ReadPtr(duint addr)
|
||||
{
|
||||
duint data;
|
||||
Read(addr, &data, sizeof(data), nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::WritePtr(duint addr, duint data)
|
||||
{
|
||||
return Write(addr, &data, sizeof(data), nullptr);
|
||||
#include "_scriptapi_memory.h"
|
||||
#include "memory.h"
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::Read(duint addr, void* data, duint size, duint* sizeRead)
|
||||
{
|
||||
return MemRead(addr, data, size, sizeRead);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::Write(duint addr, const void* data, duint size, duint* sizeWritten)
|
||||
{
|
||||
return MemWrite(addr, (void*)data, size, sizeWritten);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::IsValidPtr(duint addr)
|
||||
{
|
||||
return MemIsValidReadPtr(addr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Memory::RemoteAlloc(duint addr, duint size)
|
||||
{
|
||||
return (duint)MemAllocRemote(addr, size);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::RemoteFree(duint addr)
|
||||
{
|
||||
return MemFreeRemote(addr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT unsigned char Script::Memory::ReadByte(duint addr)
|
||||
{
|
||||
unsigned char data;
|
||||
Read(addr, &data, sizeof(data), nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::WriteByte(duint addr, unsigned char data)
|
||||
{
|
||||
return Write(addr, &data, sizeof(data), nullptr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT unsigned short Script::Memory::ReadWord(duint addr)
|
||||
{
|
||||
unsigned short data;
|
||||
Read(addr, &data, sizeof(data), nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::WriteWord(duint addr, unsigned short data)
|
||||
{
|
||||
return Write(addr, &data, sizeof(data), nullptr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT unsigned int Script::Memory::ReadDword(duint addr)
|
||||
{
|
||||
unsigned int data;
|
||||
Read(addr, &data, sizeof(data), nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::WriteDword(duint addr, unsigned int data)
|
||||
{
|
||||
return Write(addr, &data, sizeof(data), nullptr);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
SCRIPT_EXPORT unsigned long long Script::Memory::ReadQword(duint addr)
|
||||
{
|
||||
unsigned long long data;
|
||||
Read(addr, &data, sizeof(data), nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::WriteQword(duint addr, unsigned long long data)
|
||||
{
|
||||
return Write(addr, &data, sizeof(data), nullptr);
|
||||
}
|
||||
#endif //_WIN64
|
||||
|
||||
SCRIPT_EXPORT duint Script::Memory::ReadPtr(duint addr)
|
||||
{
|
||||
duint data;
|
||||
Read(addr, &data, sizeof(data), nullptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Memory::WritePtr(duint addr, duint data)
|
||||
{
|
||||
return Write(addr, &data, sizeof(data), nullptr);
|
||||
}
|
||||
|
|
@ -1,31 +1,31 @@
|
|||
#ifndef _SCRIPTAPI_MEMORY_H
|
||||
#define _SCRIPTAPI_MEMORY_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Memory
|
||||
{
|
||||
SCRIPT_EXPORT bool Read(duint addr, void* data, duint size, duint* sizeRead);
|
||||
SCRIPT_EXPORT bool Write(duint addr, const void* data, duint size, duint* sizeWritten);
|
||||
SCRIPT_EXPORT bool IsValidPtr(duint addr);
|
||||
SCRIPT_EXPORT duint RemoteAlloc(duint addr, duint size);
|
||||
SCRIPT_EXPORT bool RemoteFree(duint addr);
|
||||
|
||||
SCRIPT_EXPORT unsigned char ReadByte(duint addr);
|
||||
SCRIPT_EXPORT bool WriteByte(duint addr, unsigned char data);
|
||||
SCRIPT_EXPORT unsigned short ReadWord(duint addr);
|
||||
SCRIPT_EXPORT bool WriteWord(duint addr, unsigned short data);
|
||||
SCRIPT_EXPORT unsigned int ReadDword(duint addr);
|
||||
SCRIPT_EXPORT bool WriteDword(duint addr, unsigned int data);
|
||||
#ifdef _WIN64
|
||||
SCRIPT_EXPORT unsigned long long ReadQword(duint addr);
|
||||
SCRIPT_EXPORT bool WriteQword(duint addr, unsigned long long data);
|
||||
#endif //_WIN64
|
||||
SCRIPT_EXPORT duint ReadPtr(duint addr);
|
||||
SCRIPT_EXPORT bool WritePtr(duint addr, duint data);
|
||||
}; //Memory
|
||||
}; //Script
|
||||
|
||||
#ifndef _SCRIPTAPI_MEMORY_H
|
||||
#define _SCRIPTAPI_MEMORY_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Memory
|
||||
{
|
||||
SCRIPT_EXPORT bool Read(duint addr, void* data, duint size, duint* sizeRead);
|
||||
SCRIPT_EXPORT bool Write(duint addr, const void* data, duint size, duint* sizeWritten);
|
||||
SCRIPT_EXPORT bool IsValidPtr(duint addr);
|
||||
SCRIPT_EXPORT duint RemoteAlloc(duint addr, duint size);
|
||||
SCRIPT_EXPORT bool RemoteFree(duint addr);
|
||||
|
||||
SCRIPT_EXPORT unsigned char ReadByte(duint addr);
|
||||
SCRIPT_EXPORT bool WriteByte(duint addr, unsigned char data);
|
||||
SCRIPT_EXPORT unsigned short ReadWord(duint addr);
|
||||
SCRIPT_EXPORT bool WriteWord(duint addr, unsigned short data);
|
||||
SCRIPT_EXPORT unsigned int ReadDword(duint addr);
|
||||
SCRIPT_EXPORT bool WriteDword(duint addr, unsigned int data);
|
||||
#ifdef _WIN64
|
||||
SCRIPT_EXPORT unsigned long long ReadQword(duint addr);
|
||||
SCRIPT_EXPORT bool WriteQword(duint addr, unsigned long long data);
|
||||
#endif //_WIN64
|
||||
SCRIPT_EXPORT duint ReadPtr(duint addr);
|
||||
SCRIPT_EXPORT bool WritePtr(duint addr, duint data);
|
||||
}; //Memory
|
||||
}; //Script
|
||||
|
||||
#endif //_SCRIPTAPI_MEMORY_H
|
||||
|
|
@ -1,33 +1,33 @@
|
|||
#include "_scriptapi_misc.h"
|
||||
#include "value.h"
|
||||
|
||||
SCRIPT_EXPORT bool Script::Misc::ParseExpression(const char* expression, duint* value)
|
||||
{
|
||||
return valfromstring(expression, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Misc::RemoteGetProcAddress(const char* module, const char* api)
|
||||
{
|
||||
duint value;
|
||||
if(!ParseExpression(StringUtils::sprintf("%s:%s", module, api).c_str(), &value))
|
||||
return 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Misc::ResolveLabel(const char* label)
|
||||
{
|
||||
duint value;
|
||||
if(!ParseExpression(label, &value))
|
||||
return 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void* Script::Misc::Alloc(duint size)
|
||||
{
|
||||
return BridgeAlloc(size);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Misc::Free(void* ptr)
|
||||
{
|
||||
return BridgeFree(ptr);
|
||||
#include "_scriptapi_misc.h"
|
||||
#include "value.h"
|
||||
|
||||
SCRIPT_EXPORT bool Script::Misc::ParseExpression(const char* expression, duint* value)
|
||||
{
|
||||
return valfromstring(expression, value);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Misc::RemoteGetProcAddress(const char* module, const char* api)
|
||||
{
|
||||
duint value;
|
||||
if(!ParseExpression(StringUtils::sprintf("%s:%s", module, api).c_str(), &value))
|
||||
return 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Misc::ResolveLabel(const char* label)
|
||||
{
|
||||
duint value;
|
||||
if(!ParseExpression(label, &value))
|
||||
return 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void* Script::Misc::Alloc(duint size)
|
||||
{
|
||||
return BridgeAlloc(size);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Misc::Free(void* ptr)
|
||||
{
|
||||
return BridgeFree(ptr);
|
||||
}
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
#ifndef _SCRIPTAPI_MISC_H
|
||||
#define _SCRIPTAPI_MISC_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Misc
|
||||
{
|
||||
SCRIPT_EXPORT bool ParseExpression(const char* expression, duint* value);
|
||||
SCRIPT_EXPORT duint RemoteGetProcAddress(const char* module, const char* api);
|
||||
SCRIPT_EXPORT duint ResolveLabel(const char* label);
|
||||
SCRIPT_EXPORT void* Alloc(duint size);
|
||||
SCRIPT_EXPORT void Free(void* ptr);
|
||||
}; //Misc
|
||||
}; //Script
|
||||
|
||||
#ifndef _SCRIPTAPI_MISC_H
|
||||
#define _SCRIPTAPI_MISC_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Misc
|
||||
{
|
||||
SCRIPT_EXPORT bool ParseExpression(const char* expression, duint* value);
|
||||
SCRIPT_EXPORT duint RemoteGetProcAddress(const char* module, const char* api);
|
||||
SCRIPT_EXPORT duint ResolveLabel(const char* label);
|
||||
SCRIPT_EXPORT void* Alloc(duint size);
|
||||
SCRIPT_EXPORT void Free(void* ptr);
|
||||
}; //Misc
|
||||
}; //Script
|
||||
|
||||
#endif //_SCRIPTAPI_MISC_H
|
||||
|
|
@ -1,185 +1,185 @@
|
|||
#include "_scriptapi_module.h"
|
||||
#include "threading.h"
|
||||
#include "module.h"
|
||||
#include "debugger.h"
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::InfoFromAddr(duint addr, Script::Module::ModuleInfo* info)
|
||||
{
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
MODINFO* modInfo = ModInfoFromAddr(addr);
|
||||
if(!info || !modInfo)
|
||||
return false;
|
||||
info->base = modInfo->base;
|
||||
info->size = modInfo->size;
|
||||
info->entry = modInfo->entry;
|
||||
info->sectionCount = int(modInfo->sections.size());
|
||||
strcpy_s(info->name, modInfo->name);
|
||||
strcat_s(info->name, modInfo->extension);
|
||||
strcpy_s(info->path, modInfo->path);
|
||||
return true;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::InfoFromName(const char* name, Script::Module::ModuleInfo* info)
|
||||
{
|
||||
return Module::InfoFromAddr(Module::BaseFromName(name), info);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::BaseFromAddr(duint addr)
|
||||
{
|
||||
return ModBaseFromAddr(addr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::BaseFromName(const char* name)
|
||||
{
|
||||
return ModBaseFromName(name);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::SizeFromAddr(duint addr)
|
||||
{
|
||||
return ModSizeFromAddr(addr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::SizeFromName(const char* name)
|
||||
{
|
||||
return Module::SizeFromAddr(Module::BaseFromName(name));
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::NameFromAddr(duint addr, char* name)
|
||||
{
|
||||
return ModNameFromAddr(addr, name, true);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::PathFromAddr(duint addr, char* path)
|
||||
{
|
||||
return !!ModPathFromAddr(addr, path, MAX_PATH);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::PathFromName(const char* name, char* path)
|
||||
{
|
||||
return Module::PathFromAddr(Module::BaseFromName(name), path);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::EntryFromAddr(duint addr)
|
||||
{
|
||||
return ModEntryFromAddr(addr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::EntryFromName(const char* name)
|
||||
{
|
||||
return Module::EntryFromAddr(Module::BaseFromName(name));
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT int Script::Module::SectionCountFromAddr(duint addr)
|
||||
{
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
MODINFO* modInfo = ModInfoFromAddr(addr);
|
||||
return modInfo ? int(modInfo->sections.size()) : 0;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT int Script::Module::SectionCountFromName(const char* name)
|
||||
{
|
||||
return Module::SectionCountFromAddr(Module::BaseFromName(name));
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::SectionFromAddr(duint addr, int number, ModuleSectionInfo* section)
|
||||
{
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
MODINFO* modInfo = ModInfoFromAddr(addr);
|
||||
if(!section || !modInfo || number < 0 || number >= int(modInfo->sections.size()))
|
||||
return false;
|
||||
const MODSECTIONINFO & secInfo = modInfo->sections.at(number);
|
||||
section->addr = secInfo.addr;
|
||||
section->size = secInfo.size;
|
||||
strcpy_s(section->name, secInfo.name);
|
||||
return true;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::SectionFromName(const char* name, int number, ModuleSectionInfo* section)
|
||||
{
|
||||
return Module::SectionFromAddr(Module::BaseFromName(name), number, section);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::SectionListFromAddr(duint addr, ListOf(ModuleSectionInfo) listInfo)
|
||||
{
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
MODINFO* modInfo = ModInfoFromAddr(addr);
|
||||
if(!modInfo)
|
||||
return false;
|
||||
std::vector<ModuleSectionInfo> scriptSectionList;
|
||||
scriptSectionList.reserve(modInfo->sections.size());
|
||||
for(const auto & section : modInfo->sections)
|
||||
{
|
||||
ModuleSectionInfo scriptSection;
|
||||
scriptSection.addr = section.addr;
|
||||
scriptSection.size = section.size;
|
||||
strcpy_s(scriptSection.name, section.name);
|
||||
scriptSectionList.push_back(scriptSection);
|
||||
}
|
||||
return List<ModuleSectionInfo>::CopyData(listInfo, scriptSectionList);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::SectionListFromName(const char* name, ListOf(ModuleSectionInfo) listInfo)
|
||||
{
|
||||
return Module::SectionListFromAddr(Module::BaseFromName(name), listInfo);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::GetMainModuleInfo(ModuleInfo* info)
|
||||
{
|
||||
return Module::InfoFromAddr(Module::GetMainModuleBase(), info);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::GetMainModuleBase()
|
||||
{
|
||||
return dbggetdebuggedbase();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::GetMainModuleSize()
|
||||
{
|
||||
return Module::SizeFromAddr(Module::GetMainModuleBase());
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::GetMainModuleEntry()
|
||||
{
|
||||
return Module::EntryFromAddr(Module::GetMainModuleBase());
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT int Script::Module::GetMainModuleSectionCount()
|
||||
{
|
||||
return Module::SectionCountFromAddr(Module::GetMainModuleBase());
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::GetMainModuleName(char* name)
|
||||
{
|
||||
return Module::NameFromAddr(Module::GetMainModuleBase(), name);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::GetMainModulePath(char* path)
|
||||
{
|
||||
return Module::PathFromAddr(Module::GetMainModuleBase(), path);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::GetMainModuleSectionList(ListOf(ModuleSectionInfo) listInfo)
|
||||
{
|
||||
return Module::SectionListFromAddr(Module::GetMainModuleBase(), listInfo);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::GetList(ListOf(ModuleInfo) listInfo)
|
||||
{
|
||||
std::vector<MODINFO> modList;
|
||||
ModGetList(modList);
|
||||
std::vector<ModuleInfo> modScriptList;
|
||||
modScriptList.reserve(modList.size());
|
||||
for(const auto & mod : modList)
|
||||
{
|
||||
ModuleInfo scriptMod;
|
||||
scriptMod.base = mod.base;
|
||||
scriptMod.size = mod.size;
|
||||
scriptMod.entry = mod.entry;
|
||||
scriptMod.sectionCount = int(mod.sections.size());
|
||||
strcpy_s(scriptMod.name, mod.name);
|
||||
strcat_s(scriptMod.name, mod.extension);
|
||||
strcpy_s(scriptMod.path, mod.path);
|
||||
modScriptList.push_back(scriptMod);
|
||||
}
|
||||
return List<ModuleInfo>::CopyData(listInfo, modScriptList);
|
||||
#include "_scriptapi_module.h"
|
||||
#include "threading.h"
|
||||
#include "module.h"
|
||||
#include "debugger.h"
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::InfoFromAddr(duint addr, Script::Module::ModuleInfo* info)
|
||||
{
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
MODINFO* modInfo = ModInfoFromAddr(addr);
|
||||
if(!info || !modInfo)
|
||||
return false;
|
||||
info->base = modInfo->base;
|
||||
info->size = modInfo->size;
|
||||
info->entry = modInfo->entry;
|
||||
info->sectionCount = int(modInfo->sections.size());
|
||||
strcpy_s(info->name, modInfo->name);
|
||||
strcat_s(info->name, modInfo->extension);
|
||||
strcpy_s(info->path, modInfo->path);
|
||||
return true;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::InfoFromName(const char* name, Script::Module::ModuleInfo* info)
|
||||
{
|
||||
return Module::InfoFromAddr(Module::BaseFromName(name), info);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::BaseFromAddr(duint addr)
|
||||
{
|
||||
return ModBaseFromAddr(addr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::BaseFromName(const char* name)
|
||||
{
|
||||
return ModBaseFromName(name);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::SizeFromAddr(duint addr)
|
||||
{
|
||||
return ModSizeFromAddr(addr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::SizeFromName(const char* name)
|
||||
{
|
||||
return Module::SizeFromAddr(Module::BaseFromName(name));
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::NameFromAddr(duint addr, char* name)
|
||||
{
|
||||
return ModNameFromAddr(addr, name, true);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::PathFromAddr(duint addr, char* path)
|
||||
{
|
||||
return !!ModPathFromAddr(addr, path, MAX_PATH);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::PathFromName(const char* name, char* path)
|
||||
{
|
||||
return Module::PathFromAddr(Module::BaseFromName(name), path);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::EntryFromAddr(duint addr)
|
||||
{
|
||||
return ModEntryFromAddr(addr);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::EntryFromName(const char* name)
|
||||
{
|
||||
return Module::EntryFromAddr(Module::BaseFromName(name));
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT int Script::Module::SectionCountFromAddr(duint addr)
|
||||
{
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
MODINFO* modInfo = ModInfoFromAddr(addr);
|
||||
return modInfo ? int(modInfo->sections.size()) : 0;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT int Script::Module::SectionCountFromName(const char* name)
|
||||
{
|
||||
return Module::SectionCountFromAddr(Module::BaseFromName(name));
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::SectionFromAddr(duint addr, int number, ModuleSectionInfo* section)
|
||||
{
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
MODINFO* modInfo = ModInfoFromAddr(addr);
|
||||
if(!section || !modInfo || number < 0 || number >= int(modInfo->sections.size()))
|
||||
return false;
|
||||
const MODSECTIONINFO & secInfo = modInfo->sections.at(number);
|
||||
section->addr = secInfo.addr;
|
||||
section->size = secInfo.size;
|
||||
strcpy_s(section->name, secInfo.name);
|
||||
return true;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::SectionFromName(const char* name, int number, ModuleSectionInfo* section)
|
||||
{
|
||||
return Module::SectionFromAddr(Module::BaseFromName(name), number, section);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::SectionListFromAddr(duint addr, ListOf(ModuleSectionInfo) listInfo)
|
||||
{
|
||||
SHARED_ACQUIRE(LockModules);
|
||||
MODINFO* modInfo = ModInfoFromAddr(addr);
|
||||
if(!modInfo)
|
||||
return false;
|
||||
std::vector<ModuleSectionInfo> scriptSectionList;
|
||||
scriptSectionList.reserve(modInfo->sections.size());
|
||||
for(const auto & section : modInfo->sections)
|
||||
{
|
||||
ModuleSectionInfo scriptSection;
|
||||
scriptSection.addr = section.addr;
|
||||
scriptSection.size = section.size;
|
||||
strcpy_s(scriptSection.name, section.name);
|
||||
scriptSectionList.push_back(scriptSection);
|
||||
}
|
||||
return List<ModuleSectionInfo>::CopyData(listInfo, scriptSectionList);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::SectionListFromName(const char* name, ListOf(ModuleSectionInfo) listInfo)
|
||||
{
|
||||
return Module::SectionListFromAddr(Module::BaseFromName(name), listInfo);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::GetMainModuleInfo(ModuleInfo* info)
|
||||
{
|
||||
return Module::InfoFromAddr(Module::GetMainModuleBase(), info);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::GetMainModuleBase()
|
||||
{
|
||||
return dbggetdebuggedbase();
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::GetMainModuleSize()
|
||||
{
|
||||
return Module::SizeFromAddr(Module::GetMainModuleBase());
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Module::GetMainModuleEntry()
|
||||
{
|
||||
return Module::EntryFromAddr(Module::GetMainModuleBase());
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT int Script::Module::GetMainModuleSectionCount()
|
||||
{
|
||||
return Module::SectionCountFromAddr(Module::GetMainModuleBase());
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::GetMainModuleName(char* name)
|
||||
{
|
||||
return Module::NameFromAddr(Module::GetMainModuleBase(), name);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::GetMainModulePath(char* path)
|
||||
{
|
||||
return Module::PathFromAddr(Module::GetMainModuleBase(), path);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::GetMainModuleSectionList(ListOf(ModuleSectionInfo) listInfo)
|
||||
{
|
||||
return Module::SectionListFromAddr(Module::GetMainModuleBase(), listInfo);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Module::GetList(ListOf(ModuleInfo) listInfo)
|
||||
{
|
||||
std::vector<MODINFO> modList;
|
||||
ModGetList(modList);
|
||||
std::vector<ModuleInfo> modScriptList;
|
||||
modScriptList.reserve(modList.size());
|
||||
for(const auto & mod : modList)
|
||||
{
|
||||
ModuleInfo scriptMod;
|
||||
scriptMod.base = mod.base;
|
||||
scriptMod.size = mod.size;
|
||||
scriptMod.entry = mod.entry;
|
||||
scriptMod.sectionCount = int(mod.sections.size());
|
||||
strcpy_s(scriptMod.name, mod.name);
|
||||
strcat_s(scriptMod.name, mod.extension);
|
||||
strcpy_s(scriptMod.path, mod.path);
|
||||
modScriptList.push_back(scriptMod);
|
||||
}
|
||||
return List<ModuleInfo>::CopyData(listInfo, modScriptList);
|
||||
}
|
||||
|
|
@ -1,56 +1,56 @@
|
|||
#ifndef _SCRIPTAPI_MODULE_H
|
||||
#define _SCRIPTAPI_MODULE_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Module
|
||||
{
|
||||
struct ModuleInfo
|
||||
{
|
||||
duint base;
|
||||
duint size;
|
||||
duint entry;
|
||||
int sectionCount;
|
||||
char name[MAX_MODULE_SIZE];
|
||||
char path[MAX_PATH];
|
||||
};
|
||||
|
||||
struct ModuleSectionInfo
|
||||
{
|
||||
duint addr;
|
||||
duint size;
|
||||
char name[MAX_SECTION_SIZE * 5];
|
||||
};
|
||||
|
||||
SCRIPT_EXPORT bool InfoFromAddr(duint addr, ModuleInfo* info);
|
||||
SCRIPT_EXPORT bool InfoFromName(const char* name, ModuleInfo* info);
|
||||
SCRIPT_EXPORT duint BaseFromAddr(duint addr);
|
||||
SCRIPT_EXPORT duint BaseFromName(const char* name);
|
||||
SCRIPT_EXPORT duint SizeFromAddr(duint addr);
|
||||
SCRIPT_EXPORT duint SizeFromName(const char* name);
|
||||
SCRIPT_EXPORT bool NameFromAddr(duint addr, char* name); //name[MAX_MODULE_SIZE]
|
||||
SCRIPT_EXPORT bool PathFromAddr(duint addr, char* path); //path[MAX_MODULE_PATH_SIZE]
|
||||
SCRIPT_EXPORT bool PathFromName(const char* name, char* path); //path[MAX_PATH]
|
||||
SCRIPT_EXPORT duint EntryFromAddr(duint addr);
|
||||
SCRIPT_EXPORT duint EntryFromName(const char* name);
|
||||
SCRIPT_EXPORT int SectionCountFromAddr(duint addr);
|
||||
SCRIPT_EXPORT int SectionCountFromName(const char* name);
|
||||
SCRIPT_EXPORT bool SectionFromAddr(duint addr, int number, ModuleSectionInfo* section);
|
||||
SCRIPT_EXPORT bool SectionFromName(const char* name, int number, ModuleSectionInfo* section);
|
||||
SCRIPT_EXPORT bool SectionListFromAddr(duint addr, ListOf(ModuleSectionInfo) listInfo);
|
||||
SCRIPT_EXPORT bool SectionListFromName(const char* name, ListOf(ModuleSectionInfo) listInfo);
|
||||
SCRIPT_EXPORT bool GetMainModuleInfo(ModuleInfo* info);
|
||||
SCRIPT_EXPORT duint GetMainModuleBase();
|
||||
SCRIPT_EXPORT duint GetMainModuleSize();
|
||||
SCRIPT_EXPORT duint GetMainModuleEntry();
|
||||
SCRIPT_EXPORT int GetMainModuleSectionCount();
|
||||
SCRIPT_EXPORT bool GetMainModuleName(char* name); //name[MAX_MODULE_SIZE]
|
||||
SCRIPT_EXPORT bool GetMainModulePath(char* path); //path[MAX_PATH]
|
||||
SCRIPT_EXPORT bool GetMainModuleSectionList(ListOf(ModuleSectionInfo) listInfo); //caller has the responsibility to free the list
|
||||
SCRIPT_EXPORT bool GetList(ListOf(ModuleInfo) listInfo); //caller has the responsibility to free the list
|
||||
}; //Module
|
||||
}; //Script
|
||||
|
||||
#ifndef _SCRIPTAPI_MODULE_H
|
||||
#define _SCRIPTAPI_MODULE_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Module
|
||||
{
|
||||
struct ModuleInfo
|
||||
{
|
||||
duint base;
|
||||
duint size;
|
||||
duint entry;
|
||||
int sectionCount;
|
||||
char name[MAX_MODULE_SIZE];
|
||||
char path[MAX_PATH];
|
||||
};
|
||||
|
||||
struct ModuleSectionInfo
|
||||
{
|
||||
duint addr;
|
||||
duint size;
|
||||
char name[MAX_SECTION_SIZE * 5];
|
||||
};
|
||||
|
||||
SCRIPT_EXPORT bool InfoFromAddr(duint addr, ModuleInfo* info);
|
||||
SCRIPT_EXPORT bool InfoFromName(const char* name, ModuleInfo* info);
|
||||
SCRIPT_EXPORT duint BaseFromAddr(duint addr);
|
||||
SCRIPT_EXPORT duint BaseFromName(const char* name);
|
||||
SCRIPT_EXPORT duint SizeFromAddr(duint addr);
|
||||
SCRIPT_EXPORT duint SizeFromName(const char* name);
|
||||
SCRIPT_EXPORT bool NameFromAddr(duint addr, char* name); //name[MAX_MODULE_SIZE]
|
||||
SCRIPT_EXPORT bool PathFromAddr(duint addr, char* path); //path[MAX_MODULE_PATH_SIZE]
|
||||
SCRIPT_EXPORT bool PathFromName(const char* name, char* path); //path[MAX_PATH]
|
||||
SCRIPT_EXPORT duint EntryFromAddr(duint addr);
|
||||
SCRIPT_EXPORT duint EntryFromName(const char* name);
|
||||
SCRIPT_EXPORT int SectionCountFromAddr(duint addr);
|
||||
SCRIPT_EXPORT int SectionCountFromName(const char* name);
|
||||
SCRIPT_EXPORT bool SectionFromAddr(duint addr, int number, ModuleSectionInfo* section);
|
||||
SCRIPT_EXPORT bool SectionFromName(const char* name, int number, ModuleSectionInfo* section);
|
||||
SCRIPT_EXPORT bool SectionListFromAddr(duint addr, ListOf(ModuleSectionInfo) listInfo);
|
||||
SCRIPT_EXPORT bool SectionListFromName(const char* name, ListOf(ModuleSectionInfo) listInfo);
|
||||
SCRIPT_EXPORT bool GetMainModuleInfo(ModuleInfo* info);
|
||||
SCRIPT_EXPORT duint GetMainModuleBase();
|
||||
SCRIPT_EXPORT duint GetMainModuleSize();
|
||||
SCRIPT_EXPORT duint GetMainModuleEntry();
|
||||
SCRIPT_EXPORT int GetMainModuleSectionCount();
|
||||
SCRIPT_EXPORT bool GetMainModuleName(char* name); //name[MAX_MODULE_SIZE]
|
||||
SCRIPT_EXPORT bool GetMainModulePath(char* path); //path[MAX_PATH]
|
||||
SCRIPT_EXPORT bool GetMainModuleSectionList(ListOf(ModuleSectionInfo) listInfo); //caller has the responsibility to free the list
|
||||
SCRIPT_EXPORT bool GetList(ListOf(ModuleInfo) listInfo); //caller has the responsibility to free the list
|
||||
}; //Module
|
||||
}; //Script
|
||||
|
||||
#endif //_SCRIPTAPI_MODULE_H
|
||||
|
|
@ -1,48 +1,48 @@
|
|||
#include "_scriptapi_pattern.h"
|
||||
#include "patternfind.h"
|
||||
#include "memory.h"
|
||||
|
||||
SCRIPT_EXPORT duint Script::Pattern::Find(unsigned char* data, duint datasize, const char* pattern)
|
||||
{
|
||||
return patternfind(data, datasize, pattern);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Pattern::FindMem(duint start, duint size, const char* pattern)
|
||||
{
|
||||
Memory<unsigned char*> data(size, "Script::Pattern::FindMem::data");
|
||||
if(!MemRead(start, data(), size))
|
||||
return -1;
|
||||
return Pattern::Find(data(), data.size(), pattern) + start;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Pattern::Write(unsigned char* data, duint datasize, const char* pattern)
|
||||
{
|
||||
patternwrite(data, datasize, pattern);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Pattern::WriteMem(duint start, duint size, const char* pattern)
|
||||
{
|
||||
Memory<unsigned char*> data(size, "Script::Pattern::WriteMem::data");
|
||||
if(!MemRead(start, data(), data.size()))
|
||||
return;
|
||||
patternwrite(data(), data.size(), pattern);
|
||||
MemWrite(start, data(), data.size());
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Pattern::SearchAndReplace(unsigned char* data, duint datasize, const char* searchpattern, const char* replacepattern)
|
||||
{
|
||||
return patternsnr(data, datasize, searchpattern, replacepattern);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Pattern::SearchAndReplaceMem(duint start, duint size, const char* searchpattern, const char* replacepattern)
|
||||
{
|
||||
Memory<unsigned char*> data(size, "Script::Pattern::SearchAndReplaceMem::data");
|
||||
if(!MemRead(start, data(), size))
|
||||
return false;
|
||||
duint found = patternfind(data(), data.size(), searchpattern);
|
||||
if(found == -1)
|
||||
return false;
|
||||
patternwrite(data() + found, data.size() - found, replacepattern);
|
||||
MemWrite((start + found), data() + found, data.size() - found);
|
||||
return true;
|
||||
#include "_scriptapi_pattern.h"
|
||||
#include "patternfind.h"
|
||||
#include "memory.h"
|
||||
|
||||
SCRIPT_EXPORT duint Script::Pattern::Find(unsigned char* data, duint datasize, const char* pattern)
|
||||
{
|
||||
return patternfind(data, datasize, pattern);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Pattern::FindMem(duint start, duint size, const char* pattern)
|
||||
{
|
||||
Memory<unsigned char*> data(size, "Script::Pattern::FindMem::data");
|
||||
if(!MemRead(start, data(), size))
|
||||
return -1;
|
||||
return Pattern::Find(data(), data.size(), pattern) + start;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Pattern::Write(unsigned char* data, duint datasize, const char* pattern)
|
||||
{
|
||||
patternwrite(data, datasize, pattern);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT void Script::Pattern::WriteMem(duint start, duint size, const char* pattern)
|
||||
{
|
||||
Memory<unsigned char*> data(size, "Script::Pattern::WriteMem::data");
|
||||
if(!MemRead(start, data(), data.size()))
|
||||
return;
|
||||
patternwrite(data(), data.size(), pattern);
|
||||
MemWrite(start, data(), data.size());
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Pattern::SearchAndReplace(unsigned char* data, duint datasize, const char* searchpattern, const char* replacepattern)
|
||||
{
|
||||
return patternsnr(data, datasize, searchpattern, replacepattern);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT bool Script::Pattern::SearchAndReplaceMem(duint start, duint size, const char* searchpattern, const char* replacepattern)
|
||||
{
|
||||
Memory<unsigned char*> data(size, "Script::Pattern::SearchAndReplaceMem::data");
|
||||
if(!MemRead(start, data(), size))
|
||||
return false;
|
||||
duint found = patternfind(data(), data.size(), searchpattern);
|
||||
if(found == -1)
|
||||
return false;
|
||||
patternwrite(data() + found, data.size() - found, replacepattern);
|
||||
MemWrite((start + found), data() + found, data.size() - found);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
#ifndef _SCRIPTAPI_PATTERN_H
|
||||
#define _SCRIPTAPI_PATTERN_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Pattern
|
||||
{
|
||||
SCRIPT_EXPORT duint Find(unsigned char* data, duint datasize, const char* pattern);
|
||||
SCRIPT_EXPORT duint FindMem(duint start, duint size, const char* pattern);
|
||||
SCRIPT_EXPORT void Write(unsigned char* data, duint datasize, const char* pattern);
|
||||
SCRIPT_EXPORT void WriteMem(duint start, duint size, const char* pattern);
|
||||
SCRIPT_EXPORT bool SearchAndReplace(unsigned char* data, duint datasize, const char* searchpattern, const char* replacepattern);
|
||||
SCRIPT_EXPORT bool SearchAndReplaceMem(duint start, duint size, const char* searchpattern, const char* replacepattern);
|
||||
};
|
||||
};
|
||||
|
||||
#ifndef _SCRIPTAPI_PATTERN_H
|
||||
#define _SCRIPTAPI_PATTERN_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Pattern
|
||||
{
|
||||
SCRIPT_EXPORT duint Find(unsigned char* data, duint datasize, const char* pattern);
|
||||
SCRIPT_EXPORT duint FindMem(duint start, duint size, const char* pattern);
|
||||
SCRIPT_EXPORT void Write(unsigned char* data, duint datasize, const char* pattern);
|
||||
SCRIPT_EXPORT void WriteMem(duint start, duint size, const char* pattern);
|
||||
SCRIPT_EXPORT bool SearchAndReplace(unsigned char* data, duint datasize, const char* searchpattern, const char* replacepattern);
|
||||
SCRIPT_EXPORT bool SearchAndReplaceMem(duint start, duint size, const char* searchpattern, const char* replacepattern);
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_SCRIPTAPI_FIND_H
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,265 +1,265 @@
|
|||
#ifndef _SCRIPTAPI_REGISTER_H
|
||||
#define _SCRIPTAPI_REGISTER_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Register
|
||||
{
|
||||
enum RegisterEnum
|
||||
{
|
||||
DR0,
|
||||
DR1,
|
||||
DR2,
|
||||
DR3,
|
||||
DR6,
|
||||
DR7,
|
||||
|
||||
EAX,
|
||||
AX,
|
||||
AH,
|
||||
AL,
|
||||
EBX,
|
||||
BX,
|
||||
BH,
|
||||
BL,
|
||||
ECX,
|
||||
CX,
|
||||
CH,
|
||||
CL,
|
||||
EDX,
|
||||
DX,
|
||||
DH,
|
||||
DL,
|
||||
EDI,
|
||||
DI,
|
||||
ESI,
|
||||
SI,
|
||||
EBP,
|
||||
BP,
|
||||
ESP,
|
||||
SP,
|
||||
EIP,
|
||||
|
||||
#ifdef _WIN64
|
||||
RAX,
|
||||
RBX,
|
||||
RCX,
|
||||
RDX,
|
||||
RSI,
|
||||
SIL,
|
||||
RDI,
|
||||
DIL,
|
||||
RBP,
|
||||
BPL,
|
||||
RSP,
|
||||
SPL,
|
||||
RIP,
|
||||
R8,
|
||||
R8D,
|
||||
R8W,
|
||||
R8B,
|
||||
R9,
|
||||
R9D,
|
||||
R9W,
|
||||
R9B,
|
||||
R10,
|
||||
R10D,
|
||||
R10W,
|
||||
R10B,
|
||||
R11,
|
||||
R11D,
|
||||
R11W,
|
||||
R11B,
|
||||
R12,
|
||||
R12D,
|
||||
R12W,
|
||||
R12B,
|
||||
R13,
|
||||
R13D,
|
||||
R13W,
|
||||
R13B,
|
||||
R14,
|
||||
R14D,
|
||||
R14W,
|
||||
R14B,
|
||||
R15,
|
||||
R15D,
|
||||
R15W,
|
||||
R15B,
|
||||
#endif //_WIN64
|
||||
|
||||
CIP,
|
||||
CSP,
|
||||
}; //RegisterEnum
|
||||
|
||||
SCRIPT_EXPORT duint Get(RegisterEnum reg);
|
||||
SCRIPT_EXPORT bool Set(RegisterEnum reg, duint value);
|
||||
SCRIPT_EXPORT int Size(); //gets architecture register size in bytes
|
||||
|
||||
SCRIPT_EXPORT duint GetDR0();
|
||||
SCRIPT_EXPORT bool SetDR0(duint value);
|
||||
SCRIPT_EXPORT duint GetDR1();
|
||||
SCRIPT_EXPORT bool SetDR1(duint value);
|
||||
SCRIPT_EXPORT duint GetDR2();
|
||||
SCRIPT_EXPORT bool SetDR2(duint value);
|
||||
SCRIPT_EXPORT duint GetDR3();
|
||||
SCRIPT_EXPORT bool SetDR3(duint value);
|
||||
SCRIPT_EXPORT duint GetDR6();
|
||||
SCRIPT_EXPORT bool SetDR6(duint value);
|
||||
SCRIPT_EXPORT duint GetDR7();
|
||||
SCRIPT_EXPORT bool SetDR7(duint value);
|
||||
|
||||
SCRIPT_EXPORT unsigned int GetEAX();
|
||||
SCRIPT_EXPORT bool SetEAX(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetAX();
|
||||
SCRIPT_EXPORT bool SetAX(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetAH();
|
||||
SCRIPT_EXPORT bool SetAH(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned char GetAL();
|
||||
SCRIPT_EXPORT bool SetAL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned int GetEBX();
|
||||
SCRIPT_EXPORT bool SetEBX(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetBX();
|
||||
SCRIPT_EXPORT bool SetBX(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetBH();
|
||||
SCRIPT_EXPORT bool SetBH(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned char GetBL();
|
||||
SCRIPT_EXPORT bool SetBL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned int GetECX();
|
||||
SCRIPT_EXPORT bool SetECX(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetCX();
|
||||
SCRIPT_EXPORT bool SetCX(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetCH();
|
||||
SCRIPT_EXPORT bool SetCH(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned char GetCL();
|
||||
SCRIPT_EXPORT bool SetCL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned int GetEDX();
|
||||
SCRIPT_EXPORT bool SetEDX(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetDX();
|
||||
SCRIPT_EXPORT bool SetDX(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetDH();
|
||||
SCRIPT_EXPORT bool SetDH(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned char GetDL();
|
||||
SCRIPT_EXPORT bool SetDL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned int GetEDI();
|
||||
SCRIPT_EXPORT bool SetEDI(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetDI();
|
||||
SCRIPT_EXPORT bool SetDI(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned int GetESI();
|
||||
SCRIPT_EXPORT bool SetESI(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetSI();
|
||||
SCRIPT_EXPORT bool SetSI(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned int GetEBP();
|
||||
SCRIPT_EXPORT bool SetEBP(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetBP();
|
||||
SCRIPT_EXPORT bool SetBP(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned int GetESP();
|
||||
SCRIPT_EXPORT bool SetESP(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetSP();
|
||||
SCRIPT_EXPORT bool SetSP(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned int GetEIP();
|
||||
SCRIPT_EXPORT bool SetEIP(unsigned int value);
|
||||
|
||||
#ifdef _WIN64
|
||||
SCRIPT_EXPORT unsigned long long GetRAX();
|
||||
SCRIPT_EXPORT bool SetRAX(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned long long GetRBX();
|
||||
SCRIPT_EXPORT bool SetRBX(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned long long GetRCX();
|
||||
SCRIPT_EXPORT bool SetRCX(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned long long GetRDX();
|
||||
SCRIPT_EXPORT bool SetRDX(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned long long GetRSI();
|
||||
SCRIPT_EXPORT bool SetRSI(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned char GetSIL();
|
||||
SCRIPT_EXPORT bool SetSIL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetRDI();
|
||||
SCRIPT_EXPORT bool SetRDI(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned char GetDIL();
|
||||
SCRIPT_EXPORT bool SetDIL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetRBP();
|
||||
SCRIPT_EXPORT bool SetRBP(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned char GetBPL();
|
||||
SCRIPT_EXPORT bool SetBPL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetRSP();
|
||||
SCRIPT_EXPORT bool SetRSP(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned char GetSPL();
|
||||
SCRIPT_EXPORT bool SetSPL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetRIP();
|
||||
SCRIPT_EXPORT bool SetRIP(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned long long GetR8();
|
||||
SCRIPT_EXPORT bool SetR8(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR8D();
|
||||
SCRIPT_EXPORT bool SetR8D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR8W();
|
||||
SCRIPT_EXPORT bool SetR8W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR8B();
|
||||
SCRIPT_EXPORT bool SetR8B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR9();
|
||||
SCRIPT_EXPORT bool SetR9(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR9D();
|
||||
SCRIPT_EXPORT bool SetR9D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR9W();
|
||||
SCRIPT_EXPORT bool SetR9W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR9B();
|
||||
SCRIPT_EXPORT bool SetR9B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR10();
|
||||
SCRIPT_EXPORT bool SetR10(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR10D();
|
||||
SCRIPT_EXPORT bool SetR10D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR10W();
|
||||
SCRIPT_EXPORT bool SetR10W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR10B();
|
||||
SCRIPT_EXPORT bool SetR10B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR11();
|
||||
SCRIPT_EXPORT bool SetR11(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR11D();
|
||||
SCRIPT_EXPORT bool SetR11D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR11W();
|
||||
SCRIPT_EXPORT bool SetR11W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR11B();
|
||||
SCRIPT_EXPORT bool SetR11B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR12();
|
||||
SCRIPT_EXPORT bool SetR12(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR12D();
|
||||
SCRIPT_EXPORT bool SetR12D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR12W();
|
||||
SCRIPT_EXPORT bool SetR12W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR12B();
|
||||
SCRIPT_EXPORT bool SetR12B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR13();
|
||||
SCRIPT_EXPORT bool SetR13(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR13D();
|
||||
SCRIPT_EXPORT bool SetR13D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR13W();
|
||||
SCRIPT_EXPORT bool SetR13W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR13B();
|
||||
SCRIPT_EXPORT bool SetR13B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR14();
|
||||
SCRIPT_EXPORT bool SetR14(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR14D();
|
||||
SCRIPT_EXPORT bool SetR14D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR14W();
|
||||
SCRIPT_EXPORT bool SetR14W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR14B();
|
||||
SCRIPT_EXPORT bool SetR14B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR15();
|
||||
SCRIPT_EXPORT bool SetR15(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR15D();
|
||||
SCRIPT_EXPORT bool SetR15D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR15W();
|
||||
SCRIPT_EXPORT bool SetR15W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR15B();
|
||||
SCRIPT_EXPORT bool SetR15B(unsigned char value);
|
||||
#endif //_WIN64
|
||||
|
||||
SCRIPT_EXPORT duint GetCIP();
|
||||
SCRIPT_EXPORT bool SetCIP(duint value);
|
||||
SCRIPT_EXPORT duint GetCSP();
|
||||
SCRIPT_EXPORT bool SetCSP(duint value);
|
||||
}; //Register
|
||||
}; //Script
|
||||
|
||||
#ifndef _SCRIPTAPI_REGISTER_H
|
||||
#define _SCRIPTAPI_REGISTER_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Register
|
||||
{
|
||||
enum RegisterEnum
|
||||
{
|
||||
DR0,
|
||||
DR1,
|
||||
DR2,
|
||||
DR3,
|
||||
DR6,
|
||||
DR7,
|
||||
|
||||
EAX,
|
||||
AX,
|
||||
AH,
|
||||
AL,
|
||||
EBX,
|
||||
BX,
|
||||
BH,
|
||||
BL,
|
||||
ECX,
|
||||
CX,
|
||||
CH,
|
||||
CL,
|
||||
EDX,
|
||||
DX,
|
||||
DH,
|
||||
DL,
|
||||
EDI,
|
||||
DI,
|
||||
ESI,
|
||||
SI,
|
||||
EBP,
|
||||
BP,
|
||||
ESP,
|
||||
SP,
|
||||
EIP,
|
||||
|
||||
#ifdef _WIN64
|
||||
RAX,
|
||||
RBX,
|
||||
RCX,
|
||||
RDX,
|
||||
RSI,
|
||||
SIL,
|
||||
RDI,
|
||||
DIL,
|
||||
RBP,
|
||||
BPL,
|
||||
RSP,
|
||||
SPL,
|
||||
RIP,
|
||||
R8,
|
||||
R8D,
|
||||
R8W,
|
||||
R8B,
|
||||
R9,
|
||||
R9D,
|
||||
R9W,
|
||||
R9B,
|
||||
R10,
|
||||
R10D,
|
||||
R10W,
|
||||
R10B,
|
||||
R11,
|
||||
R11D,
|
||||
R11W,
|
||||
R11B,
|
||||
R12,
|
||||
R12D,
|
||||
R12W,
|
||||
R12B,
|
||||
R13,
|
||||
R13D,
|
||||
R13W,
|
||||
R13B,
|
||||
R14,
|
||||
R14D,
|
||||
R14W,
|
||||
R14B,
|
||||
R15,
|
||||
R15D,
|
||||
R15W,
|
||||
R15B,
|
||||
#endif //_WIN64
|
||||
|
||||
CIP,
|
||||
CSP,
|
||||
}; //RegisterEnum
|
||||
|
||||
SCRIPT_EXPORT duint Get(RegisterEnum reg);
|
||||
SCRIPT_EXPORT bool Set(RegisterEnum reg, duint value);
|
||||
SCRIPT_EXPORT int Size(); //gets architecture register size in bytes
|
||||
|
||||
SCRIPT_EXPORT duint GetDR0();
|
||||
SCRIPT_EXPORT bool SetDR0(duint value);
|
||||
SCRIPT_EXPORT duint GetDR1();
|
||||
SCRIPT_EXPORT bool SetDR1(duint value);
|
||||
SCRIPT_EXPORT duint GetDR2();
|
||||
SCRIPT_EXPORT bool SetDR2(duint value);
|
||||
SCRIPT_EXPORT duint GetDR3();
|
||||
SCRIPT_EXPORT bool SetDR3(duint value);
|
||||
SCRIPT_EXPORT duint GetDR6();
|
||||
SCRIPT_EXPORT bool SetDR6(duint value);
|
||||
SCRIPT_EXPORT duint GetDR7();
|
||||
SCRIPT_EXPORT bool SetDR7(duint value);
|
||||
|
||||
SCRIPT_EXPORT unsigned int GetEAX();
|
||||
SCRIPT_EXPORT bool SetEAX(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetAX();
|
||||
SCRIPT_EXPORT bool SetAX(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetAH();
|
||||
SCRIPT_EXPORT bool SetAH(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned char GetAL();
|
||||
SCRIPT_EXPORT bool SetAL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned int GetEBX();
|
||||
SCRIPT_EXPORT bool SetEBX(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetBX();
|
||||
SCRIPT_EXPORT bool SetBX(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetBH();
|
||||
SCRIPT_EXPORT bool SetBH(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned char GetBL();
|
||||
SCRIPT_EXPORT bool SetBL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned int GetECX();
|
||||
SCRIPT_EXPORT bool SetECX(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetCX();
|
||||
SCRIPT_EXPORT bool SetCX(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetCH();
|
||||
SCRIPT_EXPORT bool SetCH(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned char GetCL();
|
||||
SCRIPT_EXPORT bool SetCL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned int GetEDX();
|
||||
SCRIPT_EXPORT bool SetEDX(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetDX();
|
||||
SCRIPT_EXPORT bool SetDX(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetDH();
|
||||
SCRIPT_EXPORT bool SetDH(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned char GetDL();
|
||||
SCRIPT_EXPORT bool SetDL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned int GetEDI();
|
||||
SCRIPT_EXPORT bool SetEDI(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetDI();
|
||||
SCRIPT_EXPORT bool SetDI(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned int GetESI();
|
||||
SCRIPT_EXPORT bool SetESI(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetSI();
|
||||
SCRIPT_EXPORT bool SetSI(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned int GetEBP();
|
||||
SCRIPT_EXPORT bool SetEBP(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetBP();
|
||||
SCRIPT_EXPORT bool SetBP(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned int GetESP();
|
||||
SCRIPT_EXPORT bool SetESP(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetSP();
|
||||
SCRIPT_EXPORT bool SetSP(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned int GetEIP();
|
||||
SCRIPT_EXPORT bool SetEIP(unsigned int value);
|
||||
|
||||
#ifdef _WIN64
|
||||
SCRIPT_EXPORT unsigned long long GetRAX();
|
||||
SCRIPT_EXPORT bool SetRAX(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned long long GetRBX();
|
||||
SCRIPT_EXPORT bool SetRBX(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned long long GetRCX();
|
||||
SCRIPT_EXPORT bool SetRCX(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned long long GetRDX();
|
||||
SCRIPT_EXPORT bool SetRDX(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned long long GetRSI();
|
||||
SCRIPT_EXPORT bool SetRSI(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned char GetSIL();
|
||||
SCRIPT_EXPORT bool SetSIL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetRDI();
|
||||
SCRIPT_EXPORT bool SetRDI(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned char GetDIL();
|
||||
SCRIPT_EXPORT bool SetDIL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetRBP();
|
||||
SCRIPT_EXPORT bool SetRBP(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned char GetBPL();
|
||||
SCRIPT_EXPORT bool SetBPL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetRSP();
|
||||
SCRIPT_EXPORT bool SetRSP(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned char GetSPL();
|
||||
SCRIPT_EXPORT bool SetSPL(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetRIP();
|
||||
SCRIPT_EXPORT bool SetRIP(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned long long GetR8();
|
||||
SCRIPT_EXPORT bool SetR8(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR8D();
|
||||
SCRIPT_EXPORT bool SetR8D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR8W();
|
||||
SCRIPT_EXPORT bool SetR8W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR8B();
|
||||
SCRIPT_EXPORT bool SetR8B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR9();
|
||||
SCRIPT_EXPORT bool SetR9(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR9D();
|
||||
SCRIPT_EXPORT bool SetR9D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR9W();
|
||||
SCRIPT_EXPORT bool SetR9W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR9B();
|
||||
SCRIPT_EXPORT bool SetR9B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR10();
|
||||
SCRIPT_EXPORT bool SetR10(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR10D();
|
||||
SCRIPT_EXPORT bool SetR10D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR10W();
|
||||
SCRIPT_EXPORT bool SetR10W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR10B();
|
||||
SCRIPT_EXPORT bool SetR10B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR11();
|
||||
SCRIPT_EXPORT bool SetR11(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR11D();
|
||||
SCRIPT_EXPORT bool SetR11D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR11W();
|
||||
SCRIPT_EXPORT bool SetR11W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR11B();
|
||||
SCRIPT_EXPORT bool SetR11B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR12();
|
||||
SCRIPT_EXPORT bool SetR12(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR12D();
|
||||
SCRIPT_EXPORT bool SetR12D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR12W();
|
||||
SCRIPT_EXPORT bool SetR12W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR12B();
|
||||
SCRIPT_EXPORT bool SetR12B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR13();
|
||||
SCRIPT_EXPORT bool SetR13(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR13D();
|
||||
SCRIPT_EXPORT bool SetR13D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR13W();
|
||||
SCRIPT_EXPORT bool SetR13W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR13B();
|
||||
SCRIPT_EXPORT bool SetR13B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR14();
|
||||
SCRIPT_EXPORT bool SetR14(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR14D();
|
||||
SCRIPT_EXPORT bool SetR14D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR14W();
|
||||
SCRIPT_EXPORT bool SetR14W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR14B();
|
||||
SCRIPT_EXPORT bool SetR14B(unsigned char value);
|
||||
SCRIPT_EXPORT unsigned long long GetR15();
|
||||
SCRIPT_EXPORT bool SetR15(unsigned long long value);
|
||||
SCRIPT_EXPORT unsigned int GetR15D();
|
||||
SCRIPT_EXPORT bool SetR15D(unsigned int value);
|
||||
SCRIPT_EXPORT unsigned short GetR15W();
|
||||
SCRIPT_EXPORT bool SetR15W(unsigned short value);
|
||||
SCRIPT_EXPORT unsigned char GetR15B();
|
||||
SCRIPT_EXPORT bool SetR15B(unsigned char value);
|
||||
#endif //_WIN64
|
||||
|
||||
SCRIPT_EXPORT duint GetCIP();
|
||||
SCRIPT_EXPORT bool SetCIP(duint value);
|
||||
SCRIPT_EXPORT duint GetCSP();
|
||||
SCRIPT_EXPORT bool SetCSP(duint value);
|
||||
}; //Register
|
||||
}; //Script
|
||||
|
||||
#endif //_SCRIPTAPI_REGISTER_H
|
||||
|
|
@ -1,24 +1,24 @@
|
|||
#include "_scriptapi_stack.h"
|
||||
#include "_scriptapi_memory.h"
|
||||
#include "_scriptapi_register.h"
|
||||
|
||||
SCRIPT_EXPORT duint Script::Stack::Pop()
|
||||
{
|
||||
duint csp = Register::GetCSP();
|
||||
duint top = Memory::ReadPtr(csp);
|
||||
Register::SetCSP(csp + sizeof(duint));
|
||||
return top;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Stack::Push(duint value)
|
||||
{
|
||||
duint csp = Register::GetCSP();
|
||||
Register::SetCSP(csp - sizeof(duint));
|
||||
Memory::WritePtr(csp - sizeof(duint), value);
|
||||
return Memory::ReadPtr(csp);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Stack::Peek(int offset)
|
||||
{
|
||||
return Memory::ReadPtr(Register::GetCSP() + offset * sizeof(duint));
|
||||
#include "_scriptapi_stack.h"
|
||||
#include "_scriptapi_memory.h"
|
||||
#include "_scriptapi_register.h"
|
||||
|
||||
SCRIPT_EXPORT duint Script::Stack::Pop()
|
||||
{
|
||||
duint csp = Register::GetCSP();
|
||||
duint top = Memory::ReadPtr(csp);
|
||||
Register::SetCSP(csp + sizeof(duint));
|
||||
return top;
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Stack::Push(duint value)
|
||||
{
|
||||
duint csp = Register::GetCSP();
|
||||
Register::SetCSP(csp - sizeof(duint));
|
||||
Memory::WritePtr(csp - sizeof(duint), value);
|
||||
return Memory::ReadPtr(csp);
|
||||
}
|
||||
|
||||
SCRIPT_EXPORT duint Script::Stack::Peek(int offset)
|
||||
{
|
||||
return Memory::ReadPtr(Register::GetCSP() + offset * sizeof(duint));
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
#ifndef _SCRIPTAPI_STACK_H
|
||||
#define _SCRIPTAPI_STACK_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Stack
|
||||
{
|
||||
SCRIPT_EXPORT duint Pop();
|
||||
SCRIPT_EXPORT duint Push(duint value); //returns the previous top, equal to Peek(1)
|
||||
SCRIPT_EXPORT duint Peek(int offset = 0); //offset is in multiples of Register::Size(), for easy x32/x64 portability
|
||||
}; //Stack
|
||||
}; //Script
|
||||
|
||||
#ifndef _SCRIPTAPI_STACK_H
|
||||
#define _SCRIPTAPI_STACK_H
|
||||
|
||||
#include "_scriptapi.h"
|
||||
|
||||
namespace Script
|
||||
{
|
||||
namespace Stack
|
||||
{
|
||||
SCRIPT_EXPORT duint Pop();
|
||||
SCRIPT_EXPORT duint Push(duint value); //returns the previous top, equal to Peek(1)
|
||||
SCRIPT_EXPORT duint Peek(int offset = 0); //offset is in multiples of Register::Size(), for easy x32/x64 portability
|
||||
}; //Stack
|
||||
}; //Script
|
||||
|
||||
#endif //_SCRIPTAPI_STACK_H
|
||||
|
|
@ -1,236 +1,236 @@
|
|||
/**
|
||||
@file addrinfo.cpp
|
||||
|
||||
@brief Implements the addrinfo class.
|
||||
*/
|
||||
|
||||
#include "addrinfo.h"
|
||||
#include "debugger.h"
|
||||
#include "console.h"
|
||||
#include "memory.h"
|
||||
#include "breakpoint.h"
|
||||
#include "lz4\lz4file.h"
|
||||
#include "patches.h"
|
||||
#include "module.h"
|
||||
#include "comment.h"
|
||||
#include "label.h"
|
||||
#include "bookmark.h"
|
||||
#include "function.h"
|
||||
#include "loop.h"
|
||||
|
||||
//database functions
|
||||
void dbsave()
|
||||
{
|
||||
dprintf("Saving database...");
|
||||
DWORD ticks = GetTickCount();
|
||||
JSON root = json_object();
|
||||
CommentCacheSave(root);
|
||||
LabelCacheSave(root);
|
||||
BookmarkCacheSave(root);
|
||||
FunctionCacheSave(root);
|
||||
LoopCacheSave(root);
|
||||
BpCacheSave(root);
|
||||
//save notes
|
||||
char* text = nullptr;
|
||||
GuiGetDebuggeeNotes(&text);
|
||||
if(text)
|
||||
{
|
||||
json_object_set_new(root, "notes", json_string(text));
|
||||
BridgeFree(text);
|
||||
}
|
||||
GuiSetDebuggeeNotes("");
|
||||
|
||||
WString wdbpath = StringUtils::Utf8ToUtf16(dbpath);
|
||||
if(json_object_size(root))
|
||||
{
|
||||
Handle hFile = CreateFileW(wdbpath.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||
if(!hFile)
|
||||
{
|
||||
dputs("\nFailed to open database for writing!");
|
||||
json_decref(root); //free root
|
||||
return;
|
||||
}
|
||||
SetEndOfFile(hFile);
|
||||
char* jsonText = json_dumps(root, JSON_INDENT(4));
|
||||
DWORD written = 0;
|
||||
if(!WriteFile(hFile, jsonText, (DWORD)strlen(jsonText), &written, 0))
|
||||
{
|
||||
json_free(jsonText);
|
||||
dputs("\nFailed to write database file!");
|
||||
json_decref(root); //free root
|
||||
return;
|
||||
}
|
||||
hFile.Close();
|
||||
json_free(jsonText);
|
||||
if(!settingboolget("Engine", "DisableDatabaseCompression"))
|
||||
LZ4_compress_fileW(wdbpath.c_str(), wdbpath.c_str());
|
||||
}
|
||||
else //remove database when nothing is in there
|
||||
DeleteFileW(wdbpath.c_str());
|
||||
dprintf("%ums\n", GetTickCount() - ticks);
|
||||
json_decref(root); //free root
|
||||
}
|
||||
|
||||
void dbload()
|
||||
{
|
||||
// If the file doesn't exist, there is no DB to load
|
||||
if(!FileExists(dbpath))
|
||||
return;
|
||||
|
||||
dprintf("Loading database...");
|
||||
DWORD ticks = GetTickCount();
|
||||
|
||||
// Multi-byte (UTF8) file path converted to UTF16
|
||||
WString databasePathW = StringUtils::Utf8ToUtf16(dbpath);
|
||||
|
||||
// Decompress the file if compression was enabled
|
||||
bool useCompression = !settingboolget("Engine", "DisableDatabaseCompression");
|
||||
LZ4_STATUS lzmaStatus = LZ4_INVALID_ARCHIVE;
|
||||
{
|
||||
lzmaStatus = LZ4_decompress_fileW(databasePathW.c_str(), databasePathW.c_str());
|
||||
|
||||
// Check return code
|
||||
if(useCompression && lzmaStatus != LZ4_SUCCESS && lzmaStatus != LZ4_INVALID_ARCHIVE)
|
||||
{
|
||||
dputs("\nInvalid database file!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the database file
|
||||
Handle hFile = CreateFileW(databasePathW.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
if(!hFile)
|
||||
{
|
||||
dputs("\nFailed to open database file!");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int jsonFileSize = GetFileSize(hFile, 0);
|
||||
if(!jsonFileSize)
|
||||
{
|
||||
dputs("\nEmpty database file!");
|
||||
return;
|
||||
}
|
||||
|
||||
Memory<char*> jsonText(jsonFileSize + 1);
|
||||
DWORD read = 0;
|
||||
if(!ReadFile(hFile, jsonText(), jsonFileSize, &read, 0))
|
||||
{
|
||||
dputs("\nFailed to read database file!");
|
||||
return;
|
||||
}
|
||||
hFile.Close();
|
||||
|
||||
// Deserialize JSON
|
||||
JSON root = json_loads(jsonText(), 0, 0);
|
||||
|
||||
if(lzmaStatus != LZ4_INVALID_ARCHIVE && useCompression)
|
||||
LZ4_compress_fileW(databasePathW.c_str(), databasePathW.c_str());
|
||||
|
||||
// Validate JSON load status
|
||||
if(!root)
|
||||
{
|
||||
dputs("\nInvalid database file (JSON)!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally load all structures
|
||||
CommentCacheLoad(root);
|
||||
LabelCacheLoad(root);
|
||||
BookmarkCacheLoad(root);
|
||||
FunctionCacheLoad(root);
|
||||
LoopCacheLoad(root);
|
||||
BpCacheLoad(root);
|
||||
|
||||
// Load notes
|
||||
const char* text = json_string_value(json_object_get(root, "notes"));
|
||||
GuiSetDebuggeeNotes(text);
|
||||
|
||||
// Free root
|
||||
json_decref(root);
|
||||
dprintf("%ums\n", GetTickCount() - ticks);
|
||||
}
|
||||
|
||||
void dbclose()
|
||||
{
|
||||
dbsave();
|
||||
CommentClear();
|
||||
LabelClear();
|
||||
BookmarkClear();
|
||||
FunctionClear();
|
||||
LoopClear();
|
||||
BpClear();
|
||||
PatchClear();
|
||||
}
|
||||
|
||||
///api functions
|
||||
bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
VirtualQueryEx(fdProcessInfo->hProcess, (const void*)base, &mbi, sizeof(mbi));
|
||||
uint size = mbi.RegionSize;
|
||||
Memory<void*> buffer(size, "apienumexports:buffer");
|
||||
if(!MemRead(base, buffer(), size))
|
||||
return false;
|
||||
IMAGE_NT_HEADERS* pnth = (IMAGE_NT_HEADERS*)((uint)buffer() + GetPE32DataFromMappedFile((ULONG_PTR)buffer(), 0, UE_PE_OFFSET));
|
||||
uint export_dir_rva = pnth->OptionalHeader.DataDirectory[0].VirtualAddress;
|
||||
uint export_dir_size = pnth->OptionalHeader.DataDirectory[0].Size;
|
||||
IMAGE_EXPORT_DIRECTORY export_dir;
|
||||
memset(&export_dir, 0, sizeof(export_dir));
|
||||
MemRead((export_dir_rva + base), &export_dir, sizeof(export_dir));
|
||||
unsigned int NumberOfNames = export_dir.NumberOfNames;
|
||||
if(!export_dir.NumberOfFunctions || !NumberOfNames) //no named exports
|
||||
return false;
|
||||
char modname[MAX_MODULE_SIZE] = "";
|
||||
ModNameFromAddr(base, modname, true);
|
||||
uint original_name_va = export_dir.Name + base;
|
||||
char original_name[deflen] = "";
|
||||
memset(original_name, 0, sizeof(original_name));
|
||||
MemRead(original_name_va, original_name, deflen);
|
||||
char* AddrOfFunctions_va = (char*)(export_dir.AddressOfFunctions + base); //not a valid local pointer
|
||||
char* AddrOfNames_va = (char*)(export_dir.AddressOfNames + base); //not a valid local pointer
|
||||
char* AddrOfNameOrdinals_va = (char*)(export_dir.AddressOfNameOrdinals + base); //not a valid local pointer
|
||||
for(DWORD i = 0; i < NumberOfNames; i++)
|
||||
{
|
||||
DWORD curAddrOfName = 0;
|
||||
MemRead((uint)(AddrOfNames_va + sizeof(DWORD)*i), &curAddrOfName, sizeof(DWORD));
|
||||
char* cur_name_va = (char*)(curAddrOfName + base);
|
||||
char cur_name[deflen] = "";
|
||||
memset(cur_name, 0, deflen);
|
||||
MemRead((uint)cur_name_va, cur_name, deflen);
|
||||
WORD curAddrOfNameOrdinals = 0;
|
||||
MemRead((uint)(AddrOfNameOrdinals_va + sizeof(WORD)*i), &curAddrOfNameOrdinals, sizeof(WORD));
|
||||
DWORD curFunctionRva = 0;
|
||||
MemRead((uint)(AddrOfFunctions_va + sizeof(DWORD)*curAddrOfNameOrdinals), &curFunctionRva, sizeof(DWORD));
|
||||
|
||||
if(curFunctionRva >= export_dir_rva && curFunctionRva < export_dir_rva + export_dir_size)
|
||||
{
|
||||
char forwarded_api[deflen] = "";
|
||||
memset(forwarded_api, 0, deflen);
|
||||
MemRead((curFunctionRva + base), forwarded_api, deflen);
|
||||
int len = (int)strlen(forwarded_api);
|
||||
int j = 0;
|
||||
while(forwarded_api[j] != '.' && j < len)
|
||||
j++;
|
||||
if(forwarded_api[j] == '.')
|
||||
{
|
||||
forwarded_api[j] = 0;
|
||||
HINSTANCE hTempDll = LoadLibraryExA(forwarded_api, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
|
||||
if(hTempDll)
|
||||
{
|
||||
uint local_addr = (uint)GetProcAddress(hTempDll, forwarded_api + j + 1);
|
||||
if(local_addr)
|
||||
{
|
||||
uint remote_addr = ImporterGetRemoteAPIAddress(fdProcessInfo->hProcess, local_addr);
|
||||
cbEnum(base, modname, cur_name, remote_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cbEnum(base, modname, cur_name, curFunctionRva + base);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
/**
|
||||
@file addrinfo.cpp
|
||||
|
||||
@brief Implements the addrinfo class.
|
||||
*/
|
||||
|
||||
#include "addrinfo.h"
|
||||
#include "debugger.h"
|
||||
#include "console.h"
|
||||
#include "memory.h"
|
||||
#include "breakpoint.h"
|
||||
#include "lz4\lz4file.h"
|
||||
#include "patches.h"
|
||||
#include "module.h"
|
||||
#include "comment.h"
|
||||
#include "label.h"
|
||||
#include "bookmark.h"
|
||||
#include "function.h"
|
||||
#include "loop.h"
|
||||
|
||||
//database functions
|
||||
void dbsave()
|
||||
{
|
||||
dprintf("Saving database...");
|
||||
DWORD ticks = GetTickCount();
|
||||
JSON root = json_object();
|
||||
CommentCacheSave(root);
|
||||
LabelCacheSave(root);
|
||||
BookmarkCacheSave(root);
|
||||
FunctionCacheSave(root);
|
||||
LoopCacheSave(root);
|
||||
BpCacheSave(root);
|
||||
//save notes
|
||||
char* text = nullptr;
|
||||
GuiGetDebuggeeNotes(&text);
|
||||
if(text)
|
||||
{
|
||||
json_object_set_new(root, "notes", json_string(text));
|
||||
BridgeFree(text);
|
||||
}
|
||||
GuiSetDebuggeeNotes("");
|
||||
|
||||
WString wdbpath = StringUtils::Utf8ToUtf16(dbpath);
|
||||
if(json_object_size(root))
|
||||
{
|
||||
Handle hFile = CreateFileW(wdbpath.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||
if(!hFile)
|
||||
{
|
||||
dputs("\nFailed to open database for writing!");
|
||||
json_decref(root); //free root
|
||||
return;
|
||||
}
|
||||
SetEndOfFile(hFile);
|
||||
char* jsonText = json_dumps(root, JSON_INDENT(4));
|
||||
DWORD written = 0;
|
||||
if(!WriteFile(hFile, jsonText, (DWORD)strlen(jsonText), &written, 0))
|
||||
{
|
||||
json_free(jsonText);
|
||||
dputs("\nFailed to write database file!");
|
||||
json_decref(root); //free root
|
||||
return;
|
||||
}
|
||||
hFile.Close();
|
||||
json_free(jsonText);
|
||||
if(!settingboolget("Engine", "DisableDatabaseCompression"))
|
||||
LZ4_compress_fileW(wdbpath.c_str(), wdbpath.c_str());
|
||||
}
|
||||
else //remove database when nothing is in there
|
||||
DeleteFileW(wdbpath.c_str());
|
||||
dprintf("%ums\n", GetTickCount() - ticks);
|
||||
json_decref(root); //free root
|
||||
}
|
||||
|
||||
void dbload()
|
||||
{
|
||||
// If the file doesn't exist, there is no DB to load
|
||||
if(!FileExists(dbpath))
|
||||
return;
|
||||
|
||||
dprintf("Loading database...");
|
||||
DWORD ticks = GetTickCount();
|
||||
|
||||
// Multi-byte (UTF8) file path converted to UTF16
|
||||
WString databasePathW = StringUtils::Utf8ToUtf16(dbpath);
|
||||
|
||||
// Decompress the file if compression was enabled
|
||||
bool useCompression = !settingboolget("Engine", "DisableDatabaseCompression");
|
||||
LZ4_STATUS lzmaStatus = LZ4_INVALID_ARCHIVE;
|
||||
{
|
||||
lzmaStatus = LZ4_decompress_fileW(databasePathW.c_str(), databasePathW.c_str());
|
||||
|
||||
// Check return code
|
||||
if(useCompression && lzmaStatus != LZ4_SUCCESS && lzmaStatus != LZ4_INVALID_ARCHIVE)
|
||||
{
|
||||
dputs("\nInvalid database file!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the database file
|
||||
Handle hFile = CreateFileW(databasePathW.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
if(!hFile)
|
||||
{
|
||||
dputs("\nFailed to open database file!");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int jsonFileSize = GetFileSize(hFile, 0);
|
||||
if(!jsonFileSize)
|
||||
{
|
||||
dputs("\nEmpty database file!");
|
||||
return;
|
||||
}
|
||||
|
||||
Memory<char*> jsonText(jsonFileSize + 1);
|
||||
DWORD read = 0;
|
||||
if(!ReadFile(hFile, jsonText(), jsonFileSize, &read, 0))
|
||||
{
|
||||
dputs("\nFailed to read database file!");
|
||||
return;
|
||||
}
|
||||
hFile.Close();
|
||||
|
||||
// Deserialize JSON
|
||||
JSON root = json_loads(jsonText(), 0, 0);
|
||||
|
||||
if(lzmaStatus != LZ4_INVALID_ARCHIVE && useCompression)
|
||||
LZ4_compress_fileW(databasePathW.c_str(), databasePathW.c_str());
|
||||
|
||||
// Validate JSON load status
|
||||
if(!root)
|
||||
{
|
||||
dputs("\nInvalid database file (JSON)!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally load all structures
|
||||
CommentCacheLoad(root);
|
||||
LabelCacheLoad(root);
|
||||
BookmarkCacheLoad(root);
|
||||
FunctionCacheLoad(root);
|
||||
LoopCacheLoad(root);
|
||||
BpCacheLoad(root);
|
||||
|
||||
// Load notes
|
||||
const char* text = json_string_value(json_object_get(root, "notes"));
|
||||
GuiSetDebuggeeNotes(text);
|
||||
|
||||
// Free root
|
||||
json_decref(root);
|
||||
dprintf("%ums\n", GetTickCount() - ticks);
|
||||
}
|
||||
|
||||
void dbclose()
|
||||
{
|
||||
dbsave();
|
||||
CommentClear();
|
||||
LabelClear();
|
||||
BookmarkClear();
|
||||
FunctionClear();
|
||||
LoopClear();
|
||||
BpClear();
|
||||
PatchClear();
|
||||
}
|
||||
|
||||
///api functions
|
||||
bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
VirtualQueryEx(fdProcessInfo->hProcess, (const void*)base, &mbi, sizeof(mbi));
|
||||
uint size = mbi.RegionSize;
|
||||
Memory<void*> buffer(size, "apienumexports:buffer");
|
||||
if(!MemRead(base, buffer(), size))
|
||||
return false;
|
||||
IMAGE_NT_HEADERS* pnth = (IMAGE_NT_HEADERS*)((uint)buffer() + GetPE32DataFromMappedFile((ULONG_PTR)buffer(), 0, UE_PE_OFFSET));
|
||||
uint export_dir_rva = pnth->OptionalHeader.DataDirectory[0].VirtualAddress;
|
||||
uint export_dir_size = pnth->OptionalHeader.DataDirectory[0].Size;
|
||||
IMAGE_EXPORT_DIRECTORY export_dir;
|
||||
memset(&export_dir, 0, sizeof(export_dir));
|
||||
MemRead((export_dir_rva + base), &export_dir, sizeof(export_dir));
|
||||
unsigned int NumberOfNames = export_dir.NumberOfNames;
|
||||
if(!export_dir.NumberOfFunctions || !NumberOfNames) //no named exports
|
||||
return false;
|
||||
char modname[MAX_MODULE_SIZE] = "";
|
||||
ModNameFromAddr(base, modname, true);
|
||||
uint original_name_va = export_dir.Name + base;
|
||||
char original_name[deflen] = "";
|
||||
memset(original_name, 0, sizeof(original_name));
|
||||
MemRead(original_name_va, original_name, deflen);
|
||||
char* AddrOfFunctions_va = (char*)(export_dir.AddressOfFunctions + base); //not a valid local pointer
|
||||
char* AddrOfNames_va = (char*)(export_dir.AddressOfNames + base); //not a valid local pointer
|
||||
char* AddrOfNameOrdinals_va = (char*)(export_dir.AddressOfNameOrdinals + base); //not a valid local pointer
|
||||
for(DWORD i = 0; i < NumberOfNames; i++)
|
||||
{
|
||||
DWORD curAddrOfName = 0;
|
||||
MemRead((uint)(AddrOfNames_va + sizeof(DWORD)*i), &curAddrOfName, sizeof(DWORD));
|
||||
char* cur_name_va = (char*)(curAddrOfName + base);
|
||||
char cur_name[deflen] = "";
|
||||
memset(cur_name, 0, deflen);
|
||||
MemRead((uint)cur_name_va, cur_name, deflen);
|
||||
WORD curAddrOfNameOrdinals = 0;
|
||||
MemRead((uint)(AddrOfNameOrdinals_va + sizeof(WORD)*i), &curAddrOfNameOrdinals, sizeof(WORD));
|
||||
DWORD curFunctionRva = 0;
|
||||
MemRead((uint)(AddrOfFunctions_va + sizeof(DWORD)*curAddrOfNameOrdinals), &curFunctionRva, sizeof(DWORD));
|
||||
|
||||
if(curFunctionRva >= export_dir_rva && curFunctionRva < export_dir_rva + export_dir_size)
|
||||
{
|
||||
char forwarded_api[deflen] = "";
|
||||
memset(forwarded_api, 0, deflen);
|
||||
MemRead((curFunctionRva + base), forwarded_api, deflen);
|
||||
int len = (int)strlen(forwarded_api);
|
||||
int j = 0;
|
||||
while(forwarded_api[j] != '.' && j < len)
|
||||
j++;
|
||||
if(forwarded_api[j] == '.')
|
||||
{
|
||||
forwarded_api[j] = 0;
|
||||
HINSTANCE hTempDll = LoadLibraryExA(forwarded_api, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
|
||||
if(hTempDll)
|
||||
{
|
||||
uint local_addr = (uint)GetProcAddress(hTempDll, forwarded_api + j + 1);
|
||||
if(local_addr)
|
||||
{
|
||||
uint remote_addr = ImporterGetRemoteAPIAddress(fdProcessInfo->hProcess, local_addr);
|
||||
cbEnum(base, modname, cur_name, remote_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cbEnum(base, modname, cur_name, curFunctionRva + base);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,65 +1,65 @@
|
|||
#ifndef _ADDRINFO_H
|
||||
#define _ADDRINFO_H
|
||||
|
||||
#include "_global.h"
|
||||
#include <functional>
|
||||
|
||||
//ranges
|
||||
typedef std::pair<uint, uint> Range;
|
||||
typedef std::pair<uint, Range> ModuleRange; //modhash + RVA range
|
||||
typedef std::pair<int, ModuleRange> DepthModuleRange; //depth + modulerange
|
||||
|
||||
struct RangeCompare
|
||||
{
|
||||
bool operator()(const Range & a, const Range & b) //a before b?
|
||||
{
|
||||
return a.second < b.first;
|
||||
}
|
||||
};
|
||||
|
||||
struct OverlappingRangeCompare
|
||||
{
|
||||
bool operator()(const Range & a, const Range & b) //a before b?
|
||||
{
|
||||
return a.second < b.first || a.second < b.second;
|
||||
}
|
||||
};
|
||||
|
||||
struct ModuleRangeCompare
|
||||
{
|
||||
bool operator()(const ModuleRange & a, const ModuleRange & b)
|
||||
{
|
||||
if(a.first < b.first) //module hash is smaller
|
||||
return true;
|
||||
if(a.first != b.first) //module hashes are not equal
|
||||
return false;
|
||||
return a.second.second < b.second.first; //a.second is before b.second
|
||||
}
|
||||
};
|
||||
|
||||
struct DepthModuleRangeCompare
|
||||
{
|
||||
bool operator()(const DepthModuleRange & a, const DepthModuleRange & b)
|
||||
{
|
||||
if(a.first < b.first) //module depth is smaller
|
||||
return true;
|
||||
if(a.first != b.first) //module depths are not equal
|
||||
return false;
|
||||
if(a.second.first < b.second.first) //module hash is smaller
|
||||
return true;
|
||||
if(a.second.first != b.second.first) //module hashes are not equal
|
||||
return false;
|
||||
return a.second.second.second < b.second.second.first; //a.second.second is before b.second.second
|
||||
}
|
||||
};
|
||||
|
||||
//typedefs
|
||||
typedef std::function<void (uint base, const char* mod, const char* name, uint addr)> EXPORTENUMCALLBACK;
|
||||
|
||||
void dbsave();
|
||||
void dbload();
|
||||
void dbclose();
|
||||
|
||||
bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum);
|
||||
|
||||
#endif // _ADDRINFO_H
|
||||
#ifndef _ADDRINFO_H
|
||||
#define _ADDRINFO_H
|
||||
|
||||
#include "_global.h"
|
||||
#include <functional>
|
||||
|
||||
//ranges
|
||||
typedef std::pair<uint, uint> Range;
|
||||
typedef std::pair<uint, Range> ModuleRange; //modhash + RVA range
|
||||
typedef std::pair<int, ModuleRange> DepthModuleRange; //depth + modulerange
|
||||
|
||||
struct RangeCompare
|
||||
{
|
||||
bool operator()(const Range & a, const Range & b) //a before b?
|
||||
{
|
||||
return a.second < b.first;
|
||||
}
|
||||
};
|
||||
|
||||
struct OverlappingRangeCompare
|
||||
{
|
||||
bool operator()(const Range & a, const Range & b) //a before b?
|
||||
{
|
||||
return a.second < b.first || a.second < b.second;
|
||||
}
|
||||
};
|
||||
|
||||
struct ModuleRangeCompare
|
||||
{
|
||||
bool operator()(const ModuleRange & a, const ModuleRange & b)
|
||||
{
|
||||
if(a.first < b.first) //module hash is smaller
|
||||
return true;
|
||||
if(a.first != b.first) //module hashes are not equal
|
||||
return false;
|
||||
return a.second.second < b.second.first; //a.second is before b.second
|
||||
}
|
||||
};
|
||||
|
||||
struct DepthModuleRangeCompare
|
||||
{
|
||||
bool operator()(const DepthModuleRange & a, const DepthModuleRange & b)
|
||||
{
|
||||
if(a.first < b.first) //module depth is smaller
|
||||
return true;
|
||||
if(a.first != b.first) //module depths are not equal
|
||||
return false;
|
||||
if(a.second.first < b.second.first) //module hash is smaller
|
||||
return true;
|
||||
if(a.second.first != b.second.first) //module hashes are not equal
|
||||
return false;
|
||||
return a.second.second.second < b.second.second.first; //a.second.second is before b.second.second
|
||||
}
|
||||
};
|
||||
|
||||
//typedefs
|
||||
typedef std::function<void (uint base, const char* mod, const char* name, uint addr)> EXPORTENUMCALLBACK;
|
||||
|
||||
void dbsave();
|
||||
void dbload();
|
||||
void dbclose();
|
||||
|
||||
bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum);
|
||||
|
||||
#endif // _ADDRINFO_H
|
||||
|
|
@ -1,81 +1,81 @@
|
|||
/**
|
||||
@file assemble.cpp
|
||||
|
||||
@brief Implements the assemble class.
|
||||
*/
|
||||
|
||||
#include "assemble.h"
|
||||
#include "memory.h"
|
||||
#include "XEDParse\XEDParse.h"
|
||||
#include "value.h"
|
||||
#include "disasm_helper.h"
|
||||
|
||||
static bool cbUnknown(const char* text, ULONGLONG* value)
|
||||
{
|
||||
if(!text || !value)
|
||||
return false;
|
||||
uint val;
|
||||
if(!valfromstring(text, &val))
|
||||
return false;
|
||||
*value = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool assemble(uint addr, unsigned char* dest, int* size, const char* instruction, char* error)
|
||||
{
|
||||
if(strlen(instruction) >= XEDPARSE_MAXBUFSIZE)
|
||||
return false;
|
||||
XEDPARSE parse;
|
||||
memset(&parse, 0, sizeof(parse));
|
||||
#ifdef _WIN64
|
||||
parse.x64 = true;
|
||||
#else //x86
|
||||
parse.x64 = false;
|
||||
#endif
|
||||
parse.cbUnknown = cbUnknown;
|
||||
parse.cip = addr;
|
||||
strcpy_s(parse.instr, instruction);
|
||||
if(XEDParseAssemble(&parse) == XEDPARSE_ERROR)
|
||||
{
|
||||
if(error)
|
||||
strcpy_s(error, MAX_ERROR_SIZE, parse.error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(dest)
|
||||
memcpy(dest, parse.dest, parse.dest_size);
|
||||
if(size)
|
||||
*size = parse.dest_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool assembleat(uint addr, const char* instruction, int* size, char* error, bool fillnop)
|
||||
{
|
||||
int destSize;
|
||||
unsigned char dest[16];
|
||||
if(!assemble(addr, dest, &destSize, instruction, error))
|
||||
return false;
|
||||
//calculate the number of NOPs to insert
|
||||
int origLen = disasmgetsize(addr);
|
||||
while(origLen < destSize)
|
||||
origLen += disasmgetsize(addr + origLen);
|
||||
int nopsize = origLen - destSize;
|
||||
unsigned char nops[16];
|
||||
memset(nops, 0x90, sizeof(nops));
|
||||
|
||||
if(size)
|
||||
*size = destSize;
|
||||
|
||||
bool ret = MemPatch(addr, dest, destSize);
|
||||
if(ret && fillnop && nopsize)
|
||||
{
|
||||
if(size)
|
||||
*size += nopsize;
|
||||
|
||||
// Ignored if the memory patch for NOPs fail (although it should not)
|
||||
MemPatch(addr + destSize, nops, nopsize);
|
||||
}
|
||||
GuiUpdatePatches();
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
@file assemble.cpp
|
||||
|
||||
@brief Implements the assemble class.
|
||||
*/
|
||||
|
||||
#include "assemble.h"
|
||||
#include "memory.h"
|
||||
#include "XEDParse\XEDParse.h"
|
||||
#include "value.h"
|
||||
#include "disasm_helper.h"
|
||||
|
||||
static bool cbUnknown(const char* text, ULONGLONG* value)
|
||||
{
|
||||
if(!text || !value)
|
||||
return false;
|
||||
uint val;
|
||||
if(!valfromstring(text, &val))
|
||||
return false;
|
||||
*value = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool assemble(uint addr, unsigned char* dest, int* size, const char* instruction, char* error)
|
||||
{
|
||||
if(strlen(instruction) >= XEDPARSE_MAXBUFSIZE)
|
||||
return false;
|
||||
XEDPARSE parse;
|
||||
memset(&parse, 0, sizeof(parse));
|
||||
#ifdef _WIN64
|
||||
parse.x64 = true;
|
||||
#else //x86
|
||||
parse.x64 = false;
|
||||
#endif
|
||||
parse.cbUnknown = cbUnknown;
|
||||
parse.cip = addr;
|
||||
strcpy_s(parse.instr, instruction);
|
||||
if(XEDParseAssemble(&parse) == XEDPARSE_ERROR)
|
||||
{
|
||||
if(error)
|
||||
strcpy_s(error, MAX_ERROR_SIZE, parse.error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(dest)
|
||||
memcpy(dest, parse.dest, parse.dest_size);
|
||||
if(size)
|
||||
*size = parse.dest_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool assembleat(uint addr, const char* instruction, int* size, char* error, bool fillnop)
|
||||
{
|
||||
int destSize;
|
||||
unsigned char dest[16];
|
||||
if(!assemble(addr, dest, &destSize, instruction, error))
|
||||
return false;
|
||||
//calculate the number of NOPs to insert
|
||||
int origLen = disasmgetsize(addr);
|
||||
while(origLen < destSize)
|
||||
origLen += disasmgetsize(addr + origLen);
|
||||
int nopsize = origLen - destSize;
|
||||
unsigned char nops[16];
|
||||
memset(nops, 0x90, sizeof(nops));
|
||||
|
||||
if(size)
|
||||
*size = destSize;
|
||||
|
||||
bool ret = MemPatch(addr, dest, destSize);
|
||||
if(ret && fillnop && nopsize)
|
||||
{
|
||||
if(size)
|
||||
*size += nopsize;
|
||||
|
||||
// Ignored if the memory patch for NOPs fail (although it should not)
|
||||
MemPatch(addr + destSize, nops, nopsize);
|
||||
}
|
||||
GuiUpdatePatches();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef _ASSEMBLE_H
|
||||
#define _ASSEMBLE_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
bool assemble(uint addr, unsigned char* dest, int* size, const char* instruction, char* error);
|
||||
bool assembleat(uint addr, const char* instruction, int* size, char* error, bool fillnop);
|
||||
|
||||
#endif // _ASSEMBLE_H
|
||||
#ifndef _ASSEMBLE_H
|
||||
#define _ASSEMBLE_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
bool assemble(uint addr, unsigned char* dest, int* size, const char* instruction, char* error);
|
||||
bool assembleat(uint addr, const char* instruction, int* size, char* error, bool fillnop);
|
||||
|
||||
#endif // _ASSEMBLE_H
|
||||
|
|
@ -1,209 +1,209 @@
|
|||
#include "bookmark.h"
|
||||
#include "threading.h"
|
||||
#include "module.h"
|
||||
#include "memory.h"
|
||||
|
||||
std::unordered_map<uint, BOOKMARKSINFO> bookmarks;
|
||||
|
||||
bool BookmarkSet(uint Address, bool Manual)
|
||||
{
|
||||
// CHECK: Export call
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// Validate the incoming address
|
||||
if(!MemIsValidReadPtr(Address))
|
||||
return false;
|
||||
|
||||
BOOKMARKSINFO bookmark;
|
||||
ModNameFromAddr(Address, bookmark.mod, true);
|
||||
bookmark.addr = Address - ModBaseFromAddr(Address);
|
||||
bookmark.manual = Manual;
|
||||
|
||||
// Exclusive lock to insert new data
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
|
||||
if(!bookmarks.insert(std::make_pair(ModHashFromAddr(Address), bookmark)).second)
|
||||
{
|
||||
EXCLUSIVE_RELEASE();
|
||||
return BookmarkDelete(Address);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BookmarkGet(uint Address)
|
||||
{
|
||||
// CHECK: Export call
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockBookmarks);
|
||||
return (bookmarks.count(ModHashFromAddr(Address)) > 0);
|
||||
}
|
||||
|
||||
bool BookmarkDelete(uint Address)
|
||||
{
|
||||
// CHECK: Export call
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
return (bookmarks.erase(ModHashFromAddr(Address)) > 0);
|
||||
}
|
||||
|
||||
void BookmarkDelRange(uint Start, uint End)
|
||||
{
|
||||
// CHECK: Export call
|
||||
if(!DbgIsDebugging())
|
||||
return;
|
||||
|
||||
// Are all bookmarks going to be deleted?
|
||||
// 0x00000000 - 0xFFFFFFFF
|
||||
if(Start == 0 && End == ~0)
|
||||
{
|
||||
BookmarkClear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure 'Start' and 'End' reference the same module
|
||||
uint moduleBase = ModBaseFromAddr(Start);
|
||||
|
||||
if(moduleBase != ModBaseFromAddr(End))
|
||||
return;
|
||||
|
||||
// Virtual -> relative offset
|
||||
Start -= moduleBase;
|
||||
End -= moduleBase;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
for(auto itr = bookmarks.begin(); itr != bookmarks.end();)
|
||||
{
|
||||
const auto & currentBookmark = itr->second;
|
||||
|
||||
// Ignore manually set entries
|
||||
if(currentBookmark.manual)
|
||||
{
|
||||
++itr;
|
||||
continue;
|
||||
}
|
||||
|
||||
// [Start, End)
|
||||
if(currentBookmark.addr >= Start && currentBookmark.addr < End)
|
||||
itr = bookmarks.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BookmarkCacheSave(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
|
||||
const JSON jsonBookmarks = json_array();
|
||||
const JSON jsonAutoBookmarks = json_array();
|
||||
|
||||
// Save to the JSON root
|
||||
for(auto & itr : bookmarks)
|
||||
{
|
||||
JSON currentBookmark = json_object();
|
||||
|
||||
json_object_set_new(currentBookmark, "module", json_string(itr.second.mod));
|
||||
json_object_set_new(currentBookmark, "address", json_hex(itr.second.addr));
|
||||
|
||||
if(itr.second.manual)
|
||||
json_array_append_new(jsonBookmarks, currentBookmark);
|
||||
else
|
||||
json_array_append_new(jsonAutoBookmarks, currentBookmark);
|
||||
}
|
||||
|
||||
if(json_array_size(jsonBookmarks))
|
||||
json_object_set(Root, "bookmarks", jsonBookmarks);
|
||||
|
||||
if(json_array_size(jsonAutoBookmarks))
|
||||
json_object_set(Root, "autobookmarks", jsonAutoBookmarks);
|
||||
|
||||
json_decref(jsonBookmarks);
|
||||
json_decref(jsonAutoBookmarks);
|
||||
}
|
||||
|
||||
void BookmarkCacheLoad(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
|
||||
// Inline lambda to parse each JSON entry
|
||||
auto AddBookmarks = [](const JSON Object, bool Manual)
|
||||
{
|
||||
size_t i;
|
||||
JSON value;
|
||||
|
||||
json_array_foreach(Object, i, value)
|
||||
{
|
||||
BOOKMARKSINFO bookmarkInfo;
|
||||
memset(&bookmarkInfo, 0, sizeof(BOOKMARKSINFO));
|
||||
|
||||
// Load the module name
|
||||
const char* mod = json_string_value(json_object_get(value, "module"));
|
||||
|
||||
if(mod && strlen(mod) < MAX_MODULE_SIZE)
|
||||
strcpy_s(bookmarkInfo.mod, mod);
|
||||
|
||||
// Load address and set auto-generated flag
|
||||
bookmarkInfo.addr = (uint)json_hex_value(json_object_get(value, "address"));
|
||||
bookmarkInfo.manual = Manual;
|
||||
|
||||
const uint key = ModHashFromName(bookmarkInfo.mod) + bookmarkInfo.addr;
|
||||
bookmarks.insert(std::make_pair(key, bookmarkInfo));
|
||||
}
|
||||
};
|
||||
|
||||
// Remove existing entries
|
||||
bookmarks.clear();
|
||||
|
||||
const JSON jsonBookmarks = json_object_get(Root, "bookmarks");
|
||||
const JSON jsonAutoBookmarks = json_object_get(Root, "autobookmarks");
|
||||
|
||||
// Load user-set bookmarks
|
||||
if(jsonBookmarks)
|
||||
AddBookmarks(jsonBookmarks, true);
|
||||
|
||||
// Load auto-set bookmarks
|
||||
if(jsonAutoBookmarks)
|
||||
AddBookmarks(jsonAutoBookmarks, false);
|
||||
}
|
||||
|
||||
bool BookmarkEnum(BOOKMARKSINFO* List, size_t* Size)
|
||||
{
|
||||
// The array container must be set, or the size must be set, or both
|
||||
if(!List && !Size)
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockBookmarks);
|
||||
|
||||
// Return the size if set
|
||||
if(Size)
|
||||
{
|
||||
*Size = bookmarks.size() * sizeof(BOOKMARKSINFO);
|
||||
|
||||
if(!List)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copy struct and adjust the relative offset to a virtual address
|
||||
for(auto & itr : bookmarks)
|
||||
{
|
||||
*List = itr.second;
|
||||
List->addr += ModBaseFromName(List->mod);
|
||||
|
||||
List++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BookmarkClear()
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
bookmarks.clear();
|
||||
#include "bookmark.h"
|
||||
#include "threading.h"
|
||||
#include "module.h"
|
||||
#include "memory.h"
|
||||
|
||||
std::unordered_map<uint, BOOKMARKSINFO> bookmarks;
|
||||
|
||||
bool BookmarkSet(uint Address, bool Manual)
|
||||
{
|
||||
// CHECK: Export call
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// Validate the incoming address
|
||||
if(!MemIsValidReadPtr(Address))
|
||||
return false;
|
||||
|
||||
BOOKMARKSINFO bookmark;
|
||||
ModNameFromAddr(Address, bookmark.mod, true);
|
||||
bookmark.addr = Address - ModBaseFromAddr(Address);
|
||||
bookmark.manual = Manual;
|
||||
|
||||
// Exclusive lock to insert new data
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
|
||||
if(!bookmarks.insert(std::make_pair(ModHashFromAddr(Address), bookmark)).second)
|
||||
{
|
||||
EXCLUSIVE_RELEASE();
|
||||
return BookmarkDelete(Address);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BookmarkGet(uint Address)
|
||||
{
|
||||
// CHECK: Export call
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockBookmarks);
|
||||
return (bookmarks.count(ModHashFromAddr(Address)) > 0);
|
||||
}
|
||||
|
||||
bool BookmarkDelete(uint Address)
|
||||
{
|
||||
// CHECK: Export call
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
return (bookmarks.erase(ModHashFromAddr(Address)) > 0);
|
||||
}
|
||||
|
||||
void BookmarkDelRange(uint Start, uint End)
|
||||
{
|
||||
// CHECK: Export call
|
||||
if(!DbgIsDebugging())
|
||||
return;
|
||||
|
||||
// Are all bookmarks going to be deleted?
|
||||
// 0x00000000 - 0xFFFFFFFF
|
||||
if(Start == 0 && End == ~0)
|
||||
{
|
||||
BookmarkClear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure 'Start' and 'End' reference the same module
|
||||
uint moduleBase = ModBaseFromAddr(Start);
|
||||
|
||||
if(moduleBase != ModBaseFromAddr(End))
|
||||
return;
|
||||
|
||||
// Virtual -> relative offset
|
||||
Start -= moduleBase;
|
||||
End -= moduleBase;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
for(auto itr = bookmarks.begin(); itr != bookmarks.end();)
|
||||
{
|
||||
const auto & currentBookmark = itr->second;
|
||||
|
||||
// Ignore manually set entries
|
||||
if(currentBookmark.manual)
|
||||
{
|
||||
++itr;
|
||||
continue;
|
||||
}
|
||||
|
||||
// [Start, End)
|
||||
if(currentBookmark.addr >= Start && currentBookmark.addr < End)
|
||||
itr = bookmarks.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BookmarkCacheSave(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
|
||||
const JSON jsonBookmarks = json_array();
|
||||
const JSON jsonAutoBookmarks = json_array();
|
||||
|
||||
// Save to the JSON root
|
||||
for(auto & itr : bookmarks)
|
||||
{
|
||||
JSON currentBookmark = json_object();
|
||||
|
||||
json_object_set_new(currentBookmark, "module", json_string(itr.second.mod));
|
||||
json_object_set_new(currentBookmark, "address", json_hex(itr.second.addr));
|
||||
|
||||
if(itr.second.manual)
|
||||
json_array_append_new(jsonBookmarks, currentBookmark);
|
||||
else
|
||||
json_array_append_new(jsonAutoBookmarks, currentBookmark);
|
||||
}
|
||||
|
||||
if(json_array_size(jsonBookmarks))
|
||||
json_object_set(Root, "bookmarks", jsonBookmarks);
|
||||
|
||||
if(json_array_size(jsonAutoBookmarks))
|
||||
json_object_set(Root, "autobookmarks", jsonAutoBookmarks);
|
||||
|
||||
json_decref(jsonBookmarks);
|
||||
json_decref(jsonAutoBookmarks);
|
||||
}
|
||||
|
||||
void BookmarkCacheLoad(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
|
||||
// Inline lambda to parse each JSON entry
|
||||
auto AddBookmarks = [](const JSON Object, bool Manual)
|
||||
{
|
||||
size_t i;
|
||||
JSON value;
|
||||
|
||||
json_array_foreach(Object, i, value)
|
||||
{
|
||||
BOOKMARKSINFO bookmarkInfo;
|
||||
memset(&bookmarkInfo, 0, sizeof(BOOKMARKSINFO));
|
||||
|
||||
// Load the module name
|
||||
const char* mod = json_string_value(json_object_get(value, "module"));
|
||||
|
||||
if(mod && strlen(mod) < MAX_MODULE_SIZE)
|
||||
strcpy_s(bookmarkInfo.mod, mod);
|
||||
|
||||
// Load address and set auto-generated flag
|
||||
bookmarkInfo.addr = (uint)json_hex_value(json_object_get(value, "address"));
|
||||
bookmarkInfo.manual = Manual;
|
||||
|
||||
const uint key = ModHashFromName(bookmarkInfo.mod) + bookmarkInfo.addr;
|
||||
bookmarks.insert(std::make_pair(key, bookmarkInfo));
|
||||
}
|
||||
};
|
||||
|
||||
// Remove existing entries
|
||||
bookmarks.clear();
|
||||
|
||||
const JSON jsonBookmarks = json_object_get(Root, "bookmarks");
|
||||
const JSON jsonAutoBookmarks = json_object_get(Root, "autobookmarks");
|
||||
|
||||
// Load user-set bookmarks
|
||||
if(jsonBookmarks)
|
||||
AddBookmarks(jsonBookmarks, true);
|
||||
|
||||
// Load auto-set bookmarks
|
||||
if(jsonAutoBookmarks)
|
||||
AddBookmarks(jsonAutoBookmarks, false);
|
||||
}
|
||||
|
||||
bool BookmarkEnum(BOOKMARKSINFO* List, size_t* Size)
|
||||
{
|
||||
// The array container must be set, or the size must be set, or both
|
||||
if(!List && !Size)
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockBookmarks);
|
||||
|
||||
// Return the size if set
|
||||
if(Size)
|
||||
{
|
||||
*Size = bookmarks.size() * sizeof(BOOKMARKSINFO);
|
||||
|
||||
if(!List)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copy struct and adjust the relative offset to a virtual address
|
||||
for(auto & itr : bookmarks)
|
||||
{
|
||||
*List = itr.second;
|
||||
List->addr += ModBaseFromName(List->mod);
|
||||
|
||||
List++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BookmarkClear()
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBookmarks);
|
||||
bookmarks.clear();
|
||||
}
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
struct BOOKMARKSINFO
|
||||
{
|
||||
char mod[MAX_MODULE_SIZE];
|
||||
uint addr;
|
||||
bool manual;
|
||||
};
|
||||
|
||||
bool BookmarkSet(uint Address, bool Manual);
|
||||
bool BookmarkGet(uint Address);
|
||||
bool BookmarkDelete(uint Address);
|
||||
void BookmarkDelRange(uint Start, uint End);
|
||||
void BookmarkCacheSave(JSON Root);
|
||||
void BookmarkCacheLoad(JSON Root);
|
||||
bool BookmarkEnum(BOOKMARKSINFO* List, size_t* Size);
|
||||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
struct BOOKMARKSINFO
|
||||
{
|
||||
char mod[MAX_MODULE_SIZE];
|
||||
uint addr;
|
||||
bool manual;
|
||||
};
|
||||
|
||||
bool BookmarkSet(uint Address, bool Manual);
|
||||
bool BookmarkGet(uint Address);
|
||||
bool BookmarkDelete(uint Address);
|
||||
void BookmarkDelRange(uint Start, uint End);
|
||||
void BookmarkCacheSave(JSON Root);
|
||||
void BookmarkCacheLoad(JSON Root);
|
||||
bool BookmarkEnum(BOOKMARKSINFO* List, size_t* Size);
|
||||
void BookmarkClear();
|
||||
|
|
@ -1,406 +1,406 @@
|
|||
/**
|
||||
@file breakpoint.cpp
|
||||
|
||||
@brief Implements the breakpoint class.
|
||||
*/
|
||||
|
||||
#include "breakpoint.h"
|
||||
#include "memory.h"
|
||||
#include "threading.h"
|
||||
#include "module.h"
|
||||
|
||||
typedef std::pair<BP_TYPE, uint> BreakpointKey;
|
||||
std::map<BreakpointKey, BREAKPOINT> breakpoints;
|
||||
|
||||
BREAKPOINT* BpInfoFromAddr(BP_TYPE Type, uint Address)
|
||||
{
|
||||
//
|
||||
// NOTE: THIS DOES _NOT_ USE LOCKS
|
||||
//
|
||||
auto found = breakpoints.find(BreakpointKey(Type, ModHashFromAddr(Address)));
|
||||
|
||||
// Was the module found with this address?
|
||||
if(found == breakpoints.end())
|
||||
return nullptr;
|
||||
|
||||
return &found->second;
|
||||
}
|
||||
|
||||
int BpGetList(std::vector<BREAKPOINT>* List)
|
||||
{
|
||||
// CHECK: Exported function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Did the caller request an output?
|
||||
if(List)
|
||||
{
|
||||
// Enumerate all breakpoints in the global list, fixing the relative
|
||||
// offset to a virtual address
|
||||
for(auto & i : breakpoints)
|
||||
{
|
||||
BREAKPOINT currentBp = i.second;
|
||||
currentBp.addr += ModBaseFromName(currentBp.mod);
|
||||
currentBp.active = MemIsValidReadPtr(currentBp.addr);
|
||||
|
||||
List->push_back(currentBp);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)breakpoints.size();
|
||||
}
|
||||
|
||||
bool BpNew(uint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE Type, DWORD TitanType, const char* Name)
|
||||
{
|
||||
// CHECK: Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// Fail if the address is a bad memory region
|
||||
if(!MemIsValidReadPtr(Address))
|
||||
return false;
|
||||
|
||||
// Fail if the breakpoint already exists
|
||||
if(BpGet(Address, Type, Name, nullptr))
|
||||
return false;
|
||||
|
||||
// Default to an empty name if one wasn't supplied
|
||||
if(!Name)
|
||||
Name = "";
|
||||
|
||||
BREAKPOINT bp;
|
||||
memset(&bp, 0, sizeof(BREAKPOINT));
|
||||
|
||||
ModNameFromAddr(Address, bp.mod, true);
|
||||
strcpy_s(bp.name, Name);
|
||||
|
||||
bp.active = true;
|
||||
bp.addr = Address - ModBaseFromAddr(Address);
|
||||
bp.enabled = Enable;
|
||||
bp.oldbytes = OldBytes;
|
||||
bp.singleshoot = Singleshot;
|
||||
bp.titantype = TitanType;
|
||||
bp.type = Type;
|
||||
|
||||
// Insert new entry to the global list
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
breakpoints.insert(std::make_pair(BreakpointKey(Type, ModHashFromAddr(Address)), bp));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BpGet(uint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
|
||||
{
|
||||
// CHECK: Export/Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Name is optional
|
||||
if(!Name || Name[0] == '\0')
|
||||
{
|
||||
// Perform a lookup by address only
|
||||
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
|
||||
|
||||
if(!bpInfo)
|
||||
return false;
|
||||
|
||||
// Succeed even if the user didn't request anything
|
||||
if(!Bp)
|
||||
return true;
|
||||
|
||||
*Bp = *bpInfo;
|
||||
Bp->addr += ModBaseFromAddr(Address);
|
||||
Bp->active = MemIsValidReadPtr(Bp->addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do a lookup by breakpoint name
|
||||
for(auto & i : breakpoints)
|
||||
{
|
||||
// Do the names match?
|
||||
if(strcmp(Name, i.second.name) != 0)
|
||||
continue;
|
||||
|
||||
// Fill out the optional user buffer
|
||||
if(Bp)
|
||||
{
|
||||
*Bp = i.second;
|
||||
Bp->addr += ModBaseFromAddr(Address);
|
||||
Bp->active = MemIsValidReadPtr(Bp->addr);
|
||||
}
|
||||
|
||||
// Return true if the name was found at all
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BpDelete(uint Address, BP_TYPE Type)
|
||||
{
|
||||
// CHECK: Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// Erase the index from the global list
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
return (breakpoints.erase(BreakpointKey(Type, ModHashFromAddr(Address))) > 0);
|
||||
}
|
||||
|
||||
bool BpEnable(uint Address, BP_TYPE Type, bool Enable)
|
||||
{
|
||||
// CHECK: Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Check if the breakpoint exists first
|
||||
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
|
||||
|
||||
if(!bpInfo)
|
||||
return false;
|
||||
|
||||
bpInfo->enabled = Enable;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BpSetName(uint Address, BP_TYPE Type, const char* Name)
|
||||
{
|
||||
// CHECK: Future(?); This is not used anywhere
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// If a name wasn't supplied, set to nothing
|
||||
if(!Name)
|
||||
Name = "";
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Check if the breakpoint exists first
|
||||
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
|
||||
|
||||
if(!bpInfo)
|
||||
return false;
|
||||
|
||||
strcpy_s(bpInfo->name, Name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BpSetTitanType(uint Address, BP_TYPE Type, int TitanType)
|
||||
{
|
||||
// CHECK: Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Set the TitanEngine type, separate from BP_TYPE
|
||||
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
|
||||
|
||||
if(!bpInfo)
|
||||
return false;
|
||||
|
||||
bpInfo->titantype = TitanType;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module)
|
||||
{
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Loop each entry, executing the user's callback
|
||||
bool callbackStatus = true;
|
||||
|
||||
auto i = breakpoints.begin();
|
||||
while(i != breakpoints.end())
|
||||
{
|
||||
auto j = i;
|
||||
++i; //increment here, because the callback might remove the current entry
|
||||
|
||||
// If a module name was sent, check it
|
||||
if(Module && Module[0] != '\0')
|
||||
{
|
||||
if(strcmp(j->second.mod, Module) != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
BREAKPOINT bpInfo = j->second;
|
||||
bpInfo.addr += ModBaseFromName(bpInfo.mod);
|
||||
bpInfo.active = MemIsValidReadPtr(bpInfo.addr);
|
||||
|
||||
// Lock must be released due to callback sub-locks
|
||||
SHARED_RELEASE()
|
||||
|
||||
// Execute the callback
|
||||
if(!EnumCallback(&bpInfo))
|
||||
callbackStatus = false;
|
||||
|
||||
// Restore the breakpoint map lock
|
||||
SHARED_REACQUIRE();
|
||||
}
|
||||
|
||||
return callbackStatus;
|
||||
}
|
||||
|
||||
bool BpEnumAll(BPENUMCALLBACK EnumCallback)
|
||||
{
|
||||
return BpEnumAll(EnumCallback, nullptr);
|
||||
}
|
||||
|
||||
int BpGetCount(BP_TYPE Type, bool EnabledOnly)
|
||||
{
|
||||
SHARED_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Count the number of enabled/disabled breakpoint types
|
||||
int count = 0;
|
||||
|
||||
for(auto & i : breakpoints)
|
||||
{
|
||||
// Check if the type matches
|
||||
if(i.first.first != Type)
|
||||
continue;
|
||||
|
||||
// If it's not enabled, skip it
|
||||
if(EnabledOnly && !i.second.enabled)
|
||||
continue;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp)
|
||||
{
|
||||
//
|
||||
// Convert a debugger breakpoint to an open/exported
|
||||
// bridge breakpoint
|
||||
//
|
||||
// TOOD: ASSERT(?) These should never be null
|
||||
if(!Bp || !BridgeBp)
|
||||
return;
|
||||
|
||||
memset(BridgeBp, 0, sizeof(BRIDGEBP));
|
||||
strcpy_s(BridgeBp->mod, Bp->mod);
|
||||
strcpy_s(BridgeBp->name, Bp->name);
|
||||
|
||||
BridgeBp->active = Bp->active;
|
||||
BridgeBp->addr = Bp->addr;
|
||||
BridgeBp->enabled = Bp->enabled;
|
||||
BridgeBp->singleshoot = Bp->singleshoot;
|
||||
|
||||
switch(Bp->type)
|
||||
{
|
||||
case BPNORMAL:
|
||||
BridgeBp->type = bp_normal;
|
||||
break;
|
||||
case BPHARDWARE:
|
||||
BridgeBp->type = bp_hardware;
|
||||
break;
|
||||
case BPMEMORY:
|
||||
BridgeBp->type = bp_memory;
|
||||
break;
|
||||
default:
|
||||
BridgeBp->type = bp_none;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BpCacheSave(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Create a JSON array to store each sub-object with a breakpoint
|
||||
const JSON jsonBreakpoints = json_array();
|
||||
|
||||
// Loop all breakpoints
|
||||
for(auto & i : breakpoints)
|
||||
{
|
||||
auto & breakpoint = i.second;
|
||||
|
||||
// Ignore single-shot breakpoints
|
||||
if(breakpoint.singleshoot)
|
||||
continue;
|
||||
|
||||
JSON jsonObj = json_object();
|
||||
json_object_set_new(jsonObj, "address", json_hex(breakpoint.addr));
|
||||
json_object_set_new(jsonObj, "enabled", json_boolean(breakpoint.enabled));
|
||||
|
||||
// "Normal" breakpoints save the old data
|
||||
if(breakpoint.type == BPNORMAL)
|
||||
json_object_set_new(jsonObj, "oldbytes", json_hex(breakpoint.oldbytes));
|
||||
|
||||
json_object_set_new(jsonObj, "type", json_integer(breakpoint.type));
|
||||
json_object_set_new(jsonObj, "titantype", json_hex(breakpoint.titantype));
|
||||
json_object_set_new(jsonObj, "name", json_string(breakpoint.name));
|
||||
json_object_set_new(jsonObj, "module", json_string(breakpoint.mod));
|
||||
json_array_append_new(jsonBreakpoints, jsonObj);
|
||||
}
|
||||
|
||||
if(json_array_size(jsonBreakpoints))
|
||||
json_object_set(Root, "breakpoints", jsonBreakpoints);
|
||||
|
||||
// Notify garbage collector
|
||||
json_decref(jsonBreakpoints);
|
||||
}
|
||||
|
||||
void BpCacheLoad(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Remove all existing elements
|
||||
breakpoints.clear();
|
||||
|
||||
// Get a handle to the root object -> breakpoints subtree
|
||||
const JSON jsonBreakpoints = json_object_get(Root, "breakpoints");
|
||||
|
||||
// Return if there was nothing to load
|
||||
if(!jsonBreakpoints)
|
||||
return;
|
||||
|
||||
size_t i;
|
||||
JSON value;
|
||||
json_array_foreach(jsonBreakpoints, i, value)
|
||||
{
|
||||
BREAKPOINT breakpoint;
|
||||
memset(&breakpoint, 0, sizeof(BREAKPOINT));
|
||||
|
||||
if(breakpoint.type == BPNORMAL)
|
||||
breakpoint.oldbytes = (short)json_hex_value(json_object_get(value, "oldbytes"));
|
||||
breakpoint.type = (BP_TYPE)json_integer_value(json_object_get(value, "type"));
|
||||
breakpoint.addr = (uint)json_hex_value(json_object_get(value, "address"));
|
||||
breakpoint.enabled = json_boolean_value(json_object_get(value, "enabled"));
|
||||
breakpoint.titantype = (DWORD)json_hex_value(json_object_get(value, "titantype"));
|
||||
|
||||
// Name
|
||||
const char* name = json_string_value(json_object_get(value, "name"));
|
||||
|
||||
if(name)
|
||||
strcpy_s(breakpoint.name, name);
|
||||
|
||||
// Module
|
||||
const char* mod = json_string_value(json_object_get(value, "module"));
|
||||
|
||||
if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE)
|
||||
strcpy_s(breakpoint.mod, mod);
|
||||
|
||||
// Build the hash map key: MOD_HASH + ADDRESS
|
||||
const uint key = ModHashFromName(breakpoint.mod) + breakpoint.addr;
|
||||
breakpoints.insert(std::make_pair(BreakpointKey(breakpoint.type, key), breakpoint));
|
||||
}
|
||||
}
|
||||
|
||||
void BpClear()
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
breakpoints.clear();
|
||||
/**
|
||||
@file breakpoint.cpp
|
||||
|
||||
@brief Implements the breakpoint class.
|
||||
*/
|
||||
|
||||
#include "breakpoint.h"
|
||||
#include "memory.h"
|
||||
#include "threading.h"
|
||||
#include "module.h"
|
||||
|
||||
typedef std::pair<BP_TYPE, uint> BreakpointKey;
|
||||
std::map<BreakpointKey, BREAKPOINT> breakpoints;
|
||||
|
||||
BREAKPOINT* BpInfoFromAddr(BP_TYPE Type, uint Address)
|
||||
{
|
||||
//
|
||||
// NOTE: THIS DOES _NOT_ USE LOCKS
|
||||
//
|
||||
auto found = breakpoints.find(BreakpointKey(Type, ModHashFromAddr(Address)));
|
||||
|
||||
// Was the module found with this address?
|
||||
if(found == breakpoints.end())
|
||||
return nullptr;
|
||||
|
||||
return &found->second;
|
||||
}
|
||||
|
||||
int BpGetList(std::vector<BREAKPOINT>* List)
|
||||
{
|
||||
// CHECK: Exported function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Did the caller request an output?
|
||||
if(List)
|
||||
{
|
||||
// Enumerate all breakpoints in the global list, fixing the relative
|
||||
// offset to a virtual address
|
||||
for(auto & i : breakpoints)
|
||||
{
|
||||
BREAKPOINT currentBp = i.second;
|
||||
currentBp.addr += ModBaseFromName(currentBp.mod);
|
||||
currentBp.active = MemIsValidReadPtr(currentBp.addr);
|
||||
|
||||
List->push_back(currentBp);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)breakpoints.size();
|
||||
}
|
||||
|
||||
bool BpNew(uint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE Type, DWORD TitanType, const char* Name)
|
||||
{
|
||||
// CHECK: Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// Fail if the address is a bad memory region
|
||||
if(!MemIsValidReadPtr(Address))
|
||||
return false;
|
||||
|
||||
// Fail if the breakpoint already exists
|
||||
if(BpGet(Address, Type, Name, nullptr))
|
||||
return false;
|
||||
|
||||
// Default to an empty name if one wasn't supplied
|
||||
if(!Name)
|
||||
Name = "";
|
||||
|
||||
BREAKPOINT bp;
|
||||
memset(&bp, 0, sizeof(BREAKPOINT));
|
||||
|
||||
ModNameFromAddr(Address, bp.mod, true);
|
||||
strcpy_s(bp.name, Name);
|
||||
|
||||
bp.active = true;
|
||||
bp.addr = Address - ModBaseFromAddr(Address);
|
||||
bp.enabled = Enable;
|
||||
bp.oldbytes = OldBytes;
|
||||
bp.singleshoot = Singleshot;
|
||||
bp.titantype = TitanType;
|
||||
bp.type = Type;
|
||||
|
||||
// Insert new entry to the global list
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
breakpoints.insert(std::make_pair(BreakpointKey(Type, ModHashFromAddr(Address)), bp));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BpGet(uint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
|
||||
{
|
||||
// CHECK: Export/Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Name is optional
|
||||
if(!Name || Name[0] == '\0')
|
||||
{
|
||||
// Perform a lookup by address only
|
||||
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
|
||||
|
||||
if(!bpInfo)
|
||||
return false;
|
||||
|
||||
// Succeed even if the user didn't request anything
|
||||
if(!Bp)
|
||||
return true;
|
||||
|
||||
*Bp = *bpInfo;
|
||||
Bp->addr += ModBaseFromAddr(Address);
|
||||
Bp->active = MemIsValidReadPtr(Bp->addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do a lookup by breakpoint name
|
||||
for(auto & i : breakpoints)
|
||||
{
|
||||
// Do the names match?
|
||||
if(strcmp(Name, i.second.name) != 0)
|
||||
continue;
|
||||
|
||||
// Fill out the optional user buffer
|
||||
if(Bp)
|
||||
{
|
||||
*Bp = i.second;
|
||||
Bp->addr += ModBaseFromAddr(Address);
|
||||
Bp->active = MemIsValidReadPtr(Bp->addr);
|
||||
}
|
||||
|
||||
// Return true if the name was found at all
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BpDelete(uint Address, BP_TYPE Type)
|
||||
{
|
||||
// CHECK: Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// Erase the index from the global list
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
return (breakpoints.erase(BreakpointKey(Type, ModHashFromAddr(Address))) > 0);
|
||||
}
|
||||
|
||||
bool BpEnable(uint Address, BP_TYPE Type, bool Enable)
|
||||
{
|
||||
// CHECK: Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Check if the breakpoint exists first
|
||||
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
|
||||
|
||||
if(!bpInfo)
|
||||
return false;
|
||||
|
||||
bpInfo->enabled = Enable;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BpSetName(uint Address, BP_TYPE Type, const char* Name)
|
||||
{
|
||||
// CHECK: Future(?); This is not used anywhere
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// If a name wasn't supplied, set to nothing
|
||||
if(!Name)
|
||||
Name = "";
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Check if the breakpoint exists first
|
||||
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
|
||||
|
||||
if(!bpInfo)
|
||||
return false;
|
||||
|
||||
strcpy_s(bpInfo->name, Name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BpSetTitanType(uint Address, BP_TYPE Type, int TitanType)
|
||||
{
|
||||
// CHECK: Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Set the TitanEngine type, separate from BP_TYPE
|
||||
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
|
||||
|
||||
if(!bpInfo)
|
||||
return false;
|
||||
|
||||
bpInfo->titantype = TitanType;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module)
|
||||
{
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Loop each entry, executing the user's callback
|
||||
bool callbackStatus = true;
|
||||
|
||||
auto i = breakpoints.begin();
|
||||
while(i != breakpoints.end())
|
||||
{
|
||||
auto j = i;
|
||||
++i; //increment here, because the callback might remove the current entry
|
||||
|
||||
// If a module name was sent, check it
|
||||
if(Module && Module[0] != '\0')
|
||||
{
|
||||
if(strcmp(j->second.mod, Module) != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
BREAKPOINT bpInfo = j->second;
|
||||
bpInfo.addr += ModBaseFromName(bpInfo.mod);
|
||||
bpInfo.active = MemIsValidReadPtr(bpInfo.addr);
|
||||
|
||||
// Lock must be released due to callback sub-locks
|
||||
SHARED_RELEASE()
|
||||
|
||||
// Execute the callback
|
||||
if(!EnumCallback(&bpInfo))
|
||||
callbackStatus = false;
|
||||
|
||||
// Restore the breakpoint map lock
|
||||
SHARED_REACQUIRE();
|
||||
}
|
||||
|
||||
return callbackStatus;
|
||||
}
|
||||
|
||||
bool BpEnumAll(BPENUMCALLBACK EnumCallback)
|
||||
{
|
||||
return BpEnumAll(EnumCallback, nullptr);
|
||||
}
|
||||
|
||||
int BpGetCount(BP_TYPE Type, bool EnabledOnly)
|
||||
{
|
||||
SHARED_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Count the number of enabled/disabled breakpoint types
|
||||
int count = 0;
|
||||
|
||||
for(auto & i : breakpoints)
|
||||
{
|
||||
// Check if the type matches
|
||||
if(i.first.first != Type)
|
||||
continue;
|
||||
|
||||
// If it's not enabled, skip it
|
||||
if(EnabledOnly && !i.second.enabled)
|
||||
continue;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp)
|
||||
{
|
||||
//
|
||||
// Convert a debugger breakpoint to an open/exported
|
||||
// bridge breakpoint
|
||||
//
|
||||
// TOOD: ASSERT(?) These should never be null
|
||||
if(!Bp || !BridgeBp)
|
||||
return;
|
||||
|
||||
memset(BridgeBp, 0, sizeof(BRIDGEBP));
|
||||
strcpy_s(BridgeBp->mod, Bp->mod);
|
||||
strcpy_s(BridgeBp->name, Bp->name);
|
||||
|
||||
BridgeBp->active = Bp->active;
|
||||
BridgeBp->addr = Bp->addr;
|
||||
BridgeBp->enabled = Bp->enabled;
|
||||
BridgeBp->singleshoot = Bp->singleshoot;
|
||||
|
||||
switch(Bp->type)
|
||||
{
|
||||
case BPNORMAL:
|
||||
BridgeBp->type = bp_normal;
|
||||
break;
|
||||
case BPHARDWARE:
|
||||
BridgeBp->type = bp_hardware;
|
||||
break;
|
||||
case BPMEMORY:
|
||||
BridgeBp->type = bp_memory;
|
||||
break;
|
||||
default:
|
||||
BridgeBp->type = bp_none;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BpCacheSave(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Create a JSON array to store each sub-object with a breakpoint
|
||||
const JSON jsonBreakpoints = json_array();
|
||||
|
||||
// Loop all breakpoints
|
||||
for(auto & i : breakpoints)
|
||||
{
|
||||
auto & breakpoint = i.second;
|
||||
|
||||
// Ignore single-shot breakpoints
|
||||
if(breakpoint.singleshoot)
|
||||
continue;
|
||||
|
||||
JSON jsonObj = json_object();
|
||||
json_object_set_new(jsonObj, "address", json_hex(breakpoint.addr));
|
||||
json_object_set_new(jsonObj, "enabled", json_boolean(breakpoint.enabled));
|
||||
|
||||
// "Normal" breakpoints save the old data
|
||||
if(breakpoint.type == BPNORMAL)
|
||||
json_object_set_new(jsonObj, "oldbytes", json_hex(breakpoint.oldbytes));
|
||||
|
||||
json_object_set_new(jsonObj, "type", json_integer(breakpoint.type));
|
||||
json_object_set_new(jsonObj, "titantype", json_hex(breakpoint.titantype));
|
||||
json_object_set_new(jsonObj, "name", json_string(breakpoint.name));
|
||||
json_object_set_new(jsonObj, "module", json_string(breakpoint.mod));
|
||||
json_array_append_new(jsonBreakpoints, jsonObj);
|
||||
}
|
||||
|
||||
if(json_array_size(jsonBreakpoints))
|
||||
json_object_set(Root, "breakpoints", jsonBreakpoints);
|
||||
|
||||
// Notify garbage collector
|
||||
json_decref(jsonBreakpoints);
|
||||
}
|
||||
|
||||
void BpCacheLoad(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
// Remove all existing elements
|
||||
breakpoints.clear();
|
||||
|
||||
// Get a handle to the root object -> breakpoints subtree
|
||||
const JSON jsonBreakpoints = json_object_get(Root, "breakpoints");
|
||||
|
||||
// Return if there was nothing to load
|
||||
if(!jsonBreakpoints)
|
||||
return;
|
||||
|
||||
size_t i;
|
||||
JSON value;
|
||||
json_array_foreach(jsonBreakpoints, i, value)
|
||||
{
|
||||
BREAKPOINT breakpoint;
|
||||
memset(&breakpoint, 0, sizeof(BREAKPOINT));
|
||||
|
||||
if(breakpoint.type == BPNORMAL)
|
||||
breakpoint.oldbytes = (short)json_hex_value(json_object_get(value, "oldbytes"));
|
||||
breakpoint.type = (BP_TYPE)json_integer_value(json_object_get(value, "type"));
|
||||
breakpoint.addr = (uint)json_hex_value(json_object_get(value, "address"));
|
||||
breakpoint.enabled = json_boolean_value(json_object_get(value, "enabled"));
|
||||
breakpoint.titantype = (DWORD)json_hex_value(json_object_get(value, "titantype"));
|
||||
|
||||
// Name
|
||||
const char* name = json_string_value(json_object_get(value, "name"));
|
||||
|
||||
if(name)
|
||||
strcpy_s(breakpoint.name, name);
|
||||
|
||||
// Module
|
||||
const char* mod = json_string_value(json_object_get(value, "module"));
|
||||
|
||||
if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE)
|
||||
strcpy_s(breakpoint.mod, mod);
|
||||
|
||||
// Build the hash map key: MOD_HASH + ADDRESS
|
||||
const uint key = ModHashFromName(breakpoint.mod) + breakpoint.addr;
|
||||
breakpoints.insert(std::make_pair(BreakpointKey(breakpoint.type, key), breakpoint));
|
||||
}
|
||||
}
|
||||
|
||||
void BpClear()
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
breakpoints.clear();
|
||||
}
|
||||
|
|
@ -1,49 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
#define TITANSETDRX(titantype, drx) titantype &= 0x0FF; titantype |= (drx<<8)
|
||||
#define TITANGETDRX(titantype) (titantype >> 8) & 0xF
|
||||
#define TITANSETTYPE(titantype, type) titantype &= 0xF0F; titantype |= (type<<4)
|
||||
#define TITANGETTYPE(titantype) (titantype >> 4) & 0xF
|
||||
#define TITANSETSIZE(titantype, size) titantype &= 0xFF0; titantype |= size;
|
||||
#define TITANGETSIZE(titantype) titantype & 0xF
|
||||
|
||||
enum BP_TYPE
|
||||
{
|
||||
BPNORMAL = 0,
|
||||
BPHARDWARE = 1,
|
||||
BPMEMORY = 2
|
||||
};
|
||||
|
||||
struct BREAKPOINT
|
||||
{
|
||||
uint addr;
|
||||
bool enabled;
|
||||
bool singleshoot;
|
||||
bool active;
|
||||
short oldbytes;
|
||||
BP_TYPE type;
|
||||
DWORD titantype;
|
||||
char name[MAX_BREAKPOINT_SIZE];
|
||||
char mod[MAX_MODULE_SIZE];
|
||||
};
|
||||
|
||||
// Breakpoint enumeration callback
|
||||
typedef bool (*BPENUMCALLBACK)(const BREAKPOINT* bp);
|
||||
|
||||
BREAKPOINT* BpInfoFromAddr(BP_TYPE Type, uint Address);
|
||||
int BpGetList(std::vector<BREAKPOINT>* List);
|
||||
bool BpNew(uint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE Type, DWORD TitanType, const char* Name);
|
||||
bool BpGet(uint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp);
|
||||
bool BpDelete(uint Address, BP_TYPE Type);
|
||||
bool BpEnable(uint Address, BP_TYPE Type, bool Enable);
|
||||
bool BpSetName(uint Address, BP_TYPE Type, const char* Name);
|
||||
bool BpSetTitanType(uint Address, BP_TYPE Type, int TitanType);
|
||||
bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module);
|
||||
bool BpEnumAll(BPENUMCALLBACK EnumCallback);
|
||||
int BpGetCount(BP_TYPE Type, bool EnabledOnly = false);
|
||||
void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp);
|
||||
void BpCacheSave(JSON Root);
|
||||
void BpCacheLoad(JSON Root);
|
||||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
#define TITANSETDRX(titantype, drx) titantype &= 0x0FF; titantype |= (drx<<8)
|
||||
#define TITANGETDRX(titantype) (titantype >> 8) & 0xF
|
||||
#define TITANSETTYPE(titantype, type) titantype &= 0xF0F; titantype |= (type<<4)
|
||||
#define TITANGETTYPE(titantype) (titantype >> 4) & 0xF
|
||||
#define TITANSETSIZE(titantype, size) titantype &= 0xFF0; titantype |= size;
|
||||
#define TITANGETSIZE(titantype) titantype & 0xF
|
||||
|
||||
enum BP_TYPE
|
||||
{
|
||||
BPNORMAL = 0,
|
||||
BPHARDWARE = 1,
|
||||
BPMEMORY = 2
|
||||
};
|
||||
|
||||
struct BREAKPOINT
|
||||
{
|
||||
uint addr;
|
||||
bool enabled;
|
||||
bool singleshoot;
|
||||
bool active;
|
||||
short oldbytes;
|
||||
BP_TYPE type;
|
||||
DWORD titantype;
|
||||
char name[MAX_BREAKPOINT_SIZE];
|
||||
char mod[MAX_MODULE_SIZE];
|
||||
};
|
||||
|
||||
// Breakpoint enumeration callback
|
||||
typedef bool (*BPENUMCALLBACK)(const BREAKPOINT* bp);
|
||||
|
||||
BREAKPOINT* BpInfoFromAddr(BP_TYPE Type, uint Address);
|
||||
int BpGetList(std::vector<BREAKPOINT>* List);
|
||||
bool BpNew(uint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE Type, DWORD TitanType, const char* Name);
|
||||
bool BpGet(uint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp);
|
||||
bool BpDelete(uint Address, BP_TYPE Type);
|
||||
bool BpEnable(uint Address, BP_TYPE Type, bool Enable);
|
||||
bool BpSetName(uint Address, BP_TYPE Type, const char* Name);
|
||||
bool BpSetTitanType(uint Address, BP_TYPE Type, int TitanType);
|
||||
bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module);
|
||||
bool BpEnumAll(BPENUMCALLBACK EnumCallback);
|
||||
int BpGetCount(BP_TYPE Type, bool EnabledOnly = false);
|
||||
void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp);
|
||||
void BpCacheSave(JSON Root);
|
||||
void BpCacheLoad(JSON Root);
|
||||
void BpClear();
|
||||
|
|
@ -1,199 +1,199 @@
|
|||
#include "console.h"
|
||||
#include "capstone_wrapper.h"
|
||||
|
||||
csh Capstone::mHandle = 0;
|
||||
|
||||
void Capstone::GlobalInitialize()
|
||||
{
|
||||
#ifdef _WIN64
|
||||
cs_open(CS_ARCH_X86, CS_MODE_64, &mHandle);
|
||||
#else //x86
|
||||
cs_open(CS_ARCH_X86, CS_MODE_32, &mHandle);
|
||||
#endif //_WIN64
|
||||
cs_option(mHandle, CS_OPT_DETAIL, CS_OPT_ON);
|
||||
}
|
||||
|
||||
void Capstone::GlobalFinalize()
|
||||
{
|
||||
if(mHandle) //close handle
|
||||
cs_close(&mHandle);
|
||||
}
|
||||
|
||||
Capstone::Capstone()
|
||||
{
|
||||
mInstr = nullptr;
|
||||
mError = CS_ERR_OK;
|
||||
}
|
||||
|
||||
Capstone::~Capstone()
|
||||
{
|
||||
if(mInstr) //free last disassembled instruction
|
||||
cs_free(mInstr, 1);
|
||||
}
|
||||
|
||||
bool Capstone::Disassemble(uint addr, const unsigned char data[MAX_DISASM_BUFFER])
|
||||
{
|
||||
return Disassemble(addr, data, MAX_DISASM_BUFFER);
|
||||
}
|
||||
|
||||
bool Capstone::Disassemble(uint addr, const unsigned char* data, int size)
|
||||
{
|
||||
if(!data)
|
||||
return false;
|
||||
if(mInstr) //free last disassembled instruction
|
||||
{
|
||||
cs_free(mInstr, 1);
|
||||
mInstr = nullptr;
|
||||
}
|
||||
return !!cs_disasm(mHandle, data, size, addr, 1, &mInstr);
|
||||
}
|
||||
|
||||
const cs_insn* Capstone::GetInstr() const
|
||||
{
|
||||
return mInstr;
|
||||
}
|
||||
|
||||
cs_err Capstone::GetError() const
|
||||
{
|
||||
return mError;
|
||||
}
|
||||
|
||||
const char* Capstone::RegName(x86_reg reg) const
|
||||
{
|
||||
return cs_reg_name(mHandle, reg);
|
||||
}
|
||||
|
||||
bool Capstone::InGroup(cs_group_type group) const
|
||||
{
|
||||
return cs_insn_group(mHandle, mInstr, group);
|
||||
}
|
||||
|
||||
String Capstone::OperandText(int opindex) const
|
||||
{
|
||||
if(opindex >= mInstr->detail->x86.op_count)
|
||||
return "";
|
||||
const auto & op = mInstr->detail->x86.operands[opindex];
|
||||
String result;
|
||||
char temp[32] = "";
|
||||
switch(op.type)
|
||||
{
|
||||
case X86_OP_REG:
|
||||
{
|
||||
result = RegName(x86_reg(op.reg));
|
||||
}
|
||||
break;
|
||||
|
||||
case X86_OP_IMM:
|
||||
{
|
||||
if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop())
|
||||
sprintf_s(temp, "%" fext "X", op.imm + mInstr->size);
|
||||
else
|
||||
sprintf_s(temp, "%" fext "X", op.imm);
|
||||
result = temp;
|
||||
}
|
||||
break;
|
||||
|
||||
case X86_OP_MEM:
|
||||
{
|
||||
const auto & mem = op.mem;
|
||||
if(op.mem.base == X86_REG_RIP) //rip-relative
|
||||
{
|
||||
sprintf_s(temp, "%" fext "X", mInstr->address + op.mem.disp + mInstr->size);
|
||||
result += temp;
|
||||
}
|
||||
else //normal
|
||||
{
|
||||
bool prependPlus = false;
|
||||
if(mem.base)
|
||||
{
|
||||
result += RegName(x86_reg(mem.base));
|
||||
prependPlus = true;
|
||||
}
|
||||
if(mem.index)
|
||||
{
|
||||
if(prependPlus)
|
||||
result += "+";
|
||||
result += RegName(x86_reg(mem.index));
|
||||
sprintf_s(temp, "*%X", mem.scale);
|
||||
result += temp;
|
||||
prependPlus = true;
|
||||
}
|
||||
if(mem.disp)
|
||||
{
|
||||
char operatorText = '+';
|
||||
if(mem.disp < 0)
|
||||
{
|
||||
operatorText = '-';
|
||||
sprintf_s(temp, "%" fext "X", mem.disp * -1);
|
||||
}
|
||||
else
|
||||
sprintf_s(temp, "%" fext "X", mem.disp);
|
||||
if(prependPlus)
|
||||
result += operatorText;
|
||||
result += temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case X86_OP_FP:
|
||||
case X86_OP_INVALID:
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int Capstone::Size() const
|
||||
{
|
||||
return GetInstr()->size;
|
||||
}
|
||||
|
||||
uint Capstone::Address() const
|
||||
{
|
||||
return uint(GetInstr()->address);
|
||||
}
|
||||
|
||||
const cs_x86 & Capstone::x86() const
|
||||
{
|
||||
return GetInstr()->detail->x86;
|
||||
}
|
||||
|
||||
bool Capstone::IsFilling() const
|
||||
{
|
||||
switch(GetId())
|
||||
{
|
||||
case X86_INS_NOP:
|
||||
case X86_INS_INT3:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Capstone::IsLoop() const
|
||||
{
|
||||
switch(GetId())
|
||||
{
|
||||
case X86_INS_LOOP:
|
||||
case X86_INS_LOOPE:
|
||||
case X86_INS_LOOPNE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
x86_insn Capstone::GetId() const
|
||||
{
|
||||
return x86_insn(mInstr->id);
|
||||
}
|
||||
|
||||
String Capstone::InstructionText() const
|
||||
{
|
||||
String result = mInstr->mnemonic;
|
||||
result += " ";
|
||||
result += mInstr->op_str;
|
||||
return result;
|
||||
#include "console.h"
|
||||
#include "capstone_wrapper.h"
|
||||
|
||||
csh Capstone::mHandle = 0;
|
||||
|
||||
void Capstone::GlobalInitialize()
|
||||
{
|
||||
#ifdef _WIN64
|
||||
cs_open(CS_ARCH_X86, CS_MODE_64, &mHandle);
|
||||
#else //x86
|
||||
cs_open(CS_ARCH_X86, CS_MODE_32, &mHandle);
|
||||
#endif //_WIN64
|
||||
cs_option(mHandle, CS_OPT_DETAIL, CS_OPT_ON);
|
||||
}
|
||||
|
||||
void Capstone::GlobalFinalize()
|
||||
{
|
||||
if(mHandle) //close handle
|
||||
cs_close(&mHandle);
|
||||
}
|
||||
|
||||
Capstone::Capstone()
|
||||
{
|
||||
mInstr = nullptr;
|
||||
mError = CS_ERR_OK;
|
||||
}
|
||||
|
||||
Capstone::~Capstone()
|
||||
{
|
||||
if(mInstr) //free last disassembled instruction
|
||||
cs_free(mInstr, 1);
|
||||
}
|
||||
|
||||
bool Capstone::Disassemble(uint addr, const unsigned char data[MAX_DISASM_BUFFER])
|
||||
{
|
||||
return Disassemble(addr, data, MAX_DISASM_BUFFER);
|
||||
}
|
||||
|
||||
bool Capstone::Disassemble(uint addr, const unsigned char* data, int size)
|
||||
{
|
||||
if(!data)
|
||||
return false;
|
||||
if(mInstr) //free last disassembled instruction
|
||||
{
|
||||
cs_free(mInstr, 1);
|
||||
mInstr = nullptr;
|
||||
}
|
||||
return !!cs_disasm(mHandle, data, size, addr, 1, &mInstr);
|
||||
}
|
||||
|
||||
const cs_insn* Capstone::GetInstr() const
|
||||
{
|
||||
return mInstr;
|
||||
}
|
||||
|
||||
cs_err Capstone::GetError() const
|
||||
{
|
||||
return mError;
|
||||
}
|
||||
|
||||
const char* Capstone::RegName(x86_reg reg) const
|
||||
{
|
||||
return cs_reg_name(mHandle, reg);
|
||||
}
|
||||
|
||||
bool Capstone::InGroup(cs_group_type group) const
|
||||
{
|
||||
return cs_insn_group(mHandle, mInstr, group);
|
||||
}
|
||||
|
||||
String Capstone::OperandText(int opindex) const
|
||||
{
|
||||
if(opindex >= mInstr->detail->x86.op_count)
|
||||
return "";
|
||||
const auto & op = mInstr->detail->x86.operands[opindex];
|
||||
String result;
|
||||
char temp[32] = "";
|
||||
switch(op.type)
|
||||
{
|
||||
case X86_OP_REG:
|
||||
{
|
||||
result = RegName(x86_reg(op.reg));
|
||||
}
|
||||
break;
|
||||
|
||||
case X86_OP_IMM:
|
||||
{
|
||||
if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop())
|
||||
sprintf_s(temp, "%" fext "X", op.imm + mInstr->size);
|
||||
else
|
||||
sprintf_s(temp, "%" fext "X", op.imm);
|
||||
result = temp;
|
||||
}
|
||||
break;
|
||||
|
||||
case X86_OP_MEM:
|
||||
{
|
||||
const auto & mem = op.mem;
|
||||
if(op.mem.base == X86_REG_RIP) //rip-relative
|
||||
{
|
||||
sprintf_s(temp, "%" fext "X", mInstr->address + op.mem.disp + mInstr->size);
|
||||
result += temp;
|
||||
}
|
||||
else //normal
|
||||
{
|
||||
bool prependPlus = false;
|
||||
if(mem.base)
|
||||
{
|
||||
result += RegName(x86_reg(mem.base));
|
||||
prependPlus = true;
|
||||
}
|
||||
if(mem.index)
|
||||
{
|
||||
if(prependPlus)
|
||||
result += "+";
|
||||
result += RegName(x86_reg(mem.index));
|
||||
sprintf_s(temp, "*%X", mem.scale);
|
||||
result += temp;
|
||||
prependPlus = true;
|
||||
}
|
||||
if(mem.disp)
|
||||
{
|
||||
char operatorText = '+';
|
||||
if(mem.disp < 0)
|
||||
{
|
||||
operatorText = '-';
|
||||
sprintf_s(temp, "%" fext "X", mem.disp * -1);
|
||||
}
|
||||
else
|
||||
sprintf_s(temp, "%" fext "X", mem.disp);
|
||||
if(prependPlus)
|
||||
result += operatorText;
|
||||
result += temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case X86_OP_FP:
|
||||
case X86_OP_INVALID:
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int Capstone::Size() const
|
||||
{
|
||||
return GetInstr()->size;
|
||||
}
|
||||
|
||||
uint Capstone::Address() const
|
||||
{
|
||||
return uint(GetInstr()->address);
|
||||
}
|
||||
|
||||
const cs_x86 & Capstone::x86() const
|
||||
{
|
||||
return GetInstr()->detail->x86;
|
||||
}
|
||||
|
||||
bool Capstone::IsFilling() const
|
||||
{
|
||||
switch(GetId())
|
||||
{
|
||||
case X86_INS_NOP:
|
||||
case X86_INS_INT3:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Capstone::IsLoop() const
|
||||
{
|
||||
switch(GetId())
|
||||
{
|
||||
case X86_INS_LOOP:
|
||||
case X86_INS_LOOPE:
|
||||
case X86_INS_LOOPNE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
x86_insn Capstone::GetId() const
|
||||
{
|
||||
return x86_insn(mInstr->id);
|
||||
}
|
||||
|
||||
String Capstone::InstructionText() const
|
||||
{
|
||||
String result = mInstr->mnemonic;
|
||||
result += " ";
|
||||
result += mInstr->op_str;
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1,37 +1,37 @@
|
|||
#ifndef _CAPSTONE_WRAPPER_H
|
||||
#define _CAPSTONE_WRAPPER_H
|
||||
|
||||
#include "capstone\capstone.h"
|
||||
|
||||
#define MAX_DISASM_BUFFER 16
|
||||
#define INVALID_TITAN_REG 0
|
||||
|
||||
class Capstone
|
||||
{
|
||||
public:
|
||||
static void GlobalInitialize();
|
||||
static void GlobalFinalize();
|
||||
Capstone();
|
||||
~Capstone();
|
||||
bool Disassemble(uint addr, const unsigned char data[MAX_DISASM_BUFFER]);
|
||||
bool Disassemble(uint addr, const unsigned char* data, int size);
|
||||
const cs_insn* GetInstr() const;
|
||||
cs_err GetError() const;
|
||||
const char* RegName(x86_reg reg) const;
|
||||
bool InGroup(cs_group_type group) const;
|
||||
String OperandText(int opindex) const;
|
||||
int Size() const;
|
||||
uint Address() const;
|
||||
const cs_x86 & x86() const;
|
||||
bool IsFilling() const;
|
||||
bool IsLoop() const;
|
||||
x86_insn GetId() const;
|
||||
String InstructionText() const;
|
||||
|
||||
private:
|
||||
static csh mHandle;
|
||||
cs_insn* mInstr;
|
||||
cs_err mError;
|
||||
};
|
||||
|
||||
#ifndef _CAPSTONE_WRAPPER_H
|
||||
#define _CAPSTONE_WRAPPER_H
|
||||
|
||||
#include "capstone\capstone.h"
|
||||
|
||||
#define MAX_DISASM_BUFFER 16
|
||||
#define INVALID_TITAN_REG 0
|
||||
|
||||
class Capstone
|
||||
{
|
||||
public:
|
||||
static void GlobalInitialize();
|
||||
static void GlobalFinalize();
|
||||
Capstone();
|
||||
~Capstone();
|
||||
bool Disassemble(uint addr, const unsigned char data[MAX_DISASM_BUFFER]);
|
||||
bool Disassemble(uint addr, const unsigned char* data, int size);
|
||||
const cs_insn* GetInstr() const;
|
||||
cs_err GetError() const;
|
||||
const char* RegName(x86_reg reg) const;
|
||||
bool InGroup(cs_group_type group) const;
|
||||
String OperandText(int opindex) const;
|
||||
int Size() const;
|
||||
uint Address() const;
|
||||
const cs_x86 & x86() const;
|
||||
bool IsFilling() const;
|
||||
bool IsLoop() const;
|
||||
x86_insn GetId() const;
|
||||
String InstructionText() const;
|
||||
|
||||
private:
|
||||
static csh mHandle;
|
||||
cs_insn* mInstr;
|
||||
cs_err mError;
|
||||
};
|
||||
|
||||
#endif //_CAPSTONE_WRAPPER_H
|
||||
|
|
@ -1,400 +1,400 @@
|
|||
/**
|
||||
@file command.cpp
|
||||
|
||||
@brief Implements the command class.
|
||||
*/
|
||||
|
||||
#include "command.h"
|
||||
#include "value.h"
|
||||
#include "console.h"
|
||||
#include "commandparser.h"
|
||||
|
||||
/**
|
||||
\brief Finds a ::COMMAND in a command list.
|
||||
\param [in] command list.
|
||||
\param name The name of the command to find.
|
||||
\param [out] Link to the command.
|
||||
\return null if it fails, else a ::COMMAND*.
|
||||
*/
|
||||
COMMAND* cmdfind(COMMAND* command_list, const char* name, COMMAND** link)
|
||||
{
|
||||
COMMAND* cur = command_list;
|
||||
if(!cur->name)
|
||||
return 0;
|
||||
COMMAND* prev = 0;
|
||||
while(cur)
|
||||
{
|
||||
if(arraycontains(cur->name, name))
|
||||
{
|
||||
if(link)
|
||||
*link = prev;
|
||||
return cur;
|
||||
}
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Initialize a command list.
|
||||
\return a ::COMMAND*
|
||||
*/
|
||||
COMMAND* cmdinit()
|
||||
{
|
||||
COMMAND* cmd = (COMMAND*)emalloc(sizeof(COMMAND), "cmdinit:cmd");
|
||||
memset(cmd, 0, sizeof(COMMAND));
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Clear a command list.
|
||||
\param [in] cmd_list Command list to clear.
|
||||
*/
|
||||
void cmdfree(COMMAND* cmd_list)
|
||||
{
|
||||
COMMAND* cur = cmd_list;
|
||||
while(cur)
|
||||
{
|
||||
efree(cur->name, "cmdfree:cur->name");
|
||||
COMMAND* next = cur->next;
|
||||
efree(cur, "cmdfree:cur");
|
||||
cur = next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Creates a new command and adds it to the list.
|
||||
\param [in,out] command_list Command list. Cannot be null.
|
||||
\param name The command name.
|
||||
\param cbCommand The command callback.
|
||||
\param debugonly true if the command can only be executed in a debugging context.
|
||||
\return true if the command was successfully added to the list.
|
||||
*/
|
||||
bool cmdnew(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly)
|
||||
{
|
||||
if(!command_list || !cbCommand || !name || !*name || cmdfind(command_list, name, 0))
|
||||
return false;
|
||||
COMMAND* cmd;
|
||||
bool nonext = false;
|
||||
if(!command_list->name)
|
||||
{
|
||||
cmd = command_list;
|
||||
nonext = true;
|
||||
}
|
||||
else
|
||||
cmd = (COMMAND*)emalloc(sizeof(COMMAND), "cmdnew:cmd");
|
||||
memset(cmd, 0, sizeof(COMMAND));
|
||||
cmd->name = (char*)emalloc(strlen(name) + 1, "cmdnew:cmd->name");
|
||||
strcpy(cmd->name, name);
|
||||
cmd->cbCommand = cbCommand;
|
||||
cmd->debugonly = debugonly;
|
||||
COMMAND* cur = command_list;
|
||||
if(!nonext)
|
||||
{
|
||||
while(cur->next)
|
||||
cur = cur->next;
|
||||
cur->next = cmd;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets a ::COMMAND from the command list.
|
||||
\param [in] command_list Command list.
|
||||
\param cmd The command to get from the list.
|
||||
\return null if the command was not found. Otherwise a ::COMMAND*.
|
||||
*/
|
||||
COMMAND* cmdget(COMMAND* command_list, const char* cmd)
|
||||
{
|
||||
char new_cmd[deflen] = "";
|
||||
strcpy_s(new_cmd, deflen, cmd);
|
||||
int len = (int)strlen(new_cmd);
|
||||
int start = 0;
|
||||
while(new_cmd[start] != ' ' && start < len)
|
||||
start++;
|
||||
new_cmd[start] = 0;
|
||||
COMMAND* found = cmdfind(command_list, new_cmd, 0);
|
||||
if(!found)
|
||||
return 0;
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Sets a new command callback and debugonly property in a command list.
|
||||
\param [in] command_list Command list.
|
||||
\param name The name of the command to change.
|
||||
\param cbCommand The new command callback.
|
||||
\param debugonly The new debugonly value.
|
||||
\return The old command callback.
|
||||
*/
|
||||
CBCOMMAND cmdset(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly)
|
||||
{
|
||||
if(!cbCommand)
|
||||
return 0;
|
||||
COMMAND* found = cmdfind(command_list, name, 0);
|
||||
if(!found)
|
||||
return 0;
|
||||
CBCOMMAND old = found->cbCommand;
|
||||
found->cbCommand = cbCommand;
|
||||
found->debugonly = debugonly;
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Deletes a command from a command list.
|
||||
\param [in] command_list Command list.
|
||||
\param name The name of the command to delete.
|
||||
\return true if the command was deleted.
|
||||
*/
|
||||
bool cmddel(COMMAND* command_list, const char* name)
|
||||
{
|
||||
COMMAND* prev = 0;
|
||||
COMMAND* found = cmdfind(command_list, name, &prev);
|
||||
if(!found)
|
||||
return false;
|
||||
efree(found->name, "cmddel:found->name");
|
||||
if(found == command_list)
|
||||
{
|
||||
COMMAND* next = command_list->next;
|
||||
if(next)
|
||||
{
|
||||
memcpy(command_list, command_list->next, sizeof(COMMAND));
|
||||
command_list->next = next->next;
|
||||
efree(next, "cmddel:next");
|
||||
}
|
||||
else
|
||||
memset(command_list, 0, sizeof(COMMAND));
|
||||
}
|
||||
else
|
||||
{
|
||||
prev->next = found->next;
|
||||
efree(found, "cmddel:found");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
command_list: command list
|
||||
cbUnknownCommand: function to execute when an unknown command was found
|
||||
cbCommandProvider: function that provides commands (fgets for example), does not return until a command was found
|
||||
cbCommandFinder: non-default command finder
|
||||
error_is_fatal: error return of a command callback stops the command processing
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Initiates a command loop. This function will not return until a command returns ::STATUS_EXIT.
|
||||
\param [in] command_list Command list to use for the command lookups.
|
||||
\param cbUnknownCommand The unknown command callback.
|
||||
\param cbCommandProvider The command provider callback.
|
||||
\param cbCommandFinder The command finder callback.
|
||||
\param error_is_fatal true if commands that return ::STATUS_ERROR terminate the command loop.
|
||||
\return A CMDRESULT, will always be ::STATUS_EXIT.
|
||||
*/
|
||||
CMDRESULT cmdloop(COMMAND* command_list, CBCOMMAND cbUnknownCommand, CBCOMMANDPROVIDER cbCommandProvider, CBCOMMANDFINDER cbCommandFinder, bool error_is_fatal)
|
||||
{
|
||||
if(!cbUnknownCommand || !cbCommandProvider)
|
||||
return STATUS_ERROR;
|
||||
char command[deflen] = "";
|
||||
bool bLoop = true;
|
||||
while(bLoop)
|
||||
{
|
||||
if(!cbCommandProvider(command, deflen))
|
||||
break;
|
||||
if(strlen(command))
|
||||
{
|
||||
strcpy_s(command, StringUtils::Trim(command).c_str());
|
||||
COMMAND* cmd;
|
||||
if(!cbCommandFinder) //'clean' command processing
|
||||
cmd = cmdget(command_list, command);
|
||||
else //'dirty' command processing
|
||||
cmd = cbCommandFinder(command_list, command);
|
||||
|
||||
if(!cmd || !cmd->cbCommand) //unknown command
|
||||
{
|
||||
char* argv[1];
|
||||
*argv = command;
|
||||
CMDRESULT res = cbUnknownCommand(1, argv);
|
||||
if((error_is_fatal && res == STATUS_ERROR) || res == STATUS_EXIT)
|
||||
bLoop = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cmd->debugonly && !DbgIsDebugging())
|
||||
{
|
||||
dputs("this command is debug-only");
|
||||
if(error_is_fatal)
|
||||
bLoop = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Command commandParsed(command);
|
||||
int argcount = commandParsed.GetArgCount();
|
||||
char** argv = (char**)emalloc((argcount + 1) * sizeof(char*), "cmdloop:argv");
|
||||
argv[0] = command;
|
||||
for(int i = 0; i < argcount; i++)
|
||||
{
|
||||
argv[i + 1] = (char*)emalloc(deflen, "cmdloop:argv[i+1]");
|
||||
*argv[i + 1] = 0;
|
||||
strcpy_s(argv[i + 1], deflen, commandParsed.GetArg(i).c_str());
|
||||
}
|
||||
CMDRESULT res = cmd->cbCommand(argcount + 1, argv);
|
||||
for(int i = 0; i < argcount; i++)
|
||||
efree(argv[i + 1], "cmdloop:argv[i+1]");
|
||||
efree(argv, "cmdloop:argv");
|
||||
if((error_is_fatal && res == STATUS_ERROR) || res == STATUS_EXIT)
|
||||
bLoop = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return STATUS_EXIT;
|
||||
}
|
||||
|
||||
/*
|
||||
- custom command formatting rules
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Query if a string is a valid expression.
|
||||
\param expression The expression to check.
|
||||
\return true if the string is a valid expression.
|
||||
*/
|
||||
static bool isvalidexpression(const char* expression)
|
||||
{
|
||||
uint value;
|
||||
return valfromstring(expression, &value);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Check if a character is a mathematical operator. Used to determine stuff like "a *= b"
|
||||
\param ch The character to check.
|
||||
\return true if the character is an operator, false otherwise.
|
||||
*/
|
||||
static bool mathisoperator(const char ch)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case '*':
|
||||
case '`':
|
||||
case '/':
|
||||
case '%':
|
||||
case '+':
|
||||
case '-':
|
||||
case '<':
|
||||
case '>':
|
||||
case '&':
|
||||
case '^':
|
||||
case '|':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Special formats a given command. Used as a little hack to support stuff like 'x++' and 'x=y'
|
||||
\param [in,out] string String to format.
|
||||
*/
|
||||
static void specialformat(char* string)
|
||||
{
|
||||
int len = (int)strlen(string);
|
||||
char* found = strstr(string, "=");
|
||||
char str[deflen] = "";
|
||||
char backup[deflen] = "";
|
||||
strcpy_s(backup, string); //create a backup of the string
|
||||
if(found) //contains =
|
||||
{
|
||||
char* a = (found - 1);
|
||||
*found = 0;
|
||||
found++;
|
||||
if(!*found)
|
||||
{
|
||||
*found = '=';
|
||||
return;
|
||||
}
|
||||
|
||||
if(mathisoperator(*a)) //x*=3 -> x=x*3
|
||||
{
|
||||
char op = *a;
|
||||
*a = 0;
|
||||
if(isvalidexpression(string))
|
||||
sprintf_s(str, "mov %s,%s%c%s", string, string, op, found);
|
||||
else
|
||||
strcpy_s(str, backup);
|
||||
}
|
||||
else //x=y
|
||||
{
|
||||
if(isvalidexpression(found))
|
||||
sprintf_s(str, "mov %s,%s", string, found);
|
||||
else
|
||||
strcpy_s(str, backup);
|
||||
}
|
||||
strcpy_s(string, deflen, str);
|
||||
}
|
||||
else if((string[len - 1] == '+' && string[len - 2] == '+') || (string[len - 1] == '-' && string[len - 2] == '-')) //eax++/eax--
|
||||
{
|
||||
string[len - 2] = 0;
|
||||
char op = string[len - 1];
|
||||
if(isvalidexpression(string))
|
||||
sprintf_s(str, "mov %s,%s%c1", string, string, op);
|
||||
else
|
||||
strcpy_s(str, backup);
|
||||
strcpy_s(string, deflen, str);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- 'default' command finder, with some custom rules
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Default command finder. It uses specialformat() and mathformat() to make sure the command is optimally checked.
|
||||
\param [in] cmd_list Command list.
|
||||
\param [in] command Command name.
|
||||
\return null if it fails, else a COMMAND*.
|
||||
*/
|
||||
COMMAND* cmdfindmain(COMMAND* cmd_list, char* command)
|
||||
{
|
||||
COMMAND* cmd = cmdfind(cmd_list, command, 0);
|
||||
if(!cmd)
|
||||
{
|
||||
specialformat(command);
|
||||
cmd = cmdget(cmd_list, command);
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Directly execute a command.
|
||||
\param [in,out] cmd_list Command list.
|
||||
\param cmd The command to execute.
|
||||
\return A CMDRESULT.
|
||||
*/
|
||||
CMDRESULT cmddirectexec(COMMAND* cmd_list, const char* cmd)
|
||||
{
|
||||
if(!cmd || !strlen(cmd))
|
||||
return STATUS_ERROR;
|
||||
char command[deflen] = "";
|
||||
strcpy_s(command, StringUtils::Trim(cmd).c_str());
|
||||
COMMAND* found = cmdfindmain(cmd_list, command);
|
||||
if(!found || !found->cbCommand)
|
||||
return STATUS_ERROR;
|
||||
if(found->debugonly && !DbgIsDebugging())
|
||||
return STATUS_ERROR;
|
||||
Command cmdParsed(command);
|
||||
int argcount = cmdParsed.GetArgCount();
|
||||
char** argv = (char**)emalloc((argcount + 1) * sizeof(char*), "cmddirectexec:argv");
|
||||
argv[0] = command;
|
||||
for(int i = 0; i < argcount; i++)
|
||||
{
|
||||
argv[i + 1] = (char*)emalloc(deflen, "cmddirectexec:argv[i+1]");
|
||||
*argv[i + 1] = 0;
|
||||
strcpy_s(argv[i + 1], deflen, cmdParsed.GetArg(i).c_str());
|
||||
}
|
||||
CMDRESULT res = found->cbCommand(argcount + 1, argv);
|
||||
for(int i = 0; i < argcount; i++)
|
||||
efree(argv[i + 1], "cmddirectexec:argv[i+1]");
|
||||
efree(argv, "cmddirectexec:argv");
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
@file command.cpp
|
||||
|
||||
@brief Implements the command class.
|
||||
*/
|
||||
|
||||
#include "command.h"
|
||||
#include "value.h"
|
||||
#include "console.h"
|
||||
#include "commandparser.h"
|
||||
|
||||
/**
|
||||
\brief Finds a ::COMMAND in a command list.
|
||||
\param [in] command list.
|
||||
\param name The name of the command to find.
|
||||
\param [out] Link to the command.
|
||||
\return null if it fails, else a ::COMMAND*.
|
||||
*/
|
||||
COMMAND* cmdfind(COMMAND* command_list, const char* name, COMMAND** link)
|
||||
{
|
||||
COMMAND* cur = command_list;
|
||||
if(!cur->name)
|
||||
return 0;
|
||||
COMMAND* prev = 0;
|
||||
while(cur)
|
||||
{
|
||||
if(arraycontains(cur->name, name))
|
||||
{
|
||||
if(link)
|
||||
*link = prev;
|
||||
return cur;
|
||||
}
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Initialize a command list.
|
||||
\return a ::COMMAND*
|
||||
*/
|
||||
COMMAND* cmdinit()
|
||||
{
|
||||
COMMAND* cmd = (COMMAND*)emalloc(sizeof(COMMAND), "cmdinit:cmd");
|
||||
memset(cmd, 0, sizeof(COMMAND));
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Clear a command list.
|
||||
\param [in] cmd_list Command list to clear.
|
||||
*/
|
||||
void cmdfree(COMMAND* cmd_list)
|
||||
{
|
||||
COMMAND* cur = cmd_list;
|
||||
while(cur)
|
||||
{
|
||||
efree(cur->name, "cmdfree:cur->name");
|
||||
COMMAND* next = cur->next;
|
||||
efree(cur, "cmdfree:cur");
|
||||
cur = next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Creates a new command and adds it to the list.
|
||||
\param [in,out] command_list Command list. Cannot be null.
|
||||
\param name The command name.
|
||||
\param cbCommand The command callback.
|
||||
\param debugonly true if the command can only be executed in a debugging context.
|
||||
\return true if the command was successfully added to the list.
|
||||
*/
|
||||
bool cmdnew(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly)
|
||||
{
|
||||
if(!command_list || !cbCommand || !name || !*name || cmdfind(command_list, name, 0))
|
||||
return false;
|
||||
COMMAND* cmd;
|
||||
bool nonext = false;
|
||||
if(!command_list->name)
|
||||
{
|
||||
cmd = command_list;
|
||||
nonext = true;
|
||||
}
|
||||
else
|
||||
cmd = (COMMAND*)emalloc(sizeof(COMMAND), "cmdnew:cmd");
|
||||
memset(cmd, 0, sizeof(COMMAND));
|
||||
cmd->name = (char*)emalloc(strlen(name) + 1, "cmdnew:cmd->name");
|
||||
strcpy(cmd->name, name);
|
||||
cmd->cbCommand = cbCommand;
|
||||
cmd->debugonly = debugonly;
|
||||
COMMAND* cur = command_list;
|
||||
if(!nonext)
|
||||
{
|
||||
while(cur->next)
|
||||
cur = cur->next;
|
||||
cur->next = cmd;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Gets a ::COMMAND from the command list.
|
||||
\param [in] command_list Command list.
|
||||
\param cmd The command to get from the list.
|
||||
\return null if the command was not found. Otherwise a ::COMMAND*.
|
||||
*/
|
||||
COMMAND* cmdget(COMMAND* command_list, const char* cmd)
|
||||
{
|
||||
char new_cmd[deflen] = "";
|
||||
strcpy_s(new_cmd, deflen, cmd);
|
||||
int len = (int)strlen(new_cmd);
|
||||
int start = 0;
|
||||
while(new_cmd[start] != ' ' && start < len)
|
||||
start++;
|
||||
new_cmd[start] = 0;
|
||||
COMMAND* found = cmdfind(command_list, new_cmd, 0);
|
||||
if(!found)
|
||||
return 0;
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Sets a new command callback and debugonly property in a command list.
|
||||
\param [in] command_list Command list.
|
||||
\param name The name of the command to change.
|
||||
\param cbCommand The new command callback.
|
||||
\param debugonly The new debugonly value.
|
||||
\return The old command callback.
|
||||
*/
|
||||
CBCOMMAND cmdset(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly)
|
||||
{
|
||||
if(!cbCommand)
|
||||
return 0;
|
||||
COMMAND* found = cmdfind(command_list, name, 0);
|
||||
if(!found)
|
||||
return 0;
|
||||
CBCOMMAND old = found->cbCommand;
|
||||
found->cbCommand = cbCommand;
|
||||
found->debugonly = debugonly;
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Deletes a command from a command list.
|
||||
\param [in] command_list Command list.
|
||||
\param name The name of the command to delete.
|
||||
\return true if the command was deleted.
|
||||
*/
|
||||
bool cmddel(COMMAND* command_list, const char* name)
|
||||
{
|
||||
COMMAND* prev = 0;
|
||||
COMMAND* found = cmdfind(command_list, name, &prev);
|
||||
if(!found)
|
||||
return false;
|
||||
efree(found->name, "cmddel:found->name");
|
||||
if(found == command_list)
|
||||
{
|
||||
COMMAND* next = command_list->next;
|
||||
if(next)
|
||||
{
|
||||
memcpy(command_list, command_list->next, sizeof(COMMAND));
|
||||
command_list->next = next->next;
|
||||
efree(next, "cmddel:next");
|
||||
}
|
||||
else
|
||||
memset(command_list, 0, sizeof(COMMAND));
|
||||
}
|
||||
else
|
||||
{
|
||||
prev->next = found->next;
|
||||
efree(found, "cmddel:found");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
command_list: command list
|
||||
cbUnknownCommand: function to execute when an unknown command was found
|
||||
cbCommandProvider: function that provides commands (fgets for example), does not return until a command was found
|
||||
cbCommandFinder: non-default command finder
|
||||
error_is_fatal: error return of a command callback stops the command processing
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Initiates a command loop. This function will not return until a command returns ::STATUS_EXIT.
|
||||
\param [in] command_list Command list to use for the command lookups.
|
||||
\param cbUnknownCommand The unknown command callback.
|
||||
\param cbCommandProvider The command provider callback.
|
||||
\param cbCommandFinder The command finder callback.
|
||||
\param error_is_fatal true if commands that return ::STATUS_ERROR terminate the command loop.
|
||||
\return A CMDRESULT, will always be ::STATUS_EXIT.
|
||||
*/
|
||||
CMDRESULT cmdloop(COMMAND* command_list, CBCOMMAND cbUnknownCommand, CBCOMMANDPROVIDER cbCommandProvider, CBCOMMANDFINDER cbCommandFinder, bool error_is_fatal)
|
||||
{
|
||||
if(!cbUnknownCommand || !cbCommandProvider)
|
||||
return STATUS_ERROR;
|
||||
char command[deflen] = "";
|
||||
bool bLoop = true;
|
||||
while(bLoop)
|
||||
{
|
||||
if(!cbCommandProvider(command, deflen))
|
||||
break;
|
||||
if(strlen(command))
|
||||
{
|
||||
strcpy_s(command, StringUtils::Trim(command).c_str());
|
||||
COMMAND* cmd;
|
||||
if(!cbCommandFinder) //'clean' command processing
|
||||
cmd = cmdget(command_list, command);
|
||||
else //'dirty' command processing
|
||||
cmd = cbCommandFinder(command_list, command);
|
||||
|
||||
if(!cmd || !cmd->cbCommand) //unknown command
|
||||
{
|
||||
char* argv[1];
|
||||
*argv = command;
|
||||
CMDRESULT res = cbUnknownCommand(1, argv);
|
||||
if((error_is_fatal && res == STATUS_ERROR) || res == STATUS_EXIT)
|
||||
bLoop = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cmd->debugonly && !DbgIsDebugging())
|
||||
{
|
||||
dputs("this command is debug-only");
|
||||
if(error_is_fatal)
|
||||
bLoop = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Command commandParsed(command);
|
||||
int argcount = commandParsed.GetArgCount();
|
||||
char** argv = (char**)emalloc((argcount + 1) * sizeof(char*), "cmdloop:argv");
|
||||
argv[0] = command;
|
||||
for(int i = 0; i < argcount; i++)
|
||||
{
|
||||
argv[i + 1] = (char*)emalloc(deflen, "cmdloop:argv[i+1]");
|
||||
*argv[i + 1] = 0;
|
||||
strcpy_s(argv[i + 1], deflen, commandParsed.GetArg(i).c_str());
|
||||
}
|
||||
CMDRESULT res = cmd->cbCommand(argcount + 1, argv);
|
||||
for(int i = 0; i < argcount; i++)
|
||||
efree(argv[i + 1], "cmdloop:argv[i+1]");
|
||||
efree(argv, "cmdloop:argv");
|
||||
if((error_is_fatal && res == STATUS_ERROR) || res == STATUS_EXIT)
|
||||
bLoop = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return STATUS_EXIT;
|
||||
}
|
||||
|
||||
/*
|
||||
- custom command formatting rules
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Query if a string is a valid expression.
|
||||
\param expression The expression to check.
|
||||
\return true if the string is a valid expression.
|
||||
*/
|
||||
static bool isvalidexpression(const char* expression)
|
||||
{
|
||||
uint value;
|
||||
return valfromstring(expression, &value);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Check if a character is a mathematical operator. Used to determine stuff like "a *= b"
|
||||
\param ch The character to check.
|
||||
\return true if the character is an operator, false otherwise.
|
||||
*/
|
||||
static bool mathisoperator(const char ch)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case '*':
|
||||
case '`':
|
||||
case '/':
|
||||
case '%':
|
||||
case '+':
|
||||
case '-':
|
||||
case '<':
|
||||
case '>':
|
||||
case '&':
|
||||
case '^':
|
||||
case '|':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Special formats a given command. Used as a little hack to support stuff like 'x++' and 'x=y'
|
||||
\param [in,out] string String to format.
|
||||
*/
|
||||
static void specialformat(char* string)
|
||||
{
|
||||
int len = (int)strlen(string);
|
||||
char* found = strstr(string, "=");
|
||||
char str[deflen] = "";
|
||||
char backup[deflen] = "";
|
||||
strcpy_s(backup, string); //create a backup of the string
|
||||
if(found) //contains =
|
||||
{
|
||||
char* a = (found - 1);
|
||||
*found = 0;
|
||||
found++;
|
||||
if(!*found)
|
||||
{
|
||||
*found = '=';
|
||||
return;
|
||||
}
|
||||
|
||||
if(mathisoperator(*a)) //x*=3 -> x=x*3
|
||||
{
|
||||
char op = *a;
|
||||
*a = 0;
|
||||
if(isvalidexpression(string))
|
||||
sprintf_s(str, "mov %s,%s%c%s", string, string, op, found);
|
||||
else
|
||||
strcpy_s(str, backup);
|
||||
}
|
||||
else //x=y
|
||||
{
|
||||
if(isvalidexpression(found))
|
||||
sprintf_s(str, "mov %s,%s", string, found);
|
||||
else
|
||||
strcpy_s(str, backup);
|
||||
}
|
||||
strcpy_s(string, deflen, str);
|
||||
}
|
||||
else if((string[len - 1] == '+' && string[len - 2] == '+') || (string[len - 1] == '-' && string[len - 2] == '-')) //eax++/eax--
|
||||
{
|
||||
string[len - 2] = 0;
|
||||
char op = string[len - 1];
|
||||
if(isvalidexpression(string))
|
||||
sprintf_s(str, "mov %s,%s%c1", string, string, op);
|
||||
else
|
||||
strcpy_s(str, backup);
|
||||
strcpy_s(string, deflen, str);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- 'default' command finder, with some custom rules
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Default command finder. It uses specialformat() and mathformat() to make sure the command is optimally checked.
|
||||
\param [in] cmd_list Command list.
|
||||
\param [in] command Command name.
|
||||
\return null if it fails, else a COMMAND*.
|
||||
*/
|
||||
COMMAND* cmdfindmain(COMMAND* cmd_list, char* command)
|
||||
{
|
||||
COMMAND* cmd = cmdfind(cmd_list, command, 0);
|
||||
if(!cmd)
|
||||
{
|
||||
specialformat(command);
|
||||
cmd = cmdget(cmd_list, command);
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Directly execute a command.
|
||||
\param [in,out] cmd_list Command list.
|
||||
\param cmd The command to execute.
|
||||
\return A CMDRESULT.
|
||||
*/
|
||||
CMDRESULT cmddirectexec(COMMAND* cmd_list, const char* cmd)
|
||||
{
|
||||
if(!cmd || !strlen(cmd))
|
||||
return STATUS_ERROR;
|
||||
char command[deflen] = "";
|
||||
strcpy_s(command, StringUtils::Trim(cmd).c_str());
|
||||
COMMAND* found = cmdfindmain(cmd_list, command);
|
||||
if(!found || !found->cbCommand)
|
||||
return STATUS_ERROR;
|
||||
if(found->debugonly && !DbgIsDebugging())
|
||||
return STATUS_ERROR;
|
||||
Command cmdParsed(command);
|
||||
int argcount = cmdParsed.GetArgCount();
|
||||
char** argv = (char**)emalloc((argcount + 1) * sizeof(char*), "cmddirectexec:argv");
|
||||
argv[0] = command;
|
||||
for(int i = 0; i < argcount; i++)
|
||||
{
|
||||
argv[i + 1] = (char*)emalloc(deflen, "cmddirectexec:argv[i+1]");
|
||||
*argv[i + 1] = 0;
|
||||
strcpy_s(argv[i + 1], deflen, cmdParsed.GetArg(i).c_str());
|
||||
}
|
||||
CMDRESULT res = found->cbCommand(argcount + 1, argv);
|
||||
for(int i = 0; i < argcount; i++)
|
||||
efree(argv[i + 1], "cmddirectexec:argv[i+1]");
|
||||
efree(argv, "cmddirectexec:argv");
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1,42 +1,42 @@
|
|||
#ifndef _COMMAND_H
|
||||
#define _COMMAND_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
//typedefs
|
||||
|
||||
struct COMMAND;
|
||||
|
||||
enum CMDRESULT
|
||||
{
|
||||
STATUS_ERROR = false,
|
||||
STATUS_CONTINUE = true,
|
||||
STATUS_EXIT = 2,
|
||||
STATUS_PAUSE = 3
|
||||
};
|
||||
|
||||
typedef CMDRESULT(*CBCOMMAND)(int, char**);
|
||||
typedef bool (*CBCOMMANDPROVIDER)(char*, int);
|
||||
typedef COMMAND* (*CBCOMMANDFINDER)(COMMAND*, char*);
|
||||
|
||||
struct COMMAND
|
||||
{
|
||||
char* name;
|
||||
CBCOMMAND cbCommand;
|
||||
bool debugonly;
|
||||
COMMAND* next;
|
||||
};
|
||||
|
||||
//functions
|
||||
COMMAND* cmdinit();
|
||||
void cmdfree(COMMAND* cmd_list);
|
||||
COMMAND* cmdfind(COMMAND* command_list, const char* name, COMMAND** link);
|
||||
bool cmdnew(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly);
|
||||
COMMAND* cmdget(COMMAND* command_list, const char* cmd);
|
||||
CBCOMMAND cmdset(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly);
|
||||
bool cmddel(COMMAND* command_list, const char* name);
|
||||
CMDRESULT cmdloop(COMMAND* command_list, CBCOMMAND cbUnknownCommand, CBCOMMANDPROVIDER cbCommandProvider, CBCOMMANDFINDER cbCommandFinder, bool error_is_fatal);
|
||||
COMMAND* cmdfindmain(COMMAND* cmd_list, char* command);
|
||||
CMDRESULT cmddirectexec(COMMAND* cmd_list, const char* cmd);
|
||||
|
||||
#endif // _COMMAND_H
|
||||
#ifndef _COMMAND_H
|
||||
#define _COMMAND_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
//typedefs
|
||||
|
||||
struct COMMAND;
|
||||
|
||||
enum CMDRESULT
|
||||
{
|
||||
STATUS_ERROR = false,
|
||||
STATUS_CONTINUE = true,
|
||||
STATUS_EXIT = 2,
|
||||
STATUS_PAUSE = 3
|
||||
};
|
||||
|
||||
typedef CMDRESULT(*CBCOMMAND)(int, char**);
|
||||
typedef bool (*CBCOMMANDPROVIDER)(char*, int);
|
||||
typedef COMMAND* (*CBCOMMANDFINDER)(COMMAND*, char*);
|
||||
|
||||
struct COMMAND
|
||||
{
|
||||
char* name;
|
||||
CBCOMMAND cbCommand;
|
||||
bool debugonly;
|
||||
COMMAND* next;
|
||||
};
|
||||
|
||||
//functions
|
||||
COMMAND* cmdinit();
|
||||
void cmdfree(COMMAND* cmd_list);
|
||||
COMMAND* cmdfind(COMMAND* command_list, const char* name, COMMAND** link);
|
||||
bool cmdnew(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly);
|
||||
COMMAND* cmdget(COMMAND* command_list, const char* cmd);
|
||||
CBCOMMAND cmdset(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly);
|
||||
bool cmddel(COMMAND* command_list, const char* name);
|
||||
CMDRESULT cmdloop(COMMAND* command_list, CBCOMMAND cbUnknownCommand, CBCOMMANDPROVIDER cbCommandProvider, CBCOMMANDFINDER cbCommandFinder, bool error_is_fatal);
|
||||
COMMAND* cmdfindmain(COMMAND* cmd_list, char* command);
|
||||
CMDRESULT cmddirectexec(COMMAND* cmd_list, const char* cmd);
|
||||
|
||||
#endif // _COMMAND_H
|
||||
|
|
@ -1,114 +1,114 @@
|
|||
#include "commandparser.h"
|
||||
|
||||
Command::Command(const String & command)
|
||||
{
|
||||
ParseState state = Default;
|
||||
int len = (int)command.length();
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
char ch = command[i];
|
||||
switch(state)
|
||||
{
|
||||
case Default:
|
||||
switch(ch)
|
||||
{
|
||||
case ' ':
|
||||
if(!_tokens.size())
|
||||
dataFinish();
|
||||
break;
|
||||
case ',':
|
||||
dataFinish();
|
||||
break;
|
||||
case '\\':
|
||||
state = Escaped;
|
||||
break;
|
||||
case '\"':
|
||||
state = Text;
|
||||
break;
|
||||
default:
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Escaped:
|
||||
switch(ch)
|
||||
{
|
||||
case ' ':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
case ',':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
case '\"':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
default:
|
||||
dataAppend('\\');
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
state = Default;
|
||||
break;
|
||||
case Text:
|
||||
switch(ch)
|
||||
{
|
||||
case '\\':
|
||||
state = TextEscaped;
|
||||
break;
|
||||
case '\"':
|
||||
dataFinish();
|
||||
state = Default;
|
||||
break;
|
||||
default:
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TextEscaped:
|
||||
switch(ch)
|
||||
{
|
||||
case '\"':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
default:
|
||||
dataAppend('\\');
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
state = Text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(state == Escaped || state == TextEscaped)
|
||||
dataAppend('\\');
|
||||
dataFinish();
|
||||
}
|
||||
|
||||
const String Command::GetText()
|
||||
{
|
||||
return _tokens.size() ? _tokens[0] : String();
|
||||
}
|
||||
|
||||
const int Command::GetArgCount()
|
||||
{
|
||||
return _tokens.size() ? (int)_tokens.size() - 1 : 0;
|
||||
}
|
||||
|
||||
const String Command::GetArg(int argnum)
|
||||
{
|
||||
return (int)_tokens.size() < argnum + 1 ? String() : _tokens[argnum + 1];
|
||||
}
|
||||
|
||||
void Command::dataAppend(const char ch)
|
||||
{
|
||||
_data += ch;
|
||||
}
|
||||
|
||||
void Command::dataFinish()
|
||||
{
|
||||
if(_data.length())
|
||||
{
|
||||
_tokens.push_back(_data);
|
||||
_data.clear();
|
||||
}
|
||||
}
|
||||
#include "commandparser.h"
|
||||
|
||||
Command::Command(const String & command)
|
||||
{
|
||||
ParseState state = Default;
|
||||
int len = (int)command.length();
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
char ch = command[i];
|
||||
switch(state)
|
||||
{
|
||||
case Default:
|
||||
switch(ch)
|
||||
{
|
||||
case ' ':
|
||||
if(!_tokens.size())
|
||||
dataFinish();
|
||||
break;
|
||||
case ',':
|
||||
dataFinish();
|
||||
break;
|
||||
case '\\':
|
||||
state = Escaped;
|
||||
break;
|
||||
case '\"':
|
||||
state = Text;
|
||||
break;
|
||||
default:
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Escaped:
|
||||
switch(ch)
|
||||
{
|
||||
case ' ':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
case ',':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
case '\"':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
default:
|
||||
dataAppend('\\');
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
state = Default;
|
||||
break;
|
||||
case Text:
|
||||
switch(ch)
|
||||
{
|
||||
case '\\':
|
||||
state = TextEscaped;
|
||||
break;
|
||||
case '\"':
|
||||
dataFinish();
|
||||
state = Default;
|
||||
break;
|
||||
default:
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TextEscaped:
|
||||
switch(ch)
|
||||
{
|
||||
case '\"':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
default:
|
||||
dataAppend('\\');
|
||||
dataAppend(ch);
|
||||
break;
|
||||
}
|
||||
state = Text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(state == Escaped || state == TextEscaped)
|
||||
dataAppend('\\');
|
||||
dataFinish();
|
||||
}
|
||||
|
||||
const String Command::GetText()
|
||||
{
|
||||
return _tokens.size() ? _tokens[0] : String();
|
||||
}
|
||||
|
||||
const int Command::GetArgCount()
|
||||
{
|
||||
return _tokens.size() ? (int)_tokens.size() - 1 : 0;
|
||||
}
|
||||
|
||||
const String Command::GetArg(int argnum)
|
||||
{
|
||||
return (int)_tokens.size() < argnum + 1 ? String() : _tokens[argnum + 1];
|
||||
}
|
||||
|
||||
void Command::dataAppend(const char ch)
|
||||
{
|
||||
_data += ch;
|
||||
}
|
||||
|
||||
void Command::dataFinish()
|
||||
{
|
||||
if(_data.length())
|
||||
{
|
||||
_tokens.push_back(_data);
|
||||
_data.clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,30 @@
|
|||
#ifndef _COMMANDPARSER_H
|
||||
#define _COMMANDPARSER_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
Command(const String & command);
|
||||
const String GetText();
|
||||
const String GetArg(const int argnum);
|
||||
const int GetArgCount();
|
||||
|
||||
private:
|
||||
String _data;
|
||||
std::vector<String> _tokens;
|
||||
|
||||
enum ParseState
|
||||
{
|
||||
Default,
|
||||
Escaped,
|
||||
Text,
|
||||
TextEscaped
|
||||
};
|
||||
|
||||
void dataFinish();
|
||||
void dataAppend(const char ch);
|
||||
};
|
||||
|
||||
#endif // _COMMANDPARSER_H
|
||||
#ifndef _COMMANDPARSER_H
|
||||
#define _COMMANDPARSER_H
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
Command(const String & command);
|
||||
const String GetText();
|
||||
const String GetArg(const int argnum);
|
||||
const int GetArgCount();
|
||||
|
||||
private:
|
||||
String _data;
|
||||
std::vector<String> _tokens;
|
||||
|
||||
enum ParseState
|
||||
{
|
||||
Default,
|
||||
Escaped,
|
||||
Text,
|
||||
TextEscaped
|
||||
};
|
||||
|
||||
void dataFinish();
|
||||
void dataAppend(const char ch);
|
||||
};
|
||||
|
||||
#endif // _COMMANDPARSER_H
|
||||
|
|
@ -1,249 +1,249 @@
|
|||
#include "comment.h"
|
||||
#include "threading.h"
|
||||
#include "module.h"
|
||||
#include "memory.h"
|
||||
|
||||
std::unordered_map<uint, COMMENTSINFO> comments;
|
||||
|
||||
bool CommentSet(uint Address, const char* Text, bool Manual)
|
||||
{
|
||||
// CHECK: Exported/Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// A valid memory address must be supplied
|
||||
if(!MemIsValidReadPtr(Address))
|
||||
return false;
|
||||
|
||||
// Make sure the string is supplied, within bounds, and not a special delimiter
|
||||
if(!Text || Text[0] == '\1' || strlen(Text) >= MAX_COMMENT_SIZE - 1)
|
||||
return false;
|
||||
|
||||
// Delete the comment if no text was supplied
|
||||
if(Text[0] == '\0')
|
||||
return CommentDelete(Address);
|
||||
|
||||
// Fill out the structure
|
||||
COMMENTSINFO comment;
|
||||
strcpy_s(comment.text, Text);
|
||||
ModNameFromAddr(Address, comment.mod, true);
|
||||
|
||||
comment.manual = Manual;
|
||||
comment.addr = Address - ModBaseFromAddr(Address);
|
||||
|
||||
// Key generated from module hash
|
||||
const uint key = ModHashFromAddr(Address);
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
|
||||
// Insert if possible, otherwise replace
|
||||
if(!comments.insert(std::make_pair(key, comment)).second)
|
||||
comments[key] = comment;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommentGet(uint Address, char* Text)
|
||||
{
|
||||
// CHECK: Exported/Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockComments);
|
||||
|
||||
// Get an existing comment and copy the string buffer
|
||||
auto found = comments.find(ModHashFromAddr(Address));
|
||||
|
||||
// Was it found?
|
||||
if(found == comments.end())
|
||||
return false;
|
||||
|
||||
if(found->second.manual) //autocomment
|
||||
strcpy_s(Text, MAX_COMMENT_SIZE, found->second.text);
|
||||
else
|
||||
sprintf_s(Text, MAX_COMMENT_SIZE, "\1%s", found->second.text);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommentDelete(uint Address)
|
||||
{
|
||||
// CHECK: Command/Sub function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
return (comments.erase(ModHashFromAddr(Address)) > 0);
|
||||
}
|
||||
|
||||
void CommentDelRange(uint Start, uint End)
|
||||
{
|
||||
// CHECK: Export function
|
||||
if(!DbgIsDebugging())
|
||||
return;
|
||||
|
||||
// Are all comments going to be deleted?
|
||||
// 0x00000000 - 0xFFFFFFFF
|
||||
if(Start == 0 && End == ~0)
|
||||
{
|
||||
CommentClear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure 'Start' and 'End' reference the same module
|
||||
uint moduleBase = ModBaseFromAddr(Start);
|
||||
|
||||
if(moduleBase != ModBaseFromAddr(End))
|
||||
return;
|
||||
|
||||
// Virtual -> relative offset
|
||||
Start -= moduleBase;
|
||||
End -= moduleBase;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
for(auto itr = comments.begin(); itr != comments.end();)
|
||||
{
|
||||
const auto & currentComment = itr->second;
|
||||
// Ignore manually set entries
|
||||
if(currentComment.manual)
|
||||
{
|
||||
++itr;
|
||||
continue;
|
||||
}
|
||||
|
||||
// [Start, End)
|
||||
if(currentComment.addr >= Start && currentComment.addr < End)
|
||||
itr = comments.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommentCacheSave(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
|
||||
const JSON jsonComments = json_array();
|
||||
const JSON jsonAutoComments = json_array();
|
||||
|
||||
// Build the JSON array
|
||||
for(auto & itr : comments)
|
||||
{
|
||||
JSON currentComment = json_object();
|
||||
|
||||
json_object_set_new(currentComment, "module", json_string(itr.second.mod));
|
||||
json_object_set_new(currentComment, "address", json_hex(itr.second.addr));
|
||||
json_object_set_new(currentComment, "text", json_string(itr.second.text));
|
||||
|
||||
if(itr.second.manual)
|
||||
json_array_append_new(jsonComments, currentComment);
|
||||
else
|
||||
json_array_append_new(jsonAutoComments, currentComment);
|
||||
}
|
||||
|
||||
// Save to the JSON root
|
||||
if(json_array_size(jsonComments))
|
||||
json_object_set(Root, "comments", jsonComments);
|
||||
|
||||
if(json_array_size(jsonAutoComments))
|
||||
json_object_set(Root, "autocomments", jsonAutoComments);
|
||||
|
||||
json_decref(jsonComments);
|
||||
json_decref(jsonAutoComments);
|
||||
}
|
||||
|
||||
void CommentCacheLoad(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
|
||||
// Inline lambda to parse each JSON entry
|
||||
auto AddComments = [](const JSON Object, bool Manual)
|
||||
{
|
||||
size_t i;
|
||||
JSON value;
|
||||
|
||||
json_array_foreach(Object, i, value)
|
||||
{
|
||||
COMMENTSINFO commentInfo;
|
||||
memset(&commentInfo, 0, sizeof(COMMENTSINFO));
|
||||
|
||||
// Module
|
||||
const char* mod = json_string_value(json_object_get(value, "module"));
|
||||
|
||||
if(mod && strlen(mod) < MAX_MODULE_SIZE)
|
||||
strcpy_s(commentInfo.mod, mod);
|
||||
|
||||
// Address/Manual
|
||||
commentInfo.addr = (uint)json_hex_value(json_object_get(value, "address"));
|
||||
commentInfo.manual = Manual;
|
||||
|
||||
// String value
|
||||
const char* text = json_string_value(json_object_get(value, "text"));
|
||||
|
||||
if(text)
|
||||
strcpy_s(commentInfo.text, text);
|
||||
else
|
||||
{
|
||||
// Skip blank comments
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint key = ModHashFromName(commentInfo.mod) + commentInfo.addr;
|
||||
comments.insert(std::make_pair(key, commentInfo));
|
||||
}
|
||||
};
|
||||
|
||||
// Remove existing entries
|
||||
comments.clear();
|
||||
|
||||
const JSON jsonComments = json_object_get(Root, "comments");
|
||||
const JSON jsonAutoComments = json_object_get(Root, "autocomments");
|
||||
|
||||
// Load user-set comments
|
||||
if(jsonComments)
|
||||
AddComments(jsonComments, true);
|
||||
|
||||
// Load auto-set comments
|
||||
if(jsonAutoComments)
|
||||
AddComments(jsonAutoComments, false);
|
||||
}
|
||||
|
||||
bool CommentEnum(COMMENTSINFO* List, size_t* Size)
|
||||
{
|
||||
// CHECK: Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// At least 1 parameter must be supplied
|
||||
if(!List && !Size)
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockComments);
|
||||
|
||||
// Check if the user requested size only
|
||||
if(Size)
|
||||
{
|
||||
*Size = comments.size() * sizeof(COMMENTSINFO);
|
||||
|
||||
if(!List)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Populate the returned array
|
||||
for(auto & itr : comments)
|
||||
{
|
||||
*List = itr.second;
|
||||
List->addr += ModBaseFromName(List->mod);
|
||||
|
||||
List++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommentClear()
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
comments.clear();
|
||||
#include "comment.h"
|
||||
#include "threading.h"
|
||||
#include "module.h"
|
||||
#include "memory.h"
|
||||
|
||||
std::unordered_map<uint, COMMENTSINFO> comments;
|
||||
|
||||
bool CommentSet(uint Address, const char* Text, bool Manual)
|
||||
{
|
||||
// CHECK: Exported/Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// A valid memory address must be supplied
|
||||
if(!MemIsValidReadPtr(Address))
|
||||
return false;
|
||||
|
||||
// Make sure the string is supplied, within bounds, and not a special delimiter
|
||||
if(!Text || Text[0] == '\1' || strlen(Text) >= MAX_COMMENT_SIZE - 1)
|
||||
return false;
|
||||
|
||||
// Delete the comment if no text was supplied
|
||||
if(Text[0] == '\0')
|
||||
return CommentDelete(Address);
|
||||
|
||||
// Fill out the structure
|
||||
COMMENTSINFO comment;
|
||||
strcpy_s(comment.text, Text);
|
||||
ModNameFromAddr(Address, comment.mod, true);
|
||||
|
||||
comment.manual = Manual;
|
||||
comment.addr = Address - ModBaseFromAddr(Address);
|
||||
|
||||
// Key generated from module hash
|
||||
const uint key = ModHashFromAddr(Address);
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
|
||||
// Insert if possible, otherwise replace
|
||||
if(!comments.insert(std::make_pair(key, comment)).second)
|
||||
comments[key] = comment;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommentGet(uint Address, char* Text)
|
||||
{
|
||||
// CHECK: Exported/Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockComments);
|
||||
|
||||
// Get an existing comment and copy the string buffer
|
||||
auto found = comments.find(ModHashFromAddr(Address));
|
||||
|
||||
// Was it found?
|
||||
if(found == comments.end())
|
||||
return false;
|
||||
|
||||
if(found->second.manual) //autocomment
|
||||
strcpy_s(Text, MAX_COMMENT_SIZE, found->second.text);
|
||||
else
|
||||
sprintf_s(Text, MAX_COMMENT_SIZE, "\1%s", found->second.text);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommentDelete(uint Address)
|
||||
{
|
||||
// CHECK: Command/Sub function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
return (comments.erase(ModHashFromAddr(Address)) > 0);
|
||||
}
|
||||
|
||||
void CommentDelRange(uint Start, uint End)
|
||||
{
|
||||
// CHECK: Export function
|
||||
if(!DbgIsDebugging())
|
||||
return;
|
||||
|
||||
// Are all comments going to be deleted?
|
||||
// 0x00000000 - 0xFFFFFFFF
|
||||
if(Start == 0 && End == ~0)
|
||||
{
|
||||
CommentClear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure 'Start' and 'End' reference the same module
|
||||
uint moduleBase = ModBaseFromAddr(Start);
|
||||
|
||||
if(moduleBase != ModBaseFromAddr(End))
|
||||
return;
|
||||
|
||||
// Virtual -> relative offset
|
||||
Start -= moduleBase;
|
||||
End -= moduleBase;
|
||||
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
for(auto itr = comments.begin(); itr != comments.end();)
|
||||
{
|
||||
const auto & currentComment = itr->second;
|
||||
// Ignore manually set entries
|
||||
if(currentComment.manual)
|
||||
{
|
||||
++itr;
|
||||
continue;
|
||||
}
|
||||
|
||||
// [Start, End)
|
||||
if(currentComment.addr >= Start && currentComment.addr < End)
|
||||
itr = comments.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommentCacheSave(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
|
||||
const JSON jsonComments = json_array();
|
||||
const JSON jsonAutoComments = json_array();
|
||||
|
||||
// Build the JSON array
|
||||
for(auto & itr : comments)
|
||||
{
|
||||
JSON currentComment = json_object();
|
||||
|
||||
json_object_set_new(currentComment, "module", json_string(itr.second.mod));
|
||||
json_object_set_new(currentComment, "address", json_hex(itr.second.addr));
|
||||
json_object_set_new(currentComment, "text", json_string(itr.second.text));
|
||||
|
||||
if(itr.second.manual)
|
||||
json_array_append_new(jsonComments, currentComment);
|
||||
else
|
||||
json_array_append_new(jsonAutoComments, currentComment);
|
||||
}
|
||||
|
||||
// Save to the JSON root
|
||||
if(json_array_size(jsonComments))
|
||||
json_object_set(Root, "comments", jsonComments);
|
||||
|
||||
if(json_array_size(jsonAutoComments))
|
||||
json_object_set(Root, "autocomments", jsonAutoComments);
|
||||
|
||||
json_decref(jsonComments);
|
||||
json_decref(jsonAutoComments);
|
||||
}
|
||||
|
||||
void CommentCacheLoad(JSON Root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
|
||||
// Inline lambda to parse each JSON entry
|
||||
auto AddComments = [](const JSON Object, bool Manual)
|
||||
{
|
||||
size_t i;
|
||||
JSON value;
|
||||
|
||||
json_array_foreach(Object, i, value)
|
||||
{
|
||||
COMMENTSINFO commentInfo;
|
||||
memset(&commentInfo, 0, sizeof(COMMENTSINFO));
|
||||
|
||||
// Module
|
||||
const char* mod = json_string_value(json_object_get(value, "module"));
|
||||
|
||||
if(mod && strlen(mod) < MAX_MODULE_SIZE)
|
||||
strcpy_s(commentInfo.mod, mod);
|
||||
|
||||
// Address/Manual
|
||||
commentInfo.addr = (uint)json_hex_value(json_object_get(value, "address"));
|
||||
commentInfo.manual = Manual;
|
||||
|
||||
// String value
|
||||
const char* text = json_string_value(json_object_get(value, "text"));
|
||||
|
||||
if(text)
|
||||
strcpy_s(commentInfo.text, text);
|
||||
else
|
||||
{
|
||||
// Skip blank comments
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint key = ModHashFromName(commentInfo.mod) + commentInfo.addr;
|
||||
comments.insert(std::make_pair(key, commentInfo));
|
||||
}
|
||||
};
|
||||
|
||||
// Remove existing entries
|
||||
comments.clear();
|
||||
|
||||
const JSON jsonComments = json_object_get(Root, "comments");
|
||||
const JSON jsonAutoComments = json_object_get(Root, "autocomments");
|
||||
|
||||
// Load user-set comments
|
||||
if(jsonComments)
|
||||
AddComments(jsonComments, true);
|
||||
|
||||
// Load auto-set comments
|
||||
if(jsonAutoComments)
|
||||
AddComments(jsonAutoComments, false);
|
||||
}
|
||||
|
||||
bool CommentEnum(COMMENTSINFO* List, size_t* Size)
|
||||
{
|
||||
// CHECK: Command function
|
||||
if(!DbgIsDebugging())
|
||||
return false;
|
||||
|
||||
// At least 1 parameter must be supplied
|
||||
if(!List && !Size)
|
||||
return false;
|
||||
|
||||
SHARED_ACQUIRE(LockComments);
|
||||
|
||||
// Check if the user requested size only
|
||||
if(Size)
|
||||
{
|
||||
*Size = comments.size() * sizeof(COMMENTSINFO);
|
||||
|
||||
if(!List)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Populate the returned array
|
||||
for(auto & itr : comments)
|
||||
{
|
||||
*List = itr.second;
|
||||
List->addr += ModBaseFromName(List->mod);
|
||||
|
||||
List++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommentClear()
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockComments);
|
||||
comments.clear();
|
||||
}
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
struct COMMENTSINFO
|
||||
{
|
||||
char mod[MAX_MODULE_SIZE];
|
||||
uint addr;
|
||||
char text[MAX_COMMENT_SIZE];
|
||||
bool manual;
|
||||
};
|
||||
|
||||
bool CommentSet(uint Address, const char* Text, bool Manual);
|
||||
bool CommentGet(uint Address, char* Text);
|
||||
bool CommentDelete(uint Address);
|
||||
void CommentDelRange(uint Start, uint End);
|
||||
void CommentCacheSave(JSON Root);
|
||||
void CommentCacheLoad(JSON Root);
|
||||
bool CommentEnum(COMMENTSINFO* List, size_t* Size);
|
||||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
struct COMMENTSINFO
|
||||
{
|
||||
char mod[MAX_MODULE_SIZE];
|
||||
uint addr;
|
||||
char text[MAX_COMMENT_SIZE];
|
||||
bool manual;
|
||||
};
|
||||
|
||||
bool CommentSet(uint Address, const char* Text, bool Manual);
|
||||
bool CommentGet(uint Address, char* Text);
|
||||
bool CommentDelete(uint Address);
|
||||
void CommentDelRange(uint Start, uint End);
|
||||
void CommentCacheSave(JSON Root);
|
||||
void CommentCacheLoad(JSON Root);
|
||||
bool CommentEnum(COMMENTSINFO* List, size_t* Size);
|
||||
void CommentClear();
|
||||
|
|
@ -1,41 +1,41 @@
|
|||
/**
|
||||
\file console.cpp
|
||||
\brief Implements the console class.
|
||||
*/
|
||||
|
||||
#include "console.h"
|
||||
|
||||
/**
|
||||
\brief Print a line with text, terminated with a newline to the console.
|
||||
\param text The text to print.
|
||||
*/
|
||||
void dputs(const char* Text)
|
||||
{
|
||||
dprintf("%s\n", Text);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Print a formatted string to the console.
|
||||
\param format The printf format to use (see documentation of printf for more information).
|
||||
*/
|
||||
void dprintf(const char* Format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, Format);
|
||||
dprintf_args(Format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Print a formatted string to the console.
|
||||
\param format The printf format to use (see documentation of printf for more information).
|
||||
\param Args The argument buffer passed to the string parser.
|
||||
*/
|
||||
void dprintf_args(const char* Format, va_list Args)
|
||||
{
|
||||
char buffer[16384];
|
||||
vsnprintf_s(buffer, _TRUNCATE, Format, Args);
|
||||
|
||||
GuiAddLogMessage(buffer);
|
||||
}
|
||||
/**
|
||||
\file console.cpp
|
||||
\brief Implements the console class.
|
||||
*/
|
||||
|
||||
#include "console.h"
|
||||
|
||||
/**
|
||||
\brief Print a line with text, terminated with a newline to the console.
|
||||
\param text The text to print.
|
||||
*/
|
||||
void dputs(const char* Text)
|
||||
{
|
||||
dprintf("%s\n", Text);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Print a formatted string to the console.
|
||||
\param format The printf format to use (see documentation of printf for more information).
|
||||
*/
|
||||
void dprintf(const char* Format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, Format);
|
||||
dprintf_args(Format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Print a formatted string to the console.
|
||||
\param format The printf format to use (see documentation of printf for more information).
|
||||
\param Args The argument buffer passed to the string parser.
|
||||
*/
|
||||
void dprintf_args(const char* Format, va_list Args)
|
||||
{
|
||||
char buffer[16384];
|
||||
vsnprintf_s(buffer, _TRUNCATE, Format, Args);
|
||||
|
||||
GuiAddLogMessage(buffer);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
void dputs(const char* Text);
|
||||
void dprintf(const char* Format, ...);
|
||||
#pragma once
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
void dputs(const char* Text);
|
||||
void dprintf(const char* Format, ...);
|
||||
void dprintf_args(const char* Format, va_list Args);
|
||||
|
|
@ -1,445 +1,445 @@
|
|||
#include "controlflowanalysis.h"
|
||||
#include "console.h"
|
||||
#include "module.h"
|
||||
#include "TitanEngine/TitanEngine.h"
|
||||
#include "memory.h"
|
||||
#include "function.h"
|
||||
|
||||
ControlFlowAnalysis::ControlFlowAnalysis(uint base, uint size, bool exceptionDirectory) : Analysis(base, size)
|
||||
{
|
||||
_functionInfoData = nullptr;
|
||||
#ifdef _WIN64
|
||||
// This will only be valid if the address range is within a loaded module
|
||||
_moduleBase = ModBaseFromAddr(base);
|
||||
|
||||
if(exceptionDirectory && _moduleBase != 0)
|
||||
{
|
||||
char modulePath[MAX_PATH];
|
||||
memset(modulePath, 0, sizeof(modulePath));
|
||||
|
||||
ModPathFromAddr(_moduleBase, modulePath, ARRAYSIZE(modulePath));
|
||||
|
||||
HANDLE fileHandle;
|
||||
DWORD fileSize;
|
||||
HANDLE fileMapHandle;
|
||||
ULONG_PTR fileMapVa;
|
||||
if(StaticFileLoadW(
|
||||
StringUtils::Utf8ToUtf16(modulePath).c_str(),
|
||||
UE_ACCESS_READ,
|
||||
false,
|
||||
&fileHandle,
|
||||
&fileSize,
|
||||
&fileMapHandle,
|
||||
&fileMapVa))
|
||||
{
|
||||
// Find a pointer to IMAGE_DIRECTORY_ENTRY_EXCEPTION for later use
|
||||
ULONG_PTR virtualOffset = GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALOFFSET);
|
||||
_functionInfoSize = (uint)GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALSIZE);
|
||||
|
||||
// Unload the file
|
||||
StaticFileUnloadW(nullptr, false, fileHandle, fileSize, fileMapHandle, fileMapVa);
|
||||
|
||||
// Get a copy of the function table
|
||||
if(virtualOffset)
|
||||
{
|
||||
// Read the table into a buffer
|
||||
_functionInfoData = emalloc(_functionInfoSize);
|
||||
|
||||
if(_functionInfoData)
|
||||
MemRead(virtualOffset + _moduleBase, _functionInfoData, _functionInfoSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //_WIN64
|
||||
}
|
||||
|
||||
ControlFlowAnalysis::~ControlFlowAnalysis()
|
||||
{
|
||||
if(_functionInfoData)
|
||||
efree(_functionInfoData);
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::Analyse()
|
||||
{
|
||||
dputs("Starting analysis...");
|
||||
DWORD ticks = GetTickCount();
|
||||
|
||||
BasicBlockStarts();
|
||||
dprintf("Basic block starts in %ums!\n", GetTickCount() - ticks);
|
||||
ticks = GetTickCount();
|
||||
|
||||
BasicBlocks();
|
||||
dprintf("Basic blocks in %ums!\n", GetTickCount() - ticks);
|
||||
ticks = GetTickCount();
|
||||
|
||||
Functions();
|
||||
dprintf("Functions in %ums!\n", GetTickCount() - ticks);
|
||||
ticks = GetTickCount();
|
||||
|
||||
FunctionRanges();
|
||||
dprintf("Function ranges in %ums!\n", GetTickCount() - ticks);
|
||||
ticks = GetTickCount();
|
||||
|
||||
dprintf("Analysis finished!\n");
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::SetMarkers()
|
||||
{
|
||||
FunctionDelRange(_base, _base + _size);
|
||||
auto size = _functionRanges.size();
|
||||
for(size_t i = size - 1; i != -1; i--)
|
||||
{
|
||||
const auto & range = _functionRanges[i];
|
||||
FunctionAdd(range.first, range.second, false);
|
||||
}
|
||||
/*dprintf("digraph ControlFlow {\n");
|
||||
int i = 0;
|
||||
std::map<uint, int> nodeMap;
|
||||
for(const auto & it : _blocks)
|
||||
{
|
||||
const auto & block = it.second;
|
||||
nodeMap.insert({ block.start, i });
|
||||
dprintf(" node%u [label=\"s=%p, e=%p, f=%p\"];\n", i, block.start, block.end, block.function);
|
||||
i++;
|
||||
}
|
||||
for(auto it : _blocks)
|
||||
{
|
||||
const auto & block = it.second;
|
||||
int startNode = nodeMap[block.start];
|
||||
if(block.left)
|
||||
{
|
||||
if(nodeMap.count(block.left))
|
||||
dprintf(" node%u -> node%u;\n", startNode, nodeMap[block.left]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf(" node%u [shape=point];\n", i);
|
||||
dprintf(" node%u -> node%u;\n", startNode, i);
|
||||
i++;
|
||||
}
|
||||
if(block.right)
|
||||
{
|
||||
if(nodeMap.count(block.right))
|
||||
dprintf(" node%u -> node%u;\n", startNode, nodeMap[block.right]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf(" node%u [shape=point];\n", i);
|
||||
dprintf(" node%u -> node%u;\n", startNode, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
dprintf("}\n");*/
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::BasicBlockStarts()
|
||||
{
|
||||
_blockStarts.insert(_base);
|
||||
bool bSkipFilling = false;
|
||||
for(uint i = 0; i < _size;)
|
||||
{
|
||||
uint addr = _base + i;
|
||||
if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(bSkipFilling) //handle filling skip mode
|
||||
{
|
||||
if(!_cp.IsFilling()) //do nothing until the filling stopped
|
||||
{
|
||||
bSkipFilling = false;
|
||||
_blockStarts.insert(addr);
|
||||
}
|
||||
}
|
||||
else if(_cp.InGroup(CS_GRP_RET) || _cp.GetId() == X86_INS_INT3) //RET/INT3 break control flow
|
||||
{
|
||||
bSkipFilling = true; //skip INT3/NOP/whatever filling bytes (those are not part of the control flow)
|
||||
}
|
||||
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) //branches
|
||||
{
|
||||
uint dest1 = GetReferenceOperand();
|
||||
uint dest2 = 0;
|
||||
if(_cp.GetId() != X86_INS_JMP) //unconditional jump
|
||||
dest2 = addr + _cp.Size();
|
||||
|
||||
if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
|
||||
bSkipFilling = true;
|
||||
if(dest1)
|
||||
_blockStarts.insert(dest1);
|
||||
if(dest2)
|
||||
_blockStarts.insert(dest2);
|
||||
}
|
||||
else if(_cp.InGroup(CS_GRP_CALL))
|
||||
{
|
||||
uint dest1 = GetReferenceOperand();
|
||||
if(dest1)
|
||||
{
|
||||
_blockStarts.insert(dest1);
|
||||
_functionStarts.insert(dest1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint dest1 = GetReferenceOperand();
|
||||
if(dest1)
|
||||
_blockStarts.insert(dest1);
|
||||
}
|
||||
i += _cp.Size();
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::BasicBlocks()
|
||||
{
|
||||
for(auto i = _blockStarts.begin(); i != _blockStarts.end(); ++i)
|
||||
{
|
||||
uint start = *i;
|
||||
if(!IsValidAddress(start))
|
||||
continue;
|
||||
uint nextStart = _base + _size;
|
||||
auto next = std::next(i);
|
||||
if(next != _blockStarts.end())
|
||||
nextStart = *next;
|
||||
for(uint addr = start, prevaddr = 0; addr < _base + _size;)
|
||||
{
|
||||
prevaddr = addr;
|
||||
if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(_cp.InGroup(CS_GRP_RET) || _cp.GetId() == X86_INS_INT3)
|
||||
{
|
||||
insertBlock(BasicBlock(start, addr, 0, 0)); //leaf block
|
||||
break;
|
||||
}
|
||||
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop())
|
||||
{
|
||||
uint dest1 = GetReferenceOperand();
|
||||
uint dest2 = _cp.GetId() != X86_INS_JMP ? addr + _cp.Size() : 0;
|
||||
insertBlock(BasicBlock(start, addr, dest1, dest2));
|
||||
insertParent(dest1, start);
|
||||
insertParent(dest2, start);
|
||||
break;
|
||||
}
|
||||
addr += _cp.Size();
|
||||
}
|
||||
else
|
||||
addr++;
|
||||
if(addr == nextStart) //special case handling overlapping blocks
|
||||
{
|
||||
insertBlock(BasicBlock(start, prevaddr, 0, nextStart));
|
||||
insertParent(nextStart, start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_blockStarts.clear();
|
||||
|
||||
#ifdef _WIN64
|
||||
int count = 0;
|
||||
EnumerateFunctionRuntimeEntries64([&](PRUNTIME_FUNCTION Function)
|
||||
{
|
||||
const uint funcAddr = _moduleBase + Function->BeginAddress;
|
||||
const uint funcEnd = _moduleBase + Function->EndAddress;
|
||||
|
||||
// If within limits...
|
||||
if(funcAddr >= _base && funcAddr < _base + _size)
|
||||
_functionStarts.insert(funcAddr);
|
||||
count++;
|
||||
return true;
|
||||
});
|
||||
dprintf("%u functions from the exception directory...\n", count);
|
||||
#endif // _WIN64
|
||||
|
||||
dprintf("%u basic blocks, %u function starts detected...\n", _blocks.size(), _functionStarts.size());
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::Functions()
|
||||
{
|
||||
typedef std::pair<BasicBlock*, UintSet*> DelayedBlock;
|
||||
std::vector<DelayedBlock> delayedBlocks;
|
||||
for(auto & it : _blocks)
|
||||
{
|
||||
BasicBlock* block = &it.second;
|
||||
UintSet* parents = findParents(block->start);
|
||||
if(!block->function)
|
||||
{
|
||||
if(!parents || _functionStarts.count(block->start)) //no parents = function start
|
||||
{
|
||||
uint functionStart = block->start;
|
||||
block->function = functionStart;
|
||||
UintSet functionBlocks;
|
||||
functionBlocks.insert(functionStart);
|
||||
_functions[functionStart] = functionBlocks;
|
||||
}
|
||||
else //in function
|
||||
{
|
||||
uint function = findFunctionStart(block, parents);
|
||||
if(!function) //this happens with loops / unreferenced blocks sometimes
|
||||
delayedBlocks.push_back(DelayedBlock(block, parents));
|
||||
else
|
||||
block->function = function;
|
||||
}
|
||||
}
|
||||
else
|
||||
DebugBreak(); //this should not happen
|
||||
}
|
||||
int delayedCount = (int)delayedBlocks.size();
|
||||
dprintf("%u/%u delayed blocks...\n", delayedCount, _blocks.size());
|
||||
int resolved = 0;
|
||||
for(auto & delayedBlock : delayedBlocks)
|
||||
{
|
||||
BasicBlock* block = delayedBlock.first;
|
||||
UintSet* parents = delayedBlock.second;
|
||||
uint function = findFunctionStart(block, parents);
|
||||
if(!function)
|
||||
{
|
||||
continue;
|
||||
/*dprintf("unresolved block %s\n", blockToString(block).c_str());
|
||||
if(parents)
|
||||
{
|
||||
dprintf("parents:\n");
|
||||
for(auto parent : *parents)
|
||||
dprintf(" %s\n", blockToString(findBlock(parent)).c_str());
|
||||
}
|
||||
else
|
||||
dprintf("parents: null");
|
||||
dprintf("left: %s\n", blockToString(findBlock(block->left)).c_str());
|
||||
dprintf("right: %s\n", blockToString(findBlock(block->right)).c_str());
|
||||
return;*/
|
||||
}
|
||||
block->function = function;
|
||||
resolved++;
|
||||
}
|
||||
dprintf("%u/%u delayed blocks resolved (%u/%u still left, probably unreferenced functions)\n", resolved, delayedCount, delayedCount - resolved, _blocks.size());
|
||||
int unreferencedCount = 0;
|
||||
for(const auto & block : _blocks)
|
||||
{
|
||||
auto found = _functions.find(block.second.function);
|
||||
if(found == _functions.end()) //unreferenced block
|
||||
{
|
||||
unreferencedCount++;
|
||||
continue;
|
||||
}
|
||||
found->second.insert(block.second.start);
|
||||
}
|
||||
dprintf("%u/%u unreferenced blocks\n", unreferencedCount, _blocks.size());
|
||||
dprintf("%u functions found!\n", _functions.size());
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::FunctionRanges()
|
||||
{
|
||||
//iterate over the functions and then find the deepest block = function end
|
||||
for(const auto & function : _functions)
|
||||
{
|
||||
uint start = function.first;
|
||||
uint end = start;
|
||||
for(auto blockstart : function.second)
|
||||
{
|
||||
BasicBlock* block = this->findBlock(blockstart);
|
||||
if(!block)
|
||||
DebugBreak(); //this shouldn't happen
|
||||
if(block->end > end)
|
||||
end = block->end;
|
||||
}
|
||||
_functionRanges.push_back({ start, end });
|
||||
}
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::insertBlock(BasicBlock block)
|
||||
{
|
||||
if(_blocks.find(block.start) != _blocks.end())
|
||||
DebugBreak();
|
||||
_blocks[block.start] = block;
|
||||
}
|
||||
|
||||
ControlFlowAnalysis::BasicBlock* ControlFlowAnalysis::findBlock(uint start)
|
||||
{
|
||||
if(!start)
|
||||
return nullptr;
|
||||
auto found = _blocks.find(start);
|
||||
return found != _blocks.end() ? &found->second : nullptr;
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::insertParent(uint child, uint parent)
|
||||
{
|
||||
if(!child || !parent)
|
||||
return;
|
||||
auto found = _parentMap.find(child);
|
||||
if(found == _parentMap.end())
|
||||
{
|
||||
UintSet parents;
|
||||
parents.insert(parent);
|
||||
_parentMap[child] = parents;
|
||||
}
|
||||
else
|
||||
found->second.insert(parent);
|
||||
}
|
||||
|
||||
ControlFlowAnalysis::UintSet* ControlFlowAnalysis::findParents(uint child)
|
||||
{
|
||||
if(!child)
|
||||
return nullptr;
|
||||
auto found = _parentMap.find(child);
|
||||
return found != _parentMap.end() ? &found->second : nullptr;
|
||||
}
|
||||
|
||||
uint ControlFlowAnalysis::findFunctionStart(BasicBlock* block, ControlFlowAnalysis::UintSet* parents)
|
||||
{
|
||||
if(!block)
|
||||
return 0;
|
||||
if(block->function)
|
||||
return block->function;
|
||||
BasicBlock* left = findBlock(block->left);
|
||||
if(left && left->function)
|
||||
return left->function;
|
||||
BasicBlock* right = findBlock(block->right);
|
||||
if(right && right->function)
|
||||
return right->function;
|
||||
for(auto start : *parents)
|
||||
{
|
||||
BasicBlock* parent = findBlock(start);
|
||||
if(parent->function)
|
||||
return parent->function;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
String ControlFlowAnalysis::blockToString(BasicBlock* block)
|
||||
{
|
||||
if(!block)
|
||||
return String("null");
|
||||
return block->toString();
|
||||
}
|
||||
|
||||
uint ControlFlowAnalysis::GetReferenceOperand()
|
||||
{
|
||||
for(int i = 0; i < _cp.x86().op_count; i++)
|
||||
{
|
||||
const cs_x86_op & operand = _cp.x86().operands[i];
|
||||
if(operand.type == X86_OP_IMM)
|
||||
{
|
||||
uint dest = (uint)operand.imm;
|
||||
if(dest >= _base && dest < _base + _size)
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
void ControlFlowAnalysis::EnumerateFunctionRuntimeEntries64(std::function<bool(PRUNTIME_FUNCTION)> Callback)
|
||||
{
|
||||
if(!_functionInfoData)
|
||||
return;
|
||||
|
||||
// Get the table pointer and size
|
||||
auto functionTable = (PRUNTIME_FUNCTION)_functionInfoData;
|
||||
uint totalCount = (_functionInfoSize / sizeof(RUNTIME_FUNCTION));
|
||||
|
||||
// Enumerate each entry
|
||||
for(ULONG i = 0; i < totalCount; i++)
|
||||
{
|
||||
if(!Callback(&functionTable[i]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
#include "controlflowanalysis.h"
|
||||
#include "console.h"
|
||||
#include "module.h"
|
||||
#include "TitanEngine/TitanEngine.h"
|
||||
#include "memory.h"
|
||||
#include "function.h"
|
||||
|
||||
ControlFlowAnalysis::ControlFlowAnalysis(uint base, uint size, bool exceptionDirectory) : Analysis(base, size)
|
||||
{
|
||||
_functionInfoData = nullptr;
|
||||
#ifdef _WIN64
|
||||
// This will only be valid if the address range is within a loaded module
|
||||
_moduleBase = ModBaseFromAddr(base);
|
||||
|
||||
if(exceptionDirectory && _moduleBase != 0)
|
||||
{
|
||||
char modulePath[MAX_PATH];
|
||||
memset(modulePath, 0, sizeof(modulePath));
|
||||
|
||||
ModPathFromAddr(_moduleBase, modulePath, ARRAYSIZE(modulePath));
|
||||
|
||||
HANDLE fileHandle;
|
||||
DWORD fileSize;
|
||||
HANDLE fileMapHandle;
|
||||
ULONG_PTR fileMapVa;
|
||||
if(StaticFileLoadW(
|
||||
StringUtils::Utf8ToUtf16(modulePath).c_str(),
|
||||
UE_ACCESS_READ,
|
||||
false,
|
||||
&fileHandle,
|
||||
&fileSize,
|
||||
&fileMapHandle,
|
||||
&fileMapVa))
|
||||
{
|
||||
// Find a pointer to IMAGE_DIRECTORY_ENTRY_EXCEPTION for later use
|
||||
ULONG_PTR virtualOffset = GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALOFFSET);
|
||||
_functionInfoSize = (uint)GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALSIZE);
|
||||
|
||||
// Unload the file
|
||||
StaticFileUnloadW(nullptr, false, fileHandle, fileSize, fileMapHandle, fileMapVa);
|
||||
|
||||
// Get a copy of the function table
|
||||
if(virtualOffset)
|
||||
{
|
||||
// Read the table into a buffer
|
||||
_functionInfoData = emalloc(_functionInfoSize);
|
||||
|
||||
if(_functionInfoData)
|
||||
MemRead(virtualOffset + _moduleBase, _functionInfoData, _functionInfoSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //_WIN64
|
||||
}
|
||||
|
||||
ControlFlowAnalysis::~ControlFlowAnalysis()
|
||||
{
|
||||
if(_functionInfoData)
|
||||
efree(_functionInfoData);
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::Analyse()
|
||||
{
|
||||
dputs("Starting analysis...");
|
||||
DWORD ticks = GetTickCount();
|
||||
|
||||
BasicBlockStarts();
|
||||
dprintf("Basic block starts in %ums!\n", GetTickCount() - ticks);
|
||||
ticks = GetTickCount();
|
||||
|
||||
BasicBlocks();
|
||||
dprintf("Basic blocks in %ums!\n", GetTickCount() - ticks);
|
||||
ticks = GetTickCount();
|
||||
|
||||
Functions();
|
||||
dprintf("Functions in %ums!\n", GetTickCount() - ticks);
|
||||
ticks = GetTickCount();
|
||||
|
||||
FunctionRanges();
|
||||
dprintf("Function ranges in %ums!\n", GetTickCount() - ticks);
|
||||
ticks = GetTickCount();
|
||||
|
||||
dprintf("Analysis finished!\n");
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::SetMarkers()
|
||||
{
|
||||
FunctionDelRange(_base, _base + _size);
|
||||
auto size = _functionRanges.size();
|
||||
for(size_t i = size - 1; i != -1; i--)
|
||||
{
|
||||
const auto & range = _functionRanges[i];
|
||||
FunctionAdd(range.first, range.second, false);
|
||||
}
|
||||
/*dprintf("digraph ControlFlow {\n");
|
||||
int i = 0;
|
||||
std::map<uint, int> nodeMap;
|
||||
for(const auto & it : _blocks)
|
||||
{
|
||||
const auto & block = it.second;
|
||||
nodeMap.insert({ block.start, i });
|
||||
dprintf(" node%u [label=\"s=%p, e=%p, f=%p\"];\n", i, block.start, block.end, block.function);
|
||||
i++;
|
||||
}
|
||||
for(auto it : _blocks)
|
||||
{
|
||||
const auto & block = it.second;
|
||||
int startNode = nodeMap[block.start];
|
||||
if(block.left)
|
||||
{
|
||||
if(nodeMap.count(block.left))
|
||||
dprintf(" node%u -> node%u;\n", startNode, nodeMap[block.left]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf(" node%u [shape=point];\n", i);
|
||||
dprintf(" node%u -> node%u;\n", startNode, i);
|
||||
i++;
|
||||
}
|
||||
if(block.right)
|
||||
{
|
||||
if(nodeMap.count(block.right))
|
||||
dprintf(" node%u -> node%u;\n", startNode, nodeMap[block.right]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf(" node%u [shape=point];\n", i);
|
||||
dprintf(" node%u -> node%u;\n", startNode, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
dprintf("}\n");*/
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::BasicBlockStarts()
|
||||
{
|
||||
_blockStarts.insert(_base);
|
||||
bool bSkipFilling = false;
|
||||
for(uint i = 0; i < _size;)
|
||||
{
|
||||
uint addr = _base + i;
|
||||
if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(bSkipFilling) //handle filling skip mode
|
||||
{
|
||||
if(!_cp.IsFilling()) //do nothing until the filling stopped
|
||||
{
|
||||
bSkipFilling = false;
|
||||
_blockStarts.insert(addr);
|
||||
}
|
||||
}
|
||||
else if(_cp.InGroup(CS_GRP_RET) || _cp.GetId() == X86_INS_INT3) //RET/INT3 break control flow
|
||||
{
|
||||
bSkipFilling = true; //skip INT3/NOP/whatever filling bytes (those are not part of the control flow)
|
||||
}
|
||||
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) //branches
|
||||
{
|
||||
uint dest1 = GetReferenceOperand();
|
||||
uint dest2 = 0;
|
||||
if(_cp.GetId() != X86_INS_JMP) //unconditional jump
|
||||
dest2 = addr + _cp.Size();
|
||||
|
||||
if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
|
||||
bSkipFilling = true;
|
||||
if(dest1)
|
||||
_blockStarts.insert(dest1);
|
||||
if(dest2)
|
||||
_blockStarts.insert(dest2);
|
||||
}
|
||||
else if(_cp.InGroup(CS_GRP_CALL))
|
||||
{
|
||||
uint dest1 = GetReferenceOperand();
|
||||
if(dest1)
|
||||
{
|
||||
_blockStarts.insert(dest1);
|
||||
_functionStarts.insert(dest1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint dest1 = GetReferenceOperand();
|
||||
if(dest1)
|
||||
_blockStarts.insert(dest1);
|
||||
}
|
||||
i += _cp.Size();
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::BasicBlocks()
|
||||
{
|
||||
for(auto i = _blockStarts.begin(); i != _blockStarts.end(); ++i)
|
||||
{
|
||||
uint start = *i;
|
||||
if(!IsValidAddress(start))
|
||||
continue;
|
||||
uint nextStart = _base + _size;
|
||||
auto next = std::next(i);
|
||||
if(next != _blockStarts.end())
|
||||
nextStart = *next;
|
||||
for(uint addr = start, prevaddr = 0; addr < _base + _size;)
|
||||
{
|
||||
prevaddr = addr;
|
||||
if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(_cp.InGroup(CS_GRP_RET) || _cp.GetId() == X86_INS_INT3)
|
||||
{
|
||||
insertBlock(BasicBlock(start, addr, 0, 0)); //leaf block
|
||||
break;
|
||||
}
|
||||
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop())
|
||||
{
|
||||
uint dest1 = GetReferenceOperand();
|
||||
uint dest2 = _cp.GetId() != X86_INS_JMP ? addr + _cp.Size() : 0;
|
||||
insertBlock(BasicBlock(start, addr, dest1, dest2));
|
||||
insertParent(dest1, start);
|
||||
insertParent(dest2, start);
|
||||
break;
|
||||
}
|
||||
addr += _cp.Size();
|
||||
}
|
||||
else
|
||||
addr++;
|
||||
if(addr == nextStart) //special case handling overlapping blocks
|
||||
{
|
||||
insertBlock(BasicBlock(start, prevaddr, 0, nextStart));
|
||||
insertParent(nextStart, start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_blockStarts.clear();
|
||||
|
||||
#ifdef _WIN64
|
||||
int count = 0;
|
||||
EnumerateFunctionRuntimeEntries64([&](PRUNTIME_FUNCTION Function)
|
||||
{
|
||||
const uint funcAddr = _moduleBase + Function->BeginAddress;
|
||||
const uint funcEnd = _moduleBase + Function->EndAddress;
|
||||
|
||||
// If within limits...
|
||||
if(funcAddr >= _base && funcAddr < _base + _size)
|
||||
_functionStarts.insert(funcAddr);
|
||||
count++;
|
||||
return true;
|
||||
});
|
||||
dprintf("%u functions from the exception directory...\n", count);
|
||||
#endif // _WIN64
|
||||
|
||||
dprintf("%u basic blocks, %u function starts detected...\n", _blocks.size(), _functionStarts.size());
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::Functions()
|
||||
{
|
||||
typedef std::pair<BasicBlock*, UintSet*> DelayedBlock;
|
||||
std::vector<DelayedBlock> delayedBlocks;
|
||||
for(auto & it : _blocks)
|
||||
{
|
||||
BasicBlock* block = &it.second;
|
||||
UintSet* parents = findParents(block->start);
|
||||
if(!block->function)
|
||||
{
|
||||
if(!parents || _functionStarts.count(block->start)) //no parents = function start
|
||||
{
|
||||
uint functionStart = block->start;
|
||||
block->function = functionStart;
|
||||
UintSet functionBlocks;
|
||||
functionBlocks.insert(functionStart);
|
||||
_functions[functionStart] = functionBlocks;
|
||||
}
|
||||
else //in function
|
||||
{
|
||||
uint function = findFunctionStart(block, parents);
|
||||
if(!function) //this happens with loops / unreferenced blocks sometimes
|
||||
delayedBlocks.push_back(DelayedBlock(block, parents));
|
||||
else
|
||||
block->function = function;
|
||||
}
|
||||
}
|
||||
else
|
||||
DebugBreak(); //this should not happen
|
||||
}
|
||||
int delayedCount = (int)delayedBlocks.size();
|
||||
dprintf("%u/%u delayed blocks...\n", delayedCount, _blocks.size());
|
||||
int resolved = 0;
|
||||
for(auto & delayedBlock : delayedBlocks)
|
||||
{
|
||||
BasicBlock* block = delayedBlock.first;
|
||||
UintSet* parents = delayedBlock.second;
|
||||
uint function = findFunctionStart(block, parents);
|
||||
if(!function)
|
||||
{
|
||||
continue;
|
||||
/*dprintf("unresolved block %s\n", blockToString(block).c_str());
|
||||
if(parents)
|
||||
{
|
||||
dprintf("parents:\n");
|
||||
for(auto parent : *parents)
|
||||
dprintf(" %s\n", blockToString(findBlock(parent)).c_str());
|
||||
}
|
||||
else
|
||||
dprintf("parents: null");
|
||||
dprintf("left: %s\n", blockToString(findBlock(block->left)).c_str());
|
||||
dprintf("right: %s\n", blockToString(findBlock(block->right)).c_str());
|
||||
return;*/
|
||||
}
|
||||
block->function = function;
|
||||
resolved++;
|
||||
}
|
||||
dprintf("%u/%u delayed blocks resolved (%u/%u still left, probably unreferenced functions)\n", resolved, delayedCount, delayedCount - resolved, _blocks.size());
|
||||
int unreferencedCount = 0;
|
||||
for(const auto & block : _blocks)
|
||||
{
|
||||
auto found = _functions.find(block.second.function);
|
||||
if(found == _functions.end()) //unreferenced block
|
||||
{
|
||||
unreferencedCount++;
|
||||
continue;
|
||||
}
|
||||
found->second.insert(block.second.start);
|
||||
}
|
||||
dprintf("%u/%u unreferenced blocks\n", unreferencedCount, _blocks.size());
|
||||
dprintf("%u functions found!\n", _functions.size());
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::FunctionRanges()
|
||||
{
|
||||
//iterate over the functions and then find the deepest block = function end
|
||||
for(const auto & function : _functions)
|
||||
{
|
||||
uint start = function.first;
|
||||
uint end = start;
|
||||
for(auto blockstart : function.second)
|
||||
{
|
||||
BasicBlock* block = this->findBlock(blockstart);
|
||||
if(!block)
|
||||
DebugBreak(); //this shouldn't happen
|
||||
if(block->end > end)
|
||||
end = block->end;
|
||||
}
|
||||
_functionRanges.push_back({ start, end });
|
||||
}
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::insertBlock(BasicBlock block)
|
||||
{
|
||||
if(_blocks.find(block.start) != _blocks.end())
|
||||
DebugBreak();
|
||||
_blocks[block.start] = block;
|
||||
}
|
||||
|
||||
ControlFlowAnalysis::BasicBlock* ControlFlowAnalysis::findBlock(uint start)
|
||||
{
|
||||
if(!start)
|
||||
return nullptr;
|
||||
auto found = _blocks.find(start);
|
||||
return found != _blocks.end() ? &found->second : nullptr;
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::insertParent(uint child, uint parent)
|
||||
{
|
||||
if(!child || !parent)
|
||||
return;
|
||||
auto found = _parentMap.find(child);
|
||||
if(found == _parentMap.end())
|
||||
{
|
||||
UintSet parents;
|
||||
parents.insert(parent);
|
||||
_parentMap[child] = parents;
|
||||
}
|
||||
else
|
||||
found->second.insert(parent);
|
||||
}
|
||||
|
||||
ControlFlowAnalysis::UintSet* ControlFlowAnalysis::findParents(uint child)
|
||||
{
|
||||
if(!child)
|
||||
return nullptr;
|
||||
auto found = _parentMap.find(child);
|
||||
return found != _parentMap.end() ? &found->second : nullptr;
|
||||
}
|
||||
|
||||
uint ControlFlowAnalysis::findFunctionStart(BasicBlock* block, ControlFlowAnalysis::UintSet* parents)
|
||||
{
|
||||
if(!block)
|
||||
return 0;
|
||||
if(block->function)
|
||||
return block->function;
|
||||
BasicBlock* left = findBlock(block->left);
|
||||
if(left && left->function)
|
||||
return left->function;
|
||||
BasicBlock* right = findBlock(block->right);
|
||||
if(right && right->function)
|
||||
return right->function;
|
||||
for(auto start : *parents)
|
||||
{
|
||||
BasicBlock* parent = findBlock(start);
|
||||
if(parent->function)
|
||||
return parent->function;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
String ControlFlowAnalysis::blockToString(BasicBlock* block)
|
||||
{
|
||||
if(!block)
|
||||
return String("null");
|
||||
return block->toString();
|
||||
}
|
||||
|
||||
uint ControlFlowAnalysis::GetReferenceOperand()
|
||||
{
|
||||
for(int i = 0; i < _cp.x86().op_count; i++)
|
||||
{
|
||||
const cs_x86_op & operand = _cp.x86().operands[i];
|
||||
if(operand.type == X86_OP_IMM)
|
||||
{
|
||||
uint dest = (uint)operand.imm;
|
||||
if(dest >= _base && dest < _base + _size)
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
void ControlFlowAnalysis::EnumerateFunctionRuntimeEntries64(std::function<bool(PRUNTIME_FUNCTION)> Callback)
|
||||
{
|
||||
if(!_functionInfoData)
|
||||
return;
|
||||
|
||||
// Get the table pointer and size
|
||||
auto functionTable = (PRUNTIME_FUNCTION)_functionInfoData;
|
||||
uint totalCount = (_functionInfoSize / sizeof(RUNTIME_FUNCTION));
|
||||
|
||||
// Enumerate each entry
|
||||
for(ULONG i = 0; i < totalCount; i++)
|
||||
{
|
||||
if(!Callback(&functionTable[i]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // _WIN64
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue