Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ppc64 support #181

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ cmake-build-*/
prefix/
CMakeLists.txt.user
CMakeUserPresets.json
maat_state_*
maat_state_*
17 changes: 17 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ include(cmake/variables.cmake)

add_library(maat_maat
src/arch/arch_EVM.cpp
src/arch/arch_PPC64.cpp
src/arch/arch_X86.cpp
src/arch/lifter.cpp
src/arch/register_aliases.cpp
Expand Down Expand Up @@ -180,15 +181,31 @@ macro(maat_sleigh_compile ARCH_DIR ARCH)
configure_file("${spec_dir}/${ARCH_DIR}/data/languages/${ARCH}.pspec" "${spec_out_dir}/${ARCH}.pspec")
endmacro()

macro(maat_sleigh_compile_files ARCH_DIR ARCH SLASPEC PSPEC)
# ARCH_DIR is the directory that appears in Ghidra's source code hierarchy
# ARCH appears in the name of the '.slaspec' and '.pspec' file (they should be the same)
# Creates a target maat_sleigh_spec_${ARCH}
sleigh_compile(
TARGET maat_sleigh_spec_${ARCH}
COMPILER "${maat_SLEIGH_COMPILER}"
SLASPEC "${spec_dir}/${ARCH_DIR}/data/languages/${SLASPEC}.slaspec"
LOG_FILE "${PROJECT_BINARY_DIR}/sleigh-log/${ARCH}.log"
OUT_FILE "${spec_out_dir}/${SLASPEC}.sla"
)
configure_file("${spec_dir}/${ARCH_DIR}/data/languages/${PSPEC}.pspec" "${spec_out_dir}/${PSPEC}.pspec")
endmacro()

maat_sleigh_compile(x86 x86-64)
maat_sleigh_compile(x86 x86)
maat_sleigh_compile(EVM EVM)
maat_sleigh_compile_files(PowerPC PowerPC ppc_64_isa_be ppc_64)

# All of the sla spec targets are combined into this one
add_custom_target(maat_all_sla_specs DEPENDS
maat_sleigh_spec_x86-64
maat_sleigh_spec_x86
maat_sleigh_spec_EVM
maat_sleigh_spec_PowerPC
)

# Add sla specs as dependencies to our targets
Expand Down
1 change: 1 addition & 0 deletions bindings/python/py_arch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ void init_arch(PyObject* module)
PyDict_SetItemString(arch_enum, "X86", PyLong_FromLong((int)Arch::Type::X86));
PyDict_SetItemString(arch_enum, "X64", PyLong_FromLong((int)Arch::Type::X64));
PyDict_SetItemString(arch_enum, "EVM", PyLong_FromLong((int)Arch::Type::EVM));
PyDict_SetItemString(arch_enum, "PPC64", PyLong_FromLong((int)Arch::Type::PPC64));

PyObject* arch_class = create_class(PyUnicode_FromString("ARCH"), PyTuple_New(0), arch_enum);
PyModule_AddObject(module, "ARCH", arch_class);
Expand Down
229 changes: 229 additions & 0 deletions src/arch/arch_PPC64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
Commonwealth of Australia represented by the Department of Defence

Produced by Nathan Do, Student Intern at DSTG (Defence Science and Technology Group)
*/

#include "maat/arch.hpp"
#include "maat/exception.hpp"
#include "maat/cpu.hpp"

namespace maat
{

namespace PPC64
{
ArchPPC64::ArchPPC64(): Arch(Arch::Type::PPC64, 64, PPC64::NB_REGS)
{
available_modes = {CPUMode::PPC64};
reg_map =
{
{"r0", R0},
{"r1", R1},
{"r2", R2},
{"r3", R3},
{"r4", R4},
{"r5", R5},
{"r6", R6},
{"r7", R7},
{"r8", R8},
{"r9", R9},
{"r10", R10},
{"r11", R11},
{"r12", R12},
{"r13", R13},
{"r14", R14},
{"r15", R15},
{"r16", R16},
{"r17", R17},
{"r18", R18},
{"r19", R19},
{"r20", R20},
{"r21", R21},
{"r22", R22},
{"r23", R23},
{"r24", R24},
{"r25", R25},
{"r26", R26},
{"r27", R27},
{"r28", R28},
{"r29", R29},
{"r30", R30},
{"r31", R31},
{"f0", F0},
{"f1", F1},
{"f2", F2},
{"f3", F3},
{"f4", F4},
{"f5", F5},
{"f6", F6},
{"f7", F7},
{"f8", F8},
{"f9", F9},
{"f10", F10},
{"f11", F11},
{"f12", F12},
{"f13", F13},
{"f14", F14},
{"f15", F15},
{"f16", F16},
{"f17", F17},
{"f18", F18},
{"f19", F19},
{"f20", F20},
{"f21", F21},
{"f22", F22},
{"f23", F23},
{"f24", F24},
{"f25", F25},
{"f26", F26},
{"f27", F27},
{"f28", F28},
{"f29", F29},
{"f30", F30},
{"f31", F31},
{"pc", PC},
{"sp", SP},
{"cr", CR},
{"lr", LR},
{"ctr", CTR},
{"xer", XER},
{"cr0", CR0},
{"cr1", CR1},
{"cr2", CR2},
{"cr3", CR3},
{"cr4", CR4},
{"cr5", CR5},
{"cr6", CR6},
{"cr7", CR7},
{"xer_so", XER_SO},
{"xer_ov", XER_OV},
{"xer_ca", XER_CA},
{"tbl", TBL},
{"tbu", TBU},
{"fpscr", FPSCR},
{"msr", MSR},
{"pvr", PVR},
{"r2save", R2SAVE},
{"reserve", RESERVE}
};
}

size_t ArchPPC64::reg_size(reg_t reg_num) const
{
switch (reg_num)
{
case R0:
case R1:
case R2:
case R3:
case R4:
case R5:
case R6:
case R7:
case R8:
case R9:
case R10:
case R11:
case R12:
case R13:
case R14:
case R15:
case R16:
case R17:
case R18:
case R19:
case R20:
case R21:
case R22:
case R23:
case R24:
case R25:
case R26:
case R27:
case R28:
case R29:
case R30:
case R31:
case F0:
case F1:
case F2:
case F3:
case F4:
case F5:
case F6:
case F7:
case F8:
case F9:
case F10:
case F11:
case F12:
case F13:
case F14:
case F15:
case F16:
case F17:
case F18:
case F19:
case F20:
case F21:
case F22:
case F23:
case F24:
case F25:
case F26:
case F27:
case F28:
case F29:
case F30:
case F31:
return 64;
case CR:
case XER:
return 32;
case PC:
case LR:
case MSR:
case CTR:
case R2SAVE:
return 64;
case CR0:
case CR1:
case CR2:
case CR3:
case CR4:
case CR5:
case CR6:
case CR7:
case XER_SO:
case XER_OV:
case XER_CA:
return 8;
case TBL:
case TBU:
case FPSCR:
case PVR:
case RESERVE:
return 32;
default:
throw runtime_exception("ArchPPC64::reg_size(): got unsupported reg_num");
}
}

reg_t ArchPPC64::sp() const
{
return PPC64::R1;
}

reg_t ArchPPC64::pc() const
{
return PPC64::PC;
}

reg_t ArchPPC64::tsc() const
{
throw runtime_exception("ArchPPC64::tsc(): method not available");
}

} // namespace PPC64
} // namespace maat
6 changes: 6 additions & 0 deletions src/arch/lifter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ Lifter::Lifter(CPUMode m): mode(m)
pspecfile = config.find_sleigh_file("EVM.pspec");
arch = Arch::Type::EVM;
}
else if (mode == CPUMode::PPC64)
{
slafile = config.find_sleigh_file("ppc_64_isa_be.sla");
pspecfile = config.find_sleigh_file("ppc_64.pspec");
arch = Arch::Type::PPC64;
}
else
{
throw lifter_exception("Lifter: this CPU mode is not supported");
Expand Down
61 changes: 60 additions & 1 deletion src/arch/register_aliases.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,59 @@ Value x64_alias_getter(CPUContext& ctx, ir::reg_t reg)

std::set x64_aliases{X64::RFLAGS};

void PPC64_alias_setter(CPUContext& ctx, ir::reg_t reg, const Value& val)
{
if (reg == PPC64::CR)
{
_set_flag_from_bit(ctx, PPC64::CR7, val, 0, 4);
_set_flag_from_bit(ctx, PPC64::CR6, val, 4, 4);
_set_flag_from_bit(ctx, PPC64::CR5, val, 8, 4);
_set_flag_from_bit(ctx, PPC64::CR4, val, 12, 4);
_set_flag_from_bit(ctx, PPC64::CR3, val, 16, 4);
_set_flag_from_bit(ctx, PPC64::CR2, val, 20, 4);
_set_flag_from_bit(ctx, PPC64::CR1, val, 24, 4);
_set_flag_from_bit(ctx, PPC64::CR0, val, 28, 4);
}
else if (reg == PPC64::XER)
{
_set_flag_from_bit(ctx, PPC64::XER_SO, val, 31);
_set_flag_from_bit(ctx, PPC64::XER_OV, val, 30);
_set_flag_from_bit(ctx, PPC64::XER_CA, val, 29);
}
else
throw runtime_exception("PPC64_alias_setter: got unsupported register");
}

Value PPC64_alias_getter(CPUContext& ctx, ir::reg_t reg)
{
Value res;

if (reg == PPC64::CR)
{
res = extract(ctx.get(PPC64::CR7),3,0);
res.set_concat(extract(ctx.get(PPC64::CR6),3,0), res);
res.set_concat(extract(ctx.get(PPC64::CR5),3,0), res);
res.set_concat(extract(ctx.get(PPC64::CR4),3,0), res);
res.set_concat(extract(ctx.get(PPC64::CR3),3,0), res);
res.set_concat(extract(ctx.get(PPC64::CR2),3,0), res);
res.set_concat(extract(ctx.get(PPC64::CR1),3,0), res);
res.set_concat(extract(ctx.get(PPC64::CR0),3,0), res);
}
else if (reg == PPC64::XER)
{
res = extract(Value(28, 0), 28, 0);
res.set_concat(extract(ctx.get(PPC64::XER_CA),0,0), res);
res.set_concat(extract(ctx.get(PPC64::XER_OV),0,0), res);
res.set_concat(extract(ctx.get(PPC64::XER_SO),0,0), res);
}
else
throw runtime_exception("PPC64_alias_getter: got unsupported register");

return res;
}

std::set PPC64_aliases{PPC64::CR,PPC64::XER};

void CPUContext::init_alias_getset(Arch::Type arch)
{
if (arch == Arch::Type::X86)
Expand All @@ -150,7 +203,13 @@ void CPUContext::init_alias_getset(Arch::Type arch)
alias_getter = x64_alias_getter;
aliased_regs = x64_aliases;
}
else if (arch == Arch::Type::PPC64)
{
alias_setter = PPC64_alias_setter;
alias_getter = PPC64_alias_getter;
aliased_regs = PPC64_aliases;
}
}

} // namespace ir
} // namespace maat
} // namespace maat
Loading