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

MOS65xx: Include mos65xx.h (WIP) #4

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions capstonebundle/plugin/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@

#include "arm/common.h"
#include "arm/arm.h"

#include "mos65xx/mos65xx.h"
35 changes: 35 additions & 0 deletions capstonebundle/plugin/mos65xx/mos65xx.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// mos65xx.cpp
#include "mos65xx.h"

MOS65XX::MOS65XX(RDContext* ctx, cs_mode mode): Capstone(ctx, CS_ARCH_MOS65XX, mode) { }

void MOS65XX::emulate(RDEmulateResult* result)
{
rd_address address = RDEmulateResult_GetAddress(result);
auto* insn = this->decode(address, RDEmulateResult_GetView(result));
if(!insn) return;

// Instruction is decoded, you can use Capstone API to analyze it

RDContext_SetAddressAssembler(m_context, address, this->endianness() == Endianness_Big ? MOS65XXBE_ID : MOS65XXLE_ID);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used only in ARM, afaik is not neeed for MOS65XX, because it provides a single instruction set.

Tell REDasm to increase the view to the next possible instruction by calling

RDEmulateResult_SetSize(result, insn->size); // Next time "emulate" is called is after insn->size bytes

After that you need to classify instructions in order to have a detailed listing (more case you handle and more detailed will become), see here (it just a big switch case statement): https://github.com/REDasmOrg/REDasm-Assemblers/blob/db0d698029d6776f4b9f3612498439621b473987/capstonebundle/plugin/arm32/common.cpp

The easiest way is to begin to catch return, call and jump statement

if(!this->decode(address, RDEmulateResult_GetView(result))) return;

RDEmulateResult_SetSize(result, m_insn->size);

}

void MOS65XX::render(const RDRendererParams* rp)
{
// You can render instructions here
auto* insn = this->decode(rp->address, &rp->view);
Copy link
Member

@Dax89 Dax89 Oct 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to show the instruction's mnemonic with RDRenderer_MnemonicWord API:

Like here:

RDRenderer_MnemonicWord(rp->renderer, insn->mnemonic, ARM32Common::mnemonicTheme(insn));


}

void MOS65XX::lift(const Capstone* capstone, rd_address address, const RDBufferView* view, RDILFunction* il) { MOS65XXLifter::lift(capstone, address, view, il); }


//ARMLE::ARMLE(RDContext* ctx): ARM(ctx, CS_MODE_LITTLE_ENDIAN) { }
//ARMBE::ARMBE(RDContext* ctx): ARM(ctx, CS_MODE_BIG_ENDIAN) { }

MOS65XXLE::MOS65XXLE(RDContext* ctx): MOS65XX(ctx, CS_MODE_LITTLE_ENDIAN) { }
MOS65XXBE::MOS65XXBE(RDContext* ctx): MOS65XX(ctx, CS_MODE_BIG_ENDIAN) { }
36 changes: 36 additions & 0 deletions capstonebundle/plugin/mos65xx/mos65xx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// mos65xx.h
#pragma once

#define MOS65XXLE_USERDATA "mos65xxle_userdata"
#define MOS65XXBE_USERDATA "mos65xxbe_userdata"

#define MOS65XXLE_ID "mos65xxle"
#define MOS65XXBE_ID "mos65xxbe"

#include <rdapi/rdapi.h>
#include <utility>
#include "../capstone.h"

class MOS65XX: public Capstone {
public:
// Capstone(RDContext* ctx); // There is also a "cs_mode" argument, I don't know if this architecture needs it
MOS65XX(RDContext* ctx, cs_mode mode);
void emulate(RDEmulateResult* result) override; // This implements the algorithm (jumps, calls etc)
void render(const RDRendererParams* rp) override; // This renders instructions visually
void lift(const Capstone* capstone, rd_address address, const RDBufferView* view, RDILFunction* il) override;
};


class MOS65XXLifter
{
public:
MOS65XXLifter() = delete;
static void lift(const Capstone* capstone, rd_address address, const RDBufferView* view, RDILFunction* il);

private:
static RDILExpression* liftOperand(const Capstone* capstone, rd_address address, const cs_insn* insn, size_t idx, const RDILFunction* il);
};


