diff options
Diffstat (limited to 'core/processors.cc')
-rw-r--r-- | core/processors.cc | 2852 |
1 files changed, 2852 insertions, 0 deletions
diff --git a/core/processors.cc b/core/processors.cc new file mode 100644 index 0000000..e7ace85 --- /dev/null +++ b/core/processors.cc @@ -0,0 +1,2852 @@ +#include "../runtime/crypto.h" +#include "objects.h" +#include "osutils.h" +#include "streams.h" +#include "files.h" +#include "core.h" +#include "processors.h" +#include "lang.h" +#include <intrin.h> + +/** + * AddressRange + */ + +AddressRange::AddressRange(FunctionInfo *owner, uint64_t begin, uint64_t end, ICommand *begin_entry, ICommand *end_entry, ICommand *size_entry) + : IObject(), owner_(owner), begin_(begin), end_(end), original_begin_(0), original_end_(0), begin_entry_(begin_entry), end_entry_(end_entry), + size_entry_(size_entry), link_info_(NULL) +{ + +} + +AddressRange::AddressRange(FunctionInfo *owner, const AddressRange &src) + : IObject(), owner_(owner) +{ + begin_ = src.begin_; + end_ = src.end_; + begin_entry_ = src.begin_entry_; + end_entry_ = src.end_entry_; + size_entry_ = src.size_entry_; + original_begin_ = src.original_begin_; + original_end_ = src.original_end_; + link_info_ = src.link_info_; +} + +AddressRange::~AddressRange() +{ + if (owner_) + owner_->RemoveObject(this); +} + +AddressRange *AddressRange::Clone(FunctionInfo *owner) const +{ + AddressRange *range = new AddressRange(owner, *this); + return range; +} + +void AddressRange::Add(uint64_t address, size_t size) +{ + if (!begin_ || begin_ > address) + begin_ = address; + + if (!end_ || end_ < address + size) + end_ = address + size; + + for (size_t i = 0; i < link_list_.size(); i++) { + link_list_[i]->Add(address, size); + } +} + +void AddressRange::Prepare() +{ + original_begin_ = begin_; + original_end_ = end_; + begin_ = 0; + end_ = 0; +} + +void AddressRange::Rebase(uint64_t delta_base) +{ + if (begin_) + begin_ += delta_base; + if (end_) + end_ += delta_base; +} + +/** + * FunctionInfo + */ + +FunctionInfo::FunctionInfo() + : ObjectList<AddressRange>(), owner_(NULL), begin_(0), end_(0), base_type_(btValue), base_value_(0), prolog_size_(0), + entry_(NULL), frame_registr_(0), source_(NULL), data_entry_(NULL) +{ +} + +FunctionInfo::FunctionInfo(FunctionInfoList *owner, uint64_t begin, uint64_t end, AddressBaseType base_type, uint64_t base_value, size_t prolog_size, + uint8_t frame_registr, IRuntimeFunction *source, ICommand *entry) + : ObjectList<AddressRange>(), owner_(owner), begin_(begin), end_(end), base_type_(base_type), base_value_(base_value), prolog_size_(prolog_size), + entry_(entry), frame_registr_(frame_registr), source_(source), data_entry_(NULL) +{ + +} + +FunctionInfo::FunctionInfo(FunctionInfoList *owner, const FunctionInfo &src) + : ObjectList<AddressRange>(), owner_(owner) +{ + begin_ = src.begin_; + end_ = src.end_; + base_type_ = src.base_type_; + base_value_ = src.base_value_; + prolog_size_ = src.prolog_size_; + source_ = src.source_; + entry_ = src.entry_; + data_entry_ = src.data_entry_; + frame_registr_ = src.frame_registr_; + unwind_opcodes_ = src.unwind_opcodes_; + for (size_t i = 0; i < src.count(); i++) { + AddObject(src.item(i)->Clone(this)); + } +} + +FunctionInfo::~FunctionInfo() +{ + if (owner_) + owner_->RemoveObject(this); +} + +FunctionInfo *FunctionInfo::Clone(FunctionInfoList *owner) const +{ + FunctionInfo *info = new FunctionInfo(owner, *this); + return info; +} + +AddressRange *FunctionInfo::Add(uint64_t begin, uint64_t end, ICommand *begin_entry, ICommand *end_entry, ICommand *size_entry) +{ + AddressRange *range = new AddressRange(this, begin, end, begin_entry, end_entry, size_entry); + AddObject(range); + return range; +} + +AddressRange *FunctionInfo::GetRangeByAddress(uint64_t address) const +{ + for (size_t i = 0; i < count(); i++) { + AddressRange *range = item(i); + if (range->begin() <= address && range->end() > address) + return range; + } + return NULL; +} + +void FunctionInfo::Prepare() +{ + for (size_t i = 0; i < count(); i++) { + item(i)->Prepare(); + } +} + +void FunctionInfo::Compile() +{ + begin_ = 0; + end_ = 0; + for (size_t i = 0; i < count(); i++) { + AddressRange *range = item(i); + if (!range->begin()) + continue; + if (!begin_ || begin_ > range->begin()) + begin_ = range->begin(); + if (!end_ || end_ < range->end()) + end_ = range->end(); + } +} + +void FunctionInfo::WriteToFile(IArchitecture &file) +{ + if (begin_) { + std::vector<uint8_t> call_frame_instructions;; + for (size_t i = 0; i < unwind_opcodes_.size(); i++) { + ICommand *command = unwind_opcodes_[i]; + for (size_t j = 0; j < command->dump_size(); j++) { + call_frame_instructions.push_back(command->dump(j)); + } + } + file.runtime_function_list()->Add(0, begin_, end_, entry_ ? entry_->address() : 0, source_, call_frame_instructions); + } +} + +void FunctionInfo::Rebase(uint64_t delta_base) +{ + for (size_t i = 0; i < count(); i++) { + item(i)->Rebase(delta_base); + } + + if (begin_) + begin_ += delta_base; + if (end_) + end_ += delta_base; +} + +/** + * FunctionInfoList + */ + +FunctionInfoList::FunctionInfoList() + : ObjectList<FunctionInfo>() +{ + +} + +FunctionInfoList::FunctionInfoList(const FunctionInfoList &src) + : ObjectList<FunctionInfo>() +{ + for (size_t i = 0; i < src.count(); i++) { + AddObject(src.item(i)->Clone(this)); + } +} + +FunctionInfoList *FunctionInfoList::Clone() const +{ + FunctionInfoList *list = new FunctionInfoList(*this); + return list; +} + +FunctionInfo *FunctionInfoList::GetItemByAddress(uint64_t address) const +{ + for (size_t i = 0; i < count(); i++) { + FunctionInfo *info = item(i); + if (info->begin() <= address && info->end() > address) + return info; + } + return NULL; +} + +AddressRange *FunctionInfoList::GetRangeByAddress(uint64_t address) const +{ + FunctionInfo *info = GetItemByAddress(address); + return info ? info->GetRangeByAddress(address) : NULL; +} + +FunctionInfo *FunctionInfoList::Add(uint64_t begin, uint64_t end, AddressBaseType base_type, uint64_t base_value, size_t prolog_size, uint8_t frame_registr, IRuntimeFunction *source, ICommand *entry) +{ + FunctionInfo *info = new FunctionInfo(this, begin, end, base_type, base_value, prolog_size, frame_registr, source, entry); + AddObject(info); + return info; +}; + +void FunctionInfoList::Prepare() +{ + for (size_t i = 0; i < count(); i++) { + item(i)->Prepare(); + } +} + +void FunctionInfoList::Compile() +{ + for (size_t i = 0; i < count(); i++) { + item(i)->Compile(); + } +} + +void FunctionInfoList::WriteToFile(IArchitecture &file) +{ + for (size_t i = 0; i < count(); i++) { + item(i)->WriteToFile(file); + } +} + +void FunctionInfoList::Rebase(uint64_t delta_base) +{ + for (size_t i = 0; i < count(); i++) { + item(i)->Rebase(delta_base); + } +} + +/** + * BaseVMCommand + */ + +BaseVMCommand::BaseVMCommand(ICommand *owner) + : IVMCommand(), owner_(owner) +{ + +} + +BaseVMCommand::~BaseVMCommand() +{ + if (owner_) + owner_->RemoveObject(this); +} + +/** +* InternalLink +*/ + +InternalLink::InternalLink(InternalLinkList *owner, InternalLinkType type, IVMCommand *from_command, IObject *to_command) + : owner_(owner), type_(type), from_command_(from_command), to_command_(to_command) +{ + +} + +InternalLink::~InternalLink() +{ + if (owner_) + owner_->RemoveObject(this); +} + +/** +* InternalLinkList +*/ + +InternalLink *InternalLinkList::Add(InternalLinkType type, IVMCommand *from_command, IObject *to_command) +{ + InternalLink *link = new InternalLink(this, type, from_command, to_command); + AddObject(link); + return link; +} + +/** + * BaseCommand + */ + +BaseCommand::BaseCommand(IFunction *owner) + : ICommand(), owner_(owner), link_(NULL), block_(NULL), vm_address_(0), address_range_(NULL), + alignment_(0), options_(roNeedCompile) +{ + +} + +BaseCommand::BaseCommand(IFunction *owner, const std::string &value) + : ICommand(), owner_(owner), link_(NULL), block_(NULL), vm_address_(0), address_range_(NULL), + alignment_(0), options_(roNeedCompile) +{ + dump_.PushBuff(value.c_str(), value.size()); + dump_.PushByte(0); +} + +BaseCommand::BaseCommand(IFunction *owner, const os::unicode_string &value) + : ICommand(), owner_(owner), link_(NULL), block_(NULL), vm_address_(0), address_range_(NULL), + alignment_(0), options_(roNeedCompile) +{ + dump_.PushBuff(value.c_str(), value.size() * sizeof(os::unicode_char)); + dump_.PushWord(0); +} + +BaseCommand::BaseCommand(IFunction *owner, const Data &value) + : ICommand(), owner_(owner), link_(NULL), block_(NULL), vm_address_(0), address_range_(NULL), + alignment_(0), options_(roNeedCompile) +{ + dump_.PushBuff(value.data(), value.size()); +} + +BaseCommand::BaseCommand(IFunction *owner, const BaseCommand &src) + : ICommand(), owner_(owner), link_(NULL), block_(NULL) +{ + dump_ = src.dump_; + address_range_ = src.address_range_; + comment_ = src.comment_; + vm_address_ = src.vm_address_; + alignment_ = src.alignment_; + options_ = src.options_; +} + +BaseCommand::~BaseCommand() +{ + if (owner_) + owner_->RemoveObject(this); +} + +void BaseCommand::clear() +{ + dump_.clear(); +} + +void BaseCommand::Read(IArchitecture &file, size_t len) +{ + uint8_t *p = new uint8_t[len]; + file.Read(p, len); + dump_.PushBuff(p, len); + delete [] p; +} + +uint8_t BaseCommand::ReadByte(IArchitecture &file) +{ + uint8_t res = file.ReadByte(); + PushByte(res); + return res; +} + +uint16_t BaseCommand::ReadWord(IArchitecture &file) +{ + uint16_t res = file.ReadWord(); + PushWord(res); + return res; +} + +uint32_t BaseCommand::ReadDWord(IArchitecture &file) +{ + uint32_t res = file.ReadDWord(); + PushDWord(res); + return res; +} + +uint64_t BaseCommand::ReadQWord(IArchitecture &file) +{ + uint64_t res = file.ReadQWord(); + PushQWord(res); + return res; +} + +void BaseCommand::PushByte(uint8_t value) +{ + dump_.PushByte(value); +} + +void BaseCommand::PushWord(uint16_t value) +{ + dump_.PushWord(value); +} + +void BaseCommand::PushDWord(uint32_t value) +{ + dump_.PushDWord(value); +} + +void BaseCommand::PushQWord(uint64_t value) +{ + dump_.PushQWord(value); +} + +void BaseCommand::InsertByte(size_t position, uint8_t value) +{ + dump_.InsertByte(position, value); +} + +void BaseCommand::WriteDWord(size_t position, uint32_t value) +{ + dump_.WriteDWord(position, value); +} + +void BaseCommand::CompileInfo() +{ + if (address_range_) + address_range_->Add(address(), dump_size()); +} + +void BaseCommand::ReadFromBuffer(Buffer &buffer, IArchitecture &file) +{ + options_ = buffer.ReadDWord() & (roNeedCompile | roInverseFlag | roClearOriginalCode | roCreateNewBlock | roLockPrefix | roExternal | roBreaked | roVexPrefix); + alignment_ = buffer.ReadByte(); +} + +void BaseCommand::WriteToFile(IArchitecture &file) +{ + file.Write(dump_.data(), dump_.size()); +} + +CommandLink *BaseCommand::AddLink(int operand_index, LinkType type, uint64_t to_address) +{ + return owner_->link_list()->Add(this, operand_index, type, to_address); +} + +CommandLink *BaseCommand::AddLink(int operand_index, LinkType type, ICommand *to_command) +{ + return owner_->link_list()->Add(this, operand_index, type, to_command); +} + +size_t BaseCommand::vm_dump_size() const +{ + size_t res = 0; + for (size_t i = 0; i < count(); i++) { + res += item(i)->dump_size(); + } + + return res; +} + +void BaseCommand::set_vm_address(uint64_t address) +{ + vm_address_ = address; + bool backward_direction = (section_options() & rtBackwardDirection) != 0; + for (size_t i = 0; i < count(); i++) { + IVMCommand *vm_command = item(i); + vm_command->set_address(address); + if (backward_direction) { + address -= vm_command->dump_size(); + } else { + address += vm_command->dump_size(); + } + } +} + +void BaseCommand::set_dump(const void *buffer, size_t size) +{ + dump_.clear(); + dump_.PushBuff(buffer, size); +} + +bool BaseCommand::CompareDump(const uint8_t *buffer, size_t size) const +{ + if (dump_.size() != size) + return false; + + for (size_t i = 0; i < size; i++) { + if (dump_[i] != buffer[i]) + return false; + } + return true; +} + +std::string BaseCommand::dump_str() const +{ + std::string res; + + for (size_t i = 0; i < dump_size(); i++) { + res += string_format("%.2X", dump(i)); + } + + return res; +} + +uint64_t BaseCommand::dump_value(size_t pos, OperandSize size) const +{ + if (size > osQWord) + throw std::runtime_error("Invalid value size"); + + uint64_t res = 0; + memcpy(&res, &dump_[pos], OperandSizeToValue(size)); + return res; +} + +/** + * ValueCommand + */ + +ValueCommand::ValueCommand(ValueCryptor *owner, OperandSize size, CryptCommandType type, uint64_t value) + : IObject(), owner_(owner), type_(type), size_(size) +{ + switch (size_) { + case osByte: + value_ = static_cast<uint8_t>(value); + break; + case osWord: + value_ = static_cast<uint16_t>(value); + break; + case osDWord: + value_ = static_cast<uint32_t>(value); + break; + default: + value_ = value; + } +} + +ValueCommand::ValueCommand(ValueCryptor *owner, const ValueCommand &src) + : IObject(), owner_(owner) +{ + size_ = src.size_; + type_ = src.type_; + value_ = src.value_; +} + +ValueCommand *ValueCommand::Clone(ValueCryptor *owner) const +{ + ValueCommand *command = new ValueCommand(owner, *this); + return command; +} + +ValueCommand::~ValueCommand() +{ + if (owner_) + owner_->RemoveObject(this); +} + +CryptCommandType ValueCommand::type(bool is_decrypt) const +{ + CryptCommandType command = type_; + if (is_decrypt) { + switch (command) { + case ccAdd: + command = ccSub; + break; + case ccSub: + command = ccAdd; + break; + case ccInc: + command = ccDec; + break; + case ccDec: + command = ccInc; + break; + case ccRol: + command = ccRor; + break; + case ccRor: + command = ccRol; + break; + } + } + return command; +} + +uint64_t ValueCommand::Encrypt(uint64_t value) +{ + return Calc(value, false); +} + +uint64_t ValueCommand::Decrypt(uint64_t value) +{ + return Calc(value, true); +} + +uint64_t ValueCommand::Calc(uint64_t value, bool is_decrypt) +{ + switch (type(is_decrypt)) { + case ccAdd: case ccInc: + value += value_; + break; + case ccSub: case ccDec: + value -= value_; + break; + case ccXor: + value ^= value_; + break; + case ccNot: + value = ~value; + break; + case ccNeg: + value = 0 - value; + break; + case ccBswap: + switch (size_) { + case osWord: + value = __builtin_bswap16(static_cast<uint16_t>(value)); + break; + case osDWord: + value = __builtin_bswap32(static_cast<uint32_t>(value)); + break; + case osQWord: + value = __builtin_bswap64(value); + break; + } + break; + case ccRol: + switch (size_) { + case osByte: + value = _rotl8(static_cast<uint8_t>(value), static_cast<int>(value_)); + break; + case osWord: + value = _rotl16(static_cast<uint16_t>(value), static_cast<int>(value_)); + break; + case osDWord: + value = _rotl32(static_cast<uint32_t>(value), static_cast<int>(value_)); + break; + case osQWord: + value = _rotl64(value, static_cast<int>(value_)); + break; + } + break; + case ccRor: + switch (size_) { + case osByte: + value = _rotr8(static_cast<uint8_t>(value), static_cast<int>(value_)); + break; + case osWord: + value = _rotr16(static_cast<uint16_t>(value), static_cast<int>(value_)); + break; + case osDWord: + value = _rotr32(static_cast<uint32_t>(value), static_cast<int>(value_)); + break; + case osQWord: + value = _rotr64(value, static_cast<int>(value_)); + break; + } + break; + } + + return value; +} + +/** + * ValueCryptor + */ + +ValueCryptor::ValueCryptor() + : ObjectList<ValueCommand>(), size_(osByte) +{ + +} + +ValueCryptor::ValueCryptor(const ValueCryptor &src) + : ObjectList<ValueCommand>(src) +{ + for (size_t i = 0; i < src.count(); i++) { + AddObject(src.item(i)->Clone(this)); + } + size_ = src.size_; +} + +ValueCryptor *ValueCryptor::Clone() const +{ + ValueCryptor *cryptor = new ValueCryptor(*this); + return cryptor; +} + +uint64_t ValueCryptor::Encrypt(uint64_t value) +{ + size_t i; + for (i = 0; i < count(); i++) { + value = item(i)->Encrypt(value); + } + return value; +} + +uint64_t ValueCryptor::Decrypt(uint64_t value) +{ + size_t i; + for (i = count(); i > 0; i--) { + value = item(i - 1)->Decrypt(value); + } + return value; +} + +void ValueCryptor::Init(OperandSize size) +{ + clear(); + + size_ = size; + CryptCommandType last_command = ccUnknown; + for (;;) { + CryptCommandType command = static_cast<CryptCommandType>(rand() % ccUnknown); + if (command == last_command) + continue; + + uint64_t value = 0; + switch (command) { + case ccAdd: case ccSub: + if (last_command == ccAdd || last_command == ccSub || last_command == ccInc || last_command == ccDec) + continue; + value = DWordToInt64(rand32()); + break; + case ccInc: case ccDec: + if (last_command == ccAdd || last_command == ccSub || last_command == ccInc || last_command == ccDec) + continue; + value = 1; + break; + case ccXor: + value = DWordToInt64(rand32()); + break; + case ccBswap: + if (size_ == osByte || size_ == osWord) + continue; + break; + case ccRol: case ccRor: + if (last_command == ccRol || last_command == ccRor) + continue; + + value = rand() % BYTES_TO_BITS(OperandSizeToValue(size_)); + if (!value) + value = 1; + break; + } + last_command = command; + + Add(command, value); + + size_t c = count(); + if (c > 100 || (c > 3 && (rand() & 1))) + break; + } +} + +void ValueCryptor::Add(CryptCommandType command, uint64_t value) +{ + AddObject(new ValueCommand(this, size_, command, value)); +} + +/** + * OpcodeCryptor + */ + +OpcodeCryptor::OpcodeCryptor() + : ValueCryptor(), type_(ccUnknown) +{ + +} + +void OpcodeCryptor::Init(OperandSize size) +{ + //static CryptCommandType opcode_commands[] = {ccAdd, ccSub, ccXor}; + //type_ = opcode_commands[rand() % _countof(opcode_commands)]; + type_ = ccXor; + ValueCryptor::Init(size); +} + +uint64_t OpcodeCryptor::EncryptOpcode(uint64_t value1, uint64_t value2) +{ + return Calc(value1, value2, false); +} + +uint64_t OpcodeCryptor::DecryptOpcode(uint64_t value1, uint64_t value2) +{ + return Calc(value1, value2, true); +} + +uint64_t OpcodeCryptor::Calc(uint64_t value1, uint64_t value2, bool is_decrypt) +{ + CryptCommandType command = type_; + if (is_decrypt) { + switch (command) { + case ccAdd: + command = ccSub; + break; + case ccSub: + command = ccAdd; + break; + } + } + + switch (command) { + case ccAdd: + return value1 + value2; + case ccSub: + return value1 - value2; + case ccXor: + return value1 ^ value2; + } + + return 0; +} + +/** + * CommandLink + */ + +CommandLink::CommandLink(CommandLinkList *owner, ICommand *from_command, int operand_index, LinkType type, uint64_t to_address) + : IObject(), owner_(owner), parsed_(false), from_command_(from_command), parent_command_(NULL), to_command_(NULL), next_command_(NULL), + type_(type), to_address_(to_address), operand_index_(operand_index), sub_value_(0), cryptor_(NULL), base_function_info_(NULL), is_inverse_(false) +{ + if (from_command_) + from_command_->set_link(this); +} + +CommandLink::CommandLink(CommandLinkList *owner, ICommand *from_command, int operand_index, LinkType type, ICommand *to_command) + : IObject(), owner_(owner), parsed_(false), from_command_(from_command), parent_command_(NULL), to_command_(to_command), next_command_(NULL), + type_(type), to_address_(0), operand_index_(operand_index), sub_value_(0), cryptor_(NULL), base_function_info_(NULL), is_inverse_(false) +{ + if (from_command_) + from_command_->set_link(this); +} + +CommandLink::CommandLink(CommandLinkList *owner, const CommandLink &src) + : IObject(src), owner_(owner), from_command_(NULL), parent_command_(NULL), to_command_(NULL), next_command_(NULL) +{ + parsed_ = src.parsed_; + type_ = src.type_; + to_address_ = src.to_address_; + operand_index_ = src.operand_index_; + sub_value_ = src.sub_value_; + cryptor_ = src.cryptor_; + base_function_info_ = src.base_function_info_; + is_inverse_ = src.is_inverse_; +} + +CommandLink::~CommandLink() +{ + if (from_command_) + from_command_->set_link(NULL); + if (owner_) + owner_->RemoveObject(this); + delete cryptor_; +} + +CommandLink *CommandLink::Clone(CommandLinkList *owner) const +{ + CommandLink *link = new CommandLink(owner, *this); + return link; +} + +void CommandLink::set_from_command(ICommand *command) +{ + if (from_command_ == command) + return; + if (from_command_) + from_command_->set_link(NULL); + from_command_ = command; + if (from_command_) + from_command_->set_link(this); +} + +void CommandLink::Rebase(uint64_t delta_base) +{ + if (sub_value_) + sub_value_ += delta_base; + + if (to_address_) + to_address_ += delta_base; +} + +void CommandLink::set_cryptor(ValueCryptor *cryptor) +{ + if (cryptor) { + cryptor_ = cryptor->Clone(); + } else { + delete cryptor_; + cryptor_ = NULL; + } +} + +uint64_t CommandLink::Encrypt(uint64_t value) const +{ + uint64_t sub_value = base_function_info_ ? base_function_info_->begin() + base_function_info_->base_value() : sub_value_; + if (is_inverse_) + value = sub_value - value; + else + value = value - sub_value; + if (cryptor_) + value = cryptor_->Encrypt(value); + return value; +} + +/** + * CommandLinkList + */ + +CommandLinkList::CommandLinkList() + : ObjectList<CommandLink>() +{ + +} + +CommandLinkList::CommandLinkList(const CommandLinkList &src) + : ObjectList<CommandLink>(src) +{ + for (size_t i = 0; i < src.count(); i++) { + AddObject(src.item(i)->Clone(this)); + } +} + +CommandLinkList *CommandLinkList::Clone() const +{ + CommandLinkList *list = new CommandLinkList(*this); + return list; +} + +CommandLink *CommandLinkList::Add(ICommand *from_command, int operand_index, LinkType type, uint64_t to_address) +{ + CommandLink *link = new CommandLink(this, from_command, operand_index, type, to_address); + AddObject(link); + return link; +}; + +CommandLink *CommandLinkList::Add(ICommand *from_command, int operand_index, LinkType type, ICommand *to_command) +{ + CommandLink *link = new CommandLink(this, from_command, operand_index, type, to_command); + AddObject(link); + return link; +}; + +CommandLink *CommandLinkList::GetLinkByToAddress(LinkType type, uint64_t to_address) +{ + for (size_t i = 0; i < count(); i++) { + CommandLink *link = item(i); + if (link->to_address() == to_address && (type == ltNone || link->type() == type)) + return link; + } + + return NULL; +} + +void CommandLinkList::Rebase(uint64_t delta_base) +{ + for (size_t i = 0; i < count(); i++) { + item(i)->Rebase(delta_base); + } +} + +/** + * ExtCommand + */ + +ExtCommand::ExtCommand(ExtCommandList *owner, uint64_t address, ICommand *command, bool use_call) + : IObject(), owner_(owner), address_(address), command_(command), use_call_(use_call) +{ + +} + +ExtCommand::ExtCommand(ExtCommandList *owner, const ExtCommand &src) + : IObject(src), owner_(owner) +{ + address_ = src.address_; + command_ = src.command_; + use_call_ = src.use_call_; +} + +ExtCommand::~ExtCommand() +{ + if (owner_) + owner_->RemoveObject(this); +} + +ExtCommand *ExtCommand::Clone(ExtCommandList *owner) const +{ + ExtCommand *ext_command = new ExtCommand(owner, *this); + return ext_command; +} + +int ExtCommand::CompareWith(const ExtCommand &obj) const +{ + if (address() < obj.address()) + return -1; + if (address() > obj.address()) + return 1; + return 0; +} + +/** + * ExtCommandList + */ + +ExtCommandList::ExtCommandList(IFunction *owner) + : ObjectList<ExtCommand>(), owner_(owner) +{ + +} + +ExtCommandList::ExtCommandList(IFunction *owner, const ExtCommandList &src) + : ObjectList<ExtCommand>(src), owner_(owner) +{ + for (size_t i = 0; i < src.count(); i++) { + AddObject(src.item(i)->Clone(this)); + } +} + +ExtCommandList *ExtCommandList::Clone(IFunction *owner) const +{ + ExtCommandList *list = new ExtCommandList(owner, *this); + return list; +} + +ExtCommand *ExtCommandList::GetCommandByAddress(uint64_t address) const +{ + for (size_t i = 0; i < count(); i++) { + ExtCommand *ext_command = item(i); + if (ext_command->address() == address) + return ext_command; + } + + return NULL; +} + +ExtCommand *ExtCommandList::Add(uint64_t address, ICommand *command, bool use_call) +{ + ExtCommand *ext_command = new ExtCommand(this, address, command, use_call); + AddObject(ext_command); + return ext_command; +} + +ExtCommand *ExtCommandList::Add(uint64_t address) +{ + ExtCommand *ext_command = GetCommandByAddress(address); + if (ext_command) + return ext_command; + + if (owner_->address() == address || owner_->type() == otString) + return NULL; + + ICommand *command = owner_->GetCommandByAddress(address); + if (!command) + return NULL; + + return Add(address, command); +} + +void ExtCommandList::AddObject(ExtCommand *ext_command) +{ + ObjectList<ExtCommand>::AddObject(ext_command); + if (owner_) + owner_->Notify(mtAdded, ext_command); +} + +void ExtCommandList::RemoveObject(ExtCommand *ext_command) +{ + ObjectList<ExtCommand>::RemoveObject(ext_command); + if (owner_) + owner_->Notify(mtDeleted, ext_command); +} + +/** + * CommandBlock + */ + +CommandBlock::CommandBlock(CommandBlockList *owner, uint32_t type, size_t start_index) + : AddressableObject(), owner_(owner), type_(type), start_index_(start_index), end_index_(start_index), + virtual_machine_(NULL), sort_index_(0) +{ + registr_count_ = (function()->cpu_address_size() == osDWord) ? 16 : 24; + memset(registr_indexes_, 0xff, sizeof(registr_indexes_)); +} + +CommandBlock::CommandBlock(CommandBlockList *owner, const CommandBlock &src) + : AddressableObject(src), owner_(owner), virtual_machine_(NULL), sort_index_(0) +{ + type_ = src.type_; + start_index_ = src.start_index_; + end_index_ = src.end_index_; + registr_count_ = src.registr_count_; +} + +CommandBlock::~CommandBlock() +{ + if (owner_) + owner_->RemoveObject(this); +} + +CommandBlock *CommandBlock::Clone(CommandBlockList *owner) +{ + CommandBlock *block = new CommandBlock(owner, *this); + return block; +} + +IFunction *CommandBlock::function() const +{ + return owner_->owner(); +} + +void CommandBlock::Compile(MemoryManager &manager) +{ + size_t i, memory_size, alignment; + ICommand *command; + uint64_t address; + IFunction *func = function(); + + memory_size = 0; + if (type_ & mtExecutable) { + alignment = func->item(start_index_)->alignment(); + for (i = start_index_; i <= end_index_; i++) { + command = func->item(i); + memory_size += command->dump_size(); + } + } else { + alignment = 0; +#ifndef DEMO + ICommand *stor_command = NULL; + for (i = start_index_; i <= end_index_; i++) { + command = func->item(i); + if (command->is_data()) { + stor_command = NULL; + } else if (!stor_command || (command->section_options() & rtBeginSection)) { + stor_command = command; + } else if (command->section_options() & rtEndSection) { + stor_command->Merge(command); + stor_command = NULL; + } else if (!command->Merge(stor_command)) { + stor_command->Merge(command); + stor_command = command; + } + } +#endif + for (i = start_index_; i <= end_index_; i++) { + command = func->item(i); + for (size_t j = 0; j < command->count(); j++) { + command->item(j)->Compile(); + } + memory_size += command->vm_dump_size(); + } + } + + if (memory_size) { + address = (address_) ? address_ : manager.Alloc(memory_size, type_, 0, alignment); + if (type_ & mtExecutable) { + // native block + for (i = start_index_; i <= end_index_; i++) { + command = func->item(i); + command->set_address(address); + address += command->dump_size(); + } + } else { + // VM block + bool backward_direction = (func->item(start_index_)->section_options() & rtBackwardDirection) != 0; + if (backward_direction) + address += memory_size; + for (i = start_index_; i <= end_index_; i++) { + command = func->item(i); + command->set_vm_address(address); + if (backward_direction) { + address -= command->vm_dump_size(); + } else { + address += command->vm_dump_size(); + } + } + } + } +} + +void CommandBlock::CompileInfo() +{ + IFunction *func = function(); + for (size_t i = start_index_; i <= end_index_; i++) { + ICommand *command = func->item(i); + command->CompileInfo(); + } +} + +void CommandBlock::CompileLinks(const CompileContext &ctx) +{ + IFunction *func = function(); + for (size_t i = start_index_; i <= end_index_; i++) { + ICommand *command = func->item(i); + command->CompileLink(ctx); + } +} + +size_t CommandBlock::WriteToFile(IArchitecture &file) +{ + size_t i, j; + ICommand *command; + IVMCommand *vm_command; + uint32_t update_type; + + IFunction *func = function(); + + update_type = type_; + if (func->memory_type() != mtNone && (update_type & mtDiscardable) == 0) + update_type |= mtNotDiscardable; + + if (type_ & mtExecutable) { + // native block + for (i = start_index_; i <= end_index_; i++) { + file.StepProgress(); + command = func->item(i); + if (!file.AddressSeek(command->address())) + throw std::runtime_error("Invalid command address"); + + file.selected_segment()->include_write_type(update_type); + command->WriteToFile(file); + } + } else { + // VM block + if (func->item(start_index_)->section_options() & rtBackwardDirection) { + for (i = end_index_ + 1; i > start_index_ ; i--) { + file.StepProgress(); + command = func->item(i - 1); + if (!file.AddressSeek(command->vm_address() - command->vm_dump_size())) + throw std::runtime_error("Invalid command address"); + + for (j = command->count(); j > 0; j--) { + vm_command = command->item(j - 1); + file.selected_segment()->include_write_type(update_type); + vm_command->WriteToFile(file); + } + } + } else { + for (i = start_index_; i <= end_index_; i++) { + file.StepProgress(); + command = func->item(i); + if (!file.AddressSeek(command->vm_address())) + throw std::runtime_error("Invalid command address"); + + for (j = 0; j < command->count(); j++) { + vm_command = command->item(j); + file.selected_segment()->include_write_type(update_type); + vm_command->WriteToFile(file); + } + } + } + } + + return end_index_ - start_index_ + 1; +} + +uint8_t CommandBlock::GetRegistr(OperandSize size, uint8_t registr, bool is_write) +{ + uint8_t res; + OperandSize cpu_address_size = function()->cpu_address_size(); + if (registr & regExtended) { + res = (uint8_t)(registr_count_ + (registr & 0xf)); + } else if (registr == regEmpty && !is_write) { + res = (uint8_t)(rand() % registr_count_); + } else { + if(registr >= _countof(registr_indexes_)) + throw std::runtime_error("Runtime error at GetRegistr"); + + res = registr_indexes_[registr]; + if (res == 0xff || (is_write && size == cpu_address_size)) { + uint8_t empty_registr[_countof(registr_indexes_)]; + size_t empty_registr_count = 0; + for (size_t i = 0; i < registr_count_; i++) { + bool is_found = false; + for (size_t j = 0; j < regEmpty; j++) { + if (registr_indexes_[j] == i) { + is_found = true; + break; + } + } + if (!is_found) { + empty_registr[empty_registr_count] = (uint8_t)i; + empty_registr_count++; + } + } + + if (empty_registr_count) { + res = empty_registr[rand() % empty_registr_count]; + if (registr != regEmpty) + registr_indexes_[registr] = res; + } else if (res == 0xff) + throw std::runtime_error("Runtime error at GetRegistr"); + } + } + + return (uint8_t)(res * OperandSizeToValue(cpu_address_size)); +} + +/** + * CommandBlockList + */ + +CommandBlockList::CommandBlockList(IFunction *owner) + : ObjectList<CommandBlock>(), owner_(owner) +{ + +} + +CommandBlockList::CommandBlockList(IFunction *owner, const CommandBlockList &src) + : ObjectList<CommandBlock>(src), owner_(owner) +{ + for (size_t i = 0; i < src.count(); i++) { + AddObject(src.item(i)->Clone(this)); + } +} + +CommandBlockList *CommandBlockList::Clone(IFunction *owner) const +{ + CommandBlockList *list = new CommandBlockList(owner, *this); + return list; +} + +CommandBlock *CommandBlockList::Add(uint32_t memory_type, size_t start_index) +{ + CommandBlock *block = new CommandBlock(this, memory_type, start_index); + AddObject(block); + return block; +} + +void CommandBlockList::CompileBlocks(MemoryManager &manager) +{ + for (size_t i = 0; i < count(); i++) { + item(i)->Compile(manager); + } +} + +void CommandBlockList::CompileInfo() +{ + for (size_t i = 0; i < count(); i++) { + CommandBlock *block = item(i); + if (block->type() & mtExecutable) + block->CompileInfo(); + } +} + +void CommandBlockList::CompileLinks(const CompileContext &ctx) +{ + size_t i; + CommandBlock *block; + + for (i = 0; i < count(); i++) { + block = item(i); + if ((block->type() & mtExecutable) == 0) + continue; + + block->CompileLinks(ctx); + } + + for (i = 0; i < count(); i++) { + block = item(i); + if ((block->type() & mtExecutable) != 0) + continue; + + block->CompileLinks(ctx); + } +} + +size_t CommandBlockList::WriteToFile(IArchitecture &file) +{ + size_t res = 0; + for (size_t i = 0; i < count(); i++) { + CommandBlock *block = item(i); + res += block->WriteToFile(file); + } + return res; +} + +/** + * BaseFunction + */ + +BaseFunction::BaseFunction(IFunctionList *owner, const FunctionName &name, CompilationType compilation_type, uint32_t compilation_options, bool need_compile, Folder *folder) + : IFunction(), owner_(owner), name_(name), address_(0), break_address_(0), type_(otUnknown), cpu_address_size_(osDefault), compilation_type_(compilation_type), + compilation_options_(compilation_options), internal_lock_to_key_(false), default_compilation_type_(ctNone), need_compile_(need_compile), folder_(folder), memory_type_(mtNone), + tag_(0), entry_(NULL), entry_type_(etDefault), from_runtime_(false), parent_(NULL) +{ + link_list_ = new CommandLinkList(); + ext_command_list_ = new ExtCommandList(this); + block_list_ = new CommandBlockList(this); + function_info_list_ = new FunctionInfoList(); + range_list_ = new FunctionInfo(); +} + +BaseFunction::BaseFunction(IFunctionList *owner, OperandSize cpu_address_size, IFunction *parent) + : IFunction(), owner_(owner), address_(0), break_address_(0), type_(otCode), cpu_address_size_(cpu_address_size), compilation_type_(ctVirtualization), + compilation_options_(0), internal_lock_to_key_(false), default_compilation_type_(ctNone), need_compile_(true), folder_(NULL), memory_type_(mtReadable), tag_(0), entry_(NULL), + entry_type_(etDefault), from_runtime_(false), parent_(parent) +{ + link_list_ = new CommandLinkList(); + ext_command_list_ = new ExtCommandList(this); + block_list_ = new CommandBlockList(this); + function_info_list_ = new FunctionInfoList(); + range_list_ = new FunctionInfo(); +} + +BaseFunction::BaseFunction(IFunctionList *owner, const BaseFunction &src) + : IFunction(src), owner_(owner), folder_(NULL), parent_(NULL) +{ + size_t i, j; + + address_ = src.address_; + type_ = src.type_; + entry_ = NULL; + entry_type_ = src.entry_type_; + break_address_ = src.break_address_; + name_ = src.name_; + cpu_address_size_ = src.cpu_address_size_; + need_compile_ = src.need_compile_; + + compilation_type_ =src.compilation_type_; + compilation_options_ = src.compilation_options_; + internal_lock_to_key_ = src.internal_lock_to_key_; + default_compilation_type_ = src.default_compilation_type_; + memory_type_ = src.memory_type_; + tag_ = src.tag_; + from_runtime_ = src.from_runtime_; + + link_list_ = src.link_list_->Clone(); + ext_command_list_ = src.ext_command_list_->Clone(this); + block_list_ = src.block_list_->Clone(this); + function_info_list_ = src.function_info_list_->Clone(); + range_list_ = src.range_list_->Clone(NULL); + + for (i = 0; i < src.count(); i++) { + ICommand *command = src.item(i)->Clone(this); + AddObject(command); + + AddressRange *address_range = command->address_range(); + if (address_range) { + FunctionInfo *info = function_info_list_->item(src.function_info_list()->IndexOf(address_range->owner())); + command->set_address_range(info->item(address_range->owner()->IndexOf(address_range))); + } + } + + for (i = 0; i < range_list_->count(); i++) { + AddressRange *range = range_list_->item(i); + if (range->begin_entry()) + range->set_begin_entry(item(src.IndexOf(range->begin_entry()))); + if (range->end_entry()) + range->set_end_entry(item(src.IndexOf(range->end_entry()))); + if (range->size_entry()) + range->set_size_entry(item(src.IndexOf(range->size_entry()))); + } + + for (i = 0; i < function_info_list()->count(); i++) { + FunctionInfo *info = function_info_list()->item(i); + if (info->entry()) + info->set_entry(item(src.IndexOf(info->entry()))); + if (info->data_entry()) + info->set_data_entry(item(src.IndexOf(info->data_entry()))); + std::vector<ICommand *> unwind_opcodes = *info->unwind_opcodes(); + for (j = 0; j < unwind_opcodes.size(); j++) { + unwind_opcodes[j] = item(src.IndexOf(unwind_opcodes[j])); + } + info->set_unwind_opcodes(unwind_opcodes); + } + + if (src.entry_) + entry_ = item(src.IndexOf(src.entry_)); + + for (i = 0; i < src.count(); i++) { + CommandLink *src_link = src.item(i)->link(); + if (!src_link) + continue; + + CommandLink *link = link_list_->item(src.link_list()->IndexOf(src_link)); + link->set_from_command(item(i)); + if (src_link->parent_command()) + link->set_parent_command(item(src.IndexOf(src_link->parent_command()))); + if (src_link->base_function_info()) + link->set_base_function_info(function_info_list()->item(src.function_info_list()->IndexOf(src_link->base_function_info()))); + } + + for (i = 0; i < src.ext_command_list()->count(); i++) { + ExtCommand *ext_command = src.ext_command_list()->item(i); + if (!ext_command->command()) + continue; + + ext_command_list_->item(i)->set_command(item(src.IndexOf(ext_command->command()))); + } +} + +BaseFunction::~BaseFunction() +{ + if (owner_) + owner_->RemoveObject(this); + + delete link_list_; + delete ext_command_list_; + delete block_list_; + delete function_info_list_; + delete range_list_; +} + +void BaseFunction::AddObject(ICommand *command) +{ + ObjectList<ICommand>::AddObject(command); + if (command->address()) + map_[command->address()] = command; +} + +void BaseFunction::RemoveObject(ICommand *command) +{ + for (map_command_list_t::iterator it = map_.begin(); it != map_.end(); it++) { + if (it->second == command) { + map_.erase(it); + break; + } + } + IFunction::RemoveObject(command); +} + +ICommand *BaseFunction::GetCommandByLowerAddress(uint64_t address) const +{ + if (map_.empty()) + return NULL; + + map_command_list_t::const_iterator it = map_.upper_bound(address); + if (it != map_.begin()) + it--; + + return it->first > address ? NULL : it->second; +} + +ICommand *BaseFunction::GetCommandByUpperAddress(uint64_t address) const +{ + if (map_.empty()) + return NULL; + + map_command_list_t::const_iterator it = map_.upper_bound(address); + if (it == map_.end()) + return NULL; + + return it->second; +} + +ICommand *BaseFunction::GetCommandByNearAddress(uint64_t address) const +{ + ICommand *command = GetCommandByLowerAddress(address); + if (command && command->address() <= address && command->address() + command->original_dump_size() > address) + return command; + + return NULL; +} + +ICommand *BaseFunction::GetCommandByAddress(uint64_t address) const +{ + ICommand *command = GetCommandByLowerAddress(address); + if (command && command->address() == address) + return command; + + return NULL; +} + +uint64_t BaseFunction::GetNextAddress(IArchitecture &file) +{ + size_t i, j; + uint64_t max_address; + CommandLink *link; + LinkType link_type; + uint64_t to_address; + + for (i = 0; i < link_list_->count(); i++) { + link = link_list_->item(i); + link_type = link->type(); + if (link->parsed() || link_type == ltCall) + continue; + + to_address = link->to_address(); + if (link_type == ltNone || link_type == ltOffset || link_type == ltDelta || GetCommandByNearAddress(to_address)) { + link->set_parsed(true); + } else if (to_address < address_) { + link->set_parsed(true); + if (parent() && (link_type == ltJmp || link_type == ltJmpWithFlag)) { + IFunction *func = parent(); + while (func) { + if (to_address > func->address()) { + address_ = to_address; + return to_address; + } + func = func->parent(); + } + } + } else if (link_type == ltJmp) { + if (file.runtime_function_list()) { + IRuntimeFunction *runtime_function = file.runtime_function_list()->GetFunctionByAddress(link->from_command()->address()); + if (runtime_function && to_address >= runtime_function->begin() && to_address < runtime_function->end()) { + link->set_parsed(true); + return to_address; + } + } + } else { + link->set_parsed(true); + return to_address; + } + } + + max_address = address_; + for (i = 0; i < link_list_->count(); i++) { + link = link_list_->item(i); + + switch (link->type()) { + case ltSEHBlock: + case ltFinallyBlock: + case ltDualSEHBlock: + case ltFilterSEHBlock: + case ltJmpWithFlag: + if (link->to_address() > max_address) + max_address = link->to_address(); + break; + } + } + + for (i = 0; i < link_list_->count(); i++) { + link = link_list_->item(i); + if (link->parsed()) + continue; + + to_address = link->to_address(); + if (link->type() == ltJmp && to_address < max_address) { + link->set_parsed(true); + return to_address; + } + } + + for (i = 0; i < link_list_->count(); i++) { + link = link_list_->item(i); + if (link->parsed() || link->type() != ltJmp) + continue; + + // backward/forward jump + bool res = false; + to_address = link->to_address(); + if (parent()) { + res = true; + } else { + bool is_forward_aligned = to_address > link->from_command()->address() && (to_address & 0x0f) == 0; + IFunction *temp_func = CreateFunction(this); + temp_func->ReadFromFile(file, to_address); + for (j = 0; j < temp_func->count(); j++) { + ICommand *command = temp_func->item(j); + CommandLink *temp_link = command->link(); + if (temp_link && (temp_link->type() == ltJmp || temp_link->type() == ltJmpWithFlag)) { + if (GetCommandByAddress(temp_link->to_address()) || (is_forward_aligned && temp_link->to_address() == to_address) + || (temp_link->type() == ltJmpWithFlag && temp_link->to_address() == link->from_command()->next_address())) { + res = true; + break; + } + } + if (command->is_data() || command->is_end() || (command->options() & roBreaked)) + continue; + + if (command->next_address() == to_address) { + res = true; + break; + } + } + delete temp_func; + } + + if (res) { + link->set_parsed(true); + return to_address; + } + } + + return 0; +} + +void BaseFunction::clear() +{ + address_ = 0; + break_address_ = 0; + type_ = otUnknown; + entry_ = NULL; + entry_type_ = etDefault; + name_.clear(); + internal_lock_to_key_ = false; + default_compilation_type_ = ctNone; + + ClearItems(); +} + +void BaseFunction::ClearItems() +{ + map_.clear(); + link_list_->clear(); + ext_command_list_->clear(); + block_list_->clear(); + function_info_list_->clear(); + range_list_->clear(); + IFunction::clear(); +} + +size_t BaseFunction::ReadFromFile(IArchitecture &file, uint64_t address) +{ + MapFunction *map_function; + ICommand *command; + ISectionList *segment_list; + uint64_t def_parsed_address, parsed_address; + size_t i; + Reference *ref; + ReferenceList *reference_list; + + clear(); + + address_ = address; + cpu_address_size_ = file.cpu_address_size(); + memory_type_ = file.segment_list()->GetMemoryTypeByAddress(address); + + map_function = file.map_function_list()->GetFunctionByAddress(address); + if (map_function) { + default_compilation_type_ = map_function->compilation_type(); + internal_lock_to_key_ = map_function->lock_to_key(); + name_ = map_function->full_name(); + type_ = map_function->type(); + } else { + name_.clear(); + type_ = otCode; + } + + ParseBeginCommands(file); + + if (type_ == otString) { + if (map_function) { + ParseString(file, address_, static_cast<size_t>(map_function->end_address() - address_)); + reference_list = map_function->equal_address_list(); + for (i = 0; i < reference_list->count(); i++) { + ref = reference_list->item(i); + ParseString(file, ref->address(), static_cast<size_t>(ref->operand_address() - ref->address())); + } + } + } else { + segment_list = file.segment_list(); + def_parsed_address = -1; + parsed_address = def_parsed_address; + IRuntimeFunctionList *runtime_function_list = file.runtime_function_list(); + IRuntimeFunction *runtime_function = NULL; + + for (;;) { + command = NULL; + if (address < parsed_address && (segment_list->GetMemoryTypeByAddress(address) & mtExecutable)) { + if (runtime_function_list) { + if (runtime_function && (address < runtime_function->begin() || address >= runtime_function->end())) + runtime_function = NULL; + if (!runtime_function) + runtime_function = runtime_function_list->GetFunctionByAddress(address); + if (runtime_function) + runtime_function->Parse(file, *this); + } + command = ParseCommand(file, address); + } + + if (!command || command->is_end() || (command->options() & roBreaked) != 0) { + address = GetNextAddress(file); + if (!address) + break; + command = GetCommandByUpperAddress(address); + parsed_address = command ? command->address() : def_parsed_address; + } else { + address = command->next_address(); + } + } + } + + ParseEndCommands(file); + + Sort(); + + if (type_ != otString) + entry_ = GetCommandByAddress(address_); + + return count(); +} + +bool BaseFunction::FreeByManager(const CompileContext &ctx) +{ + MemoryManager *manager = ctx.manager; + uint64_t block_address = 0; + size_t block_size = 0; + uint32_t block_memory_type = mtNone; + ISectionList *segment_list = (from_runtime() ? ctx.runtime : ctx.file)->segment_list(); + + for (size_t i = 0; i < count(); i++) { + ICommand *command = item(i); + if (command->address() && (command->options() & roClearOriginalCode) && !is_breaked_address(command->address())) { + for (size_t j = 0; j < command->original_dump_size(); j++) { + MemoryRegion *region = manager->GetRegionByAddress(command->address() + j); + if (region) { + IFunction *func = region->parent_function(); + uint64_t func_address; + std::string func_name; + if (func) { + func_name = func->name(); + func_address = func->address(); + } else { + func_name.clear(); + func_address = region->address(); + } + if (func_name.empty()) + func_name = string_format("%.8llX", func_address); + ctx.file->Notify(mtError, command, string_format(language[lsAddressUsedByFunction].c_str(), func_name.c_str())); + return false; + } + } + + uint32_t command_memory_type = segment_list->GetMemoryTypeByAddress(command->address()); + if (block_address && ((block_address + block_size) != command->address() || block_memory_type != command_memory_type)) { + if (block_size) + manager->Add(block_address, block_size, block_memory_type, this); + block_address = 0; + block_size = 0; + block_memory_type = mtNone; + } + if (!block_address) { + block_address = command->address(); + block_memory_type = command_memory_type; + } + block_size += command->original_dump_size(); + } + } + + if (block_size) + manager->Add(block_address, block_size, block_memory_type, this); + + return true; +} + +bool BaseFunction::PrepareExtCommands(const CompileContext &ctx) +{ + return true; +} + +bool BaseFunction::PrepareLinks(const CompileContext &ctx) +{ + IFunctionList *function_list = ctx.file->function_list(); + for (size_t i = 0; i < link_list_->count(); i++) { + CommandLink *link = link_list_->item(i); + if (link->type() == ltNone) + continue; + + if (link->to_address()) { + ICommand *command = function_list->GetCommandByAddress(link->to_address(), true); + if (is_breaked_address(link->from_command()->address())) { + if (command && command->owner()->address() != link->to_address() && !command->owner()->ext_command_list()->GetCommandByAddress(link->to_address())) + ctx.file->Notify(mtWarning, link->from_command(), string_format(language[lsJumpToInternalAddress].c_str(), link->to_address())); + continue; + } else { + if (!command && function_list->GetCommandByNearAddress(link->to_address(), true)) { + ctx.file->Notify(mtError, link->from_command(), language[lsJumpToCommandPart]); + return false; + } + link->set_to_command(command && (command->options() & roNeedCompile) ? command : NULL); + } + } + + link->from_command()->PrepareLink(ctx); + } + + return true; +} + +bool BaseFunction::Init(const CompileContext &/*ctx*/) +{ + ICommand *command; + size_t i; + + if (function_info_list()->count()) { + std::set<uint64_t> address_list; + FunctionInfo *info; + AddressRange *range; + for (i = 0; i < function_info_list_->count(); i++) { + info = function_info_list_->item(i); + address_list.insert(info->begin()); + address_list.insert(info->end()); + } + for (i = 0; i < range_list_->count(); i++) { + range = range_list_->item(i); + info = function_info_list_->GetItemByAddress(range->begin()); + if (!info) + continue; + + range->set_link_info(info); + if (!range->end()) + range->set_end(info->end()); + address_list.insert(range->begin()); + address_list.insert(range->end()); + } + + uint64_t begin = 0; + for (std::set<uint64_t>::const_iterator it = address_list.begin(); it != address_list.end(); it++) { + if (begin) { + uint64_t end = *it; + info = function_info_list_->GetItemByAddress(begin); + if (info) { + AddressRange *dest = info->Add(begin, end, NULL, NULL, NULL); + for (i = 0; i < range_list_->count(); i++) { + range = range_list_->item(i); + if (range->begin() <= begin && range->end() > begin) + dest->AddLink(range); + } + } + } + begin = *it; + } + + for (i = 0; i < count(); i++) { + command = item(i); + if (command->address_range()) + continue; + + command->set_address_range(function_info_list_->GetRangeByAddress(command->address())); + } + } + + return true; +} + +bool BaseFunction::Prepare(const CompileContext &ctx) +{ + if (!FreeByManager(ctx)) + return false; + + range_list()->Prepare(); + function_info_list()->Prepare(); + + return true; +} + +bool BaseFunction::Compile(const CompileContext &ctx) +{ + return true; +} + +void BaseFunction::AfterCompile(const CompileContext &ctx) +{ + +} + +void BaseFunction::CompileInfo(const CompileContext &ctx) +{ + block_list()->CompileInfo(); + function_info_list()->Compile(); +} + +void BaseFunction::CompileLinks(const CompileContext &ctx) +{ + block_list()->CompileLinks(ctx); +} + +size_t BaseFunction::WriteToFile(IArchitecture &file) +{ + size_t res = block_list_->WriteToFile(file); + function_info_list_->WriteToFile(file); + return res; +} + +void BaseFunction::ReadFromBuffer(Buffer &buffer, IArchitecture &file) +{ + size_t i, j, c; + ICommand *command; + uint64_t add_address = file.image_base(); + + tag_ = buffer.ReadByte(); + uint8_t b = buffer.ReadByte(); + + switch (b & 0x30) { + case 0x10: + entry_type_ = etNone; + break; + case 0x20: + entry_type_ = etRandomAddress; + break; + } + + compilation_type_ =static_cast<CompilationType>(b & 0xf); + type_ = static_cast<ObjectType>(buffer.ReadByte()); + cpu_address_size_ = static_cast<OperandSize>(buffer.ReadByte()); + address_ = buffer.ReadDWord() + add_address; + + c = buffer.ReadDWord(); + for (i = 0; i < c; i++) { + command = CreateCommand(); + command->ReadFromBuffer(buffer, file); + AddObject(command); + } + + c = buffer.ReadDWord(); + for (i = 0; i < c; i++) { + uint32_t begin = buffer.ReadDWord(); + uint32_t end = buffer.ReadDWord(); + AddressBaseType base_type = static_cast<AddressBaseType>(buffer.ReadByte()); + uint32_t base_value = (base_type == btValue) ? buffer.ReadDWord() : 0; + size_t prolog_size = buffer.ReadDWord(); + uint8_t frame_registr = buffer.ReadByte(); + uint32_t index = buffer.ReadDWord(); + uint32_t data_index = buffer.ReadDWord(); + std::vector<ICommand *> unwind_opcodes; + unwind_opcodes.resize(buffer.ReadDWord()); + for (j = 0; j < unwind_opcodes.size(); j++) { + unwind_opcodes[j] = item(buffer.ReadDWord() - 1); + } + FunctionInfo *info = function_info_list()->Add(begin + add_address, end + add_address, base_type, base_value, prolog_size, frame_registr, + file.runtime_function_list()->GetFunctionByAddress(begin + add_address), (index != 0) ? item(index - 1) : NULL); + if (data_index != 0) + info->set_data_entry(item(data_index - 1)); + info->set_unwind_opcodes(unwind_opcodes); + } + + c = buffer.ReadDWord(); + for (i = 0; i < c; i++) { + uint32_t begin = buffer.ReadDWord(); + uint32_t end = buffer.ReadDWord(); + uint32_t begin_index = buffer.ReadDWord(); + uint32_t end_index = buffer.ReadDWord(); + uint32_t size_index = buffer.ReadDWord(); + range_list_->Add(begin + add_address, end + add_address, + begin_index != 0 ? item(begin_index - 1) : NULL, + end_index != 0 ? item(end_index - 1) : NULL, + size_index != 0 ? item(size_index - 1) : NULL); + } + + c = buffer.ReadDWord(); + for (i = 0; i < c; i++) { + uint32_t dw = buffer.ReadDWord(); + LinkType link_type = static_cast<LinkType>(buffer.ReadByte()); + int operand_index = static_cast<int8_t>(buffer.ReadByte()); + uint8_t opt = buffer.ReadByte(); + uint64_t qw = (opt & 1) ? buffer.ReadDWord() + add_address : 0; + CommandLink *link = item(dw - 1)->AddLink(operand_index, link_type, qw); + if (opt & 2) + link->set_sub_value(buffer.ReadDWord() + add_address); + if (opt & 4) { + dw = buffer.ReadDWord(); + if (dw != 0) + link->set_parent_command(item(dw - 1)); + } + if (opt & 8) { + dw = buffer.ReadDWord(); + if (dw != 0) + link->set_base_function_info(function_info_list()->item(dw - 1)); + } + } + + memory_type_ = owner_->owner()->segment_list()->GetMemoryTypeByAddress(address_); + if (type_ != otString) + entry_ = GetCommandByAddress(address_); +} + +CommandBlock *BaseFunction::AddBlock(size_t start_index, bool is_executable) +{ + return block_list_->Add((memory_type_ & (mtDiscardable | mtNotPaged)) | (is_executable ? mtExecutable : mtReadable), start_index); +} + +uint8_t *version_watermark = NULL; +uint8_t *owner_watermark = NULL; + +void BaseFunction::AddWatermark(Watermark *watermark, int copy_count) +{ + Watermark secure_watermark(NULL); + std::string value; + uint8_t *internal_watermarks[] = {version_watermark, owner_watermark}; + + for (size_t k = 0; k < 1 + _countof(internal_watermarks); k++) { + if (k == 0) { + if (!watermark) + continue; + } else { + uint8_t *ptr = internal_watermarks[k - 1]; + if (!ptr) + continue; + + uint32_t key = *reinterpret_cast<uint32_t *>(ptr); + uint16_t len = *reinterpret_cast<uint16_t *>(ptr + 4); + value.resize(len); + for (size_t i = 0; i < value.size(); i++) { + value[i] = ptr[6 + i] ^ static_cast<uint8_t>(_rotl32(key, (int)i) + i); + } + secure_watermark.set_value(value); + watermark = &secure_watermark; + } + + for (int i = 0; i < copy_count; i++) { + watermark->Compile(); + ICommand *command = AddCommand(Data(watermark->dump())); + command->include_option(roCreateNewBlock); + } + } +} + +void BaseFunction::Rebase(uint64_t delta_base) +{ + map_.clear(); + for (size_t i = 0; i < count(); i++) { + ICommand *command = item(i); + command->Rebase(delta_base); + if (command->address()) + map_[command->address()] = command; + } + link_list_->Rebase(delta_base); + range_list_->Rebase(delta_base); + function_info_list_->Rebase(delta_base); + + if (address_) + address_ += delta_base; +} + +void BaseFunction::Notify(MessageType type, IObject *sender, const std::string &message) const +{ + if (owner_) + owner_->Notify(type, sender, message); +} + +void BaseFunction::set_compilation_type(CompilationType compilation_type) +{ + if (default_compilation_type_ != ctNone) + return; + + if (compilation_type_ != compilation_type) { + compilation_type_ = compilation_type; + Notify(mtChanged, this); + } +} + +void BaseFunction::set_compilation_options(uint32_t compilation_options) +{ + if (compilation_options_ != compilation_options) { + compilation_options_ = compilation_options; + Notify(mtChanged, this); + } +} + +void BaseFunction::set_need_compile(bool need_compile) +{ + if (need_compile_ != need_compile) { + need_compile_ = need_compile; + Notify(mtChanged, this); + } +} + +void BaseFunction::set_folder(Folder *folder) +{ + if (folder_ != folder) { + folder_ = folder; + Notify(mtChanged, this); + } +} + +void BaseFunction::set_break_address(uint64_t break_address) +{ + if (type_ == otString) + return; + + if (break_address_ != break_address) { + break_address_ = break_address; + Notify(mtChanged, this); + } +} + +std::string BaseFunction::display_address(const std::string &arch_name) const +{ + std::string res; + if (type() != otUnknown) + res.append(arch_name).append(DisplayValue(cpu_address_size(), address())); + if (type() == otString) { + for (size_t i = 1; i < count(); i++) { + res.append(", ").append(arch_name).append(DisplayValue(cpu_address_size(), item(i)->address())); + } + } + + return res; +} + +Data BaseFunction::hash() const +{ + Data res; + bool is_unknown = (type() == otUnknown); + res.PushBuff(name().c_str(), name().size() + 1); + res.PushByte(need_compile()); + res.PushByte(is_unknown); + res.PushDWord(is_unknown ? tag() : -1); + res.PushByte(compilation_type()); + res.PushDWord(compilation_options()); + res.PushDWord(break_address() ? static_cast<uint32_t>(break_address() - address()) : 0); + res.PushDWord(static_cast<uint32_t>(ext_command_list()->count())); + for (size_t i = 0; i < ext_command_list()->count(); i++) { + res.PushDWord(static_cast<uint32_t>(ext_command_list()->item(i)->address() - address())); + } + return res; +} + +#ifdef CHECKED +bool BaseFunction::check_hash() const +{ + for (size_t i = 0; i < count(); i++) { + if (!item(i)->check_hash()) + return false; + } + return true; +} +#endif + +IVirtualMachine *BaseFunction::virtual_machine(IVirtualMachineList *virtual_machine_list, ICommand *command) const +{ + if (virtual_machine_list) { + std::vector<IVirtualMachine *> list; + for (size_t i = 0; i < virtual_machine_list->count(); i++) { + IVirtualMachine *virtual_machine = virtual_machine_list->item(i); + if (virtual_machine->processor()->cpu_address_size() == cpu_address_size()) + list.push_back(virtual_machine); + } + return list[rand() % list.size()]; + } + + return NULL; +} + +/** + * Signature + */ + +Signature::Signature(SignatureList *owner, const std::string &value, uint32_t tag) + : IObject(), owner_(owner), value_(value), tag_(tag) +{ + Init(); +} + +Signature::~Signature() +{ + if (owner_) + owner_->RemoveObject(this); +} + +void Signature::Init() +{ + size_t i, p; + uint8_t m, b; + char c; + + dump_.clear(); + mask_.clear(); + + if (value_.size() == 0) + return; + + for (i = 0; i < value_.size(); i++) { + p = i / 2; + if (p >= dump_.size()) { + dump_.push_back(0); + mask_.push_back(0); + } + + m = 0xff; + c = value_[i]; + if ((c >= '0') && (c <= '9')) { + b = c - '0'; + } else if ((c >= 'A') && (c <= 'F')) { + b = c - 'A' + 0x0a; + } else if ((c >= 'a') && (c <= 'f')) { + b = c - 'a' + 0x0a; + } else { + m = 0; + b = 0; + } + + if ((i & 1) == 0) { + dump_[p] = (dump_[p] & 0x0f) | (b << 4); + mask_[p] = (mask_[p] & 0x0f) | (m << 4); + } else { + dump_[p] = (dump_[p] & 0xf0) | (b & 0x0f); + mask_[p] = (mask_[p] & 0xf0) | (m & 0x0f); + } + } +} + +bool Signature::SearchByte(uint8_t value) +{ + int i; + size_t p; + bool res; + + if (dump_.size() == 0) + return false; + + res = false; + for (i = (int)pos_.size() - 1; i >= -1; i--) { + p = (i == -1) ? 0 : pos_[i]; + if ((dump_[p] & mask_[p]) == (value & mask_[p])) { + p++; + if (p == dump_.size()) { + res = true; + if (i > -1) + pos_.erase(pos_.begin() + i); + } else if (i == -1) { + pos_.push_back(p); + } else { + pos_[i] = p; + } + } else if (i > -1) { + pos_.erase(pos_.begin() + i); + } + } + + return res; +} + +/** + * SignatureList + */ + +SignatureList::SignatureList() + : ObjectList<Signature>() +{ + +} + +Signature *SignatureList::Add(const std::string &value, uint32_t tag) +{ + Signature *sign = new Signature(this, value, tag); + AddObject(sign); + return sign; +} + +void SignatureList::InitSearch() +{ + for (size_t i = 0; i < count(); i++) { + item(i)->InitSearch(); + } +} + +/** + * BaseFunctionList + */ + +BaseFunctionList::BaseFunctionList(IArchitecture *owner) + : IFunctionList(), owner_(owner) +{ + +} + +BaseFunctionList::BaseFunctionList(IArchitecture *owner, const BaseFunctionList &src) + : IFunctionList(src), owner_(owner) +{ + size_t i; + std::vector<Folder*> src_folders, folders; + Folder *folder; + + for (i = 0; i < src.count(); i++) { + AddObject(src.item(i)->Clone(this)); + } + + src_folders = src.owner()->owner()->folder_list()->GetFolderList(); + FolderList *folder_list = NULL; + if (owner && owner->owner()) folder_list = owner->owner()->folder_list(); + if (folder_list) folders = folder_list->GetFolderList(); + for (i = 0; i < src.count(); i++) { + std::vector<Folder*>::const_iterator it = std::find(src_folders.begin(), src_folders.end(), src.item(i)->folder()); + folder = (it == src_folders.end()) ? folder_list : *it; + if (folder) item(i)->set_folder(folder); + } +} + +IFunction *BaseFunctionList::AddUnknown(const std::string &name, CompilationType compilation_type, uint32_t compilation_options, bool need_compile, Folder *folder) +{ + IFunction *func = GetUnknownByName(name); + if (!func) { + func = Add(name, compilation_type, compilation_options, need_compile, folder); + if (func) + Notify(mtAdded, func); + } else { + func->set_compilation_type(compilation_type); + func->set_compilation_options(compilation_options); + func->set_need_compile(need_compile); + func->set_folder(folder); + } + return func; +}; + +IFunction *BaseFunctionList::AddByAddress(uint64_t address, CompilationType compilation_type, uint32_t compilation_options, bool need_compile, Folder *folder) +{ + IFunction *func = GetFunctionByAddress(address); + if (!func) { + // check address + uint32_t memory_type = owner_->segment_list()->GetMemoryTypeByAddress(address); + if ((memory_type & mtExecutable) == 0) { + MapFunction *map_function = owner_->map_function_list()->GetFunctionByAddress(address); + if (!map_function || map_function->type() != otString) + return NULL; + } + + func = Add("", compilation_type, compilation_options, need_compile, folder); + if (func) { + func->ReadFromFile(*owner_, address); + Notify(mtAdded, func); + } + } else { + func->set_compilation_type(compilation_type); + func->set_compilation_options(compilation_options); + func->set_need_compile(need_compile); + func->set_folder(folder); + } + return func; +}; + +IFunction *BaseFunctionList::GetFunctionByAddress(uint64_t address) const +{ + for (size_t i = 0; i < count(); i++) { + IFunction *func = item(i); + if (func->address() == address) + return func; + } + + return NULL; +} + +IFunction *BaseFunctionList::GetFunctionByName(const std::string &name) const +{ + for (size_t i = 0; i < count(); i++) { + IFunction *func = item(i); + if (func->name().compare(name) == 0 && func->type() != otUnknown) + return func; + } + + return NULL; +} + +IFunction *BaseFunctionList::GetUnknownByName(const std::string &name) const +{ + for (size_t i = 0; i < count(); i++) { + IFunction *func = item(i); + if (func->name().compare(name) == 0 && func->type() == otUnknown) + return func; + } + + return NULL; +} + +ICommand *BaseFunctionList::GetCommandByAddress(uint64_t address, bool need_compile) const +{ + for (size_t i = 0; i < count(); i++) { + IFunction *func = item(i); + if (need_compile && !func->need_compile()) + continue; + + ICommand *command = func->GetCommandByAddress(address); + if (command) + return (need_compile && func->is_breaked_address(command->address())) ? NULL : command; + } + + return NULL; +} + +ICommand *BaseFunctionList::GetCommandByNearAddress(uint64_t address, bool need_compile) const +{ + for (size_t i = 0; i < count(); i++) { + IFunction *func = item(i); + if (need_compile && !func->need_compile()) + continue; + + ICommand *command = func->GetCommandByNearAddress(address); + if (command) + return (need_compile && func->is_breaked_address(command->address())) ? NULL : command; + } + + return NULL; +} + +bool BaseFunctionList::Prepare(const CompileContext &ctx) +{ + size_t i, j; + + bool need_machines = (ctx.runtime != NULL); + uint32_t memory_type = mtReadable | mtDiscardable; + for (i = count(); i > 0; i--) { + IFunction *func = item(i - 1); + if (!func->need_compile()) + delete func; + else if (func->type() != otUnknown && func->compilation_type() != ctMutation) { + if ((func->memory_type() & mtDiscardable) == 0) + memory_type &= ~mtDiscardable; + if (func->memory_type() & mtNotPaged) + memory_type |= mtNotPaged; + need_machines = true; + } + } + + if (need_machines) { + IVirtualMachineList *virtual_machine_list = ctx.file->virtual_machine_list(); + virtual_machine_list->Prepare(ctx); + std::vector<IFunction *> processor_list = ctx.file->function_list()->processor_list(); + for (i = 0; i < processor_list.size(); i++) { + processor_list[i]->set_memory_type(memory_type); + } + } + + for (j = 0; j < 4; j++) { + for (i = 0; i < count(); i++) { + IFunction *func = item(i); + switch (j) { + case 0: + if (func->type() == otUnknown) { + ctx.file->Notify(mtWarning, func, string_format(language[lsFunctionNotFound].c_str(), func->name().c_str())); + continue; + } + if (!func->Init(ctx)) + return false; + break; + case 1: + if (!func->Prepare(ctx)) + return false; + break; + case 2: + if (!func->PrepareExtCommands(ctx)) + return false; + break; + case 3: + if (!func->PrepareLinks(ctx)) + return false; + break; + } + } + } + + return true; +} + +bool BaseFunctionList::Compile(const CompileContext &ctx) +{ + size_t i, j, k; + IFunction *func; + CommandBlock *block; + std::vector<CommandBlock *> block_list; + + j = 0; + auto jjj = count(); + for (i = 0; i < count(); i++) { + func = item(i); + j += func->count(); + if (func->compilation_type() == ctUltra) + j += func->count(); + } + ctx.file->StartProgress(string_format("%s...", language[lsCompiling].c_str()), j); + + for (i = 0; i < count(); i++) { + func = item(i); + if (!func->Compile(ctx)) + return false; + } + for (i = 0; i < count(); i++) { + func = item(i); + func->AfterCompile(ctx); + if (!func->need_compile()) + continue; + + for (j = 0; j < func->block_list()->count(); j++) { + block_list.push_back(func->block_list()->item(j)); + } + } + + for (i = 0; i < block_list.size(); i++) { + std::swap(block_list[i], block_list[rand() % block_list.size()]); + } + + if (ctx.file->runtime_function_list() && ctx.file->runtime_function_list()->count()) { + // sort blocks by address range + for (i = 0; i < block_list.size(); i++) { + block_list[i]->set_sort_index(i); + } + std::sort(block_list.begin(), block_list.end(), CommandBlockListCompareHelper()); + // add prolog blocks + std::set<FunctionInfo *> function_info_list; + Data data; + for (i = 0; i < block_list.size(); i++) { + block = block_list[i]; + if ((block->type() & mtExecutable) == 0) + continue; + + AddressRange *address_range = block->function()->item(block->start_index())->address_range(); + if (!address_range) + continue; + + FunctionInfo *function_info = address_range->owner(); + if (!function_info->prolog_size() || function_info_list.find(function_info) != function_info_list.end()) + continue; + + func = block->function(); + size_t prolog_size = 0; + for (j = block->start_index(); j <= block->end_index(); j++) { + prolog_size += func->item(j)->dump_size(); + } + + if (prolog_size < function_info->prolog_size()) { + size_t size = function_info->prolog_size() - prolog_size; + data.resize(size); + for (k = 0; k < data.size(); k++) { + data[k] = rand(); + } + CommandBlock *new_block = func->AddBlock(func->count(), true); + ICommand *command = func->AddCommand(data); + command->set_block(new_block); + command->set_address_range(address_range); + + block_list.insert(block_list.begin() + i + 1, new_block); + } + + function_info_list.insert(function_info); + } + } + + for (i = 0; i < block_list.size(); i++) { + block_list[i]->Compile(*ctx.manager); + } + + CompileInfo(ctx); + CompileLinks(ctx); + + ctx.file->EndProgress(); + + return true; +} + +void BaseFunctionList::CompileInfo(const CompileContext &ctx) +{ + for (size_t i = 0; i < count(); i++) { + item(i)->CompileInfo(ctx); + } +} + +void BaseFunctionList::CompileLinks(const CompileContext &ctx) +{ + for (size_t i = 0; i < count(); i++) { + IFunction *func = item(i); + if (func->compilation_type() != ctMutation) + continue; + + func->CompileLinks(ctx); + } + + for (size_t i = 0; i < count(); i++) { + IFunction *func = item(i); + if (func->compilation_type() == ctMutation) + continue; + + func->CompileLinks(ctx); + } +} + +void BaseFunctionList::ReadFromBuffer(Buffer &buffer, IArchitecture &file) +{ + size_t c = buffer.ReadDWord(); + for (size_t i = 0; i < c; i++) { + IFunction *func = CreateFunction(); + AddObject(func); + + func->ReadFromBuffer(buffer, file); + } +} + +void BaseFunctionList::Rebase(uint64_t delta_base) +{ + for (size_t i = 0; i < count(); i++) { + item(i)->Rebase(delta_base); + } +} + +void BaseFunctionList::RemoveObject(IFunction *func) +{ + Notify(mtDeleted, func); + IFunctionList::RemoveObject(func); +} + +void BaseFunctionList::Notify(MessageType type, IObject *sender, const std::string &message) const +{ + if (owner_) + owner_->Notify(type, sender, message); +} + +std::vector<IFunction *> BaseFunctionList::processor_list() const +{ + std::vector<IFunction *> res; + for (size_t i = 0; i < count(); i++) { + IFunction *func = item(i); + if (func->tag() == ftProcessor) + res.push_back(func); + } + return res; +} + +#ifdef CHECKED +bool BaseFunctionList::check_hash() const +{ + for (size_t i = 0; i < count(); i++) { + if (!item(i)->check_hash()) + return false; + } + return true; +} +#endif + +/** + * CommandInfo + */ + +CommandInfo::CommandInfo(CommandInfoList *owner, AccessType type, uint8_t value, OperandType operand_type, OperandSize size) + : IObject(), owner_(owner), type_(type), value_(value), operand_type_(operand_type), size_(size) +{ + +} + +CommandInfo::~CommandInfo() +{ + if (owner_) + owner_->RemoveObject(this); +} + +/** + * CommandInfoList + */ + +CommandInfoList::CommandInfoList() + : ObjectList<CommandInfo>(), need_flags_(0), change_flags_(0) +{ + +} + +void CommandInfoList::Add(AccessType type, uint8_t value, OperandType operand_type, OperandSize size) +{ + CommandInfo *command_info = GetInfo(type, operand_type, value); + if (command_info) { + if (operand_type == otHiPartRegistr) { + if (size == command_info->size()) + return; + } else { + if (size > command_info->size()) + command_info->set_size(size); + return; + } + } + + if (operand_type == otRegistr) { + command_info = GetInfo(type, otHiPartRegistr, value); + if (command_info) { + if (size > command_info->size()) { + delete command_info; + } else if (size == command_info->size()) { + delete command_info; + size = static_cast<OperandSize>(size + 1); + } + } + } else if (operand_type == otHiPartRegistr) { + command_info = GetInfo(type, otRegistr, value); + if (command_info) { + if (size < command_info->size()) + return; + if (size == command_info->size()) { + command_info->set_size(static_cast<OperandSize>(size + 1)); + return; + } + } + } + + command_info = new CommandInfo(this, type, value, operand_type, size); + AddObject(command_info); +} + +CommandInfo *CommandInfoList::GetInfo(AccessType type, OperandType operand_type, uint8_t value) const +{ + for (size_t i = 0; i < count(); i++) { + CommandInfo *command_info = item(i); + if (command_info->type() == type && command_info->value() == value && command_info->operand_type() == operand_type) + return command_info; + } + return NULL; +} + +CommandInfo *CommandInfoList::GetInfo(AccessType type, OperandType operand_type) const +{ + for (size_t i = 0; i < count(); i++) { + CommandInfo *command_info = item(i); + if (command_info->type() == type && command_info->operand_type() == operand_type) + return command_info; + } + return NULL; +} + +CommandInfo *CommandInfoList::GetInfo(OperandType operand_type) const +{ + for (size_t i = 0; i < count(); i++) { + CommandInfo *command_info = item(i); + if (command_info->operand_type() == operand_type) + return command_info; + } + return NULL; +} + +void CommandInfoList::clear() +{ + need_flags_ = 0; + change_flags_ = 0; + ObjectList<CommandInfo>::clear(); +} + +bool CommandBlockListCompareHelper::operator()(const CommandBlock *block1, const CommandBlock *block2) const +{ + AddressRange *range1 = (block1->type() & mtExecutable) ? block1->function()->item(block1->start_index())->address_range() : NULL; + AddressRange *range2 = (block2->type() & mtExecutable) ? block2->function()->item(block2->start_index())->address_range() : NULL; + + FunctionInfo *info1 = range1 ? range1->owner() : NULL; + FunctionInfo *info2 = range2 ? range2->owner() : NULL; + + bool res; + if (info1 == info2 && range1 && range2) { + if (range1->original_begin() == range2->original_begin()) + res = range1->original_begin() ? block1->start_index() < block2->start_index() : block1->sort_index() < block2->sort_index(); + else + res = range1->original_begin() < range2->original_begin(); + } else { + uint64_t value1 = info1 ? info1->begin() : 0; + uint64_t value2 = info2 ? info2->begin() : 0; + res = (value1 == value2) ? block1->sort_index() < block2->sort_index() : (value1 < value2); + } + + return res; +} + +/** +* BaseVirtualMachine +*/ + +BaseVirtualMachine::BaseVirtualMachine(IVirtualMachineList *owner, uint8_t id) + : IVirtualMachine(), owner_(owner), id_(id) +{ + +} + +BaseVirtualMachine::~BaseVirtualMachine() +{ + if (owner_) + owner_->RemoveObject(this); +}
\ No newline at end of file |