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

Conversation

paulmcquad
Copy link

Starting to build a plugin around Capstone

Signed-off-by: Paul McQuade [email protected]

Starting to build a plugin around Capstone

Signed-off-by: Paul McQuade <[email protected]>
@paulmcquad paulmcquad marked this pull request as ready for review October 18, 2022 18:35
Step 1 - Attempt to build plugin

Signed-off-by: Paul McQuade <[email protected]>
Started structure of Plugin

Signed-off-by: Paul McQuade <[email protected]>
CS_ARCH_MOS65XX Added to plugin

Signed-off-by: Paul McQuade <[email protected]>
Create a Class for MOS65xx

Signed-off-by: Paul McQuade <[email protected]>
Created a Lifter class

Signed-off-by: Paul McQuade <[email protected]>
Doesn't output anything throught.

Signed-off-by: Paul McQuade <[email protected]>

// 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

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

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));

not mandatory

Signed-off-by: Paul McQuade <[email protected]>
@paulmcquad
Copy link
Author

@Dax89
I tried to remove the lifter part but it crashes the build below:

MOS65xx Plugin 5 - Remove Lifter Part

@Dax89
Copy link
Member

Dax89 commented Oct 25, 2022

Mmmmh, it's a bug.

So restore the lifter part, I will investigate when I have some free time

@paulmcquad
Copy link
Author

@Dax89 Please see my first attempt at adding in support for branching emulation code.
Can you provide more details around emulation support? Am i doing it right?

47c8c3b

@Dax89
Copy link
Member

Dax89 commented Nov 2, 2022

Yes, it looks ok.

I have checked for "BVS" instruction (this one? https://www.c64-wiki.com/wiki/BVS): is it a conditional jump?
It must be handled like this: https://github.com/REDasmOrg/REDasm-Assemblers/blob/master/capstonebundle/plugin/arm32/common.cpp#L13

RDEmulateResult_AddBranchTrue(result, jump_target);
RDEmulateResult_AddBranchFalse(result, address + insn->size); // If not jumps, try to emulate the next instruction

It is very important to check for "return" type instructions too

Can you provide more details around emulation support?

With the emulate callback you are creating a control flow similar to a real cpu (well...an ideal one, we can't emulate everything).
Every jump/call is queued and marked to be disassembled (a jump symbol or function is generated automatically), the engine stops the when RDEmulateResult_AddReturn() is called, in this case a new address is extracted from the queue, if the queue is empty the emulation step is completed.

If the decoded instruction is not a jump, call or return, the engine relies to the decoded instruction's size which is set by calling RDEmulateResult_SetSize(result, m_insn->size).

For example:

  • emulate address 0x00401000 with size 4
  • emulate address 0x00401004 with size 4
  • emulate address 0x00401008 with size 4
  • ...

@paulmcquad
Copy link
Author

@Dax89 - Thanks for your help but for the MOS65XX_INS_BVS instruction code. There doesn't seem to be a conditional jump code available like ARM_CC_AL. There are operand type code like MOS65XX_OP_IMM but noting like a ARM_INS_BLX case available.

@Dax89
Copy link
Member

Dax89 commented Nov 4, 2022

It was just for reference: all ARM_XYZ prefixed values are ARM specific for Capstone.

The only APIs you need are RDEmulateResult_AddBranchTrue() and RDEmulateResult_AddBranchFalse() instead of RDEmulateResult_AddBranch() which is used for unconditional jumps

@paulmcquad
Copy link
Author

@Dax89
Copy link
Member

Dax89 commented Nov 4, 2022

Nothing, BVS is a conditional jump without checking anything else:

case MOS65XX_INS_BVS: {
    RDEmulateResult_AddBranchTrue(result, mos65xx.operands[0].imm);
    RDEmulateResult_AddBranchFalse(result, address + insn->size);
    return;
}

Added MOS65XX_INS_BVS case

Signed-off-by: Paul McQuade <[email protected]>
RDRenderer_MnemonicWord API

Signed-off-by: Paul McQuade <[email protected]>
@paulmcquad
Copy link
Author

@Dax89 Am i doing this the right way, the Render Part?

https://github.com/paulmcquad/REDasm-Assemblers/blob/MOS65xx/capstonebundle/plugin/mos65xx/mos65xx.cpp#L33

RDRenderer_MnemonicWord() API

@Dax89
Copy link
Member

Dax89 commented Nov 10, 2022

Yes, but you need to call auto* insn = this->decode(rp->address, &rp->view); again and use insn variable (instructions aren't stored anywhere because decoding is pretty past)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants