Skip to content

Commit

Permalink
Distinguish between subtypes of different graph node types.
Browse files Browse the repository at this point in the history
  • Loading branch information
Rot127 committed Mar 13, 2024
1 parent 71bc3ce commit 6a81376
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 101 deletions.
13 changes: 10 additions & 3 deletions librz/core/agraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -3748,9 +3748,16 @@ RZ_API RZ_BORROW RzANode *rz_agraph_add_node_from_node_info(RZ_NONNULL const RzA
break;
case RZ_GRAPH_NODE_TYPE_CFG:
case RZ_GRAPH_NODE_TYPE_CFG_IWORD: {
char *annotation = rz_graph_get_node_subtype_annotation(info->subtype, utf8);
char *annotation = NULL;
ut64 addr = 0;
if (info->type == RZ_GRAPH_NODE_TYPE_CFG) {
annotation = rz_graph_get_node_subtype_annotation_cfg(info->cfg.subtype, true, utf8);
addr = info->cfg.address;
} else {
annotation = rz_graph_get_node_subtype_annotation_cfg_iword(info->cfg_iword.subtype, true, utf8);
addr = info->cfg_iword.address;
}
rz_return_val_if_fail(annotation, NULL);
ut64 addr = info->type == RZ_GRAPH_NODE_TYPE_CFG ? info->cfg.address : info->cfg_iword.address;
char *cfg_title = rz_str_appendf(NULL, "0x%" PFMT64x "%s", addr, annotation);
rz_return_val_if_fail(cfg_title, NULL);
an = rz_agraph_add_node(g, cfg_title, "");
Expand All @@ -3764,7 +3771,7 @@ RZ_API RZ_BORROW RzANode *rz_agraph_add_node_from_node_info(RZ_NONNULL const RzA
}
case RZ_GRAPH_NODE_TYPE_ICFG:
rz_strf(title, "0x%" PFMT64x "%s", info->icfg.address,
info->subtype & RZ_GRAPH_NODE_SUBTYPE_ICFG_MALLOC ? " (alloc)" : "");
info->icfg.subtype & RZ_GRAPH_NODE_SUBTYPE_ICFG_MALLOC ? " (alloc)" : "");
an = rz_agraph_add_node(g, title, "");
if (!an) {
return NULL;
Expand Down
31 changes: 15 additions & 16 deletions librz/core/cgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,7 @@ static RzGraphNode *rz_graph_add_node_info_icfg(RzGraph /*<RzGraphNodeInfo *>*/
if (rz_analysis_function_is_malloc(fcn)) {
data = rz_graph_create_node_info_icfg(fcn->addr, RZ_GRAPH_NODE_SUBTYPE_ICFG_MALLOC);
} else {
data = rz_graph_create_node_info_icfg(fcn->addr, RZ_GRAPH_NODE_SUBTYPE_NONE);
data = rz_graph_create_node_info_icfg(fcn->addr, RZ_GRAPH_NODE_SUBTYPE_ICFG_NONE);
}
if (!data) {
rz_warn_if_reached();
Expand Down Expand Up @@ -939,9 +939,9 @@ static inline bool ignore_next_instr(const RzAnalysisOp *op) {
return is_uncond_jump(op) || (op->fail != UT64_MAX && !is_call(op)); // Except calls, everything which has set fail
}

static RzGraphNodeSubType get_cfg_node_flags(const RzAnalysisOp *op) {
rz_return_val_if_fail(op, RZ_GRAPH_NODE_SUBTYPE_NONE);
RzGraphNodeSubType subtype = RZ_GRAPH_NODE_SUBTYPE_NONE;
static RzGraphNodeCFGSubType get_cfg_node_flags(const RzAnalysisOp *op) {
rz_return_val_if_fail(op, RZ_GRAPH_NODE_SUBTYPE_CFG_NONE);
RzGraphNodeCFGSubType subtype = RZ_GRAPH_NODE_SUBTYPE_CFG_NONE;
if (is_call(op)) {
subtype |= RZ_GRAPH_NODE_SUBTYPE_CFG_CALL;
}
Expand All @@ -954,29 +954,28 @@ static RzGraphNodeSubType get_cfg_node_flags(const RzAnalysisOp *op) {
return subtype;
}

static RzGraphNodeSubType get_cfg_iword_node_flags(const RzAnalysisInsnWord *iword) {
rz_return_val_if_fail(iword, RZ_GRAPH_NODE_SUBTYPE_NONE);
RzGraphNodeSubType subtype = RZ_GRAPH_NODE_SUBTYPE_NONE;
if (iword->props & RZ_ANALYSIS_IWORD_CALL) {
subtype |= RZ_GRAPH_NODE_SUBTYPE_CFG_CALL;
}
static RzGraphNodeCFGIWordSubType get_cfg_iword_node_flags(const RzAnalysisInsnWord *iword) {
rz_return_val_if_fail(iword, RZ_GRAPH_NODE_SUBTYPE_CFG_IWORD_NONE);
RzGraphNodeCFGIWordSubType subtype = RZ_GRAPH_NODE_SUBTYPE_CFG_IWORD_NONE;
if (iword->props & RZ_ANALYSIS_IWORD_RET) {
subtype |= RZ_GRAPH_NODE_SUBTYPE_CFG_RETURN;
subtype |= RZ_GRAPH_NODE_SUBTYPE_CFG_IWORD_RETURN;
}
if (iword->props & RZ_ANALYSIS_IWORD_COND) {
subtype |= RZ_GRAPH_NODE_SUBTYPE_CFG_COND;
subtype |= RZ_GRAPH_NODE_SUBTYPE_CFG_IWORD_COND;
}
return subtype;
}

static RzGraphNode *add_node_info_cfg(RzGraph /*<RzGraphNodeInfo *>*/ *cfg, const RzAnalysisOp *op, bool is_entry) {
rz_return_val_if_fail(cfg, NULL);
RzGraphNodeSubType subtype = get_cfg_node_flags(op);
RzGraphNodeCFGSubType subtype = get_cfg_node_flags(op);
if (is_entry) {
subtype |= RZ_GRAPH_NODE_SUBTYPE_CFG_ENTRY;
}
ut64 call_target = is_call(op) ? op->jump : UT64_MAX;
RzGraphNodeInfo *data = rz_graph_create_node_info_cfg(op->addr, call_target, subtype);
ut64 jump_target = rz_analysis_op_is_jump(op) ? op->jump : UT64_MAX;
ut64 next = is_return(op) ? UT64_MAX : op->addr + op->size;
RzGraphNodeInfo *data = rz_graph_create_node_info_cfg(op->addr, call_target, jump_target, next, subtype);
if (!data) {
return NULL;
}
Expand Down Expand Up @@ -1156,9 +1155,9 @@ RZ_API RZ_OWN RzGraph /*<RzGraphNodeInfo *>*/ *rz_core_graph_cfg(RZ_NONNULL RzCo

static RzGraphNode *add_iword_to_cfg(RzGraph /*<RzGraphNodeInfo *>*/ *cfg, const RzAnalysisInsnWord *iword, bool is_entry) {
rz_return_val_if_fail(cfg, NULL);
RzGraphNodeSubType subtype = get_cfg_iword_node_flags(iword);
RzGraphNodeCFGIWordSubType subtype = get_cfg_iword_node_flags(iword);
if (is_entry) {
subtype |= RZ_GRAPH_NODE_SUBTYPE_CFG_ENTRY;
subtype |= RZ_GRAPH_NODE_SUBTYPE_CFG_IWORD_ENTRY;
}
RzGraphNodeInfo *data = rz_graph_create_node_info_cfg_iword(iword, subtype);
if (!data) {
Expand Down
4 changes: 4 additions & 0 deletions librz/include/rz_analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,10 @@ static inline bool rz_analysis_op_is_jump(const RzAnalysisOp *op) {
return is_jump;
}

static inline bool rz_analysis_op_is_return(const RzAnalysisOp *op) {
return (op->type == RZ_ANALYSIS_OP_TYPE_RET);
}

static inline bool rz_analysis_op_is_cjump(const RzAnalysisOp *op) {
return rz_analysis_op_is_jump(op) && op->type & RZ_ANALYSIS_OP_TYPE_COND;
}
Expand Down
61 changes: 34 additions & 27 deletions librz/include/rz_util/rz_graph_drawable.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ typedef enum {
} RzGraphNodeType;

typedef enum {
RZ_GRAPH_NODE_SUBTYPE_NONE = 0, ///< No details given to this node.
RZ_GRAPH_NODE_SUBTYPE_ICFG_NONE = 0, ///< No details given to this node.
RZ_GRAPH_NODE_SUBTYPE_ICFG_MALLOC = 1 << 5, ///< Node represents a memory allocating procedure.
} RzGraphNodeiCFGSubType;

typedef enum {
RZ_GRAPH_NODE_SUBTYPE_CFG_NONE = 0, ///< No details given to this node.
RZ_GRAPH_NODE_SUBTYPE_CFG_ENTRY = 1 << 0, ///< Entry node of the procedure CFG.
RZ_GRAPH_NODE_SUBTYPE_CFG_CALL = 1 << 1, ///> A node which calls another procedure.
RZ_GRAPH_NODE_SUBTYPE_CFG_RETURN = 1 << 2, ///< A return node of the procedure.
Expand All @@ -30,8 +35,15 @@ typedef enum {
RZ_GRAPH_NODE_SUBTYPE_CFG_ENTRY_CALL = RZ_GRAPH_NODE_SUBTYPE_CFG_ENTRY | RZ_GRAPH_NODE_SUBTYPE_CFG_CALL,
RZ_GRAPH_NODE_SUBTYPE_CFG_ENTRY_RETURN = RZ_GRAPH_NODE_SUBTYPE_CFG_ENTRY | RZ_GRAPH_NODE_SUBTYPE_CFG_RETURN,
RZ_GRAPH_NODE_SUBTYPE_CFG_ENTRY_EXIT = RZ_GRAPH_NODE_SUBTYPE_CFG_ENTRY | RZ_GRAPH_NODE_SUBTYPE_CFG_EXIT,
RZ_GRAPH_NODE_SUBTYPE_ICFG_MALLOC = 1 << 5, ///< Node represents a memory allocating procedure.
} RzGraphNodeSubType;
} RzGraphNodeCFGSubType;

typedef enum {
RZ_GRAPH_NODE_SUBTYPE_CFG_IWORD_NONE = 0, ///< No details given to this node.
RZ_GRAPH_NODE_SUBTYPE_CFG_IWORD_ENTRY = 1 << 0, ///< Entry node of the procedure CFG with iwords
RZ_GRAPH_NODE_SUBTYPE_CFG_IWORD_RETURN = 1 << 2, ///< A return node of the procedure.
RZ_GRAPH_NODE_SUBTYPE_CFG_IWORD_COND = 1 << 3, ///< A conditional instruction word.
RZ_GRAPH_NODE_SUBTYPE_CFG_IWORD_ENTRY_RETURN = RZ_GRAPH_NODE_SUBTYPE_CFG_ENTRY | RZ_GRAPH_NODE_SUBTYPE_CFG_RETURN,
} RzGraphNodeCFGIWordSubType;

typedef struct {
char *title;
Expand All @@ -45,34 +57,32 @@ typedef struct {
ut64 offset;
} RzGraphNodeInfoDataDefault;

/**
* \brief Info struct for a CFG node with single instructions.
*/
typedef struct {
/**
* \brief Address of the node.
*/
ut64 address;
/**
* \brief Address of called procedure, if node is of type RZ_GRAPH_NODE_TYPE_CFG_CALL.
* It is set to UT64_MAX if invalid.
*/
ut64 call_address;
ut64 address; ///< Address of the node.
ut64 call_address; ///< Address of called procedure, if node is of type RZ_GRAPH_NODE_TYPE_CFG_CALL. It is set to UT64_MAX if invalid.
ut64 jump_address; ///< Address this instr. jumps to. It is set to UT64_MAX if invalid.
ut64 next; ///< Address of following instruction. It is set to UT64_MAX if it is a return instruction.
RzGraphNodeCFGSubType subtype; ///< Optional flags which describe the node further.
} RzGraphNodeInfoDataCFG;

/**
* \brief A node of a CFG with instruction words.
* Each instruction word can consist of multiiple instructions.
* So an instruction word node is an unification of all it's member instructions.
* So an instruction word node is an unification of all its member instructions.
*/
typedef struct {
ut64 address; ///< Address of the instruction word.
RzPVector /* RzGraphNodeInfoDataCFG * */ *insn; ///< Single instruction nodes.
RzPVector /* RzGraphNodeInfoDataCFG * */ *insn; ///< Single instruction node.
RzGraphNodeCFGIWordSubType subtype; ///< Optional flags which describe the node further.
} RzGraphNodeInfoDataCFGIWord;

typedef struct {
/**
* \brief Address of the node.
*/
ut64 address;
ut64 address; ///< Address of the node.
bool is_malloc; ///< Flag set if this node is a memory allocating function.
RzGraphNodeiCFGSubType subtype; ///< Optional flags which describe the node further.
} RzGraphNodeInfoDataICFG;

/**
Expand All @@ -81,11 +91,7 @@ typedef struct {
* Provides minimal information to draw something without output format specific details.
*/
typedef struct rz_analysis_graph_node_info_t {
/**
* \brief Optional flags which describe the node further.
*/
RzGraphNodeType type;
RzGraphNodeSubType subtype;
RzGraphNodeType type; ///< Node type. Determines which node info is set below.
union {
RzGraphNodeInfoDataDefault def;
RzGraphNodeInfoDataCFG cfg;
Expand All @@ -94,13 +100,14 @@ typedef struct rz_analysis_graph_node_info_t {
};
} RzGraphNodeInfo;

RZ_API RZ_OWN char *rz_graph_get_node_subtype_annotation(RzGraphNodeSubType subtype, bool utf8);
RZ_API RZ_OWN char *rz_graph_get_node_subtype_annotation_cfg(ut32 subtype, bool letter_abbr, bool utf8);
RZ_API RZ_OWN char *rz_graph_get_node_subtype_annotation_cfg_iword(RzGraphNodeCFGIWordSubType subtype, bool letter_abbr, bool utf8);
RZ_API RZ_OWN RzGraphNodeInfo *rz_graph_get_node_info_data(RZ_BORROW void *data);
RZ_API void rz_graph_free_node_info(RZ_NULLABLE void *ptr);
RZ_API RzGraphNodeInfo *rz_graph_create_node_info_default(const char *title, const char *body, ut64 offset);
RZ_API RzGraphNodeInfo *rz_graph_create_node_info_icfg(ut64 address, RzGraphNodeSubType subtype);
RZ_API RzGraphNodeInfo *rz_graph_create_node_info_cfg(ut64 address, ut64 call_target_addr, RzGraphNodeSubType subtype);
RZ_API RzGraphNodeInfo *rz_graph_create_node_info_cfg_iword(const RzAnalysisInsnWord *iword, RzGraphNodeSubType subtype);
RZ_API RzGraphNodeInfo *rz_graph_create_node_info_icfg(ut64 address, RzGraphNodeiCFGSubType subtype);
RZ_API RzGraphNodeInfo *rz_graph_create_node_info_cfg(ut64 address, ut64 call_target_addr, ut64 jump_target_addr, ut64 next, RzGraphNodeCFGSubType subtype);
RZ_API RzGraphNodeInfo *rz_graph_create_node_info_cfg_iword(const RzAnalysisInsnWord *iword, RzGraphNodeCFGIWordSubType subtype);
RZ_API RzGraphNode *rz_graph_add_node_info(RzGraph /*<RzGraphNodeInfo *>*/ *graph, const char *title, const char *body, ut64 offset);
RZ_API void rz_graph_node_info_data_cfg_iword_init(RZ_BORROW RzGraphNodeInfoDataCFGIWord *info);
RZ_API void rz_graph_node_info_data_cfg_iword_fini(RZ_NULLABLE RZ_OWN RzGraphNodeInfoDataCFGIWord *node_info);
Expand Down
Loading

0 comments on commit 6a81376

Please sign in to comment.