From 32540a7190e44857f7a5097101eae1ab2bded9da Mon Sep 17 00:00:00 2001 From: wargio Date: Mon, 30 Sep 2024 21:15:53 +0200 Subject: [PATCH 1/9] Initial version of RzArch and its internal structures. --- librz/include/rz_arch.h | 138 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 3 deletions(-) diff --git a/librz/include/rz_arch.h b/librz/include/rz_arch.h index bf628fe5ecc..77ea5cddf78 100644 --- a/librz/include/rz_arch.h +++ b/librz/include/rz_arch.h @@ -6,6 +6,10 @@ #define RZ_ARCH_H #include +#include +#include + +// Deprecated includes. #include #include #include @@ -16,12 +20,140 @@ extern "C" { RZ_LIB_VERSION_HEADER(rz_arch); +typedef enum { + RZ_ARCH_XCODE_MEMBER_BYTES = 0, ///< Member is raw bytes + RZ_ARCH_XCODE_MEMBER_ASSEMBLY, ///< Member is assembly + RZ_ARCH_XCODE_MEMBER_PACKET, ///< Member is RzArchPacket + RZ_ARCH_XCODE_MEMBER_HINT, ///< Member is RzArchHint + RZ_ARCH_XCODE_MEMBER_DETAIL, ///< Member is RzArchDetail + RZ_ARCH_XCODE_MEMBER_IL, ///< Member is RzIL + RZ_ARCH_XCODE_MEMBER_PARSE, ///< [Deprecated] Member is parsed string (pseudo code) + RZ_ARCH_XCODE_MEMBER_ESIL, ///< [Deprecated] Member is ESIL +} RzArchXCodeMember; + +#define RZ_ARCH_BUFFER_SIZE 128 + +typedef struct rz_arch_xcode_t { + RzArchXCodeMember member; ///< Describes the content of array + void *array; ///< Array of variable size, containing one or more structures of type member. + size_t length; ///< Length of the data as an array +} RzArchXCode; + +/// This needs to be redone, copied for reference from RzAnalysisOp +typedef struct rz_arch_packet_t { + char *mnemonic; /* mnemonic.. it actually contains the args too, we should replace rasm with this */ + ut64 addr; /* address */ + ut32 type; /* type of opcode */ + RzAnalysisOpPrefix prefix; /* type of opcode prefix (rep,lock,..) */ + ut32 type2; /* used by java */ + RzAnalysisStackOp stackop; /* operation on stack? */ + RzTypeCond cond; /* condition type */ + int size; /* size in bytes of opcode */ + int nopcode; /* number of bytes representing the opcode (not the arguments) TODO: find better name */ + int cycles; /* cpu-cycles taken by instruction */ + int failcycles; /* conditional cpu-cycles */ + RzAnalysisOpFamily family; /* family of opcode */ + int id; /* instruction id */ + bool eob; /* end of block (boolean) */ + bool sign; /* operates on signed values, false by default */ + /* Run N instructions before executing the current one */ + int delay; /* delay N slots (mips, ..)*/ + ut64 jump; /* true jmp */ + ut64 fail; /* false jmp */ + RzAnalysisOpDirection direction; + st64 ptr; /* reference to memory */ /* XXX signed? */ + ut64 val; /* reference to value */ /* XXX signed? */ + RzAnalysisValue analysis_vals[6]; /* Analyzable values */ + int ptrsize; /* f.ex: zero extends for 8, 16 or 32 bits only */ + st64 stackptr; /* stack pointer */ + int refptr; /* if (0) ptr = "reference" else ptr = "load memory of refptr bytes" */ + ut64 mmio_address; // mmio address + RzAnalysisValue *src[6]; + RzAnalysisValue *dst; + RzList /**/ *access; /* RzAnalysisValue access information */ + RzStrBuf esil; + RzStrBuf opex; + RzAnalysisLiftedILOp il_op; + const char *reg; /* destination register */ + const char *ireg; /* register used for indirect memory computation*/ + int scale; + ut64 disp; + RzAnalysisSwitchOp *switch_op; + RzAnalysisHint hint; + RzAnalysisDataType datatype; +} RzArchPacket; + +/// This needs to be redone, copied for reference from RzAnalysisHint +typedef struct rz_arch_hint_t { + ut64 addr; + ut64 ptr; + ut64 val; // used to hint jmp rax + ut64 jump; + ut64 fail; + ut64 ret; // hint for function ret values + char *arch; + char *opcode; + char *syntax; + char *esil; + char *offset; + ut32 type; + ut64 size; + int bits; + int new_bits; // change asm.bits after evaluating this instruction + int immbase; + bool high; // highlight hint + int nword; + ut64 stackframe; +} RzArchHint; + +typedef enum { + RZ_ARCH_DETAIL_ACCESS_UNDEF = 0, ///< Undefined access + RZ_ARCH_DETAIL_ACCESS_READ, ///< Read access + RZ_ARCH_DETAIL_ACCESS_WRITE, ///< Write access +} RzArchDetailAccess; + +typedef enum { + RZ_ARCH_DETAIL_MEMBER_REGISTER = 0, ///< Member is raw bytes + RZ_ARCH_DETAIL_MEMBER_UNSIGNED, ///< Member is assembly + RZ_ARCH_DETAIL_MEMBER_SIGNED, ///< Member is RzArchPacket +} RzArchDetailMember; + +typedef struct rz_arch_detail_value_t { + RzArchDetailMember member; + union { + size_t register_id; + ut64 imm_unsigned; + st64 imm_signed; + }; +} RzArchDetailValue; + +typedef struct rz_arch_detail_t { + RzArchDetailValue source[6]; + RzArchDetailValue destination; +} RzArchDetail; + +typedef void RzArchPluginContext; + typedef struct rz_arch_plugin_t { - RZ_DEPRECATE RzAsmPlugin *p_asm; ///< Assembly Plugin - RZ_DEPRECATE RzAnalysisPlugin *p_analysis; ///< Analysis Plugin - RZ_DEPRECATE RzParsePlugin *p_parse; ///< Parse Plugin + RZ_DEPRECATE RzAsmPlugin *p_asm; ///< [Deprecated] Assembly Plugin + RZ_DEPRECATE RzAnalysisPlugin *p_analysis; ///< [Deprecated] Analysis Plugin + RZ_DEPRECATE RzParsePlugin *p_parse; ///< [Deprecated] Parse Plugin + + bool (*init)(RZ_NONNULL RzConfig *config); ///< Global constructor for the plugin to fill the configuration values. + bool (*fini)(); ///< Global destructor for the plugin + bool (*can_xcode_in)(RZ_NONNULL RzArchXCodeMember input); ///< Returns true if the plugin can support the given RzArchXCodeMember in input. + bool (*can_xcode_out)(RZ_NONNULL RzArchXCodeMember output); ///< Returns true if the plugin can support the given RzArchXCodeMember in ouput. + bool (*context_init)(RZ_NONNULL RzConfig *config, RZ_OUT RzArchPluginContext** context); ///< Create a new context for a given configuration + void (*context_fini)(RZ_NULLABLE RzArchPluginContext *context); ///< Free the given context + void (*context_update)(RZ_NULLABLE RzArchPluginContext *context, RZ_NONNULL RzConfig *config); ///< Updates the given context with the given configuration. + bool (*context_xcode)(RZ_NULLABLE RzArchPluginContext *context, RZ_NONNULL RzArchXCode *input, RZ_NONNULL RzArchXCode *output); ///< Updates the given context with the given configuration. } RzArchPlugin; +typedef struct rz_arch_t { + RzPVector /**/ *plugins; + HtSP /**/ plugins_config; +} RzArch; + RZ_DEPRECATE RZ_API const size_t rz_arch_get_n_plugins(); RZ_DEPRECATE RZ_API RZ_BORROW RzAsmPlugin *rz_arch_get_asm_plugin(size_t index); RZ_DEPRECATE RZ_API RZ_BORROW RzAnalysisPlugin *rz_arch_get_analysis_plugin(size_t index); From 4b8e489496b2760c27b6fbce7e555302f6b37ce1 Mon Sep 17 00:00:00 2001 From: wargio Date: Mon, 30 Sep 2024 21:26:32 +0200 Subject: [PATCH 2/9] Add IL --- librz/include/rz_arch.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/librz/include/rz_arch.h b/librz/include/rz_arch.h index 77ea5cddf78..bb1d8966015 100644 --- a/librz/include/rz_arch.h +++ b/librz/include/rz_arch.h @@ -26,7 +26,8 @@ typedef enum { RZ_ARCH_XCODE_MEMBER_PACKET, ///< Member is RzArchPacket RZ_ARCH_XCODE_MEMBER_HINT, ///< Member is RzArchHint RZ_ARCH_XCODE_MEMBER_DETAIL, ///< Member is RzArchDetail - RZ_ARCH_XCODE_MEMBER_IL, ///< Member is RzIL + RZ_ARCH_XCODE_MEMBER_IL, ///< Member is RzILEffect + RZ_ARCH_XCODE_MEMBER_TOKEN, ///< Member is RzArchToken RZ_ARCH_XCODE_MEMBER_PARSE, ///< [Deprecated] Member is parsed string (pseudo code) RZ_ARCH_XCODE_MEMBER_ESIL, ///< [Deprecated] Member is ESIL } RzArchXCodeMember; @@ -73,7 +74,6 @@ typedef struct rz_arch_packet_t { RzList /**/ *access; /* RzAnalysisValue access information */ RzStrBuf esil; RzStrBuf opex; - RzAnalysisLiftedILOp il_op; const char *reg; /* destination register */ const char *ireg; /* register used for indirect memory computation*/ int scale; From 4228b2914fcbd40151e8e8f84d15a4c2b2c12793 Mon Sep 17 00:00:00 2001 From: Rot127 Date: Wed, 2 Oct 2024 07:17:46 -0500 Subject: [PATCH 3/9] Replace Bytes member with RzBuffer member. RzBuffer is more versatile. --- librz/include/rz_arch.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/librz/include/rz_arch.h b/librz/include/rz_arch.h index bb1d8966015..efddaf58a7d 100644 --- a/librz/include/rz_arch.h +++ b/librz/include/rz_arch.h @@ -21,7 +21,8 @@ extern "C" { RZ_LIB_VERSION_HEADER(rz_arch); typedef enum { - RZ_ARCH_XCODE_MEMBER_BYTES = 0, ///< Member is raw bytes + RZ_ARCH_XCODE_MEMBER_INVALID = 0, ///< Invalid member + RZ_ARCH_XCODE_MEMBER_BUFFER, ///< Member is a RzBuffer RZ_ARCH_XCODE_MEMBER_ASSEMBLY, ///< Member is assembly RZ_ARCH_XCODE_MEMBER_PACKET, ///< Member is RzArchPacket RZ_ARCH_XCODE_MEMBER_HINT, ///< Member is RzArchHint From 449a5da4cb0bed3c4250abed128f2cb39029c9b0 Mon Sep 17 00:00:00 2001 From: Rot127 Date: Fri, 4 Oct 2024 02:37:40 -0500 Subject: [PATCH 4/9] Ad proposal of RzArchPacket design. --- librz/include/rz_arch.h | 70 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/librz/include/rz_arch.h b/librz/include/rz_arch.h index efddaf58a7d..a9e865ad890 100644 --- a/librz/include/rz_arch.h +++ b/librz/include/rz_arch.h @@ -5,6 +5,7 @@ #ifndef RZ_ARCH_H #define RZ_ARCH_H +#include #include #include #include @@ -35,6 +36,8 @@ typedef enum { #define RZ_ARCH_BUFFER_SIZE 128 +typedef ut64 RzAddress; + typedef struct rz_arch_xcode_t { RzArchXCodeMember member; ///< Describes the content of array void *array; ///< Array of variable size, containing one or more structures of type member. @@ -42,9 +45,9 @@ typedef struct rz_arch_xcode_t { } RzArchXCode; /// This needs to be redone, copied for reference from RzAnalysisOp -typedef struct rz_arch_packet_t { +typedef struct rz_arch_insn_t { char *mnemonic; /* mnemonic.. it actually contains the args too, we should replace rasm with this */ - ut64 addr; /* address */ + RzAddress addr; /* address */ ut32 type; /* type of opcode */ RzAnalysisOpPrefix prefix; /* type of opcode prefix (rep,lock,..) */ ut32 type2; /* used by java */ @@ -60,8 +63,8 @@ typedef struct rz_arch_packet_t { bool sign; /* operates on signed values, false by default */ /* Run N instructions before executing the current one */ int delay; /* delay N slots (mips, ..)*/ - ut64 jump; /* true jmp */ - ut64 fail; /* false jmp */ + RzAddress jump; /* true jmp */ + RzAddress fail; /* false jmp */ RzAnalysisOpDirection direction; st64 ptr; /* reference to memory */ /* XXX signed? */ ut64 val; /* reference to value */ /* XXX signed? */ @@ -82,6 +85,65 @@ typedef struct rz_arch_packet_t { RzAnalysisSwitchOp *switch_op; RzAnalysisHint hint; RzAnalysisDataType datatype; +} RzArchInsn; + +/** + * \brief Values a packet can contain. + */ +typedef enum { + RZ_ARCH_PACKET_ITER_KIND_INVALID = 0, + RZ_ARCH_PACKET_ITER_KIND_CALL_TARGETS, + RZ_ARCH_PACKET_ITER_KIND_JUMP_TARGETS, + RZ_ARCH_PACKET_ITER_KIND_DATA_REFS, + RZ_ARCH_PACKET_ITER_KIND_CODE_REFS, + RZ_ARCH_PACKET_ITER_KIND_IMMS, + RZ_ARCH_PACKET_ITER_KIND_REGS, +} RzArchPacketIterKind; + +typedef enum { + RZ_ARCH_PACKET_INSN_ORDER_INVALID = 0, + RZ_ARCH_PACKET_INSN_ORDER_LOW_ADDR_FIRST, + RZ_ARCH_PACKET_INSN_ORDER_HIGH_ADDR_FIRST, +} RzArchPacketInsnOrder; + +/// We should implement an enum for each of it though. +typedef _RzAnalysisOpType RzArchPacketType; +typedef _RzAnalysisOpType RzArchInsnType; + +struct rz_arch_packet_t; + +/** + * \brief Get an iterator over elements of type \p kind from all instructions in the packet. + * The order of values follows RzArchPacket.order. Values of the first instruction are returned first. + * + * \param packet The instruction packet. + * \param kind The kind of values the iterator should yield. + * + * \return Returns an iterator over the \p kind elements. + * Or NULL if the architecture doesn't support this iterator kind. Or has no elements to iterate over. + */ +typedef RZ_OWN RzIterator /**/ *(*rz_arch_packet_iter)(const struct rz_arch_packet_t *packet, RzArchPacketIterKind kind); + +/** + * \brief Get an iterator instructions with \p property. + * The order of instrctions follows RzArchPacket.order. + * + * \param packet The instruction packet. + * \param kind The kind of values the iterator should yield. + * + * \return Returns an iterator over the insturctions with \p insn_type. + * Or NULL if the packet has no instructions of such type. + */ +typedef RZ_OWN RzIterator /**/ *(*rz_arch_packet_iter_insn)(const struct rz_arch_packet_t *packet, RzArchInsnType insn_type); + +/** + * \brief An atomically executed unit. Can contain 1-n instructions. + */ +typedef struct rz_arch_packet_t { + RzArchPacketInsnOrder order; ///< Order the instructions. + RzPVector /**/ *insns; ///< All instructions of a packet. Sorted according to order. + rz_arch_packet_iter value_iter; + rz_arch_packet_iter_insn insn_iter; } RzArchPacket; /// This needs to be redone, copied for reference from RzAnalysisHint From 2427d257a18331453c6cebeb12b8fc6cfcbf88fe Mon Sep 17 00:00:00 2001 From: Rot127 Date: Fri, 4 Oct 2024 02:59:33 -0500 Subject: [PATCH 5/9] Change member description back to bytes. The xcode function is actually from bytes -> asm/packet etc. The RzBuffer is just the vehicle to provide the bytes. --- librz/include/rz_arch.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/librz/include/rz_arch.h b/librz/include/rz_arch.h index a9e865ad890..a2f7470d4f1 100644 --- a/librz/include/rz_arch.h +++ b/librz/include/rz_arch.h @@ -23,7 +23,7 @@ RZ_LIB_VERSION_HEADER(rz_arch); typedef enum { RZ_ARCH_XCODE_MEMBER_INVALID = 0, ///< Invalid member - RZ_ARCH_XCODE_MEMBER_BUFFER, ///< Member is a RzBuffer + RZ_ARCH_XCODE_MEMBER_BYTES, ///< Member are bytes provided by a RzBuffer. RZ_ARCH_XCODE_MEMBER_ASSEMBLY, ///< Member is assembly RZ_ARCH_XCODE_MEMBER_PACKET, ///< Member is RzArchPacket RZ_ARCH_XCODE_MEMBER_HINT, ///< Member is RzArchHint @@ -34,8 +34,6 @@ typedef enum { RZ_ARCH_XCODE_MEMBER_ESIL, ///< [Deprecated] Member is ESIL } RzArchXCodeMember; -#define RZ_ARCH_BUFFER_SIZE 128 - typedef ut64 RzAddress; typedef struct rz_arch_xcode_t { From 4d0f00491a04f366c0b9d306cb75b541a658b80b Mon Sep 17 00:00:00 2001 From: Rot127 Date: Mon, 7 Oct 2024 06:56:43 -0500 Subject: [PATCH 6/9] Change members to RzPVector --- librz/include/rz_arch.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/librz/include/rz_arch.h b/librz/include/rz_arch.h index a2f7470d4f1..7fa7c9a876d 100644 --- a/librz/include/rz_arch.h +++ b/librz/include/rz_arch.h @@ -37,9 +37,8 @@ typedef enum { typedef ut64 RzAddress; typedef struct rz_arch_xcode_t { - RzArchXCodeMember member; ///< Describes the content of array - void *array; ///< Array of variable size, containing one or more structures of type member. - size_t length; ///< Length of the data as an array + RzArchXCodeMember member_type; ///< Describes the content of array + RzPVector /**/ *members; ///< Array of variable size, containing one or more structures of type member. } RzArchXCode; /// This needs to be redone, copied for reference from RzAnalysisOp From e44ec83212e8db10b90c8eec226b8e4f849cce4e Mon Sep 17 00:00:00 2001 From: Rot127 Date: Mon, 7 Oct 2024 07:49:41 -0500 Subject: [PATCH 7/9] Move and extend detail object to operand object. --- librz/include/rz_arch.h | 120 ++++++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 30 deletions(-) diff --git a/librz/include/rz_arch.h b/librz/include/rz_arch.h index 7fa7c9a876d..3812f421778 100644 --- a/librz/include/rz_arch.h +++ b/librz/include/rz_arch.h @@ -5,6 +5,7 @@ #ifndef RZ_ARCH_H #define RZ_ARCH_H +#include #include #include #include @@ -84,6 +85,85 @@ typedef struct rz_arch_insn_t { RzAnalysisDataType datatype; } RzArchInsn; +typedef enum { + RZ_ARCH_OPERAND_ACCESS_UNDEF = 0, ///< Undefined access + RZ_ARCH_OPERAND_ACCESS_READ, ///< Read access + RZ_ARCH_OPERAND_ACCESS_WRITE, ///< Write access +} RzArchOperandAccess; + +#define RZ_ARCH_OPERAND_MEMBER_ATOMIC 0xffff +#define RZ_ARCH_OPERAND_MEMBER_CLASS 0xff0000 + +/** + * \brief Memberships of operands. + */ +typedef enum { + RZ_ARCH_OPERAND_MEMBER_INVALID = 0, + RZ_ARCH_OPERAND_MEMBER_REGISTER, ///< Register operand + RZ_ARCH_OPERAND_MEMBER_IMMEDIATE, ///< Immediate value of any sign operand. + RZ_ARCH_OPERAND_MEMBER_UNSIGNED, ///< Unsigned immediate value operand. + RZ_ARCH_OPERAND_MEMBER_SIGNED, ///< Signed immediate value operand. + RZ_ARCH_OPERAND_MEMBER_COMPLEX = 0x10000, ///< This operand consists of multiple other operands. + RZ_ARCH_OPERAND_MEMBER_ADDRESS = 0x20000, ///< This operand should be interpreted as an address. +} RzArchOperandMember; + +/// The bitvecor must be initialized with rz_bv_fini. In case it holds a value >64bits. +typedef struct rz_arch_operand_value_t { + RzArchOperandMember member; ///< Details about the operand membership. + RzArchOperandAccess access; ///< Access to this operand. + union { + size_t register_id; ///< A register + RzBitVector imm; ///< An immediate value. + }; + RzPVector /**/ *components; ///< Components of complex operands. +} RzArchOperand; + +static inline bool rz_arch_op_val_is_reg(RZ_NONNULL const RzArchOperand *op) { + return op->member & RZ_ARCH_OPERAND_MEMBER_REGISTER; +} + +static inline bool rz_arch_op_val_is_imm(RZ_NONNULL const RzArchOperand *op) { + return op->member & RZ_ARCH_OPERAND_MEMBER_IMMEDIATE; +} + +static inline bool rz_arch_op_val_is_signed(RZ_NONNULL const RzArchOperand *op) { + return op->member & RZ_ARCH_OPERAND_MEMBER_SIGNED; +} + +static inline bool rz_arch_op_val_is_unsigned(RZ_NONNULL const RzArchOperand *op) { + return op->member & RZ_ARCH_OPERAND_MEMBER_UNSIGNED; +} + +static inline bool rz_arch_op_val_is_complex(RZ_NONNULL const RzArchOperand *op) { + return op->member & RZ_ARCH_OPERAND_MEMBER_COMPLEX; +} + +/** + * \brief Returns the member a complex operand was reduced to. + * + * E.g.: a complex address operand consisting of two immediate values `base` and `offset`. + * If the plugin already reduced them to their final value (`base + offset`), this function + * returns RZ_ARCH_OPERAND_MEMBER_IMMEDIATE. + * + * \return The member the combined operands are reduced to. The reduced value is stored in the suitable field. + * It returns RZ_ARCH_OPERAND_MEMBER_INVALID, if the plugin cannot reduce complex operand. + */ +static inline RzArchOperandMember rz_arch_op_val_is_complex_reduced(RZ_NONNULL const RzArchOperand *op) { + return (RzArchOperandMember) (op->member & RZ_ARCH_OPERAND_MEMBER_ATOMIC); +} + +static inline bool rz_arch_op_val_is_address(RZ_NONNULL const RzArchOperand *op) { + return op->member & RZ_ARCH_OPERAND_MEMBER_ADDRESS; +} + +static inline RzArchOperandMember rz_arch_op_val_member_atmoic(RZ_NONNULL const RzArchOperand *op) { + return (RzArchOperandMember) (op->member & RZ_ARCH_OPERAND_MEMBER_ATOMIC); +} + +static inline RzArchOperandMember rz_arch_op_val_member_class(RZ_NONNULL const RzArchOperand *op) { + return (RzArchOperandMember) (op->member & RZ_ARCH_OPERAND_MEMBER_CLASS); +} + /** * \brief Values a packet can contain. */ @@ -95,8 +175,14 @@ typedef enum { RZ_ARCH_PACKET_ITER_KIND_CODE_REFS, RZ_ARCH_PACKET_ITER_KIND_IMMS, RZ_ARCH_PACKET_ITER_KIND_REGS, + RZ_ARCH_PACKET_ITER_KIND_OPERANDS, } RzArchPacketIterKind; +typedef enum { + RZ_ARCH_PACKET_ITER_GROUPED_NONE = 0, ///< The iterator iterates over all requested elements in a packet. + RZ_ARCH_PACKET_ITER_GROUPED_INSN, ///< The iterator groups the requested elements by instuctions (iterator over iterators). +} RzArchPacketIterGrouped; + typedef enum { RZ_ARCH_PACKET_INSN_ORDER_INVALID = 0, RZ_ARCH_PACKET_INSN_ORDER_LOW_ADDR_FIRST, @@ -119,7 +205,7 @@ struct rz_arch_packet_t; * \return Returns an iterator over the \p kind elements. * Or NULL if the architecture doesn't support this iterator kind. Or has no elements to iterate over. */ -typedef RZ_OWN RzIterator /**/ *(*rz_arch_packet_iter)(const struct rz_arch_packet_t *packet, RzArchPacketIterKind kind); +typedef RZ_OWN RzIterator /**/ *(*rz_arch_packet_iter)(const struct rz_arch_packet_t *packet, RzArchPacketIterKind kind, RzArchPacketIterGrouped grouped_by); /** * \brief Get an iterator instructions with \p property. @@ -166,32 +252,6 @@ typedef struct rz_arch_hint_t { ut64 stackframe; } RzArchHint; -typedef enum { - RZ_ARCH_DETAIL_ACCESS_UNDEF = 0, ///< Undefined access - RZ_ARCH_DETAIL_ACCESS_READ, ///< Read access - RZ_ARCH_DETAIL_ACCESS_WRITE, ///< Write access -} RzArchDetailAccess; - -typedef enum { - RZ_ARCH_DETAIL_MEMBER_REGISTER = 0, ///< Member is raw bytes - RZ_ARCH_DETAIL_MEMBER_UNSIGNED, ///< Member is assembly - RZ_ARCH_DETAIL_MEMBER_SIGNED, ///< Member is RzArchPacket -} RzArchDetailMember; - -typedef struct rz_arch_detail_value_t { - RzArchDetailMember member; - union { - size_t register_id; - ut64 imm_unsigned; - st64 imm_signed; - }; -} RzArchDetailValue; - -typedef struct rz_arch_detail_t { - RzArchDetailValue source[6]; - RzArchDetailValue destination; -} RzArchDetail; - typedef void RzArchPluginContext; typedef struct rz_arch_plugin_t { @@ -199,11 +259,11 @@ typedef struct rz_arch_plugin_t { RZ_DEPRECATE RzAnalysisPlugin *p_analysis; ///< [Deprecated] Analysis Plugin RZ_DEPRECATE RzParsePlugin *p_parse; ///< [Deprecated] Parse Plugin - bool (*init)(RZ_NONNULL RzConfig *config); ///< Global constructor for the plugin to fill the configuration values. - bool (*fini)(); ///< Global destructor for the plugin + bool (*init)(RZ_NONNULL RzConfig *config); ///< Global constructor for the plugin to fill the configuration values. + bool (*fini)(); ///< Global destructor for the plugin bool (*can_xcode_in)(RZ_NONNULL RzArchXCodeMember input); ///< Returns true if the plugin can support the given RzArchXCodeMember in input. bool (*can_xcode_out)(RZ_NONNULL RzArchXCodeMember output); ///< Returns true if the plugin can support the given RzArchXCodeMember in ouput. - bool (*context_init)(RZ_NONNULL RzConfig *config, RZ_OUT RzArchPluginContext** context); ///< Create a new context for a given configuration + bool (*context_init)(RZ_NONNULL RzConfig *config, RZ_OUT RzArchPluginContext **context); ///< Create a new context for a given configuration void (*context_fini)(RZ_NULLABLE RzArchPluginContext *context); ///< Free the given context void (*context_update)(RZ_NULLABLE RzArchPluginContext *context, RZ_NONNULL RzConfig *config); ///< Updates the given context with the given configuration. bool (*context_xcode)(RZ_NULLABLE RzArchPluginContext *context, RZ_NONNULL RzArchXCode *input, RZ_NONNULL RzArchXCode *output); ///< Updates the given context with the given configuration. From 6594a29b798409033bb61a0386f8a1b00e35c860 Mon Sep 17 00:00:00 2001 From: Rot127 Date: Mon, 7 Oct 2024 08:00:22 -0500 Subject: [PATCH 8/9] Add a grouped iterator --- librz/include/rz_arch.h | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/librz/include/rz_arch.h b/librz/include/rz_arch.h index 3812f421778..3cb387e1a7e 100644 --- a/librz/include/rz_arch.h +++ b/librz/include/rz_arch.h @@ -169,13 +169,13 @@ static inline RzArchOperandMember rz_arch_op_val_member_class(RZ_NONNULL const R */ typedef enum { RZ_ARCH_PACKET_ITER_KIND_INVALID = 0, - RZ_ARCH_PACKET_ITER_KIND_CALL_TARGETS, - RZ_ARCH_PACKET_ITER_KIND_JUMP_TARGETS, - RZ_ARCH_PACKET_ITER_KIND_DATA_REFS, - RZ_ARCH_PACKET_ITER_KIND_CODE_REFS, - RZ_ARCH_PACKET_ITER_KIND_IMMS, - RZ_ARCH_PACKET_ITER_KIND_REGS, - RZ_ARCH_PACKET_ITER_KIND_OPERANDS, + RZ_ARCH_PACKET_ITER_KIND_CALL_TARGETS, ///< Element type: RzBitevector + RZ_ARCH_PACKET_ITER_KIND_JUMP_TARGETS, ///< Element type: RzBitevector + RZ_ARCH_PACKET_ITER_KIND_DATA_REFS, ///< Element type: RzBitevector + RZ_ARCH_PACKET_ITER_KIND_CODE_REFS, ///< Element type: RzBitevector + RZ_ARCH_PACKET_ITER_KIND_IMMS, ///< Element type: RzBitevector + RZ_ARCH_PACKET_ITER_KIND_REGS, ///< Element type: size_t + RZ_ARCH_PACKET_ITER_KIND_OPERANDS, ///< Element type: RzArchOperand } RzArchPacketIterKind; typedef enum { @@ -205,7 +205,20 @@ struct rz_arch_packet_t; * \return Returns an iterator over the \p kind elements. * Or NULL if the architecture doesn't support this iterator kind. Or has no elements to iterate over. */ -typedef RZ_OWN RzIterator /**/ *(*rz_arch_packet_iter)(const struct rz_arch_packet_t *packet, RzArchPacketIterKind kind, RzArchPacketIterGrouped grouped_by); +typedef RZ_OWN RzIterator /**/ *(*rz_arch_packet_iter)(const struct rz_arch_packet_t *packet, RzArchPacketIterKind kind); + +/** + * \brief Get an iterator over elements of type \p kind from all instructions in the packet. + * The order of values follows RzArchPacket.order. Values of the first instruction are returned first. + * + * \param packet The instruction packet. + * \param kind The kind of values the iterator should yield. + * \param grouped_by Groups the elements as requested. + * + * \return Returns an iterator over RzIterator. + * Or NULL if the architecture doesn't support this iterator kind. Or has no elements to iterate over. + */ +typedef RZ_OWN RzIterator /**/ *(*rz_arch_packet_grouped_iter)(const struct rz_arch_packet_t *packet, RzArchPacketIterKind kind, RzArchPacketIterGrouped grouped_by); /** * \brief Get an iterator instructions with \p property. @@ -226,6 +239,7 @@ typedef struct rz_arch_packet_t { RzArchPacketInsnOrder order; ///< Order the instructions. RzPVector /**/ *insns; ///< All instructions of a packet. Sorted according to order. rz_arch_packet_iter value_iter; + rz_arch_packet_grouped_iter grouped_value_iter; rz_arch_packet_iter_insn insn_iter; } RzArchPacket; From 7d1ac637ef0ce1bfaeeca185e907fc11a1dbd852 Mon Sep 17 00:00:00 2001 From: Rot127 Date: Wed, 23 Oct 2024 09:51:30 -0500 Subject: [PATCH 9/9] Add basic proposal for plugin storage/management. --- librz/include/rz_arch.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/librz/include/rz_arch.h b/librz/include/rz_arch.h index 3cb387e1a7e..0d351964a2e 100644 --- a/librz/include/rz_arch.h +++ b/librz/include/rz_arch.h @@ -284,10 +284,21 @@ typedef struct rz_arch_plugin_t { } RzArchPlugin; typedef struct rz_arch_t { - RzPVector /**/ *plugins; - HtSP /**/ plugins_config; + HtSP /**/ *plugins; ///< Existing RzArch plugins. NOT initialized. + HtUP /**/ *in_use_plugins; ///< Initialized RzArch plugins in use. + HtUP /**/ *plugins_config; ///< Configurations of initialized plugins. + HtUP /**/ *plugins_data; ///< Private data of each initialized plugin. } RzArch; +/** + * \brief Initializes an instance of the plugin \p name. + * It also initializes a private configuration and data for this instance. + * + * \return The ID of the plugin instance, or UT32_MAX in case of failure. + */ +RZ_API RZ_BORROW ut32 rz_arch_init_plugin(RZ_BORROW RzArch *rz_arch, const char *name); +RZ_API RZ_BORROW RzArchPlugin *rz_arch_get_plugin_instance(const RzArch *rz_arch, ut32 instance_id); + RZ_DEPRECATE RZ_API const size_t rz_arch_get_n_plugins(); RZ_DEPRECATE RZ_API RZ_BORROW RzAsmPlugin *rz_arch_get_asm_plugin(size_t index); RZ_DEPRECATE RZ_API RZ_BORROW RzAnalysisPlugin *rz_arch_get_analysis_plugin(size_t index);