11// SPDX-FileCopyrightText: 2024-2026 moste00 <ubermenchun@gmail.com>
22// SPDX-License-Identifier: BSD-3-Clause
33
4- #include <rz_analysis.h>
4+ #ifndef ANALYSIS_RISCV_UTILS_H
5+ #define ANALYSIS_RISCV_UTILS_H
56
6- #include "cs_operand.h"
7- #include "rz_util/rz_log.h"
7+ #include <rz_analysis.h>
88
99#include <capstone/capstone.h>
1010#include <capstone/riscv.h>
1111#include <stdint.h>
1212
13- // A more high-level alternative to direct indexing that can get immediates and operands without exact
14- // indices
15- // While also enforcing high-level constraints such as "exactly one immediate operand is present"
16- // or "at most one operand is present" or "get the single register that is read/written"
13+ // A more high-level alternative to direct indexing that can get immediates and operands without exact indices
14+ // While also enforcing high-level constraints such as "exactly one immediate operand is present" or "at most
15+ // one operand is present" or "get the single register that is read/written"
1716
18- static inline int find_at_most_one_op (cs_riscv_op * operands , uint8_t op_count , riscv_op_type type , const char * type_str ) {
19- int first = -1 ;
20- for (int i = 0 ; i < op_count ; i ++ ) {
17+ static inline ut32 find_at_most_one_op (cs_riscv_op * operands , uint8_t op_count , riscv_op_type type , const char * type_str ) {
18+ ut32 first = UT32_MAX ;
19+ for (ut32 i = 0 ; i < op_count ; i ++ ) {
2120 if (operands [i ].type == type ) {
22- if (first == -1 ) {
21+ if (first == UT32_MAX ) {
2322 first = i ;
2423 } else {
25- RZ_LOG_FATAL ("Expected exactly one %s operand, two elements matched (the %ith and %ith elements)" , type_str , first , i );
26- exit (-1 );
24+ RZ_LOG_DEBUG ("Expected exactly one %s operand, two elements matched (the %ith and %ith elements)" , type_str , first , i );
2725 }
2826 }
2927 }
3028 return first ;
3129}
3230
33- static inline int find_at_most_one_imm (cs_riscv_op * operands , uint8_t op_count ) {
31+ static inline ut32 find_at_most_one_imm (cs_riscv_op * operands , uint8_t op_count ) {
3432 return find_at_most_one_op (operands , op_count , RISCV_OP_IMM , "immediate" );
3533}
3634
37- static inline int find_exactly_one_op (cs_riscv_op * operands , uint8_t op_count , riscv_op_type type , const char * type_str ) {
38- int first = find_at_most_one_op (operands , op_count , type , type_str );
39- if (first == -1 ) {
40- RZ_LOG_FATAL ("Expected exactly one %s operand, found none" , type_str );
41- exit (-1 );
42- }
43- return first ;
35+ static inline ut32 find_exactly_one_op (cs_riscv_op * operands , uint8_t op_count , riscv_op_type type , const char * type_str ) {
36+ return find_at_most_one_op (operands , op_count , type , type_str );
4437}
4538
46- static inline int find_exactly_one_imm (cs_riscv_op * operands , uint8_t op_count ) {
39+ static inline ut32 find_exactly_one_imm (cs_riscv_op * operands , uint8_t op_count ) {
4740 return find_exactly_one_op (operands , op_count , RISCV_OP_IMM , "immediate" );
4841}
4942
5043static inline int64_t get_exactly_one_immediate (cs_riscv_op * operands , uint8_t op_count ) {
51- return operands [find_exactly_one_imm (operands , op_count )].imm ;
44+ ut32 idx = find_exactly_one_imm (operands , op_count );
45+ if (idx < op_count ) {
46+ return operands [idx ].imm ;
47+ }
48+ return INT64_MAX ;
5249}
5350
5451static inline int64_t get_at_most_one_immediate (cs_riscv_op * operands , uint8_t op_count ) {
55- int64_t idx = find_at_most_one_imm (operands , op_count );
56- if (idx == -1 ) {
57- return INT64_MAX ;
52+ ut32 idx = find_at_most_one_imm (operands , op_count );
53+ if (idx < op_count ) {
54+ return operands [ idx ]. imm ;
5855 }
59- return operands [ idx ]. imm ;
56+ return INT64_MAX ;
6057}
6158
6259#define SINGLE_IMM (insn ) get_exactly_one_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count);
6360#define MAYBE_IMM (insn ) get_at_most_one_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count);
6461
65- static inline int find_first_op (cs_riscv_op * operands , uint8_t op_count , riscv_op_type type ) {
66- for (int i = 0 ; i < op_count ; i ++ ) {
62+ static inline ut32 find_first_op (cs_riscv_op * operands , uint8_t op_count , riscv_op_type type ) {
63+ for (ut32 i = 0 ; i < op_count ; i ++ ) {
6764 if (operands [i ].type == type ) {
6865 return i ;
6966 }
7067 }
71- return -1 ;
68+ return UT32_MAX ;
7269}
7370
74- static inline int find_first_imm (cs_riscv_op * operands , uint8_t op_count ) {
71+ static inline ut32 find_first_imm (cs_riscv_op * operands , uint8_t op_count ) {
7572 return find_first_op (operands , op_count , RISCV_OP_IMM );
7673}
7774
7875static inline int64_t get_first_immediate (cs_riscv_op * operands , uint8_t op_count ) {
79- int idx = find_first_imm (operands , op_count );
80- if (idx == -1 ) {
81- return INT64_MAX ;
76+ ut32 idx = find_first_imm (operands , op_count );
77+ if (idx < op_count ) {
78+ return operands [ idx ]. imm ;
8279 }
83- return operands [ idx ]. imm ;
80+ return INT64_MAX ;
8481}
8582
8683#define FIRST_IMM (insn ) get_first_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count);
8784
88- static inline unsigned int get_any_reg_accessed_as (cs_riscv_op * operands , uint8_t op_count , cs_ac_type access ) {
89- for (int i = 0 ; i < op_count ; i ++ ) {
85+ static inline ut32 get_any_reg_accessed_as (cs_riscv_op * operands , uint8_t op_count , cs_ac_type access ) {
86+ for (ut32 i = 0 ; i < op_count ; i ++ ) {
9087 if (operands [i ].type == RISCV_OP_REG && (operands [i ].access & access )) {
9188 return operands [i ].reg ;
9289 }
9390 }
94- RZ_LOG_FATAL ("Expected at least one register with %s access, found none" , access == CS_AC_READ ? "read" : "write" );
95- exit (-1 );
91+ RZ_LOG_DEBUG ("Expected at least one register with %s access, found none" , access == CS_AC_READ ? "read" : "write" );
9692 return 0 ; // dummy for type checking, never reached
9793}
9894
99- static inline unsigned int first_read_register (cs_riscv_op * operands , uint8_t op_count ) {
95+ static inline ut32 first_read_register (cs_riscv_op * operands , uint8_t op_count ) {
10096 return get_any_reg_accessed_as (operands , op_count , CS_AC_READ );
10197}
10298
103- static inline unsigned int first_written_register (cs_riscv_op * operands , uint8_t op_count ) {
99+ static inline ut32 first_written_register (cs_riscv_op * operands , uint8_t op_count ) {
104100 return get_any_reg_accessed_as (operands , op_count , CS_AC_WRITE );
105101}
106102
107103#define FIRST_READ_REGID (insn ) first_read_register(insn->detail->riscv.operands, insn->detail->riscv.op_count)
108104#define FIRST_WRITTEN_REGID (insn ) first_written_register(insn->detail->riscv.operands, insn->detail->riscv.op_count)
109105
110106// check if a certain reg is ever accessed as read/write register
111- static inline bool is_any_reg_accessed_as (cs_riscv_op * operands , uint8_t op_count , unsigned int reg , cs_ac_type access ) {
107+ static inline bool is_any_reg_accessed_as (cs_riscv_op * operands , uint8_t op_count , ut32 reg , cs_ac_type access ) {
112108 for (int i = 0 ; i < op_count ; i ++ ) {
113109 if (operands [i ].type == RISCV_OP_REG && operands [i ].reg == reg && (operands [i ].access & access )) {
114110 return true;
@@ -117,23 +113,25 @@ static inline bool is_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_coun
117113 return false;
118114}
119115
120- static inline bool is_reg_written (cs_riscv_op * operands , uint8_t op_count , unsigned int reg ) {
116+ static inline bool is_reg_written (cs_riscv_op * operands , uint8_t op_count , ut32 reg ) {
121117 return is_any_reg_accessed_as (operands , op_count , reg , CS_AC_WRITE );
122118}
123- static inline bool is_reg_read (cs_riscv_op * operands , uint8_t op_count , unsigned int reg ) {
119+ static inline bool is_reg_read (cs_riscv_op * operands , uint8_t op_count , ut32 reg ) {
124120 return is_any_reg_accessed_as (operands , op_count , reg , CS_AC_READ );
125121}
126122
127123#define IS_REG_WRITTEN (insn , reg ) is_reg_written(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
128124#define IS_REG_READ (insn , reg ) is_reg_read(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
129125
130126static inline bool is_any_reg_memory_base (cs_riscv_op * operands , uint8_t op_count , unsigned int reg ) {
131- for (int i = 0 ; i < op_count ; i ++ ) {
127+ for (ut32 i = 0 ; i < op_count ; i ++ ) {
132128 if (operands [i ].type == RISCV_OP_MEM && operands [i ].mem .base == reg ) {
133129 return true;
134130 }
135131 }
136132 return false;
137133}
138134
139- #define MEM_BASE (insn , reg ) is_any_reg_memory_base(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
135+ #define MEM_BASE (insn , reg ) is_any_reg_memory_base(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
136+
137+ #endif /* ANALYSIS_RISCV_UTILS_H */
0 commit comments