|
|
|
@ -8,35 +8,103 @@ comp_t::comp_t(decomp::decomp_t* dcmp,
|
|
|
|
|
resolver_t resolve)
|
|
|
|
|
: m_dcmp(dcmp), m_allocator(alloc), m_copier(copy), m_resolver(resolve) {}
|
|
|
|
|
|
|
|
|
|
void comp_t::compose() {
|
|
|
|
|
void comp_t::allocate() {
|
|
|
|
|
// map code & data/rdata/bss sections first...
|
|
|
|
|
//
|
|
|
|
|
m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) {
|
|
|
|
|
// if this symbol is a function..
|
|
|
|
|
switch (sym.sym_type()) {
|
|
|
|
|
case decomp::sym_type_t::section:
|
|
|
|
|
case decomp::sym_type_t::function: {
|
|
|
|
|
sym.allocated_at(m_allocator(sym.size(), sym.scn()->characteristics));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case decomp::sym_type_t::inst_split: {
|
|
|
|
|
// TODO: call into reloc_t static methods to generate random code to
|
|
|
|
|
// obfuscate relocations...
|
|
|
|
|
//
|
|
|
|
|
if (sym.scn()->characteristics.mem_execute) {
|
|
|
|
|
// if comp type is none (meaning entire function) then we just allocate
|
|
|
|
|
// it...
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// then map data/rdata/bss symbols to the allocated sections...
|
|
|
|
|
//
|
|
|
|
|
if (sym.dcmp_type() == decomp::decomp_type_t::none) {
|
|
|
|
|
sym.allocated_at(m_allocator(sym.size(), sym.scn()->characteristics));
|
|
|
|
|
spdlog::info("allocated entire function: {} at address: {:X} size: {}",
|
|
|
|
|
sym.name(), sym.allocated_at(), sym.size());
|
|
|
|
|
} else { // else the dcmp_type is split instrs we are going to apply
|
|
|
|
|
// transformations...
|
|
|
|
|
m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) {
|
|
|
|
|
if (sym.sym_type() == decomp::sym_type_t::data) {
|
|
|
|
|
auto scn_sym =
|
|
|
|
|
m_dcmp->syms()->sym_from_hash(m_dcmp->scn_hash_tbl()[sym.scn()]);
|
|
|
|
|
|
|
|
|
|
sym.allocated_at(m_allocator(sym.size(), sym.scn()->characteristics));
|
|
|
|
|
if (!scn_sym.has_value()) {
|
|
|
|
|
spdlog::error("failed to locate section: {} for symbol: {}",
|
|
|
|
|
sym.scn()->name.to_string(), sym.name());
|
|
|
|
|
|
|
|
|
|
spdlog::info(
|
|
|
|
|
"transformed relocations of symbol: {} size is now: {} allocated "
|
|
|
|
|
"at: {:X}",
|
|
|
|
|
sym.name(), sym.size(), sym.allocated_at());
|
|
|
|
|
assert(scn_sym.has_value());
|
|
|
|
|
}
|
|
|
|
|
} else { // else the allocation is data which means we dont have any
|
|
|
|
|
// relocs...
|
|
|
|
|
sym.allocated_at(m_allocator(sym.size(), sym.scn()->characteristics));
|
|
|
|
|
|
|
|
|
|
sym.allocated_at(scn_sym.value().allocated_at() + sym.offset());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void comp_t::resolve() {
|
|
|
|
|
// resolve relocations in all symbols...
|
|
|
|
|
//
|
|
|
|
|
m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) {
|
|
|
|
|
std::for_each(sym.relocs().begin(), sym.relocs().end(), [&](reloc_t reloc) {
|
|
|
|
|
if (reloc.offset() > sym.data().size()) {
|
|
|
|
|
spdlog::error(
|
|
|
|
|
"invalid relocation... writing outside of symbol length... offset: "
|
|
|
|
|
"{} sym size: {}",
|
|
|
|
|
sym.offset(), sym.data().size());
|
|
|
|
|
|
|
|
|
|
assert(reloc.offset() > sym.data().size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// try and resolve the symbol by refering to the internal symbol table
|
|
|
|
|
// first... if there is no symbol then refer to the resolver...
|
|
|
|
|
//
|
|
|
|
|
auto reloc_sym = m_dcmp->syms()->sym_from_hash(reloc.hash());
|
|
|
|
|
auto allocated_at = reloc_sym.has_value()
|
|
|
|
|
? reloc_sym.value().allocated_at()
|
|
|
|
|
: m_resolver(reloc.name());
|
|
|
|
|
|
|
|
|
|
if (!allocated_at) {
|
|
|
|
|
spdlog::error("failed to resolve reloc from symbol: {} to symbol: {}",
|
|
|
|
|
sym.name(), reloc.name());
|
|
|
|
|
|
|
|
|
|
assert(allocated_at);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (sym.sym_type()) {
|
|
|
|
|
case decomp::sym_type_t::function: {
|
|
|
|
|
*reinterpret_cast<std::uintptr_t*>(sym.data().data() +
|
|
|
|
|
reloc.offset()) = allocated_at;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case decomp::sym_type_t::inst_split: {
|
|
|
|
|
// TODO: run the vector of transformation operations here if the
|
|
|
|
|
// symbol is of type inst_split... the transformations will be applied
|
|
|
|
|
// to allocate_at() result on the symbol...
|
|
|
|
|
//
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void comp_t::copy_syms() {
|
|
|
|
|
// copy symbols into memory using the copier supplied...
|
|
|
|
|
//
|
|
|
|
|
m_dcmp->syms()->for_each([&](theo::decomp::symbol_t& sym) {
|
|
|
|
|
m_copier(sym.allocated_at(), sym.data().data(), sym.data().size());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void comp_t::allocator(allocator_t alloc) {
|
|
|
|
|
m_allocator = alloc;
|
|
|
|
|
}
|
|
|
|
@ -50,8 +118,7 @@ void comp_t::resolver(resolver_t resolve) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::uintptr_t comp_t::resolve(const std::string&& sym) {
|
|
|
|
|
return m_dcmp->syms()
|
|
|
|
|
->sym_from_hash(decomp::symbol_t::hash(sym))
|
|
|
|
|
.allocated_at();
|
|
|
|
|
auto res = m_dcmp->syms()->sym_from_hash(decomp::symbol_t::hash(sym));
|
|
|
|
|
return res.has_value() ? res->allocated_at() : 0;
|
|
|
|
|
}
|
|
|
|
|
} // namespace theo::comp
|