|
|
@ -34,19 +34,16 @@ namespace theo::decomp {
|
|
|
|
routine_t::routine_t(coff::symbol_t* sym,
|
|
|
|
routine_t::routine_t(coff::symbol_t* sym,
|
|
|
|
coff::image_t* img,
|
|
|
|
coff::image_t* img,
|
|
|
|
coff::section_header_t* scn,
|
|
|
|
coff::section_header_t* scn,
|
|
|
|
std::vector<std::uint8_t>& fn,
|
|
|
|
std::vector<std::uint8_t>& fn)
|
|
|
|
sym_type_t dcmp_type)
|
|
|
|
: m_img(img), m_scn(scn), m_data(fn), m_sym(sym) {}
|
|
|
|
: m_img(img), m_scn(scn), m_data(fn), m_dcmp_type(dcmp_type), m_sym(sym) {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<decomp::symbol_t> routine_t::decompose() {
|
|
|
|
decomp::symbol_t routine_t::decompose() {
|
|
|
|
std::vector<decomp::symbol_t> result;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (m_dcmp_type) {
|
|
|
|
|
|
|
|
case function: {
|
|
|
|
|
|
|
|
std::vector<recomp::reloc_t> relocs;
|
|
|
|
std::vector<recomp::reloc_t> relocs;
|
|
|
|
auto scn_relocs = reinterpret_cast<coff::reloc_t*>(
|
|
|
|
auto scn_relocs = reinterpret_cast<coff::reloc_t*>(
|
|
|
|
m_scn->ptr_relocs + reinterpret_cast<std::uint8_t*>(m_img));
|
|
|
|
m_scn->ptr_relocs + reinterpret_cast<std::uint8_t*>(m_img));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// extract all of the relocations that this function has...
|
|
|
|
|
|
|
|
//
|
|
|
|
for (auto idx = 0u; idx < m_scn->num_relocs; ++idx) {
|
|
|
|
for (auto idx = 0u; idx < m_scn->num_relocs; ++idx) {
|
|
|
|
auto scn_reloc = &scn_relocs[idx];
|
|
|
|
auto scn_reloc = &scn_relocs[idx];
|
|
|
|
// if the reloc is in the current function...
|
|
|
|
// if the reloc is in the current function...
|
|
|
@ -56,113 +53,16 @@ std::vector<decomp::symbol_t> routine_t::decompose() {
|
|
|
|
auto sym_name = symbol_t::name(m_img, sym_reloc);
|
|
|
|
auto sym_name = symbol_t::name(m_img, sym_reloc);
|
|
|
|
auto sym_hash = decomp::symbol_t::hash(sym_name.data());
|
|
|
|
auto sym_hash = decomp::symbol_t::hash(sym_name.data());
|
|
|
|
relocs.push_back(
|
|
|
|
relocs.push_back(
|
|
|
|
recomp::reloc_t(scn_reloc->virtual_address - m_sym->value,
|
|
|
|
recomp::reloc_t(scn_reloc->virtual_address - m_sym->value, sym_hash,
|
|
|
|
sym_hash, sym_name.data()));
|
|
|
|
sym_name.data()));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.push_back(decomp::symbol_t(
|
|
|
|
|
|
|
|
m_img, symbol_t::name(m_img, m_sym).data(), m_sym->value, m_data,
|
|
|
|
|
|
|
|
m_scn, m_sym, relocs, sym_type_t::function));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case instruction: {
|
|
|
|
|
|
|
|
std::uint32_t offset = {};
|
|
|
|
|
|
|
|
xed_error_enum_t err;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
xed_decoded_inst_t instr;
|
|
|
|
|
|
|
|
xed_state_t istate{XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b};
|
|
|
|
|
|
|
|
xed_decoded_inst_zero_set_mode(&instr, &istate);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// keep looping over the section, lower the number of bytes each time...
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
while ((err = xed_decode(&instr, m_data.data() + offset,
|
|
|
|
|
|
|
|
m_data.size() - offset)) == XED_ERROR_NONE) {
|
|
|
|
|
|
|
|
// symbol name is of the format: symbol@instroffset, I.E: main@11...
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
auto new_sym_name = symbol_t::name(m_img, m_sym);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// first instruction doesnt need the @offset...
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
if (offset)
|
|
|
|
|
|
|
|
new_sym_name.append("@").append(std::to_string(offset));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<recomp::reloc_t> relocs;
|
|
|
|
|
|
|
|
auto scn_relocs = reinterpret_cast<coff::reloc_t*>(
|
|
|
|
|
|
|
|
m_scn->ptr_relocs + reinterpret_cast<std::uint8_t*>(m_img));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// find if this instruction has a relocation or not...
|
|
|
|
|
|
|
|
// if so, return the reloc_t...
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
auto reloc = std::find_if(
|
|
|
|
|
|
|
|
scn_relocs, scn_relocs + m_scn->num_relocs,
|
|
|
|
|
|
|
|
[&](coff::reloc_t reloc) {
|
|
|
|
|
|
|
|
return reloc.virtual_address >= m_sym->value + offset &&
|
|
|
|
|
|
|
|
reloc.virtual_address <
|
|
|
|
|
|
|
|
m_sym->value + offset +
|
|
|
|
|
|
|
|
xed_decoded_inst_get_length(&instr);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if there is indeed a reloc for this instruction...
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
if (reloc != scn_relocs + m_scn->num_relocs) {
|
|
|
|
|
|
|
|
auto sym_reloc = m_img->get_symbol(reloc->symbol_index);
|
|
|
|
|
|
|
|
auto sym_name = symbol_t::name(m_img, sym_reloc);
|
|
|
|
|
|
|
|
auto sym_hash = decomp::symbol_t::hash(sym_name.data());
|
|
|
|
|
|
|
|
auto reloc_offset = reloc->virtual_address - m_sym->value - offset;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
relocs.push_back(
|
|
|
|
|
|
|
|
recomp::reloc_t(reloc_offset, sym_hash, sym_name.data()));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// add a reloc to the next instruction...
|
|
|
|
|
|
|
|
// note that the offset is ZERO... comp_t will understand that
|
|
|
|
|
|
|
|
// relocs with offset ZERO means the next instructions...
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
auto next_inst_sym =
|
|
|
|
|
|
|
|
symbol_t::name(m_img, m_sym)
|
|
|
|
|
|
|
|
.append("@")
|
|
|
|
|
|
|
|
.append(std::to_string(offset +
|
|
|
|
|
|
|
|
xed_decoded_inst_get_length(&instr)));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
relocs.push_back(recomp::reloc_t(
|
|
|
|
|
|
|
|
0, decomp::symbol_t::hash(next_inst_sym), next_inst_sym.data()));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// get the instructions bytes
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
std::vector<std::uint8_t> inst_bytes(
|
|
|
|
|
|
|
|
m_data.data() + offset,
|
|
|
|
|
|
|
|
m_data.data() + offset + xed_decoded_inst_get_length(&instr));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.push_back(decomp::symbol_t(m_img, new_sym_name, offset,
|
|
|
|
|
|
|
|
inst_bytes, m_scn, m_sym, relocs,
|
|
|
|
|
|
|
|
sym_type_t::instruction));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// after creating the symbol and dealing with relocs then print the
|
|
|
|
|
|
|
|
// information we have concluded...
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
char buff[255];
|
|
|
|
|
|
|
|
offset += xed_decoded_inst_get_length(&instr);
|
|
|
|
|
|
|
|
xed_format_context(XED_SYNTAX_INTEL, &instr, buff, sizeof buff, NULL,
|
|
|
|
|
|
|
|
NULL, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spdlog::info("{}: {}", new_sym_name, buff);
|
|
|
|
|
|
|
|
// need to set this so that instr can be used to decode again...
|
|
|
|
|
|
|
|
xed_decoded_inst_zero_set_mode(&instr, &istate);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// remove the relocation to the next symbol from the last instruction
|
|
|
|
// return the created symbol_t for this function...
|
|
|
|
//
|
|
|
|
//
|
|
|
|
auto& last_inst = result.back();
|
|
|
|
return decomp::symbol_t(m_img, symbol_t::name(m_img, m_sym).data(),
|
|
|
|
auto& last_inst_relocs = last_inst.relocs();
|
|
|
|
m_sym->value, m_data, m_scn, m_sym, relocs,
|
|
|
|
last_inst_relocs.erase(last_inst_relocs.end() - 1);
|
|
|
|
sym_type_t::function);
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
coff::section_header_t* routine_t::scn() {
|
|
|
|
coff::section_header_t* routine_t::scn() {
|
|
|
|