class MOS65XXLE: public MOS65XX { public: MOS65XXLE(RDContext* ctx); };
class MOS65XXBE: public MOS65XX { public: MOS65XXBE(RDContext* ctx); };
26 changes: 26 additions & 0 deletions capstonebundle/plugin/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ static void initUserData()
CS_ITEMS[hashArch(CS_ARCH_ARM64, CS_MODE_BIG_ENDIAN)] = { ARM64BE_USERDATA, [](RDContext* ctx) { return new ARM64BE(ctx); } };
CS_ITEMS[hashArch(CS_ARCH_ARM, CS_MODE_LITTLE_ENDIAN)] = { ARM32LE_USERDATA, [](RDContext* ctx) { return new ARM32LE(ctx); } };
CS_ITEMS[hashArch(CS_ARCH_ARM, CS_MODE_BIG_ENDIAN)] = { ARM32BE_USERDATA, [](RDContext* ctx) { return new ARM32BE(ctx); } };

// Editing
CS_ITEMS[hashArch(CS_ARCH_MOS65XX, CS_MODE_LITTLE_ENDIAN)] = { MOS65XXLE_USERDATA, [](RDContext* ctx) { return new MOS65XXLE(ctx); } };
CS_ITEMS[hashArch(CS_ARCH_MOS65XX, CS_MODE_BIG_ENDIAN)] = { MOS65XXBE_USERDATA, [](RDContext* ctx) { return new MOS65XXBE(ctx); } };
// End Editing

CS_ITEMS[hashArch(CS_ARCH_ARM, CS_MODE_THUMB | CS_MODE_LITTLE_ENDIAN)] = { THUMB32LE_USERDATA, [](RDContext* ctx) { return new ThumbLE(ctx); } };
CS_ITEMS[hashArch(CS_ARCH_ARM, CS_MODE_THUMB | CS_MODE_BIG_ENDIAN)] = { THUMB32BE_USERDATA, [](RDContext* ctx) { return new ThumbBE(ctx); } };
}
Expand Down Expand Up @@ -110,6 +116,26 @@ void rdplugin_init(RDContext*, RDPluginModule* pm)
arm32be.bits = 32;
RDAssembler_Register(pm, &arm32be);

// Editing

RD_PLUGIN_ENTRY(RDEntryAssembler, mos65xxbe, "MOS65xxx (Big Endian)");
mos65xxbe.emulate = &emulate<CS_ARCH_MOS65XX, CS_MODE_BIG_ENDIAN>;
mos65xxbe.renderinstruction = &render<CS_ARCH_MOS65XX, CS_MODE_BIG_ENDIAN>;
mos65xxbe.lift = &lift<CS_ARCH_MOS65XX, CS_MODE_BIG_ENDIAN>;
mos65xxbe.bits = 8;
RDAssembler_Register(pm, &mos65xxbe);


RD_PLUGIN_ENTRY(RDEntryAssembler, mos65xxle, "MOS65xxx (Little Endian)");
mos65xxle.emulate = &emulate<CS_ARCH_MOS65XX, CS_MODE_LITTLE_ENDIAN>;
mos65xxle.renderinstruction = &render<CS_ARCH_MOS65XX, CS_MODE_LITTLE_ENDIAN>;
mos65xxle.lift = &lift<CS_ARCH_MOS65XX, CS_MODE_LITTLE_ENDIAN>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove the lifter part, is not mandatory

mos65xxle.bits = 8;
RDAssembler_Register(pm, &mos65xxle);


// Editing Ended

RD_PLUGIN_ENTRY(RDEntryAssembler, thumble, "THUMB (Little Endian)");
thumble.emulate = &emulate<CS_ARCH_ARM, CS_MODE_THUMB | CS_MODE_LITTLE_ENDIAN>;
thumble.renderinstruction = &render<CS_ARCH_ARM, CS_MODE_THUMB | CS_MODE_LITTLE_ENDIAN>;
Expand Down