12426 lines
345 KiB
C++
12426 lines
345 KiB
C++
#include "../runtime/crypto.h"
|
|
#include "objects.h"
|
|
#include "osutils.h"
|
|
#include "streams.h"
|
|
#include "files.h"
|
|
#include "pefile.h"
|
|
#include "processors.h"
|
|
#include "il.h"
|
|
#include "dotnet.h"
|
|
#include "dotnetfile.h"
|
|
#include "core.h"
|
|
#include "lang.h"
|
|
#include "script.h"
|
|
|
|
static AssemblyResolver resolver;
|
|
|
|
std::string ILName(const std::string &ret, const std::string &type, const std::string &method, const std::string &signature)
|
|
{
|
|
std::string res;
|
|
if (!ret.empty())
|
|
res += ret + ' ';
|
|
if (!type.empty())
|
|
res += type + "::";
|
|
return res + method + signature;
|
|
}
|
|
|
|
/**
|
|
* ILData
|
|
*/
|
|
|
|
ILData::ILData()
|
|
: std::vector<uint8_t>()
|
|
{
|
|
|
|
}
|
|
|
|
ILData::ILData(const uint8_t *data, size_t size)
|
|
: std::vector<uint8_t>()
|
|
{
|
|
insert(begin(), data, data + size);
|
|
}
|
|
|
|
uint32_t ILData::ReadEncoded(uint32_t &pos) const
|
|
{
|
|
if (pos >= size())
|
|
throw std::runtime_error("Invalid index for stream");
|
|
|
|
uint32_t res;
|
|
uint8_t b = at(pos);
|
|
if ((b & 0x80) == 0) {
|
|
res = at(pos) & 0x7f;
|
|
pos++;
|
|
} else if ((b & 0x40) == 0) {
|
|
res = ((at(pos) & 0x3f) << 8) + at(pos + 1);
|
|
pos += 2;
|
|
} else {
|
|
res = ((at(pos) & 0x1f) << 24) + (at(pos + 1) << 16) + (at(pos + 2) << 8) + at(pos + 3);
|
|
pos += 4;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void ILData::WriteEncoded(uint32_t value)
|
|
{
|
|
if (value < 0x80) {
|
|
WriteByte(static_cast<uint8_t>(value));
|
|
} else if (value < 0x4000) {
|
|
WriteByte(static_cast<uint8_t>(value >> 8) | 0x80);
|
|
WriteByte(static_cast<uint8_t>(value));
|
|
} else if (value < 0x02000000) {
|
|
WriteByte(static_cast<uint8_t>(value >> 24) | 0xc0);
|
|
WriteByte(static_cast<uint8_t>(value >> 16));
|
|
WriteByte(static_cast<uint8_t>(value >> 8));
|
|
WriteByte(static_cast<uint8_t>(value));
|
|
} else {
|
|
throw std::runtime_error("Value can not be encoded");
|
|
}
|
|
}
|
|
|
|
void ILData::Read(uint32_t &pos, void *buffer, uint32_t size) const
|
|
{
|
|
if (pos + size > this->size())
|
|
throw std::runtime_error("Invalid index for stream");
|
|
memcpy(buffer, data() + pos, size);
|
|
pos += size;
|
|
}
|
|
|
|
uint8_t ILData::ReadByte(uint32_t &pos) const
|
|
{
|
|
uint8_t res;
|
|
Read(pos, &res, sizeof(res));
|
|
return res;
|
|
}
|
|
|
|
uint16_t ILData::ReadWord(uint32_t &pos) const
|
|
{
|
|
uint16_t res;
|
|
Read(pos, &res, sizeof(res));
|
|
return res;
|
|
}
|
|
|
|
uint32_t ILData::ReadDWord(uint32_t &pos) const
|
|
{
|
|
uint32_t res;
|
|
Read(pos, &res, sizeof(res));
|
|
return res;
|
|
}
|
|
|
|
uint64_t ILData::ReadQWord(uint32_t &pos) const
|
|
{
|
|
uint64_t res;
|
|
Read(pos, &res, sizeof(res));
|
|
return res;
|
|
}
|
|
|
|
std::string ILData::ReadString(uint32_t &pos) const
|
|
{
|
|
std::string res;
|
|
uint32_t size = ReadEncoded(pos);
|
|
for (size_t i = 0; i < size; i++) {
|
|
res.push_back(ReadByte(pos));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void ILData::WriteByte(uint8_t value)
|
|
{
|
|
push_back(value);
|
|
}
|
|
|
|
void ILData::WriteWord(uint16_t value)
|
|
{
|
|
Write(&value, sizeof(value));
|
|
}
|
|
|
|
void ILData::WriteDWord(uint32_t value)
|
|
{
|
|
Write(&value, sizeof(value));
|
|
}
|
|
|
|
void ILData::WriteQWord(uint64_t value)
|
|
{
|
|
Write(&value, sizeof(value));
|
|
}
|
|
|
|
void ILData::Write(const void *buffer, size_t size)
|
|
{
|
|
if (size) {
|
|
const uint8_t *ptr = reinterpret_cast<const uint8_t *>(buffer);
|
|
insert(end(), ptr, ptr + size);
|
|
}
|
|
}
|
|
|
|
void ILData::WriteString(const std::string &value)
|
|
{
|
|
WriteEncoded(static_cast<uint32_t>(value.size()));
|
|
if (!value.empty())
|
|
Write(value.data(), value.size());
|
|
}
|
|
|
|
/**
|
|
* ILStream
|
|
*/
|
|
|
|
ILStream::ILStream(ILMetaData *owner, uint64_t address, uint32_t size, const std::string &name)
|
|
: BaseLoadCommand(owner), address_(address), size_(size), name_(name)
|
|
{
|
|
|
|
}
|
|
|
|
ILStream::ILStream(ILMetaData *owner, const ILStream &src)
|
|
: BaseLoadCommand(owner)
|
|
{
|
|
address_ = src.address_;
|
|
size_ = src.size_;
|
|
name_ = src.name_;
|
|
}
|
|
|
|
ILStream *ILStream::Clone(ILoadCommandList *owner) const
|
|
{
|
|
ILStream *stream = new ILStream(reinterpret_cast<ILMetaData *>(owner), *this);
|
|
return stream;
|
|
}
|
|
|
|
void ILStream::WriteToFile(NETArchitecture &file)
|
|
{
|
|
address_ = file.AddressTell();
|
|
}
|
|
|
|
void ILStream::Rebase(uint64_t delta_base)
|
|
{
|
|
address_ += delta_base;
|
|
}
|
|
|
|
void ILStream::FreeByManager(MemoryManager &manager)
|
|
{
|
|
manager.Add(address(), size());
|
|
}
|
|
|
|
/**
|
|
* ILStringsStream
|
|
*/
|
|
|
|
ILStringsStream::ILStringsStream(ILMetaData *owner, uint64_t address, uint32_t size, const std::string &name)
|
|
: ILStream(owner, address, size, name)
|
|
{
|
|
|
|
}
|
|
|
|
ILStringsStream::ILStringsStream(ILMetaData *owner, const ILStringsStream &src)
|
|
: ILStream(owner, src)
|
|
{
|
|
data_ = src.data_;
|
|
}
|
|
|
|
ILStream *ILStringsStream::Clone(ILoadCommandList *owner) const
|
|
{
|
|
ILStringsStream *stream = new ILStringsStream(reinterpret_cast<ILMetaData *>(owner), *this);
|
|
return stream;
|
|
}
|
|
|
|
void ILStringsStream::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
if (!file.AddressSeek(address()))
|
|
throw std::runtime_error("Invalid stream address");
|
|
|
|
data_.resize(size());
|
|
file.Read(data_.data(), data_.size());
|
|
}
|
|
|
|
void ILStringsStream::WriteToFile(NETArchitecture &file)
|
|
{
|
|
ILStream::WriteToFile(file);
|
|
data_.resize(AlignValue(data_.size(), sizeof(uint32_t)), 0);
|
|
set_size(static_cast<uint32_t>(file.Write(data_.data(), data_.size())));
|
|
}
|
|
|
|
void ILStringsStream::Prepare()
|
|
{
|
|
data_.clear();
|
|
map_.clear();
|
|
AddString("");
|
|
}
|
|
|
|
std::string ILStringsStream::GetString(uint32_t pos) const
|
|
{
|
|
if (pos >= data_.size())
|
|
throw std::runtime_error("Invalid index for " + name());
|
|
|
|
size_t len = data_.size() - pos;
|
|
for (size_t i = 0; i < len; i++) {
|
|
if (data_[pos + i] == 0) {
|
|
len = i;
|
|
break;
|
|
}
|
|
}
|
|
if (len == data_.size() - pos)
|
|
throw std::runtime_error("Invalid index for " + name());
|
|
|
|
return std::string(reinterpret_cast<const char *>(data_.data() + pos), len);
|
|
}
|
|
|
|
uint32_t ILStringsStream::AddString(const std::string &str)
|
|
{
|
|
std::map<std::string, uint32_t>::const_iterator it = map_.find(str);
|
|
if (it != map_.end())
|
|
return it->second;
|
|
|
|
uint32_t res = static_cast<uint32_t>(data_.size());
|
|
map_[str] = res;
|
|
|
|
data_.insert(data_.end(), str.data(), str.data() + str.size() + 1);
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* ILUserStringsStream
|
|
*/
|
|
|
|
ILUserStringsStream::ILUserStringsStream(ILMetaData *owner, uint64_t address, uint32_t size, const std::string &name)
|
|
: ILStream(owner, address, size, name)
|
|
{
|
|
|
|
}
|
|
|
|
ILUserStringsStream::ILUserStringsStream(ILMetaData *owner, const ILUserStringsStream &src)
|
|
: ILStream(owner, src)
|
|
{
|
|
data_ = src.data_;
|
|
}
|
|
|
|
ILUserStringsStream *ILUserStringsStream::Clone(ILoadCommandList *owner) const
|
|
{
|
|
ILUserStringsStream *stream = new ILUserStringsStream(reinterpret_cast<ILMetaData *>(owner), *this);
|
|
return stream;
|
|
}
|
|
|
|
void ILUserStringsStream::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
if (!file.AddressSeek(address()))
|
|
throw std::runtime_error("Invalid stream address");
|
|
|
|
data_.resize(size());
|
|
file.Read(data_.data(), data_.size());
|
|
}
|
|
|
|
void ILUserStringsStream::WriteToFile(NETArchitecture &file)
|
|
{
|
|
ILStream::WriteToFile(file);
|
|
data_.resize(AlignValue(data_.size(), sizeof(uint32_t)), 0);
|
|
set_size(static_cast<uint32_t>(file.Write(data_.data(), data_.size())));
|
|
}
|
|
|
|
void ILUserStringsStream::Prepare()
|
|
{
|
|
data_.clear();
|
|
data_.push_back(0);
|
|
map_.clear();
|
|
}
|
|
|
|
std::string ILUserStringsStream::GetString(uint32_t pos) const
|
|
{
|
|
uint32_t len = data_.ReadEncoded(pos);
|
|
if (pos + len > data_.size())
|
|
throw std::runtime_error("Invalid index for " + name());
|
|
|
|
len >>= 1;
|
|
if (!len)
|
|
return std::string();
|
|
|
|
os::unicode_string str;
|
|
str.resize(len);
|
|
memcpy(&str[0], &data_[pos], str.size() * sizeof(os::unicode_char));
|
|
|
|
return os::ToUTF8(str);
|
|
}
|
|
|
|
ILData ILUserStringsStream::GetData(uint32_t pos, uint64_t *address) const
|
|
{
|
|
uint32_t len = data_.ReadEncoded(pos);
|
|
if (pos + len > data_.size())
|
|
throw std::runtime_error("Invalid index for " + name());
|
|
|
|
if (len & 1)
|
|
len--;
|
|
if (address)
|
|
*address = this->address() + pos;
|
|
return ILData(&data_[pos], len);
|
|
}
|
|
|
|
uint32_t ILUserStringsStream::AddString(const std::string &str)
|
|
{
|
|
std::map<std::string, uint32_t>::const_iterator it = map_.find(str);
|
|
if (it != map_.end())
|
|
return it->second;
|
|
|
|
uint32_t res = static_cast<uint32_t>(data_.size());
|
|
map_[str] = res;
|
|
|
|
os::unicode_string tmp = os::FromUTF8(str);
|
|
size_t size = tmp.size() * sizeof(os::unicode_char) + 1;
|
|
data_.WriteEncoded(static_cast<uint32_t>(size));
|
|
data_.insert(data_.end(), reinterpret_cast<const uint8_t *>(tmp.data()), reinterpret_cast<const uint8_t *>(tmp.data()) + size);
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* ILBlobStream
|
|
*/
|
|
|
|
ILBlobStream::ILBlobStream(ILMetaData *owner, uint64_t address, uint32_t size, const std::string &name)
|
|
: ILStream(owner, address, size, name)
|
|
{
|
|
|
|
}
|
|
|
|
ILBlobStream::ILBlobStream(ILMetaData *owner, const ILBlobStream &src)
|
|
: ILStream(owner, src)
|
|
{
|
|
data_ = src.data_;
|
|
}
|
|
|
|
ILStream *ILBlobStream::Clone(ILoadCommandList *owner) const
|
|
{
|
|
ILBlobStream *stream = new ILBlobStream(reinterpret_cast<ILMetaData *>(owner), *this);
|
|
return stream;
|
|
}
|
|
|
|
void ILBlobStream::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
if (!file.AddressSeek(address()))
|
|
throw std::runtime_error("Invalid stream address");
|
|
|
|
data_.resize(size());
|
|
file.Read(data_.data(), data_.size());
|
|
}
|
|
|
|
void ILBlobStream::WriteToFile(NETArchitecture &file)
|
|
{
|
|
ILStream::WriteToFile(file);
|
|
data_.resize(AlignValue(data_.size(), sizeof(uint32_t)), 0);
|
|
set_size(static_cast<uint32_t>(file.Write(data_.data(), data_.size())));
|
|
}
|
|
|
|
void ILBlobStream::Prepare()
|
|
{
|
|
data_.clear();
|
|
map_.clear();
|
|
AddData(ILData());
|
|
}
|
|
|
|
ILData ILBlobStream::GetData(uint32_t pos) const
|
|
{
|
|
uint32_t len = data_.ReadEncoded(pos);
|
|
if (pos + len > data_.size())
|
|
throw std::runtime_error("Invalid index for " + name());
|
|
|
|
return ILData(&data_[pos], len);
|
|
}
|
|
|
|
uint32_t ILBlobStream::AddData(const ILData &value)
|
|
{
|
|
std::map<ILData, uint32_t>::const_iterator it = map_.find(value);
|
|
if (it != map_.end())
|
|
return it->second;
|
|
|
|
uint32_t res = static_cast<uint32_t>(data_.size());
|
|
map_[value] = res;
|
|
|
|
data_.WriteEncoded(static_cast<uint32_t>(value.size()));
|
|
data_.insert(data_.end(), value.data(), value.data() + value.size());
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* ILGuidStream
|
|
*/
|
|
|
|
ILGuidStream::ILGuidStream(ILMetaData *owner, uint64_t address, uint32_t size, const std::string &name)
|
|
: ILStream(owner, address, size, name)
|
|
{
|
|
|
|
}
|
|
|
|
ILGuidStream::ILGuidStream(ILMetaData *owner, const ILGuidStream &src)
|
|
: ILStream(owner, src)
|
|
{
|
|
data_ = src.data_;
|
|
}
|
|
|
|
ILStream *ILGuidStream::Clone(ILoadCommandList *owner) const
|
|
{
|
|
ILGuidStream *stream = new ILGuidStream(reinterpret_cast<ILMetaData *>(owner), *this);
|
|
return stream;
|
|
}
|
|
|
|
void ILGuidStream::Prepare()
|
|
{
|
|
data_.clear();
|
|
map_.clear();
|
|
}
|
|
|
|
void ILGuidStream::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
if (!file.AddressSeek(address()))
|
|
throw std::runtime_error("Invalid stream address");
|
|
|
|
data_.resize(size());
|
|
file.Read(data_.data(), data_.size());
|
|
}
|
|
|
|
void ILGuidStream::WriteToFile(NETArchitecture &file)
|
|
{
|
|
ILStream::WriteToFile(file);
|
|
data_.resize(AlignValue(data_.size(), sizeof(uint32_t)), 0);
|
|
set_size(static_cast<uint32_t>(file.Write(data_.data(), data_.size())));
|
|
}
|
|
|
|
ILData ILGuidStream::GetData(uint32_t pos) const
|
|
{
|
|
uint32_t len = 16;
|
|
if (pos + len > data_.size())
|
|
throw std::runtime_error("Invalid index for " + name());
|
|
|
|
return ILData(&data_[pos], len);
|
|
}
|
|
|
|
uint32_t ILGuidStream::AddData(const ILData &value)
|
|
{
|
|
std::map<ILData, uint32_t>::const_iterator it = map_.find(value);
|
|
if (it != map_.end())
|
|
return it->second;
|
|
|
|
uint32_t res = static_cast<uint32_t>(data_.size());
|
|
map_[value] = res;
|
|
|
|
data_.insert(data_.end(), value.data(), value.data() + value.size());
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* ILHeapStream
|
|
*/
|
|
|
|
ILHeapStream::ILHeapStream(ILMetaData *owner, uint64_t address, uint32_t size, const std::string &name)
|
|
: ILStream(owner, address, size, name)
|
|
{
|
|
|
|
}
|
|
|
|
ILHeapStream::~ILHeapStream()
|
|
{
|
|
for (size_t i = 0; i < table_list_.size(); i++) {
|
|
delete table_list_[i];
|
|
}
|
|
}
|
|
|
|
ILHeapStream::ILHeapStream(ILMetaData *owner, const ILHeapStream &src)
|
|
: ILStream(owner, src)
|
|
{
|
|
reserved_ = src.reserved_;
|
|
major_version_ = src.major_version_;
|
|
minor_version_ = src.minor_version_;
|
|
heap_offset_sizes_ = src.heap_offset_sizes_;
|
|
reserved2_ = src.reserved2_;
|
|
mask_valid_ = src.mask_valid_;
|
|
mask_sorted_ = src.mask_sorted_;
|
|
extra_data_ = src.extra_data_;
|
|
|
|
for (size_t i = 0; i < src.table_list_.size(); i++) {
|
|
table_list_.push_back(src.table_list_[i]->Clone(owner));
|
|
}
|
|
}
|
|
|
|
ILStream *ILHeapStream::Clone(ILoadCommandList *owner) const
|
|
{
|
|
ILHeapStream *stream = new ILHeapStream(reinterpret_cast<ILMetaData *>(owner), *this);
|
|
return stream;
|
|
}
|
|
|
|
ILTable *ILHeapStream::Add(ILTokenType type, uint32_t row_count)
|
|
{
|
|
ILTable *table = new ILTable(reinterpret_cast<ILMetaData *>(owner()), type, row_count);
|
|
table_list_.push_back(table);
|
|
return table;
|
|
}
|
|
|
|
void ILHeapStream::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
if (!file.AddressSeek(address()))
|
|
throw std::runtime_error("Invalid heap address");
|
|
|
|
reserved_ = file.ReadDWord();
|
|
major_version_ = file.ReadByte();
|
|
minor_version_ = file.ReadByte();
|
|
heap_offset_sizes_ = file.ReadByte();
|
|
reserved2_ = file.ReadByte();
|
|
mask_valid_ = file.ReadQWord();
|
|
mask_sorted_ = file.ReadQWord();
|
|
|
|
size_t i;
|
|
uint64_t mask = mask_valid_;
|
|
for (i = 0; i < 64; mask >>= 1, i++) {
|
|
uint32_t token_count = (mask & 1) ? file.ReadDWord() : 0;
|
|
Add(static_cast<ILTokenType>(i << 24), token_count);
|
|
}
|
|
|
|
if (heap_offset_sizes_ & 0x40) {
|
|
extra_data_.resize(sizeof(uint32_t));
|
|
file.Read(extra_data_.data(), extra_data_.size());
|
|
}
|
|
|
|
for (i = 0; i < count(); i++) {
|
|
table(i)->ReadFromFile(file);
|
|
}
|
|
}
|
|
|
|
void ILHeapStream::WriteToFile(NETArchitecture &file)
|
|
{
|
|
ILStream::WriteToFile(file);
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < count(); i++) {
|
|
table(i)->WriteToStreams(*reinterpret_cast<ILMetaData*>(owner()));
|
|
}
|
|
|
|
heap_offset_sizes_ = 0;
|
|
if (file.command_list()->string_data_size() > UINT16_MAX)
|
|
heap_offset_sizes_ |= 1;
|
|
if (file.command_list()->guid_data_size() > UINT16_MAX)
|
|
heap_offset_sizes_ |= 2;
|
|
if (file.command_list()->blob_data_size() > UINT16_MAX)
|
|
heap_offset_sizes_ |= 4;
|
|
if (!extra_data_.empty())
|
|
heap_offset_sizes_ |= 0x40;
|
|
|
|
uint64_t pos = file.Tell();
|
|
|
|
file.WriteDWord(reserved_);
|
|
file.WriteByte(major_version_);
|
|
file.WriteByte(minor_version_);
|
|
file.WriteByte(heap_offset_sizes_);
|
|
file.WriteByte(reserved2_);
|
|
|
|
mask_valid_ = 0;
|
|
uint64_t mask = 1;
|
|
for (i = 0; i < count(); mask <<= 1, i++) {
|
|
ILTable *table = this->table(i);
|
|
if (table->count())
|
|
mask_valid_ |= mask;
|
|
}
|
|
|
|
file.WriteQWord(mask_valid_);
|
|
file.WriteQWord(mask_sorted_);
|
|
|
|
for (i = 0; i < count(); i++) {
|
|
ILTable *table = this->table(i);
|
|
if (table->count())
|
|
file.WriteDWord(static_cast<uint32_t>(table->count()));
|
|
}
|
|
|
|
if (!extra_data_.empty())
|
|
file.Write(extra_data_.data(), extra_data_.size());
|
|
|
|
for (i = 0; i < count(); i++) {
|
|
table(i)->WriteToFile(file);
|
|
}
|
|
|
|
size_t size, pad_size;
|
|
for (size = static_cast<size_t>(file.Tell() - pos), pad_size = AlignValue(size, sizeof(uint32_t)); size < pad_size; size++) {
|
|
file.WriteByte(0);
|
|
}
|
|
set_size(static_cast<uint32_t>(size));
|
|
}
|
|
|
|
void ILHeapStream::Rebase(uint64_t delta_base)
|
|
{
|
|
ILStream::Rebase(delta_base);
|
|
|
|
for (size_t i = 0; i < count(); i++) {
|
|
table(i)->Rebase(delta_base);
|
|
}
|
|
}
|
|
|
|
void ILHeapStream::UpdateTokens()
|
|
{
|
|
size_t i, j;
|
|
std::map<ILToken *, ILToken *> token_map;
|
|
ILTable *table;
|
|
ILToken *token;
|
|
|
|
for (i = 0; i < count(); i++) {
|
|
table = this->table(i);
|
|
for (j = 0; j < table->count(); j++) {
|
|
token = table->item(j);
|
|
if (token->is_deleted())
|
|
token_map[token] = NULL;
|
|
}
|
|
}
|
|
if (!token_map.empty()) {
|
|
for (i = 0; i < count(); i++) {
|
|
table = this->table(i);
|
|
for (j = 0; j < table->count(); j++) {
|
|
token = table->item(j);
|
|
if (token->is_deleted())
|
|
continue;
|
|
|
|
token->RemapTokens(token_map);
|
|
if (token->is_deleted())
|
|
token_map[token] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<ILTable *> need_sort_list;
|
|
for (i = 0; i < count(); i++) {
|
|
table = this->table(i);
|
|
switch (table->type()) {
|
|
case ttConstant:
|
|
case ttCustomAttribute:
|
|
case ttGenericParam:
|
|
case ttGenericParamConstraint:
|
|
case ttImplMap:
|
|
case ttInterfaceImpl:
|
|
case ttMethodImpl:
|
|
case ttMethodSemantics:
|
|
need_sort_list.push_back(table);
|
|
break;
|
|
default:
|
|
table->UpdateTokens();
|
|
break;
|
|
}
|
|
}
|
|
for (i = 0; i < need_sort_list.size(); i++) {
|
|
table = need_sort_list[i];
|
|
table->Sort();
|
|
table->UpdateTokens();
|
|
}
|
|
}
|
|
|
|
void ILHeapStream::Pack()
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
table(i)->Pack();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ILMetaData
|
|
*/
|
|
|
|
ILMetaData::ILMetaData(NETArchitecture *owner)
|
|
: BaseCommandList(owner), strings_(NULL), user_strings_(NULL), blob_(NULL), guid_(NULL), heap_(NULL),
|
|
address_(0), signature_(0), major_version_(0), minor_version_(0), reserved_(0), flags_(0), size_(0)
|
|
{
|
|
us_table_ = new ILUserStringsTable(this);
|
|
}
|
|
|
|
ILMetaData::ILMetaData(NETArchitecture *owner, const ILMetaData &src)
|
|
: BaseCommandList(owner, src), strings_(NULL), user_strings_(NULL), blob_(NULL), guid_(NULL), heap_(NULL), size_(0)
|
|
{
|
|
address_ = src.address_;
|
|
signature_ = src.signature_;
|
|
major_version_ = src.major_version_;
|
|
minor_version_ = src.minor_version_;
|
|
reserved_ = src.reserved_;
|
|
flags_ = src.flags_;
|
|
version_ = src.version_;
|
|
framework_ = src.framework_;
|
|
us_table_ = src.us_table_->Clone(this);
|
|
|
|
if (src.strings_)
|
|
strings_ = reinterpret_cast<ILStringsStream *>(item(src.IndexOf(src.strings_)));
|
|
if (src.user_strings_)
|
|
user_strings_ = reinterpret_cast<ILUserStringsStream *>(item(src.IndexOf(src.user_strings_)));
|
|
if (src.blob_)
|
|
blob_ = reinterpret_cast<ILBlobStream *>(item(src.IndexOf(src.blob_)));
|
|
if (src.guid_)
|
|
guid_ = reinterpret_cast<ILGuidStream *>(item(src.IndexOf(src.guid_)));
|
|
if (src.heap_) {
|
|
heap_ = reinterpret_cast<ILHeapStream *>(item(src.IndexOf(src.heap_)));
|
|
for (size_t i = 0; i < heap_->count(); i++) {
|
|
ILTable *table = heap_->table(i);
|
|
for (size_t j = 0; j < table->count(); j++) {
|
|
table->item(j)->UpdateTokens();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ILMetaData::~ILMetaData()
|
|
{
|
|
delete us_table_;
|
|
}
|
|
|
|
ILMetaData *ILMetaData::Clone(NETArchitecture *owner) const
|
|
{
|
|
ILMetaData *meta_data = new ILMetaData(owner, *this);
|
|
return meta_data;
|
|
}
|
|
|
|
ILStream *ILMetaData::Add(uint64_t address, uint32_t size, const std::string &name)
|
|
{
|
|
ILStream *stream = NULL;
|
|
if (name == "#Strings") {
|
|
if (!strings_) {
|
|
strings_ = new ILStringsStream(this, address, size, name);
|
|
stream = strings_;
|
|
}
|
|
} else if (name == "#US") {
|
|
if (!user_strings_) {
|
|
user_strings_ = new ILUserStringsStream(this, address, size, name);
|
|
stream = user_strings_;
|
|
}
|
|
} else if (name == "#Blob") {
|
|
if (!blob_) {
|
|
blob_ = new ILBlobStream(this, address, size, name);
|
|
stream = blob_;
|
|
}
|
|
} else if (name == "#GUID") {
|
|
if (!guid_) {
|
|
guid_ = new ILGuidStream(this, address, size, name);
|
|
stream = guid_;
|
|
}
|
|
} else if (name == "#~") {
|
|
if (!heap_) {
|
|
heap_ = new ILHeapStream(this, address, size, name);
|
|
stream = heap_;
|
|
}
|
|
}
|
|
|
|
if (!stream)
|
|
stream = new ILStream(this, address, size, name);
|
|
AddObject(stream);
|
|
return stream;
|
|
}
|
|
|
|
void ILMetaData::ReadFromFile(NETArchitecture &file, uint64_t address)
|
|
{
|
|
if (!file.AddressSeek(address))
|
|
throw std::runtime_error("Invalid meta data address");
|
|
|
|
size_t i;
|
|
address_ = address;
|
|
signature_ = file.ReadDWord();
|
|
if (signature_ != 'BJSB')
|
|
throw std::runtime_error("Invalid meta data signature");
|
|
|
|
major_version_ = file.ReadWord();
|
|
minor_version_ = file.ReadWord();
|
|
reserved_ = file.ReadDWord();
|
|
size_t version_len = file.ReadDWord();
|
|
if (version_len) {
|
|
version_.resize(version_len);
|
|
file.Read(&version_[0], version_len);
|
|
}
|
|
flags_ = file.ReadWord();
|
|
size_t streams = file.ReadWord();
|
|
for (i = 0; i < streams; i++) {
|
|
uint64_t stream_address = file.ReadDWord() + address_;
|
|
uint32_t stream_size = file.ReadDWord();
|
|
std::string stream_name = file.ReadString();
|
|
for (size_t str_size = stream_name.size() + 1, pad_size = AlignValue(str_size, sizeof(uint32_t)); str_size < pad_size; str_size++) {
|
|
file.ReadByte();
|
|
}
|
|
Add(stream_address, stream_size, stream_name);
|
|
}
|
|
if (!heap_)
|
|
throw std::runtime_error("Invalid .NET format");
|
|
|
|
for (i = 0; i < count(); i++) {
|
|
ILStream *stream = item(i);
|
|
if (stream == heap_)
|
|
continue;
|
|
stream->ReadFromFile(file);
|
|
}
|
|
heap_->ReadFromFile(file);
|
|
|
|
ILTable *table = this->table(ttNestedClass);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILNestedClass *nested = reinterpret_cast<ILNestedClass *>(table->item(i));
|
|
ILTypeDef *nested_type = nested->nested_type();
|
|
ILTypeDef *declaring_type = nested->declaring_type();
|
|
if (!nested_type || !declaring_type)
|
|
throw std::runtime_error("Invalid nested class");
|
|
nested_type->set_declaring_type(declaring_type);
|
|
}
|
|
|
|
table = this->table(ttTypeDef);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(table->item(i));
|
|
ILTypeDef *next = type_def->next();
|
|
ILMethodDef *method_end = next ? next->method_list() : NULL;
|
|
if (type_def->method_list() == method_end)
|
|
type_def->set_method_list(NULL);
|
|
else for (ILMethodDef *method = type_def->method_list(); method && method != method_end; method = method->next())
|
|
method->set_declaring_type(type_def);
|
|
|
|
ILField *field_end = next ? next->field_list() : NULL;
|
|
if (type_def->field_list() == field_end)
|
|
type_def->set_field_list(NULL);
|
|
else for (ILField *field = type_def->field_list(); field && field != field_end; field = field->next())
|
|
field->set_declaring_type(type_def);
|
|
}
|
|
|
|
table = this->table(ttMethodDef);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILMethodDef *method = reinterpret_cast<ILMethodDef *>(table->item(i));
|
|
ILMethodDef *next = method->next();
|
|
ILParam *param_end = next ? next->param_list() : NULL;
|
|
if (method->param_list() == param_end)
|
|
method->set_param_list(NULL);
|
|
else for (ILParam *param = method->param_list(); param && param != param_end; param = param->next())
|
|
param->set_parent(method);
|
|
}
|
|
|
|
table = this->table(ttPropertyMap);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILPropertyMap *property_map = reinterpret_cast<ILPropertyMap *>(table->item(i));
|
|
ILPropertyMap *next = property_map->next();
|
|
ILProperty *property_end = next ? next->property_list() : NULL;
|
|
if (property_map->property_list() == property_end)
|
|
property_map->set_property_list(NULL);
|
|
else for (ILProperty *property = property_map->property_list(); property && property != property_end; property = property->next())
|
|
property->set_declaring_type(property_map->parent());
|
|
}
|
|
|
|
table = this->table(ttEventMap);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILEventMap *event_map = reinterpret_cast<ILEventMap *>(table->item(i));
|
|
ILEventMap *next = event_map->next();
|
|
ILEvent *event_end = next ? next->event_list() : NULL;
|
|
if (event_map->event_list() == event_end)
|
|
event_map->set_event_list(NULL);
|
|
else for (ILEvent *event = event_map->event_list(); event && event != event_end; event = event->next())
|
|
event->set_declaring_type(event_map->parent());
|
|
}
|
|
|
|
table = this->table(ttCustomAttribute);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILCustomAttribute *attribute = reinterpret_cast<ILCustomAttribute *>(table->item(i));
|
|
if (attribute->type()->type() == ttMemberRef) {
|
|
ILMemberRef *member_ref = reinterpret_cast<ILMemberRef *>(attribute->type());
|
|
if (member_ref->name() == ".ctor") {
|
|
if (ILToken *declaring_type = member_ref->declaring_type()) {
|
|
std::string full_name;
|
|
switch (declaring_type->type()) {
|
|
case ttTypeRef:
|
|
full_name = reinterpret_cast<ILTypeRef *>(declaring_type)->full_name();
|
|
break;
|
|
}
|
|
if (full_name == "System.Runtime.Versioning.TargetFrameworkAttribute") {
|
|
CustomAttributeValue *value = attribute->ParseValue();
|
|
if (value->fixed_list()->count() == 1) {
|
|
std::string str = value->fixed_list()->item(0)->ToString();
|
|
str.erase(std::remove_if(str.begin(), str.end(), [](char c) { return c == ' '; }), str.end());
|
|
i = str.find(",");
|
|
if (i != std::string::npos) {
|
|
std::string name = str.substr(0, i);
|
|
if (name == ".NETFramework")
|
|
framework_.type = fwFramework;
|
|
else if (name == ".NETCoreApp")
|
|
framework_.type = fwCore;
|
|
else if (name == ".NETStandard")
|
|
framework_.type = fwStandard;
|
|
}
|
|
if (framework_.type != fwUnknown) {
|
|
i = str.find("Version=v");
|
|
if (i != std::string::npos)
|
|
framework_.version.Parse(str.substr(i + 9));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (framework_.type == fwUnknown) {
|
|
if (ILAssemblyRef *core_lib = GetCoreLib()) {
|
|
if (core_lib->name() == "mscorlib") {
|
|
framework_.type = fwFramework;
|
|
framework_.version.major = core_lib->major_version();
|
|
}
|
|
else if (core_lib->name() == "System.Runtime")
|
|
framework_.type = fwCore;
|
|
else if (core_lib->name() == "netstandard")
|
|
framework_.type = fwStandard;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ILMetaData::FreeByManager(MemoryManager &manager)
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->FreeByManager(manager);
|
|
}
|
|
}
|
|
|
|
void ILMetaData::Prepare()
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->Prepare();
|
|
}
|
|
}
|
|
|
|
void ILMetaData::WriteToFile(NETArchitecture &file)
|
|
{
|
|
if (heap_)
|
|
heap_->Pack();
|
|
|
|
address_ = file.AddressTell();
|
|
uint64_t pos = file.Tell();
|
|
|
|
size_t i;
|
|
file.WriteDWord(signature_);
|
|
file.WriteWord(major_version_);
|
|
file.WriteWord(minor_version_);
|
|
file.WriteDWord(reserved_);
|
|
file.WriteDWord(static_cast<uint32_t>(version_.size()));
|
|
if (!version_.empty())
|
|
file.Write(version_.data(), version_.size());
|
|
file.WriteWord(flags_);
|
|
file.WriteWord(static_cast<uint16_t>(count()));
|
|
|
|
std::vector<uint64_t> pos_list;
|
|
for (i = 0; i < count(); i++) {
|
|
ILStream *stream = item(i);
|
|
pos_list.push_back(file.Tell());
|
|
file.WriteDWord(0);
|
|
file.WriteDWord(0);
|
|
std::string stream_name = stream->name();
|
|
file.Write(stream_name.c_str(), stream_name.size() + 1);
|
|
for (size_t str_size = stream_name.size() + 1, pad_size = AlignValue(str_size, sizeof(uint32_t)); str_size < pad_size; str_size++) {
|
|
file.WriteByte(0);
|
|
}
|
|
}
|
|
|
|
if (heap_)
|
|
heap_->WriteToFile(file);
|
|
for (i = 0; i < count(); i++) {
|
|
ILStream *stream = item(i);
|
|
if (stream == heap_)
|
|
continue;
|
|
stream->WriteToFile(file);
|
|
}
|
|
|
|
size_ = static_cast<uint32_t>(file.Tell() - pos);
|
|
|
|
for (i = 0; i < count(); i++) {
|
|
ILStream *stream = item(i);
|
|
file.Seek(pos_list[i]);
|
|
file.WriteDWord(static_cast<uint32_t>(stream->address() - address_));
|
|
file.WriteDWord(stream->size());
|
|
}
|
|
}
|
|
|
|
ILStream *ILMetaData::item(size_t index) const
|
|
{
|
|
return reinterpret_cast<ILStream *>(BaseCommandList::item(index));
|
|
}
|
|
|
|
ILStream *ILMetaData::GetStreamByName(const std::string &name) const
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
ILStream *stream = item(i);
|
|
if (stream->name() == name)
|
|
return stream;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ILTable *ILMetaData::table(ILTokenType type) const
|
|
{
|
|
if (type == ttUserString)
|
|
return us_table_;
|
|
|
|
size_t i = type >> 24;
|
|
if (i >= heap_->count())
|
|
return NULL;
|
|
|
|
return heap_->table(i);
|
|
}
|
|
|
|
uint32_t ILMetaData::token_count(ILTokenType type) const
|
|
{
|
|
ILTable *table = this->table(type);
|
|
if (!table)
|
|
return 0;
|
|
|
|
return static_cast<uint32_t>(table->count());
|
|
}
|
|
|
|
ILToken *ILMetaData::token(uint32_t id) const
|
|
{
|
|
ILTokenType type = static_cast<ILTokenType>(TOKEN_TYPE(id));
|
|
uint32_t value = TOKEN_VALUE(id);
|
|
if (type == ttUserString)
|
|
return us_table_->GetTokenByPos(value);
|
|
|
|
ILTable *table = this->table(type);
|
|
if (!table || value < 1 || value > table->count())
|
|
return NULL;
|
|
|
|
return table->item(value - 1);
|
|
}
|
|
|
|
size_t ILMetaData::field_size(ILTokenType type) const
|
|
{
|
|
return (token_count(type) < 0x10000) ? sizeof(uint16_t) : sizeof(uint32_t);
|
|
}
|
|
|
|
size_t ILMetaData::field_size(const EncodingDesc &desc) const
|
|
{
|
|
uint32_t count = 0;
|
|
for (size_t i = 0; i < desc.size; i++) {
|
|
count = std::max(count, token_count(desc.types[i]));
|
|
}
|
|
return (count < uint32_t(1 << (16 - desc.bits))) ? sizeof(uint16_t) : sizeof(uint32_t);
|
|
}
|
|
|
|
std::string ILMetaData::GetUserString(uint32_t pos) const
|
|
{
|
|
if (!user_strings_)
|
|
throw std::runtime_error("Invalid .NET format");
|
|
return user_strings_->GetString(pos);
|
|
}
|
|
|
|
ILData ILMetaData::GetUserData(uint32_t pos, uint64_t *address) const
|
|
{
|
|
if (!user_strings_)
|
|
throw std::runtime_error("Invalid .NET format");
|
|
return user_strings_->GetData(pos, address);
|
|
}
|
|
|
|
std::string ILMetaData::GetString(uint32_t pos) const
|
|
{
|
|
if (!strings_)
|
|
throw std::runtime_error("Invalid .NET format");
|
|
return strings_->GetString(pos);
|
|
}
|
|
|
|
ILData ILMetaData::GetGuid(uint32_t pos) const
|
|
{
|
|
if (!pos)
|
|
return ILData();
|
|
|
|
if (!guid_)
|
|
throw std::runtime_error("Invalid .NET format");
|
|
return guid_->GetData(pos - 1);
|
|
}
|
|
|
|
ILData ILMetaData::GetBlob(uint32_t pos) const
|
|
{
|
|
if (!pos)
|
|
return ILData();
|
|
|
|
if (!blob_)
|
|
throw std::runtime_error("Invalid .NET format");
|
|
return blob_->GetData(pos);
|
|
}
|
|
|
|
uint32_t ILMetaData::AddUserString(const std::string &str) const
|
|
{
|
|
if (!user_strings_)
|
|
throw std::runtime_error("Invalid .NET format");
|
|
return user_strings_->AddString(str);
|
|
}
|
|
|
|
uint32_t ILMetaData::AddString(const std::string &str) const
|
|
{
|
|
if (!strings_)
|
|
throw std::runtime_error("Invalid .NET format");
|
|
return strings_->AddString(str);
|
|
}
|
|
|
|
uint32_t ILMetaData::AddGuid(const ILData &data) const
|
|
{
|
|
if (data.empty())
|
|
return 0;
|
|
|
|
if (!guid_)
|
|
throw std::runtime_error("Invalid .NET format");
|
|
return guid_->AddData(data) + 1;
|
|
}
|
|
|
|
uint32_t ILMetaData::AddBlob(const ILData &data) const
|
|
{
|
|
if (data.empty())
|
|
return 0;
|
|
|
|
if (!blob_)
|
|
throw std::runtime_error("Invalid .NET format");
|
|
return blob_->AddData(data);
|
|
}
|
|
|
|
void ILMetaData::UpdateTokens()
|
|
{
|
|
uint64_t pos = owner()->Tell();
|
|
if (heap_)
|
|
heap_->UpdateTokens();
|
|
if (us_table_)
|
|
us_table_->UpdateTokens();
|
|
owner()->Seek(pos);
|
|
}
|
|
|
|
void ILMetaData::Rebase(uint64_t delta_base)
|
|
{
|
|
BaseCommandList::Rebase(delta_base);
|
|
us_table_->Rebase(delta_base);
|
|
}
|
|
|
|
const char *ElementTypeToName[ELEMENT_TYPE_MAX] =
|
|
{
|
|
"", "Void", "Boolean", "Char",
|
|
"SByte", "Byte", "Int16", "UInt16",
|
|
"Int32", "UInt32", "Int64", "UInt64",
|
|
"Single", "Double", "String", "", "", "", "", "", "", "", "", "", "IntPtr", "UIntPtr", "", "", "Object", "Array", "", "", "", ""
|
|
};
|
|
|
|
ILToken *ILMetaData::GetType(const ILElement &element) const
|
|
{
|
|
std::string type_name;
|
|
ILTable *table;
|
|
size_t i;
|
|
ILToken *assembly_ref;
|
|
|
|
switch (element.type()) {
|
|
case ELEMENT_TYPE_VOID:
|
|
case ELEMENT_TYPE_BOOLEAN:
|
|
case ELEMENT_TYPE_CHAR:
|
|
case ELEMENT_TYPE_I1:
|
|
case ELEMENT_TYPE_U1:
|
|
case ELEMENT_TYPE_I2:
|
|
case ELEMENT_TYPE_U2:
|
|
case ELEMENT_TYPE_I4:
|
|
case ELEMENT_TYPE_U4:
|
|
case ELEMENT_TYPE_I8:
|
|
case ELEMENT_TYPE_U8:
|
|
case ELEMENT_TYPE_R4:
|
|
case ELEMENT_TYPE_R8:
|
|
case ELEMENT_TYPE_STRING:
|
|
case ELEMENT_TYPE_I:
|
|
case ELEMENT_TYPE_U:
|
|
case ELEMENT_TYPE_OBJECT:
|
|
case ELEMENT_TYPE_SZARRAY:
|
|
assembly_ref = GetCoreLib();
|
|
if (!assembly_ref)
|
|
throw std::runtime_error("Unknown framework");
|
|
|
|
return GetTypeRef(assembly_ref, "System", ElementTypeToName[element.type()]);
|
|
break;
|
|
case ELEMENT_TYPE_GENERICINST:
|
|
case ELEMENT_TYPE_PTR:
|
|
case ELEMENT_TYPE_ARRAY:
|
|
type_name = element.name();
|
|
table = this->table(ttTypeSpec);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILTypeSpec *ref = reinterpret_cast<ILTypeSpec *>(table->item(i));
|
|
if (ref->name() == type_name)
|
|
return ref;
|
|
}
|
|
break;
|
|
case ELEMENT_TYPE_CLASS:
|
|
case ELEMENT_TYPE_VALUETYPE:
|
|
return element.token();
|
|
default:
|
|
throw std::runtime_error("Invalid element type");
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ILTypeRef *ILMetaData::ImportTypeRef(ILToken *resolution_scope, const std::string &name_space, const std::string &name)
|
|
{
|
|
ILTypeRef *res = GetTypeRef(resolution_scope, name_space, name);
|
|
if (!res)
|
|
res = AddTypeRef(resolution_scope, name_space, name);
|
|
return res;
|
|
}
|
|
|
|
ILTypeRef *ILMetaData::GetTypeRef(ILToken *resolution_scope, const std::string &name_space, const std::string &name) const
|
|
{
|
|
ILTable *table = this->table(ttTypeRef);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILTypeRef *ref = reinterpret_cast<ILTypeRef *>(table->item(i));
|
|
if (ref->resolution_scope() == resolution_scope && ref->name_space() == name_space && ref->name() == name)
|
|
return ref;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ILTypeRef *ILMetaData::AddTypeRef(ILToken *resolution_scope, const std::string &name_space, const std::string &name)
|
|
{
|
|
ILTable *table = this->table(ttTypeRef);
|
|
ILTypeRef *res = new ILTypeRef(this, table, resolution_scope, name_space, name);
|
|
table->AddObject(res);
|
|
return res;
|
|
}
|
|
|
|
ILToken *ILMetaData::AddType(const ILElement &element)
|
|
{
|
|
ILData data;
|
|
ILTable *table;
|
|
ILToken *assembly_ref;
|
|
ILToken *res;
|
|
|
|
switch (element.type()) {
|
|
case ELEMENT_TYPE_VOID:
|
|
case ELEMENT_TYPE_BOOLEAN:
|
|
case ELEMENT_TYPE_CHAR:
|
|
case ELEMENT_TYPE_I1:
|
|
case ELEMENT_TYPE_U1:
|
|
case ELEMENT_TYPE_I2:
|
|
case ELEMENT_TYPE_U2:
|
|
case ELEMENT_TYPE_I4:
|
|
case ELEMENT_TYPE_U4:
|
|
case ELEMENT_TYPE_I8:
|
|
case ELEMENT_TYPE_U8:
|
|
case ELEMENT_TYPE_R4:
|
|
case ELEMENT_TYPE_R8:
|
|
case ELEMENT_TYPE_STRING:
|
|
case ELEMENT_TYPE_I:
|
|
case ELEMENT_TYPE_U:
|
|
case ELEMENT_TYPE_OBJECT:
|
|
case ELEMENT_TYPE_SZARRAY:
|
|
assembly_ref = GetCoreLib();
|
|
if (!assembly_ref)
|
|
throw std::runtime_error("Unknown framework");
|
|
|
|
return AddTypeRef(assembly_ref, "System", ElementTypeToName[element.type()]);
|
|
case ELEMENT_TYPE_GENERICINST:
|
|
case ELEMENT_TYPE_PTR:
|
|
case ELEMENT_TYPE_ARRAY:
|
|
element.WriteToData(data);
|
|
table = this->table(ttTypeSpec);
|
|
res = new ILTypeSpec(this, table, data);
|
|
table->AddObject(res);
|
|
return res;
|
|
default:
|
|
throw std::runtime_error("Invalid element type");
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ILToken *ILMetaData::ImportType(CorElementType type)
|
|
{
|
|
ILElement element(NULL, NULL, type);
|
|
return ImportType(element);
|
|
}
|
|
|
|
ILToken *ILMetaData::ImportType(const ILElement &element)
|
|
{
|
|
ILToken *res = GetType(element);
|
|
if (!res)
|
|
res = AddType(element);
|
|
return res;
|
|
}
|
|
|
|
ILMethodDef *ILMetaData::GetMethod(uint64_t address) const
|
|
{
|
|
ILTable *table = this->table(ttMethodDef);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILMethodDef *method = reinterpret_cast<ILMethodDef*>(table->item(i));
|
|
if (method->address() == address)
|
|
return method;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ILTypeDef *ILMetaData::GetTypeDef(const std::string &name) const
|
|
{
|
|
ILTable *table = this->table(ttTypeDef);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef*>(table->item(i));
|
|
if (type_def->full_name() == name)
|
|
return type_def;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ILExportedType *ILMetaData::GetExportedType(const std::string &name) const
|
|
{
|
|
ILTable *table = this->table(ttExportedType);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILExportedType *exported_type = reinterpret_cast<ILExportedType*>(table->item(i));
|
|
if (exported_type->full_name() == name)
|
|
return exported_type;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ILAssemblyRef *ILMetaData::GetAssemblyRef(const std::string &name) const
|
|
{
|
|
ILTable *table = this->table(ttAssemblyRef);
|
|
bool is_full_name = (name.find(',') != std::string::npos);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILAssemblyRef *ref = reinterpret_cast<ILAssemblyRef*>(table->item(i));
|
|
if (is_full_name) {
|
|
if (ref->full_name() == name)
|
|
return ref;
|
|
}
|
|
else {
|
|
if (ref->name() == name)
|
|
return ref;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ILStandAloneSig *ILMetaData::AddStandAloneSig(const ILData &data)
|
|
{
|
|
ILTable *table = this->table(ttStandAloneSig);
|
|
ILStandAloneSig *signature = new ILStandAloneSig(this, table, data);
|
|
table->AddObject(signature);
|
|
signature->set_value(static_cast<uint32_t>(table->count()));
|
|
return signature;
|
|
}
|
|
|
|
ILAssemblyRef *ILMetaData::GetCoreLib() const
|
|
{
|
|
ILTable *table = this->table(ttAssemblyRef);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILAssemblyRef *ref = reinterpret_cast<ILAssemblyRef *>(table->item(i));
|
|
if (ref->name() == "mscorlib" || ref->name() == "System.Runtime" || ref->name() == "netstandard")
|
|
return ref;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ILTypeDef *ILMetaData::AddTypeDef(ILToken *base_type, const std::string &name_space, const std::string &name, CorTypeAttr flags)
|
|
{
|
|
ILTable *table = this->table(ttTypeDef);
|
|
ILTypeDef *res = new ILTypeDef(this, table, base_type, name_space, name, flags);
|
|
table->AddObject(res);
|
|
return res;
|
|
}
|
|
|
|
ILMethodDef *ILMetaData::AddMethod(ILTypeDef *declaring_type, const std::string &name, const ILData &signature, CorMethodAttr flags, CorMethodImpl impl_flags)
|
|
{
|
|
ILMethodDef *res = new ILMethodDef(this, table(ttMethodDef), name, signature, flags, impl_flags);
|
|
res->set_declaring_type(declaring_type);
|
|
declaring_type->AddMethod(res);
|
|
return res;
|
|
}
|
|
|
|
ILMetaData *ILMetaData::ResolveAssembly(const std::string &name, bool show_error) const
|
|
{
|
|
if (ILAssembly *assembly = reinterpret_cast<ILAssembly *>(token(ttAssembly | 1))) {
|
|
std::string self_name = (name.find(',') == std::string::npos) ? assembly->name() : assembly->full_name();
|
|
if (self_name == name)
|
|
return const_cast<ILMetaData *>(this);
|
|
}
|
|
|
|
ILMetaData *res = resolver.Resolve(*this, name);
|
|
if (!res && show_error)
|
|
throw std::runtime_error(string_format("Can't resolve assembly: %s", name.c_str()));
|
|
|
|
return res;
|
|
}
|
|
|
|
ILTypeDef *ILMetaData::ResolveType(const std::string &name, bool show_error)
|
|
{
|
|
size_t pos = 0;
|
|
size_t length = name.size();
|
|
|
|
std::string type_name;
|
|
while (pos < length) {
|
|
char c = name[pos];
|
|
if (c == ',' || c == '+')
|
|
break;
|
|
pos++;
|
|
}
|
|
type_name = name.substr(0, pos);
|
|
|
|
std::vector<std::string> nested_names;
|
|
while (pos < length && name[pos] == '+') {
|
|
pos++;
|
|
size_t start = pos;
|
|
while (pos < length) {
|
|
char c = name[pos];
|
|
if (c == ',' || c == '+')
|
|
break;
|
|
pos++;
|
|
}
|
|
nested_names.push_back(name.substr(start, pos - start));
|
|
}
|
|
|
|
std::string assembly_name;
|
|
if (pos < length && name[pos] == ',') {
|
|
pos++;
|
|
while (pos < length && name[pos] == ' ') {
|
|
pos++;
|
|
}
|
|
|
|
size_t start = pos;
|
|
while (pos < length) {
|
|
char c = name[pos];
|
|
if (c == '[' || c == ']')
|
|
break;
|
|
pos++;
|
|
}
|
|
assembly_name = name.substr(start, pos - start);
|
|
}
|
|
|
|
if (assembly_name.empty() && nested_names.empty() && name.substr(0, 7) == "System.") {
|
|
std::string corlib_type = name.substr(7);
|
|
const char *corlib_types[] = { "Void", "Boolean", "Char", "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Single", "Double", "String", "TypedReference", "IntPtr", "UIntPtr", "Object" };
|
|
for (size_t i = 0; i < _countof(corlib_types); i++) {
|
|
if (corlib_types[i] == corlib_type) {
|
|
if (ILAssemblyRef *assembly_ref = GetCoreLib())
|
|
assembly_name = assembly_ref->full_name();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ILMetaData *assembly = assembly_name.empty() ? this : ResolveAssembly(assembly_name, show_error);
|
|
if (assembly) {
|
|
ILTypeDef *type_def = assembly->GetTypeDef(type_name);
|
|
if (!type_def) {
|
|
if (ILExportedType *exported_type = assembly->GetExportedType(type_name))
|
|
type_def = Resolve(exported_type, show_error);
|
|
}
|
|
if (type_def) {
|
|
for (size_t i = 0; i < nested_names.size(); i++) {
|
|
type_def = type_def->GetNested(nested_names[i]);
|
|
if (!type_def)
|
|
break;
|
|
}
|
|
return type_def;
|
|
}
|
|
}
|
|
|
|
if (show_error)
|
|
throw std::runtime_error(string_format("Can't resolve type: %s", name.c_str()));
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ILTypeDef *ILMetaData::Resolve(const ILExportedType *exported_type, bool show_error) const
|
|
{
|
|
std::string type_name = exported_type->full_name();
|
|
|
|
std::set<const ILExportedType *> recursion_stack;
|
|
while (true) {
|
|
if (recursion_stack.find(exported_type) != recursion_stack.end())
|
|
break;
|
|
recursion_stack.insert(exported_type);
|
|
|
|
const ILExportedType *non_nested_type = exported_type;
|
|
while (non_nested_type->declaring_type()) {
|
|
non_nested_type = non_nested_type->declaring_type();
|
|
}
|
|
|
|
ILToken *scope = non_nested_type->implementation();
|
|
if (scope && scope->type() == ttAssemblyRef) {
|
|
if (ILMetaData *assembly = ResolveAssembly(reinterpret_cast<ILAssemblyRef *>(scope)->full_name(), show_error)) {
|
|
if (ILTypeDef *type_def = assembly->GetTypeDef(type_name))
|
|
return type_def;
|
|
exported_type = assembly->GetExportedType(type_name);
|
|
if (exported_type)
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ILTypeDef *ILMetaData::Resolve(const ILTypeRef *type_ref, bool show_error) const
|
|
{
|
|
std::string type_name = type_ref->full_name();
|
|
|
|
const ILTypeRef *non_nested_type = type_ref;
|
|
while (non_nested_type->declaring_type()) {
|
|
non_nested_type = non_nested_type->declaring_type();
|
|
}
|
|
|
|
ILToken *scope = non_nested_type->resolution_scope();
|
|
if (scope && scope->type() == ttAssemblyRef) {
|
|
if (ILMetaData *assembly = ResolveAssembly(reinterpret_cast<ILAssemblyRef *>(scope)->full_name(), show_error)) {
|
|
ILTypeDef *type_def = assembly->GetTypeDef(type_name);
|
|
if (!type_def) {
|
|
if (ILExportedType *exported_type = assembly->GetExportedType(type_name))
|
|
type_def = Resolve(exported_type, show_error);
|
|
}
|
|
if (type_def)
|
|
return type_def;
|
|
}
|
|
}
|
|
|
|
if (show_error)
|
|
throw std::runtime_error(string_format("Can't resolve token: %.8x", type_ref->id()));
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* TokenReference
|
|
*/
|
|
|
|
TokenReference::TokenReference(TokenReferenceList *owner, uint64_t address, uint32_t command_type)
|
|
: IObject(), owner_(owner), address_(address), is_deleted_(false), command_type_(command_type)
|
|
{
|
|
|
|
}
|
|
|
|
TokenReference::TokenReference(TokenReferenceList *owner, const TokenReference &src)
|
|
: IObject(src), owner_(owner)
|
|
{
|
|
address_ = src.address_;
|
|
is_deleted_ = src.is_deleted_;
|
|
command_type_ = src.command_type_;
|
|
}
|
|
|
|
TokenReference::~TokenReference()
|
|
{
|
|
if (owner_)
|
|
owner_->RemoveObject(this);
|
|
}
|
|
|
|
void TokenReference::set_owner(TokenReferenceList *owner)
|
|
{
|
|
if (owner == owner_)
|
|
return;
|
|
if (owner_)
|
|
owner_->RemoveObject(this);
|
|
owner_ = owner;
|
|
if (owner_)
|
|
owner_->AddObject(this);
|
|
}
|
|
|
|
TokenReference *TokenReference::Clone(TokenReferenceList *owner) const
|
|
{
|
|
TokenReference *ref = new TokenReference(owner, *this);
|
|
return ref;
|
|
}
|
|
|
|
void TokenReference::Rebase(uint64_t delta_base)
|
|
{
|
|
address_ += delta_base;
|
|
}
|
|
|
|
/**
|
|
* TokenReferenceList
|
|
*/
|
|
|
|
TokenReferenceList::TokenReferenceList(ILToken *owner)
|
|
: ObjectList<TokenReference>(), owner_(owner)
|
|
{
|
|
|
|
}
|
|
|
|
TokenReferenceList::TokenReferenceList(ILToken *owner, const TokenReferenceList &src)
|
|
: ObjectList<TokenReference>(src), owner_(owner)
|
|
{
|
|
for (size_t i = 0; i < src.count(); i++) {
|
|
AddObject(src.item(i)->Clone(this));
|
|
}
|
|
}
|
|
|
|
TokenReferenceList *TokenReferenceList::Clone(ILToken *owner) const
|
|
{
|
|
TokenReferenceList *list = new TokenReferenceList(owner, *this);
|
|
return list;
|
|
}
|
|
|
|
TokenReference *TokenReferenceList::Add(uint64_t address, uint32_t command_type)
|
|
{
|
|
TokenReference *ref = new TokenReference(this, address, command_type);
|
|
AddObject(ref);
|
|
return ref;
|
|
}
|
|
|
|
TokenReference *TokenReferenceList::GetReferenceByAddress(uint64_t address) const
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
TokenReference *ref = item(i);
|
|
if (ref->address() == address)
|
|
return ref;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void TokenReferenceList::Rebase(uint64_t delta_base)
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->Rebase(delta_base);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EncodingDesc
|
|
*/
|
|
|
|
const ILTokenType resolution_scope_types[] = {ttModule, ttModuleRef, ttAssemblyRef, ttTypeRef};
|
|
const ILTokenType typedef_ref_types[] = {ttTypeDef, ttTypeRef, ttTypeSpec};
|
|
const ILTokenType type_or_methoddef_types[] = {ttTypeDef, ttMethodDef};
|
|
const ILTokenType has_semantics_types[] = {ttEvent, ttProperty};
|
|
const ILTokenType methoddef_ref_types[] = {ttMethodDef, ttMemberRef};
|
|
const ILTokenType member_forwarded_types[] = {ttField, ttMethodDef};
|
|
const ILTokenType has_field_marshal_types[] = {ttField, ttParam};
|
|
const ILTokenType implementation_types[] = {ttFile, ttAssemblyRef, ttExportedType};
|
|
const ILTokenType member_ref_parent_types[] = {ttTypeDef, ttTypeRef, ttModuleRef, ttMethodDef, ttTypeSpec};
|
|
const ILTokenType has_constant_types[] = {ttField, ttParam, ttProperty};
|
|
const ILTokenType custom_attribute_types[] = {ttInvalid, ttInvalid, ttMethodDef, ttMemberRef};
|
|
const ILTokenType has_custom_attribute_types[] = {ttMethodDef, ttField, ttTypeRef, ttTypeDef, ttParam, ttInterfaceImpl, ttMemberRef, ttModule, ttDeclSecurity,
|
|
ttProperty, ttEvent, ttStandAloneSig, ttModuleRef, ttTypeSpec, ttAssembly, ttAssemblyRef, ttFile, ttExportedType,
|
|
ttManifestResource, ttGenericParam, ttGenericParamConstraint, ttMethodSpec};
|
|
const ILTokenType has_decl_security_types[] = {ttTypeDef, ttMethodDef, ttAssembly};
|
|
|
|
const EncodingDesc ResolutionScope = EncodingDesc(resolution_scope_types, _countof(resolution_scope_types), 2);
|
|
const EncodingDesc TypeDefRef = EncodingDesc(typedef_ref_types, _countof(typedef_ref_types), 2);
|
|
const EncodingDesc TypeMethodDef = EncodingDesc(type_or_methoddef_types, _countof(type_or_methoddef_types), 1);
|
|
const EncodingDesc HasSemantics = EncodingDesc(has_semantics_types, _countof(has_semantics_types), 1);
|
|
const EncodingDesc MethodDefRef = EncodingDesc(methoddef_ref_types, _countof(methoddef_ref_types), 1);
|
|
const EncodingDesc MemberForwarded = EncodingDesc(member_forwarded_types, _countof(member_forwarded_types), 1);
|
|
const EncodingDesc HasFieldMarshal = EncodingDesc(has_field_marshal_types, _countof(has_field_marshal_types), 1);
|
|
const EncodingDesc Implementation = EncodingDesc(implementation_types, _countof(implementation_types), 2);
|
|
const EncodingDesc MemberRefParent = EncodingDesc(member_ref_parent_types, _countof(member_ref_parent_types), 3);
|
|
const EncodingDesc HasConstant = EncodingDesc(has_constant_types, _countof(has_constant_types), 2);
|
|
const EncodingDesc CustomAttribute = EncodingDesc(custom_attribute_types, _countof(custom_attribute_types), 3);
|
|
const EncodingDesc HasCustomAttribute = EncodingDesc(has_custom_attribute_types, _countof(has_custom_attribute_types), 5);
|
|
const EncodingDesc HasDeclSecurity = EncodingDesc(has_decl_security_types, _countof(has_decl_security_types), 2);
|
|
|
|
/**
|
|
* ILToken
|
|
*/
|
|
|
|
ILToken::ILToken(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: IObject(), meta_(meta), owner_(owner), id_(id), is_deleted_(false), can_rename_(true)
|
|
{
|
|
reference_list_ = new TokenReferenceList(this);
|
|
}
|
|
|
|
ILToken::ILToken(ILMetaData *meta, ILTable *owner, const ILToken &src)
|
|
: IObject(), meta_(meta), owner_(owner)
|
|
{
|
|
id_ = src.id_;
|
|
is_deleted_ = src.is_deleted_;
|
|
can_rename_ = src.can_rename_;
|
|
reference_list_ = src.reference_list_->Clone(this);
|
|
}
|
|
|
|
ILToken::~ILToken()
|
|
{
|
|
if (owner_)
|
|
owner_->RemoveObject(this);
|
|
delete reference_list_;
|
|
}
|
|
|
|
ILToken *ILToken::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILToken *token = new ILToken(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILToken::set_value(uint32_t value, IArchitecture *file)
|
|
{
|
|
if (value == this->value())
|
|
return;
|
|
|
|
id_ = TOKEN_TYPE(id_) | TOKEN_VALUE(value);
|
|
if (file) {
|
|
for (size_t i = 0; i < reference_list_->count(); i++) {
|
|
TokenReference *reference = reference_list_->item(i);
|
|
if (reference->is_deleted() || !reference->address())
|
|
continue;
|
|
|
|
if (!file->AddressSeek(reference->address()))
|
|
throw std::runtime_error("Invalid reference address");
|
|
file->WriteDWord(id_);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ILToken::set_owner(ILMetaData *meta, ILTable *owner)
|
|
{
|
|
meta_ = meta;
|
|
if (owner == owner_)
|
|
return;
|
|
if (owner_)
|
|
owner_->RemoveObject(this);
|
|
owner_ = owner;
|
|
if (owner_)
|
|
owner_->AddObject(this);
|
|
}
|
|
|
|
ILToken *ILToken::next() const
|
|
{
|
|
return meta_->token(id() + 1);
|
|
}
|
|
|
|
std::string ILToken::ReadStringFromFile(NETArchitecture &file) const
|
|
{
|
|
uint32_t value = (meta_->string_field_size() == sizeof(uint16_t)) ? file.ReadWord() : file.ReadDWord();
|
|
return meta_->GetString(value);
|
|
}
|
|
|
|
std::string ILToken::ReadUserString(uint32_t value) const
|
|
{
|
|
return meta_->GetUserString(value);
|
|
}
|
|
|
|
ILData ILToken::ReadBlobFromFile(NETArchitecture &file) const
|
|
{
|
|
uint32_t value = (meta_->blob_field_size() == sizeof(uint16_t)) ? file.ReadWord() : file.ReadDWord();
|
|
return meta_->GetBlob(value);
|
|
}
|
|
|
|
ILData ILToken::ReadGUIDFromFile(NETArchitecture &file) const
|
|
{
|
|
std::string res;
|
|
uint32_t value = (meta_->guid_field_size() == sizeof(uint16_t)) ? file.ReadWord() : file.ReadDWord();
|
|
return meta_->GetGuid(value);
|
|
}
|
|
|
|
ILToken *ILToken::ReadTokenFromFile(NETArchitecture &file, const EncodingDesc &desc) const
|
|
{
|
|
uint32_t value = (meta_->field_size(desc) == sizeof(uint16_t)) ? file.ReadWord() : file.ReadDWord();
|
|
size_t i = (value & ((1 << desc.bits) - 1));
|
|
if (i >= desc.size || desc.types[i] == ttInvalid)
|
|
throw std::runtime_error("Unknown ref type");
|
|
return meta_->token(desc.types[i] | (value >> desc.bits));
|
|
}
|
|
|
|
ILToken *ILToken::ReadTokenFromFile(NETArchitecture &file, ILTokenType type) const
|
|
{
|
|
uint32_t value = (meta_->field_size(type) == sizeof(uint16_t)) ? file.ReadWord() : file.ReadDWord();
|
|
return meta_->token(type | value);
|
|
}
|
|
|
|
void ILToken::WriteStringToFile(NETArchitecture &file, uint32_t pos) const
|
|
{
|
|
if (meta_->string_field_size() == sizeof(uint16_t))
|
|
file.WriteWord(static_cast<uint16_t>(pos));
|
|
else
|
|
file.WriteDWord(pos);
|
|
}
|
|
|
|
void ILToken::WriteGuidToFile(NETArchitecture &file, uint32_t pos) const
|
|
{
|
|
if (meta_->guid_field_size() == sizeof(uint16_t))
|
|
file.WriteWord(static_cast<uint16_t>(pos));
|
|
else
|
|
file.WriteDWord(pos);
|
|
}
|
|
|
|
void ILToken::WriteBlobToFile(NETArchitecture &file, uint32_t pos) const
|
|
{
|
|
if (meta_->blob_field_size() == sizeof(uint16_t))
|
|
file.WriteWord(static_cast<uint16_t>(pos));
|
|
else
|
|
file.WriteDWord(pos);
|
|
}
|
|
|
|
void ILToken::WriteTokenToFile(NETArchitecture &file, ILTokenType type, ILToken *token) const
|
|
{
|
|
uint32_t value = token ? token->value() : 0;
|
|
if (meta_->field_size(type) == sizeof(uint16_t))
|
|
file.WriteWord(static_cast<uint16_t>(value));
|
|
else
|
|
file.WriteDWord(value);
|
|
}
|
|
|
|
void ILToken::WriteTokenListToFile(NETArchitecture &file, ILTokenType type, ILToken *token) const
|
|
{
|
|
uint32_t value = token ? token->value() : static_cast<uint32_t>(meta_->table(type)->count() + 1);
|
|
if (meta_->field_size(type) == sizeof(uint16_t))
|
|
file.WriteWord(static_cast<uint16_t>(value));
|
|
else
|
|
file.WriteDWord(value);
|
|
}
|
|
|
|
uint32_t ILToken::Encode(const EncodingDesc &desc) const
|
|
{
|
|
uint32_t res = value() << desc.bits;
|
|
for (size_t i = 0; i < desc.size; i++) {
|
|
if (type() == desc.types[i]) {
|
|
res |= i;
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void ILToken::WriteTokenToFile(NETArchitecture &file, const EncodingDesc &desc, ILToken *token) const
|
|
{
|
|
uint32_t value = token ? token->Encode(desc) : 0;
|
|
if (meta_->field_size(desc) == sizeof(uint16_t))
|
|
file.WriteWord(static_cast<uint16_t>(value));
|
|
else
|
|
file.WriteDWord(value);
|
|
}
|
|
|
|
void ILToken::Rebase(uint64_t delta_base)
|
|
{
|
|
reference_list_->Rebase(delta_base);
|
|
}
|
|
|
|
int ILToken::CompareWith(const ILToken &other) const
|
|
{
|
|
throw std::runtime_error("Abstract error");
|
|
}
|
|
|
|
/**
|
|
* ILAssembly
|
|
*/
|
|
|
|
ILAssembly::ILAssembly(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), hash_id_(0), major_version_(0), minor_version_(0), build_number_(0), revision_number_(0), flags_(0),
|
|
name_pos_(0), public_key_pos_(0), culture_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILAssembly::ILAssembly(ILMetaData *meta, ILTable *owner, const std::string &name)
|
|
: ILToken(meta, owner, ttAssembly), hash_id_(0), major_version_(0), minor_version_(0), build_number_(0), revision_number_(0), flags_(0),
|
|
name_pos_(0), public_key_pos_(0), culture_pos_(0), name_(name)
|
|
{
|
|
|
|
}
|
|
|
|
ILAssembly::ILAssembly(ILMetaData *meta, ILTable *owner, const ILAssembly &src)
|
|
: ILToken(meta, owner, src), name_pos_(0), public_key_pos_(0), culture_pos_(0)
|
|
{
|
|
hash_id_ = src.hash_id_;
|
|
major_version_ = src.major_version_;
|
|
minor_version_ = src.minor_version_;
|
|
build_number_ = src.build_number_;
|
|
revision_number_ = src.revision_number_;
|
|
flags_ = src.flags_;
|
|
public_key_ = src.public_key_;
|
|
name_ = src.name_;
|
|
culture_ = src.culture_;
|
|
}
|
|
|
|
ILToken *ILAssembly::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILAssembly *token = new ILAssembly(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILAssembly::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
hash_id_ = file.ReadDWord();
|
|
major_version_ = file.ReadWord();
|
|
minor_version_ = file.ReadWord();
|
|
build_number_ = file.ReadWord();
|
|
revision_number_ = file.ReadWord();
|
|
flags_ = file.ReadDWord();
|
|
public_key_ = ReadBlobFromFile(file);
|
|
name_ = ReadStringFromFile(file);
|
|
culture_ = ReadStringFromFile(file);
|
|
}
|
|
|
|
void ILAssembly::WriteToStreams(ILMetaData &data)
|
|
{
|
|
public_key_pos_ = data.AddBlob(public_key_);
|
|
name_pos_ = data.AddString(name_);
|
|
culture_pos_ = data.AddString(culture_);
|
|
}
|
|
|
|
void ILAssembly::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(hash_id_);
|
|
file.WriteWord(major_version_);
|
|
file.WriteWord(minor_version_);
|
|
file.WriteWord(build_number_);
|
|
file.WriteWord(revision_number_);
|
|
file.WriteDWord(flags_);
|
|
WriteBlobToFile(file,public_key_pos_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteStringToFile(file, culture_pos_);
|
|
}
|
|
|
|
std::string ILAssembly::full_name() const
|
|
{
|
|
std::string res = name_;
|
|
res += ", Version=" + string_format("%d.%d.%d.%d", major_version_, minor_version_, build_number_, revision_number_);
|
|
res += ", Culture=" + (!culture_.empty() ? culture_ : "neutral");
|
|
res += ", PublicKeyToken=";
|
|
if (public_key_.empty())
|
|
res += "null";
|
|
else {
|
|
SHA1 sha;
|
|
sha.Input(public_key_.data(), public_key_.size());
|
|
const uint8_t *p = sha.Result();
|
|
for (size_t i = 0; i < 8; i++) {
|
|
res += string_format("%.2x", p[sha.ResultSize() - 1 - i]);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* ILAssemblyOS
|
|
*/
|
|
|
|
ILAssemblyOS::ILAssemblyOS(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), os_platform_id_(0), os_major_version_(0), os_minor_version_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void ILAssemblyOS::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
os_platform_id_ = file.ReadDWord();
|
|
os_major_version_ = file.ReadDWord();
|
|
os_minor_version_ = file.ReadDWord();
|
|
}
|
|
|
|
void ILAssemblyOS::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(os_platform_id_);
|
|
file.WriteDWord(os_major_version_);
|
|
file.WriteDWord(os_minor_version_);
|
|
}
|
|
|
|
/**
|
|
* ILAssemblyProcessor
|
|
*/
|
|
|
|
ILAssemblyProcessor::ILAssemblyProcessor(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), processor_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void ILAssemblyProcessor::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
processor_ = file.ReadDWord();
|
|
}
|
|
|
|
void ILAssemblyProcessor::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(processor_);
|
|
}
|
|
|
|
/**
|
|
* ILAssemblyRef
|
|
*/
|
|
|
|
ILAssemblyRef::ILAssemblyRef(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), major_version_(0), minor_version_(0), build_number_(0), revision_number_(0), flags_(0), name_pos_(0),
|
|
public_key_or_token_pos_(0), culture_pos_(0), hash_value_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILAssemblyRef::ILAssemblyRef(ILMetaData *meta, ILTable *owner, const std::string &name)
|
|
: ILToken(meta, owner, ttAssemblyRef), major_version_(0), minor_version_(0), build_number_(0), revision_number_(0), flags_(0), name_pos_(0),
|
|
public_key_or_token_pos_(0), culture_pos_(0), hash_value_pos_(0), name_(name)
|
|
{
|
|
|
|
}
|
|
|
|
ILAssemblyRef::ILAssemblyRef(ILMetaData *meta, ILTable *owner, const ILAssemblyRef &src)
|
|
: ILToken(meta, owner, src), name_pos_(0), public_key_or_token_pos_(0), culture_pos_(0), hash_value_pos_(0)
|
|
{
|
|
major_version_ = src.major_version_;
|
|
minor_version_ = src.minor_version_;
|
|
build_number_ = src.build_number_;
|
|
revision_number_ = src.revision_number_;
|
|
flags_ = src.flags_;
|
|
public_key_or_token_ = src.public_key_or_token_;
|
|
name_ = src.name_;
|
|
culture_ = src.culture_;
|
|
hash_value_ = src.hash_value_;
|
|
}
|
|
|
|
ILToken *ILAssemblyRef::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILAssemblyRef *token = new ILAssemblyRef(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILAssemblyRef::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
major_version_ = file.ReadWord();
|
|
minor_version_ = file.ReadWord();
|
|
build_number_ = file.ReadWord();
|
|
revision_number_ = file.ReadWord();
|
|
flags_ = file.ReadDWord();
|
|
public_key_or_token_ = ReadBlobFromFile(file);
|
|
name_ = ReadStringFromFile(file);
|
|
culture_ = ReadStringFromFile(file);
|
|
hash_value_ = ReadBlobFromFile(file);
|
|
}
|
|
|
|
void ILAssemblyRef::WriteToStreams(ILMetaData &data)
|
|
{
|
|
public_key_or_token_pos_ = data.AddBlob(public_key_or_token_);
|
|
name_pos_ = data.AddString(name_);
|
|
culture_pos_ = data.AddString(culture_);
|
|
hash_value_pos_ = data.AddBlob(hash_value_);
|
|
}
|
|
|
|
void ILAssemblyRef::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(major_version_);
|
|
file.WriteWord(minor_version_);
|
|
file.WriteWord(build_number_);
|
|
file.WriteWord(revision_number_);
|
|
file.WriteDWord(flags_);
|
|
WriteBlobToFile(file, public_key_or_token_pos_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteStringToFile(file, culture_pos_);
|
|
WriteBlobToFile(file, hash_value_pos_);
|
|
}
|
|
|
|
std::string ILAssemblyRef::full_name() const
|
|
{
|
|
std::string res = name_;
|
|
res += ", Version=" + string_format("%d.%d.%d.%d", major_version_, minor_version_, build_number_, revision_number_);
|
|
res += ", Culture=" + (!culture_.empty() ? culture_ : "neutral");
|
|
res += ", PublicKeyToken=";
|
|
if (public_key_or_token_.empty())
|
|
res += "null";
|
|
else {
|
|
if (flags_ & afPublicKey) {
|
|
SHA1 sha;
|
|
sha.Input(public_key_or_token_.data(), public_key_or_token_.size());
|
|
const uint8_t *p = sha.Result();
|
|
for (size_t i = 0; i < 8; i++) {
|
|
res += string_format("%.2x", p[sha.ResultSize() - 1 - i]);
|
|
}
|
|
}
|
|
else {
|
|
for (size_t i = 0; i < public_key_or_token_.size(); i++) {
|
|
res += string_format("%.2x", public_key_or_token_[i]);
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* ILAssemblyRefOS
|
|
*/
|
|
|
|
ILAssemblyRefOS::ILAssemblyRefOS(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), os_platform_id_(0), os_major_version_(0), os_minor_version_(0), assembly_ref_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void ILAssemblyRefOS::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
os_platform_id_ = file.ReadDWord();
|
|
os_major_version_ = file.ReadDWord();
|
|
os_minor_version_ = file.ReadDWord();
|
|
assembly_ref_ = reinterpret_cast<ILAssemblyRef *>(ReadTokenFromFile(file, ttAssemblyRef));
|
|
}
|
|
|
|
void ILAssemblyRefOS::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(os_platform_id_);
|
|
file.WriteDWord(os_major_version_);
|
|
file.WriteDWord(os_minor_version_);
|
|
WriteTokenToFile(file, ttAssemblyRef, assembly_ref_);
|
|
}
|
|
|
|
void ILAssemblyRefOS::UpdateTokens()
|
|
{
|
|
if (assembly_ref_)
|
|
assembly_ref_ = reinterpret_cast<ILAssemblyRef *>(meta()->token(assembly_ref_->id()));
|
|
}
|
|
|
|
/**
|
|
* ILAssemblyRefProcessor
|
|
*/
|
|
|
|
ILAssemblyRefProcessor::ILAssemblyRefProcessor(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), processor_(0), assembly_ref_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void ILAssemblyRefProcessor::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
processor_ = file.ReadDWord();
|
|
assembly_ref_ = reinterpret_cast<ILAssemblyRef *>(ReadTokenFromFile(file, ttAssemblyRef));
|
|
}
|
|
|
|
void ILAssemblyRefProcessor::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(processor_);
|
|
WriteTokenToFile(file, ttAssemblyRef, assembly_ref_);
|
|
}
|
|
|
|
void ILAssemblyRefProcessor::UpdateTokens()
|
|
{
|
|
if (assembly_ref_)
|
|
assembly_ref_ = reinterpret_cast<ILAssemblyRef *>(meta()->token(assembly_ref_->id()));
|
|
}
|
|
|
|
/**
|
|
* ILClassLayout
|
|
*/
|
|
|
|
ILClassLayout::ILClassLayout(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), packing_size_(0), class_size_(0), parent_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILClassLayout::ILClassLayout(ILMetaData *meta, ILTable *owner, const ILClassLayout &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
packing_size_ = src.packing_size_;
|
|
class_size_ = src.class_size_;
|
|
parent_ = src.parent_;
|
|
}
|
|
|
|
ILToken *ILClassLayout::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILClassLayout *token = new ILClassLayout(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILClassLayout::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
packing_size_ = file.ReadWord();
|
|
class_size_ = file.ReadDWord();
|
|
parent_ = reinterpret_cast<ILTypeDef *>(ReadTokenFromFile(file, ttTypeDef));
|
|
}
|
|
|
|
void ILClassLayout::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(packing_size_);
|
|
file.WriteDWord(class_size_);
|
|
WriteTokenToFile(file, ttTypeDef, parent_);
|
|
}
|
|
|
|
void ILClassLayout::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = reinterpret_cast<ILTypeDef *>(meta()->token(parent_->id()));
|
|
}
|
|
|
|
void ILClassLayout::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(parent_);
|
|
if (it != token_map.end()) {
|
|
parent_ = reinterpret_cast<ILTypeDef *>(it->second);
|
|
if (!parent_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ILConstant
|
|
*/
|
|
|
|
ILConstant::ILConstant(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), type_(0), padding_zero_(0), parent_(NULL), value_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILConstant::ILConstant(ILMetaData *meta, ILTable *owner, const ILConstant &src)
|
|
: ILToken(meta, owner, src), value_pos_(0)
|
|
{
|
|
type_ = src.type_;
|
|
padding_zero_ = src.padding_zero_;
|
|
parent_ = src.parent_;
|
|
value_ = src.value_;
|
|
}
|
|
|
|
ILToken *ILConstant::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILConstant *token = new ILConstant(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILConstant::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
type_ = file.ReadByte();
|
|
padding_zero_ = file.ReadByte();
|
|
parent_ = ReadTokenFromFile(file, HasConstant);
|
|
value_ = ReadBlobFromFile(file);
|
|
}
|
|
|
|
void ILConstant::WriteToStreams(ILMetaData &data)
|
|
{
|
|
value_pos_ = data.AddBlob(value_);
|
|
}
|
|
|
|
void ILConstant::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteByte(type_);
|
|
file.WriteByte(padding_zero_);
|
|
WriteTokenToFile(file, HasConstant, parent_);
|
|
WriteBlobToFile(file, value_pos_);
|
|
}
|
|
|
|
void ILConstant::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = meta()->token(parent_->id());
|
|
}
|
|
|
|
void ILConstant::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(parent_);
|
|
if (it != token_map.end()) {
|
|
parent_ = it->second;
|
|
if (!parent_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
int ILConstant::CompareWith(const ILToken &other) const
|
|
{
|
|
if (other.type() == ttConstant) {
|
|
const ILConstant &obj = reinterpret_cast<const ILConstant &>(other);
|
|
uint32_t self_value = parent_ ? parent_->Encode(HasConstant) : 0;
|
|
uint32_t other_value = obj.parent_ ? obj.parent_->Encode(HasConstant) : 0;
|
|
if (self_value < other_value)
|
|
return -1;
|
|
if (self_value > other_value)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
return ILToken::CompareWith(other);
|
|
}
|
|
|
|
/**
|
|
* ILCustomAttribute
|
|
*/
|
|
|
|
ILCustomAttribute::ILCustomAttribute(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), parent_(NULL), type_(NULL), value_pos_(0)
|
|
{
|
|
parser_ = new CustomAttributeValue(meta);
|
|
}
|
|
|
|
ILCustomAttribute::ILCustomAttribute(ILMetaData *meta, ILTable *owner, const ILCustomAttribute &src)
|
|
: ILToken(meta, owner, src), value_pos_(0)
|
|
{
|
|
parser_ = new CustomAttributeValue(meta);
|
|
|
|
parent_ = src.parent_;
|
|
type_ = src.type_;
|
|
value_ = src.value_;
|
|
}
|
|
|
|
ILCustomAttribute::~ILCustomAttribute()
|
|
{
|
|
delete parser_;
|
|
}
|
|
|
|
ILToken *ILCustomAttribute::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILCustomAttribute *token = new ILCustomAttribute(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILCustomAttribute::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
parent_ = ReadTokenFromFile(file, HasCustomAttribute);
|
|
type_ = ReadTokenFromFile(file, CustomAttribute);
|
|
value_ = ReadBlobFromFile(file);
|
|
}
|
|
|
|
void ILCustomAttribute::WriteToStreams(ILMetaData &data)
|
|
{
|
|
value_pos_ = data.AddBlob(value_);
|
|
}
|
|
|
|
void ILCustomAttribute::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, HasCustomAttribute, parent_);
|
|
WriteTokenToFile(file, CustomAttribute, type_);
|
|
WriteBlobToFile(file, value_pos_);
|
|
}
|
|
|
|
void ILCustomAttribute::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = meta()->token(parent_->id());
|
|
if (type_)
|
|
type_ = meta()->token(type_->id());
|
|
}
|
|
|
|
void ILCustomAttribute::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(parent_);
|
|
if (it != token_map.end()) {
|
|
parent_ = it->second;
|
|
if (!parent_)
|
|
set_deleted(true);
|
|
}
|
|
it = token_map.find(type_);
|
|
if (it != token_map.end()) {
|
|
type_ = it->second;
|
|
if (!type_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
int ILCustomAttribute::CompareWith(const ILToken &other) const
|
|
{
|
|
if (other.type() == ttCustomAttribute) {
|
|
const ILCustomAttribute &obj = reinterpret_cast<const ILCustomAttribute &>(other);
|
|
uint32_t self_value = parent_ ? parent_->Encode(HasCustomAttribute) : 0;
|
|
uint32_t other_value = obj.parent_ ? obj.parent_->Encode(HasCustomAttribute) : 0;
|
|
if (self_value < other_value)
|
|
return -1;
|
|
if (self_value > other_value)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
return ILToken::CompareWith(other);
|
|
}
|
|
|
|
CustomAttributeValue *ILCustomAttribute::ParseValue() const
|
|
{
|
|
parser_->Parse(type_, value_);
|
|
return parser_;
|
|
}
|
|
|
|
void ILCustomAttribute::UpdateValue()
|
|
{
|
|
value_.clear();
|
|
parser_->Write(value_);
|
|
}
|
|
|
|
/**
|
|
* ILDeclSecurity
|
|
*/
|
|
|
|
ILDeclSecurity::ILDeclSecurity(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), action_(0), parent_(NULL), permission_set_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILDeclSecurity::ILDeclSecurity(ILMetaData *meta, ILTable *owner, const ILDeclSecurity &src)
|
|
: ILToken(meta, owner, src), permission_set_pos_(0)
|
|
{
|
|
action_ = src.action_;
|
|
parent_ = src.parent_;
|
|
permission_set_ = src.permission_set_;
|
|
}
|
|
|
|
ILToken *ILDeclSecurity::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILDeclSecurity *token = new ILDeclSecurity(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILDeclSecurity::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
action_ = file.ReadWord();
|
|
parent_ = ReadTokenFromFile(file, HasDeclSecurity);
|
|
permission_set_ = ReadBlobFromFile(file);
|
|
}
|
|
|
|
void ILDeclSecurity::WriteToStreams(ILMetaData &data)
|
|
{
|
|
permission_set_pos_ = data.AddBlob(permission_set_);
|
|
}
|
|
|
|
void ILDeclSecurity::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(action_);
|
|
WriteTokenToFile(file, HasDeclSecurity, parent_);
|
|
WriteBlobToFile(file, permission_set_pos_);
|
|
}
|
|
|
|
void ILDeclSecurity::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = meta()->token(parent_->id());
|
|
}
|
|
|
|
/**
|
|
* ILEvent
|
|
*/
|
|
|
|
ILEvent::ILEvent(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), flags_(0), parent_(NULL), name_pos_(0), declaring_type_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
ILEvent::ILEvent(ILMetaData *meta, ILTable *owner, const ILEvent &src)
|
|
: ILToken(meta, owner, src), name_pos_(0)
|
|
{
|
|
flags_ = src.flags_;
|
|
name_ = src.name_;
|
|
parent_ = src.parent_;
|
|
declaring_type_ = src.declaring_type_;
|
|
}
|
|
|
|
ILToken *ILEvent::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILEvent *token = new ILEvent(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILEvent::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
flags_ = file.ReadWord();
|
|
name_ = ReadStringFromFile(file);
|
|
parent_ = ReadTokenFromFile(file, TypeDefRef);
|
|
}
|
|
|
|
void ILEvent::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
}
|
|
|
|
void ILEvent::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(flags_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteTokenToFile(file, TypeDefRef, parent_);
|
|
}
|
|
|
|
void ILEvent::UpdateTokens()
|
|
{
|
|
if (declaring_type_)
|
|
declaring_type_ = reinterpret_cast<ILTypeDef *>(meta()->token(declaring_type_->id()));
|
|
if (parent_)
|
|
parent_ = meta()->token(parent_->id());
|
|
}
|
|
|
|
void ILEvent::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(declaring_type_);
|
|
if (it != token_map.end()) {
|
|
declaring_type_ = reinterpret_cast<ILTypeDef *>(it->second);
|
|
if (!declaring_type_)
|
|
set_deleted(true);
|
|
}
|
|
|
|
it = token_map.find(parent_);
|
|
if (it != token_map.end()) {
|
|
parent_ = reinterpret_cast<ILTypeDef *>(it->second);
|
|
if (!parent_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
bool ILEvent::is_exported() const
|
|
{
|
|
return parent_->is_exported();
|
|
}
|
|
|
|
/**
|
|
* ILEventMap
|
|
*/
|
|
|
|
ILEventMap::ILEventMap(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), parent_(0), event_list_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILEventMap::ILEventMap(ILMetaData *meta, ILTable *owner, const ILEventMap &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
parent_ = src.parent_;
|
|
event_list_ = src.event_list_;
|
|
}
|
|
|
|
ILToken *ILEventMap::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILEventMap *token = new ILEventMap(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILEventMap::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
parent_ = reinterpret_cast<ILTypeDef *>(ReadTokenFromFile(file, ttTypeDef));
|
|
event_list_ = reinterpret_cast<ILEvent *>(ReadTokenFromFile(file, ttEvent));
|
|
}
|
|
|
|
void ILEventMap::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, ttTypeDef, parent_);
|
|
|
|
ILEvent *event_list = NULL;
|
|
for (ILEventMap *src = this; src != NULL && event_list == NULL; src = src->next())
|
|
event_list = src->event_list_;
|
|
WriteTokenListToFile(file, ttEvent, event_list);
|
|
}
|
|
|
|
void ILEventMap::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = reinterpret_cast<ILTypeDef *>(meta()->token(parent_->id()));
|
|
if (event_list_)
|
|
event_list_ = reinterpret_cast<ILEvent *>(meta()->token(event_list_->id()));
|
|
}
|
|
|
|
/**
|
|
* ILField
|
|
*/
|
|
|
|
ILField::ILField(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), flags_(0), declaring_type_(NULL), signature_pos_(0), name_pos_(0)
|
|
{
|
|
signature_ = new ILSignature(meta);
|
|
}
|
|
|
|
ILField::ILField(ILMetaData *meta, ILTable *owner, const ILField &src)
|
|
: ILToken(meta, owner, src), signature_pos_(0), name_pos_(0)
|
|
{
|
|
flags_ = src.flags_;
|
|
name_ = src.name_;
|
|
declaring_type_ = src.declaring_type_;
|
|
signature_ = src.signature_->Clone(meta);
|
|
}
|
|
|
|
ILField::~ILField()
|
|
{
|
|
delete signature_;
|
|
}
|
|
|
|
ILToken *ILField::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILField *token = new ILField(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILField::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
flags_ = file.ReadWord();
|
|
name_ = ReadStringFromFile(file);
|
|
signature_->Parse(ReadBlobFromFile(file));
|
|
}
|
|
|
|
void ILField::UpdateTokens()
|
|
{
|
|
if (declaring_type_)
|
|
declaring_type_ = reinterpret_cast<ILTypeDef *>(meta()->token(declaring_type_->id()));
|
|
|
|
signature_->UpdateTokens();
|
|
}
|
|
|
|
void ILField::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(declaring_type_);
|
|
if (it != token_map.end()) {
|
|
declaring_type_ = reinterpret_cast<ILTypeDef *>(it->second);
|
|
if (!declaring_type_)
|
|
set_deleted(true);
|
|
}
|
|
signature_->RemapTokens(token_map);
|
|
}
|
|
|
|
void ILField::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
signature_pos_ = data.AddBlob(signature_->data());
|
|
}
|
|
|
|
void ILField::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(flags_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteBlobToFile(file, signature_pos_);
|
|
}
|
|
|
|
bool ILField::is_exported() const
|
|
{
|
|
if (declaring_type_->is_exported()) {
|
|
switch (flags_ & fdFieldAccessMask) {
|
|
case fdFamily:
|
|
case fdFamORAssem:
|
|
case fdPublic:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
std::string ILField::full_name(bool mode) const
|
|
{
|
|
return ILName(signature_->ret_name(mode), declaring_type_ ? declaring_type_->full_name() : "<NULL>", name_, "");
|
|
}
|
|
|
|
/**
|
|
* ILFieldLayout
|
|
*/
|
|
|
|
ILFieldLayout::ILFieldLayout(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), offset_(0), field_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
ILFieldLayout::ILFieldLayout(ILMetaData *meta, ILTable *owner, const ILFieldLayout &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
offset_ = src.offset_;
|
|
field_ = src.field_;
|
|
}
|
|
|
|
ILToken *ILFieldLayout::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILFieldLayout *token = new ILFieldLayout(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILFieldLayout::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
offset_ = file.ReadDWord();
|
|
field_ = reinterpret_cast<ILField *>(ReadTokenFromFile(file, ttField));
|
|
}
|
|
|
|
void ILFieldLayout::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(offset_);
|
|
WriteTokenToFile(file, ttField, field_);
|
|
}
|
|
|
|
void ILFieldLayout::UpdateTokens()
|
|
{
|
|
if (field_)
|
|
field_ = reinterpret_cast<ILField *>(meta()->token(field_->id()));
|
|
}
|
|
|
|
void ILFieldLayout::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(field_);
|
|
if (it != token_map.end()) {
|
|
field_ = reinterpret_cast<ILField *>(it->second);
|
|
if (!field_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ILFieldMarshal
|
|
*/
|
|
|
|
ILFieldMarshal::ILFieldMarshal(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), parent_(NULL), native_type_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILFieldMarshal::ILFieldMarshal(ILMetaData *meta, ILTable *owner, const ILFieldMarshal &src)
|
|
: ILToken(meta, owner, src), native_type_pos_(0)
|
|
{
|
|
parent_ = src.parent_;
|
|
native_type_ = src.native_type_;
|
|
}
|
|
|
|
ILToken *ILFieldMarshal::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILFieldMarshal *token = new ILFieldMarshal(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILFieldMarshal::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
parent_ = ReadTokenFromFile(file, HasFieldMarshal);
|
|
native_type_ = ReadBlobFromFile(file);
|
|
}
|
|
|
|
void ILFieldMarshal::WriteToStreams(ILMetaData &data)
|
|
{
|
|
native_type_pos_ = data.AddBlob(native_type_);
|
|
}
|
|
|
|
void ILFieldMarshal::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, HasFieldMarshal, parent_);
|
|
WriteBlobToFile(file, native_type_pos_);
|
|
}
|
|
|
|
void ILFieldMarshal::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = meta()->token(parent_->id());
|
|
}
|
|
|
|
/**
|
|
* ILFieldRVA
|
|
*/
|
|
|
|
ILFieldRVA::ILFieldRVA(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), address_(0), field_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
ILFieldRVA::ILFieldRVA(ILMetaData *meta, ILTable *owner, const ILFieldRVA &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
address_ = src.address_;
|
|
field_ = src.field_;
|
|
}
|
|
|
|
ILToken *ILFieldRVA::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILFieldRVA *token = new ILFieldRVA(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILFieldRVA::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
address_ = file.ReadDWord() + file.image_base();
|
|
field_ = reinterpret_cast<ILField *>(ReadTokenFromFile(file, ttField));
|
|
}
|
|
|
|
void ILFieldRVA::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(static_cast<uint32_t>(address_ - file.image_base()));
|
|
WriteTokenToFile(file, ttField, field_);
|
|
}
|
|
|
|
void ILFieldRVA::UpdateTokens()
|
|
{
|
|
if (field_)
|
|
field_ = reinterpret_cast<ILField *>(meta()->token(field_->id()));
|
|
}
|
|
|
|
void ILFieldRVA::Rebase(uint64_t delta_base)
|
|
{
|
|
ILToken::Rebase(delta_base);
|
|
|
|
address_ += delta_base;
|
|
}
|
|
|
|
void ILFieldRVA::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(field_);
|
|
if (it != token_map.end()) {
|
|
field_ = reinterpret_cast<ILField *>(it->second);
|
|
if (!field_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ILFile
|
|
*/
|
|
|
|
ILFile::ILFile(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), flags_(0), name_pos_(0), value_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void ILFile::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
flags_ = file.ReadDWord();
|
|
name_ = ReadStringFromFile(file);
|
|
value_ = ReadBlobFromFile(file);
|
|
}
|
|
|
|
void ILFile::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
value_pos_ = data.AddBlob(value_);
|
|
}
|
|
|
|
void ILFile::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(flags_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteBlobToFile(file, value_pos_);
|
|
}
|
|
|
|
/**
|
|
* ILGenericParam
|
|
*/
|
|
|
|
ILGenericParam::ILGenericParam(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), number_(0), flags_(0), parent_(NULL), name_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILGenericParam::ILGenericParam(ILMetaData *meta, ILTable *owner, const ILGenericParam &src)
|
|
: ILToken(meta, owner, src), name_pos_(0)
|
|
{
|
|
number_ = src.number_;
|
|
flags_ = src.flags_;
|
|
parent_ = src.parent_;
|
|
name_ = src.name_;
|
|
}
|
|
|
|
ILToken *ILGenericParam::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILGenericParam *token = new ILGenericParam(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILGenericParam::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
number_ = file.ReadWord();
|
|
flags_ = file.ReadWord();
|
|
parent_ = ReadTokenFromFile(file, TypeMethodDef);
|
|
name_ = ReadStringFromFile(file);
|
|
}
|
|
|
|
void ILGenericParam::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
}
|
|
|
|
void ILGenericParam::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(number_);
|
|
file.WriteWord(flags_);
|
|
WriteTokenToFile(file, TypeMethodDef, parent_);
|
|
WriteStringToFile(file, name_pos_);
|
|
}
|
|
|
|
void ILGenericParam::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = meta()->token(parent_->id());
|
|
}
|
|
|
|
void ILGenericParam::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(parent_);
|
|
if (it != token_map.end()) {
|
|
parent_ = it->second;
|
|
if (!parent_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
int ILGenericParam::CompareWith(const ILToken &other) const
|
|
{
|
|
if (other.type() == ttGenericParam) {
|
|
const ILGenericParam &obj = reinterpret_cast<const ILGenericParam &>(other);
|
|
uint32_t self_value = parent_ ? parent_->Encode(TypeMethodDef) : 0;
|
|
uint32_t other_value = obj.parent_ ? obj.parent_->Encode(TypeMethodDef) : 0;
|
|
if (self_value < other_value)
|
|
return -1;
|
|
if (self_value > other_value)
|
|
return 1;
|
|
|
|
if (number_ < obj.number_)
|
|
return -1;
|
|
if (number_ > obj.number_)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
return ILToken::CompareWith(other);
|
|
}
|
|
|
|
/**
|
|
* ILGenericParamConstraint
|
|
*/
|
|
|
|
ILGenericParamConstraint::ILGenericParamConstraint(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), parent_(0), constraint_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILGenericParamConstraint::ILGenericParamConstraint(ILMetaData *meta, ILTable *owner, const ILGenericParamConstraint &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
parent_ = src.parent_;
|
|
constraint_ = src.constraint_;
|
|
}
|
|
|
|
ILToken *ILGenericParamConstraint::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILGenericParamConstraint *token = new ILGenericParamConstraint(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILGenericParamConstraint::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
parent_ = reinterpret_cast<ILGenericParam *>(ReadTokenFromFile(file, ttGenericParam));
|
|
constraint_ = ReadTokenFromFile(file, TypeDefRef);
|
|
}
|
|
|
|
void ILGenericParamConstraint::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, ttGenericParam, parent_);
|
|
WriteTokenToFile(file, TypeDefRef, constraint_);
|
|
}
|
|
|
|
void ILGenericParamConstraint::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = reinterpret_cast<ILGenericParam *>(meta()->token(parent_->id()));
|
|
if (constraint_)
|
|
constraint_ = meta()->token(constraint_->id());
|
|
}
|
|
|
|
|
|
void ILGenericParamConstraint::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(parent_);
|
|
if (it != token_map.end()) {
|
|
parent_ = reinterpret_cast<ILGenericParam *>(it->second);
|
|
if (!parent_)
|
|
set_deleted(true);
|
|
}
|
|
it = token_map.find(constraint_);
|
|
if (it != token_map.end()) {
|
|
constraint_ = it->second;
|
|
if (!constraint_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
int ILGenericParamConstraint::CompareWith(const ILToken &other) const
|
|
{
|
|
if (other.type() == ttGenericParamConstraint) {
|
|
const ILGenericParamConstraint &obj = reinterpret_cast<const ILGenericParamConstraint &>(other);
|
|
uint32_t self_value = parent_->value();
|
|
uint32_t other_value = obj.parent_->value();
|
|
if (self_value < other_value)
|
|
return -1;
|
|
if (self_value > other_value)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
return ILToken::CompareWith(other);
|
|
}
|
|
|
|
/**
|
|
* ILImplMap
|
|
*/
|
|
|
|
ILImplMap::ILImplMap(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), mapping_flags_(0), member_forwarded_(0), import_scope_(0), import_name_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILImplMap::ILImplMap(ILMetaData *meta, ILTable *owner, const ILImplMap &src)
|
|
: ILToken(meta, owner, src), import_name_pos_(0)
|
|
{
|
|
mapping_flags_ = src.mapping_flags_;
|
|
member_forwarded_ = src.member_forwarded_;
|
|
import_name_ = src.import_name_;
|
|
import_scope_ = src.import_scope_;
|
|
}
|
|
|
|
ILToken *ILImplMap::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILImplMap *token = new ILImplMap(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILImplMap::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
mapping_flags_ = file.ReadWord();
|
|
member_forwarded_ = ReadTokenFromFile(file, MemberForwarded);
|
|
import_name_ = ReadStringFromFile(file);
|
|
import_scope_ = reinterpret_cast<ILModuleRef *>(ReadTokenFromFile(file, ttModuleRef));
|
|
}
|
|
|
|
void ILImplMap::WriteToStreams(ILMetaData &data)
|
|
{
|
|
import_name_pos_ = data.AddString(import_name_);
|
|
}
|
|
|
|
void ILImplMap::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(mapping_flags_);
|
|
WriteTokenToFile(file, MemberForwarded, member_forwarded_);
|
|
WriteStringToFile(file, import_name_pos_);
|
|
WriteTokenToFile(file, ttModuleRef, import_scope_);
|
|
}
|
|
|
|
void ILImplMap::UpdateTokens()
|
|
{
|
|
if (member_forwarded_)
|
|
member_forwarded_ = meta()->token(member_forwarded_->id());
|
|
if (import_scope_)
|
|
import_scope_ = reinterpret_cast<ILModuleRef *>(meta()->token(import_scope_->id()));
|
|
}
|
|
|
|
void ILImplMap::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(member_forwarded_);
|
|
if (it != token_map.end()) {
|
|
member_forwarded_ = it->second;
|
|
if (!member_forwarded_)
|
|
set_deleted(true);
|
|
}
|
|
it = token_map.find(import_scope_);
|
|
if (it != token_map.end()) {
|
|
import_scope_ = reinterpret_cast<ILModuleRef *>(it->second);
|
|
if (!import_scope_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
int ILImplMap::CompareWith(const ILToken &other) const
|
|
{
|
|
if (other.type() == ttImplMap) {
|
|
const ILImplMap &obj = reinterpret_cast<const ILImplMap &>(other);
|
|
uint32_t self_value = member_forwarded_ ? member_forwarded_->Encode(MemberForwarded) : 0;
|
|
uint32_t other_value = obj.member_forwarded_ ? obj.member_forwarded_->Encode(MemberForwarded) : 0;
|
|
if (self_value < other_value)
|
|
return -1;
|
|
if (self_value > other_value)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
return ILToken::CompareWith(other);
|
|
}
|
|
|
|
/**
|
|
* ILInterfaceImpl
|
|
*/
|
|
|
|
ILInterfaceImpl::ILInterfaceImpl(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), class_(0), interface_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILInterfaceImpl::ILInterfaceImpl(ILMetaData *meta, ILTable *owner, const ILInterfaceImpl &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
class_ = src.class_;
|
|
interface_ = src.interface_;
|
|
}
|
|
|
|
ILToken *ILInterfaceImpl::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILInterfaceImpl *token = new ILInterfaceImpl(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILInterfaceImpl::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
class_ = reinterpret_cast<ILTypeDef *>(ReadTokenFromFile(file, ttTypeDef));
|
|
interface_ = ReadTokenFromFile(file, TypeDefRef);
|
|
}
|
|
|
|
void ILInterfaceImpl::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, ttTypeDef, class_);
|
|
WriteTokenToFile(file, TypeDefRef, interface_);
|
|
}
|
|
|
|
void ILInterfaceImpl::UpdateTokens()
|
|
{
|
|
if (class_)
|
|
class_ = reinterpret_cast<ILTypeDef *>(meta()->token(class_->id()));
|
|
if (interface_)
|
|
interface_ = meta()->token(interface_->id());
|
|
}
|
|
|
|
void ILInterfaceImpl::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(class_);
|
|
if (it != token_map.end()) {
|
|
class_ = reinterpret_cast<ILTypeDef *>(it->second);
|
|
if (!class_)
|
|
set_deleted(true);
|
|
}
|
|
it = token_map.find(interface_);
|
|
if (it != token_map.end()) {
|
|
interface_ = it->second;
|
|
if (!interface_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
int ILInterfaceImpl::CompareWith(const ILToken &other) const
|
|
{
|
|
if (other.type() == ttInterfaceImpl) {
|
|
const ILInterfaceImpl &obj = reinterpret_cast<const ILInterfaceImpl &>(other);
|
|
uint32_t self_value = class_ ? class_->value() : 0;
|
|
uint32_t other_value = obj.class_ ? obj.class_->value() : 0;
|
|
if (self_value < other_value)
|
|
return -1;
|
|
if (self_value > other_value)
|
|
return 1;
|
|
|
|
self_value = interface_ ? interface_->Encode(TypeDefRef) : 0;
|
|
other_value = obj.interface_ ? obj.interface_->Encode(TypeDefRef) : 0;
|
|
if (self_value < other_value)
|
|
return -1;
|
|
if (self_value > other_value)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
return ILToken::CompareWith(other);
|
|
}
|
|
|
|
/**
|
|
* ILManifestResource
|
|
*/
|
|
|
|
ILManifestResource::ILManifestResource(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), offset_(0), flags_(0), implementation_(NULL), name_pos_(0)
|
|
{
|
|
value_ = new ManifestResourceValue();
|
|
}
|
|
|
|
ILManifestResource::ILManifestResource(ILMetaData *meta, ILTable *owner, const ILManifestResource &src)
|
|
: ILToken(meta, owner, src), name_pos_(0)
|
|
{
|
|
offset_ = src.offset_;
|
|
flags_ = src.flags_;
|
|
name_ = src.name_;
|
|
implementation_ = src.implementation_;
|
|
value_ = src.value_->Clone();
|
|
}
|
|
|
|
ILManifestResource::~ILManifestResource()
|
|
{
|
|
delete value_;
|
|
}
|
|
|
|
ILToken *ILManifestResource::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILManifestResource *token = new ILManifestResource(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILManifestResource::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
offset_ = file.ReadDWord();
|
|
flags_ = file.ReadDWord();
|
|
name_ = ReadStringFromFile(file);
|
|
implementation_ = ReadTokenFromFile(file, Implementation);
|
|
|
|
if (!implementation_) {
|
|
if (uint64_t resource_address = file.header().Resources.VirtualAddress) {
|
|
uint64_t pos = file.Tell();
|
|
value_->ReadFromFile(file, resource_address + file.image_base() + offset_);
|
|
file.Seek(pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ILManifestResource::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
}
|
|
|
|
void ILManifestResource::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(offset_);
|
|
file.WriteDWord(flags_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteTokenToFile(file, Implementation, implementation_);
|
|
}
|
|
|
|
void ILManifestResource::UpdateTokens()
|
|
{
|
|
if (implementation_)
|
|
implementation_ = meta()->token(implementation_->id());
|
|
}
|
|
|
|
void ILManifestResource::UpdateValue()
|
|
{
|
|
NETStream stream;
|
|
|
|
value_->WriteToStream(stream);
|
|
data_ = stream.data();
|
|
}
|
|
|
|
/**
|
|
* ManifestResourceItem
|
|
*/
|
|
|
|
ManifestResourceItem::ManifestResourceItem(ManifestResourceValue *owner, const std::string &name, uint32_t type, uint64_t address, uint32_t size, const std::vector<uint8_t> &data)
|
|
: IObject(), owner_(owner), name_(name), type_(type), address_(address), size_(size), data_(data), baml_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
ManifestResourceItem::ManifestResourceItem(ManifestResourceValue *owner, const ManifestResourceItem &src)
|
|
: IObject(), owner_(owner), baml_(NULL)
|
|
{
|
|
name_ = src.name_;
|
|
type_ = src.type_;
|
|
address_ = src.address_;
|
|
size_ = src.size_;
|
|
data_ = src.data_;
|
|
}
|
|
|
|
ManifestResourceItem::~ManifestResourceItem()
|
|
{
|
|
if (owner_)
|
|
owner_->RemoveObject(this);
|
|
delete baml_;
|
|
}
|
|
|
|
ManifestResourceItem *ManifestResourceItem::Clone(ManifestResourceValue *owner) const
|
|
{
|
|
ManifestResourceItem *item = new ManifestResourceItem(owner, *this);
|
|
return item;
|
|
}
|
|
|
|
BamlDocument *ManifestResourceItem::ParseBaml()
|
|
{
|
|
if (baml_)
|
|
delete baml_;
|
|
|
|
NETStream stream;
|
|
stream.Write(data_.data(), data_.size());
|
|
stream.Seek(0, soBeginning);
|
|
|
|
baml_ = new BamlDocument();
|
|
if (baml_->ReadFromStream(stream))
|
|
return baml_;
|
|
return NULL;
|
|
}
|
|
|
|
int32_t ManifestResourceItem::name_hash() const
|
|
{
|
|
os::unicode_string name = os::FromUTF8(name_);
|
|
|
|
uint32_t hash = 5381;
|
|
for (size_t j = 0; j < name.size(); j++) {
|
|
hash = ((hash << 5) + hash) ^ name[j];
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
std::vector<uint8_t> ManifestResourceItem::data() const
|
|
{
|
|
if (baml_) {
|
|
NETStream stream;
|
|
baml_->WriteToStream(stream);
|
|
return stream.data();
|
|
}
|
|
|
|
return data_;
|
|
}
|
|
|
|
/**
|
|
* ManifestResourceValue
|
|
*/
|
|
|
|
ManifestResourceValue::ManifestResourceValue()
|
|
: ObjectList<ManifestResourceItem>()
|
|
{
|
|
|
|
}
|
|
|
|
ManifestResourceValue::ManifestResourceValue(const ManifestResourceValue &src)
|
|
{
|
|
address_ = src.address_;
|
|
size_ = src.size_;
|
|
|
|
magic_ = src.magic_;
|
|
header_version_ = src.header_version_;
|
|
reader_type_name_ = src.reader_type_name_;
|
|
set_type_name_ = src.set_type_name_;
|
|
reader_version_ = src.reader_version_;
|
|
|
|
for (size_t i = 0; i < src.count(); i++) {
|
|
AddObject(src.item(i)->Clone(this));
|
|
}
|
|
}
|
|
|
|
ManifestResourceValue *ManifestResourceValue::Clone() const
|
|
{
|
|
ManifestResourceValue *value = new ManifestResourceValue(*this);
|
|
return value;
|
|
}
|
|
|
|
enum ResourceTypeCode {
|
|
// Primitives
|
|
Null = 0,
|
|
String = 1,
|
|
Boolean = 2,
|
|
Char = 3,
|
|
Byte = 4,
|
|
SByte = 5,
|
|
Int16 = 6,
|
|
UInt16 = 7,
|
|
Int32 = 8,
|
|
UInt32 = 9,
|
|
Int64 = 0xa,
|
|
UInt64 = 0xb,
|
|
Single = 0xc,
|
|
Double = 0xd,
|
|
Decimal = 0xe,
|
|
DateTime = 0xf,
|
|
TimeSpan = 0x10,
|
|
|
|
// Types with a special representation, like byte[] and Stream
|
|
ByteArray = 0x20,
|
|
Stream = 0x21,
|
|
|
|
// User types - serialized using the binary formatter.
|
|
StartOfUserTypes = 0x40
|
|
};
|
|
|
|
void ManifestResourceValue::ReadFromFile(NETArchitecture &file, uint64_t address)
|
|
{
|
|
if (!file.AddressSeek(address))
|
|
return;
|
|
|
|
size_ = file.ReadDWord();
|
|
address_ = address + sizeof(uint32_t);
|
|
|
|
if (!size_)
|
|
return;
|
|
|
|
NETStream stream(*file.owner()->stream(), size_);
|
|
|
|
magic_ = stream.ReadDWord();
|
|
if (magic_ != 0xBEEFCACE)
|
|
return;
|
|
|
|
size_t i;
|
|
header_version_ = stream.ReadDWord();
|
|
uint32_t skip_bytes = stream.ReadDWord();
|
|
if (header_version_ > 1) {
|
|
stream.Seek(skip_bytes, soCurrent);
|
|
} else {
|
|
reader_type_name_ = stream.ReadString();
|
|
set_type_name_ = stream.ReadString();
|
|
}
|
|
|
|
reader_version_ = stream.ReadDWord();
|
|
if (reader_version_ != 1 && reader_version_ != 2)
|
|
return;
|
|
|
|
uint32_t num_resources = stream.ReadDWord();
|
|
uint32_t num_types = stream.ReadDWord();
|
|
for (i = 0; i < num_types; i++) {
|
|
type_names_.push_back(stream.ReadString());
|
|
}
|
|
while (stream.Tell() & 7)
|
|
stream.ReadByte();
|
|
|
|
std::vector<uint32_t> name_hashes;
|
|
for (i = 0; i < num_resources; i++) {
|
|
name_hashes.push_back(stream.ReadDWord());
|
|
}
|
|
|
|
std::vector<uint32_t> name_offsets;
|
|
for (i = 0; i < num_resources; i++) {
|
|
name_offsets.push_back(stream.ReadDWord());
|
|
}
|
|
uint32_t data_section_offset = stream.ReadDWord();
|
|
uint32_t name_section_offset = static_cast<uint32_t>(stream.Tell());
|
|
|
|
struct ResourceInfo {
|
|
std::string name;
|
|
uint32_t offset;
|
|
ResourceInfo(std::string _name, uint32_t _offset) : name(_name), offset(_offset) {}
|
|
};
|
|
|
|
std::sort(name_offsets.begin(), name_offsets.end());
|
|
std::vector<ResourceInfo> info_list;
|
|
for (i = 0; i < num_resources; i++) {
|
|
stream.Seek(name_section_offset + name_offsets[i], soBeginning);
|
|
std::string name = stream.ReadUnicodeString();
|
|
uint32_t offset = data_section_offset + stream.ReadDWord();
|
|
info_list.push_back(ResourceInfo(name, offset));
|
|
}
|
|
|
|
for (i = 0; i < num_resources; i++) {
|
|
ResourceInfo info = info_list[i];
|
|
stream.Seek(info.offset, soBeginning);
|
|
uint32_t type = stream.ReadEncoded();
|
|
uint32_t size;
|
|
if (reader_version_ == 1) {
|
|
throw std::runtime_error("Unsupported reader version");
|
|
}
|
|
else {
|
|
switch ((ResourceTypeCode)type) {
|
|
case Null:
|
|
size = 0;
|
|
break;
|
|
case String:
|
|
size = stream.ReadEncoded7Bit();
|
|
break;
|
|
case Boolean:
|
|
case Byte:
|
|
case SByte:
|
|
size = sizeof(uint8_t);
|
|
break;
|
|
case Char:
|
|
case Int16:
|
|
case UInt16:
|
|
size = sizeof(uint16_t);
|
|
break;
|
|
case Int32:
|
|
case UInt32:
|
|
size = sizeof(uint32_t);
|
|
break;
|
|
case Int64:
|
|
case UInt64:
|
|
size = sizeof(uint64_t);
|
|
break;
|
|
case Single:
|
|
size = 4;
|
|
break;
|
|
case Double:
|
|
size = 8;
|
|
break;
|
|
case Decimal:
|
|
size = 16;
|
|
break;
|
|
case DateTime:
|
|
case TimeSpan:
|
|
size = sizeof(uint64_t);
|
|
break;
|
|
case ByteArray:
|
|
case Stream:
|
|
size = stream.ReadDWord();
|
|
break;
|
|
default:
|
|
if (type >= StartOfUserTypes) {
|
|
// search next data offset
|
|
uint32_t next_offset = static_cast<uint32_t>(size_);
|
|
for (size_t j = 0; j < info_list.size(); j++) {
|
|
uint32_t cur_offset = info_list[j].offset;
|
|
if (cur_offset > stream.Tell() && next_offset > cur_offset)
|
|
next_offset = cur_offset;
|
|
}
|
|
size = next_offset - static_cast<uint32_t>(stream.Tell());
|
|
}
|
|
else
|
|
throw std::runtime_error("Unknown type of resource");
|
|
break;
|
|
}
|
|
}
|
|
std::vector<uint8_t> data;
|
|
if (size) {
|
|
data.resize(size);
|
|
stream.Read(data.data(), data.size());
|
|
}
|
|
Add(info.name, type, address_ + stream.Tell(), size, data);
|
|
}
|
|
}
|
|
|
|
ManifestResourceItem *ManifestResourceValue::Add(const std::string &name, uint32_t id, uint64_t address, uint32_t size, const std::vector<uint8_t> &data)
|
|
{
|
|
ManifestResourceItem *item = new ManifestResourceItem(this, name, id, address, size, data);
|
|
AddObject(item);
|
|
return item;
|
|
}
|
|
|
|
void ManifestResourceValue::WriteToStream(NETStream &stream)
|
|
{
|
|
size_t i;
|
|
uint64_t pos;
|
|
|
|
stream.WriteDWord(magic_);
|
|
stream.WriteDWord(header_version_);
|
|
|
|
if (header_version_ > 1) {
|
|
stream.WriteDWord(0);
|
|
}
|
|
else {
|
|
stream.WriteDWord(0);
|
|
pos = stream.Size();
|
|
stream.WriteString(reader_type_name_);
|
|
stream.WriteString(set_type_name_);
|
|
uint32_t skip_bytes = static_cast<uint32_t>(stream.Size() - pos);
|
|
|
|
stream.Seek(pos - sizeof(uint32_t) , soBeginning);
|
|
stream.WriteDWord(skip_bytes);
|
|
stream.Seek(0, soEnd);
|
|
}
|
|
stream.WriteDWord(reader_version_);
|
|
|
|
stream.WriteDWord(static_cast<uint32_t>(count()));
|
|
stream.WriteDWord(static_cast<uint32_t>(type_names_.size()));
|
|
for (i = 0; i < type_names_.size(); i++) {
|
|
stream.WriteString(type_names_[i]);
|
|
}
|
|
const char *pad_str = "PAD";
|
|
for (i = 0; static_cast<uint32_t>(stream.Size()) & 7; i++) {
|
|
stream.WriteByte(pad_str[i % 3]);
|
|
}
|
|
|
|
std::vector<int32_t> name_hashes;
|
|
for (i = 0; i < count(); i++) {
|
|
name_hashes.push_back(item(i)->name_hash());
|
|
}
|
|
std::sort(name_hashes.begin(), name_hashes.end());
|
|
for (i = 0; i < name_hashes.size(); i++) {
|
|
stream.WriteDWord(name_hashes[i]);
|
|
}
|
|
|
|
uint64_t name_offsets_pos = stream.Size();
|
|
for (i = 0; i < count(); i++) {
|
|
stream.WriteDWord(0);
|
|
}
|
|
|
|
uint64_t data_section_offset_pos = stream.Size();
|
|
stream.WriteDWord(0);
|
|
|
|
uint64_t name_section_offset = stream.Size();
|
|
|
|
std::vector<uint64_t> data_offset_pos;
|
|
for (i = 0; i < count(); i++) {
|
|
ManifestResourceItem *resource = item(i);
|
|
|
|
pos = stream.Size();
|
|
|
|
std::vector<int32_t>::const_iterator it = std::find(name_hashes.begin(), name_hashes.end(), resource->name_hash());
|
|
size_t hash_index = it - name_hashes.begin();
|
|
stream.Seek(name_offsets_pos + hash_index * sizeof(uint32_t), soBeginning);
|
|
stream.WriteDWord(static_cast<uint32_t>(pos - name_section_offset));
|
|
stream.Seek(0, soEnd);
|
|
|
|
stream.WriteUnicodeString(os::FromUTF8(resource->name()));
|
|
data_offset_pos.push_back(stream.Size());
|
|
stream.WriteDWord(0);
|
|
}
|
|
|
|
uint32_t data_section_offset = static_cast<uint32_t>(stream.Size());
|
|
stream.Seek(data_section_offset_pos, soBeginning);
|
|
stream.WriteDWord(data_section_offset);
|
|
stream.Seek(0, soEnd);
|
|
|
|
for (i = 0; i < count(); i++) {
|
|
ManifestResourceItem *resource = item(i);
|
|
|
|
pos = stream.Size();
|
|
|
|
stream.Seek(data_offset_pos[i], soBeginning);
|
|
stream.WriteDWord(static_cast<uint32_t>(pos - data_section_offset));
|
|
stream.Seek(0, soEnd);
|
|
|
|
stream.WriteEncoded(resource->type());
|
|
|
|
std::vector<uint8_t> data = resource->data();
|
|
if (reader_version_ == 1) {
|
|
// FIXME
|
|
} else {
|
|
switch ((ResourceTypeCode)resource->type()) {
|
|
case String:
|
|
stream.WriteEncoded7Bit(static_cast<uint32_t>(data.size()));
|
|
break;
|
|
case ByteArray:
|
|
case Stream:
|
|
stream.WriteDWord(static_cast<uint32_t>(data.size()));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!data.empty())
|
|
stream.Write(data.data(), data.size());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ILMemberRef
|
|
*/
|
|
|
|
ILMemberRef::ILMemberRef(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), declaring_type_(NULL), signature_pos_(0), name_pos_(0)
|
|
{
|
|
signature_ = new ILSignature(meta);
|
|
}
|
|
|
|
ILMemberRef::ILMemberRef(ILMetaData *meta, ILTable *owner, const ILMemberRef &src)
|
|
: ILToken(meta, owner, src), signature_pos_(0), name_pos_(0)
|
|
{
|
|
declaring_type_ = src.declaring_type_;
|
|
name_ = src.name_;
|
|
signature_ = src.signature_->Clone(meta);
|
|
}
|
|
|
|
ILMemberRef::~ILMemberRef()
|
|
{
|
|
delete signature_;
|
|
}
|
|
|
|
ILToken *ILMemberRef::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILMemberRef *token = new ILMemberRef(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
std::string ILMemberRef::full_name(bool mode, ILSignature *method_gen_signature) const
|
|
{
|
|
std::string type_name;
|
|
if (declaring_type_) {
|
|
switch (declaring_type_->type()) {
|
|
case ttTypeDef:
|
|
type_name = reinterpret_cast<ILTypeDef *>(declaring_type_)->name();
|
|
break;
|
|
case ttTypeRef:
|
|
type_name = reinterpret_cast<ILTypeRef *>(declaring_type_)->full_name(mode);
|
|
break;
|
|
case ttTypeSpec:
|
|
type_name = reinterpret_cast<ILTypeSpec *>(declaring_type_)->name(mode);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
type_name = "<NULL>";
|
|
|
|
return ILName(signature_->ret_name(mode), type_name, name(), signature_->is_method() ? signature_->name(mode, method_gen_signature) : "");
|
|
}
|
|
|
|
void ILMemberRef::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
declaring_type_ = ReadTokenFromFile(file, MemberRefParent);
|
|
name_ = ReadStringFromFile(file);
|
|
signature_->Parse(ReadBlobFromFile(file));
|
|
}
|
|
|
|
void ILMemberRef::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
signature_pos_ = data.AddBlob(signature_->data());
|
|
}
|
|
|
|
void ILMemberRef::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, MemberRefParent, declaring_type_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteBlobToFile(file, signature_pos_);
|
|
}
|
|
|
|
void ILMemberRef::UpdateTokens()
|
|
{
|
|
if (declaring_type_)
|
|
declaring_type_ = meta()->token(declaring_type_->id());
|
|
signature_->UpdateTokens();
|
|
}
|
|
|
|
void ILMemberRef::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(declaring_type_);
|
|
if (it != token_map.end()) {
|
|
declaring_type_ = it->second;
|
|
if (!declaring_type_)
|
|
set_deleted(true);
|
|
}
|
|
signature_->RemapTokens(token_map);
|
|
}
|
|
|
|
/**
|
|
* ILCustomMod
|
|
*/
|
|
|
|
ILCustomMod::ILCustomMod(ILMetaData *meta)
|
|
: IObject(), meta_(meta), type_(ELEMENT_TYPE_END), token_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
ILCustomMod::ILCustomMod(ILMetaData *meta, const ILCustomMod &src)
|
|
: IObject(), meta_(meta)
|
|
{
|
|
type_ = src.type_;
|
|
token_ = src.token_;
|
|
}
|
|
|
|
ILCustomMod *ILCustomMod::Clone(ILMetaData *meta)
|
|
{
|
|
ILCustomMod *mod = new ILCustomMod(meta, *this);
|
|
return mod;
|
|
}
|
|
|
|
void ILCustomMod::Parse(const ILData &data, uint32_t &id)
|
|
{
|
|
type_ = static_cast<CorElementType>(data.ReadByte(id));
|
|
switch (type_) {
|
|
case ELEMENT_TYPE_CMOD_REQD:
|
|
case ELEMENT_TYPE_CMOD_OPT:
|
|
// do nothing
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid mod type");
|
|
}
|
|
|
|
uint32_t value = data.ReadEncoded(id);
|
|
ILTokenType ref_type;
|
|
switch (value & 3) {
|
|
case 0:
|
|
ref_type = ttTypeDef;
|
|
break;
|
|
case 1:
|
|
ref_type = ttTypeRef;
|
|
break;
|
|
case 2:
|
|
ref_type = ttTypeSpec;
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid token");
|
|
}
|
|
|
|
token_ = meta_->token(ref_type | (value >> 2));
|
|
if (!token_)
|
|
throw std::runtime_error("Invalid token");
|
|
}
|
|
|
|
void ILCustomMod::WriteToData(ILData &data)
|
|
{
|
|
data.push_back(type_);
|
|
uint32_t value = token_->value() << 2;
|
|
switch (token_->type()) {
|
|
case ttTypeDef:
|
|
value |= 0;
|
|
break;
|
|
case ttTypeRef:
|
|
value |= 1;
|
|
break;
|
|
case ttTypeSpec:
|
|
value |= 2;
|
|
break;
|
|
}
|
|
data.WriteEncoded(value);
|
|
}
|
|
|
|
std::string ILCustomMod::name(bool mode) const
|
|
{
|
|
std::string res = (type_ == ELEMENT_TYPE_CMOD_REQD) ? "modreq" : "modopt";
|
|
|
|
res += '(';
|
|
switch (token_->type()) {
|
|
case ttTypeRef:
|
|
res += reinterpret_cast<ILTypeRef*>(token_)->full_name(mode);
|
|
break;
|
|
case ttTypeDef:
|
|
res += reinterpret_cast<ILTypeDef*>(token_)->full_name();
|
|
break;
|
|
}
|
|
res += ')';
|
|
|
|
return res;
|
|
}
|
|
|
|
void ILCustomMod::UpdateTokens()
|
|
{
|
|
if (token_)
|
|
token_ = meta_->token(token_->id());
|
|
}
|
|
|
|
void ILCustomMod::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
if (token_) {
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(token_);
|
|
if (it != token_map.end())
|
|
token_ = it->second;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ILElement
|
|
*/
|
|
|
|
ILElement::ILElement(ILMetaData *meta, ILSignature *owner, CorElementType type, ILToken *token, ILElement *next)
|
|
: IObject(), meta_(meta), owner_(owner), type_(type), next_(next), byref_(false),
|
|
token_(token), method_(NULL), generic_param_(0), array_shape_(NULL), pinned_(false), is_predicate_(false)
|
|
{
|
|
|
|
}
|
|
|
|
ILElement::ILElement(ILMetaData *meta, ILSignature *owner, const ILElement &src)
|
|
: IObject(), meta_(meta), owner_(owner), next_(NULL), method_(NULL), array_shape_(NULL)
|
|
{
|
|
type_ = src.type_;
|
|
byref_ = src.byref_;
|
|
pinned_ = src.pinned_;
|
|
generic_param_ = src.generic_param_;
|
|
is_predicate_ = src.is_predicate_;
|
|
if (src.next_)
|
|
next_ = src.next_->Clone(meta, NULL);
|
|
token_ = src.token_;
|
|
if (src.method_)
|
|
method_ = src.method_->Clone(meta);
|
|
if (src.array_shape_)
|
|
array_shape_ = src.array_shape_->Clone();
|
|
for (size_t i = 0; i < src.mod_list_.size(); i++) {
|
|
mod_list_.push_back(src.mod_list_[i]->Clone(meta));
|
|
}
|
|
for (size_t i = 0; i < src.child_list_.size(); i++) {
|
|
child_list_.push_back(src.child_list_[i]->Clone(meta, NULL));
|
|
}
|
|
}
|
|
|
|
ILElement::~ILElement()
|
|
{
|
|
if (owner_)
|
|
owner_->RemoveObject(this);
|
|
|
|
for (size_t i = 0; i < mod_list_.size(); i++) {
|
|
delete mod_list_[i];
|
|
}
|
|
for (size_t i = 0; i < child_list_.size(); i++) {
|
|
delete child_list_[i];
|
|
}
|
|
|
|
delete next_;
|
|
delete method_;
|
|
delete array_shape_;
|
|
}
|
|
|
|
ILElement *ILElement::Clone(ILMetaData *meta, ILSignature *owner)
|
|
{
|
|
ILElement *element = new ILElement(meta, owner, *this);
|
|
return element;
|
|
}
|
|
|
|
ILCustomMod *ILElement::AddMod()
|
|
{
|
|
ILCustomMod *mod = new ILCustomMod(meta_);
|
|
mod_list_.push_back(mod);
|
|
return mod;
|
|
}
|
|
|
|
ILElement *ILElement::AddElement()
|
|
{
|
|
ILElement *element = new ILElement(meta_, NULL);
|
|
child_list_.push_back(element);
|
|
return element;
|
|
}
|
|
|
|
void ILElement::Parse(const ILData &data)
|
|
{
|
|
uint32_t id = 0;
|
|
Parse(data, id);
|
|
}
|
|
|
|
void ILElement::Parse(const ILData &data, uint32_t &id)
|
|
{
|
|
for (bool mod_found = true; mod_found;) {
|
|
switch (data.ReadByte(id)) {
|
|
case ELEMENT_TYPE_BYREF:
|
|
byref_ = true;
|
|
break;
|
|
case ELEMENT_TYPE_PINNED:
|
|
pinned_ = true;
|
|
break;
|
|
case ELEMENT_TYPE_CMOD_REQD:
|
|
case ELEMENT_TYPE_CMOD_OPT:
|
|
{
|
|
id--;
|
|
ILCustomMod *mod = AddMod();
|
|
mod->Parse(data, id);
|
|
}
|
|
break;
|
|
default:
|
|
mod_found = false;
|
|
id--;
|
|
break;
|
|
}
|
|
}
|
|
|
|
type_ = static_cast<CorElementType>(data.ReadEncoded(id));
|
|
|
|
switch (type_){
|
|
case ELEMENT_TYPE_VOID:
|
|
case ELEMENT_TYPE_BOOLEAN:
|
|
case ELEMENT_TYPE_CHAR:
|
|
case ELEMENT_TYPE_I1:
|
|
case ELEMENT_TYPE_U1:
|
|
case ELEMENT_TYPE_I2:
|
|
case ELEMENT_TYPE_U2:
|
|
case ELEMENT_TYPE_I4:
|
|
case ELEMENT_TYPE_U4:
|
|
case ELEMENT_TYPE_I8:
|
|
case ELEMENT_TYPE_U8:
|
|
case ELEMENT_TYPE_R4:
|
|
case ELEMENT_TYPE_R8:
|
|
case ELEMENT_TYPE_I:
|
|
case ELEMENT_TYPE_U:
|
|
case ELEMENT_TYPE_STRING:
|
|
case ELEMENT_TYPE_OBJECT:
|
|
case ELEMENT_TYPE_TYPEDBYREF:
|
|
case ELEMENT_TYPE_SENTINEL:
|
|
case ELEMENT_TYPE_PINNED:
|
|
break;
|
|
case ELEMENT_TYPE_VALUETYPE:
|
|
case ELEMENT_TYPE_CLASS:
|
|
{
|
|
uint32_t value = data.ReadEncoded(id);
|
|
ILTokenType ref_type;
|
|
switch (value & 3) {
|
|
case 0:
|
|
ref_type = ttTypeDef;
|
|
break;
|
|
case 1:
|
|
ref_type = ttTypeRef;
|
|
break;
|
|
case 2:
|
|
ref_type = ttTypeSpec;
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid token");
|
|
}
|
|
|
|
token_ = meta_->token(ref_type | (value >> 2));
|
|
if (!token_)
|
|
throw std::runtime_error("Invalid token");
|
|
}
|
|
break;
|
|
case ELEMENT_TYPE_SZARRAY:
|
|
next_ = new ILElement(meta_, NULL);
|
|
next_->Parse(data, id);
|
|
break;
|
|
case ELEMENT_TYPE_PTR:
|
|
next_ = new ILElement(meta_, NULL);
|
|
next_->Parse(data, id);
|
|
break;
|
|
case ELEMENT_TYPE_FNPTR:
|
|
method_ = new ILSignature(meta_);
|
|
method_->Parse(data, id);
|
|
if (!method_->is_method())
|
|
throw std::runtime_error("Invalid signature type");
|
|
break;
|
|
case ELEMENT_TYPE_ARRAY:
|
|
next_ = new ILElement(meta_, NULL);
|
|
next_->Parse(data, id);
|
|
array_shape_ = new ILArrayShape();
|
|
array_shape_->Parse(data, id);
|
|
break;
|
|
case ELEMENT_TYPE_MVAR:
|
|
case ELEMENT_TYPE_VAR:
|
|
generic_param_ = data.ReadEncoded(id);
|
|
break;
|
|
case ELEMENT_TYPE_GENERICINST:
|
|
next_ = new ILElement(meta_, NULL);
|
|
next_->Parse(data, id);
|
|
{
|
|
uint32_t count = data.ReadEncoded(id);
|
|
for (size_t i = 0; i < count; i++) {
|
|
ILElement *element = AddElement();
|
|
element->Parse(data, id);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid element type");
|
|
}
|
|
}
|
|
|
|
std::string ILElement::name(bool mode) const
|
|
{
|
|
std::string res;
|
|
|
|
switch (type_) {
|
|
case ELEMENT_TYPE_VOID:
|
|
res += "void";
|
|
break;
|
|
case ELEMENT_TYPE_BOOLEAN:
|
|
res += "bool";
|
|
break;
|
|
case ELEMENT_TYPE_CHAR:
|
|
res += "char";
|
|
break;
|
|
case ELEMENT_TYPE_I1:
|
|
res += "int8";
|
|
break;
|
|
case ELEMENT_TYPE_U1:
|
|
res += "unsigned int8";
|
|
break;
|
|
case ELEMENT_TYPE_I2:
|
|
res += "int16";
|
|
break;
|
|
case ELEMENT_TYPE_U2:
|
|
res += "unsigned int16";
|
|
break;
|
|
case ELEMENT_TYPE_I4:
|
|
res += "int32";
|
|
break;
|
|
case ELEMENT_TYPE_U4:
|
|
res += "unsigned int32";
|
|
break;
|
|
case ELEMENT_TYPE_I8:
|
|
res += "int64";
|
|
break;
|
|
case ELEMENT_TYPE_U8:
|
|
res += "unsigned int64";
|
|
break;
|
|
case ELEMENT_TYPE_R4:
|
|
res += "float32";
|
|
break;
|
|
case ELEMENT_TYPE_R8:
|
|
res += "float64";
|
|
break;
|
|
case ELEMENT_TYPE_I:
|
|
res += "native int";
|
|
break;
|
|
case ELEMENT_TYPE_U:
|
|
res += "native unsigned int";
|
|
break;
|
|
case ELEMENT_TYPE_OBJECT:
|
|
res += "object";
|
|
break;
|
|
case ELEMENT_TYPE_STRING:
|
|
res += "string";
|
|
break;
|
|
case ELEMENT_TYPE_SZARRAY:
|
|
res += next_->name(mode);
|
|
res += "[]";
|
|
break;
|
|
case ELEMENT_TYPE_PTR:
|
|
res += next_->name(mode);
|
|
res += '*';
|
|
break;
|
|
case ELEMENT_TYPE_TYPEDBYREF:
|
|
res += "typedref";
|
|
break;
|
|
case ELEMENT_TYPE_FNPTR:
|
|
{
|
|
std::string call_type = method_->type_name();
|
|
res = string_format("method %s%s%s *%s", call_type.c_str(), call_type.empty() ? "" : " ", method_->ret_name(mode).c_str(), method_->name(mode).c_str());
|
|
}
|
|
break;
|
|
case ELEMENT_TYPE_ARRAY:
|
|
res += next_->name(mode);
|
|
res += ' ';
|
|
res += array_shape_->name();
|
|
break;
|
|
case ELEMENT_TYPE_VALUETYPE:
|
|
case ELEMENT_TYPE_CLASS:
|
|
res += (type_ == ELEMENT_TYPE_VALUETYPE) ? "valuetype " : "class ";
|
|
|
|
switch (token_->type()) {
|
|
case ttTypeRef:
|
|
res += reinterpret_cast<ILTypeRef*>(token_)->full_name(mode);
|
|
break;
|
|
case ttTypeDef:
|
|
res += reinterpret_cast<ILTypeDef*>(token_)->full_name();
|
|
break;
|
|
}
|
|
break;
|
|
case ELEMENT_TYPE_GENERICINST:
|
|
res += next_->name(mode);
|
|
res += '<';
|
|
for (size_t i = 0; i < child_list_.size(); i++) {
|
|
if (i > 0)
|
|
res += ", ";
|
|
res += child_list_[i]->name(mode);
|
|
}
|
|
res += '>';
|
|
break;
|
|
case ELEMENT_TYPE_MVAR:
|
|
case ELEMENT_TYPE_VAR:
|
|
res += string_format("%s%d", (type_ == ELEMENT_TYPE_VAR) ? "!" : "!!", generic_param_);
|
|
break;
|
|
default:
|
|
// FIXME
|
|
res += "???";
|
|
}
|
|
|
|
for (size_t i = 0; i < mod_list_.size(); i++) {
|
|
res += ' ';
|
|
res += mod_list_[i]->name(mode);
|
|
}
|
|
|
|
if (byref_)
|
|
res += '&';
|
|
|
|
if (pinned_)
|
|
res += " pinned";
|
|
|
|
return res;
|
|
}
|
|
|
|
void ILElement::UpdateTokens()
|
|
{
|
|
if (token_)
|
|
token_ = meta_->token(token_->id());
|
|
if (method_)
|
|
method_->UpdateTokens();
|
|
if (next_)
|
|
next_->UpdateTokens();
|
|
for (size_t i = 0; i < mod_list_.size(); i++) {
|
|
mod_list_[i]->UpdateTokens();
|
|
}
|
|
for (size_t i = 0; i < child_list_.size(); i++) {
|
|
child_list_[i]->UpdateTokens();
|
|
}
|
|
}
|
|
|
|
void ILElement::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
if (token_) {
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(token_);
|
|
if (it != token_map.end())
|
|
token_ = it->second;
|
|
}
|
|
if (method_)
|
|
method_->RemapTokens(token_map);
|
|
if (next_)
|
|
next_->RemapTokens(token_map);
|
|
for (size_t i = 0; i < mod_list_.size(); i++) {
|
|
mod_list_[i]->RemapTokens(token_map);
|
|
}
|
|
for (size_t i = 0; i < child_list_.size(); i++) {
|
|
child_list_[i]->RemapTokens(token_map);
|
|
}
|
|
}
|
|
|
|
ILData ILElement::data() const
|
|
{
|
|
ILData data;
|
|
WriteToData(data);
|
|
return data;
|
|
}
|
|
|
|
void ILElement::WriteToData(ILData &data) const
|
|
{
|
|
if (pinned_)
|
|
data.push_back(ELEMENT_TYPE_PINNED);
|
|
if (byref_)
|
|
data.push_back(ELEMENT_TYPE_BYREF);
|
|
|
|
for (size_t i = 0; i < mod_list_.size(); i++) {
|
|
ILCustomMod *mod = mod_list_[i];
|
|
mod->WriteToData(data);
|
|
}
|
|
|
|
data.WriteEncoded(type_);
|
|
switch (type_) {
|
|
case ELEMENT_TYPE_VALUETYPE:
|
|
case ELEMENT_TYPE_CLASS:
|
|
{
|
|
uint32_t value = token_->value() << 2;
|
|
switch (token_->type()) {
|
|
case ttTypeDef:
|
|
value |= 0;
|
|
break;
|
|
case ttTypeRef:
|
|
value |= 1;
|
|
break;
|
|
case ttTypeSpec:
|
|
value |= 2;
|
|
break;
|
|
}
|
|
data.WriteEncoded(value);
|
|
}
|
|
break;
|
|
case ELEMENT_TYPE_SZARRAY:
|
|
case ELEMENT_TYPE_PTR:
|
|
next_->WriteToData(data);
|
|
break;
|
|
case ELEMENT_TYPE_FNPTR:
|
|
method_->WriteToData(data);
|
|
break;
|
|
case ELEMENT_TYPE_ARRAY:
|
|
next_->WriteToData(data);
|
|
array_shape_->WriteToData(data);
|
|
break;
|
|
case ELEMENT_TYPE_MVAR:
|
|
case ELEMENT_TYPE_VAR:
|
|
data.WriteEncoded(generic_param_);
|
|
break;
|
|
case ELEMENT_TYPE_GENERICINST:
|
|
next_->WriteToData(data);
|
|
{
|
|
data.WriteEncoded(static_cast<uint32_t>(child_list_.size()));
|
|
for (size_t i = 0; i < child_list_.size(); i++) {
|
|
ILElement *element = child_list_[i];
|
|
element->WriteToData(data);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ILArrayShape
|
|
*/
|
|
|
|
ILArrayShape::ILArrayShape()
|
|
: IObject(), rank_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILArrayShape::ILArrayShape(const ILArrayShape &src)
|
|
: IObject()
|
|
{
|
|
rank_ = src.rank_;
|
|
sizes_ = src.sizes_;
|
|
lo_bounds_ = src.lo_bounds_;
|
|
}
|
|
|
|
ILArrayShape *ILArrayShape::Clone()
|
|
{
|
|
ILArrayShape *shape = new ILArrayShape(*this);
|
|
return shape;
|
|
}
|
|
|
|
std::string ILArrayShape::name() const
|
|
{
|
|
std::string res;
|
|
|
|
res += '[';
|
|
for (size_t i = 0; i < rank_; i++) {
|
|
if (i > 0)
|
|
res += ',';
|
|
if (i < lo_bounds_.size()) {
|
|
uint32_t lo_bound = lo_bounds_[i];
|
|
res += string_format("%d..", lo_bound);
|
|
if (i < sizes_.size())
|
|
res += string_format("%d", lo_bound + sizes_[rank_] - 1);
|
|
else
|
|
res += '.';
|
|
}
|
|
}
|
|
res += ']';
|
|
return res;
|
|
}
|
|
|
|
void ILArrayShape::Parse(const ILData &data, uint32_t &id)
|
|
{
|
|
rank_ = data.ReadEncoded(id);
|
|
uint32_t count = data.ReadEncoded(id);
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
sizes_.push_back(data.ReadEncoded(id));
|
|
}
|
|
count = data.ReadEncoded(id);
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
lo_bounds_.push_back(data.ReadEncoded(id));
|
|
}
|
|
}
|
|
|
|
void ILArrayShape::WriteToData(ILData &data) const
|
|
{
|
|
data.WriteEncoded(rank_);
|
|
data.WriteEncoded(static_cast<uint32_t>(sizes_.size()));
|
|
for (uint32_t i = 0; i < sizes_.size(); i++) {
|
|
data.WriteEncoded(sizes_[i]);
|
|
}
|
|
data.WriteEncoded(static_cast<uint32_t>(lo_bounds_.size()));
|
|
for (uint32_t i = 0; i < lo_bounds_.size(); i++) {
|
|
data.WriteEncoded(lo_bounds_[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ILSignature
|
|
*/
|
|
|
|
ILSignature::ILSignature(ILMetaData *meta)
|
|
: ObjectList<ILElement>(), meta_(meta), type_(stDefault), gen_param_count_(0)
|
|
{
|
|
ret_ = new ILElement(meta, NULL);
|
|
}
|
|
|
|
ILSignature::ILSignature(ILMetaData *meta, const ILSignature &src)
|
|
: ObjectList<ILElement>(), meta_(meta)
|
|
{
|
|
type_ = src.type_;
|
|
gen_param_count_ = src.gen_param_count_;
|
|
ret_ = src.ret_->Clone(meta, this);
|
|
|
|
for (size_t i = 0; i < src.count(); i++) {
|
|
AddObject(src.item(i)->Clone(meta, this));
|
|
}
|
|
}
|
|
|
|
ILSignature::~ILSignature()
|
|
{
|
|
delete ret_;
|
|
}
|
|
|
|
ILSignature *ILSignature::Clone(ILMetaData *meta)
|
|
{
|
|
ILSignature *sign = new ILSignature(meta, *this);
|
|
return sign;
|
|
}
|
|
|
|
ILElement *ILSignature::Add()
|
|
{
|
|
ILElement *element = new ILElement(meta_, this);
|
|
AddObject(element);
|
|
return element;
|
|
}
|
|
|
|
void ILSignature::Parse(const ILData &data)
|
|
{
|
|
uint32_t id = 0;
|
|
Parse(data, id);
|
|
}
|
|
|
|
bool ILSignature::Parse(const ILData &data, uint32_t &id)
|
|
{
|
|
type_ = static_cast<ILSignatureType>(data.ReadByte(id));
|
|
if (type_ & stGeneric)
|
|
gen_param_count_ = data.ReadEncoded(id);
|
|
|
|
switch (type_ & 0x0f) {
|
|
case stDefault:
|
|
case stC:
|
|
case stStdCall:
|
|
case stThisCall:
|
|
case stFastCall:
|
|
case stVarArg:
|
|
case stUnmanaged:
|
|
case stNativeVarArg:
|
|
case stProperty:
|
|
{
|
|
uint32_t param_count = data.ReadEncoded(id);
|
|
ret_->Parse(data, id);
|
|
for (uint32_t i = 0; i < param_count; i++) {
|
|
ILElement *element = Add();
|
|
element->Parse(data, id);
|
|
}
|
|
}
|
|
break;
|
|
case stField:
|
|
ret_->Parse(data, id);
|
|
break;
|
|
case stLocal:
|
|
case stGenericinst:
|
|
{
|
|
uint32_t param_count = data.ReadEncoded(id);
|
|
for (uint32_t i = 0; i < param_count; i++) {
|
|
ILElement *element = Add();
|
|
element->Parse(data, id);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Unknown signature type");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::string ILSignature::name(bool mode, ILSignature *gen_signature) const
|
|
{
|
|
std::string res;
|
|
|
|
bool is_generic_inst = false;
|
|
switch (type_ & 0x0f) {
|
|
case stGenericinst:
|
|
is_generic_inst = true;
|
|
// fall through
|
|
case stDefault:
|
|
case stC:
|
|
case stStdCall:
|
|
case stThisCall:
|
|
case stFastCall:
|
|
case stVarArg:
|
|
case stLocal:
|
|
case stUnmanaged:
|
|
case stNativeVarArg:
|
|
if (type_ & stGeneric) {
|
|
if (gen_signature)
|
|
res += gen_signature->name(mode);
|
|
else {
|
|
res += '<';
|
|
for (size_t i = 0; i < gen_param_count_; i++) {
|
|
if (i > 0)
|
|
res += ", ";
|
|
res += string_format("%d", i);
|
|
}
|
|
res += '>';
|
|
}
|
|
}
|
|
|
|
res += is_generic_inst ? '<' : '(';
|
|
for (size_t i = 0; i < count(); i++) {
|
|
if (i > 0)
|
|
res += ", ";
|
|
res += item(i)->name(mode);
|
|
}
|
|
res += is_generic_inst ? '>' : ')';
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
std::string ILSignature::type_name() const
|
|
{
|
|
std::string res;
|
|
|
|
switch (type_ & 0x0f) {
|
|
case stDefault:
|
|
break;
|
|
case stC:
|
|
break;
|
|
case stStdCall:
|
|
res = "stdcall";
|
|
break;
|
|
case stThisCall:
|
|
res = "thiscall";
|
|
break;
|
|
case stFastCall:
|
|
res = "fastcall";
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
std::string ILSignature::ret_name(bool mode) const
|
|
{
|
|
std::string res;
|
|
|
|
if (has_this())
|
|
res = "instance ";
|
|
|
|
res += ret_->name(mode);
|
|
return res;
|
|
}
|
|
|
|
void ILSignature::WriteToData(ILData &data) const
|
|
{
|
|
data.push_back(type_);
|
|
|
|
if (type_ & stGeneric)
|
|
data.WriteEncoded(gen_param_count_);
|
|
|
|
switch (type_ & 0x0f) {
|
|
case stDefault:
|
|
case stC:
|
|
case stStdCall:
|
|
case stThisCall:
|
|
case stFastCall:
|
|
case stVarArg:
|
|
case stProperty:
|
|
case stUnmanaged:
|
|
case stNativeVarArg:
|
|
{
|
|
data.WriteEncoded(static_cast<uint32_t>(count()));
|
|
ret_->WriteToData(data);
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->WriteToData(data);
|
|
}
|
|
}
|
|
break;
|
|
case stField:
|
|
ret_->WriteToData(data);
|
|
break;
|
|
case stLocal:
|
|
case stGenericinst:
|
|
{
|
|
data.WriteEncoded(static_cast<uint32_t>(count()));
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->WriteToData(data);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ILSignature::UpdateTokens()
|
|
{
|
|
if (ret_)
|
|
ret_->UpdateTokens();
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->UpdateTokens();
|
|
}
|
|
}
|
|
|
|
void ILSignature::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
if (ret_)
|
|
ret_->RemapTokens(token_map);
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->RemapTokens(token_map);
|
|
}
|
|
}
|
|
|
|
ILData ILSignature::data() const
|
|
{
|
|
ILData data;
|
|
WriteToData(data);
|
|
return data;
|
|
}
|
|
|
|
bool ILSignature::is_method() const
|
|
{
|
|
switch (type_ & 0x0f) {
|
|
case stDefault:
|
|
case stC:
|
|
case stStdCall:
|
|
case stThisCall:
|
|
case stFastCall:
|
|
case stVarArg:
|
|
case stUnmanaged:
|
|
case stNativeVarArg:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool ILSignature::is_field() const
|
|
{
|
|
return ((type_ & 0x0f) == stField);
|
|
}
|
|
|
|
/**
|
|
* ILMethod
|
|
*/
|
|
|
|
ILMethodDef::ILMethodDef(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), address_(0), impl_flags_(miIL), flags_(mdPrivateScope), param_list_(NULL),
|
|
declaring_type_(NULL), locals_(NULL), fat_size_(0), code_size_(0), signature_pos_(0), name_pos_(0)
|
|
{
|
|
signature_ = new ILSignature(meta);
|
|
}
|
|
|
|
ILMethodDef::ILMethodDef(ILMetaData *meta, ILTable *owner, const ILMethodDef &src)
|
|
: ILToken(meta, owner, src), signature_pos_(0), name_pos_(0)
|
|
{
|
|
address_ = src.address_;
|
|
impl_flags_ = src.impl_flags_;
|
|
flags_ = src.flags_;
|
|
name_ = src.name_;
|
|
signature_ = src.signature_->Clone(meta);
|
|
param_list_ = src.param_list_;
|
|
declaring_type_ = src.declaring_type_;
|
|
fat_size_ = src.fat_size_;
|
|
code_size_ = src.code_size_;
|
|
locals_ = src.locals_;
|
|
}
|
|
|
|
ILMethodDef::ILMethodDef(ILMetaData *meta, ILTable *owner, const std::string &name, const ILData &signature, CorMethodAttr flags, CorMethodImpl impl_flags)
|
|
: ILToken(meta, owner, ttMethodDef), name_(name), flags_(flags), param_list_(NULL), locals_(NULL), fat_size_(0), code_size_(0),
|
|
impl_flags_(impl_flags), declaring_type_(NULL), signature_pos_(0), name_pos_(0), address_(0)
|
|
{
|
|
signature_ = new ILSignature(meta);
|
|
signature_->Parse(signature);
|
|
}
|
|
|
|
ILMethodDef::~ILMethodDef()
|
|
{
|
|
delete signature_;
|
|
}
|
|
|
|
ILToken *ILMethodDef::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILMethodDef *method = new ILMethodDef(meta, owner, *this);
|
|
return method;
|
|
}
|
|
|
|
void ILMethodDef::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
address_ = file.ReadDWord();
|
|
if (address_)
|
|
address_ += file.image_base();
|
|
impl_flags_ = static_cast<CorMethodImpl>(file.ReadWord());
|
|
flags_ = static_cast<CorMethodAttr>(file.ReadWord());
|
|
name_ = ReadStringFromFile(file);
|
|
signature_->Parse(ReadBlobFromFile(file));
|
|
param_list_ = reinterpret_cast<ILParam *>(ReadTokenFromFile(file, ttParam));
|
|
|
|
if (address_ && (impl_flags_ & miCodeTypeMask) == miIL) {
|
|
uint64_t pos = file.Tell();
|
|
if (file.AddressSeek(address_)) {
|
|
IMAGE_COR_ILMETHOD_FAT fat = IMAGE_COR_ILMETHOD_FAT();
|
|
file.Read(&fat, sizeof(uint8_t));
|
|
|
|
switch (fat.Flags & CorILMethod_FormatMask) {
|
|
case CorILMethod_TinyFormat:
|
|
fat_size_ = 1;
|
|
code_size_ = (fat.Flags >> CorILMethod_FormatShift);
|
|
break;
|
|
case CorILMethod_FatFormat:
|
|
file.Read(reinterpret_cast<uint8_t *>(&fat) + 1, sizeof(fat) - 1);
|
|
fat_size_ = fat.Size * sizeof(uint32_t);
|
|
code_size_ = fat.CodeSize;
|
|
if (fat.LocalVarSigTok) {
|
|
ILToken *token = meta()->token(fat.LocalVarSigTok);
|
|
if (!token || token->type() != ttStandAloneSig)
|
|
throw std::runtime_error("Invalid method signature");
|
|
locals_ = reinterpret_cast<ILStandAloneSig *>(token);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
file.Seek(pos);
|
|
}
|
|
}
|
|
|
|
void ILMethodDef::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
signature_pos_ = data.AddBlob(signature_->data());
|
|
}
|
|
|
|
void ILMethodDef::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(address_ ? static_cast<uint32_t>(address_ - file.image_base()) : 0);
|
|
file.WriteWord(impl_flags_);
|
|
file.WriteWord(flags_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteBlobToFile(file, signature_pos_);
|
|
|
|
ILParam *param_list = NULL;
|
|
for (ILMethodDef *src = this; src != NULL && param_list == NULL; src = src->next())
|
|
param_list = src->param_list_;
|
|
WriteTokenListToFile(file, ttParam, param_list);
|
|
}
|
|
|
|
void ILMethodDef::UpdateTokens()
|
|
{
|
|
if (declaring_type_)
|
|
declaring_type_ = reinterpret_cast<ILTypeDef *>(meta()->token(declaring_type_->id()));
|
|
if (param_list_)
|
|
param_list_ = reinterpret_cast<ILParam *>(meta()->token(param_list_->id()));
|
|
if (locals_)
|
|
locals_ = reinterpret_cast<ILStandAloneSig *>(meta()->token(locals_->id()));
|
|
signature_->UpdateTokens();
|
|
}
|
|
|
|
void ILMethodDef::Rebase(uint64_t delta_base)
|
|
{
|
|
ILToken::Rebase(delta_base);
|
|
|
|
if (address_)
|
|
address_ += delta_base;
|
|
}
|
|
|
|
void ILMethodDef::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(declaring_type_);
|
|
if (it != token_map.end()) {
|
|
declaring_type_ = reinterpret_cast<ILTypeDef*>(it->second);
|
|
if (!declaring_type_)
|
|
set_deleted(true);
|
|
}
|
|
signature_->RemapTokens(token_map);
|
|
}
|
|
|
|
bool ILMethodDef::is_exported() const
|
|
{
|
|
if (declaring_type_->is_exported()) {
|
|
switch (flags_ & mdMemberAccessMask) {
|
|
case mdFamily:
|
|
case mdFamORAssem:
|
|
case mdPublic:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
std::string ILMethodDef::full_name(bool mode, ILSignature *method_gen_signature) const
|
|
{
|
|
return ILName(signature_->ret_name(mode), declaring_type_ ? declaring_type_->full_name() : "<NULL>", name_, signature_->name(mode, method_gen_signature));
|
|
}
|
|
|
|
/**
|
|
* ILMethodImpl
|
|
*/
|
|
|
|
ILMethodImpl::ILMethodImpl(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), class_(0), method_body_(0), method_declaration_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILMethodImpl::ILMethodImpl(ILMetaData *meta, ILTable *owner, const ILMethodImpl &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
class_ = src.class_;
|
|
method_body_ = src.method_body_;
|
|
method_declaration_ = src.method_declaration_;
|
|
}
|
|
|
|
ILToken *ILMethodImpl::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILMethodImpl *token = new ILMethodImpl(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILMethodImpl::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
class_ = reinterpret_cast<ILTypeDef *>(ReadTokenFromFile(file, ttTypeDef));
|
|
method_body_ = ReadTokenFromFile(file, MethodDefRef);
|
|
method_declaration_ = ReadTokenFromFile(file, MethodDefRef);
|
|
}
|
|
|
|
void ILMethodImpl::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, ttTypeDef, class_);
|
|
WriteTokenToFile(file, MethodDefRef, method_body_);
|
|
WriteTokenToFile(file, MethodDefRef, method_declaration_);
|
|
}
|
|
|
|
void ILMethodImpl::UpdateTokens()
|
|
{
|
|
if (class_)
|
|
class_ = reinterpret_cast<ILTypeDef *>(meta()->token(class_->id()));
|
|
if (method_body_)
|
|
method_body_ = meta()->token(method_body_->id());
|
|
if (method_declaration_)
|
|
method_declaration_ = meta()->token(method_declaration_->id());
|
|
}
|
|
|
|
int ILMethodImpl::CompareWith(const ILToken &other) const
|
|
{
|
|
if (other.type() == ttMethodImpl) {
|
|
const ILMethodImpl &obj = reinterpret_cast<const ILMethodImpl &>(other);
|
|
uint32_t self_value = class_ ? class_->value() : 0;
|
|
uint32_t other_value = obj.class_ ? obj.class_->value() : 0;
|
|
if (self_value < other_value)
|
|
return -1;
|
|
if (self_value > other_value)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
return ILToken::CompareWith(other);
|
|
}
|
|
|
|
/**
|
|
* ILMethodImpl
|
|
*/
|
|
|
|
ILMethodSemantics::ILMethodSemantics(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), flags_(CorMethodSemanticsAttr(0)), method_(0), association_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILMethodSemantics::ILMethodSemantics(ILMetaData *meta, ILTable *owner, const ILMethodSemantics &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
flags_ = src.flags_;
|
|
method_ = src.method_;
|
|
association_ = src.association_;
|
|
}
|
|
|
|
ILToken *ILMethodSemantics::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILMethodSemantics *token = new ILMethodSemantics(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILMethodSemantics::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
flags_ = (CorMethodSemanticsAttr)file.ReadWord();
|
|
method_ = reinterpret_cast<ILMethodDef *>(ReadTokenFromFile(file, ttMethodDef));
|
|
association_ = ReadTokenFromFile(file, HasSemantics);
|
|
}
|
|
|
|
void ILMethodSemantics::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(flags_);
|
|
WriteTokenToFile(file, ttMethodDef, method_);
|
|
WriteTokenToFile(file, HasSemantics, association_);
|
|
}
|
|
|
|
void ILMethodSemantics::UpdateTokens()
|
|
{
|
|
if (method_)
|
|
method_ = reinterpret_cast<ILMethodDef *>(meta()->token(method_->id()));
|
|
if (association_)
|
|
association_ = meta()->token(association_->id());
|
|
}
|
|
|
|
void ILMethodSemantics::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(method_);
|
|
if (it != token_map.end()) {
|
|
method_ = reinterpret_cast<ILMethodDef*>(it->second);
|
|
if (!method_)
|
|
set_deleted(true);
|
|
}
|
|
it = token_map.find(association_);
|
|
if (it != token_map.end())
|
|
association_ = it->second;
|
|
}
|
|
|
|
int ILMethodSemantics::CompareWith(const ILToken &other) const
|
|
{
|
|
if (other.type() == ttMethodSemantics) {
|
|
const ILMethodSemantics &obj = reinterpret_cast<const ILMethodSemantics &>(other);
|
|
uint32_t self_value = association_ ? association_->Encode(HasSemantics) : 0;
|
|
uint32_t other_value = obj.association_ ? obj.association_->Encode(HasSemantics) : 0;
|
|
if (self_value < other_value)
|
|
return -1;
|
|
if (self_value > other_value)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
return ILToken::CompareWith(other);
|
|
}
|
|
|
|
/**
|
|
* ILMethodSpec
|
|
*/
|
|
|
|
ILMethodSpec::ILMethodSpec(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), parent_(NULL), instantiation_pos_(0)
|
|
{
|
|
signature_ = new ILSignature(meta);
|
|
}
|
|
|
|
ILMethodSpec::ILMethodSpec(ILMetaData *meta, ILTable *owner, const ILMethodSpec &src)
|
|
: ILToken(meta, owner, src), instantiation_pos_(0)
|
|
{
|
|
parent_ = src.parent_;
|
|
signature_ = src.signature_->Clone(meta);
|
|
}
|
|
|
|
ILMethodSpec::~ILMethodSpec()
|
|
{
|
|
delete signature_;
|
|
}
|
|
|
|
ILToken *ILMethodSpec::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILMethodSpec *token = new ILMethodSpec(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILMethodSpec::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
parent_ = ReadTokenFromFile(file, MethodDefRef);
|
|
signature_->Parse(ReadBlobFromFile(file));
|
|
}
|
|
|
|
void ILMethodSpec::WriteToStreams(ILMetaData &data)
|
|
{
|
|
instantiation_pos_ = data.AddBlob(signature_->data());
|
|
}
|
|
|
|
void ILMethodSpec::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, MethodDefRef, parent_);
|
|
WriteBlobToFile(file, instantiation_pos_);
|
|
}
|
|
|
|
void ILMethodSpec::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = meta()->token(parent_->id());
|
|
signature_->UpdateTokens();
|
|
}
|
|
|
|
void ILMethodSpec::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(parent_);
|
|
if (it != token_map.end()) {
|
|
parent_ = it->second;
|
|
if (!parent_)
|
|
set_deleted(true);
|
|
}
|
|
signature_->RemapTokens(token_map);
|
|
}
|
|
|
|
std::string ILMethodSpec::full_name(bool mode) const
|
|
{
|
|
if (parent_) {
|
|
switch (parent_->type()) {
|
|
case ttMethodDef:
|
|
return reinterpret_cast<ILMethodDef*>(parent_)->full_name(mode, signature_);
|
|
case ttMemberRef:
|
|
return reinterpret_cast<ILMemberRef*>(parent_)->full_name(mode, signature_);
|
|
}
|
|
}
|
|
|
|
return "<NULL>";
|
|
}
|
|
|
|
/**
|
|
* ILModule
|
|
*/
|
|
|
|
ILModule::ILModule(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), generation_(0), name_pos_(0), mv_id_pos_(0), enc_id_pos_(0), enc_base_id_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILModule::ILModule(ILMetaData *meta, ILTable *owner, const std::string &name)
|
|
: ILToken(meta, owner, ttModule), generation_(0), name_pos_(0), mv_id_pos_(0), enc_id_pos_(0), enc_base_id_pos_(0), name_(name)
|
|
{
|
|
for (size_t i = 0; i < 16; i++) {
|
|
mv_id_.push_back(rand());
|
|
}
|
|
}
|
|
|
|
ILModule::ILModule(ILMetaData *meta, ILTable *owner, const ILModule &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
generation_ = src.generation_;
|
|
name_ = src.name_;
|
|
mv_id_ = src.mv_id_;
|
|
enc_id_ = src.enc_id_;
|
|
enc_base_id_ = src.enc_base_id_;
|
|
}
|
|
|
|
ILToken *ILModule::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILModule *token = new ILModule(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILModule::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
generation_ = file.ReadWord();
|
|
name_ = ReadStringFromFile(file);
|
|
mv_id_ = ReadGUIDFromFile(file);
|
|
enc_id_ = ReadGUIDFromFile(file);
|
|
enc_base_id_ = ReadGUIDFromFile(file);
|
|
}
|
|
|
|
void ILModule::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
mv_id_pos_ = data.AddGuid(mv_id_);
|
|
enc_id_pos_ = data.AddGuid(enc_id_);
|
|
enc_base_id_pos_ = data.AddGuid(enc_base_id_);
|
|
}
|
|
|
|
void ILModule::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(generation_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteGuidToFile(file, mv_id_pos_);
|
|
WriteGuidToFile(file, enc_id_pos_);
|
|
WriteGuidToFile(file, enc_base_id_pos_);
|
|
}
|
|
|
|
/**
|
|
* ILModuleRef
|
|
*/
|
|
|
|
ILModuleRef::ILModuleRef(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), name_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILModuleRef::ILModuleRef(ILMetaData *meta, ILTable *owner, const ILModuleRef &src)
|
|
: ILToken(meta, owner, src), name_pos_(0)
|
|
{
|
|
name_ = src.name_;
|
|
}
|
|
|
|
ILToken *ILModuleRef::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILModuleRef *token = new ILModuleRef(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILModuleRef::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
name_ = ReadStringFromFile(file);
|
|
}
|
|
|
|
void ILModuleRef::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
}
|
|
|
|
void ILModuleRef::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteStringToFile(file, name_pos_);
|
|
}
|
|
|
|
/**
|
|
* ILNestedClass
|
|
*/
|
|
|
|
ILNestedClass::ILNestedClass(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), nested_type_(NULL), declaring_type_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
ILNestedClass::ILNestedClass(ILMetaData *meta, ILTable *owner, const ILNestedClass &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
nested_type_ = src.nested_type_;
|
|
declaring_type_ = src.declaring_type_;
|
|
}
|
|
|
|
ILToken *ILNestedClass::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILNestedClass *token = new ILNestedClass(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILNestedClass::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
nested_type_ = reinterpret_cast<ILTypeDef*>(ReadTokenFromFile(file, ttTypeDef));
|
|
declaring_type_ = reinterpret_cast<ILTypeDef*>(ReadTokenFromFile(file, ttTypeDef));
|
|
}
|
|
|
|
void ILNestedClass::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, ttTypeDef, nested_type_);
|
|
WriteTokenToFile(file, ttTypeDef, declaring_type_);
|
|
}
|
|
|
|
void ILNestedClass::UpdateTokens()
|
|
{
|
|
if (nested_type_)
|
|
nested_type_ = reinterpret_cast<ILTypeDef*>(meta()->token(nested_type_->id()));
|
|
if (declaring_type_)
|
|
declaring_type_ = reinterpret_cast<ILTypeDef*>(meta()->token(declaring_type_->id()));
|
|
}
|
|
|
|
void ILNestedClass::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(nested_type_);
|
|
if (it != token_map.end()) {
|
|
nested_type_ = reinterpret_cast<ILTypeDef*>(it->second);
|
|
if (!nested_type_)
|
|
set_deleted(true);
|
|
}
|
|
|
|
it = token_map.find(declaring_type_);
|
|
if (it != token_map.end())
|
|
declaring_type_ = reinterpret_cast<ILTypeDef *>(it->second);
|
|
}
|
|
|
|
/**
|
|
* ILParam
|
|
*/
|
|
|
|
ILParam::ILParam(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), flags_(0), sequence_(0), parent_(NULL), name_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILParam::ILParam(ILMetaData *meta, ILTable *owner, const ILParam &src)
|
|
: ILToken(meta, owner, src), name_pos_(0)
|
|
{
|
|
flags_ = src.flags_;
|
|
sequence_ = src.sequence_;
|
|
name_ = src.name_;
|
|
parent_ = src.parent_;
|
|
}
|
|
|
|
ILToken *ILParam::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILParam *param = new ILParam(meta, owner, *this);
|
|
return param;
|
|
}
|
|
|
|
void ILParam::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
flags_ = file.ReadWord();
|
|
sequence_ = file.ReadWord();
|
|
name_ = ReadStringFromFile(file);
|
|
}
|
|
|
|
void ILParam::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
}
|
|
|
|
void ILParam::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(flags_);
|
|
file.WriteWord(sequence_);
|
|
WriteStringToFile(file, name_pos_);
|
|
}
|
|
|
|
void ILParam::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = reinterpret_cast<ILMethodDef *>(meta()->token(parent_->id()));
|
|
}
|
|
|
|
void ILParam::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(parent_);
|
|
if (it != token_map.end()) {
|
|
parent_ = reinterpret_cast<ILMethodDef *>(it->second);
|
|
if (!parent_)
|
|
set_deleted(true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ILProperty
|
|
*/
|
|
|
|
ILProperty::ILProperty(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), flags_(0), name_pos_(0), type_pos_(0), declaring_type_(NULL)
|
|
{
|
|
type_ = new ILSignature(meta);
|
|
}
|
|
|
|
ILProperty::ILProperty(ILMetaData *meta, ILTable *owner, const ILProperty &src)
|
|
: ILToken(meta, owner, src), name_pos_(0), type_pos_(0)
|
|
{
|
|
flags_ = src.flags_;
|
|
name_ = src.name_;
|
|
type_ = src.type_->Clone(meta);
|
|
declaring_type_ = src.declaring_type_;
|
|
name_pos_ = src.name_pos_;
|
|
type_pos_ = src.type_pos_;
|
|
}
|
|
|
|
ILProperty::~ILProperty()
|
|
{
|
|
delete type_;
|
|
}
|
|
|
|
ILToken *ILProperty::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILProperty *token = new ILProperty(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILProperty::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
flags_ = file.ReadWord();
|
|
name_ = ReadStringFromFile(file);
|
|
type_->Parse(ReadBlobFromFile(file));
|
|
}
|
|
|
|
void ILProperty::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
type_pos_ = data.AddBlob(type_->data());
|
|
}
|
|
|
|
void ILProperty::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteWord(flags_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteBlobToFile(file, type_pos_);
|
|
}
|
|
|
|
void ILProperty::UpdateTokens()
|
|
{
|
|
if (declaring_type_)
|
|
declaring_type_ = reinterpret_cast<ILTypeDef *>(meta()->token(declaring_type_->id()));
|
|
|
|
type_->UpdateTokens();
|
|
}
|
|
|
|
void ILProperty::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(declaring_type_);
|
|
if (it != token_map.end()) {
|
|
declaring_type_ = reinterpret_cast<ILTypeDef *>(it->second);
|
|
if (!declaring_type_)
|
|
set_deleted(true);
|
|
}
|
|
type_->RemapTokens(token_map);
|
|
}
|
|
|
|
bool ILProperty::is_exported() const
|
|
{
|
|
return declaring_type_->is_exported();
|
|
}
|
|
|
|
/**
|
|
* ILPropertyMap
|
|
*/
|
|
|
|
ILPropertyMap::ILPropertyMap(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), parent_(0), property_list_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILPropertyMap::ILPropertyMap(ILMetaData *meta, ILTable *owner, const ILPropertyMap &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
parent_ = src.parent_;
|
|
property_list_ = src.property_list_;
|
|
}
|
|
|
|
ILToken *ILPropertyMap::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILPropertyMap *token = new ILPropertyMap(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILPropertyMap::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
parent_ = reinterpret_cast<ILTypeDef *>(ReadTokenFromFile(file, ttTypeDef));
|
|
property_list_ = reinterpret_cast<ILProperty *>(ReadTokenFromFile(file, ttProperty));
|
|
}
|
|
|
|
void ILPropertyMap::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, ttTypeDef, parent_);
|
|
|
|
ILProperty *property_list = NULL;
|
|
for (ILPropertyMap *src = this; src != NULL && property_list == NULL; src = src->next())
|
|
property_list = src->property_list_;
|
|
WriteTokenListToFile(file, ttProperty, property_list);
|
|
}
|
|
|
|
void ILPropertyMap::UpdateTokens()
|
|
{
|
|
if (parent_)
|
|
parent_ = reinterpret_cast<ILTypeDef *>(meta()->token(parent_->id()));
|
|
}
|
|
|
|
void ILPropertyMap::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(parent_);
|
|
if (it != token_map.end()) {
|
|
parent_ = reinterpret_cast<ILTypeDef *>(it->second);
|
|
if (!parent_)
|
|
set_deleted(true);
|
|
}
|
|
it = token_map.find(property_list_);
|
|
if (it != token_map.end())
|
|
property_list_ = reinterpret_cast<ILProperty *>(it->second);
|
|
}
|
|
|
|
bool ILPropertyMap::is_exported() const
|
|
{
|
|
return parent_->is_exported();
|
|
}
|
|
|
|
/**
|
|
* ILStandAloneSig
|
|
*/
|
|
|
|
ILStandAloneSig::ILStandAloneSig(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), signature_(0), signature_pos_(0)
|
|
{
|
|
signature_ = new ILSignature(meta);
|
|
}
|
|
|
|
ILStandAloneSig::ILStandAloneSig(ILMetaData *meta, ILTable *owner, const ILStandAloneSig &src)
|
|
: ILToken(meta, owner, src), signature_pos_(0)
|
|
{
|
|
signature_ = src.signature_->Clone(meta);
|
|
}
|
|
|
|
ILStandAloneSig::ILStandAloneSig(ILMetaData *meta, ILTable *owner, const ILData &data)
|
|
: ILToken(meta, owner, ttStandAloneSig)
|
|
{
|
|
signature_ = new ILSignature(meta);
|
|
signature_->Parse(data);
|
|
}
|
|
|
|
ILStandAloneSig *ILStandAloneSig::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILStandAloneSig *token = new ILStandAloneSig(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
ILStandAloneSig::~ILStandAloneSig()
|
|
{
|
|
delete signature_;
|
|
}
|
|
|
|
void ILStandAloneSig::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
signature_->Parse(ReadBlobFromFile(file));
|
|
}
|
|
|
|
void ILStandAloneSig::UpdateTokens()
|
|
{
|
|
signature_->UpdateTokens();
|
|
}
|
|
|
|
void ILStandAloneSig::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
signature_->RemapTokens(token_map);
|
|
}
|
|
|
|
void ILStandAloneSig::WriteToStreams(ILMetaData &data)
|
|
{
|
|
signature_pos_ = data.AddBlob(signature_->data());
|
|
}
|
|
|
|
void ILStandAloneSig::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteBlobToFile(file, signature_pos_);
|
|
}
|
|
|
|
std::string ILStandAloneSig::name(bool mode) const
|
|
{
|
|
std::string res;
|
|
if (signature_->is_method())
|
|
res += signature_->ret_name(mode);
|
|
|
|
if (!res.empty())
|
|
res += ' ';
|
|
|
|
return res + signature_->name(mode);
|
|
}
|
|
|
|
/**
|
|
* ILTypeDef
|
|
*/
|
|
|
|
ILTypeDef::ILTypeDef(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), flags_(tdNotPublic), base_type_(NULL), field_list_(NULL), method_list_(NULL), declaring_type_(NULL),
|
|
class_size_(0), name_pos_(0), namespace_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILTypeDef::ILTypeDef(ILMetaData *meta, ILTable *owner, ILToken *base_type, const std::string &name_space, const std::string &name, CorTypeAttr flags)
|
|
: ILToken(meta, owner, ttTypeDef), flags_(flags), base_type_(base_type), field_list_(NULL), method_list_(NULL), declaring_type_(NULL),
|
|
class_size_(0), name_pos_(0), namespace_pos_(0), namespace_(name_space), name_(name)
|
|
{
|
|
|
|
}
|
|
|
|
ILTypeDef::ILTypeDef(ILMetaData *meta, ILTable *owner, const ILTypeDef &src)
|
|
: ILToken(meta, owner, src), name_pos_(0), namespace_pos_(0)
|
|
{
|
|
flags_ = src.flags_;
|
|
name_ = src.name_;
|
|
namespace_ = src.namespace_;
|
|
base_type_ = src.base_type_;
|
|
field_list_ = src.field_list_;
|
|
method_list_ = src.method_list_;
|
|
class_size_ = src.class_size_;
|
|
declaring_type_ = src.declaring_type_;
|
|
}
|
|
|
|
ILToken *ILTypeDef::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILTypeDef *token = new ILTypeDef(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILTypeDef::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
flags_ = static_cast<CorTypeAttr>(file.ReadDWord());
|
|
name_ = ReadStringFromFile(file);
|
|
namespace_ = ReadStringFromFile(file);
|
|
base_type_ = ReadTokenFromFile(file, TypeDefRef);
|
|
field_list_ = reinterpret_cast<ILField *>(ReadTokenFromFile(file, ttField));
|
|
method_list_ = reinterpret_cast<ILMethodDef *>(ReadTokenFromFile(file, ttMethodDef));
|
|
}
|
|
|
|
void ILTypeDef::UpdateTokens()
|
|
{
|
|
if (declaring_type_)
|
|
declaring_type_ = reinterpret_cast<ILTypeDef *>(meta()->token(declaring_type_->id()));
|
|
if (base_type_)
|
|
base_type_ = meta()->token(base_type_->id());
|
|
if (field_list_)
|
|
field_list_ = reinterpret_cast<ILField *>(meta()->token(field_list_->id()));
|
|
if (method_list_)
|
|
method_list_ = reinterpret_cast<ILMethodDef *>(meta()->token(method_list_->id()));
|
|
}
|
|
|
|
void ILTypeDef::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(base_type_);
|
|
if (it != token_map.end())
|
|
base_type_ = it->second;
|
|
it = token_map.find(field_list_);
|
|
if (it != token_map.end())
|
|
field_list_ = reinterpret_cast<ILField *>(it->second);
|
|
it = token_map.find(method_list_);
|
|
if (it != token_map.end())
|
|
method_list_ = reinterpret_cast<ILMethodDef *>(it->second);
|
|
}
|
|
|
|
void ILTypeDef::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
namespace_pos_ = data.AddString(namespace_);
|
|
}
|
|
|
|
void ILTypeDef::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(flags_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteStringToFile(file, namespace_pos_);
|
|
WriteTokenToFile(file, TypeDefRef, base_type_);
|
|
|
|
ILField *field_list = NULL;
|
|
for (ILTypeDef *src = this; src != NULL && field_list == NULL; src = src->next())
|
|
field_list = src->field_list_;
|
|
WriteTokenListToFile(file, ttField, field_list);
|
|
|
|
ILMethodDef *method_list = NULL;
|
|
for (ILTypeDef *src = this; src != NULL && method_list == NULL; src = src->next())
|
|
method_list = src->method_list_;
|
|
WriteTokenListToFile(file, ttMethodDef, method_list);
|
|
}
|
|
|
|
std::string ILTypeDef::full_name() const
|
|
{
|
|
std::string res;
|
|
if (declaring_type_)
|
|
res = declaring_type_->full_name() + '/';
|
|
else {
|
|
res = namespace_;
|
|
if (!res.empty())
|
|
res += '.';
|
|
}
|
|
res += name_;
|
|
|
|
return res;
|
|
}
|
|
|
|
std::string ILTypeDef::reflection_name() const
|
|
{
|
|
std::string res;
|
|
if (declaring_type_)
|
|
res = declaring_type_->full_name() + '+';
|
|
else {
|
|
res = namespace_;
|
|
if (!res.empty())
|
|
res += '.';
|
|
}
|
|
res += name_;
|
|
|
|
return res;
|
|
}
|
|
|
|
bool ILTypeDef::is_exported() const
|
|
{
|
|
const ILTypeDef *type_def = this;
|
|
while (type_def->declaring_type()) {
|
|
if ((type_def->flags() & (tdNestedPublic | tdNestedFamily | tdNestedFamORAssem)) == 0)
|
|
return false;
|
|
type_def = type_def->declaring_type();
|
|
}
|
|
return (type_def->flags() & tdPublic) != 0;
|
|
}
|
|
|
|
void ILTypeDef::AddMethod(ILMethodDef *method)
|
|
{
|
|
size_t pos = NOT_ID;
|
|
ILTable *type_table = meta()->table(ttTypeDef);
|
|
ILTable *method_table = meta()->table(ttMethodDef);
|
|
for (size_t i = type_table->IndexOf(this) + 1; i < type_table->count(); i++) {
|
|
ILTypeDef *next = reinterpret_cast<ILTypeDef *>(type_table->item(i));
|
|
if (next->method_list()) {
|
|
pos = method_table->IndexOf(next->method_list());
|
|
break;
|
|
}
|
|
}
|
|
if (pos == NOT_ID)
|
|
method_table->AddObject(method);
|
|
else
|
|
method_table->InsertObject(pos, method);
|
|
|
|
if (!method_list_)
|
|
method_list_ = method;
|
|
}
|
|
|
|
ILField *ILTypeDef::GetField(const std::string &name) const
|
|
{
|
|
if (field_list_) {
|
|
ILTable *table = meta()->table(ttField);
|
|
for (size_t i = table->IndexOf(field_list_); i < table->count(); i++) {
|
|
ILField *field = reinterpret_cast<ILField *>(table->item(i));
|
|
if (field->declaring_type() != this)
|
|
break;
|
|
|
|
if (field->name() == name)
|
|
return field;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ILMethodDef *ILTypeDef::GetMethod(const std::string &name, ILSignature *signature) const
|
|
{
|
|
if (method_list_) {
|
|
std::string full_name;
|
|
if (signature)
|
|
full_name = ILName(signature->ret_name(), this->full_name(), name, signature->name());
|
|
ILTable *table = meta()->table(ttMethodDef);
|
|
for (size_t i = table->IndexOf(method_list_); i < table->count(); i++) {
|
|
ILMethodDef *method = reinterpret_cast<ILMethodDef *>(table->item(i));
|
|
if (method->declaring_type() != this)
|
|
break;
|
|
|
|
if (signature) {
|
|
if (method->full_name() == full_name)
|
|
return method;
|
|
}
|
|
else {
|
|
if (method->name() == name)
|
|
return method;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ILProperty *ILTypeDef::GetProperty(const std::string &name) const
|
|
{
|
|
ILTable *table = meta()->table(ttProperty);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILProperty *prop = reinterpret_cast<ILProperty *>(table->item(i));
|
|
if (prop->declaring_type() == this && prop->name() == name)
|
|
return prop;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ILEvent *ILTypeDef::GetEvent(const std::string &name) const
|
|
{
|
|
ILTable *table = meta()->table(ttEvent);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILEvent *event = reinterpret_cast<ILEvent *>(table->item(i));
|
|
if (event->declaring_type() == this && event->name() == name)
|
|
return event;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ILTypeDef *ILTypeDef::GetNested(const std::string &name) const
|
|
{
|
|
ILTable *table = meta()->table(ttTypeDef);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef*>(table->item(i));
|
|
if (type_def->declaring_type() == this && type_def->name() == name)
|
|
return type_def;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ILElement *ILTypeDef::GetEnumUnderlyingType() const
|
|
{
|
|
ILTable *table = meta()->table(ttField);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILField *field = reinterpret_cast<ILField*>(table->item(i));
|
|
if (field->declaring_type() == this && (field->flags() & fdStatic) == 0)
|
|
return field->signature()->ret();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool ILTypeDef::FindBaseType(const std::string &name) const
|
|
{
|
|
ILToken *base_type = base_type_;
|
|
while (base_type) {
|
|
ILTypeDef *type_def;
|
|
switch (base_type->type()) {
|
|
case ttTypeRef:
|
|
type_def = reinterpret_cast<ILTypeRef *>(base_type)->Resolve(true);
|
|
break;
|
|
case ttTypeDef:
|
|
type_def = reinterpret_cast<ILTypeDef *>(base_type);
|
|
break;
|
|
default:
|
|
type_def = NULL;
|
|
break;
|
|
}
|
|
|
|
if (!type_def)
|
|
break;
|
|
|
|
if (type_def->full_name() == name)
|
|
return true;
|
|
|
|
base_type = type_def->base_type();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ILTypeDef::FindImplement(const std::string &name) const
|
|
{
|
|
const ILTypeDef *type_def = this;
|
|
while (type_def) {
|
|
ILTable *table = type_def->meta()->table(ttInterfaceImpl);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILInterfaceImpl *impl = reinterpret_cast<ILInterfaceImpl *>(table->item(i));
|
|
if (impl->parent() == type_def) {
|
|
ILToken *token = impl->_interface();
|
|
switch (token->type()) {
|
|
case ttTypeRef:
|
|
if (reinterpret_cast<ILTypeRef *>(token)->full_name() == name)
|
|
return true;
|
|
break;
|
|
case ttTypeDef:
|
|
if (reinterpret_cast<ILTypeDef *>(token)->full_name() == name)
|
|
return true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!type_def->base_type())
|
|
break;
|
|
|
|
ILToken *base_type = type_def->base_type();
|
|
switch (base_type->type()) {
|
|
case ttTypeRef:
|
|
type_def = reinterpret_cast<ILTypeRef *>(base_type)->Resolve(true);
|
|
break;
|
|
case ttTypeDef:
|
|
type_def = reinterpret_cast<ILTypeDef *>(base_type);
|
|
break;
|
|
default:
|
|
type_def = NULL;
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* ILTypeRef
|
|
*/
|
|
|
|
ILTypeRef::ILTypeRef(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), resolution_scope_(NULL), name_pos_(0), namespace_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILTypeRef::ILTypeRef(ILMetaData *meta, ILTable *owner, ILToken *resolution_scope, const std::string &name_space, const std::string &name)
|
|
: ILToken(meta, owner, ttTypeRef), resolution_scope_(resolution_scope), namespace_(name_space), name_(name), name_pos_(0), namespace_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILTypeRef::ILTypeRef(ILMetaData *meta, ILTable *owner, const ILTypeRef &src)
|
|
: ILToken(meta, owner, src), name_pos_(0), namespace_pos_(0)
|
|
{
|
|
resolution_scope_ = src.resolution_scope_;
|
|
name_ = src.name_;
|
|
namespace_ = src.namespace_;
|
|
}
|
|
|
|
ILToken *ILTypeRef::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILTypeRef *token = new ILTypeRef(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
std::string ILTypeRef::module_name() const
|
|
{
|
|
ILTypeRef *declaring_type = this->declaring_type();
|
|
if (declaring_type)
|
|
return declaring_type->module_name();
|
|
|
|
ILToken *scope = this->resolution_scope();
|
|
if (scope) {
|
|
switch (scope->type()) {
|
|
case ttAssemblyRef:
|
|
return reinterpret_cast<ILAssemblyRef*>(scope)->name();
|
|
case ttModuleRef:
|
|
return reinterpret_cast<ILModuleRef*>(scope)->name();
|
|
}
|
|
}
|
|
|
|
return std::string();
|
|
}
|
|
|
|
ILTypeRef *ILTypeRef::declaring_type() const
|
|
{
|
|
ILToken *scope = this->resolution_scope();
|
|
if (scope && scope->type() == ttTypeRef)
|
|
return reinterpret_cast<ILTypeRef*>(scope);
|
|
return NULL;
|
|
}
|
|
|
|
std::string ILTypeRef::full_name(bool mode) const
|
|
{
|
|
std::string res;
|
|
|
|
res = namespace_;
|
|
if (!res.empty())
|
|
res += '.';
|
|
res += name_;
|
|
|
|
ILTypeRef *declaring_type = this->declaring_type();
|
|
while (declaring_type) {
|
|
res = declaring_type->full_name() + '/' + res;
|
|
declaring_type = declaring_type->declaring_type();
|
|
}
|
|
|
|
if (mode)
|
|
res = '[' + module_name() + ']' + res;
|
|
|
|
return res;
|
|
}
|
|
|
|
void ILTypeRef::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
resolution_scope_ = ReadTokenFromFile(file, ResolutionScope);
|
|
name_ = ReadStringFromFile(file);
|
|
namespace_ = ReadStringFromFile(file);
|
|
}
|
|
|
|
void ILTypeRef::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
namespace_pos_ = data.AddString(namespace_);
|
|
}
|
|
|
|
void ILTypeRef::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteTokenToFile(file, ResolutionScope, resolution_scope_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteStringToFile(file, namespace_pos_);
|
|
}
|
|
|
|
void ILTypeRef::UpdateTokens()
|
|
{
|
|
if (resolution_scope_)
|
|
resolution_scope_ = meta()->token(resolution_scope_->id());
|
|
}
|
|
|
|
void ILTypeRef::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
std::map<ILToken*, ILToken*>::const_iterator it = token_map.find(resolution_scope_);
|
|
if (it != token_map.end())
|
|
resolution_scope_ = it->second;
|
|
}
|
|
|
|
ILTypeDef *ILTypeRef::Resolve(bool show_error) const
|
|
{
|
|
return meta()->Resolve(this, show_error);
|
|
}
|
|
|
|
/**
|
|
* ILTypeSpec
|
|
*/
|
|
|
|
ILTypeSpec::ILTypeSpec(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), signature_pos_(0)
|
|
{
|
|
signature_ = new ILElement(meta, NULL);
|
|
}
|
|
|
|
ILTypeSpec::ILTypeSpec(ILMetaData *meta, ILTable *owner, const ILTypeSpec &src)
|
|
: ILToken(meta, owner, src), signature_pos_(0)
|
|
{
|
|
signature_ = src.signature_->Clone(meta, NULL);
|
|
}
|
|
|
|
ILTypeSpec::ILTypeSpec(ILMetaData *meta, ILTable *owner, ILData &data)
|
|
: ILToken(meta, owner, ttTypeSpec)
|
|
{
|
|
signature_ = new ILElement(meta, NULL);
|
|
signature_->Parse(data);
|
|
}
|
|
|
|
ILTypeSpec::~ILTypeSpec()
|
|
{
|
|
delete signature_;
|
|
}
|
|
|
|
ILToken *ILTypeSpec::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILTypeSpec *token = new ILTypeSpec(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILTypeSpec::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
signature_->Parse(ReadBlobFromFile(file));
|
|
}
|
|
|
|
void ILTypeSpec::WriteToStreams(ILMetaData &data)
|
|
{
|
|
signature_pos_ = data.AddBlob(signature_->data());
|
|
}
|
|
|
|
void ILTypeSpec::WriteToFile(NETArchitecture &file)
|
|
{
|
|
WriteBlobToFile(file, signature_pos_);
|
|
}
|
|
|
|
void ILTypeSpec::UpdateTokens()
|
|
{
|
|
signature_->UpdateTokens();
|
|
}
|
|
|
|
void ILTypeSpec::RemapTokens(const std::map<ILToken*, ILToken*> &token_map)
|
|
{
|
|
signature_->RemapTokens(token_map);
|
|
}
|
|
|
|
/**
|
|
* ILUserString
|
|
*/
|
|
|
|
ILUserString::ILUserString(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id)
|
|
{
|
|
name_ = ReadUserString(value());
|
|
}
|
|
|
|
ILUserString::ILUserString(ILMetaData *meta, ILTable *owner, const ILUserString &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
name_ = src.name_;
|
|
}
|
|
|
|
ILToken *ILUserString::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILToken *token = new ILUserString(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
/**
|
|
* ILExportedType
|
|
*/
|
|
|
|
ILExportedType::ILExportedType(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), flags_(0), type_def_id_(0), implementation_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
ILExportedType::ILExportedType(ILMetaData *meta, ILTable *owner, const ILExportedType &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
flags_ = src.flags_;
|
|
type_def_id_ = src.type_def_id_;
|
|
name_ = src.name_;
|
|
namespace_ = src.namespace_;
|
|
implementation_ = src.implementation_;
|
|
}
|
|
|
|
ILToken *ILExportedType::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILToken *token = new ILExportedType(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILExportedType::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
flags_ = file.ReadDWord();
|
|
type_def_id_ = file.ReadDWord();
|
|
name_ = ReadStringFromFile(file);
|
|
namespace_ = ReadStringFromFile(file);
|
|
implementation_ = ReadTokenFromFile(file, Implementation);
|
|
}
|
|
|
|
void ILExportedType::WriteToStreams(ILMetaData &data)
|
|
{
|
|
name_pos_ = data.AddString(name_);
|
|
namespace_pos_ = data.AddString(namespace_);
|
|
}
|
|
|
|
void ILExportedType::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(flags_);
|
|
file.WriteDWord(type_def_id_);
|
|
WriteStringToFile(file, name_pos_);
|
|
WriteStringToFile(file, namespace_pos_);
|
|
WriteTokenToFile(file, Implementation, implementation_);
|
|
}
|
|
|
|
void ILExportedType::UpdateTokens()
|
|
{
|
|
if (implementation_)
|
|
implementation_ = meta()->token(implementation_->id());
|
|
}
|
|
|
|
ILExportedType *ILExportedType::declaring_type() const
|
|
{
|
|
ILToken *scope = implementation();
|
|
if (scope && scope->type() == ttExportedType)
|
|
return reinterpret_cast<ILExportedType*>(scope);
|
|
return NULL;
|
|
}
|
|
|
|
std::string ILExportedType::full_name() const
|
|
{
|
|
std::string res;
|
|
|
|
res = namespace_;
|
|
if (!res.empty())
|
|
res += '.';
|
|
res += name_;
|
|
|
|
ILExportedType *declaring_type = this->declaring_type();
|
|
while (declaring_type) {
|
|
res = declaring_type->full_name() + '/' + res;
|
|
declaring_type = declaring_type->declaring_type();
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* ILENCLog
|
|
*/
|
|
|
|
ILEncLog::ILEncLog(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), token_(0), func_code_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILEncLog::ILEncLog(ILMetaData *meta, ILTable *owner, const ILEncLog &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
token_ = src.token_;
|
|
func_code_ = src.func_code_;
|
|
}
|
|
|
|
ILToken *ILEncLog::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILToken *token = new ILEncLog(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILEncLog::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
token_ = file.ReadDWord();
|
|
func_code_ = file.ReadDWord();
|
|
}
|
|
|
|
void ILEncLog::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(token_);
|
|
file.WriteDWord(func_code_);
|
|
}
|
|
|
|
/**
|
|
* ILENCMap
|
|
*/
|
|
|
|
ILEncMap::ILEncMap(ILMetaData *meta, ILTable *owner, uint32_t id)
|
|
: ILToken(meta, owner, id), token_(0)
|
|
{
|
|
|
|
}
|
|
|
|
ILEncMap::ILEncMap(ILMetaData *meta, ILTable *owner, const ILEncMap &src)
|
|
: ILToken(meta, owner, src)
|
|
{
|
|
token_ = src.token_;
|
|
}
|
|
|
|
ILToken *ILEncMap::Clone(ILMetaData *meta, ILTable *owner) const
|
|
{
|
|
ILToken *token = new ILEncMap(meta, owner, *this);
|
|
return token;
|
|
}
|
|
|
|
void ILEncMap::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
token_ = file.ReadDWord();
|
|
}
|
|
|
|
void ILEncMap::WriteToFile(NETArchitecture &file)
|
|
{
|
|
file.WriteDWord(token_);
|
|
}
|
|
|
|
/**
|
|
* ILTable
|
|
*/
|
|
|
|
ILTable::ILTable(ILMetaData *meta, ILTokenType type, uint32_t token_count)
|
|
: ObjectList<ILToken>(), meta_(meta), type_(type)
|
|
{
|
|
for (uint32_t i = 1; i <= token_count; i++) {
|
|
Add(type_ | i);
|
|
}
|
|
}
|
|
|
|
ILTable::ILTable(ILMetaData *meta, const ILTable &src)
|
|
: ObjectList<ILToken>(), meta_(meta)
|
|
{
|
|
type_ = src.type_;
|
|
|
|
for (size_t i = 0; i < src.count(); i++) {
|
|
AddObject(src.item(i)->Clone(meta, this));
|
|
}
|
|
}
|
|
|
|
ILTable *ILTable::Clone(ILMetaData *meta) const
|
|
{
|
|
ILTable *table = new ILTable(meta, *this);
|
|
return table;
|
|
}
|
|
|
|
ILToken *ILTable::Add(uint32_t id)
|
|
{
|
|
ILToken *token = NULL;
|
|
switch (type_) {
|
|
case ttAssembly:
|
|
token = new ILAssembly(meta_, this, id);
|
|
break;
|
|
case ttAssemblyOS:
|
|
token = new ILAssemblyOS(meta_, this, id);
|
|
break;
|
|
case ttAssemblyProcessor:
|
|
token = new ILAssemblyProcessor(meta_, this, id);
|
|
break;
|
|
case ttAssemblyRef:
|
|
token = new ILAssemblyRef(meta_, this, id);
|
|
break;
|
|
case ttAssemblyRefOS:
|
|
token = new ILAssemblyRefOS(meta_, this, id);
|
|
break;
|
|
case ttAssemblyRefProcessor:
|
|
token = new ILAssemblyRefProcessor(meta_, this, id);
|
|
break;
|
|
case ttClassLayout:
|
|
token = new ILClassLayout(meta_, this, id);
|
|
break;
|
|
case ttConstant:
|
|
token = new ILConstant(meta_, this, id);
|
|
break;
|
|
case ttCustomAttribute:
|
|
token = new ILCustomAttribute(meta_, this, id);
|
|
break;
|
|
case ttDeclSecurity:
|
|
token = new ILDeclSecurity(meta_, this, id);
|
|
break;
|
|
case ttEvent:
|
|
token = new ILEvent(meta_, this, id);
|
|
break;
|
|
case ttEventMap:
|
|
token = new ILEventMap(meta_, this, id);
|
|
break;
|
|
case ttField:
|
|
token = new ILField(meta_, this, id);
|
|
break;
|
|
case ttFieldLayout:
|
|
token = new ILFieldLayout(meta_, this, id);
|
|
break;
|
|
case ttFieldMarshal:
|
|
token = new ILFieldMarshal(meta_, this, id);
|
|
break;
|
|
case ttFieldRVA:
|
|
token = new ILFieldRVA(meta_, this, id);
|
|
break;
|
|
case ttFile:
|
|
token = new ILFile(meta_, this, id);
|
|
break;
|
|
case ttGenericParam:
|
|
token = new ILGenericParam(meta_, this, id);
|
|
break;
|
|
case ttGenericParamConstraint:
|
|
token = new ILGenericParamConstraint(meta_, this, id);
|
|
break;
|
|
case ttImplMap:
|
|
token = new ILImplMap(meta_, this, id);
|
|
break;
|
|
case ttInterfaceImpl:
|
|
token = new ILInterfaceImpl(meta_, this, id);
|
|
break;
|
|
case ttManifestResource:
|
|
token = new ILManifestResource(meta_, this, id);
|
|
break;
|
|
case ttMemberRef:
|
|
token = new ILMemberRef(meta_, this, id);
|
|
break;
|
|
case ttMethodDef:
|
|
token = new ILMethodDef(meta_, this, id);
|
|
break;
|
|
case ttMethodImpl:
|
|
token = new ILMethodImpl(meta_, this, id);
|
|
break;
|
|
case ttMethodSemantics:
|
|
token = new ILMethodSemantics(meta_, this, id);
|
|
break;
|
|
case ttMethodSpec:
|
|
token = new ILMethodSpec(meta_, this, id);
|
|
break;
|
|
case ttModule:
|
|
token = new ILModule(meta_, this, id);
|
|
break;
|
|
case ttModuleRef:
|
|
token = new ILModuleRef(meta_, this, id);
|
|
break;
|
|
case ttNestedClass:
|
|
token = new ILNestedClass(meta_, this, id);
|
|
break;
|
|
case ttParam:
|
|
token = new ILParam(meta_, this, id);
|
|
break;
|
|
case ttProperty:
|
|
token = new ILProperty(meta_, this, id);
|
|
break;
|
|
case ttPropertyMap:
|
|
token = new ILPropertyMap(meta_, this, id);
|
|
break;
|
|
case ttStandAloneSig:
|
|
token = new ILStandAloneSig(meta_, this, id);
|
|
break;
|
|
case ttTypeDef:
|
|
token = new ILTypeDef(meta_, this, id);
|
|
break;
|
|
case ttTypeRef:
|
|
token = new ILTypeRef(meta_, this, id);
|
|
break;
|
|
case ttTypeSpec:
|
|
token = new ILTypeSpec(meta_, this, id);
|
|
break;
|
|
case ttUserString:
|
|
token = new ILUserString(meta_, this, id);
|
|
break;
|
|
case ttExportedType:
|
|
token = new ILExportedType(meta_, this, id);
|
|
break;
|
|
case ttEncLog:
|
|
token = new ILEncLog(meta_, this, id);
|
|
break;
|
|
case ttEncMap:
|
|
token = new ILEncMap(meta_, this, id);
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Unknown token type");
|
|
}
|
|
|
|
AddObject(token);
|
|
return token;
|
|
}
|
|
|
|
void ILTable::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->ReadFromFile(file);
|
|
}
|
|
}
|
|
|
|
void ILTable::WriteToStreams(ILMetaData &data)
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->WriteToStreams(data);
|
|
}
|
|
}
|
|
|
|
void ILTable::WriteToFile(NETArchitecture &file)
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->WriteToFile(file);
|
|
}
|
|
}
|
|
|
|
void ILTable::Rebase(uint64_t delta_base)
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->Rebase(delta_base);
|
|
}
|
|
}
|
|
|
|
void ILTable::Pack()
|
|
{
|
|
size_t i;
|
|
ILToken *token;
|
|
|
|
for (i = count(); i > 0; i--) {
|
|
token = item(i - 1);
|
|
if (token->is_deleted())
|
|
delete token;
|
|
}
|
|
}
|
|
|
|
void ILTable::UpdateTokens()
|
|
{
|
|
size_t i, j;
|
|
ILToken *token;
|
|
|
|
IArchitecture *file = meta_->owner();
|
|
if (type_ == ttUserString) {
|
|
for (i = 0; i < count(); i++) {
|
|
ILUserString *user_string = reinterpret_cast<ILUserString*>(item(i));
|
|
bool has_references = false;
|
|
for (j = 0; j < user_string->reference_list()->count(); j++) {
|
|
if (!user_string->reference_list()->item(j)->is_deleted()) {
|
|
has_references = true;
|
|
break;
|
|
}
|
|
}
|
|
if (has_references)
|
|
user_string->set_value(meta_->AddUserString(user_string->name()), file);
|
|
}
|
|
} else {
|
|
uint32_t id = 1;
|
|
for (i = 0; i < count(); i++) {
|
|
token = item(i);
|
|
if (token->is_deleted())
|
|
continue;
|
|
|
|
token->set_value(id++, file);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* NETImportFunction
|
|
*/
|
|
|
|
NETImportFunction::NETImportFunction(NETImport *owner, uint32_t token, const std::string &name, size_t name_pos)
|
|
: BaseImportFunction(owner), token_(token), name_(name), name_pos_(name_pos)
|
|
{
|
|
|
|
}
|
|
|
|
NETImportFunction::NETImportFunction(NETImport *owner, const NETImportFunction &src)
|
|
: BaseImportFunction(owner, src)
|
|
{
|
|
token_ = src.token_;
|
|
name_ = src.name_;
|
|
name_pos_ = src.name_pos_;
|
|
}
|
|
|
|
NETImportFunction *NETImportFunction::Clone(IImport *owner) const
|
|
{
|
|
NETImportFunction *func = new NETImportFunction(reinterpret_cast<NETImport *>(owner), *this);
|
|
return func;
|
|
}
|
|
|
|
/**
|
|
* NETImport
|
|
*/
|
|
|
|
NETImport::NETImport(NETImportList *owner, uint32_t token, const std::string &name)
|
|
: BaseImport(owner), token_(token), name_(name), is_sdk_(false)
|
|
{
|
|
|
|
}
|
|
|
|
NETImport::NETImport(NETImportList *owner, const NETImport &src)
|
|
: BaseImport(owner, src)
|
|
{
|
|
token_ = src.token_;
|
|
name_ = src.name_;
|
|
is_sdk_ = src.is_sdk_;
|
|
}
|
|
|
|
NETImportFunction *NETImport::item(size_t index) const
|
|
{
|
|
return reinterpret_cast<NETImportFunction *>(BaseImport::item(index));
|
|
}
|
|
|
|
NETImport *NETImport::Clone(IImportList *owner) const
|
|
{
|
|
NETImport *import = new NETImport(reinterpret_cast<NETImportList *>(owner), *this);
|
|
return import;
|
|
}
|
|
|
|
NETImportFunction *NETImport::Add(uint32_t token, const std::string &name, size_t name_pos)
|
|
{
|
|
NETImportFunction *func = new NETImportFunction(this, token, name, name_pos);
|
|
AddObject(func);
|
|
return func;
|
|
}
|
|
|
|
NETImportFunction *NETImport::GetFunctionByToken(uint32_t token) const
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
NETImportFunction *func = item(i);
|
|
if (func->token() == token)
|
|
return func;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* NETImportList
|
|
*/
|
|
|
|
NETImportList::NETImportList(NETArchitecture *owner)
|
|
: BaseImportList(owner)
|
|
{
|
|
|
|
}
|
|
|
|
NETImportList::NETImportList(NETArchitecture *owner, const NETImportList &src)
|
|
: BaseImportList(owner, src)
|
|
{
|
|
|
|
}
|
|
|
|
NETImportList *NETImportList::Clone(NETArchitecture *owner) const
|
|
{
|
|
NETImportList *list = new NETImportList(owner, *this);
|
|
return list;
|
|
}
|
|
|
|
NETImport *NETImportList::GetImportByName(const std::string &name) const
|
|
{
|
|
return reinterpret_cast<NETImport *>(BaseImportList::GetImportByName(name));
|
|
}
|
|
|
|
NETImport *NETImportList::item(size_t index) const
|
|
{
|
|
return reinterpret_cast<NETImport *>(BaseImportList::item(index));
|
|
}
|
|
|
|
NETImportFunction *NETImportList::GetFunctionByToken(uint32_t token) const
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
NETImportFunction *func = item(i)->GetFunctionByToken(token);
|
|
if (func)
|
|
return func;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
NETImport *NETImportList::Add(uint32_t token, const std::string &name)
|
|
{
|
|
NETImport *import = new NETImport(this, token, name);
|
|
AddObject(import);
|
|
return import;
|
|
}
|
|
|
|
void NETImportList::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
static const ImportInfo sdk_info[] = {
|
|
{atBegin, "void VMProtect.Begin::.ctor()", ioNone, ctNone},
|
|
{atBegin, "void VMProtect.BeginVirtualization::.ctor()", ioHasCompilationType, ctVirtualization},
|
|
{atBegin, "void VMProtect.BeginMutation::.ctor()", ioHasCompilationType, ctMutation},
|
|
{atBegin, "void VMProtect.BeginUltra::.ctor()", ioHasCompilationType, ctUltra},
|
|
{atBegin, "void VMProtect.BeginVirtualizationLockByKey::.ctor()", ioHasCompilationType | ioLockToKey, ctVirtualization},
|
|
{atBegin, "void VMProtect.BeginUltraLockByKey::.ctor()", ioHasCompilationType | ioLockToKey, ctUltra},
|
|
{atIsProtected, "bool VMProtect.SDK::IsProtected()", ioNone, ctNone},
|
|
{atIsVirtualMachinePresent, "bool VMProtect.SDK::IsVirtualMachinePresent()", ioNone, ctNone},
|
|
{atIsDebuggerPresent, "bool VMProtect.SDK::IsDebuggerPresent(bool)", ioNone, ctNone},
|
|
{atIsValidImageCRC, "bool VMProtect.SDK::IsValidImageCRC()", ioNone, ctNone},
|
|
{atDecryptStringA, "string VMProtect.SDK::DecryptString(string)", ioNone, ctNone},
|
|
{atFreeString, "bool VMProtect.SDK::FreeString(string&)", ioNone, ctNone },
|
|
{atSetSerialNumber, "valuetype VMProtect.SerialState VMProtect.SDK::SetSerialNumber(string)", ioNone, ctNone},
|
|
{atGetSerialNumberState, "valuetype VMProtect.SerialState VMProtect.SDK::GetSerialNumberState()", ioNone, ctNone},
|
|
{atGetSerialNumberData, "bool VMProtect.SDK::GetSerialNumberData(class VMProtect.SerialNumberData&)", ioNone, ctNone},
|
|
{atGetCurrentHWID, "string VMProtect.SDK::GetCurrentHWID()", ioNone, ctNone},
|
|
{atActivateLicense, "valuetype VMProtect.ActivationStatus VMProtect.SDK::ActivateLicense(string, string&)", ioNone, ctNone},
|
|
{atDeactivateLicense, "valuetype VMProtect.ActivationStatus VMProtect.SDK::DeactivateLicense(string)", ioNone, ctNone},
|
|
{atGetOfflineActivationString, "valuetype VMProtect.ActivationStatus VMProtect.SDK::GetOfflineActivationString(string, string&)", ioNone, ctNone},
|
|
{atGetOfflineDeactivationString, "valuetype VMProtect.ActivationStatus VMProtect.SDK::GetOfflineDeactivationString(string, string&)", ioNone, ctNone}
|
|
};
|
|
|
|
size_t i;
|
|
std::map<ILToken *, NETImport *> import_map;
|
|
std::map<ILToken *, NETImport *> type_map;
|
|
NETImport *import;
|
|
|
|
ILTable *table = file.command_list()->table(ttAssemblyRef);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILAssemblyRef *assembly_ref = reinterpret_cast<ILAssemblyRef *>(table->item(i));
|
|
std::string module_name = assembly_ref->name();
|
|
|
|
import = GetImportByName(module_name);
|
|
if (!import) {
|
|
import = Add(assembly_ref->id(), module_name);
|
|
std::transform(module_name.begin(), module_name.end(), module_name.begin(), tolower);
|
|
if (module_name == "vmprotect.sdk")
|
|
import->set_is_sdk(true);
|
|
}
|
|
import_map[assembly_ref] = import;
|
|
}
|
|
|
|
table = file.command_list()->table(ttTypeRef);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILTypeRef *type_ref = reinterpret_cast<ILTypeRef *>(table->item(i));
|
|
std::map<ILToken *, NETImport *>::const_iterator it = import_map.find(type_ref->resolution_scope());
|
|
if (it == import_map.end())
|
|
continue;
|
|
|
|
import = it->second;
|
|
type_map[type_ref] = import;
|
|
import->Add(type_ref->id(), type_ref->full_name(), 0);
|
|
}
|
|
|
|
|
|
table = file.command_list()->table(ttTypeSpec);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILTypeSpec *type_spec = reinterpret_cast<ILTypeSpec *>(table->item(i));
|
|
ILToken *token = NULL;
|
|
|
|
switch (type_spec->info()->type()) {
|
|
case ELEMENT_TYPE_GENERICINST:
|
|
token = type_spec->info()->next()->token();
|
|
break;
|
|
case ELEMENT_TYPE_VALUETYPE:
|
|
case ELEMENT_TYPE_CLASS:
|
|
token = type_spec->info()->token();
|
|
break;
|
|
}
|
|
|
|
if (!token || (token->type() != ttTypeRef))
|
|
continue;
|
|
|
|
std::map<ILToken *, NETImport *>::const_iterator it = import_map.find(reinterpret_cast<ILTypeRef *>(token)->resolution_scope());
|
|
if (it == import_map.end())
|
|
continue;
|
|
|
|
import = it->second;
|
|
type_map[type_spec] = import;
|
|
import->Add(type_spec->id(), type_spec->name(), 0);
|
|
}
|
|
|
|
table = file.command_list()->table(ttMemberRef);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILMemberRef *member_ref = reinterpret_cast<ILMemberRef*>(table->item(i));
|
|
std::map<ILToken *, NETImport *>::const_iterator it = type_map.find(member_ref->declaring_type());
|
|
if (it == type_map.end())
|
|
continue;
|
|
|
|
import = it->second;
|
|
std::string ret_name = member_ref->signature()->ret_name();
|
|
NETImportFunction *func = import->Add(member_ref->id(), member_ref->full_name(), ret_name.empty() ? 0 : ret_name.size() + 1);
|
|
if (import->is_sdk()) {
|
|
for (size_t i = 0; i < _countof(sdk_info); i++) {
|
|
const ImportInfo *import_info = &sdk_info[i];
|
|
if (func->name().compare(import_info->name) == 0) {
|
|
func->set_type(import_info->type);
|
|
if (import_info->options & ioHasCompilationType) {
|
|
func->include_option(ioHasCompilationType);
|
|
func->set_compilation_type(import_info->compilation_type);
|
|
if (import_info->options & ioLockToKey)
|
|
func->include_option(ioLockToKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
table = file.command_list()->table(ttModuleRef);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILModuleRef *module_ref = reinterpret_cast<ILModuleRef *>(table->item(i));
|
|
|
|
import = GetImportByName(module_ref->name());
|
|
if (!import)
|
|
import = Add(module_ref->id(), module_ref->name());
|
|
import_map[module_ref] = import;
|
|
}
|
|
|
|
table = file.command_list()->table(ttImplMap);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILImplMap *impl_map = reinterpret_cast<ILImplMap*>(table->item(i));
|
|
std::map<ILToken *, NETImport *>::const_iterator it = import_map.find(impl_map->import_scope());
|
|
if (it == import_map.end())
|
|
continue;
|
|
|
|
import = it->second;
|
|
NETImportFunction *func = import->Add(impl_map->id(), impl_map->import_name(), 0);
|
|
}
|
|
}
|
|
|
|
void NETImportList::Pack()
|
|
{
|
|
size_t i, j, k;
|
|
std::map<ILToken *, ILToken *> type_map;
|
|
ILMetaData *meta = reinterpret_cast<NETArchitecture*>(owner())->command_list();
|
|
|
|
ILTable *type_def_table = meta->table(ttTypeDef);
|
|
ILTable *field_table = meta->table(ttField);
|
|
ILTable *method_table = meta->table(ttMethodDef);
|
|
ILTable *custom_attribute_table = meta->table(ttCustomAttribute);
|
|
for (i = 0; i < count(); i++) {
|
|
NETImport *import = item(i);
|
|
if (!import->is_sdk())
|
|
continue;
|
|
|
|
ILToken *token = meta->token(import->token());
|
|
token->set_deleted(true);
|
|
|
|
for (j = 0; j < import->count(); j++) {
|
|
NETImportFunction *func = import->item(j);
|
|
|
|
token = meta->token(func->token());
|
|
switch (token->type()) {
|
|
case ttTypeRef:
|
|
{
|
|
ILTypeRef *type_ref = reinterpret_cast<ILTypeRef *>(token);
|
|
for (k = 0; k < type_def_table->count(); k++) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(type_def_table->item(k));
|
|
if (type_def->full_name() == type_ref->full_name()) {
|
|
type_map[type_ref] = type_def;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case ttMemberRef:
|
|
{
|
|
ILMemberRef *member_ref = reinterpret_cast<ILMemberRef*>(meta->token(func->token()));
|
|
ILToken *declaring_type = member_ref->declaring_type();
|
|
if (declaring_type && declaring_type->type() == ttTypeRef) {
|
|
ILTypeRef *type_ref = reinterpret_cast<ILTypeRef *>(declaring_type);
|
|
if (func->type() == atNone) {
|
|
std::string name = member_ref->full_name();
|
|
if (member_ref->signature()->is_field()) {
|
|
// field
|
|
for (k = 0; k < field_table->count(); k++) {
|
|
ILField *field = reinterpret_cast<ILField *>(field_table->item(k));
|
|
if (field->full_name() == name) {
|
|
type_map[member_ref] = field;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
// method
|
|
for (k = 0; k < method_table->count(); k++) {
|
|
ILMethodDef *method = reinterpret_cast<ILMethodDef *>(method_table->item(k));
|
|
if (method->full_name() == name) {
|
|
type_map[member_ref] = method;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
type_ref->set_deleted(true);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!type_map.empty()) {
|
|
for (std::map<ILToken *, ILToken *>::const_iterator it = type_map.begin(); it != type_map.end(); it++) {
|
|
ILToken *src_token = it->first;
|
|
ILToken *dst_token = it->second;
|
|
src_token->set_deleted(true);
|
|
|
|
while (src_token->reference_list()->count()) {
|
|
TokenReference *reference = src_token->reference_list()->item(0);
|
|
reference->set_owner(dst_token->reference_list());
|
|
}
|
|
if (dst_token->value() != src_token->value())
|
|
dst_token->set_value(0);
|
|
}
|
|
|
|
for (i = 0; i < 64; i++) {
|
|
ILTable *table = meta->table(static_cast<ILTokenType>(i << 24));
|
|
for (size_t j = 0; j < table->count(); j++) {
|
|
table->item(j)->RemapTokens(type_map);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* NETExport
|
|
*/
|
|
|
|
NETExport::NETExport(NETExportList *owner, uint64_t address, const std::string &name, size_t name_pos)
|
|
: BaseExport(owner), address_(address), name_(name), name_pos_(name_pos)
|
|
{
|
|
|
|
}
|
|
|
|
NETExport::NETExport(NETExportList *owner, const NETExport &src)
|
|
: BaseExport(owner, src)
|
|
{
|
|
address_ = src.address_;
|
|
name_ = src.name_;
|
|
name_pos_ = src.name_pos_;
|
|
}
|
|
|
|
NETExport *NETExport::Clone(IExportList *owner) const
|
|
{
|
|
NETExport *exp = new NETExport(reinterpret_cast<NETExportList *>(owner), *this);
|
|
return exp;
|
|
}
|
|
|
|
void NETExport::Rebase(uint64_t delta_base)
|
|
{
|
|
address_ += delta_base;
|
|
}
|
|
|
|
/**
|
|
* NETExportList
|
|
*/
|
|
|
|
NETExportList::NETExportList(NETArchitecture *owner)
|
|
: BaseExportList(owner)
|
|
{
|
|
|
|
}
|
|
|
|
NETExportList::NETExportList(NETArchitecture *owner, const NETExportList &src)
|
|
: BaseExportList(owner, src)
|
|
{
|
|
|
|
}
|
|
|
|
NETExportList *NETExportList::Clone(NETArchitecture *owner) const
|
|
{
|
|
NETExportList *list = new NETExportList(owner, *this);
|
|
return list;
|
|
}
|
|
|
|
IExport *NETExportList::Add(uint64_t address)
|
|
{
|
|
return Add(address, "", 0);
|
|
}
|
|
|
|
NETExport *NETExportList::Add(uint64_t address, const std::string &name, size_t name_pos)
|
|
{
|
|
NETExport *exp = new NETExport(this, address, name, name_pos);
|
|
AddObject(exp);
|
|
return exp;
|
|
}
|
|
|
|
void NETExportList::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
ILTable *table = file.command_list()->table(ttMethodDef);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILMethodDef *method = reinterpret_cast<ILMethodDef *>(table->item(i));
|
|
if (!method->declaring_type() || (method->flags() & mdMemberAccessMask) != mdPublic)
|
|
continue;
|
|
|
|
std::string ret_name = method->signature()->ret_name();
|
|
Add(method->address(), method->full_name(), ret_name.empty() ? 0 : ret_name.size() + 1);
|
|
}
|
|
}
|
|
|
|
void NETExportList::ReadFromBuffer(Buffer &buffer, IArchitecture &file)
|
|
{
|
|
static const APIType export_function_types[] = {
|
|
atSetupImage,
|
|
atDecryptStringA,
|
|
atDecryptStringW,
|
|
atFreeString,
|
|
atSetSerialNumber,
|
|
atGetSerialNumberState,
|
|
atGetSerialNumberData,
|
|
atGetCurrentHWID,
|
|
atActivateLicense,
|
|
atDeactivateLicense,
|
|
atGetOfflineActivationString,
|
|
atGetOfflineDeactivationString,
|
|
atIsValidImageCRC,
|
|
atIsDebuggerPresent,
|
|
atIsVirtualMachinePresent,
|
|
atDecryptBuffer,
|
|
atIsProtected,
|
|
atLoaderData,
|
|
atRandom,
|
|
atCalcCRC,
|
|
atBoxPointer,
|
|
atUnboxPointer
|
|
};
|
|
|
|
clear();
|
|
BaseExportList::ReadFromBuffer(buffer, file);
|
|
|
|
assert(count() == _countof(export_function_types));
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->set_type(export_function_types[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* NETRuntimeFunction
|
|
*/
|
|
|
|
NETRuntimeFunction::NETRuntimeFunction(NETRuntimeFunctionList *owner, uint64_t begin, uint64_t end, uint64_t start, ILMethodDef *method)
|
|
: BaseRuntimeFunction(owner), begin_(begin), end_(end), start_(start)
|
|
{
|
|
if (method)
|
|
method_list_.push_back(method);
|
|
}
|
|
|
|
NETRuntimeFunction::NETRuntimeFunction(NETRuntimeFunctionList *owner, const NETRuntimeFunction &src)
|
|
: BaseRuntimeFunction(owner)
|
|
{
|
|
begin_ = src.begin_;
|
|
end_ = src.end_;
|
|
start_ = src.start_;
|
|
method_list_ = src.method_list_;
|
|
}
|
|
|
|
NETRuntimeFunction *NETRuntimeFunction::Clone(IRuntimeFunctionList *owner) const
|
|
{
|
|
NETRuntimeFunction *func = new NETRuntimeFunction(reinterpret_cast<NETRuntimeFunctionList *>(owner), *this);
|
|
return func;
|
|
}
|
|
|
|
void NETRuntimeFunction::Rebase(uint64_t delta_base)
|
|
{
|
|
begin_ += delta_base;
|
|
end_ += delta_base;
|
|
start_ += delta_base;
|
|
}
|
|
|
|
void NETRuntimeFunction::set_begin(uint64_t begin)
|
|
{
|
|
begin_ = begin;
|
|
for (size_t i = 0; i < method_list_.size(); i++) {
|
|
method_list_[i]->set_address(begin_);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* NETRuntimeFunctionList
|
|
*/
|
|
|
|
NETRuntimeFunctionList::NETRuntimeFunctionList()
|
|
: BaseRuntimeFunctionList()
|
|
{
|
|
|
|
}
|
|
|
|
NETRuntimeFunctionList::NETRuntimeFunctionList(const NETRuntimeFunctionList &src)
|
|
: BaseRuntimeFunctionList(src)
|
|
{
|
|
|
|
}
|
|
|
|
NETRuntimeFunctionList *NETRuntimeFunctionList::Clone() const
|
|
{
|
|
NETRuntimeFunctionList *list = new NETRuntimeFunctionList(*this);
|
|
return list;
|
|
}
|
|
|
|
NETRuntimeFunction *NETRuntimeFunctionList::item(size_t index) const
|
|
{
|
|
return reinterpret_cast<NETRuntimeFunction *>(IRuntimeFunctionList::item(index));
|
|
}
|
|
|
|
NETRuntimeFunction *NETRuntimeFunctionList::GetFunctionByAddress(uint64_t address) const
|
|
{
|
|
return reinterpret_cast<NETRuntimeFunction *>(BaseRuntimeFunctionList::GetFunctionByAddress(address));
|
|
}
|
|
|
|
NETRuntimeFunction * NETRuntimeFunctionList::Add(uint64_t begin, uint64_t end, uint64_t start, ILMethodDef *method)
|
|
{
|
|
NETRuntimeFunction *func = new NETRuntimeFunction(this, begin, end, start, method);
|
|
AddObject(func);
|
|
return func;
|
|
}
|
|
|
|
void NETRuntimeFunctionList::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
ILTable *table = file.command_list()->table(ttMethodDef);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILMethodDef *method = reinterpret_cast<ILMethodDef *>(table->item(i));
|
|
if (!method->address() || (method->impl_flags() & miCodeTypeMask) != miIL)
|
|
continue;
|
|
|
|
uint64_t address = method->address();
|
|
uint64_t start_address = address + method->fat_size();
|
|
uint64_t end_address = start_address + method->code_size();
|
|
NETRuntimeFunction *func = GetFunctionByAddress(address);
|
|
if (func)
|
|
func->AddMethod(method);
|
|
else
|
|
Add(address, end_address, start_address, method);
|
|
}
|
|
}
|
|
|
|
IRuntimeFunction *NETRuntimeFunctionList::Add(uint64_t address, uint64_t begin, uint64_t end, uint64_t unwind_address, IRuntimeFunction *source, const std::vector<uint8_t> &call_frame_instructions)
|
|
{
|
|
if (source) {
|
|
NETRuntimeFunction *runtime_func = reinterpret_cast<NETRuntimeFunction *>(source);
|
|
runtime_func->set_begin(begin);
|
|
runtime_func->set_end(end);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* NETResource
|
|
*/
|
|
|
|
NETResource::NETResource(IResource *owner, const std::string &name, uint32_t id, uint64_t address, uint32_t size)
|
|
: BaseResource(owner), name_(name), id_(id), address_(address), size_(size)
|
|
{
|
|
|
|
}
|
|
|
|
NETResource::NETResource(IResource *owner, const NETResource &src)
|
|
: BaseResource(owner, src)
|
|
{
|
|
name_ = src.name_;
|
|
id_ = src.id_;
|
|
address_ = src.address_;
|
|
size_ = src.size_;
|
|
}
|
|
|
|
IResource *NETResource::Clone(IResource *owner) const
|
|
{
|
|
NETResource *resource = new NETResource(owner, *this);
|
|
return resource;
|
|
}
|
|
|
|
NETResource *NETResource::item(size_t index) const
|
|
{
|
|
return reinterpret_cast<NETResource *>(BaseResource::item(index));
|
|
}
|
|
|
|
NETResource *NETResource::Add(const std::string &name, uint32_t id, uint64_t address, uint32_t size)
|
|
{
|
|
NETResource *resource = new NETResource(this, name, id, address, size);
|
|
AddObject(resource);
|
|
return resource;
|
|
}
|
|
|
|
/**
|
|
* NETResourceList
|
|
*/
|
|
|
|
NETResourceList::NETResourceList(NETArchitecture *owner)
|
|
: BaseResourceList(owner)
|
|
{
|
|
|
|
}
|
|
|
|
NETResourceList::NETResourceList(NETArchitecture *owner, const NETResourceList &src)
|
|
: BaseResourceList(owner, src)
|
|
{
|
|
|
|
}
|
|
|
|
NETResourceList *NETResourceList::Clone(NETArchitecture *owner) const
|
|
{
|
|
NETResourceList *list = new NETResourceList(owner, *this);
|
|
return list;
|
|
}
|
|
|
|
NETResource *NETResourceList::item(size_t index) const
|
|
{
|
|
return reinterpret_cast<NETResource *>(BaseResourceList::item(index));
|
|
}
|
|
|
|
NETResource *NETResourceList::Add(const std::string &name, uint32_t id, uint64_t address, uint32_t size)
|
|
{
|
|
NETResource *resource = new NETResource(this, name, id, address, size);
|
|
AddObject(resource);
|
|
return resource;
|
|
}
|
|
|
|
void NETResourceList::ReadFromFile(NETArchitecture &file)
|
|
{
|
|
ILTable *table = file.command_list()->table(ttManifestResource);
|
|
for (size_t i = 0; i < table->count(); i++) {
|
|
ILManifestResource *resource = reinterpret_cast<ILManifestResource*>(table->item(i));
|
|
ILToken *implementation = resource->implementation();
|
|
if (implementation) {
|
|
NETResource *folder = reinterpret_cast<NETResource*>(GetResourceById(string_format("%.4X", implementation->id())));
|
|
if (!folder) {
|
|
std::string name;
|
|
switch (implementation->type()) {
|
|
case ttFile:
|
|
folder = Add(reinterpret_cast<ILFile*>(implementation)->name(), implementation->id(), 0, 0);
|
|
break;
|
|
case ttAssemblyRef:
|
|
folder = Add(reinterpret_cast<ILAssemblyRef*>(implementation)->name(), implementation->id(), 0, 0);
|
|
break;
|
|
}
|
|
if (!folder)
|
|
continue;
|
|
}
|
|
folder->Add(resource->name(), resource->id(), resource->offset(), 0);
|
|
} else {
|
|
NETResource *folder = Add(resource->name(), resource->id(), resource->value()->address(), resource->value()->size());
|
|
for (size_t j = 0; j < resource->value()->count(); j++) {
|
|
ManifestResourceItem *item = resource->value()->item(j);
|
|
folder->Add(item->name(), static_cast<uint32_t>(j), item->address(), item->size());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* NETArchitecture
|
|
*/
|
|
|
|
NETArchitecture::NETArchitecture(PEFile *owner)
|
|
: BaseArchitecture(owner, owner->arch_pe()->offset(), owner->arch_pe()->size()), function_list_(NULL),
|
|
entry_point_(0), pe_(owner->arch_pe()), virtual_machine_list_(NULL), optimized_section_count_(0), resize_header_(0)
|
|
{
|
|
meta_data_ = new ILMetaData(this);
|
|
import_list_ = new NETImportList(this);
|
|
export_list_ = new NETExportList(this);
|
|
resource_list_ = new NETResourceList(this);
|
|
runtime_function_list_ = new NETRuntimeFunctionList();
|
|
}
|
|
|
|
NETArchitecture::NETArchitecture(PEFile *owner, const NETArchitecture &src)
|
|
: BaseArchitecture(owner, src), pe_(owner->arch_pe()), function_list_(NULL), entry_point_(NULL),
|
|
virtual_machine_list_(NULL), optimized_section_count_(0), resize_header_(0)
|
|
{
|
|
size_t i, j;
|
|
|
|
header_ = src.header_;
|
|
meta_data_ = src.meta_data_->Clone(this);
|
|
import_list_ = src.import_list_->Clone(this);
|
|
export_list_ = src.export_list_->Clone(this);
|
|
resource_list_ = src.resource_list_->Clone(this);
|
|
runtime_function_list_ = src.runtime_function_list_->Clone();
|
|
|
|
if (src.entry_point_)
|
|
entry_point_ = reinterpret_cast<ILMethodDef *>(meta_data_->token(src.entry_point_->id()));
|
|
|
|
if (src.function_list_)
|
|
function_list_ = src.function_list_->Clone(this);
|
|
if (src.virtual_machine_list_)
|
|
virtual_machine_list_ = src.virtual_machine_list_->Clone();
|
|
|
|
for (i = 0; i < runtime_function_list_->count(); i++) {
|
|
NETRuntimeFunction *func = runtime_function_list_->item(i);
|
|
std::vector<ILMethodDef *> method_list = func->method_list();
|
|
for (j = 0; j < method_list.size(); j++) {
|
|
method_list[j] = reinterpret_cast<ILMethodDef *>(meta_data_->token(method_list[j]->id()));
|
|
}
|
|
func->set_method_list(method_list);
|
|
}
|
|
|
|
if (function_list_) {
|
|
for (i = 0; i < function_list_->count(); i++) {
|
|
ILFunction *func = reinterpret_cast<ILFunction *>(function_list_->item(i));
|
|
for (j = 0; j < func->count(); j++) {
|
|
ILCommand *command = func->item(j);
|
|
if (command->token_reference())
|
|
command->set_token_reference(meta_data_->token(command->token_reference()->owner()->owner()->id())->reference_list()->GetReferenceByAddress(command->token_reference()->address()));
|
|
}
|
|
for (j = 0; j < func->function_info_list()->count(); j++) {
|
|
FunctionInfo *info = func->function_info_list()->item(j);
|
|
if (info->source())
|
|
info->set_source(runtime_function_list_->GetFunctionByAddress(info->source()->begin()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
NETArchitecture::~NETArchitecture()
|
|
{
|
|
delete import_list_;
|
|
delete export_list_;
|
|
delete resource_list_;
|
|
delete runtime_function_list_;
|
|
delete meta_data_;
|
|
delete function_list_;
|
|
}
|
|
|
|
NETArchitecture *NETArchitecture::Clone(IFile *file) const
|
|
{
|
|
NETArchitecture *arch = new NETArchitecture(dynamic_cast<PEFile *>(file), *this);
|
|
return arch;
|
|
}
|
|
|
|
OpenStatus NETArchitecture::ReadFromFile(uint32_t mode)
|
|
{
|
|
PEDirectory *dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
|
|
if (!dir || !dir->address() || !AddressSeek(dir->address()))
|
|
return osUnknownFormat;
|
|
|
|
Read(&header_, sizeof(header_));
|
|
if (!header_.MetaData.VirtualAddress)
|
|
return osInvalidFormat;
|
|
|
|
entry_point_ = NULL;
|
|
meta_data_->ReadFromFile(*this, header_.MetaData.VirtualAddress + image_base());
|
|
if (header_.u.EntryPointToken && (header_.Flags & COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0) {
|
|
ILToken *token = meta_data_->token(header_.u.EntryPointToken);
|
|
if (!token || token->type() != ttMethodDef)
|
|
return osInvalidFormat;
|
|
entry_point_ = reinterpret_cast<ILMethodDef*>(token);
|
|
}
|
|
|
|
size_t i, j;
|
|
|
|
if (header_.VTableFixups.VirtualAddress) {
|
|
if (!AddressSeek(image_base() + header_.VTableFixups.VirtualAddress))
|
|
return osInvalidFormat;
|
|
|
|
for (i = 0; i < header_.VTableFixups.Size / sizeof(IMAGE_COR_VTABLEFIXUP); i++) {
|
|
IMAGE_COR_VTABLEFIXUP fixup;
|
|
Read(&fixup, sizeof(fixup));
|
|
uint64_t pos = Tell();
|
|
uint64_t address = image_base() + fixup.RVA;
|
|
if (!AddressSeek(address))
|
|
return osInvalidFormat;
|
|
|
|
for (j = 0; j < fixup.Count; j++) {
|
|
ILToken *token = meta_data_->token(ReadDWord());
|
|
if (!token)
|
|
return osInvalidFormat;
|
|
|
|
token->reference_list()->Add(address);
|
|
|
|
address += 4;
|
|
if (fixup.Type & COR_VTABLE_64BIT) {
|
|
ReadDWord();
|
|
address += 4;
|
|
}
|
|
}
|
|
Seek(pos);
|
|
}
|
|
}
|
|
|
|
import_list_->ReadFromFile(*this);
|
|
resource_list_->ReadFromFile(*this);
|
|
runtime_function_list_->ReadFromFile(*this);
|
|
|
|
if ((mode & foHeaderOnly) == 0) {
|
|
ILAssemblyRef *corelib = meta_data_->GetCoreLib();
|
|
bool is_supported_framework = false;
|
|
if (corelib) {
|
|
if (corelib->name() == "mscorlib") {
|
|
// .NET Framework
|
|
if (corelib->major_version() >= 2)
|
|
is_supported_framework = true;
|
|
}
|
|
else if (corelib->name() == "System.Runtime") {
|
|
// .NET Core
|
|
if (corelib->major_version() == 4) {
|
|
if (corelib->minor_version() == 2 && corelib->build_number() >= 1)
|
|
is_supported_framework = true;
|
|
if (corelib->minor_version() > 2)
|
|
is_supported_framework = true;
|
|
}
|
|
else if (corelib->major_version() > 4)
|
|
is_supported_framework = true;
|
|
}
|
|
else if (corelib->name() == "netstandard") {
|
|
// .NET Standard
|
|
if (corelib->major_version() == 2 && corelib->minor_version() >= 1)
|
|
is_supported_framework = true;
|
|
else if (corelib->major_version() > 2)
|
|
is_supported_framework = true;
|
|
}
|
|
}
|
|
if (!is_supported_framework)
|
|
return osUnsupportedSubsystem;
|
|
|
|
enum ObfuscationType {
|
|
ftUnknown,
|
|
ftRenaming,
|
|
ftCompilationType,
|
|
ftStrings
|
|
};
|
|
|
|
struct ObfuscationInfo {
|
|
bool exclude;
|
|
bool apply_to_members;
|
|
size_t value;
|
|
ObfuscationInfo() : exclude(false), apply_to_members(false), value(0) {}
|
|
};
|
|
|
|
std::map<ILToken *, NETImportFunction *> import_map;
|
|
std::map<ILToken *, std::map<ObfuscationType, ObfuscationInfo> > attribute_map;
|
|
ILTable *table = meta_data_->table(ttCustomAttribute);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILCustomAttribute *attribute = reinterpret_cast<ILCustomAttribute *>(table->item(i));
|
|
if (!attribute->parent() || !attribute->type())
|
|
continue;
|
|
|
|
if (attribute->type()->type() == ttMemberRef) {
|
|
ILMemberRef *member_ref = reinterpret_cast<ILMemberRef *>(attribute->type());
|
|
if (member_ref->name() == ".ctor") {
|
|
if (ILToken *declaring_type = member_ref->declaring_type()) {
|
|
std::string full_name;
|
|
switch (declaring_type->type()) {
|
|
case ttTypeRef:
|
|
full_name = reinterpret_cast<ILTypeRef *>(declaring_type)->full_name();
|
|
break;
|
|
}
|
|
if (full_name == "System.Reflection.ObfuscationAttribute") {
|
|
std::map<ObfuscationType, ObfuscationInfo> feature_map;
|
|
std::map<ILToken *, std::map<ObfuscationType, ObfuscationInfo> >::iterator attribute_it = attribute_map.find(attribute->parent());
|
|
if (attribute_it != attribute_map.end())
|
|
feature_map = attribute_it->second;
|
|
|
|
ObfuscationType feature = ftUnknown;
|
|
ObfuscationInfo info;
|
|
info.exclude = true; // default value of ObfuscationAttribute.Exclude
|
|
bool need_delete = true;
|
|
CustomAttributeValue *value = attribute->ParseValue();
|
|
for (j = 0; j < value->named_list()->count(); j++) {
|
|
CustomAttributeNamedArgument *arg = value->named_list()->item(j);
|
|
if (arg->is_field())
|
|
continue;
|
|
|
|
if (arg->name() == "Exclude")
|
|
info.exclude = arg->ToBoolean();
|
|
else if (arg->name() == "ApplyToMembers")
|
|
info.apply_to_members = arg->ToBoolean();
|
|
else if (arg->name() == "StripAfterObfuscation")
|
|
need_delete = arg->ToBoolean();
|
|
else if (arg->name() == "Feature") {
|
|
std::string str = arg->ToString();
|
|
if (str == "renaming")
|
|
feature = ftRenaming;
|
|
else if (str == "virtualization") {
|
|
feature = ftCompilationType;
|
|
info.value = ctVirtualization;
|
|
}
|
|
else if (str == "mutation") {
|
|
feature = ftCompilationType;
|
|
info.value = ctMutation;
|
|
}
|
|
else if (str == "ultra") {
|
|
feature = ftCompilationType;
|
|
info.value = ctUltra;
|
|
}
|
|
else if (str == "virtualizationlockbykey") {
|
|
feature = ftCompilationType;
|
|
info.value = ctVirtualization | 0x80;
|
|
}
|
|
else if (str == "ultralockbykey") {
|
|
feature = ftCompilationType;
|
|
info.value = ctUltra | 0x80;
|
|
}
|
|
else if (str == "strings")
|
|
feature = ftStrings;
|
|
}
|
|
}
|
|
|
|
if (need_delete)
|
|
attribute->set_deleted(true);
|
|
|
|
std::map<ObfuscationType, ObfuscationInfo>::const_iterator feature_it = feature_map.find(feature);
|
|
if (feature_it != feature_map.end()) {
|
|
if (feature_it->second.exclude != info.exclude)
|
|
feature_map.erase(feature_it);
|
|
} else
|
|
feature_map[feature] = info;
|
|
|
|
attribute_map[attribute->parent()] = feature_map;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
NETImportFunction *import_function = import_list_->GetFunctionByToken(attribute->type()->id());
|
|
if (import_function && import_function->owner()->is_sdk())
|
|
import_map[attribute->parent()] = import_function;
|
|
}
|
|
|
|
if (!attribute_map.empty()) {
|
|
std::map<ObfuscationType, ObfuscationInfo> assembly_map;
|
|
if (ILToken *assembly = meta_data_->token(ttAssembly | 1)) {
|
|
std::map<ILToken *, std::map<ObfuscationType, ObfuscationInfo> >::const_iterator attribute_it = attribute_map.find(assembly);
|
|
if (attribute_it != attribute_map.end())
|
|
assembly_map = attribute_it->second;
|
|
}
|
|
|
|
const ILTokenType table_types[] = {ttTypeDef, ttMethodDef, ttField, ttProperty};
|
|
for (i = 0; i < _countof(table_types); i++) {
|
|
table = meta_data_->table(table_types[i]);
|
|
for (j = 0; j < table->count(); j++) {
|
|
std::map<ObfuscationType, ObfuscationInfo> feature_map;
|
|
ILToken *token = table->item(j);
|
|
|
|
std::map<ILToken *, std::map<ObfuscationType, ObfuscationInfo> >::const_iterator attribute_it = attribute_map.find(token);
|
|
if (attribute_it != attribute_map.end())
|
|
feature_map = attribute_it->second;
|
|
|
|
ILTypeDef *declaring_type = NULL;
|
|
switch (token->type()) {
|
|
case ttTypeDef:
|
|
declaring_type = reinterpret_cast<ILTypeDef *>(token)->declaring_type();
|
|
break;
|
|
case ttMethodDef:
|
|
declaring_type = reinterpret_cast<ILMethodDef *>(token)->declaring_type();
|
|
break;
|
|
case ttField:
|
|
declaring_type = reinterpret_cast<ILField *>(token)->declaring_type();
|
|
break;
|
|
case ttProperty:
|
|
declaring_type = reinterpret_cast<ILProperty *>(token)->declaring_type();
|
|
break;
|
|
}
|
|
|
|
while (declaring_type) {
|
|
attribute_it = attribute_map.find(declaring_type);
|
|
if (attribute_it != attribute_map.end()) {
|
|
std::map<ObfuscationType, ObfuscationInfo> parent_map = attribute_it->second;
|
|
for (std::map<ObfuscationType, ObfuscationInfo>::const_iterator parent_feature_it = parent_map.begin(); parent_feature_it != parent_map.end(); parent_feature_it++) {
|
|
ObfuscationType feature = parent_feature_it->first;
|
|
ObfuscationInfo info = parent_feature_it->second;
|
|
if (info.apply_to_members && feature_map.find(feature) == feature_map.end())
|
|
feature_map[feature] = info;
|
|
}
|
|
}
|
|
declaring_type = declaring_type->declaring_type();
|
|
}
|
|
|
|
for (std::map<ObfuscationType, ObfuscationInfo>::const_iterator parent_feature_it = assembly_map.begin(); parent_feature_it != assembly_map.end(); parent_feature_it++) {
|
|
ObfuscationType feature = parent_feature_it->first;
|
|
ObfuscationInfo info = parent_feature_it->second;
|
|
if (feature_map.find(feature) == feature_map.end())
|
|
feature_map[feature] = info;
|
|
}
|
|
|
|
std::map<ObfuscationType, ObfuscationInfo>::const_iterator feature_it = feature_map.find(ftRenaming);
|
|
if (feature_it != feature_map.end() && feature_it->second.exclude)
|
|
token->set_can_rename(false);
|
|
|
|
if (token->type() == ttMethodDef)
|
|
attribute_map[token] = feature_map;
|
|
}
|
|
}
|
|
}
|
|
|
|
table = meta_data_->table(ttMethodDef);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILMethodDef *method = reinterpret_cast<ILMethodDef *>(table->item(i));
|
|
if (!method->declaring_type())
|
|
continue;
|
|
|
|
MapFunctionList *map_function_list = (method->impl_flags() & miCodeTypeMask) == miNative ? pe_->map_function_list() : this->map_function_list();
|
|
|
|
std::string ret_name = method->signature()->ret_name();
|
|
MapFunction *map_function = map_function_list->Add(method->address(), 0, ((method->flags() & mdMemberAccessMask) == mdPublic) ? otExport : otCode,
|
|
FunctionName(method->full_name(), ret_name.empty() ? 0 : ret_name.size() + 1));
|
|
|
|
std::map<ILToken *, std::map<ObfuscationType, ObfuscationInfo> >::const_iterator attribute_it = attribute_map.find(method);
|
|
if (attribute_it != attribute_map.end()) {
|
|
std::map<ObfuscationType, ObfuscationInfo> feature_map = attribute_it->second;
|
|
std::map<ObfuscationType, ObfuscationInfo>::const_iterator feature_it = feature_map.find(ftStrings);
|
|
if (feature_it != feature_map.end()) {
|
|
ObfuscationInfo info = feature_it->second;
|
|
if (!info.exclude)
|
|
map_function->set_strings_protection(true);
|
|
}
|
|
}
|
|
|
|
std::map<ILToken *, NETImportFunction *>::const_iterator it = import_map.find(method);
|
|
if (it != import_map.end()) {
|
|
map_function->set_type(otMarker);
|
|
NETImportFunction *import_function = it->second;
|
|
if (import_function->compilation_type() != ctNone) {
|
|
map_function->set_compilation_type(import_function->compilation_type());
|
|
map_function->set_lock_to_key((import_function->options() & ioLockToKey) != 0);
|
|
}
|
|
}
|
|
else if (attribute_it != attribute_map.end()) {
|
|
std::map<ObfuscationType, ObfuscationInfo> feature_map = attribute_it->second;
|
|
std::map<ObfuscationType, ObfuscationInfo>::const_iterator feature_it = feature_map.find(ftCompilationType);
|
|
if (feature_it != feature_map.end()) {
|
|
ObfuscationInfo info = feature_it->second;
|
|
if (!info.exclude) {
|
|
map_function->set_type(otMarker);
|
|
if (info.value != ctNone) {
|
|
map_function->set_compilation_type((CompilationType)(info.value & 0x7f));
|
|
map_function->set_lock_to_key((info.value & 0x80) != 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
map_function_list()->ReadFromFile(*this);
|
|
export_list_->ReadFromFile(*this);
|
|
}
|
|
|
|
function_list_ = new ILFunctionList(this);
|
|
virtual_machine_list_ = new ILVirtualMachineList();
|
|
if ((mode & foHeaderOnly) == 0) {
|
|
ILFileHelper helper;
|
|
helper.Parse(*this);
|
|
}
|
|
|
|
return osSuccess;
|
|
}
|
|
|
|
bool NETArchitecture::Prepare(CompileContext &ctx)
|
|
{
|
|
ctx.vm_runtime = ctx.runtime;
|
|
if (!BaseArchitecture::Prepare(ctx))
|
|
return false;
|
|
|
|
size_t i;
|
|
PESegment *section;
|
|
std::vector<PESegment *> optimized_section_list;
|
|
|
|
// optimize sections
|
|
if (pe_->resource_section())
|
|
optimized_section_list.push_back(pe_->resource_section());
|
|
if (pe_->fixup_section())
|
|
optimized_section_list.push_back(pe_->fixup_section());
|
|
|
|
optimized_section_count_ = segment_list()->count();
|
|
for (i = segment_list()->count(); i > 0; i--) {
|
|
section = segment_list()->item(i - 1);
|
|
|
|
std::vector<PESegment *>::iterator it = std::find(optimized_section_list.begin(), optimized_section_list.end(), section);
|
|
if (it != optimized_section_list.end()) {
|
|
optimized_section_list.erase(it);
|
|
optimized_section_count_--;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// calc new header size
|
|
uint32_t new_section_count = static_cast<uint32_t>(segment_list()->count() + 1);
|
|
if (ctx.runtime)
|
|
new_section_count++;
|
|
|
|
// calc header resizes
|
|
uint32_t new_header_size = header_offset() + offsetof(IMAGE_NT_HEADERS32, OptionalHeader) + header_size() + new_section_count * sizeof(IMAGE_SECTION_HEADER);
|
|
uint32_t aligned_header_size = AlignValue(new_header_size, file_alignment());
|
|
resize_header_ = 0;
|
|
for (size_t i = 0; i < segment_list()->count(); i++) {
|
|
section = segment_list()->item(i);
|
|
if (section->physical_size() == 0 || section->physical_offset() == 0 || aligned_header_size <= section->physical_offset())
|
|
continue;
|
|
|
|
uint32_t rva = static_cast<uint32_t>(section->address() - image_base());
|
|
if (aligned_header_size > rva) {
|
|
Notify(mtError, NULL, language[lsCreateSegmentError]);
|
|
return false;
|
|
}
|
|
if (aligned_header_size > section->physical_offset())
|
|
resize_header_ = std::max(resize_header_, aligned_header_size - section->physical_offset());
|
|
}
|
|
|
|
if (optimized_section_count_ > 0) {
|
|
section = segment_list()->item(optimized_section_count_ - 1);
|
|
if (ctx.runtime) {
|
|
NETArchitecture *runtime = reinterpret_cast<NETArchitecture *>(ctx.runtime);
|
|
if (runtime->segment_list()->count()) {
|
|
MemoryManager runtime_manager(runtime);
|
|
if (runtime->segment_list()->last() == runtime->pe_->fixup_section())
|
|
delete runtime->pe_->fixup_section();
|
|
if (runtime->segment_list()->last() == runtime->pe_->resource_section())
|
|
delete runtime->pe_->resource_section();
|
|
runtime->Rebase(AlignValue(section->address() + section->size(), segment_alignment()) - runtime->segment_list()->item(0)->address());
|
|
runtime->meta_data_->FreeByManager(runtime_manager);
|
|
runtime_manager.Pack();
|
|
for (i = 0; i < runtime_manager.count(); i++) {
|
|
MemoryRegion *region = runtime_manager.item(i);
|
|
ctx.manager->Add(region->address(), region->size(), region->type());
|
|
}
|
|
section = runtime->segment_list()->last();
|
|
} else {
|
|
runtime->Rebase(UINT32_MAX);
|
|
}
|
|
}
|
|
else if (ctx.vm_runtime) {
|
|
NETArchitecture *runtime = reinterpret_cast<NETArchitecture *>(ctx.vm_runtime);
|
|
runtime->segment_list()->clear();
|
|
runtime->Rebase(UINT32_MAX);
|
|
}
|
|
|
|
// add new section
|
|
assert(section);
|
|
ctx.manager->Add(AlignValue(section->address() + section->size(), segment_alignment()), static_cast<uint32_t>(-1), mtReadable | mtExecutable | mtWritable | mtNotPaged | (runtime_function_list()->count() ? mtSolid : mtNone));
|
|
}
|
|
|
|
if (ctx.options.flags & (cpPack | cpStripDebugInfo)) {
|
|
PEDirectory *dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_DEBUG);
|
|
if (dir && dir->address() && dir->size()) {
|
|
ctx.manager->Add(dir->address(), dir->size());
|
|
if (AddressSeek(dir->address())) {
|
|
IMAGE_DEBUG_DIRECTORY debug_directory_data;
|
|
size_t c = dir->size() / sizeof(debug_directory_data);
|
|
for (i = 0; i < c; i++) {
|
|
Read(&debug_directory_data, sizeof(debug_directory_data));
|
|
if (debug_directory_data.AddressOfRawData)
|
|
ctx.manager->Add(debug_directory_data.AddressOfRawData + image_base(), debug_directory_data.SizeOfData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rename_map_.clear();
|
|
if (ctx.options.flags & cpStripDebugInfo)
|
|
RenameSymbols();
|
|
|
|
meta_data_->FreeByManager(*ctx.manager);
|
|
meta_data_->Prepare();
|
|
|
|
resolver.Prepare();
|
|
|
|
return true;
|
|
}
|
|
|
|
void NETArchitecture::RenameToken(ILToken *token)
|
|
{
|
|
bool need_first_char = false;
|
|
if (token->type() == ttTypeDef) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(token);
|
|
if (type_def->flags() & tdSerializable)
|
|
need_first_char = true;
|
|
}
|
|
|
|
std::string new_name;
|
|
do {
|
|
uint32_t id = rand32();
|
|
if (need_first_char)
|
|
id |= 0xA0000000;
|
|
new_name = string_format("%.8X", id);
|
|
} while (rename_map_.find(new_name) != rename_map_.end());
|
|
rename_map_.insert(new_name);
|
|
|
|
switch (token->type()) {
|
|
case ttParam:
|
|
{
|
|
ILParam *param = reinterpret_cast<ILParam *>(token);
|
|
param->set_name(new_name);
|
|
}
|
|
break;
|
|
case ttTypeDef:
|
|
{
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(token);
|
|
type_def->set_name(new_name);
|
|
type_def->set_namespace("");
|
|
}
|
|
break;
|
|
case ttMethodDef:
|
|
{
|
|
ILMethodDef *mehod = reinterpret_cast<ILMethodDef *>(token);
|
|
mehod->set_name(new_name);
|
|
}
|
|
break;
|
|
case ttField:
|
|
{
|
|
ILField *field = reinterpret_cast<ILField *>(token);
|
|
field->set_name(new_name);
|
|
}
|
|
break;
|
|
case ttProperty:
|
|
{
|
|
ILProperty *prop = reinterpret_cast<ILProperty *>(token);
|
|
prop->set_name(new_name);
|
|
}
|
|
break;
|
|
case ttEvent:
|
|
{
|
|
ILEvent *event = reinterpret_cast<ILEvent *>(token);
|
|
event->set_name(new_name);
|
|
}
|
|
break;
|
|
case ttGenericParam:
|
|
{
|
|
ILGenericParam *generic_param = reinterpret_cast<ILGenericParam *>(token);
|
|
generic_param->set_name(new_name);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void NETArchitecture::RenameSymbols()
|
|
{
|
|
size_t i, j, k;
|
|
ILTable *table;
|
|
ILToken *token;
|
|
std::vector<ILToken *> token_list;
|
|
NameReferenceList reference_list;
|
|
bool is_dll = (pe_->image_type() == itLibrary);
|
|
if (ILToken *assembly = meta_data_->token(ttAssembly | 1)) {
|
|
table = meta_data_->table(ttCustomAttribute);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILCustomAttribute *attribute = reinterpret_cast<ILCustomAttribute *>(table->item(i));
|
|
if (attribute->parent() != assembly || !attribute->type())
|
|
continue;
|
|
|
|
if (attribute->type()->type() == ttMemberRef) {
|
|
ILMemberRef *member_ref = reinterpret_cast<ILMemberRef *>(attribute->type());
|
|
if (member_ref->name() == ".ctor") {
|
|
if (ILToken *declaring_type = member_ref->declaring_type()) {
|
|
std::string full_name;
|
|
switch (declaring_type->type()) {
|
|
case ttTypeRef:
|
|
full_name = reinterpret_cast<ILTypeRef *>(declaring_type)->full_name();
|
|
break;
|
|
}
|
|
if (full_name == "System.Reflection.ObfuscateAssemblyAttribute") {
|
|
bool need_delete = true;
|
|
CustomAttributeValue *value = attribute->ParseValue();
|
|
if (value->fixed_list()->count() == 1)
|
|
is_dll = !value->fixed_list()->item(0)->ToBoolean();
|
|
for (j = 0; j < value->named_list()->count(); j++) {
|
|
CustomAttributeNamedArgument *arg = value->named_list()->item(j);
|
|
if (arg->is_field())
|
|
continue;
|
|
|
|
if (arg->name() == "StripAfterObfuscation")
|
|
need_delete = arg->ToBoolean();
|
|
}
|
|
|
|
if (need_delete)
|
|
attribute->set_deleted(true);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ILTokenType source_types[] = { ttTypeDef, ttMethodDef, ttField, ttProperty, ttEvent, ttParam, ttGenericParam };
|
|
for (i = 0; i < _countof(source_types); i++) {
|
|
table = meta_data_->table(source_types[i]);
|
|
for (j = 0; j < table->count(); j++) {
|
|
token = table->item(j);
|
|
if (!token->can_rename())
|
|
continue;
|
|
|
|
if (is_dll && token->is_exported()) {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
|
|
switch (token->type()) {
|
|
case ttTypeDef:
|
|
{
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(token);
|
|
if (type_def->value() == 1 || (type_def->flags() & tdRTSpecialName)) {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
|
|
if (type_def->FindBaseType("System.Configuration.SettingsBase")) {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
case ttMethodDef:
|
|
{
|
|
ILMethodDef *method = reinterpret_cast<ILMethodDef *>(token);
|
|
if (method->flags() & mdRTSpecialName) {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
|
|
if (method->flags() & mdVirtual) {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
|
|
if ((method->declaring_type()->flags() & tdClassSemanticsMask) == tdClass) {
|
|
// check delegate
|
|
ILToken *base_type = method->declaring_type()->base_type();
|
|
if (base_type && base_type->type() == ttTypeRef) {
|
|
ILTypeRef *type_ref = reinterpret_cast<ILTypeRef *>(base_type);
|
|
if (type_ref->resolution_scope() == meta_data_->GetCoreLib() && type_ref->name_space() == "System" && type_ref->name() == "MulticastDelegate") {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case ttField:
|
|
{
|
|
ILField *field = reinterpret_cast<ILField *>(token);
|
|
if (field->flags() & fdRTSpecialName) {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
if ((field->declaring_type()->flags() & tdSerializable) && (field->flags() & fdNotSerialized) == 0) {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
if (field->flags() & fdLiteral) {
|
|
// check enum
|
|
if ((field->declaring_type()->flags() & tdClassSemanticsMask) == tdClass) {
|
|
ILToken *base_type = field->declaring_type()->base_type();
|
|
if (base_type && base_type->type() == ttTypeRef) {
|
|
ILTypeRef *type_ref = reinterpret_cast<ILTypeRef *>(base_type);
|
|
if (type_ref->resolution_scope() == meta_data_->GetCoreLib() && type_ref->name_space() == "System" && type_ref->name() == "Enum") {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case ttProperty:
|
|
{
|
|
ILProperty *prop = reinterpret_cast<ILProperty *>(token);
|
|
if (prop->flags() & prRTSpecialName) {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
|
|
if (prop->declaring_type()->FindImplement("System.ComponentModel.INotifyPropertyChanged")) {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
case ttEvent:
|
|
{
|
|
ILEvent *event = reinterpret_cast<ILEvent *>(token);
|
|
if (event->flags() & evRTSpecialName) {
|
|
token->set_can_rename(false);
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
token_list.push_back(token);
|
|
}
|
|
}
|
|
|
|
table = meta_data_->table(ttUserString);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILUserString *str = reinterpret_cast<ILUserString *>(table->item(i));
|
|
ILTypeDef *type_def = meta_data_->GetTypeDef(str->name());
|
|
if (type_def && type_def->can_rename()) {
|
|
reference_list.AddStringReference(str, type_def);
|
|
|
|
uint64_t address;
|
|
if (!meta_data_->GetUserData(str->value(), &address).empty()) {
|
|
if (ILCommand *command = reinterpret_cast<ILCommand *>(function_list_->GetCommandByAddress(address, true)))
|
|
reference_list.AddCommandReference(command, type_def);
|
|
}
|
|
}
|
|
}
|
|
|
|
table = meta_data_->table(ttMethodSpec);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILMethodSpec *method_spec = reinterpret_cast<ILMethodSpec *>(table->item(i));
|
|
if (method_spec->parent() && method_spec->parent()->type() == ttMemberRef) {
|
|
std::string name = reinterpret_cast<ILMemberRef*>(method_spec->parent())->full_name();
|
|
if (name.size() > 54 && name.substr(0, 54) == "!!0 Newtonsoft.Json.JsonConvert::DeserializeObject<0>(") {
|
|
token = method_spec->signature()->item(0)->token();
|
|
if (token && token->type() == ttTypeDef) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(token);
|
|
ILTable *ref_table = meta_data_->table(ttProperty);
|
|
for (size_t r = 0; r < ref_table->count(); r++) {
|
|
ILProperty *property = reinterpret_cast<ILProperty*>(ref_table->item(r));
|
|
if (property->declaring_type() == type_def)
|
|
property->set_can_rename(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
table = meta_data_->table(ttMemberRef);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILMemberRef *member_ref = reinterpret_cast<ILMemberRef *>(table->item(i));
|
|
ILToken *declaring_type = member_ref->declaring_type();
|
|
if (declaring_type->type() == ttTypeSpec) {
|
|
ILTypeSpec *type_spec = reinterpret_cast<ILTypeSpec *>(declaring_type);
|
|
if (type_spec->info()->type() == ELEMENT_TYPE_GENERICINST) {
|
|
if (type_spec->info()->next()->token()->type() == ttTypeDef) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(type_spec->info()->next()->token());
|
|
if (member_ref->signature()->is_method()) {
|
|
ILMethodDef *method = type_def->GetMethod(member_ref->name(), member_ref->signature());
|
|
if (method && method->can_rename())
|
|
reference_list.AddMemberReference(member_ref, method);
|
|
}
|
|
else if (member_ref->signature()->is_field()) {
|
|
ILField *field = type_def->GetField(member_ref->name());
|
|
if (field && field->can_rename())
|
|
reference_list.AddMemberReference(member_ref, field);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
table = meta_data_->table(ttCustomAttribute);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILCustomAttribute *attribute = reinterpret_cast<ILCustomAttribute *>(table->item(i));
|
|
CustomAttributeValue *value = attribute->ParseValue();
|
|
|
|
std::vector<CustomAttributeArgument *> arg_list;
|
|
for (j = 0; j < value->fixed_list()->count(); j++) {
|
|
arg_list.push_back(value->fixed_list()->item(j));
|
|
}
|
|
for (j = 0; j < value->named_list()->count(); j++) {
|
|
arg_list.push_back(value->named_list()->item(j));
|
|
}
|
|
|
|
for (j = 0; j < arg_list.size(); j++) {
|
|
CustomAttributeArgument *arg = arg_list[j];
|
|
if (arg->reference() && arg->reference()->meta() == meta_data_) {
|
|
if (arg->reference()->can_rename())
|
|
reference_list.AddCustomAttribute(attribute);
|
|
}
|
|
|
|
if (arg->children()) {
|
|
for (size_t k = 0; k < arg->children()->count(); k++) {
|
|
arg_list.push_back(arg->children()->item(k));
|
|
}
|
|
}
|
|
}
|
|
|
|
ILToken *type;
|
|
switch (attribute->type()->type()) {
|
|
case ttMethodDef:
|
|
type = reinterpret_cast<ILMethodDef *>(attribute->type())->declaring_type();
|
|
break;
|
|
case ttMemberRef:
|
|
type = reinterpret_cast<ILMemberRef *>(attribute->type())->declaring_type();
|
|
break;
|
|
default:
|
|
type = NULL;
|
|
break;
|
|
}
|
|
|
|
for (size_t j = 0; j < value->named_list()->count(); j++) {
|
|
CustomAttributeNamedArgument *arg = value->named_list()->item(j);
|
|
while (type && type->type() == ttTypeDef) {
|
|
ILTypeDef *declaring_type = reinterpret_cast<ILTypeDef *>(type);
|
|
if (arg->is_field()) {
|
|
if (ILField *field = declaring_type->GetField(arg->name())) {
|
|
if (field->can_rename())
|
|
reference_list.AddCustomAttributeNameReference(attribute, arg, field);
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
if (ILProperty *prop = declaring_type->GetProperty(arg->name())) {
|
|
if (prop->can_rename())
|
|
reference_list.AddCustomAttributeNameReference(attribute, arg, prop);
|
|
break;
|
|
}
|
|
}
|
|
type = declaring_type->base_type();
|
|
}
|
|
}
|
|
}
|
|
|
|
std::map<std::string, std::set<ILProperty *> > property_map;
|
|
table = meta_data_->table(ttProperty);
|
|
ILTable *method_semantics_table = meta_data_->table(ttMethodSemantics);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILProperty *prop = reinterpret_cast<ILProperty *>(table->item(i));
|
|
|
|
CorMethodAttr method_flags = (CorMethodAttr)0;
|
|
for (j = 0; j < method_semantics_table->count(); j++) {
|
|
ILMethodSemantics *semantics = reinterpret_cast<ILMethodSemantics *>(method_semantics_table->item(j));
|
|
if (semantics->association() == prop) {
|
|
method_flags = semantics->method()->flags();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((method_flags & mdMemberAccessMask) == mdPublic && (method_flags & mdStatic) == 0) {
|
|
std::map<std::string, std::set<ILProperty *> >::iterator it = property_map.find(prop->name());
|
|
if (it == property_map.end())
|
|
property_map[prop->name()].insert(prop);
|
|
else
|
|
it->second.insert(prop);
|
|
}
|
|
}
|
|
|
|
table = meta_data_->table(ttManifestResource);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILManifestResource *resource = reinterpret_cast<ILManifestResource *>(table->item(i));
|
|
if (resource->implementation())
|
|
continue;
|
|
|
|
std::string name = resource->name();
|
|
if (name.size() >= 10 && name.substr(name.size() - 10) != ".resources")
|
|
continue;
|
|
|
|
if (name.size() >= 2 && name.substr(name.size() - 2) == ".g")
|
|
continue;
|
|
|
|
name = name.substr(0, name.size() - 10);
|
|
ILTypeDef *type_def = meta_data_->GetTypeDef(name);
|
|
if (type_def && type_def->can_rename())
|
|
reference_list.AddResourceReference(resource, type_def, ".resources");
|
|
|
|
ManifestResourceValue *resource_value = resource->value();
|
|
for (j = 0; j < resource_value->count(); j++) {
|
|
ManifestResourceItem *resource_item = resource_value->item(j);
|
|
std::string name = resource_item->name();
|
|
if (name.size() >= 5 && name.substr(name.size() - 5) == ".baml") {
|
|
BamlDocument *baml = resource_item->ParseBaml();
|
|
if (!baml)
|
|
continue;
|
|
|
|
for (k = baml->count(); k > 0; k--) {
|
|
BamlRecord *record = baml->item(k - 1);
|
|
if (record->type() == LineNumberAndPosition || record->type() == LinePosition) {
|
|
delete record;
|
|
reference_list.AddManifestResource(resource);
|
|
}
|
|
}
|
|
|
|
BamlElement root(NULL);
|
|
if (root.Parse(baml)) {
|
|
std::map<uint16_t, ILMetaData *> assembly_info_map;
|
|
std::map<uint16_t, ILTypeDef *> type_info_map;
|
|
std::map<uint16_t, AttributeInfoRecord *> attribute_info_map;
|
|
|
|
for (k = 0; k < baml->count(); k++) {
|
|
BamlRecord *record = baml->item(k);
|
|
switch (record->type()) {
|
|
case AssemblyInfo:
|
|
{
|
|
AssemblyInfoRecord *assembly_info = reinterpret_cast<AssemblyInfoRecord *>(record);
|
|
if (ILMetaData *assembly = meta_data_->ResolveAssembly(assembly_info->assembly_name(), false))
|
|
assembly_info_map[assembly_info->assembly_id()] = assembly;
|
|
}
|
|
break;
|
|
case AttributeInfo:
|
|
{
|
|
AttributeInfoRecord *attribute_info = reinterpret_cast<AttributeInfoRecord *>(record);
|
|
attribute_info_map[attribute_info->attribute_id()] = attribute_info;
|
|
}
|
|
break;
|
|
case TypeInfo:
|
|
case TypeSerializerInfo:
|
|
{
|
|
TypeInfoRecord *type_info = reinterpret_cast<TypeInfoRecord *>(record);
|
|
std::map<uint16_t, ILMetaData *>::const_iterator it = assembly_info_map.find(type_info->assembly_id());
|
|
if (it != assembly_info_map.end()) {
|
|
if (ILTypeDef *type_def = it->second->GetTypeDef(type_info->type_name()))
|
|
type_info_map[type_info->type_id()] = type_def;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::vector<BamlElement *> stack;
|
|
stack.push_back(&root);
|
|
BamlElement *type_root = root.children().empty() ? NULL : root.children().at(0);
|
|
while (!stack.empty()) {
|
|
BamlElement *elem = stack.back();
|
|
stack.pop_back();
|
|
|
|
// process header
|
|
switch (elem->header()->type()) {
|
|
case ConstructorParametersStart:
|
|
elem->set_type(elem->parent()->type());
|
|
break;
|
|
case ElementStart:
|
|
case NamedElementStart:
|
|
{
|
|
ElementStartRecord *element_record = reinterpret_cast<ElementStartRecord *>(elem->header());
|
|
std::map<uint16_t, ILTypeDef *>::const_iterator it = type_info_map.find(element_record->type_id());
|
|
if (it != type_info_map.end())
|
|
elem->set_type(it->second);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// process body
|
|
std::vector<BamlRecord *> body = elem->body();
|
|
for (k = 0; k < body.size(); k++) {
|
|
BamlRecord *record = body[k];
|
|
switch (record->type()) {
|
|
case Property:
|
|
case PropertyWithConverter:
|
|
{
|
|
if (!type_root || !type_root->type())
|
|
break;
|
|
|
|
PropertyRecord *property = reinterpret_cast<PropertyRecord *>(record);
|
|
std::map<uint16_t, AttributeInfoRecord *>::const_iterator attribute_it = attribute_info_map.find(property->attribute_id());
|
|
if (attribute_it != attribute_info_map.end()) {
|
|
AttributeInfoRecord *attribute_info = attribute_it->second;
|
|
std::map<uint16_t, ILTypeDef *>::const_iterator it = type_info_map.find(attribute_info->owner_type_id());
|
|
if (it != type_info_map.end()) {
|
|
ILTypeDef *type_def = it->second;
|
|
while (type_def) {
|
|
if (ILEvent *event = type_def->GetEvent(attribute_info->name())) {
|
|
if (ILMethodDef *method = type_root->type()->GetMethod(property->value(), NULL)) {
|
|
if (method->meta() == meta_data_ && method->can_rename())
|
|
reference_list.AddPropertyRecordReference(resource, property, method);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ILToken *base_type = type_def->base_type();
|
|
if (!base_type)
|
|
break;
|
|
|
|
switch (base_type->type()) {
|
|
case ttTypeDef:
|
|
type_def = reinterpret_cast<ILTypeDef *>(base_type);
|
|
break;
|
|
case ttTypeRef:
|
|
type_def = reinterpret_cast<ILTypeRef *>(base_type)->Resolve(true);
|
|
break;
|
|
default:
|
|
type_def = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case Text:
|
|
{
|
|
TextRecord *text = reinterpret_cast<TextRecord *>(record);
|
|
std::map<std::string, std::set<ILProperty *> >::const_iterator it = property_map.find(text->value());
|
|
if (it != property_map.end()) {
|
|
for (std::set<ILProperty *>::const_iterator prop_it = it->second.begin(); prop_it != it->second.end(); prop_it++) {
|
|
(*prop_it)->set_can_rename(false);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case TypeInfo:
|
|
case TypeSerializerInfo:
|
|
{
|
|
TypeInfoRecord *type_info = reinterpret_cast<TypeInfoRecord *>(record);
|
|
std::map<uint16_t, ILTypeDef *>::const_iterator it = type_info_map.find(type_info->type_id());
|
|
if (it != type_info_map.end()) {
|
|
ILTypeDef *type_def = it->second;
|
|
if (type_def->meta() == meta_data_ && type_def->can_rename())
|
|
reference_list.AddTypeInfoRecordReference(resource, type_info, type_def);
|
|
}
|
|
}
|
|
break;
|
|
case AttributeInfo:
|
|
{
|
|
AttributeInfoRecord *attribute_info = reinterpret_cast<AttributeInfoRecord *>(record);
|
|
std::map<uint16_t, ILTypeDef *>::const_iterator it = type_info_map.find(attribute_info->owner_type_id());
|
|
if (it != type_info_map.end()) {
|
|
ILTypeDef *type_def = it->second;
|
|
while (type_def) {
|
|
if (ILProperty *prop = type_def->GetProperty(attribute_info->name())) {
|
|
if (prop->meta() == meta_data_ && prop->can_rename())
|
|
reference_list.AddAttributeInfoRecordReference(resource, attribute_info, prop);
|
|
break;
|
|
}
|
|
|
|
if (ILEvent *event = type_def->GetEvent(attribute_info->name())) {
|
|
if (event->meta() == meta_data_ && event->can_rename())
|
|
reference_list.AddAttributeInfoRecordReference(resource, attribute_info, event);
|
|
break;
|
|
}
|
|
|
|
ILToken *base_type = type_def->base_type();
|
|
if (!base_type)
|
|
break;
|
|
|
|
switch (base_type->type()) {
|
|
case ttTypeDef:
|
|
type_def = reinterpret_cast<ILTypeDef *>(base_type);
|
|
break;
|
|
case ttTypeRef:
|
|
type_def = reinterpret_cast<ILTypeRef *>(base_type)->Resolve(true);
|
|
break;
|
|
default:
|
|
type_def = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// process children
|
|
std::vector<BamlElement *> children = elem->children();
|
|
for (k = 0; k < children.size(); k++) {
|
|
stack.push_back(children[k]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < token_list.size(); i++) {
|
|
token = token_list[i];
|
|
if (token->can_rename())
|
|
RenameToken(token);
|
|
}
|
|
|
|
reference_list.UpdateNames();
|
|
}
|
|
|
|
void NETArchitecture::Save(CompileContext &ctx)
|
|
{
|
|
PESegment *vmp_segment, *last_segment, *segment;
|
|
uint64_t address, file_crc_address, loader_crc_address, loader_crc_size_address, loader_crc_hash_address, file_crc_size_address;
|
|
uint32_t size;
|
|
PEDirectory *dir;
|
|
size_t i, c, j, vmp_index;
|
|
uint64_t pos;
|
|
uint32_t fixup_section_flags, resource_section_flags, file_crc_size, loader_crc_size;
|
|
std::string fixup_section_name, resource_section_name;
|
|
MemoryRegion *region;
|
|
std::set<ILTypeDef *> runtime_type_list;
|
|
|
|
MemoryManager *manager = memory_manager();
|
|
NETArchitecture *source = (NETArchitecture *)this->source();
|
|
|
|
// erase sections area
|
|
{
|
|
IMAGE_SECTION_HEADER section_header = IMAGE_SECTION_HEADER();
|
|
Seek(header_offset() + offsetof(IMAGE_NT_HEADERS32, OptionalHeader) + header_size());
|
|
for (i = 0; i < segment_list()->count(); i++) {
|
|
Write(§ion_header, sizeof(section_header));
|
|
}
|
|
}
|
|
|
|
// resize header
|
|
if (resize_header_) {
|
|
size_t total_header_size = offsetof(IMAGE_NT_HEADERS32, OptionalHeader) + header_size() + segment_list()->count() * sizeof(IMAGE_SECTION_HEADER);
|
|
if (resize_header_) {
|
|
source->Seek(header_offset() + total_header_size);
|
|
Seek(header_offset() + total_header_size);
|
|
for (i = 0; i < resize_header_; i++) {
|
|
WriteByte(0);
|
|
}
|
|
CopyFrom(*source, this->size() - source->Tell());
|
|
for (i = 0; i < segment_list()->count(); i++) {
|
|
segment = segment_list()->item(i);
|
|
if (segment->physical_offset())
|
|
segment->set_physical_offset(segment->physical_offset() + resize_header_);
|
|
}
|
|
}
|
|
}
|
|
|
|
// calc progress maximum
|
|
c = 0;
|
|
if (ctx.runtime)
|
|
c += ctx.runtime->segment_list()->count();
|
|
for (i = 0; i < function_list_->count(); i++) {
|
|
IFunction *func = function_list_->item(i);
|
|
if (!func->need_compile())
|
|
continue;
|
|
|
|
for (j = 0; j < func->block_list()->count(); j++) {
|
|
CommandBlock *block = func->block_list()->item(j);
|
|
c += block->end_index() - block->start_index() + 1;
|
|
}
|
|
}
|
|
StartProgress(string_format("%s...", language[lsSaving].c_str()), c);
|
|
|
|
resource_section_flags = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA;
|
|
resource_section_name = ".rsrc";
|
|
|
|
fixup_section_flags = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA;
|
|
fixup_section_name = ".reloc";
|
|
|
|
// need erase optimized sections
|
|
for (i = segment_list()->count(); i > optimized_section_count_; i--) {
|
|
PESegment *section = segment_list()->item(i - 1);
|
|
if (pe_->resource_section() == section) {
|
|
resource_section_flags = section->flags();
|
|
resource_section_name = section->name();
|
|
} else if (pe_->fixup_section() == section) {
|
|
fixup_section_flags = section->flags();
|
|
fixup_section_name = section->name();
|
|
}
|
|
delete section;
|
|
}
|
|
|
|
vmp_index = 0;
|
|
last_segment = segment_list()->last();
|
|
address = AlignValue(last_segment->address() + last_segment->size(), segment_alignment());
|
|
pos = Resize(AlignValue(this->size(), file_alignment()));
|
|
vmp_segment = segment_list()->Add(address, -1, static_cast<uint32_t>(pos), -1, IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE, "");
|
|
|
|
std::vector<IFunction *> ref_function_list = this->function_list()->processor_list();
|
|
NETArchitecture *runtime = reinterpret_cast<NETArchitecture *>(ctx.vm_runtime);
|
|
if (ctx.runtime) {
|
|
// create EntryPoint method
|
|
ILTypeDef *module = reinterpret_cast<ILTypeDef *>(meta_data_->token(ttTypeDef | 1));
|
|
if (!module)
|
|
throw std::runtime_error("Runtime error at Save");
|
|
|
|
ILData signature;
|
|
signature.push_back(0x00);
|
|
signature.push_back(0x00);
|
|
signature.push_back(0x01);
|
|
ILMethodDef *module_cctor = meta_data_->AddMethod(module, ".cctor", signature, (CorMethodAttr)(mdPrivate | mdHideBySig | mdStatic | mdSpecialName | mdRTSpecialName), miIL);
|
|
runtime->set_entry_point_method(module_cctor);
|
|
|
|
// merge runtime objects
|
|
if (runtime->segment_list()->count()) {
|
|
// merge segments
|
|
for (i = 0; i < runtime->segment_list()->count(); i++) {
|
|
segment = runtime->segment_list()->item(i);
|
|
if (segment->physical_offset() && segment->physical_size()) {
|
|
runtime->Seek(segment->physical_offset());
|
|
size = static_cast<uint32_t>(segment->physical_size());
|
|
uint8_t *buffer = new uint8_t[size];
|
|
runtime->Read(buffer, size);
|
|
Write(buffer, size);
|
|
delete[] buffer;
|
|
}
|
|
size = static_cast<uint32_t>(AlignValue(segment->size(), runtime->segment_alignment()) - segment->physical_size());
|
|
for (j = 0; j < size; j++) {
|
|
WriteByte(0);
|
|
}
|
|
vmp_segment->include_write_type(segment->memory_type());
|
|
|
|
StepProgress();
|
|
}
|
|
ref_function_list.clear();
|
|
}
|
|
else {
|
|
for (i = 0; i < runtime->function_list()->count(); i++) {
|
|
IFunction *func = runtime->function_list()->item(i);
|
|
if (func->tag() == ftLoader)
|
|
ref_function_list.push_back(func);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (ref_function_list.empty())
|
|
runtime = NULL;
|
|
}
|
|
|
|
if (runtime) {
|
|
if (ref_function_list.empty()) {
|
|
ILToken *token = runtime->meta_data_->token(ttTypeDef | 1);
|
|
if (token)
|
|
token->set_deleted(true);
|
|
} else {
|
|
std::set<ILToken *> filter_token_list;
|
|
for (i = 0; i < ref_function_list.size(); i++) {
|
|
ILFunction *func = reinterpret_cast<ILFunction *>(ref_function_list[i]);
|
|
for (j = 0; j < func->count(); j++) {
|
|
ILCommand *command = func->item(j);
|
|
if (command->token_reference()) {
|
|
ILToken *token = command->token_reference()->owner()->owner();
|
|
ILSignature *signature = NULL;
|
|
switch (token->type()) {
|
|
case ttMethodDef:
|
|
filter_token_list.insert(token);
|
|
filter_token_list.insert(reinterpret_cast<ILMethodDef *>(token)->declaring_type());
|
|
signature = reinterpret_cast<ILMethodDef *>(token)->signature();
|
|
break;
|
|
case ttMethodSpec:
|
|
filter_token_list.insert(token);
|
|
filter_token_list.insert(reinterpret_cast<ILMethodSpec *>(token)->parent());
|
|
signature = reinterpret_cast<ILMethodSpec *>(token)->signature();
|
|
break;
|
|
case ttMemberRef:
|
|
filter_token_list.insert(token);
|
|
filter_token_list.insert(reinterpret_cast<ILMemberRef *>(token)->declaring_type());
|
|
signature = reinterpret_cast<ILMemberRef *>(token)->signature();
|
|
break;
|
|
case ttField:
|
|
filter_token_list.insert(reinterpret_cast<ILField *>(token)->declaring_type());
|
|
signature = reinterpret_cast<ILField *>(token)->signature();
|
|
break;
|
|
case ttStandAloneSig:
|
|
filter_token_list.insert(token);
|
|
signature = reinterpret_cast<ILStandAloneSig *>(token)->signature();
|
|
break;
|
|
default:
|
|
filter_token_list.insert(token);
|
|
break;
|
|
}
|
|
|
|
if (signature) {
|
|
std::vector<ILElement *> element_list;
|
|
for (c = 0; c < signature->count(); c++) {
|
|
element_list.push_back(signature->item(c));
|
|
}
|
|
if (signature->ret())
|
|
element_list.push_back(signature->ret());
|
|
for (c = 0; c < element_list.size(); c++) {
|
|
ILElement *element = element_list[c];
|
|
do {
|
|
if (element->token())
|
|
filter_token_list.insert(element->token());
|
|
element = element->next();
|
|
} while (element);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ILTokenType link_types[] = { ttTypeDef, ttMethodDef, ttUserString, ttStandAloneSig, ttImplMap, ttModuleRef, ttMemberRef, ttTypeSpec, ttTypeRef };
|
|
for (i = 0; i < _countof(link_types); i++) {
|
|
ILTokenType type = link_types[i];
|
|
ILTable *table = runtime->meta_data_->table(type);
|
|
for (j = 0; j < table->count(); j++) {
|
|
ILToken *token = table->item(j);
|
|
if (token->type() == ttImplMap) {
|
|
ILImplMap *impl_map = reinterpret_cast<ILImplMap *>(token);
|
|
if (filter_token_list.find(impl_map->member_forwarded()) != filter_token_list.end())
|
|
filter_token_list.insert(impl_map->import_scope());
|
|
}
|
|
else if (filter_token_list.find(token) != filter_token_list.end()) {
|
|
if (token->type() == ttTypeDef) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(token);
|
|
if (type_def->base_type())
|
|
filter_token_list.insert(type_def->base_type());
|
|
}
|
|
} else {
|
|
// token not found
|
|
if (token->type() == ttTypeDef) {
|
|
bool has_nested = false;
|
|
for (std::set<ILToken *>::const_iterator it = filter_token_list.begin(); it != filter_token_list.end(); it++) {
|
|
ILToken *tmp = *it;
|
|
if (tmp->type() == ttTypeDef) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(tmp);
|
|
while (type_def) {
|
|
ILTypeDef *declaring_type = type_def->declaring_type();
|
|
if (declaring_type == token) {
|
|
has_nested = true;
|
|
break;
|
|
}
|
|
type_def = declaring_type;
|
|
}
|
|
}
|
|
if (has_nested)
|
|
break;
|
|
}
|
|
if (has_nested)
|
|
continue;
|
|
} else if (token->type() == ttMethodDef) {
|
|
ILMethodDef *method = reinterpret_cast<ILMethodDef *>(token);
|
|
if (filter_token_list.find(method->declaring_type()) != filter_token_list.end()) {
|
|
if (method->flags() & (mdRTSpecialName | mdVirtual)) {
|
|
if (!method->declaring_type()->is_deleted()) {
|
|
ILSignature *signature = method->signature();
|
|
std::vector<ILElement *> element_list;
|
|
for (c = 0; c < signature->count(); c++) {
|
|
element_list.push_back(signature->item(c));
|
|
}
|
|
if (signature->ret())
|
|
element_list.push_back(signature->ret());
|
|
for (c = 0; c < element_list.size(); c++) {
|
|
ILElement *element = element_list[c];
|
|
do {
|
|
if (element->token())
|
|
filter_token_list.insert(element->token());
|
|
element = element->next();
|
|
} while (element);
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (method->declaring_type()->method_list() == method) {
|
|
ILMethodDef *next_method = method->next();
|
|
method->declaring_type()->set_method_list(next_method->declaring_type() == method->declaring_type() ? next_method : NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (token->type() == ttUserString)
|
|
token->reference_list()->clear();
|
|
else
|
|
token->set_deleted(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// merge meta data
|
|
ILTable *src_table = runtime->meta_data_->us_table();
|
|
ILTable *dst_table = meta_data_->us_table();
|
|
for (i = 0; i < src_table->count(); i++) {
|
|
ILToken *src_token = src_table->item(i);
|
|
ILToken *dst_token = src_token->Clone(meta_data_, dst_table);
|
|
dst_token->reference_list()->clear();
|
|
while (src_token->reference_list()->count()) {
|
|
TokenReference *reference = src_token->reference_list()->item(0);
|
|
reference->set_owner(dst_token->reference_list());
|
|
if (runtime->segment_list()->count() == 0)
|
|
reference->set_address(0);
|
|
}
|
|
dst_table->AddObject(dst_token);
|
|
}
|
|
|
|
src_table = runtime->meta_data_->table(ttTypeDef);
|
|
for (i = 0; i < src_table->count(); i++) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(src_table->item(i));
|
|
if (type_def->full_name() == "VMProtect.DeleteOnCompilation") {
|
|
type_def->set_deleted(true);
|
|
src_table = runtime->meta_data_->table(ttCustomAttribute);
|
|
for (j = 0; j < src_table->count(); j++) {
|
|
ILCustomAttribute *attribute = reinterpret_cast<ILCustomAttribute *>(src_table->item(j));
|
|
if (attribute->type() == type_def->method_list())
|
|
attribute->parent()->set_deleted(true);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
src_table = runtime->meta_data_->table(ttCustomAttribute);
|
|
for (i = 0; i < src_table->count(); i++) {
|
|
ILCustomAttribute *attribute = reinterpret_cast<ILCustomAttribute *>(src_table->item(i));
|
|
if (attribute->parent()->is_deleted())
|
|
continue;
|
|
|
|
switch (attribute->parent()->type()) {
|
|
case ttModule:
|
|
case ttAssembly:
|
|
attribute->set_deleted(true);
|
|
{
|
|
ILToken *token = attribute->type();
|
|
if (token->type() == ttMemberRef) {
|
|
ILMemberRef *member_ref = reinterpret_cast<ILMemberRef *>(token);
|
|
if (member_ref->declaring_type()->type() == ttTypeRef && reinterpret_cast<ILTypeRef *>(member_ref->declaring_type())->full_name() == "System.Runtime.CompilerServices.SuppressIldasmAttribute") {
|
|
member_ref->set_deleted(false);
|
|
member_ref->declaring_type()->set_deleted(false);
|
|
attribute->set_deleted(false);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
ILTokenType types[] = { ttModule, ttAssembly, ttAssemblyRef, ttModuleRef, ttTypeRef, ttTypeDef, ttTypeSpec, ttNestedClass, ttClassLayout, ttMemberRef, ttField,
|
|
ttFieldLayout, ttFieldRVA, ttMethodDef, ttMethodSpec, ttImplMap, ttParam, ttGenericParam, ttConstant, ttCustomAttribute, ttPropertyMap, ttProperty,
|
|
ttMethodSemantics, ttStandAloneSig, ttInterfaceImpl};
|
|
std::map<ILToken *, ILToken *> token_map;
|
|
for (i = 0; i < _countof(types); i++) {
|
|
ILTokenType type = types[i];
|
|
src_table = runtime->meta_data_->table(type);
|
|
dst_table = meta_data_->table(type);
|
|
c = dst_table->count();
|
|
for (size_t k = 0; k < src_table->count();) {
|
|
ILToken *src_token = src_table->item(k);
|
|
|
|
if (runtime->segment_list()->count() == 0) {
|
|
for (j = 0; j < src_token->reference_list()->count(); j++) {
|
|
src_token->reference_list()->item(j)->set_address(0);
|
|
}
|
|
}
|
|
|
|
src_token->RemapTokens(token_map);
|
|
bool is_equal = false;
|
|
if (!src_token->is_deleted()) {
|
|
if (type == ttModule || type == ttAssembly || type == ttAssemblyRef || type == ttModuleRef || type == ttTypeRef || type == ttMemberRef || type == ttCustomAttribute) {
|
|
for (j = 0; j < c; j++) {
|
|
ILToken *dst_token = dst_table->item(j);
|
|
switch (type) {
|
|
case ttModule:
|
|
case ttAssembly:
|
|
is_equal = src_token->id() == dst_token->id();
|
|
break;
|
|
case ttAssemblyRef:
|
|
{
|
|
ILAssemblyRef *src = reinterpret_cast<ILAssemblyRef *>(src_token);
|
|
ILAssemblyRef *dst = reinterpret_cast<ILAssemblyRef *>(dst_token);
|
|
is_equal = (src->name() == dst->name());
|
|
}
|
|
break;
|
|
case ttModuleRef:
|
|
{
|
|
ILModuleRef *src = reinterpret_cast<ILModuleRef *>(src_token);
|
|
ILModuleRef *dst = reinterpret_cast<ILModuleRef *>(dst_token);
|
|
is_equal = (src->name() == dst->name());
|
|
}
|
|
break;
|
|
case ttTypeRef:
|
|
{
|
|
ILTypeRef *src = reinterpret_cast<ILTypeRef *>(src_token);
|
|
ILTypeRef *dst = reinterpret_cast<ILTypeRef *>(dst_token);
|
|
is_equal = (src->resolution_scope() == dst->resolution_scope() && src->name_space() == dst->name_space() && src->name() == dst->name());
|
|
}
|
|
break;
|
|
case ttMemberRef:
|
|
{
|
|
ILMemberRef *src = reinterpret_cast<ILMemberRef *>(src_token);
|
|
ILMemberRef *dst = reinterpret_cast<ILMemberRef *>(dst_token);
|
|
is_equal = (src->declaring_type() == dst->declaring_type() && src->name() == dst->name() && src->signature()->ret_name(true) == dst->signature()->ret_name(true) && src->signature()->name(true) == dst->signature()->name(true));
|
|
}
|
|
break;
|
|
case ttCustomAttribute:
|
|
{
|
|
ILCustomAttribute *src = reinterpret_cast<ILCustomAttribute *>(src_token);
|
|
ILCustomAttribute *dst = reinterpret_cast<ILCustomAttribute *>(dst_token);
|
|
is_equal = (src->parent() == dst->parent() && src->type() == dst->type());
|
|
}
|
|
break;
|
|
}
|
|
if (is_equal) {
|
|
token_map[src_token] = dst_token;
|
|
while (src_token->reference_list()->count()) {
|
|
TokenReference *reference = src_token->reference_list()->item(0);
|
|
reference->set_owner(dst_token->reference_list());
|
|
}
|
|
if (dst_token->value() != src_token->value())
|
|
dst_token->set_value(0);
|
|
k++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!is_equal) {
|
|
src_token->set_owner(meta_data_, dst_table);
|
|
if (src_token->type() == ttTypeDef)
|
|
runtime_type_list.insert(reinterpret_cast<ILTypeDef*>(src_token));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
import_list_->Pack();
|
|
meta_data_->UpdateTokens();
|
|
|
|
// update tokens
|
|
for (i = 0; i < function_list_->count(); i++) {
|
|
ILFunction *func = reinterpret_cast<ILFunction *>(function_list_->item(i));
|
|
for (j = 0; j < func->count(); j++) {
|
|
ILCommand *command = func->item(j);
|
|
if (!command->block())
|
|
continue;
|
|
|
|
if (command->block()->type() & mtExecutable) {
|
|
TokenReference *reference = command->token_reference();
|
|
if (reference) {
|
|
uint32_t id = reference->owner()->owner()->id();
|
|
if (command->operand_value() != id) {
|
|
if (command->type() == icComment) {
|
|
Data data;
|
|
data.PushDWord(id);
|
|
command->set_dump(data.data(), data.size());
|
|
}
|
|
else {
|
|
command->set_operand_value(0, id);
|
|
command->CompileToNative();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (c = 0; c < command->count(); c++) {
|
|
ILVMCommand *vm_command = command->item(c);
|
|
TokenReference *reference = vm_command->token_reference();
|
|
if (reference) {
|
|
uint32_t id = reference->owner()->owner()->id();
|
|
if (vm_command->value() != id) {
|
|
vm_command->set_value(id);
|
|
vm_command->Compile();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// write functions
|
|
for (i = 0; i < function_list_->count(); i++) {
|
|
function_list_->item(i)->WriteToFile(*this);
|
|
}
|
|
|
|
// erase not used memory regions
|
|
if (manager->count() > 1) {
|
|
// need skip last big region
|
|
for (i = 0; i < manager->count() - 1; i++) {
|
|
region = manager->item(i);
|
|
if (!AddressSeek(region->address()))
|
|
continue;
|
|
|
|
for (j = 0; j < region->size(); j++) {
|
|
WriteByte((region->type() & mtReadable) ? rand() : 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (vmp_segment->write_type() == mtNone)
|
|
delete vmp_segment;
|
|
else {
|
|
vmp_segment->set_name(string_format("%s%d", ctx.options.section_name.c_str(), vmp_index++));
|
|
|
|
size = static_cast<uint32_t>(this->size() - vmp_segment->physical_offset());
|
|
vmp_segment->set_size(size);
|
|
vmp_segment->set_physical_size(AlignValue(size, file_alignment()));
|
|
vmp_segment->update_type(vmp_segment->write_type());
|
|
|
|
Resize(vmp_segment->physical_offset() + vmp_segment->physical_size());
|
|
}
|
|
|
|
//if (false)
|
|
if (!runtime_type_list.empty()) {
|
|
// rename runtime symbols
|
|
NameReferenceList reference_list;
|
|
std::vector<ILToken *> rename_token_list;
|
|
for (std::set<ILTypeDef *>::const_iterator it = runtime_type_list.begin(); it != runtime_type_list.end(); it++) {
|
|
rename_token_list.push_back(*it);
|
|
}
|
|
|
|
ILTable *table = meta_data_->table(ttMethodDef);
|
|
for (j = 0; j < table->count(); j++) {
|
|
ILMethodDef *method = reinterpret_cast<ILMethodDef*>(table->item(j));
|
|
if (runtime_type_list.find(method->declaring_type()) != runtime_type_list.end()) {
|
|
if (method->flags() & mdRTSpecialName)
|
|
continue;
|
|
|
|
if (method->flags() & mdVirtual) {
|
|
if (method->name() == "Invoke" || method->name() == "BeginInvoke" || method->name() == "EndInvoke" || method->name() == "ToString")
|
|
continue;
|
|
|
|
ILToken *base_type = method->declaring_type()->base_type();
|
|
ILMethodDef *base_method = NULL;
|
|
while (base_type && base_type->type() == ttTypeDef) {
|
|
ILTypeDef *type_def = reinterpret_cast<ILTypeDef *>(base_type);
|
|
if (ILMethodDef *tmp_method = type_def->GetMethod(method->name(), method->signature()))
|
|
base_method = tmp_method;
|
|
base_type = type_def->base_type();
|
|
}
|
|
|
|
if (base_method) {
|
|
reference_list.AddMethodReference(method, base_method);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
rename_token_list.push_back(method);
|
|
}
|
|
}
|
|
|
|
table = meta_data_->table(ttParam);
|
|
for (j = 0; j < table->count(); j++) {
|
|
ILParam *param = reinterpret_cast<ILParam*>(table->item(j));
|
|
if (param->parent() && runtime_type_list.find(param->parent()->declaring_type()) != runtime_type_list.end())
|
|
rename_token_list.push_back(param);
|
|
}
|
|
|
|
table = meta_data_->table(ttField);
|
|
for (j = 0; j < table->count(); j++) {
|
|
ILField *field = reinterpret_cast<ILField*>(table->item(j));
|
|
if (field->flags() & fdRTSpecialName)
|
|
continue;
|
|
|
|
if (runtime_type_list.find(field->declaring_type()) != runtime_type_list.end()) {
|
|
if (field->flags() & fdLiteral) {
|
|
std::string type_name = field->declaring_type()->full_name();
|
|
if (type_name == "VMProtect.SerialState" || type_name == "VMProtect.ActivationStatus")
|
|
continue;
|
|
}
|
|
|
|
rename_token_list.push_back(field);
|
|
}
|
|
}
|
|
|
|
table = meta_data_->table(ttProperty);
|
|
for (j = 0; j < table->count(); j++) {
|
|
ILProperty *prop = reinterpret_cast<ILProperty*>(table->item(j));
|
|
if (prop->flags() & prRTSpecialName)
|
|
continue;
|
|
|
|
if (runtime_type_list.find(prop->declaring_type()) != runtime_type_list.end())
|
|
rename_token_list.push_back(prop);
|
|
}
|
|
|
|
for (i = 0; i < rename_token_list.size(); i++) {
|
|
RenameToken(rename_token_list[i]);
|
|
}
|
|
reference_list.UpdateNames();
|
|
}
|
|
|
|
// write memory CRC table
|
|
if (function_list_->crc_table()) {
|
|
ILCRCTable *il_crc = reinterpret_cast<ILCRCTable *>(function_list_->crc_table());
|
|
CRCTable crc_table(function_list_->crc_cryptor(), il_crc->table_size());
|
|
|
|
// add non writable sections
|
|
for (i = 0; i < segment_list()->count(); i++) {
|
|
segment = segment_list()->item(i);
|
|
if ((segment->memory_type() & (mtReadable | mtWritable)) != mtReadable || segment->excluded_from_memory_protection())
|
|
continue;
|
|
|
|
size = std::min(static_cast<uint32_t>(segment->size()), segment->physical_size());
|
|
if (size)
|
|
crc_table.Add(segment->address(), size);
|
|
}
|
|
|
|
// skip writable runtime's sections
|
|
if (runtime) {
|
|
for (i = 0; i < runtime->segment_list()->count(); i++) {
|
|
segment = runtime->segment_list()->item(i);
|
|
if (segment->memory_type() & mtWritable)
|
|
crc_table.Remove(segment->address(), static_cast<uint32_t>(segment->size()));
|
|
}
|
|
}
|
|
|
|
// skip IAT
|
|
size = OperandSizeToValue(pe_->cpu_address_size());
|
|
size_t k = (runtime && runtime->segment_list()->count() > 0) ? 2 : 1;
|
|
for (size_t n = 0; n < k; n++) {
|
|
PEImportList *import_list = (n == 0) ? pe_->import_list() : runtime->pe_->import_list();
|
|
for (i = 0; i < import_list->count(); i++) {
|
|
PEImport *import = import_list->item(i);
|
|
if (import->count() > 0)
|
|
crc_table.Remove(import->item(0)->address(), size * import->count());
|
|
}
|
|
}
|
|
|
|
// skip fixups
|
|
if ((ctx.options.flags & cpStripFixups) == 0) {
|
|
for (i = 0; i < pe_->fixup_list()->count(); i++) {
|
|
PEFixup *fixup = pe_->fixup_list()->item(i);
|
|
if (!fixup->is_deleted())
|
|
crc_table.Remove(fixup->address(), OperandSizeToValue(fixup->size()));
|
|
}
|
|
}
|
|
|
|
// skip memory CRC table
|
|
crc_table.Remove(il_crc->table_entry()->address(), il_crc->table_size());
|
|
crc_table.Remove(il_crc->size_entry()->address(), sizeof(uint32_t));
|
|
crc_table.Remove(il_crc->hash_entry()->address(), sizeof(uint32_t));
|
|
|
|
// write to file
|
|
AddressSeek(il_crc->table_entry()->address());
|
|
uint32_t hash;
|
|
size = static_cast<uint32_t>(crc_table.WriteToFile(*this, false, &hash));
|
|
AddressSeek(il_crc->size_entry()->address());
|
|
WriteDWord(size);
|
|
AddressSeek(il_crc->hash_entry()->address());
|
|
WriteDWord(hash);
|
|
|
|
il_crc->size_entry()->set_operand_value(0, size);
|
|
il_crc->hash_entry()->set_operand_value(0, hash);
|
|
}
|
|
EndProgress();
|
|
|
|
file_crc_address = 0;
|
|
file_crc_size = 0;
|
|
file_crc_size_address = 0;
|
|
loader_crc_address = 0;
|
|
loader_crc_size = 0;
|
|
loader_crc_size_address = 0;
|
|
loader_crc_hash_address = 0;
|
|
if (ctx.runtime) {
|
|
std::vector<IFunction *> processor_list = function_list_->processor_list();
|
|
|
|
NETLoader *loader = new NETLoader(NULL, cpu_address_size());
|
|
|
|
last_segment = segment_list()->last();
|
|
address = AlignValue(last_segment->address() + last_segment->size(), segment_alignment());
|
|
|
|
manager->clear();
|
|
manager->Add(address, -1, mtReadable | mtExecutable | mtWritable | mtNotPaged | (runtime_function_list()->count() ? mtSolid : mtNone));
|
|
|
|
if (!loader->Prepare(ctx)) {
|
|
delete loader;
|
|
throw std::runtime_error("Runtime error at Save");
|
|
}
|
|
size_t processor_count = 0;
|
|
for (i = 0; i < processor_list.size(); i++) {
|
|
processor_count += processor_list[i]->count();
|
|
}
|
|
ctx.file->StartProgress(string_format("%s...", language[lsSavingStartupCode].c_str()), loader->count() + processor_count);
|
|
loader->Compile(ctx);
|
|
|
|
pos = Resize(AlignValue(this->size(), file_alignment()));
|
|
segment = segment_list()->Add(address, -1, static_cast<uint32_t>(pos), -1, IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE, string_format("%s%d", ctx.options.section_name.c_str(), vmp_index++));
|
|
loader->WriteToFile(*this);
|
|
segment->update_type(segment->write_type());
|
|
for (i = 0; i < processor_list.size(); i++) {
|
|
processor_list[i]->WriteToFile(*this);
|
|
}
|
|
|
|
// copy directories
|
|
if (ctx.options.flags & cpPack) {
|
|
IArchitecture *source = const_cast<IArchitecture *>(this->source());
|
|
last_segment = segment_list()->last();
|
|
|
|
dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG);
|
|
if (dir && dir->address() && dir->physical_size() && source->AddressSeek(dir->address())) {
|
|
size = dir->physical_size();
|
|
pos = Resize(AlignValue(this->size(), 0x10));
|
|
CopyFrom(*source, size);
|
|
address = last_segment->address() + pos - last_segment->physical_offset();
|
|
for (i = 0; i < size; i++) {
|
|
PEFixup *fixup = reinterpret_cast<PEFixup *>(source->fixup_list()->GetFixupByAddress(dir->address() + i));
|
|
if (fixup) {
|
|
fixup = fixup->Clone(fixup_list());
|
|
fixup->set_address(address + i);
|
|
fixup_list()->AddObject(fixup);
|
|
}
|
|
}
|
|
dir->set_address(address);
|
|
}
|
|
|
|
if ((ctx.options.flags & cpStripDebugInfo) == 0) {
|
|
dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_DEBUG);
|
|
if (dir && dir->address() && dir->physical_size() && source->AddressSeek(dir->address())) {
|
|
IMAGE_DEBUG_DIRECTORY debug_directory_data;
|
|
std::vector<IMAGE_DEBUG_DIRECTORY> debug_directory_data_list;
|
|
c = dir->size() / sizeof(debug_directory_data);
|
|
for (i = 0; i < c; i++) {
|
|
source->Read(&debug_directory_data, sizeof(debug_directory_data));
|
|
debug_directory_data_list.push_back(debug_directory_data);
|
|
}
|
|
for (i = 0; i < debug_directory_data_list.size(); i++) {
|
|
debug_directory_data = debug_directory_data_list[i];
|
|
if (source->Seek(debug_directory_data.PointerToRawData)) {
|
|
size = debug_directory_data.SizeOfData;
|
|
pos = Resize(AlignValue(this->size(), 0x10));
|
|
CopyFrom(*source, size);
|
|
address = last_segment->address() + pos - last_segment->physical_offset();
|
|
|
|
debug_directory_data.PointerToRawData = static_cast<uint32_t>(pos);
|
|
debug_directory_data.AddressOfRawData = static_cast<uint32_t>(address - image_base());
|
|
debug_directory_data_list[i] = debug_directory_data;
|
|
}
|
|
}
|
|
pos = Resize(AlignValue(this->size(), 0x10));
|
|
address = last_segment->address() + pos - last_segment->physical_offset();
|
|
for (i = 0; i < debug_directory_data_list.size(); i++) {
|
|
debug_directory_data = debug_directory_data_list[i];
|
|
Write(&debug_directory_data, sizeof(debug_directory_data));
|
|
}
|
|
dir->set_address(address);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (loader->import_entry()) {
|
|
dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_IMPORT);
|
|
if (dir) {
|
|
dir->set_address(loader->import_entry()->address());
|
|
dir->set_size(loader->import_size());
|
|
}
|
|
|
|
dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_IAT);
|
|
if (dir) {
|
|
dir->set_address(loader->iat_entry()->address());
|
|
dir->set_size(loader->iat_size());
|
|
}
|
|
}
|
|
|
|
if (loader->tls_entry()) {
|
|
dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_TLS);
|
|
if (dir) {
|
|
if (loader->tls_size()) {
|
|
dir->set_address(loader->tls_entry()->address());
|
|
dir->set_size(loader->tls_size());
|
|
}
|
|
else {
|
|
dir->clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (loader->pe_entry())
|
|
pe_->set_entry_point(loader->pe_entry()->address());
|
|
|
|
if (loader->strong_name_signature_entry())
|
|
header_.StrongNameSignature.VirtualAddress = static_cast<uint32_t>(loader->strong_name_signature_entry()->address() - image_base());
|
|
|
|
if (loader->vtable_fixups_entry())
|
|
header_.VTableFixups.VirtualAddress = static_cast<uint32_t>(loader->vtable_fixups_entry()->address() - image_base());
|
|
|
|
if (loader->file_crc_entry()) {
|
|
file_crc_address = loader->file_crc_entry()->address();
|
|
file_crc_size = loader->file_crc_size();
|
|
file_crc_size_address = loader->file_crc_size_entry()->address();
|
|
}
|
|
|
|
if (loader->loader_crc_entry()) {
|
|
loader_crc_address = loader->loader_crc_entry()->address();
|
|
loader_crc_size = loader->loader_crc_size();
|
|
loader_crc_size_address = loader->loader_crc_size_entry()->address();
|
|
loader_crc_hash_address = loader->loader_crc_hash_entry()->address();
|
|
}
|
|
|
|
delete loader;
|
|
|
|
ctx.file->EndProgress();
|
|
}
|
|
|
|
// write NET header
|
|
vmp_segment = segment_list()->last();
|
|
pos = Resize(AlignValue(this->size(), 0x10));
|
|
address = vmp_segment->address() + pos - vmp_segment->physical_offset();
|
|
vmp_segment->set_physical_size(-1);
|
|
dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
|
|
dir->set_address(address);
|
|
Write(&header_, sizeof(header_));
|
|
|
|
// write NET resources
|
|
if (header_.Resources.VirtualAddress) {
|
|
if (ctx.options.flags & cpResourceProtection) {
|
|
header_.Resources.VirtualAddress = 0;
|
|
header_.Resources.Size = 0;
|
|
}
|
|
else {
|
|
Resize(AlignValue(this->size(), sizeof(uint32_t)));
|
|
address = AddressTell();
|
|
ILTable *table = meta_data_->table(ttManifestResource);
|
|
for (i = 0; i < table->count(); i++) {
|
|
ILManifestResource *manifest_resource = reinterpret_cast<ILManifestResource *>(table->item(i));;
|
|
if (manifest_resource->implementation())
|
|
continue;
|
|
|
|
std::vector<uint8_t> data = manifest_resource->data();
|
|
if (data.empty()) {
|
|
source->AddressSeek(header_.Resources.VirtualAddress + image_base() + manifest_resource->offset());
|
|
size = source->ReadDWord();
|
|
manifest_resource->set_offset(static_cast<uint32_t>(AddressTell() - address));
|
|
WriteDWord(size);
|
|
CopyFrom(*source, size);
|
|
}
|
|
else {
|
|
manifest_resource->set_offset(static_cast<uint32_t>(AddressTell() - address));
|
|
WriteDWord(static_cast<uint32_t>(data.size()));
|
|
Write(data.data(), data.size());
|
|
}
|
|
}
|
|
header_.Resources.VirtualAddress = static_cast<uint32_t>(address - image_base());
|
|
}
|
|
}
|
|
|
|
// write metadata
|
|
Resize(AlignValue(this->size(), sizeof(uint32_t)));
|
|
meta_data_->WriteToFile(*this);
|
|
|
|
size = static_cast<uint32_t>(this->size() - vmp_segment->physical_offset());
|
|
vmp_segment->set_size(size);
|
|
vmp_segment->set_physical_size(AlignValue(size, pe_->file_alignment()));
|
|
Resize(vmp_segment->physical_offset() + vmp_segment->physical_size());
|
|
|
|
// write PE resources
|
|
dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_RESOURCE);
|
|
if (dir && dir->address() && dir->physical_size() && source->AddressSeek(dir->address())) {
|
|
last_segment = segment_list()->last();
|
|
address = AlignValue(last_segment->address() + last_segment->size(), pe_->segment_alignment());
|
|
pos = Resize(AlignValue(this->size(), pe_->file_alignment()));
|
|
segment = segment_list()->Add(address, dir->size(), static_cast<uint32_t>(pos), AlignValue(dir->size(), pe_->file_alignment()), resource_section_flags, resource_section_name);
|
|
|
|
uint32_t delta_rva = static_cast<uint32_t>(address - dir->address());
|
|
CopyFrom(*source, dir->size());
|
|
|
|
std::vector<uint64_t> directory_list;
|
|
directory_list.push_back(pos);
|
|
|
|
for (i = 0; i < directory_list.size(); i++) {
|
|
Seek(directory_list[i]);
|
|
IMAGE_RESOURCE_DIRECTORY directory;
|
|
Read(&directory, sizeof(directory));
|
|
for (size_t j = 0; j < static_cast<size_t>(directory.NumberOfNamedEntries) + static_cast<size_t>(directory.NumberOfIdEntries); j++) {
|
|
IMAGE_RESOURCE_DIRECTORY_ENTRY entry;
|
|
Read(&entry, sizeof(entry));
|
|
if (entry.u2.OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY)
|
|
directory_list.push_back(directory_list[0] + (entry.u2.OffsetToData & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY));
|
|
else {
|
|
pos = Tell();
|
|
Seek(directory_list[0] + entry.u2.OffsetToData);
|
|
IMAGE_RESOURCE_DATA_ENTRY item;
|
|
Read(&item, sizeof(item));
|
|
|
|
Seek(directory_list[0] + entry.u2.OffsetToData);
|
|
item.OffsetToData += delta_rva;
|
|
Write(&item, sizeof(item));
|
|
Seek(pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
Resize(segment->physical_offset() + segment->physical_size());
|
|
|
|
dir->set_address(address);
|
|
}
|
|
|
|
// write relocations
|
|
dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_BASERELOC);
|
|
if (dir) {
|
|
if (pe_->fixup_list()->Pack() == 0 || (ctx.options.flags & cpStripFixups) != 0) {
|
|
dir->clear();
|
|
} else {
|
|
last_segment = segment_list()->last();
|
|
address = AlignValue(last_segment->address() + last_segment->size(), pe_->segment_alignment());
|
|
pos = Resize(AlignValue(this->size(), pe_->file_alignment()));
|
|
|
|
size = static_cast<uint32_t>(pe_->fixup_list()->WriteToFile(*pe_));
|
|
|
|
segment = segment_list()->Add(address, size, static_cast<uint32_t>(pos), AlignValue(size, file_alignment()), fixup_section_flags, fixup_section_name);
|
|
Resize(segment->physical_offset() + segment->physical_size());
|
|
|
|
dir->set_address(address);
|
|
dir->set_size(size);
|
|
}
|
|
}
|
|
|
|
// clear directories
|
|
if (ctx.options.flags & cpStripDebugInfo) {
|
|
dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_DEBUG);
|
|
if (dir)
|
|
dir->clear();
|
|
}
|
|
|
|
if (ctx.options.script)
|
|
ctx.options.script->DoAfterSaveFile();
|
|
|
|
// write header
|
|
WriteToFile();
|
|
|
|
// write loader CRC table
|
|
if (loader_crc_address) {
|
|
CRCTable crc_table(function_list_->crc_cryptor(), loader_crc_size);
|
|
|
|
// add loader sections
|
|
j = segment_list()->IndexOf(segment_list()->GetSectionByAddress(loader_crc_address));
|
|
if (j != NOT_ID) {
|
|
c = (ctx.options.flags & cpLoaderCRC) ? j + 1 : segment_list()->count();
|
|
for (i = j; i < c; i++) {
|
|
segment = segment_list()->item(i);
|
|
if (segment->memory_type() & mtWritable)
|
|
continue;
|
|
|
|
size = std::min(static_cast<uint32_t>(segment->size()), segment->physical_size());
|
|
if (size)
|
|
crc_table.Add(segment->address(), size);
|
|
}
|
|
}
|
|
|
|
// skip IAT directory
|
|
dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_IAT);
|
|
if (dir)
|
|
crc_table.Remove(dir->address(), dir->size());
|
|
|
|
// skip fixups
|
|
if ((ctx.options.flags & cpStripFixups) == 0) {
|
|
for (i = 0; i < pe_->fixup_list()->count(); i++) {
|
|
PEFixup *fixup = pe_->fixup_list()->item(i);
|
|
if (!fixup->is_deleted())
|
|
crc_table.Remove(fixup->address(), OperandSizeToValue(fixup->size()));
|
|
}
|
|
}
|
|
// skip loader CRC table
|
|
crc_table.Remove(loader_crc_address, loader_crc_size);
|
|
crc_table.Remove(loader_crc_size_address, sizeof(uint32_t));
|
|
crc_table.Remove(loader_crc_hash_address, sizeof(uint32_t));
|
|
// skip file CRC table
|
|
if (file_crc_address)
|
|
crc_table.Remove(file_crc_address, file_crc_size);
|
|
if (file_crc_size_address)
|
|
crc_table.Remove(file_crc_size_address, sizeof(uint32_t));
|
|
|
|
// write to file
|
|
AddressSeek(loader_crc_address);
|
|
uint32_t hash;
|
|
size = static_cast<uint32_t>(crc_table.WriteToFile(*this, false, &hash));
|
|
AddressSeek(loader_crc_size_address);
|
|
WriteDWord(size);
|
|
AddressSeek(loader_crc_hash_address);
|
|
WriteDWord(hash);
|
|
}
|
|
|
|
// write file CRC table
|
|
if (file_crc_address) {
|
|
CRCTable crc_table(function_list_->crc_cryptor(), file_crc_size - sizeof(uint32_t));
|
|
|
|
// add file range
|
|
crc_table.Add(1, static_cast<size_t>(this->size()) - 1);
|
|
// skip IMAGE_OPTIONAL_HEADER.CheckSum
|
|
crc_table.Remove(header_offset() + sizeof(uint32_t) + sizeof(IMAGE_FILE_HEADER) +
|
|
((cpu_address_size() == osDWord) ? offsetof(IMAGE_OPTIONAL_HEADER32, CheckSum) : offsetof(IMAGE_OPTIONAL_HEADER64, CheckSum)),
|
|
sizeof(uint32_t));
|
|
// skip position of security directory
|
|
crc_table.Remove(header_offset() + sizeof(uint32_t) + sizeof(IMAGE_FILE_HEADER) +
|
|
((cpu_address_size() == osDWord) ? offsetof(IMAGE_OPTIONAL_HEADER32, DataDirectory) : offsetof(IMAGE_OPTIONAL_HEADER64, DataDirectory)) +
|
|
IMAGE_DIRECTORY_ENTRY_SECURITY * sizeof(IMAGE_DATA_DIRECTORY),
|
|
sizeof(IMAGE_DATA_DIRECTORY));
|
|
// skip file CRC table
|
|
if (AddressSeek(file_crc_address))
|
|
crc_table.Remove(Tell(), file_crc_size);
|
|
if (AddressSeek(file_crc_size_address))
|
|
crc_table.Remove(Tell(), sizeof(uint32_t));
|
|
|
|
// write to file
|
|
AddressSeek(file_crc_address);
|
|
size = static_cast<uint32_t>(this->size());
|
|
WriteDWord(size);
|
|
size = static_cast<uint32_t>(crc_table.WriteToFile(*this, true));
|
|
AddressSeek(file_crc_size_address);
|
|
WriteDWord(size);
|
|
}
|
|
|
|
pe_->WriteCheckSum();
|
|
|
|
EndProgress();
|
|
}
|
|
|
|
bool NETArchitecture::WriteToFile()
|
|
{
|
|
PEDirectory *dir = pe_->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
|
|
if (!dir || !AddressSeek(dir->address()))
|
|
return false;
|
|
|
|
if ((header_.Flags & COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0)
|
|
header_.u.EntryPointToken = entry_point_ ? entry_point_->id() : 0;
|
|
header_.MetaData.VirtualAddress = static_cast<uint32_t>(meta_data_->address() - image_base());
|
|
header_.MetaData.Size = meta_data_->size();
|
|
Write(&header_, sizeof(header_));
|
|
return pe_->WriteToFile();
|
|
}
|
|
|
|
bool NETArchitecture::WriteResources(const std::string module_name, Data &dest_data)
|
|
{
|
|
dest_data.clear();
|
|
|
|
if (!header_.Resources.VirtualAddress)
|
|
return false;
|
|
|
|
size_t i;
|
|
std::vector<ILManifestResource *> resource_list;
|
|
|
|
ILTable *src_table = command_list()->table(ttManifestResource);
|
|
for (i = 0; i < src_table->count(); i++) {
|
|
ILManifestResource *resource = reinterpret_cast<ILManifestResource *>(src_table->item(i));
|
|
if (resource->is_deleted() || resource->implementation())
|
|
continue;
|
|
|
|
resource_list.push_back(resource);
|
|
}
|
|
if (resource_list.empty())
|
|
return false;
|
|
|
|
Data data;
|
|
|
|
// DOS header
|
|
data.PushByte(0x4d); data.PushByte(0x5a); data.PushByte(0x90); data.PushByte(0x00); data.PushByte(0x03); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00);
|
|
data.PushByte(0x04); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0xff); data.PushByte(0xff); data.PushByte(0x00); data.PushByte(0x00);
|
|
data.PushByte(0xb8); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00);
|
|
data.PushByte(0x40); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00);
|
|
data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00);
|
|
data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00);
|
|
data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00);
|
|
data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x80); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00);
|
|
data.PushByte(0x0e); data.PushByte(0x1f); data.PushByte(0xba); data.PushByte(0x0e); data.PushByte(0x00); data.PushByte(0xb4); data.PushByte(0x09); data.PushByte(0xcd);
|
|
data.PushByte(0x21); data.PushByte(0xb8); data.PushByte(0x01); data.PushByte(0x4c); data.PushByte(0xcd); data.PushByte(0x21); data.PushByte(0x54); data.PushByte(0x68);
|
|
data.PushByte(0x69); data.PushByte(0x73); data.PushByte(0x20); data.PushByte(0x70); data.PushByte(0x72); data.PushByte(0x6f); data.PushByte(0x67); data.PushByte(0x72);
|
|
data.PushByte(0x61); data.PushByte(0x6d); data.PushByte(0x20); data.PushByte(0x63); data.PushByte(0x61); data.PushByte(0x6e); data.PushByte(0x6e); data.PushByte(0x6f);
|
|
data.PushByte(0x74); data.PushByte(0x20); data.PushByte(0x62); data.PushByte(0x65); data.PushByte(0x20); data.PushByte(0x72); data.PushByte(0x75); data.PushByte(0x6e);
|
|
data.PushByte(0x20); data.PushByte(0x69); data.PushByte(0x6e); data.PushByte(0x20); data.PushByte(0x44); data.PushByte(0x4f); data.PushByte(0x53); data.PushByte(0x20);
|
|
data.PushByte(0x6d); data.PushByte(0x6f); data.PushByte(0x64); data.PushByte(0x65); data.PushByte(0x2e); data.PushByte(0x0d); data.PushByte(0x0d); data.PushByte(0x0a);
|
|
data.PushByte(0x24); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00); data.PushByte(0x00);
|
|
|
|
// PE header
|
|
data.PushDWord(IMAGE_NT_SIGNATURE); // Magic
|
|
data.PushWord(IMAGE_FILE_MACHINE_I386); // Machine
|
|
data.PushWord(1); // NumberOfSections
|
|
data.PushDWord(static_cast<uint32_t>(pe()->time_stamp())); // TimeDateStamp
|
|
data.PushDWord(0); // PointerToSymbolTable
|
|
data.PushDWord(0); // NumberOfSymbols
|
|
data.PushWord(sizeof(IMAGE_OPTIONAL_HEADER32)); // SizeOfOptionalHeader
|
|
data.PushWord(IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_32BIT_MACHINE); // Characteristics
|
|
|
|
// optional header
|
|
data.PushWord(IMAGE_NT_OPTIONAL_HDR32_MAGIC); // Magic
|
|
data.PushByte(0x30); // MajorLinkerVersion
|
|
data.PushByte(0); // MinorLinkerVersion
|
|
data.PushDWord(0); // SizeOfCode
|
|
data.PushDWord(0); // SizeOfInitializedData
|
|
data.PushDWord(0); // SizeOfUninitializedData
|
|
data.PushDWord(0); // AddressOfEntryPoint
|
|
data.PushDWord(0); // BaseOfCode
|
|
data.PushDWord(0); // BaseOfData
|
|
data.PushDWord(0x10000000); // ImageBase
|
|
data.PushDWord(0x2000); // SectionAlignment
|
|
data.PushDWord(0x200); // FileAlignment
|
|
data.PushWord(4); // MajorOperatingSystemVersion
|
|
data.PushWord(0); // MinorOperatingSystemVersion
|
|
data.PushWord(0); // MajorImageVersion
|
|
data.PushWord(0); // MinorImageVersion
|
|
data.PushWord(4); // MajorSubsystemVersion
|
|
data.PushWord(0); // MinorSubsystemVersion
|
|
data.PushDWord(0); // Win32VersionValue
|
|
data.PushDWord(0); // SizeOfImage
|
|
data.PushDWord(0); // SizeOfHeaders
|
|
data.PushDWord(0); // CheckSum
|
|
data.PushWord(IMAGE_SUBSYSTEM_WINDOWS_GUI); // Subsystem
|
|
data.PushWord(IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE | IMAGE_DLLCHARACTERISTICS_NO_SEH | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE); // DllCharacteristics
|
|
data.PushDWord(0x100000); // SizeOfStackReserve
|
|
data.PushDWord(0x1000); // SizeOfStackCommit
|
|
data.PushDWord(0x100000); // SizeOfHeapReserve
|
|
data.PushDWord(0x1000); // SizeOfHeapCommit
|
|
data.PushDWord(0); // LoaderFlags
|
|
data.PushDWord(0x10); // NumberOfRvaAndSizes
|
|
|
|
// directories
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0x2000);
|
|
data.PushDWord(0x48);
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
|
|
// sections
|
|
std::string str = ".text";
|
|
str.resize(8);
|
|
data.PushBuff(str.c_str(), str.size());
|
|
data.PushDWord(0x1000); // VirtualSize
|
|
data.PushDWord(0x2000); // VirtualAddress
|
|
data.PushDWord(0x1000); // SizeOfRawData
|
|
data.PushDWord(0x200); // PointerToRawData
|
|
data.PushDWord(0); // PointerToRelocations
|
|
data.PushDWord(0); // PointerToLineNumbers
|
|
data.PushWord(0); // NumberOfRelocations
|
|
data.PushWord(0); // NumberOfLineNumbers
|
|
data.PushDWord(IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE); // Characteristics
|
|
|
|
// ".text"
|
|
data.resize(AlignValue(data.size(), 0x200));
|
|
data.PushDWord(0x48);
|
|
data.PushWord(header_.MajorRuntimeVersion);
|
|
data.PushWord(header_.MinorRuntimeVersion);
|
|
data.PushDWord(0x2048);
|
|
data.PushDWord(0x1000);
|
|
data.PushDWord(1);
|
|
data.PushDWord(0); // EntryPoint
|
|
data.PushDWord(0); data.PushDWord(0); // Resources
|
|
data.PushDWord(0); data.PushDWord(0); // StrongNameSignature
|
|
data.PushDWord(0); data.PushDWord(0); // CodeManagerTable
|
|
data.PushDWord(0); data.PushDWord(0); // VTableFixups
|
|
data.PushDWord(0); data.PushDWord(0); // ExportAddressTableJumps
|
|
data.PushDWord(0); data.PushDWord(0); // ManagedNativeHeader
|
|
|
|
size_t start_offset = data.size();
|
|
data.PushDWord(0x424a5342); // Signature
|
|
data.PushWord(1); // MajorVersion
|
|
data.PushWord(1); // MinorVersion
|
|
data.PushDWord(0); // Reserved
|
|
str = meta_data_->version();
|
|
data.PushDWord(static_cast<uint32_t>(str.size()));
|
|
data.PushBuff(str.c_str(), str.size());
|
|
data.PushWord(0); // Flags
|
|
data.PushWord(5); // StreamCount
|
|
|
|
size_t heap_offset = data.size();
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
str = "#~";
|
|
str.resize(AlignValue(str.size() + 1, sizeof(uint32_t)));
|
|
data.PushBuff(str.c_str(), str.size());
|
|
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
str = "#Strings";
|
|
str.resize(AlignValue(str.size() + 1, sizeof(uint32_t)));
|
|
data.PushBuff(str.c_str(), str.size());
|
|
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
str = "#US";
|
|
str.resize(AlignValue(str.size() + 1, sizeof(uint32_t)));
|
|
data.PushBuff(str.c_str(), str.size());
|
|
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
str = "#GUID";
|
|
str.resize(AlignValue(str.size() + 1, sizeof(uint32_t)));
|
|
data.PushBuff(str.c_str(), str.size());
|
|
|
|
data.PushDWord(0);
|
|
data.PushDWord(0);
|
|
str = "#Blob";
|
|
str.resize(AlignValue(str.size() + 1, sizeof(uint32_t)));
|
|
data.PushBuff(str.c_str(), str.size());
|
|
|
|
data.WriteDWord(heap_offset, static_cast<uint32_t>(data.size() - start_offset));
|
|
data.PushDWord(0);
|
|
data.PushByte(2);
|
|
data.PushByte(0);
|
|
data.PushByte(0);
|
|
data.PushByte(1);
|
|
data.PushQWord(0);
|
|
data.PushQWord(0x000016003301FA00);
|
|
|
|
PEFile pe_file;
|
|
pe_file.OpenResource(data.data(), data.size(), false);
|
|
NETArchitecture *dst = reinterpret_cast<NETArchitecture *>(pe_file.item(1));
|
|
dst->set_append_mode(true);
|
|
|
|
ILTable *dst_table = dst->command_list()->table(ttModule);
|
|
ILModule *module_def = new ILModule(dst->command_list(), dst_table, module_name + ".dll");
|
|
dst_table->AddObject(module_def);
|
|
|
|
dst_table = dst->command_list()->table(ttAssembly);
|
|
ILAssembly *assembly_def = new ILAssembly(dst->command_list(), dst_table, module_name);
|
|
dst_table->AddObject(assembly_def);
|
|
|
|
dst_table = dst->command_list()->table(ttTypeDef);
|
|
ILTypeDef *type_def = new ILTypeDef(dst->command_list(), dst_table, NULL, "", "<Module>");
|
|
dst_table->AddObject(type_def);
|
|
|
|
dst_table = command_list()->table(ttAssemblyRef);
|
|
ILAssemblyRef *assembly_ref = new ILAssemblyRef(command_list(), dst_table, module_name);
|
|
dst_table->AddObject(assembly_ref);
|
|
|
|
// ".text"
|
|
PESegment *segment = dst->segment_list()->item(0);
|
|
segment->set_size(UINT32_MAX);
|
|
segment->set_physical_size(UINT32_MAX);
|
|
dst->Resize(segment->physical_offset());
|
|
|
|
uint64_t address = dst->AddressTell();
|
|
PEDirectory *iat = dst->pe()->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_IAT);
|
|
iat->set_address(address);
|
|
iat->set_size(8);
|
|
dst->WriteDWord(0);
|
|
dst->WriteDWord(0);
|
|
|
|
address = dst->AddressTell();
|
|
PEDirectory *dir = dst->pe()->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
|
|
dir->set_address(address);
|
|
|
|
IMAGE_COR20_HEADER header = {};
|
|
dst->Write(&header, sizeof(header));
|
|
|
|
uint32_t size;
|
|
uint64_t pos = dst->Resize(AlignValue(dst->size(), sizeof(uint32_t)));
|
|
address = dst->AddressTell();
|
|
dst_table = dst->command_list()->table(ttManifestResource);
|
|
for (i = 0; i < resource_list.size(); i++) {
|
|
uint32_t offset = static_cast<uint32_t>(dst->Resize(AlignValue(dst->size(), sizeof(uint32_t))) - pos);
|
|
ILManifestResource *resource = resource_list[i];
|
|
size_t resource_offset = resource->offset();
|
|
ILManifestResource *dest_resource = reinterpret_cast<ILManifestResource *>(resource->Clone(dst->command_list(), dst_table));
|
|
resource->set_offset(0);
|
|
resource->set_implementation(assembly_ref);
|
|
|
|
dest_resource->set_flags(mrPublic);
|
|
dest_resource->set_offset(offset);
|
|
dst_table->AddObject(dest_resource);
|
|
|
|
std::vector<uint8_t> data = resource->data();
|
|
if (data.empty()) {
|
|
AddressSeek(image_base() + header_.Resources.VirtualAddress + resource_offset);
|
|
size = ReadDWord();
|
|
dst->WriteDWord(size);
|
|
dst->CopyFrom(*this, size);
|
|
}
|
|
else {
|
|
dst->WriteDWord(static_cast<uint32_t>(data.size()));
|
|
dst->Write(data.data(), data.size());
|
|
}
|
|
}
|
|
dst->header_.Resources.VirtualAddress = static_cast<uint32_t>(address - dst->image_base());
|
|
dst->header_.Resources.Size = static_cast<uint32_t>(dst->size() - pos);
|
|
|
|
dst->meta_data_->Prepare();
|
|
dst->meta_data_->UpdateTokens();
|
|
dst->Resize(AlignValue(dst->size(), sizeof(uint32_t)));
|
|
dst->meta_data_->WriteToFile(*dst);
|
|
|
|
dst->Resize(AlignValue(dst->size(), sizeof(uint32_t)));
|
|
address = dst->AddressTell();
|
|
dir = dst->pe()->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_IMPORT);
|
|
dir->set_address(address);
|
|
dir->set_size(0x4f);
|
|
dst->WriteDWord(static_cast<uint32_t>(address - dst->image_base() + 40));
|
|
dst->WriteDWord(0);
|
|
dst->WriteDWord(0);
|
|
dst->WriteDWord(static_cast<uint32_t>(address - dst->image_base() + 66));
|
|
dst->WriteDWord(static_cast<uint32_t>(iat->address() - dst->image_base()));
|
|
|
|
dst->WriteDWord(0);
|
|
dst->WriteDWord(0);
|
|
dst->WriteDWord(0);
|
|
dst->WriteDWord(0);
|
|
dst->WriteDWord(0);
|
|
|
|
dst->WriteDWord(static_cast<uint32_t>(address - dst->image_base() + 52));
|
|
dst->WriteDWord(0);
|
|
dst->WriteDWord(0);
|
|
address = dst->AddressTell();
|
|
dst->WriteWord(0);
|
|
str = "_CorDllMain";
|
|
dst->Write(str.c_str(), str.size() + 1);
|
|
str = "mscoree.dll";
|
|
dst->Write(str.c_str(), str.size() + 1);
|
|
dst->WriteByte(0);
|
|
dst->AddressSeek(iat->address());
|
|
dst->WriteDWord(static_cast<uint32_t>(address - dst->image_base()));
|
|
dst->Seek(dst->size());
|
|
|
|
address = dst->AddressTell();
|
|
dst->pe()->set_entry_point(address);
|
|
dst->WriteByte(0xff);
|
|
dst->WriteByte(0x25);
|
|
dst->WriteDWord(static_cast<uint32_t>(iat->address()));
|
|
|
|
size = static_cast<uint32_t>(dst->size() - segment->physical_offset());
|
|
segment->set_size(size);
|
|
segment->set_physical_size(AlignValue(size, dst->file_alignment()));
|
|
dst->Resize(segment->physical_offset() + segment->physical_size());
|
|
|
|
// ".reloc"
|
|
address = AlignValue(segment->address() + segment->size(), dst->segment_alignment());
|
|
segment = dst->segment_list()->Add(address, UINT32_MAX, segment->physical_offset() + segment->physical_size(), UINT32_MAX, IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA, ".reloc");
|
|
uint32_t reloc_rva = static_cast<uint32_t>(dst->pe()->entry_point() - dst->image_base()) + 2;
|
|
uint32_t page_rva = reloc_rva & ~0xfff;
|
|
dst->WriteDWord(page_rva);
|
|
dst->WriteDWord(0x0c);
|
|
dst->WriteDWord((IMAGE_REL_BASED_HIGHLOW << 12) + reloc_rva - page_rva);
|
|
size = static_cast<uint32_t>(dst->size() - segment->physical_offset());
|
|
segment->set_size(size);
|
|
segment->set_physical_size(AlignValue(size, dst->file_alignment()));
|
|
dir = dst->pe()->command_list()->GetCommandByType(IMAGE_DIRECTORY_ENTRY_BASERELOC);
|
|
dir->set_address(segment->address());
|
|
dir->set_size(size);
|
|
dst->Resize(segment->physical_offset() + segment->physical_size());
|
|
|
|
dst->Seek(dst->pe()->header_offset() + offsetof(IMAGE_NT_HEADERS32, OptionalHeader) + offsetof(IMAGE_OPTIONAL_HEADER32, SizeOfCode));
|
|
dst->WriteDWord(static_cast<uint32_t>(dst->segment_list()->item(0)->physical_size()));
|
|
dst->WriteDWord(static_cast<uint32_t>(dst->segment_list()->item(1)->physical_size()));
|
|
dst->Seek(dst->pe()->header_offset() + offsetof(IMAGE_NT_HEADERS32, OptionalHeader) + offsetof(IMAGE_OPTIONAL_HEADER32, BaseOfCode));
|
|
dst->WriteDWord(static_cast<uint32_t>(dst->segment_list()->item(0)->address() - dst->image_base()));
|
|
dst->WriteDWord(static_cast<uint32_t>(dst->segment_list()->item(1)->address() - dst->image_base()));
|
|
|
|
dst->WriteToFile();
|
|
|
|
dst->set_append_mode(false);
|
|
|
|
dst->Seek(0);
|
|
dest_data.resize(static_cast<size_t>(pe_file.stream()->Size()));
|
|
dst->Read(&dest_data[0], dest_data.size());
|
|
|
|
return true;
|
|
}
|
|
|
|
void NETArchitecture::Rebase(uint64_t delta_base)
|
|
{
|
|
BaseArchitecture::Rebase(delta_base);
|
|
|
|
meta_data_->Rebase(delta_base);
|
|
segment_list()->Rebase(delta_base);
|
|
runtime_function_list_->Rebase(delta_base);
|
|
export_list_->Rebase(delta_base);
|
|
function_list_->Rebase(delta_base);
|
|
|
|
if (entry_point_)
|
|
entry_point_ += delta_base;
|
|
//image_base_ += delta_base;
|
|
}
|
|
|
|
bool NETArchitecture::is_executable() const
|
|
{
|
|
return pe_->is_executable();
|
|
}
|
|
|
|
std::string NETArchitecture::full_name() const
|
|
{
|
|
if (ILAssembly *assembly = reinterpret_cast<ILAssembly *>(meta_data_->token(ttAssembly | 1)))
|
|
return assembly->full_name();
|
|
return std::string();
|
|
}
|
|
|
|
/**
|
|
* ILUserStringsTable
|
|
*/
|
|
|
|
ILUserStringsTable::ILUserStringsTable(ILMetaData *meta)
|
|
: ILTable(meta, ttUserString, 0)
|
|
{
|
|
|
|
}
|
|
|
|
ILUserStringsTable::ILUserStringsTable(ILMetaData *meta, const ILUserStringsTable &src)
|
|
: ILTable(meta, src)
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
ILToken *token = item(i);
|
|
map_[token->value()] = token;
|
|
}
|
|
}
|
|
|
|
ILUserStringsTable *ILUserStringsTable::Clone(ILMetaData *meta) const
|
|
{
|
|
ILUserStringsTable *table = new ILUserStringsTable(meta, *this);
|
|
return table;
|
|
}
|
|
|
|
ILToken *ILUserStringsTable::GetTokenByPos(uint32_t pos) const
|
|
{
|
|
auto it = map_.find(pos);
|
|
if (it != map_.end())
|
|
return it->second;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void ILUserStringsTable::AddObject(ILToken *token)
|
|
{
|
|
ILTable::AddObject(token);
|
|
map_[token->value()] = token;
|
|
}
|
|
|
|
/**
|
|
* BaseNameReference
|
|
*/
|
|
|
|
BaseNameReference::BaseNameReference(NameReferenceList *owner)
|
|
: INameReference(), owner_(owner)
|
|
{
|
|
|
|
}
|
|
|
|
BaseNameReference::~BaseNameReference()
|
|
{
|
|
if (owner_)
|
|
owner_->RemoveObject(this);
|
|
}
|
|
|
|
/**
|
|
* ResourceNameReference
|
|
*/
|
|
|
|
ResourceNameReference::ResourceNameReference(NameReferenceList *owner, ILManifestResource *resource, ILTypeDef *type, const std::string &add)
|
|
: BaseNameReference(owner), resource_(resource), type_(type), add_(add)
|
|
{
|
|
|
|
}
|
|
|
|
void ResourceNameReference::UpdateName()
|
|
{
|
|
resource_->set_name(type_->full_name() + add_);
|
|
}
|
|
|
|
/**
|
|
* StringNameReference
|
|
*/
|
|
|
|
StringNameReference::StringNameReference(NameReferenceList *owner, ILUserString *string, ILTypeDef *type)
|
|
: BaseNameReference(owner), string_(string), type_(type)
|
|
{
|
|
|
|
}
|
|
|
|
void StringNameReference::UpdateName()
|
|
{
|
|
string_->set_name(type_->full_name());
|
|
}
|
|
|
|
/**
|
|
* CommandNameReference
|
|
*/
|
|
|
|
CommandNameReference::CommandNameReference(NameReferenceList *owner, ILCommand *command, ILTypeDef *type)
|
|
: BaseNameReference(owner), command_(command), type_(type)
|
|
{
|
|
|
|
}
|
|
|
|
void CommandNameReference::UpdateName()
|
|
{
|
|
os::unicode_string unicode_name = os::FromUTF8(type_->full_name());
|
|
command_->set_dump(unicode_name.data(), unicode_name.size() * sizeof(os::unicode_char));
|
|
}
|
|
|
|
/**
|
|
* CustomAttributeNameReference
|
|
*/
|
|
|
|
CustomAttributeNameReference::CustomAttributeNameReference(NameReferenceList *owner, CustomAttributeNamedArgument *arg, ILToken *token)
|
|
: BaseNameReference(owner), arg_(arg), token_(token)
|
|
{
|
|
|
|
}
|
|
|
|
void CustomAttributeNameReference::UpdateName()
|
|
{
|
|
std::string name;
|
|
switch (token_->type()) {
|
|
case ttField:
|
|
name = reinterpret_cast<ILField *>(token_)->name();
|
|
break;
|
|
case ttProperty:
|
|
name = reinterpret_cast<ILProperty *>(token_)->name();
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid token type");
|
|
}
|
|
arg_->set_name(name);
|
|
}
|
|
|
|
/**
|
|
* MemberReference
|
|
*/
|
|
|
|
MemberReference::MemberReference(NameReferenceList *owner, ILMemberRef *member, ILToken *token)
|
|
: BaseNameReference(owner), member_(member), token_(token)
|
|
{
|
|
|
|
}
|
|
|
|
void MemberReference::UpdateName()
|
|
{
|
|
std::string name;
|
|
switch (token_->type()) {
|
|
case ttField:
|
|
name = reinterpret_cast<ILField *>(token_)->name();
|
|
break;
|
|
case ttMethodDef:
|
|
name = reinterpret_cast<ILMethodDef *>(token_)->name();
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid token type");
|
|
}
|
|
|
|
member_->set_name(name);
|
|
}
|
|
|
|
/**
|
|
* MethodReference
|
|
*/
|
|
|
|
MethodReference::MethodReference(NameReferenceList *owner, ILMethodDef *method, ILMethodDef *source)
|
|
: BaseNameReference(owner), method_(method), source_(source)
|
|
{
|
|
|
|
}
|
|
|
|
void MethodReference::UpdateName()
|
|
{
|
|
method_->set_name(source_->name());
|
|
}
|
|
|
|
/**
|
|
* BamlTypeInfoRecordReference
|
|
*/
|
|
|
|
BamlTypeInfoRecordReference::BamlTypeInfoRecordReference(NameReferenceList *owner, TypeInfoRecord *record, ILToken *token)
|
|
: BaseNameReference(owner), record_(record), token_(token)
|
|
{
|
|
|
|
}
|
|
|
|
void BamlTypeInfoRecordReference::UpdateName()
|
|
{
|
|
std::string name;
|
|
switch (token_->type()) {
|
|
case ttTypeDef:
|
|
name = reinterpret_cast<ILTypeDef *>(token_)->name();
|
|
break;
|
|
case ttTypeRef:
|
|
name = reinterpret_cast<ILTypeRef *>(token_)->name();
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid token type");
|
|
}
|
|
|
|
record_->set_type_name(name);
|
|
}
|
|
|
|
/**
|
|
* BamlAttributeInfoRecordReference
|
|
*/
|
|
|
|
BamlAttributeInfoRecordReference::BamlAttributeInfoRecordReference(NameReferenceList *owner, AttributeInfoRecord *record, ILToken *token)
|
|
: BaseNameReference(owner), record_(record), token_(token)
|
|
{
|
|
|
|
}
|
|
|
|
void BamlAttributeInfoRecordReference::UpdateName()
|
|
{
|
|
std::string name;
|
|
switch (token_->type()) {
|
|
case ttProperty:
|
|
name = reinterpret_cast<ILProperty *>(token_)->name();
|
|
break;
|
|
case ttEvent:
|
|
name = reinterpret_cast<ILEvent *>(token_)->name();
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid token type");
|
|
}
|
|
|
|
record_->set_name(name);
|
|
}
|
|
|
|
/**
|
|
* BamlPropertyRecordReference
|
|
*/
|
|
|
|
BamlPropertyRecordReference::BamlPropertyRecordReference(NameReferenceList *owner, PropertyRecord *record, ILToken *token)
|
|
: BaseNameReference(owner), record_(record), token_(token)
|
|
{
|
|
|
|
}
|
|
|
|
void BamlPropertyRecordReference::UpdateName()
|
|
{
|
|
std::string name;
|
|
switch (token_->type()) {
|
|
case ttMethodDef:
|
|
name = reinterpret_cast<ILMethodDef *>(token_)->name();
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid token type");
|
|
}
|
|
|
|
record_->set_value(name);
|
|
}
|
|
|
|
/**
|
|
* NameReferenceList
|
|
*/
|
|
|
|
NameReferenceList::NameReferenceList()
|
|
: ObjectList<INameReference>()
|
|
{
|
|
|
|
}
|
|
|
|
void NameReferenceList::AddResourceReference(ILManifestResource *resource, ILTypeDef *type, const std::string &add)
|
|
{
|
|
AddObject(new ResourceNameReference(this, resource, type, add));
|
|
}
|
|
|
|
void NameReferenceList::AddStringReference(ILUserString *string, ILTypeDef *type)
|
|
{
|
|
AddObject(new StringNameReference(this, string, type));
|
|
}
|
|
|
|
void NameReferenceList::AddCommandReference(ILCommand *command, ILTypeDef *type)
|
|
{
|
|
AddObject(new CommandNameReference(this, command, type));
|
|
}
|
|
|
|
void NameReferenceList::AddCustomAttributeNameReference(ILCustomAttribute *attribute, CustomAttributeNamedArgument *arg, ILToken *token)
|
|
{
|
|
AddObject(new CustomAttributeNameReference(this, arg, token));
|
|
if (attribute)
|
|
custom_attribute_list_.insert(attribute);
|
|
}
|
|
|
|
void NameReferenceList::AddCustomAttribute(ILCustomAttribute *attribute)
|
|
{
|
|
if (attribute)
|
|
custom_attribute_list_.insert(attribute);
|
|
}
|
|
|
|
void NameReferenceList::AddMemberReference(ILMemberRef *member, ILToken *token)
|
|
{
|
|
AddObject(new MemberReference(this, member, token));
|
|
}
|
|
|
|
void NameReferenceList::UpdateNames()
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->UpdateName();
|
|
}
|
|
|
|
for (std::set<ILCustomAttribute *>::const_iterator it = custom_attribute_list_.begin(); it != custom_attribute_list_.end(); it++) {
|
|
(*it)->UpdateValue();
|
|
}
|
|
|
|
for (std::set<ILManifestResource *>::const_iterator it = manifest_resource_list_.begin(); it != manifest_resource_list_.end(); it++) {
|
|
(*it)->UpdateValue();
|
|
}
|
|
}
|
|
|
|
void NameReferenceList::AddTypeInfoRecordReference(ILManifestResource *resource, TypeInfoRecord *record, ILToken *token)
|
|
{
|
|
AddObject(new BamlTypeInfoRecordReference(this, record, token));
|
|
if (resource)
|
|
manifest_resource_list_.insert(resource);
|
|
}
|
|
|
|
void NameReferenceList::AddAttributeInfoRecordReference(ILManifestResource *resource, AttributeInfoRecord *record, ILToken *token)
|
|
{
|
|
AddObject(new BamlAttributeInfoRecordReference(this, record, token));
|
|
if (resource)
|
|
manifest_resource_list_.insert(resource);
|
|
}
|
|
|
|
void NameReferenceList::AddPropertyRecordReference(ILManifestResource *resource, PropertyRecord *record, ILToken *token)
|
|
{
|
|
AddObject(new BamlPropertyRecordReference(this, record, token));
|
|
if (resource)
|
|
manifest_resource_list_.insert(resource);
|
|
}
|
|
|
|
void NameReferenceList::AddMethodReference(ILMethodDef *method, ILMethodDef *source)
|
|
{
|
|
AddObject(new MethodReference(this, method, source));
|
|
}
|
|
|
|
void NameReferenceList::AddManifestResource(ILManifestResource *resource)
|
|
{
|
|
if (resource)
|
|
manifest_resource_list_.insert(resource);
|
|
}
|
|
|
|
/**
|
|
* BamlRecord
|
|
*/
|
|
|
|
BamlRecord::BamlRecord(BamlDocument *owner)
|
|
: IObject(), owner_(owner), position_(0)
|
|
{
|
|
|
|
}
|
|
|
|
BamlRecord::~BamlRecord()
|
|
{
|
|
if (owner_)
|
|
owner_->RemoveObject(this);
|
|
}
|
|
|
|
uint64_t BamlRecord::GetPosition(size_t index)
|
|
{
|
|
while (index < owner()->count()) {
|
|
bool keys = true;
|
|
switch (owner()->item(index)->type()) {
|
|
case DefAttributeKeyString:
|
|
case DefAttributeKeyType:
|
|
case OptimizedStaticResource:
|
|
break;
|
|
case StaticResourceStart:
|
|
index = owner()->GetClosedIndex(StaticResourceStart, StaticResourceEnd, index + 1);
|
|
if (index == NOT_ID)
|
|
throw std::runtime_error("Invalid record index");
|
|
break;
|
|
case KeyElementStart:
|
|
index = owner()->GetClosedIndex(KeyElementStart, KeyElementEnd, index + 1);
|
|
if (index == NOT_ID)
|
|
throw std::runtime_error("Invalid record index");
|
|
break;
|
|
default:
|
|
keys = false;
|
|
break;
|
|
}
|
|
if (!keys)
|
|
break;
|
|
|
|
index++;
|
|
}
|
|
return owner()->item(index)->position();
|
|
}
|
|
|
|
/**
|
|
* SizedBamlRecord
|
|
*/
|
|
|
|
SizedBamlRecord::SizedBamlRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), data_size_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void SizedBamlRecord::Read(NETStream &stream)
|
|
{
|
|
uint64_t pos = stream.Tell();
|
|
uint32_t size = stream.ReadEncoded7Bit();
|
|
data_size_ = size - static_cast<uint32_t>(stream.Tell() - pos);
|
|
ReadData(stream);
|
|
}
|
|
|
|
uint32_t SizeOfEncodedInt(uint32_t value)
|
|
{
|
|
if ((value & ~0x7F) == 0)
|
|
return 1;
|
|
if ((value & ~0x3FFF) == 0)
|
|
return 2;
|
|
if ((value & ~0x1FFFFF) == 0)
|
|
return 3;
|
|
if ((value & ~0xFFFFFFF) == 0)
|
|
return 4;
|
|
return 5;
|
|
}
|
|
|
|
void SizedBamlRecord::Write(NETStream &stream)
|
|
{
|
|
uint64_t pos = stream.Tell();
|
|
WriteData(stream);
|
|
uint32_t size = static_cast<uint32_t>(stream.Tell() - pos);
|
|
size = SizeOfEncodedInt(SizeOfEncodedInt(size) + size) + size;
|
|
stream.Seek(pos, soBeginning);
|
|
stream.WriteEncoded7Bit(size);
|
|
WriteData(stream);
|
|
}
|
|
|
|
/**
|
|
* DocumentStartRecord
|
|
*/
|
|
|
|
DocumentStartRecord::DocumentStartRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
void DocumentStartRecord::Read(NETStream &stream)
|
|
{
|
|
load_async_ = stream.ReadBoolean();
|
|
max_async_records_ = stream.ReadDWord();
|
|
debug_baml_ = stream.ReadBoolean();
|
|
}
|
|
|
|
void DocumentStartRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteBoolean(load_async_);
|
|
stream.WriteDWord(max_async_records_);
|
|
stream.WriteBoolean(debug_baml_);
|
|
}
|
|
|
|
/**
|
|
* DocumentEndRecord
|
|
*/
|
|
|
|
DocumentEndRecord::DocumentEndRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* ElementStartRecord
|
|
*/
|
|
|
|
ElementStartRecord::ElementStartRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), type_id_(0), flags_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void ElementStartRecord::Read(NETStream &stream)
|
|
{
|
|
type_id_ = stream.ReadWord();
|
|
flags_ = stream.ReadByte();
|
|
}
|
|
|
|
void ElementStartRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteWord(type_id_);
|
|
stream.WriteByte(flags_);
|
|
}
|
|
|
|
/**
|
|
* ElementEndRecord
|
|
*/
|
|
|
|
ElementEndRecord::ElementEndRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* AssemblyInfoRecord
|
|
*/
|
|
|
|
AssemblyInfoRecord::AssemblyInfoRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), assembly_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void AssemblyInfoRecord::ReadData(NETStream &stream)
|
|
{
|
|
assembly_id_ = stream.ReadWord();
|
|
assembly_name_ = stream.ReadString();
|
|
}
|
|
|
|
void AssemblyInfoRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteWord(assembly_id_);
|
|
stream.WriteString(assembly_name_);
|
|
}
|
|
|
|
/**
|
|
* TypeInfoRecord
|
|
*/
|
|
|
|
TypeInfoRecord::TypeInfoRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), type_id_(0), assembly_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void TypeInfoRecord::ReadData(NETStream &stream)
|
|
{
|
|
type_id_ = stream.ReadWord();
|
|
assembly_id_ = stream.ReadWord();
|
|
type_name_ = stream.ReadString();
|
|
}
|
|
|
|
void TypeInfoRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteWord(type_id_);
|
|
stream.WriteWord(assembly_id_);
|
|
stream.WriteString(type_name_);
|
|
}
|
|
|
|
/**
|
|
* XmlnsPropertyRecord
|
|
*/
|
|
|
|
XmlnsPropertyRecord::XmlnsPropertyRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
void XmlnsPropertyRecord::ReadData(NETStream &stream)
|
|
{
|
|
prefix_ = stream.ReadString();
|
|
xml_namespace_ = stream.ReadString();
|
|
assembly_ids_.resize(stream.ReadWord());
|
|
for (size_t i = 0; i < assembly_ids_.size(); i++) {
|
|
assembly_ids_[i] = stream.ReadWord();
|
|
}
|
|
}
|
|
|
|
void XmlnsPropertyRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteString(prefix_);
|
|
stream.WriteString(xml_namespace_);
|
|
stream.WriteWord(static_cast<uint16_t>(assembly_ids_.size()));
|
|
for (size_t i = 0; i < assembly_ids_.size(); i++) {
|
|
stream.WriteWord(assembly_ids_[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* AttributeInfoRecord
|
|
*/
|
|
|
|
AttributeInfoRecord::AttributeInfoRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), attribute_id_(0), owner_type_id_(0), attribute_usage_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void AttributeInfoRecord::ReadData(NETStream &stream)
|
|
{
|
|
attribute_id_ = stream.ReadWord();
|
|
owner_type_id_ = stream.ReadWord();
|
|
attribute_usage_ = stream.ReadByte();
|
|
name_ = stream.ReadString();
|
|
}
|
|
|
|
void AttributeInfoRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteWord(attribute_id_);
|
|
stream.WriteWord(owner_type_id_);
|
|
stream.WriteByte(attribute_usage_);
|
|
stream.WriteString(name_);
|
|
}
|
|
|
|
/**
|
|
* PropertyDictionaryStartRecord
|
|
*/
|
|
|
|
PropertyDictionaryStartRecord::PropertyDictionaryStartRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
void PropertyDictionaryStartRecord::Read(NETStream &stream)
|
|
{
|
|
attribute_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void PropertyDictionaryStartRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteWord(attribute_id_);
|
|
}
|
|
|
|
/**
|
|
* PropertyDictionaryEndRecord
|
|
*/
|
|
|
|
PropertyDictionaryEndRecord::PropertyDictionaryEndRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* StringInfoRecord
|
|
*/
|
|
|
|
StringInfoRecord::StringInfoRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), string_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void StringInfoRecord::ReadData(NETStream &stream)
|
|
{
|
|
string_id_ = stream.ReadWord();
|
|
value_ = stream.ReadString();
|
|
}
|
|
|
|
void StringInfoRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteWord(string_id_);
|
|
stream.WriteString(value_);
|
|
}
|
|
|
|
/**
|
|
* DeferableContentStartRecord
|
|
*/
|
|
|
|
DeferableContentStartRecord::DeferableContentStartRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), offset_(0), offset_pos_(0), record_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
void DeferableContentStartRecord::Read(NETStream &stream)
|
|
{
|
|
offset_pos_ = stream.Tell();
|
|
offset_ = stream.ReadDWord();
|
|
}
|
|
|
|
void DeferableContentStartRecord::Write(NETStream &stream)
|
|
{
|
|
offset_pos_ = stream.Tell();
|
|
stream.WriteDWord(0);
|
|
}
|
|
|
|
void DeferableContentStartRecord::ReadDefer(size_t index)
|
|
{
|
|
record_ = owner()->GetRecordByPosition(offset_pos_ + sizeof(offset_) + offset_);
|
|
}
|
|
|
|
void DeferableContentStartRecord::WriteDefer(size_t index, NETStream &stream)
|
|
{
|
|
stream.Seek(offset_pos_, soBeginning);
|
|
stream.WriteDWord(static_cast<uint32_t>(record_->position() - (offset_pos_ + sizeof(offset_))));
|
|
}
|
|
|
|
/**
|
|
* DefAttributeKeyStringRecord
|
|
*/
|
|
|
|
DefAttributeKeyStringRecord::DefAttributeKeyStringRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), value_id_(0), offset_(0), shared_(false), shared_set_(false), record_(NULL), offset_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void DefAttributeKeyStringRecord::ReadData(NETStream &stream)
|
|
{
|
|
value_id_ = stream.ReadWord();
|
|
offset_ = stream.ReadDWord();
|
|
shared_ = stream.ReadBoolean();
|
|
shared_set_ = stream.ReadBoolean();
|
|
}
|
|
|
|
void DefAttributeKeyStringRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteWord(value_id_);
|
|
offset_pos_ = static_cast<uint32_t>(stream.Tell());
|
|
stream.WriteDWord(offset_);
|
|
stream.WriteBoolean(shared_);
|
|
stream.WriteBoolean(shared_set_);
|
|
}
|
|
|
|
void DefAttributeKeyStringRecord::ReadDefer(size_t index)
|
|
{
|
|
record_ = owner()->GetRecordByPosition(GetPosition(index) + offset_);
|
|
}
|
|
|
|
void DefAttributeKeyStringRecord::WriteDefer(size_t index, NETStream &stream)
|
|
{
|
|
stream.Seek(offset_pos_, soBeginning);
|
|
stream.WriteDWord(static_cast<uint32_t>(record_->position() - GetPosition(index)));
|
|
}
|
|
|
|
/**
|
|
* DefAttributeKeyTypeRecord
|
|
*/
|
|
|
|
DefAttributeKeyTypeRecord::DefAttributeKeyTypeRecord(BamlDocument *owner)
|
|
: ElementStartRecord(owner), offset_(0), record_(NULL), offset_pos_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void DefAttributeKeyTypeRecord::Read(NETStream &stream)
|
|
{
|
|
ElementStartRecord::Read(stream);
|
|
offset_ = stream.ReadDWord();
|
|
shared_ = stream.ReadBoolean();
|
|
shared_set_ = stream.ReadBoolean();
|
|
}
|
|
|
|
void DefAttributeKeyTypeRecord::Write(NETStream &stream)
|
|
{
|
|
ElementStartRecord::Write(stream);
|
|
offset_pos_ = stream.Tell();
|
|
stream.WriteDWord(0);
|
|
stream.WriteBoolean(shared_);
|
|
stream.WriteBoolean(shared_set_);
|
|
}
|
|
|
|
void DefAttributeKeyTypeRecord::ReadDefer(size_t index)
|
|
{
|
|
record_ = owner()->GetRecordByPosition(GetPosition(index) + offset_);
|
|
}
|
|
|
|
void DefAttributeKeyTypeRecord::WriteDefer(size_t index, NETStream &stream)
|
|
{
|
|
stream.Seek(offset_pos_, soBeginning);
|
|
stream.WriteDWord(static_cast<uint32_t>(record_->position() - GetPosition(index)));
|
|
}
|
|
|
|
/**
|
|
* PropertyComplexStartRecord
|
|
*/
|
|
|
|
PropertyComplexStartRecord::PropertyComplexStartRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), attribute_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void PropertyComplexStartRecord::Read(NETStream &stream)
|
|
{
|
|
attribute_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void PropertyComplexStartRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteWord(attribute_id_);
|
|
}
|
|
|
|
/**
|
|
* PropertyComplexEndRecord
|
|
*/
|
|
|
|
PropertyComplexEndRecord::PropertyComplexEndRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* PropertyTypeReferenceRecord
|
|
*/
|
|
|
|
PropertyTypeReferenceRecord::PropertyTypeReferenceRecord(BamlDocument *owner)
|
|
: PropertyComplexStartRecord(owner), type_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void PropertyTypeReferenceRecord::Read(NETStream &stream)
|
|
{
|
|
PropertyComplexStartRecord::Read(stream);
|
|
type_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void PropertyTypeReferenceRecord::Write(NETStream &stream)
|
|
{
|
|
PropertyComplexStartRecord::Write(stream);
|
|
stream.WriteWord(type_id_);
|
|
}
|
|
|
|
/**
|
|
* ContentPropertyRecord
|
|
*/
|
|
|
|
ContentPropertyRecord::ContentPropertyRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), attribute_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void ContentPropertyRecord::Read(NETStream &stream)
|
|
{
|
|
attribute_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void ContentPropertyRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteWord(attribute_id_);
|
|
}
|
|
|
|
/**
|
|
* PropertyCustomRecord
|
|
*/
|
|
|
|
PropertyCustomRecord::PropertyCustomRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), attribute_id_(0), serializer_type_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void PropertyCustomRecord::ReadData(NETStream &stream)
|
|
{
|
|
uint64_t pos = stream.Tell();
|
|
attribute_id_ = stream.ReadWord();
|
|
serializer_type_id_ = stream.ReadWord();
|
|
data_.resize(data_size() - static_cast<uint32_t>(stream.Tell() - pos));
|
|
stream.Read(data_.data(), data_.size());
|
|
}
|
|
|
|
void PropertyCustomRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteWord(attribute_id_);
|
|
stream.WriteWord(serializer_type_id_);
|
|
stream.Write(data_.data(), data_.size());
|
|
}
|
|
|
|
/**
|
|
* PropertyRecord
|
|
*/
|
|
|
|
PropertyRecord::PropertyRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), attribute_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void PropertyRecord::ReadData(NETStream &stream)
|
|
{
|
|
attribute_id_ = stream.ReadWord();
|
|
value_ = stream.ReadString();
|
|
}
|
|
|
|
void PropertyRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteWord(attribute_id_);
|
|
stream.WriteString(value_);
|
|
}
|
|
|
|
/**
|
|
* PropertyWithConverterRecord
|
|
*/
|
|
|
|
PropertyWithConverterRecord::PropertyWithConverterRecord(BamlDocument *owner)
|
|
: PropertyRecord(owner), converter_type_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void PropertyWithConverterRecord::ReadData(NETStream &stream)
|
|
{
|
|
PropertyRecord::ReadData(stream);
|
|
converter_type_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void PropertyWithConverterRecord::WriteData(NETStream &stream)
|
|
{
|
|
PropertyRecord::WriteData(stream);
|
|
stream.WriteWord(converter_type_id_);
|
|
}
|
|
|
|
/**
|
|
* PIMappingRecord
|
|
*/
|
|
|
|
PIMappingRecord::PIMappingRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), assembly_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void PIMappingRecord::ReadData(NETStream &stream)
|
|
{
|
|
xml_namespace_ = stream.ReadString();
|
|
clr_namespace_ = stream.ReadString();
|
|
assembly_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void PIMappingRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteString(xml_namespace_);
|
|
stream.WriteString(clr_namespace_);
|
|
stream.WriteWord(assembly_id_);
|
|
}
|
|
|
|
/**
|
|
* PropertyListStartRecord
|
|
*/
|
|
|
|
PropertyListStartRecord::PropertyListStartRecord(BamlDocument *owner)
|
|
: PropertyComplexStartRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* PropertyListEndRecord
|
|
*/
|
|
|
|
PropertyListEndRecord::PropertyListEndRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* ConnectionIdRecord
|
|
*/
|
|
|
|
ConnectionIdRecord::ConnectionIdRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), connection_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void ConnectionIdRecord::Read(NETStream &stream)
|
|
{
|
|
connection_id_ = stream.ReadDWord();
|
|
}
|
|
|
|
void ConnectionIdRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteDWord(connection_id_);
|
|
}
|
|
|
|
/**
|
|
* OptimizedStaticResourceRecord
|
|
*/
|
|
|
|
OptimizedStaticResourceRecord::OptimizedStaticResourceRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), flags_(0), value_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void OptimizedStaticResourceRecord::Read(NETStream &stream)
|
|
{
|
|
flags_ = stream.ReadByte();
|
|
value_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void OptimizedStaticResourceRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteByte(flags_);
|
|
stream.WriteWord(value_id_);
|
|
}
|
|
|
|
/**
|
|
* ConstructorParametersStartRecord
|
|
*/
|
|
|
|
ConstructorParametersStartRecord::ConstructorParametersStartRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* ConstructorParametersEndRecord
|
|
*/
|
|
|
|
ConstructorParametersEndRecord::ConstructorParametersEndRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* TextRecord
|
|
*/
|
|
|
|
TextRecord::TextRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
void TextRecord::ReadData(NETStream &stream)
|
|
{
|
|
value_ = stream.ReadString();
|
|
}
|
|
|
|
void TextRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteString(value_);
|
|
}
|
|
|
|
/**
|
|
* StaticResourceIdRecord
|
|
*/
|
|
|
|
StaticResourceIdRecord::StaticResourceIdRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), static_resource_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void StaticResourceIdRecord::Read(NETStream &stream)
|
|
{
|
|
static_resource_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void StaticResourceIdRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteWord(static_resource_id_);
|
|
}
|
|
|
|
/**
|
|
* StaticResourceEndRecord
|
|
*/
|
|
|
|
StaticResourceEndRecord::StaticResourceEndRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* StaticResourceStartRecord
|
|
*/
|
|
|
|
StaticResourceStartRecord::StaticResourceStartRecord(BamlDocument *owner)
|
|
: ElementStartRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* PropertyWithStaticResourceIdRecord
|
|
*/
|
|
|
|
PropertyWithStaticResourceIdRecord::PropertyWithStaticResourceIdRecord(BamlDocument *owner)
|
|
: StaticResourceIdRecord(owner), attribute_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void PropertyWithStaticResourceIdRecord::Read(NETStream &stream)
|
|
{
|
|
attribute_id_ = stream.ReadWord();
|
|
StaticResourceIdRecord::Read(stream);
|
|
}
|
|
|
|
void PropertyWithStaticResourceIdRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteWord(attribute_id_);
|
|
StaticResourceIdRecord::Write(stream);
|
|
}
|
|
|
|
/**
|
|
* PropertyWithExtensionRecord
|
|
*/
|
|
|
|
PropertyWithExtensionRecord::PropertyWithExtensionRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), attribute_id_(0), flags_(0), value_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void PropertyWithExtensionRecord::Read(NETStream &stream)
|
|
{
|
|
attribute_id_ = stream.ReadWord();
|
|
flags_ = stream.ReadWord();
|
|
value_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void PropertyWithExtensionRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteWord(attribute_id_);
|
|
stream.WriteWord(flags_);
|
|
stream.WriteWord(value_id_);
|
|
}
|
|
|
|
/**
|
|
* DefAttributeRecord
|
|
*/
|
|
|
|
DefAttributeRecord::DefAttributeRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), name_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void DefAttributeRecord::ReadData(NETStream &stream)
|
|
{
|
|
value_ = stream.ReadString();
|
|
name_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void DefAttributeRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteString(value_);
|
|
stream.WriteWord(name_id_);
|
|
}
|
|
|
|
/**
|
|
* KeyElementStartRecord
|
|
*/
|
|
|
|
KeyElementStartRecord::KeyElementStartRecord(BamlDocument *owner)
|
|
: DefAttributeKeyTypeRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* KeyElementEndRecord
|
|
*/
|
|
|
|
KeyElementEndRecord::KeyElementEndRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* ConstructorParameterTypeRecord
|
|
*/
|
|
|
|
ConstructorParameterTypeRecord::ConstructorParameterTypeRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), type_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void ConstructorParameterTypeRecord::Read(NETStream &stream)
|
|
{
|
|
type_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void ConstructorParameterTypeRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteWord(type_id_);
|
|
}
|
|
|
|
/**
|
|
* TextWithConverterRecord
|
|
*/
|
|
|
|
TextWithConverterRecord::TextWithConverterRecord(BamlDocument *owner)
|
|
: TextRecord(owner), converter_type_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void TextWithConverterRecord::ReadData(NETStream &stream)
|
|
{
|
|
TextRecord::ReadData(stream);
|
|
converter_type_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void TextWithConverterRecord::WriteData(NETStream &stream)
|
|
{
|
|
TextRecord::WriteData(stream);
|
|
stream.WriteWord(converter_type_id_);
|
|
}
|
|
|
|
/**
|
|
* TextWithIdRecord
|
|
*/
|
|
|
|
TextWithIdRecord::TextWithIdRecord(BamlDocument *owner)
|
|
: TextRecord(owner), value_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void TextWithIdRecord::ReadData(NETStream &stream)
|
|
{
|
|
TextRecord::ReadData(stream);
|
|
value_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void TextWithIdRecord::WriteData(NETStream &stream)
|
|
{
|
|
TextRecord::WriteData(stream);
|
|
stream.WriteWord(value_id_);
|
|
}
|
|
|
|
/**
|
|
* LineNumberAndPositionRecord
|
|
*/
|
|
|
|
LineNumberAndPositionRecord::LineNumberAndPositionRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), line_number_(0), line_position_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void LineNumberAndPositionRecord::Read(NETStream &stream)
|
|
{
|
|
line_number_ = stream.ReadDWord();
|
|
line_position_ = stream.ReadDWord();
|
|
}
|
|
|
|
void LineNumberAndPositionRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteDWord(line_number_);
|
|
stream.WriteDWord(line_position_);
|
|
}
|
|
|
|
/**
|
|
* LinePositionRecord
|
|
*/
|
|
|
|
LinePositionRecord::LinePositionRecord(BamlDocument *owner)
|
|
: BamlRecord(owner), line_position_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void LinePositionRecord::Read(NETStream &stream)
|
|
{
|
|
line_position_ = stream.ReadDWord();
|
|
}
|
|
|
|
void LinePositionRecord::Write(NETStream &stream)
|
|
{
|
|
stream.WriteDWord(line_position_);
|
|
}
|
|
|
|
/**
|
|
* LiteralContentRecord
|
|
*/
|
|
|
|
LiteralContentRecord::LiteralContentRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), reserved0_(0), reserved1_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void LiteralContentRecord::ReadData(NETStream &stream)
|
|
{
|
|
value_ = stream.ReadString();
|
|
reserved0_ = stream.ReadDWord();
|
|
reserved1_ = stream.ReadDWord();
|
|
}
|
|
|
|
void LiteralContentRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteString(value_);
|
|
stream.WriteDWord(reserved0_);
|
|
stream.WriteDWord(reserved1_);
|
|
}
|
|
|
|
/**
|
|
* PresentationOptionsAttributeRecord
|
|
*/
|
|
|
|
PresentationOptionsAttributeRecord::PresentationOptionsAttributeRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), name_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void PresentationOptionsAttributeRecord::ReadData(NETStream &stream)
|
|
{
|
|
value_ = stream.ReadString();
|
|
name_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void PresentationOptionsAttributeRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteString(value_);
|
|
stream.WriteWord(name_id_);
|
|
}
|
|
|
|
/**
|
|
* PropertyArrayStartRecord
|
|
*/
|
|
|
|
PropertyArrayStartRecord::PropertyArrayStartRecord(BamlDocument *owner)
|
|
: PropertyComplexStartRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* PropertyArrayStartRecord
|
|
*/
|
|
|
|
PropertyArrayEndRecord::PropertyArrayEndRecord(BamlDocument *owner)
|
|
: BamlRecord(owner)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* PropertyStringReferenceRecord
|
|
*/
|
|
|
|
PropertyStringReferenceRecord::PropertyStringReferenceRecord(BamlDocument *owner)
|
|
: PropertyComplexStartRecord(owner), string_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void PropertyStringReferenceRecord::Read(NETStream &stream)
|
|
{
|
|
PropertyComplexStartRecord::Read(stream);
|
|
string_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void PropertyStringReferenceRecord::Write(NETStream &stream)
|
|
{
|
|
PropertyComplexStartRecord::Write(stream);
|
|
stream.WriteWord(string_id_);
|
|
}
|
|
|
|
/**
|
|
* RoutedEventRecord
|
|
*/
|
|
|
|
RoutedEventRecord::RoutedEventRecord(BamlDocument *owner)
|
|
: SizedBamlRecord(owner), attribute_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void RoutedEventRecord::ReadData(NETStream &stream)
|
|
{
|
|
attribute_id_ = stream.ReadWord();
|
|
value_ = stream.ReadString();
|
|
}
|
|
|
|
void RoutedEventRecord::WriteData(NETStream &stream)
|
|
{
|
|
stream.WriteWord(attribute_id_);
|
|
stream.WriteString(value_);
|
|
}
|
|
|
|
/**
|
|
* TypeSerializerInfoRecord
|
|
*/
|
|
|
|
TypeSerializerInfoRecord::TypeSerializerInfoRecord(BamlDocument *owner)
|
|
: TypeInfoRecord(owner), type_id_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void TypeSerializerInfoRecord::ReadData(NETStream &stream)
|
|
{
|
|
TypeInfoRecord::ReadData(stream);
|
|
type_id_ = stream.ReadWord();
|
|
}
|
|
|
|
void TypeSerializerInfoRecord::WriteData(NETStream &stream)
|
|
{
|
|
TypeInfoRecord::WriteData(stream);
|
|
stream.WriteWord(type_id_);
|
|
}
|
|
|
|
/**
|
|
* NETStream
|
|
*/
|
|
|
|
NETStream::NETStream()
|
|
: MemoryStream()
|
|
{
|
|
|
|
}
|
|
|
|
NETStream::NETStream(AbstractStream &stream, size_t size)
|
|
{
|
|
CopyFrom(stream, size);
|
|
Seek(0, soBeginning);
|
|
}
|
|
|
|
size_t NETStream::Read(void *Buffer, size_t Count)
|
|
{
|
|
size_t res = MemoryStream::Read(Buffer, Count);
|
|
if (res != Count)
|
|
throw std::runtime_error("Runtime error at Read");
|
|
return res;
|
|
}
|
|
|
|
uint8_t NETStream::ReadByte()
|
|
{
|
|
uint8_t b;
|
|
Read(&b, sizeof(b));
|
|
return b;
|
|
}
|
|
|
|
uint16_t NETStream::ReadWord()
|
|
{
|
|
uint16_t w;
|
|
Read(&w, sizeof(w));
|
|
return w;
|
|
}
|
|
|
|
uint32_t NETStream::ReadDWord()
|
|
{
|
|
uint32_t dw;
|
|
Read(&dw, sizeof(dw));
|
|
return dw;
|
|
}
|
|
|
|
bool NETStream::ReadBoolean()
|
|
{
|
|
return (ReadByte() != 0);
|
|
}
|
|
|
|
uint32_t NETStream::ReadEncoded()
|
|
{
|
|
uint32_t res;
|
|
uint8_t b = ReadByte();
|
|
if ((b & 0x80) == 0) {
|
|
res = b & 0x7f;
|
|
}
|
|
else if ((b & 0x40) == 0) {
|
|
res = ((b & 0x3f) << 8) + ReadByte();
|
|
}
|
|
else {
|
|
res = ((b & 0x1f) << 24) + (ReadByte() << 16) + (ReadByte() << 8) + ReadByte();
|
|
}
|
|
return res;
|
|
}
|
|
|
|
uint32_t NETStream::ReadEncoded7Bit()
|
|
{
|
|
uint32_t res = 0;
|
|
size_t shift = 0;
|
|
uint8_t b;
|
|
do {
|
|
b = ReadByte();
|
|
res |= (b & 0x7F) << shift;
|
|
shift += 7;
|
|
} while ((b & 0x80) != 0);
|
|
return res;
|
|
}
|
|
|
|
std::string NETStream::ReadString()
|
|
{
|
|
std::string res;
|
|
uint32_t size = ReadEncoded7Bit();
|
|
for (size_t i = 0; i < size; i++) {
|
|
res.push_back(ReadByte());
|
|
}
|
|
return res;
|
|
}
|
|
|
|
std::string NETStream::ReadUnicodeString()
|
|
{
|
|
os::unicode_string res;
|
|
uint32_t size = ReadEncoded7Bit() >> 1;
|
|
for (size_t i = 0; i < size; i++) {
|
|
res.push_back(ReadWord());
|
|
}
|
|
return os::ToUTF8(res);
|
|
}
|
|
|
|
void NETStream::WriteByte(uint8_t value)
|
|
{
|
|
Write(&value, sizeof(value));
|
|
}
|
|
|
|
void NETStream::WriteWord(uint16_t value)
|
|
{
|
|
Write(&value, sizeof(value));
|
|
}
|
|
|
|
void NETStream::WriteDWord(uint32_t value)
|
|
{
|
|
Write(&value, sizeof(value));
|
|
}
|
|
|
|
void NETStream::WriteEncoded7Bit(uint32_t value)
|
|
{
|
|
while (value >= 0x80) {
|
|
WriteByte(static_cast<uint8_t>(value) | 0x80);
|
|
value >>= 7;
|
|
}
|
|
WriteByte(static_cast<uint8_t>(value));
|
|
}
|
|
|
|
void NETStream::WriteString(const std::string &value)
|
|
{
|
|
WriteEncoded7Bit(static_cast<uint32_t>(value.size()));
|
|
Write(value.c_str(), value.size());
|
|
}
|
|
|
|
void NETStream::WriteBoolean(bool value)
|
|
{
|
|
WriteByte(value ? 1 : 0);
|
|
}
|
|
|
|
void NETStream::WriteUnicodeString(const os::unicode_string &value)
|
|
{
|
|
WriteEncoded7Bit(static_cast<uint32_t>(value.size()) << 1);
|
|
for (size_t i = 0; i < value.size(); i++) {
|
|
WriteWord(value[i]);
|
|
}
|
|
}
|
|
|
|
void NETStream::WriteEncoded(uint32_t value)
|
|
{
|
|
if (value < 0x80) {
|
|
WriteByte(static_cast<uint8_t>(value));
|
|
}
|
|
else if (value < 0x4000) {
|
|
WriteByte(static_cast<uint8_t>(value >> 8) | 0x80);
|
|
WriteByte(static_cast<uint8_t>(value));
|
|
}
|
|
else if (value < 0x02000000) {
|
|
WriteByte(static_cast<uint8_t>(value >> 24) | 0xc0);
|
|
WriteByte(static_cast<uint8_t>(value >> 16));
|
|
WriteByte(static_cast<uint8_t>(value >> 8));
|
|
WriteByte(static_cast<uint8_t>(value));
|
|
}
|
|
else {
|
|
throw std::runtime_error("Value can not be encoded");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* BamlDocument
|
|
*/
|
|
|
|
BamlDocument::BamlDocument()
|
|
: ObjectList<BamlRecord>(), reader_version_major_(0), reader_version_minor_(0), updater_version_major_(0), updater_version_minor_(0),
|
|
writer_version_major_(0), writer_version_minor_(0)
|
|
{
|
|
|
|
}
|
|
|
|
void BamlDocument::clear()
|
|
{
|
|
ObjectList<BamlRecord>::clear();
|
|
reader_version_major_ = 0;
|
|
reader_version_minor_ = 0;
|
|
updater_version_major_ = 0;
|
|
updater_version_minor_ = 0;
|
|
writer_version_major_ = 0;
|
|
writer_version_minor_ = 0;
|
|
}
|
|
|
|
BamlRecord *BamlDocument::GetRecordByPosition(uint64_t pos) const
|
|
{
|
|
for (size_t i = 0; i < count(); i++) {
|
|
BamlRecord *record = item(i);
|
|
if (record->position() == pos)
|
|
return record;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
size_t BamlDocument::GetClosedIndex(BamlRecordType start, BamlRecordType end, size_t index)
|
|
{
|
|
while (index < count()) {
|
|
BamlRecord *record = item(index);
|
|
if (record->type() == start) {
|
|
index = GetClosedIndex(start, end, index + 1);
|
|
if (index == NOT_ID)
|
|
break;
|
|
} else if (record->type() == end)
|
|
return index;
|
|
index++;
|
|
}
|
|
return NOT_ID;
|
|
}
|
|
|
|
bool BamlDocument::ReadFromStream(NETStream &stream)
|
|
{
|
|
clear();
|
|
|
|
const os::unicode_char MSBAML[6] = { 'M', 'S', 'B', 'A', 'M', 'L' };
|
|
|
|
uint32_t signature_size = stream.ReadDWord();
|
|
signature_.resize(signature_size >> 1);
|
|
stream.Read(&signature_[0], signature_.size() * sizeof(os::unicode_char));
|
|
|
|
if (signature_.size() != _countof(MSBAML) || memcmp(signature_.data(), MSBAML, signature_.size() * sizeof(os::unicode_char)))
|
|
return false;
|
|
|
|
reader_version_major_ = stream.ReadWord();
|
|
reader_version_minor_ = stream.ReadWord();
|
|
updater_version_major_ = stream.ReadWord();
|
|
updater_version_minor_ = stream.ReadWord();
|
|
writer_version_major_ = stream.ReadWord();
|
|
writer_version_minor_ = stream.ReadWord();
|
|
|
|
if (reader_version_major_ != 0 || reader_version_minor_ != 0x60 ||
|
|
updater_version_major_ != 0 || updater_version_minor_ != 0x60 ||
|
|
writer_version_major_ != 0 || writer_version_minor_ != 0x60)
|
|
return false;
|
|
|
|
uint64_t size = stream.Size();
|
|
while (stream.Tell() < size) {
|
|
uint64_t pos = stream.Tell();
|
|
uint8_t type = stream.ReadByte();
|
|
BamlRecord *rec;
|
|
switch (type) {
|
|
case AssemblyInfo:
|
|
rec = new AssemblyInfoRecord(this);
|
|
break;
|
|
case AttributeInfo:
|
|
rec = new AttributeInfoRecord(this);
|
|
break;
|
|
case ConstructorParametersStart:
|
|
rec = new ConstructorParametersStartRecord(this);
|
|
break;
|
|
case ConstructorParametersEnd:
|
|
rec = new ConstructorParametersEndRecord(this);
|
|
break;
|
|
case ConstructorParameterType:
|
|
rec = new ConstructorParameterTypeRecord(this);
|
|
break;
|
|
case ConnectionId:
|
|
rec = new ConnectionIdRecord(this);
|
|
break;
|
|
case ContentProperty:
|
|
rec = new ContentPropertyRecord(this);
|
|
break;
|
|
case DefAttribute:
|
|
rec = new DefAttributeRecord(this);
|
|
break;
|
|
case DefAttributeKeyString:
|
|
rec = new DefAttributeKeyStringRecord(this);
|
|
break;
|
|
case DefAttributeKeyType:
|
|
rec = new DefAttributeKeyTypeRecord(this);
|
|
break;
|
|
case DeferableContentStart:
|
|
rec = new DeferableContentStartRecord(this);
|
|
break;
|
|
case DocumentEnd:
|
|
rec = new DocumentEndRecord(this);
|
|
break;
|
|
case DocumentStart:
|
|
rec = new DocumentStartRecord(this);
|
|
break;
|
|
case ElementEnd:
|
|
rec = new ElementEndRecord(this);
|
|
break;
|
|
case ElementStart:
|
|
rec = new ElementStartRecord(this);
|
|
break;
|
|
case KeyElementEnd:
|
|
rec = new KeyElementEndRecord(this);
|
|
break;
|
|
case KeyElementStart:
|
|
rec = new KeyElementStartRecord(this);
|
|
break;
|
|
case LineNumberAndPosition:
|
|
rec = new LineNumberAndPositionRecord(this);
|
|
break;
|
|
case LinePosition:
|
|
rec = new LinePositionRecord(this);
|
|
break;
|
|
case LiteralContent:
|
|
rec = new LiteralContentRecord(this);
|
|
break;
|
|
case OptimizedStaticResource:
|
|
rec = new OptimizedStaticResourceRecord(this);
|
|
break;
|
|
case PIMapping:
|
|
rec = new PIMappingRecord(this);
|
|
break;
|
|
case PresentationOptionsAttribute:
|
|
rec = new PresentationOptionsAttributeRecord(this);
|
|
break;
|
|
case Property:
|
|
rec = new PropertyRecord(this);
|
|
break;
|
|
case PropertyArrayEnd:
|
|
rec = new PropertyArrayEndRecord(this);
|
|
break;
|
|
case PropertyArrayStart:
|
|
rec = new PropertyArrayStartRecord(this);
|
|
break;
|
|
case PropertyComplexEnd:
|
|
rec = new PropertyComplexEndRecord(this);
|
|
break;
|
|
case PropertyComplexStart:
|
|
rec = new PropertyComplexStartRecord(this);
|
|
break;
|
|
case PropertyCustom:
|
|
rec = new PropertyCustomRecord(this);
|
|
break;
|
|
case PropertyDictionaryEnd:
|
|
rec = new PropertyDictionaryEndRecord(this);
|
|
break;
|
|
case PropertyDictionaryStart:
|
|
rec = new PropertyDictionaryStartRecord(this);
|
|
break;
|
|
case PropertyListEnd:
|
|
rec = new PropertyListEndRecord(this);
|
|
break;
|
|
case PropertyListStart:
|
|
rec = new PropertyListStartRecord(this);
|
|
break;
|
|
case PropertyStringReference:
|
|
rec = new PropertyStringReferenceRecord(this);
|
|
break;
|
|
case PropertyTypeReference:
|
|
rec = new PropertyTypeReferenceRecord(this);
|
|
break;
|
|
case PropertyWithConverter:
|
|
rec = new PropertyWithConverterRecord(this);
|
|
break;
|
|
case PropertyWithExtension:
|
|
rec = new PropertyWithExtensionRecord(this);
|
|
break;
|
|
case PropertyWithStaticResourceId:
|
|
rec = new PropertyWithStaticResourceIdRecord(this);
|
|
break;
|
|
case RoutedEvent:
|
|
rec = new RoutedEventRecord(this);
|
|
break;
|
|
case StaticResourceEnd:
|
|
rec = new StaticResourceEndRecord(this);
|
|
break;
|
|
case StaticResourceId:
|
|
rec = new StaticResourceIdRecord(this);
|
|
break;
|
|
case StaticResourceStart:
|
|
rec = new StaticResourceStartRecord(this);
|
|
break;
|
|
case StringInfo:
|
|
rec = new StringInfoRecord(this);
|
|
break;
|
|
case Text:
|
|
rec = new TextRecord(this);
|
|
break;
|
|
case TextWithConverter:
|
|
rec = new TextWithConverterRecord(this);
|
|
break;
|
|
case TextWithId:
|
|
rec = new TextWithIdRecord(this);
|
|
break;
|
|
case TypeInfo:
|
|
rec = new TypeInfoRecord(this);
|
|
break;
|
|
case XmlnsProperty:
|
|
rec = new XmlnsPropertyRecord(this);
|
|
break;
|
|
case TypeSerializerInfo:
|
|
rec = new TypeSerializerInfoRecord(this);
|
|
break;
|
|
default:
|
|
throw std::runtime_error(string_format("Unknown BAML record type: %x", type));
|
|
}
|
|
rec->set_position(pos);
|
|
AddObject(rec);
|
|
|
|
rec->Read(stream);
|
|
}
|
|
|
|
for (size_t i = 0; i < count(); i++) {
|
|
item(i)->ReadDefer(i);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void BamlDocument::WriteToStream(NETStream &stream)
|
|
{
|
|
stream.WriteDWord(static_cast<uint32_t>(signature_.size() * sizeof(os::unicode_char)));
|
|
stream.Write(signature_.data(), signature_.size() * sizeof(os::unicode_char));
|
|
stream.WriteWord(reader_version_major_);
|
|
stream.WriteWord(reader_version_minor_);
|
|
stream.WriteWord(updater_version_major_);
|
|
stream.WriteWord(updater_version_minor_);
|
|
stream.WriteWord(writer_version_major_);
|
|
stream.WriteWord(writer_version_minor_);
|
|
|
|
size_t i;
|
|
for (i = 0; i < count(); i++) {
|
|
BamlRecord *rec = item(i);
|
|
rec->set_position(stream.Tell());
|
|
stream.WriteByte(rec->type());
|
|
rec->Write(stream);
|
|
}
|
|
for (i = 0; i < count(); i++) {
|
|
item(i)->WriteDefer(i, stream);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* BamlElement
|
|
*/
|
|
|
|
BamlElement::BamlElement(BamlElement *parent)
|
|
: IObject(), parent_(parent), header_(NULL), footer_(NULL), type_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
BamlElement::~BamlElement()
|
|
{
|
|
for (size_t i = 0; i < children_.size(); i++) {
|
|
delete children_[i];
|
|
}
|
|
}
|
|
|
|
bool BamlElement::is_header(BamlRecordType type)
|
|
{
|
|
switch (type) {
|
|
case ConstructorParametersStart:
|
|
case DocumentStart:
|
|
case ElementStart:
|
|
case KeyElementStart:
|
|
case NamedElementStart:
|
|
case PropertyArrayStart:
|
|
case PropertyComplexStart:
|
|
case PropertyDictionaryStart:
|
|
case PropertyListStart:
|
|
case StaticResourceStart:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool BamlElement::is_footer(BamlRecordType type)
|
|
{
|
|
switch (type) {
|
|
case ConstructorParametersEnd:
|
|
case DocumentEnd:
|
|
case ElementEnd:
|
|
case KeyElementEnd:
|
|
case PropertyArrayEnd:
|
|
case PropertyComplexEnd:
|
|
case PropertyDictionaryEnd:
|
|
case PropertyListEnd:
|
|
case StaticResourceEnd:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool BamlElement::is_match(BamlRecordType header, BamlRecordType footer)
|
|
{
|
|
switch (header) {
|
|
case ConstructorParametersStart:
|
|
return footer == ConstructorParametersEnd;
|
|
|
|
case DocumentStart:
|
|
return footer == DocumentEnd;
|
|
|
|
case KeyElementStart:
|
|
return footer == KeyElementEnd;
|
|
|
|
case PropertyArrayStart:
|
|
return footer == PropertyArrayEnd;
|
|
|
|
case PropertyComplexStart:
|
|
return footer == PropertyComplexEnd;
|
|
|
|
case PropertyDictionaryStart:
|
|
return footer == PropertyDictionaryEnd;
|
|
|
|
case PropertyListStart:
|
|
return footer == PropertyListEnd;
|
|
|
|
case StaticResourceStart:
|
|
return footer == StaticResourceEnd;
|
|
|
|
case ElementStart:
|
|
case NamedElementStart:
|
|
return footer == ElementEnd;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool BamlElement::Parse(BamlDocument *document)
|
|
{
|
|
std::vector<BamlElement *> stack;
|
|
BamlElement *current = NULL;
|
|
|
|
for (size_t i = 0; i < document->count(); i++) {
|
|
BamlRecord *record = document->item(i);
|
|
if (is_header(record->type())) {
|
|
BamlElement *prev = current;
|
|
|
|
current = prev ? new BamlElement(prev) : this;
|
|
current->header_ = record;
|
|
if (prev) {
|
|
prev->children_.push_back(current);
|
|
stack.push_back(prev);
|
|
}
|
|
}
|
|
else if (is_footer(record->type())) {
|
|
if (!current)
|
|
return false;
|
|
|
|
while (!is_match(current->header_->type(), record->type())) {
|
|
if (stack.empty())
|
|
return false;
|
|
|
|
current = stack.back();
|
|
stack.pop_back();
|
|
}
|
|
|
|
current->footer_ = record;
|
|
if (!stack.empty()) {
|
|
current = stack.back();
|
|
stack.pop_back();
|
|
}
|
|
}
|
|
else {
|
|
if (!current)
|
|
return false;
|
|
|
|
current->body_.push_back(record);
|
|
}
|
|
}
|
|
|
|
return (header_ && header_->type() == DocumentStart && footer_ && footer_->type() == DocumentEnd);
|
|
}
|
|
|
|
/**
|
|
* CustomAttributeValue
|
|
*/
|
|
|
|
CustomAttributeValue::CustomAttributeValue(ILMetaData *meta)
|
|
: IObject(), meta_(meta)
|
|
{
|
|
fixed_list_ = new CustomAttributeArgumentList();
|
|
named_list_ = new CustomAttributeNamedArgumentList();
|
|
}
|
|
|
|
CustomAttributeValue::~CustomAttributeValue()
|
|
{
|
|
delete fixed_list_;
|
|
delete named_list_;
|
|
}
|
|
|
|
void CustomAttributeValue::clear()
|
|
{
|
|
fixed_list_->clear();
|
|
named_list_->clear();
|
|
}
|
|
|
|
void CustomAttributeValue::Parse(ILToken *type, const ILData &data)
|
|
{
|
|
clear();
|
|
|
|
uint32_t id = 0;
|
|
if (data.ReadWord(id) != 1)
|
|
throw std::runtime_error("Invalid format");
|
|
|
|
ILSignature *signature;
|
|
switch (type->type()) {
|
|
case ttMethodDef:
|
|
signature = reinterpret_cast<ILMethodDef *>(type)->signature();
|
|
break;
|
|
case ttMemberRef:
|
|
signature = reinterpret_cast<ILMemberRef *>(type)->signature();
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid format");
|
|
}
|
|
|
|
size_t i, c;
|
|
|
|
for (i = 0; i < signature->count(); i++) {
|
|
CustomAttributeFixedArgument *arg = new CustomAttributeFixedArgument(meta_, fixed_list_, signature->item(i));
|
|
fixed_list_->AddObject(arg);
|
|
arg->Read(data, id);
|
|
}
|
|
|
|
c = data.ReadWord(id);
|
|
for (i = 0; i < c; i++) {
|
|
CustomAttributeNamedArgument *arg = new CustomAttributeNamedArgument(meta_, named_list_);
|
|
named_list_->AddObject(arg);
|
|
arg->Read(data, id);
|
|
}
|
|
}
|
|
|
|
void CustomAttributeValue::Write(ILData &data)
|
|
{
|
|
size_t i;
|
|
|
|
data.WriteWord(1);
|
|
for (i = 0; i < fixed_list_->count(); i++) {
|
|
fixed_list_->item(i)->Write(data);
|
|
}
|
|
|
|
data.WriteWord(static_cast<uint16_t>(named_list_->count()));
|
|
for (i = 0; i < named_list_->count(); i++) {
|
|
named_list_->item(i)->Write(data);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* BaseCustomAttributeArgument
|
|
*/
|
|
|
|
CustomAttributeArgument::CustomAttributeArgument(ILMetaData *meta, CustomAttributeArgumentList *owner)
|
|
: IObject(), meta_(meta), owner_(owner), children_(NULL), reference_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
CustomAttributeArgument::~CustomAttributeArgument()
|
|
{
|
|
if (owner_)
|
|
owner_->RemoveObject(this);
|
|
delete children_;
|
|
}
|
|
|
|
ILElement *CustomAttributeArgument::ReadFieldOrPropType(const ILData &data, uint32_t &id)
|
|
{
|
|
CorElementType type = static_cast<CorElementType>(data.ReadByte(id));
|
|
switch (type) {
|
|
case ELEMENT_TYPE_BOOLEAN:
|
|
case ELEMENT_TYPE_CHAR:
|
|
case ELEMENT_TYPE_I1:
|
|
case ELEMENT_TYPE_U1:
|
|
case ELEMENT_TYPE_I2:
|
|
case ELEMENT_TYPE_U2:
|
|
case ELEMENT_TYPE_I4:
|
|
case ELEMENT_TYPE_U4:
|
|
case ELEMENT_TYPE_I8:
|
|
case ELEMENT_TYPE_U8:
|
|
case ELEMENT_TYPE_R4:
|
|
case ELEMENT_TYPE_R8:
|
|
case ELEMENT_TYPE_STRING:
|
|
case ELEMENT_TYPE_TYPE:
|
|
case ELEMENT_TYPE_TAGGED_OBJECT:
|
|
return new ILElement(meta_, NULL, type);
|
|
case ELEMENT_TYPE_SZARRAY:
|
|
return new ILElement(meta_, NULL, ELEMENT_TYPE_SZARRAY, NULL, ReadFieldOrPropType(data, id));
|
|
case ELEMENT_TYPE_ENUM:
|
|
return new ILElement(meta_, NULL, ELEMENT_TYPE_ENUM, ReadType(data, id), NULL);
|
|
default:
|
|
throw std::runtime_error("Invalid serialization type");
|
|
}
|
|
}
|
|
|
|
CustomAttributeFixedArgument *CustomAttributeArgument::AddChild(ILElement *type)
|
|
{
|
|
if (!children_)
|
|
children_ = new CustomAttributeArgumentList();
|
|
CustomAttributeFixedArgument *res = new CustomAttributeFixedArgument(meta_, children_, type);
|
|
children_->AddObject(res);
|
|
return res;
|
|
}
|
|
|
|
void CustomAttributeArgument::Read(const ILData &data, uint32_t &id)
|
|
{
|
|
ReadValue(data, id, type());
|
|
}
|
|
|
|
void CustomAttributeArgument::ReadEnum(const ILData &data, uint32_t &id, ILToken *type)
|
|
{
|
|
ILTypeDef *type_def;
|
|
switch (type->type()) {
|
|
case ttTypeDef:
|
|
type_def = reinterpret_cast<ILTypeDef *>(type);
|
|
break;
|
|
case ttTypeRef:
|
|
type_def = reinterpret_cast<ILTypeRef *>(type)->Resolve(true);
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid token type");
|
|
}
|
|
|
|
ILElement *underlying_type = type_def->GetEnumUnderlyingType();
|
|
if (!underlying_type || underlying_type->type() < ELEMENT_TYPE_BOOLEAN || underlying_type->type() > ELEMENT_TYPE_U8)
|
|
throw std::runtime_error("Invalid enum underlying type");
|
|
|
|
ReadValue(data, id, underlying_type);
|
|
}
|
|
|
|
void CustomAttributeArgument::ReadObject(const ILData &data, uint32_t &id)
|
|
{
|
|
AddChild(ReadFieldOrPropType(data, id))->Read(data, id);
|
|
}
|
|
|
|
void CustomAttributeArgument::ReadArray(const ILData &data, uint32_t &id, ILElement *type)
|
|
{
|
|
size_t size = data.ReadDWord(id);
|
|
if (size == UINT32_MAX)
|
|
return;
|
|
|
|
for (size_t i = 0; i < size; i++) {
|
|
AddChild(type)->Read(data, id);
|
|
}
|
|
}
|
|
|
|
std::string CustomAttributeArgument::ReadString(const ILData &data, uint32_t &id)
|
|
{
|
|
std::string res;
|
|
uint32_t old_pos = id;
|
|
if (data.ReadByte(id) != 0xff) {
|
|
--id;
|
|
res = data.ReadString(id);
|
|
}
|
|
value_.Write(data.data() + old_pos, id - old_pos);
|
|
return res;
|
|
}
|
|
|
|
ILTypeDef *CustomAttributeArgument::ReadType(const ILData &data, uint32_t &id)
|
|
{
|
|
std::string type_name = data.ReadString(id);
|
|
if (type_name.empty())
|
|
throw std::runtime_error("Invalid format");
|
|
|
|
return meta_->ResolveType(type_name, true);
|
|
}
|
|
|
|
void CustomAttributeArgument::ReadValue(const ILData &data, uint32_t &id, ILElement *type)
|
|
{
|
|
switch (type->type()) {
|
|
case ELEMENT_TYPE_BOOLEAN:
|
|
case ELEMENT_TYPE_I1:
|
|
case ELEMENT_TYPE_U1:
|
|
value_.WriteByte(data.ReadByte(id));
|
|
break;
|
|
case ELEMENT_TYPE_CHAR:
|
|
case ELEMENT_TYPE_I2:
|
|
case ELEMENT_TYPE_U2:
|
|
value_.WriteWord(data.ReadWord(id));
|
|
break;
|
|
case ELEMENT_TYPE_I4:
|
|
case ELEMENT_TYPE_U4:
|
|
case ELEMENT_TYPE_R4:
|
|
value_.WriteDWord(data.ReadDWord(id));
|
|
break;
|
|
case ELEMENT_TYPE_I8:
|
|
case ELEMENT_TYPE_U8:
|
|
case ELEMENT_TYPE_R8:
|
|
value_.WriteQWord(data.ReadQWord(id));
|
|
break;
|
|
case ELEMENT_TYPE_STRING:
|
|
ReadString(data, id);
|
|
break;
|
|
case ELEMENT_TYPE_TYPE:
|
|
reference_ = ReadType(data, id);
|
|
break;
|
|
case ELEMENT_TYPE_SZARRAY:
|
|
ReadArray(data, id, type->next());
|
|
break;
|
|
case ELEMENT_TYPE_OBJECT:
|
|
case ELEMENT_TYPE_TAGGED_OBJECT:
|
|
ReadObject(data, id);
|
|
break;
|
|
case ELEMENT_TYPE_ENUM:
|
|
reference_ = reinterpret_cast<ILTypeDef *>(type->token());
|
|
ReadEnum(data, id, type->token());
|
|
break;
|
|
case ELEMENT_TYPE_VALUETYPE:
|
|
ReadEnum(data, id, type->token());
|
|
break;
|
|
case ELEMENT_TYPE_CLASS:
|
|
if (type->token()->type() == ttTypeRef) {
|
|
ILTypeRef *type_ref = reinterpret_cast<ILTypeRef *>(type->token());
|
|
if (type_ref->resolution_scope() == type_ref->meta()->GetCoreLib() && type_ref->name_space() == "System") {
|
|
if (type_ref->name() == "Type") {
|
|
reference_ = ReadType(data, id);
|
|
break;
|
|
} else if (type_ref->name() == "String") {
|
|
ReadString(data, id);
|
|
break;
|
|
}
|
|
else if (type_ref->name() == "Object") {
|
|
ReadObject(data, id);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
ReadEnum(data, id, type->token());
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid element type");
|
|
}
|
|
}
|
|
|
|
void CustomAttributeArgument::Write(ILData &data) const
|
|
{
|
|
WriteValue(data, type());
|
|
}
|
|
|
|
void CustomAttributeArgument::WriteArray(ILData &data) const
|
|
{
|
|
if (!children_) {
|
|
data.WriteDWord(UINT32_MAX);
|
|
return;
|
|
}
|
|
|
|
data.WriteDWord(static_cast<uint32_t>(children_->count()));
|
|
for (size_t i = 0; i < children_->count(); i++) {
|
|
children_->item(i)->Write(data);
|
|
}
|
|
}
|
|
|
|
void CustomAttributeArgument::WriteObject(ILData &data) const
|
|
{
|
|
CustomAttributeArgument *child = children_->item(0);
|
|
WriteFieldOrPropType(data, child->type());
|
|
child->Write(data);
|
|
}
|
|
|
|
void CustomAttributeArgument::WriteType(ILData &data, ILTypeDef *type_def) const
|
|
{
|
|
std::string type_name = type_def->reflection_name();
|
|
if (type_def->meta() != meta_) {
|
|
ILAssembly *assembly = reinterpret_cast<ILAssembly *>(type_def->meta()->token(ttAssembly | 1));
|
|
type_name += ", " + assembly->full_name();
|
|
}
|
|
data.WriteString(type_name);
|
|
}
|
|
|
|
void CustomAttributeArgument::WriteFieldOrPropType(ILData &data, ILElement *type) const
|
|
{
|
|
data.WriteByte(type->type());
|
|
switch (type->type()) {
|
|
case ELEMENT_TYPE_BOOLEAN:
|
|
case ELEMENT_TYPE_CHAR:
|
|
case ELEMENT_TYPE_I1:
|
|
case ELEMENT_TYPE_U1:
|
|
case ELEMENT_TYPE_I2:
|
|
case ELEMENT_TYPE_U2:
|
|
case ELEMENT_TYPE_I4:
|
|
case ELEMENT_TYPE_U4:
|
|
case ELEMENT_TYPE_I8:
|
|
case ELEMENT_TYPE_U8:
|
|
case ELEMENT_TYPE_R4:
|
|
case ELEMENT_TYPE_R8:
|
|
case ELEMENT_TYPE_STRING:
|
|
case ELEMENT_TYPE_TYPE:
|
|
case ELEMENT_TYPE_TAGGED_OBJECT:
|
|
break;
|
|
case ELEMENT_TYPE_SZARRAY:
|
|
WriteFieldOrPropType(data, type->next());
|
|
break;
|
|
case ELEMENT_TYPE_ENUM:
|
|
WriteType(data, reinterpret_cast<ILTypeDef *>(type->token()));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CustomAttributeArgument::WriteValue(ILData &data, ILElement *type) const
|
|
{
|
|
switch (type->type()) {
|
|
case ELEMENT_TYPE_BOOLEAN:
|
|
case ELEMENT_TYPE_I1:
|
|
case ELEMENT_TYPE_U1:
|
|
case ELEMENT_TYPE_CHAR:
|
|
case ELEMENT_TYPE_I2:
|
|
case ELEMENT_TYPE_U2:
|
|
case ELEMENT_TYPE_I4:
|
|
case ELEMENT_TYPE_U4:
|
|
case ELEMENT_TYPE_R4:
|
|
case ELEMENT_TYPE_I8:
|
|
case ELEMENT_TYPE_U8:
|
|
case ELEMENT_TYPE_R8:
|
|
case ELEMENT_TYPE_STRING:
|
|
case ELEMENT_TYPE_TYPE:
|
|
case ELEMENT_TYPE_VALUETYPE:
|
|
case ELEMENT_TYPE_ENUM:
|
|
data.Write(value_.data(), value_.size());
|
|
break;
|
|
case ELEMENT_TYPE_SZARRAY:
|
|
WriteArray(data);
|
|
break;
|
|
case ELEMENT_TYPE_OBJECT:
|
|
case ELEMENT_TYPE_TAGGED_OBJECT:
|
|
WriteObject(data);
|
|
break;
|
|
case ELEMENT_TYPE_CLASS:
|
|
if (reference_) // System.Type
|
|
WriteType(data, reference_);
|
|
else if (children_) // System.Object
|
|
WriteObject(data);
|
|
else
|
|
data.Write(value_.data(), value_.size());
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid element type");
|
|
}
|
|
}
|
|
|
|
bool CustomAttributeArgument::ToBoolean() const
|
|
{
|
|
if (type()->type() != ELEMENT_TYPE_BOOLEAN)
|
|
throw std::runtime_error("Invalid element type");
|
|
if (value_.size() != 1)
|
|
throw std::runtime_error("Invalid value size");
|
|
return (value_[0] != 0);
|
|
}
|
|
|
|
std::string CustomAttributeArgument::ToString() const
|
|
{
|
|
if (type()->type() != ELEMENT_TYPE_STRING)
|
|
throw std::runtime_error("Invalid element type");
|
|
uint32_t pos = 0;
|
|
return value_.ReadString(pos);
|
|
}
|
|
|
|
/**
|
|
* CustomAttributeArgument
|
|
*/
|
|
|
|
CustomAttributeFixedArgument::CustomAttributeFixedArgument(ILMetaData *meta, CustomAttributeArgumentList *owner, ILElement *type)
|
|
: CustomAttributeArgument(meta, owner), type_(type)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* CustomAttributeArgumentList
|
|
*/
|
|
|
|
CustomAttributeArgumentList::CustomAttributeArgumentList()
|
|
: ObjectList<CustomAttributeArgument>()
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* CustomAttributeNamedArgument
|
|
*/
|
|
|
|
CustomAttributeNamedArgument::CustomAttributeNamedArgument(ILMetaData *meta, CustomAttributeArgumentList *owner)
|
|
: CustomAttributeArgument(meta, owner), is_field_(false), type_(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
CustomAttributeNamedArgument::~CustomAttributeNamedArgument()
|
|
{
|
|
delete type_;
|
|
}
|
|
|
|
void CustomAttributeNamedArgument::Read(const ILData &data, uint32_t &id)
|
|
{
|
|
switch (data.ReadByte(id)) {
|
|
case 0x53:
|
|
is_field_ = true;
|
|
break;
|
|
case 0x54:
|
|
is_field_ = false;
|
|
break;
|
|
default:
|
|
throw std::runtime_error("Invalid format");
|
|
}
|
|
type_ = ReadFieldOrPropType(data, id);
|
|
name_ = data.ReadString(id);
|
|
CustomAttributeArgument::Read(data, id);
|
|
}
|
|
|
|
void CustomAttributeNamedArgument::Write(ILData &data) const
|
|
{
|
|
data.WriteByte(is_field_ ? 0x53 : 0x54);
|
|
WriteFieldOrPropType(data, type());
|
|
data.WriteString(name_);
|
|
CustomAttributeArgument::Write(data);
|
|
}
|
|
|
|
/**
|
|
* CustomAttributeNamedArgumentList
|
|
*/
|
|
|
|
CustomAttributeNamedArgumentList::CustomAttributeNamedArgumentList()
|
|
: CustomAttributeArgumentList()
|
|
{
|
|
|
|
}
|
|
|
|
CustomAttributeNamedArgument *CustomAttributeNamedArgumentList::item(size_t index) const
|
|
{
|
|
return reinterpret_cast<CustomAttributeNamedArgument *>(CustomAttributeArgumentList::item(index));
|
|
}
|
|
|
|
/**
|
|
* FrameworkVersion
|
|
*/
|
|
|
|
bool try_stou(const std::string &str, uint32_t *value)
|
|
{
|
|
if (str.empty())
|
|
return false;
|
|
|
|
if (str.find_first_not_of("0123456789") != std::string::npos)
|
|
return false;
|
|
|
|
*value = std::stoul(str);
|
|
return true;
|
|
}
|
|
|
|
bool FrameworkVersion::Parse(const std::string &version)
|
|
{
|
|
size_t pos;
|
|
size_t start = 0;
|
|
size_t value_index = 0;
|
|
uint32_t values[3] = { 0 };
|
|
uint32_t num;
|
|
while (value_index < _countof(values)) {
|
|
pos = version.find('.', start);
|
|
if (pos != std::string::npos) {
|
|
if (try_stou(version.substr(start, pos - start), &num)) {
|
|
values[value_index] = num;
|
|
value_index++;
|
|
start = pos + 1;
|
|
continue;
|
|
}
|
|
}
|
|
pos = version.find_first_not_of("0123456789", start);
|
|
if (try_stou(version.substr(start, (pos != std::string::npos) ? pos - start : std::string::npos), &num))
|
|
values[value_index] = num;
|
|
break;
|
|
}
|
|
|
|
if (value_index == 0)
|
|
return false;
|
|
|
|
major = values[0];
|
|
minor = values[1];
|
|
patch = values[2];
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* AssemblyName
|
|
*/
|
|
|
|
AssemblyName::AssemblyName(const std::string &name)
|
|
{
|
|
size_t start, end;
|
|
for (start = 0; ; start = end + 1) {
|
|
end = name.find(',', start);
|
|
while (name[start] == ' ')
|
|
start++;
|
|
std::string str = (end == std::string::npos) ? name.substr(start) : name.substr(start, end - start);
|
|
if (start == 0)
|
|
this->name = str;
|
|
else {
|
|
size_t p = str.find('=');
|
|
if (p == std::string::npos)
|
|
throw std::runtime_error("Malformed assembly name: " + name);
|
|
|
|
std::string key = str.substr(0, p);
|
|
std::string value = str.substr(p + 1);
|
|
if (key == "Version")
|
|
version = value;
|
|
else if (key == "Culture")
|
|
culture = value;
|
|
else if (key == "PublicKeyToken")
|
|
public_key_token = value;
|
|
}
|
|
|
|
if (end == std::string::npos)
|
|
break;
|
|
}
|
|
|
|
if (culture == "neutral")
|
|
culture.clear();
|
|
}
|
|
|
|
std::string AssemblyName::value() const
|
|
{
|
|
std::string res = name;
|
|
res += ", Version=" + version;
|
|
res += ", Culture=" + (culture.empty() ? "neutral" : culture);
|
|
res += ", PublicKeyToken=" + (public_key_token.empty() ? "null" : public_key_token);
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* AssemblyResolver
|
|
*/
|
|
|
|
AssemblyResolver::AssemblyResolver()
|
|
: IObject()
|
|
{
|
|
#ifdef VMP_GNU
|
|
#else
|
|
win_dir_ = os::GetEnvironmentVariable("WINDIR");
|
|
|
|
std::string root = os::GetEnvironmentVariable("ProgramFiles");
|
|
if (!root.empty()) {
|
|
root = os::CombinePaths(root.c_str(), "dotnet");
|
|
if (os::FileExists(root.c_str())) {
|
|
root = os::CombinePaths(root.c_str(), "shared");
|
|
if (os::FileExists(root.c_str())) {
|
|
std::vector<std::string> root_list = os::FindFiles(root.c_str(), "*", true);
|
|
for (size_t i = 0; i < root_list.size(); i++) {
|
|
std::string path = os::CombinePaths(root.c_str(), root_list[i].c_str());
|
|
std::vector<std::string> path_list = os::FindFiles(path.c_str(), "*", true);
|
|
|
|
for (size_t j = 0; j < path_list.size(); j++) {
|
|
FrameworkVersion version;
|
|
if (!version.Parse(os::ExtractFileName(path_list[j].c_str())))
|
|
continue;
|
|
|
|
dotnet_dir_list_.push_back(FrameworkPathInfo(os::CombinePaths(os::CombinePaths(path.c_str(), path_list[j].c_str()).c_str(), ""), version));
|
|
}
|
|
}
|
|
|
|
std::sort(dotnet_dir_list_.begin(), dotnet_dir_list_.end(), [](const FrameworkPathInfo &left, const FrameworkPathInfo &right)
|
|
{
|
|
return (left.version < right.version);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
redirect_v2_map_["Accessibility"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["cscompmgd"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0");
|
|
redirect_v2_map_["CustomMarshalers"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["IEExecRemote"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["IEHost"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["IIEHost"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["ISymWrapper"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["Microsoft.JScript"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0");
|
|
redirect_v2_map_["Microsoft.VisualBasic"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0");
|
|
redirect_v2_map_["Microsoft.VisualBasic.Compatibility"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0");
|
|
redirect_v2_map_["Microsoft.VisualBasic.Compatibility.Data"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0");
|
|
redirect_v2_map_["Microsoft.VisualBasic.Vsa"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0");
|
|
redirect_v2_map_["Microsoft.VisualC"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0");
|
|
redirect_v2_map_["Microsoft.Vsa"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0");
|
|
redirect_v2_map_["Microsoft.Vsa.Vb.CodeDOMProcessor"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0");
|
|
redirect_v2_map_["Microsoft_VsaVb"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "8.0.0.0");
|
|
redirect_v2_map_["mscorcfg"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["mscorlib"] = FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0");
|
|
redirect_v2_map_["System"] = FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0");
|
|
redirect_v2_map_["System.Configuration"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Configuration.Install"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Data"] = FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0");
|
|
redirect_v2_map_["System.Data.OracleClient"] = FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0");
|
|
redirect_v2_map_["System.Data.SqlXml"] = FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0");
|
|
redirect_v2_map_["System.Deployment"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Design"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.DirectoryServices"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.DirectoryServices.Protocols"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Drawing"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Drawing.Design"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.EnterpriseServices"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Management"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Messaging"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Runtime.Remoting"] = FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0");
|
|
redirect_v2_map_["System.Runtime.Serialization.Formatters.Soap"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Security"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.ServiceProcess"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Transactions"] = FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0");
|
|
redirect_v2_map_["System.Web"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Web.Mobile"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Web.RegularExpressions"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Web.Services"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["System.Windows.Forms"] = FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0");
|
|
redirect_v2_map_["System.Xml"] = FrameworkRedirectInfo("b77a5c561934e089", "2.0.0.0");
|
|
redirect_v2_map_["vjscor"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["VJSharpCodeProvider"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["vjsJBC"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["vjslib"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["vjslibcw"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["Vjssupuilib"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["vjsvwaux"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["vjswfc"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["VJSWfcBrowserStubLib"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["vjswfccw"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v2_map_["vjswfchtml"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
|
|
redirect_v4_map_["Accessibility"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["CustomMarshalers"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["ISymWrapper"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.JScript"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0");
|
|
redirect_v4_map_["Microsoft.VisualBasic"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0");
|
|
redirect_v4_map_["Microsoft.VisualBasic.Compatibility"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0");
|
|
redirect_v4_map_["Microsoft.VisualBasic.Compatibility.Data"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0");
|
|
redirect_v4_map_["Microsoft.VisualC"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0");
|
|
redirect_v4_map_["mscorlib"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Configuration"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Configuration.Install"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Data"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Data.OracleClient"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Data.SqlXml"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Deployment"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Design"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.DirectoryServices"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.DirectoryServices.Protocols"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Drawing"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Drawing.Design"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.EnterpriseServices"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Management"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Messaging"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.Remoting"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.Serialization.Formatters.Soap"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Security"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceProcess"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Transactions"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Web"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.Mobile"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.RegularExpressions"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.Services"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Windows.Forms"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Xml"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["AspNetMMCExt"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["sysglobl"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Build.Engine"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Build.Framework"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["PresentationCFFRasterizer"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationCore"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework.Aero"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework.Classic"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework.Luna"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework.Royale"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationUI"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["ReachFramework"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Printing"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Speech"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["UIAutomationClient"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["UIAutomationClientsideProviders"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["UIAutomationProvider"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["UIAutomationTypes"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["WindowsBase"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["WindowsFormsIntegration"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["SMDiagnostics"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.IdentityModel"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.IdentityModel.Selectors"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.IO.Log"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.Serialization"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Install"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.WasHosting"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Workflow.Activities"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Workflow.ComponentModel"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Workflow.Runtime"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Transactions.Bridge"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Transactions.Bridge.Dtc"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.AddIn"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.AddIn.Contract"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ComponentModel.Composition"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Core"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Data.DataSetExtensions"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Data.Linq"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Xml.Linq"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.DirectoryServices.AccountManagement"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Management.Instrumentation"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Net"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Web"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.Extensions"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.Extensions.Design"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Windows.Presentation"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.WorkflowServices"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.ComponentModel.DataAnnotations"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Data.Entity"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Data.Entity.Design"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Data.Services"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Data.Services.Client"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Data.Services.Design"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.Abstractions"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.DynamicData"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.DynamicData.Design"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.Entity"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.Entity.Design"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.Routing"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Build"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.CSharp"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Dynamic"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Numerics"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Xaml"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Workflow.Compiler"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Activities.Build"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Build.Conversion.v4.0"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Build.Tasks.v4.0"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Build.Utilities.v4.0"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.Internal.Tasks.Dataflow"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["Microsoft.VisualBasic.Activities.Compiler"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "10.0.0.0");
|
|
redirect_v4_map_["Microsoft.VisualC.STLCLR"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "2.0.0.0");
|
|
redirect_v4_map_["Microsoft.Windows.ApplicationServer.Applications"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationBuildTasks"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework.Aero2"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework.AeroLite"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework-SystemCore"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework-SystemData"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework-SystemDrawing"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework-SystemXml"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["PresentationFramework-SystemXmlLinq"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Activities"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Activities.Core.Presentation"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Activities.DurableInstancing"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Activities.Presentation"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.ComponentModel.Composition.Registration"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Device"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.IdentityModel.Services"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.IO.Compression"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.IO.Compression.FileSystem"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Net.Http"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Net.Http.WebRequest"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Reflection.Context"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.Caching"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.DurableInstancing"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.WindowsRuntime"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.WindowsRuntime.UI.Xaml"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Activation"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Activities"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Channels"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Discovery"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Internals"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Routing"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.ServiceMoniker40"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.ApplicationServices"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.DataVisualization"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Web.DataVisualization.Design"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Windows.Controls.Ribbon"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Windows.Forms.DataVisualization"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Windows.Forms.DataVisualization.Design"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Windows.Input.Manipulations"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
redirect_v4_map_["System.Xaml.Hosting"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["XamlBuildTask"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["XsdBuildTask"] = FrameworkRedirectInfo("31bf3856ad364e35", "4.0.0.0");
|
|
redirect_v4_map_["System.Collections"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Collections.Concurrent"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ComponentModel"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ComponentModel.Annotations"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ComponentModel.EventBasedAsync"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Diagnostics.Contracts"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Diagnostics.Debug"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Diagnostics.Tools"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Diagnostics.Tracing"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Dynamic.Runtime"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Globalization"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.IO"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Linq"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Linq.Expressions"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Linq.Parallel"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Linq.Queryable"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Net.NetworkInformation"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Net.Primitives"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Net.Requests"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ObjectModel"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Reflection"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Reflection.Emit"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Reflection.Emit.ILGeneration"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Reflection.Emit.Lightweight"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Reflection.Extensions"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Reflection.Primitives"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Resources.ResourceManager"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.Extensions"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.InteropServices"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.InteropServices.WindowsRuntime"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.Numerics"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.Serialization.Json"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.Serialization.Primitives"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Runtime.Serialization.Xml"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Security.Principal"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Duplex"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Http"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.NetTcp"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Primitives"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.ServiceModel.Security"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Text.Encoding"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Text.Encoding.Extensions"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Text.RegularExpressions"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Threading"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Threading.Timer"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Threading.Tasks"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Threading.Tasks.Parallel"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Xml.ReaderWriter"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Xml.XDocument"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Xml.XmlSerializer"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Net.Http.Rtc"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Windows"] = FrameworkRedirectInfo("b03f5f7f11d50a3a", "4.0.0.0");
|
|
redirect_v4_map_["System.Xml.Serialization"] = FrameworkRedirectInfo("b77a5c561934e089", "4.0.0.0");
|
|
#endif
|
|
}
|
|
|
|
AssemblyResolver::~AssemblyResolver()
|
|
{
|
|
for (std::map<std::string, PEFile *>::const_iterator it = cache_.begin(); it != cache_.end(); it++) {
|
|
delete it->second;
|
|
}
|
|
}
|
|
|
|
void AssemblyResolver::Prepare()
|
|
{
|
|
framework_path_map_.clear();
|
|
for (std::map<std::string, PEFile *>::const_iterator it = cache_.begin(); it != cache_.end();) {
|
|
if (!it->second)
|
|
it = cache_.erase(it);
|
|
else
|
|
it++;
|
|
}
|
|
}
|
|
|
|
ILMetaData *AssemblyResolver::Resolve(const ILMetaData &source, const std::string &orig_name)
|
|
{
|
|
std::map<std::string, PEFile *>::const_iterator cache_it = cache_.find(orig_name);
|
|
if (cache_it != cache_.end())
|
|
return cache_it->second ? reinterpret_cast<NETArchitecture *>(cache_it->second->item(1))->command_list() : NULL;
|
|
|
|
std::string name = orig_name;
|
|
AssemblyName assembly(name);
|
|
|
|
if (assembly.culture.empty()) {
|
|
const std::map<std::string, FrameworkRedirectInfo, ci_less> *map;
|
|
FrameworkInfo info = source.framework();
|
|
if (info.type == fwFramework)
|
|
map = (info.version.major >= 4) ? &redirect_v4_map_ : &redirect_v2_map_;
|
|
else
|
|
map = NULL;
|
|
|
|
if (map) {
|
|
std::map<std::string, FrameworkRedirectInfo>::const_iterator redirect_it = map->find(assembly.name);
|
|
if (redirect_it != map->end() && assembly.public_key_token == redirect_it->second.public_key_token) {
|
|
assembly.version = redirect_it->second.version;
|
|
name = assembly.value();
|
|
|
|
// find redirected name
|
|
cache_it = cache_.find(name);
|
|
if (cache_it != cache_.end())
|
|
return cache_it->second ? reinterpret_cast<NETArchitecture *>(cache_it->second->item(1))->command_list() : NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> file_names = FindAssemblies(source, assembly);
|
|
PEFile *file = new PEFile();
|
|
for (size_t i = 0; i < file_names.size(); i++) {
|
|
try {
|
|
if (file->Open(file_names[i].c_str(), foRead | foHeaderOnly) == osSuccess) {
|
|
if (file->count() > 1) {
|
|
NETArchitecture *net = reinterpret_cast<NETArchitecture *>(file->item(1));
|
|
std::string loaded_name = net->full_name();
|
|
|
|
if (loaded_name != name) {
|
|
AssemblyName loaded(loaded_name);
|
|
if (_strcmpi(loaded.name.c_str(), assembly.name.c_str()) != 0)
|
|
continue;
|
|
|
|
if (loaded.version != assembly.version) {
|
|
FrameworkVersion loaded_version;
|
|
if (!loaded_version.Parse(loaded.version))
|
|
continue;
|
|
|
|
FrameworkVersion assembly_version;
|
|
if (!assembly_version.Parse(assembly.version))
|
|
continue;
|
|
|
|
if (loaded_version.major != assembly_version.major)
|
|
continue;
|
|
|
|
if (loaded_version.minor < assembly_version.minor)
|
|
continue;
|
|
}
|
|
|
|
if (loaded.culture != assembly.culture)
|
|
continue;
|
|
|
|
if (loaded.public_key_token != assembly.public_key_token)
|
|
continue;
|
|
}
|
|
|
|
cache_[name] = file;
|
|
return net->command_list();
|
|
}
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
|
|
}
|
|
file->Close();
|
|
}
|
|
delete file;
|
|
|
|
cache_[name] = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
std::vector<std::string> AssemblyResolver::FindAssemblies(const ILMetaData &source, const AssemblyName &assembly)
|
|
{
|
|
std::vector<std::string> res;
|
|
size_t i;
|
|
|
|
std::string full_dll_name = assembly.name + ".dll";
|
|
std::string source_path = os::ExtractFilePath(source.owner()->owner()->file_name().c_str());
|
|
FrameworkInfo framework = source.framework();
|
|
if (framework.type != fwUnknown) {
|
|
if (source.owner()->owner()->is_executable())
|
|
framework_path_map_[source_path] = framework;
|
|
}
|
|
if (framework.type == fwUnknown || framework.type == fwStandard) {
|
|
std::map<std::string, FrameworkInfo>::const_iterator it = framework_path_map_.find(source_path);
|
|
if (it != framework_path_map_.end())
|
|
framework = it->second;
|
|
}
|
|
|
|
std::string file_name = os::CombinePaths(source_path.c_str(), full_dll_name.c_str());
|
|
if (std::find(res.begin(), res.end(), file_name) == res.end()) {
|
|
if (os::FileExists(file_name.c_str()))
|
|
res.push_back(file_name);
|
|
}
|
|
|
|
switch (framework.type) {
|
|
case fwFramework:
|
|
case fwStandard:
|
|
if (!win_dir_.empty()) {
|
|
// search in GAC
|
|
std::string prefix, path;
|
|
std::vector<std::string> search_paths;
|
|
|
|
if (framework.type == fwStandard || framework.version.major >= 4) {
|
|
prefix = "v4.0_";
|
|
path = os::CombinePaths(os::CombinePaths(win_dir_.c_str(), "Microsoft.NET").c_str(), "assembly");
|
|
search_paths.push_back(os::CombinePaths(path.c_str(), "GAC_32"));
|
|
search_paths.push_back(os::CombinePaths(path.c_str(), "GAC_64"));
|
|
search_paths.push_back(os::CombinePaths(path.c_str(), "GAC_MSIL"));
|
|
} else {
|
|
prefix.clear();
|
|
path = os::CombinePaths(win_dir_.c_str(), "assembly");
|
|
search_paths.push_back(os::CombinePaths(path.c_str(), "GAC_32"));
|
|
search_paths.push_back(os::CombinePaths(path.c_str(), "GAC_64"));
|
|
search_paths.push_back(os::CombinePaths(path.c_str(), "GAC_MSIL"));
|
|
search_paths.push_back(os::CombinePaths(path.c_str(), "GAC"));
|
|
}
|
|
|
|
for (i = 0; i < search_paths.size(); i++) {
|
|
path = os::CombinePaths(os::CombinePaths(search_paths[i].c_str(), assembly.name.c_str()).c_str(), string_format("%s%s_%s_%s", prefix.c_str(), assembly.version.c_str(), assembly.culture.c_str(), assembly.public_key_token.c_str()).c_str());
|
|
std::string file_name = os::CombinePaths(path.c_str(), full_dll_name.c_str());
|
|
if (os::FileExists(file_name.c_str()))
|
|
res.push_back(file_name);
|
|
}
|
|
}
|
|
break;
|
|
case fwCore:
|
|
if (!dotnet_dir_list_.empty()) {
|
|
std::vector<std::string> search_paths;
|
|
std::map<uint32_t, std::vector<std::string> > minor_list;
|
|
for (i = dotnet_dir_list_.size(); i > 0; i--) {
|
|
FrameworkPathInfo info = dotnet_dir_list_[i - 1];
|
|
if (framework.version.major) {
|
|
if (info.version.major != framework.version.major)
|
|
continue;
|
|
|
|
// select best minor version
|
|
uint32_t d;
|
|
if (info.version.minor >= framework.version.minor)
|
|
d = info.version.minor - framework.version.minor;
|
|
else
|
|
d = 0x80000000 + framework.version.minor - info.version.minor - 1;
|
|
|
|
std::map<uint32_t, std::vector<std::string> >::iterator it = minor_list.find(d);
|
|
if (it == minor_list.end()) {
|
|
std::vector<std::string> list;
|
|
list.push_back(info.path);
|
|
minor_list[d] = list;
|
|
}
|
|
else
|
|
it->second.push_back(info.path);
|
|
} else
|
|
search_paths.push_back(info.path);
|
|
}
|
|
|
|
if (!minor_list.empty()) {
|
|
std::map<uint32_t, std::vector<std::string> >::const_iterator it = minor_list.begin();
|
|
for (i = 0; i < it->second.size(); i++) {
|
|
search_paths.push_back(it->second[i]);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < search_paths.size(); i++) {
|
|
std::string path = search_paths[i];
|
|
std::string file_name = os::CombinePaths(path.c_str(), full_dll_name.c_str());
|
|
if (os::FileExists(file_name.c_str()))
|
|
res.push_back(file_name);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
} |