ROSE 0.11.145.147
Disassembler/Aarch64.h
1#ifndef ROSE_BinaryAnalysis_Disassembler_Aarch64_H
2#define ROSE_BinaryAnalysis_Disassembler_Aarch64_H
3#include <featureTests.h>
4#ifdef ROSE_ENABLE_ASM_AARCH64
5#include <Rose/BinaryAnalysis/Disassembler/Base.h>
6
7#include <capstone/capstone.h>
8
9namespace Rose {
10namespace BinaryAnalysis {
11namespace Disassembler {
12
20class Aarch64: public Base {
21public:
22 // <rant>
23 //
24 // ARM naming is a total mess! The term "ARM" is used for the company that licenses all this, and the architecture, and
25 // some of the instruction sets, and some of the implementations. For instance, "ARM10E" is an implementation of
26 // "ARMv5TE" architecture having the "A32" (a.k.a., "AArch32") and "T32" (a.k.a., "Thumb", which also sometimes means
27 // both "Thumb" and "Thumb-2") instruction sets, all of which was designed by "Arm Holdings". Another case in point: the
28 // "Thumb-2" instruction set was extended and named "ThumbEE" (why not just "Thumb-3"?), was erroneously called
29 // "Thumb-2EE" in some ARM documentation, and was marketed as "Jazelle RCT". Then there's the inconsistencies with
30 // dashes and spaces, as in "ARM Cortex-A64" and "ARM Neoverse E1" which are both implementations created by Arm
31 // Holdings; and inconsistencies in capitalization as in "ARM" vs. "Arm" (as in "Arm Limited") vs. "arm" (as on the title
32 // page of Arm Limited's instruction reference guide); "Armv8" vs. "ARMv8", etc. It's no wonder that references like the
33 // Wikipedia page for ARM (if "ARM" is even the correct term) are riddled with mistakes, and disassemblers like Capstone
34 // are confusingly ambiguous, and ROSE itself has poor documentation for all things ARM related. The whole thing is a
35 // rat's nest probably creatied by some overzealous marketing department.
36 //
37 // Since ROSE is using Capstone for the decoding, instead of spending more effort trying to make heads and tails of this
38 // mess, I'm going to just use the same parameters as Capstone, namely a set of non-orthogonal and ill-documented
39 // enums. Best of luck to you.
40 //
41 // </rant>
42
44 using Ptr = Aarch64Ptr;
45
47 enum Mode {
48 MODE_MCLASS = CS_MODE_MCLASS,
49 };
50
52 using Modes = BitFlags<Mode>;
53
54private:
55 Modes modes_; // a subset of Capstone's cs_mode constants (warning: nonorthoganal concepts)
56 csh capstone_; // the capstone handle
57 bool capstoneOpened_ = false; // whether capstone_ is initialized
58
59protected:
60 // Constructor for specific architecture.
61 Aarch64(const Architecture::BaseConstPtr&, Modes);
62
63public:
65 static Ptr instance(const Architecture::BaseConstPtr&, Modes modes = Modes());
66
67 ~Aarch64();
68
69 // overrides
70 Base::Ptr clone() const override;
71 SgAsmInstruction* disassembleOne(const MemoryMap::Ptr&, rose_addr_t startVa, AddressSet *successors=nullptr) override;
72 SgAsmInstruction* makeUnknownInstruction(const Exception&) override;
73
74private:
75 void openCapstone();
76
77 // Returns the opcode as a 32-bit value.
78 uint32_t opcode(const cs_insn&);
79 uint32_t opcode(SgAsmInstruction*);
80
81 // Make a ROSE instruction operand from a Capstone operand
82 SgAsmExpression* makeOperand(const cs_insn&, const cs_arm64_op&);
83
84 // Make a ROSE register descriptor from a Capstone register enum constant.
85 RegisterDescriptor makeRegister(arm64_reg);
86
87 // Restrict a register to just part of a register
88 RegisterDescriptor subRegister(RegisterDescriptor reg, int idx, arm64_vess elmtSize);
89
90// // Extract a particular element out of the expression and return a new expression.
91// SgAsmExpression* extractElement(SgAsmExpression*, arm64_vess elmtSizeSpec, int idx);
92
93 // Extend an expression. Given an expression of some integer type, and given a destination type and an ARM extender
94 // function, generate a new expression (if necessary) that represents the ARM extender function. This may consist of an
95 // truncation and/or a signed or unsigned extend operation.
96 SgAsmExpression* extendOperand(SgAsmExpression*, const cs_insn&, arm64_extender, SgAsmType*, arm64_shifter, unsigned shiftAmount) const;
97
98 // Return a type for register.
99 SgAsmType* registerType(RegisterDescriptor, arm64_vas);
100
101 // Capstone doesn't return information about how much memory is read for a memory read operand. Therefore, we need to
102 // partially decode instructions ourselves to get this information.
103 SgAsmType* typeForMemoryRead(const cs_insn&);
104
105 // Change a memory reference expresson's address by wrapping it in a SgAsmPreIncrementExpression or
106 // SgAsmPostIncrementExpression if necessary.
107 void wrapPrePostIncrement(SgAsmOperandList*, const cs_arm64&);
108};
109
110} // namespace
111} // namespace
112} // namespace
113
114#endif
115#endif
Base class for expressions.
Base class for machine instructions.
List of operands for an instruction.
Base class for binary types.
Sawyer::SharedPointer< Node > Ptr
Reference counting pointer.
The ROSE library.
const char * Mode(int64_t)
Convert Rose::AST::cmdline::graphviz_t::Mode enum constant to a string.