Rizin
unix-like reverse engineering framework and cli tools
path.c File Reference
#include <rz_util.h>
#include <rz_type.h>

Go to the source code of this file.

Functions

RZ_API RZ_OWN RzTypePathrz_type_path_new (RZ_BORROW RZ_NONNULL RzType *type, RZ_OWN RZ_NONNULL char *path)
 Creates a new instance of RzTypePath. More...
 
RZ_API void rz_type_path_free (RZ_NULLABLE RzTypePath *tpath)
 Frees the RzTypePath. More...
 
static st64 path_walker (const RzTypeDB *typedb, const char *path)
 
RZ_API st64 rz_type_offset_by_path (const RzTypeDB *typedb, RZ_NONNULL const char *path)
 Returns the offset of the member given path. More...
 
static bool structured_member_walker (const RzTypeDB *typedb, RzList *list, RzType *parent, RzType *type, char *path, ut64 offset)
 
RZ_API RZ_OWN RzListrz_type_path_by_offset (const RzTypeDB *typedb, RzBaseType *btype, ut64 offset)
 Returns the list of all type paths matching the offset. More...
 
RZ_API RZ_OWN RzListrz_type_db_get_by_offset (const RzTypeDB *typedb, ut64 offset)
 Returns the list of all structured types that have members matching the offset. More...
 
RZ_API ut64 rz_type_db_struct_member_packed_offset (RZ_NONNULL const RzTypeDB *typedb, RZ_NONNULL const char *name, RZ_NONNULL const char *member)
 Returns the packed offset in bits of the structure member if there is a match. More...
 
RZ_API ut64 rz_type_db_struct_member_offset (RZ_NONNULL const RzTypeDB *typedb, RZ_NONNULL const char *name, RZ_NONNULL const char *member)
 Returns the offset in bytes of the structure member if there is a match. More...
 

Function Documentation

◆ path_walker()

static st64 path_walker ( const RzTypeDB typedb,
const char *  path 
)
static

Definition at line 39 of file path.c.

39  {
40  rz_return_val_if_fail(typedb && path, -1);
41  const char *member;
42  size_t membsize;
43  ut64 index;
44  st64 offset = 0;
45  RzType *parent = NULL;
46  const char *path_begin = path;
47  while (*path) {
48  switch (*path++) {
49  case '\0':
50  break;
51  case '[':
52  member = path;
53  index = (ut64)strtoull(member, (char **)&path, 10);
54  if (member == path || *path != ']') {
55  eprintf("Type path: expected ] (\"%s\")", path - 1);
56  return -1;
57  }
58  ++path;
59  if (!parent || parent->kind != RZ_TYPE_KIND_ARRAY) {
60  return -1;
61  }
62  offset += rz_type_db_get_bitsize(typedb, parent) * index;
63  break;
64  case '.':
65  member = path;
66  for (membsize = 0; member[membsize]; ++membsize) {
67  if (strchr(".[", member[membsize])) {
68  break;
69  }
70  }
71  if (membsize == 0) {
72  eprintf("Type path: expected member (\"%s\")", path - 1);
73  return -1;
74  }
75  if (!parent) {
76  if (member <= path) {
77  return -1;
78  }
79  size_t typenamesize = member - path_begin;
80  char *typename = malloc(typenamesize + 1);
81  if (!typename) {
82  return -1;
83  }
84  strncpy(typename, path_begin, typenamesize);
85  typename[typenamesize] = '\0';
86  parent = rz_type_identifier_of_base_type_str(typedb, typename);
87  free(typename);
88  if (!parent) {
89  return -1;
90  }
91  } else {
92  if (parent->kind != RZ_TYPE_KIND_IDENTIFIER) {
93  return -1;
94  }
96  return -1;
97  }
98  }
99  offset += rz_type_db_struct_member_packed_offset(typedb, parent->identifier.name, member);
100  path = member + membsize;
101  break;
102  default:
103  eprintf("Type path: unexpected char (\"%s\")", path - 1);
104  return -1;
105  }
106  }
107  return offset;
108 }
#define NULL
Definition: cris-opc.c:27
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
RZ_API RZ_OWN RzType * rz_type_identifier_of_base_type_str(const RzTypeDB *typedb, RZ_NONNULL const char *name)
Creates a new RzType indentifier from the given RzBaseType name.
Definition: helpers.c:47
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
void * malloc(size_t size)
Definition: malloc.c:123
#define eprintf(x, y...)
Definition: rlcc.c:7
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
@ RZ_TYPE_IDENTIFIER_KIND_STRUCT
Definition: rz_type.h:136
@ RZ_TYPE_IDENTIFIER_KIND_UNION
Definition: rz_type.h:137
@ RZ_TYPE_KIND_ARRAY
Definition: rz_type.h:130
@ RZ_TYPE_KIND_IDENTIFIER
Definition: rz_type.h:128
#define st64
Definition: rz_types_base.h:10
RzTypeKind kind
Definition: rz_type.h:155
struct rz_type_t::@292::@294 identifier
RZ_API ut64 rz_type_db_struct_member_packed_offset(RZ_NONNULL const RzTypeDB *typedb, RZ_NONNULL const char *name, RZ_NONNULL const char *member)
Returns the packed offset in bits of the structure member if there is a match.
Definition: path.c:244
RZ_API ut64 rz_type_db_get_bitsize(const RzTypeDB *typedb, RZ_NONNULL RzType *type)
Returns the type size in bits (target dependent)
Definition: type.c:779
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References eprintf, free(), rz_type_t::identifier, rz_type_t::kind, malloc(), NULL, path, rz_return_val_if_fail, rz_type_db_get_bitsize(), rz_type_db_struct_member_packed_offset(), RZ_TYPE_IDENTIFIER_KIND_STRUCT, RZ_TYPE_IDENTIFIER_KIND_UNION, rz_type_identifier_of_base_type_str(), RZ_TYPE_KIND_ARRAY, RZ_TYPE_KIND_IDENTIFIER, st64, and ut64().

Referenced by rz_type_offset_by_path().

◆ rz_type_db_get_by_offset()

RZ_API RZ_OWN RzList* rz_type_db_get_by_offset ( const RzTypeDB typedb,
ut64  offset 
)

Returns the list of all structured types that have members matching the offset.

Parameters
typedbTypes Database instance
offsetThe offset of the member to match against

Definition at line 219 of file path.c.

219  {
220  rz_return_val_if_fail(typedb, NULL);
223  RzListIter *iter;
224  RzBaseType *t;
225  rz_list_foreach (types, iter, t) {
227  RzList *list = rz_type_path_by_offset(typedb, t, offset);
228  if (list) {
229  rz_list_join(result, list);
230  }
231  }
232  }
234  return result;
235 }
RZ_API RZ_OWN RzList * rz_type_db_get_base_types(const RzTypeDB *typedb)
Returns the list of all basic types.
Definition: base.c:120
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API bool rz_list_join(RZ_NONNULL RzList *list1, RZ_NONNULL RzList *list2)
Joins 2 list into one (list2 pointer needs to be freed by the user)
Definition: list.c:209
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
insn_type_descr_t types[]
Definition: or1k_disas.c:7
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
@ RZ_BASE_TYPE_KIND_UNION
Definition: rz_type.h:74
@ RZ_BASE_TYPE_KIND_STRUCT
Definition: rz_type.h:73
RzBaseTypeKind kind
Definition: rz_type.h:115
RZ_API RZ_OWN RzList * rz_type_path_by_offset(const RzTypeDB *typedb, RzBaseType *btype, ut64 offset)
Returns the list of all type paths matching the offset.
Definition: path.c:176
RZ_API void rz_type_path_free(RZ_NULLABLE RzTypePath *tpath)
Frees the RzTypePath.
Definition: path.c:31

References rz_base_type_t::kind, list(), NULL, RZ_BASE_TYPE_KIND_STRUCT, RZ_BASE_TYPE_KIND_UNION, rz_list_free(), rz_list_join(), rz_list_newf(), rz_return_val_if_fail, rz_type_db_get_base_types(), rz_type_path_by_offset(), rz_type_path_free(), and types.

Referenced by rz_analysis_list_struct_offsets_handler(), and rz_core_analysis_hint_set_offset().

◆ rz_type_db_struct_member_offset()

RZ_API ut64 rz_type_db_struct_member_offset ( RZ_NONNULL const RzTypeDB typedb,
RZ_NONNULL const char *  name,
RZ_NONNULL const char *  member 
)

Returns the offset in bytes of the structure member if there is a match.

Parameters
typedbTypes Database instance
nameThe structure type name
nameThe structure member name

Definition at line 269 of file path.c.

269  {
270  rz_return_val_if_fail(typedb && name && member, 0);
271  RzBaseType *btype = rz_type_db_get_base_type(typedb, name);
272  if (!btype || btype->kind != RZ_BASE_TYPE_KIND_STRUCT) {
273  return 0;
274  }
275  RzTypeStructMember *memb;
276  rz_vector_foreach(&btype->struct_data.members, memb) {
277  if (!strcmp(memb->name, member)) {
278  return memb->offset;
279  }
280  }
281  return 0;
282 }
RZ_API RZ_BORROW RzBaseType * rz_type_db_get_base_type(const RzTypeDB *typedb, RZ_NONNULL const char *name)
Searches for the RzBaseType in the types database given the name.
Definition: base.c:57
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
Definition: z80asm.h:102
RzBaseTypeStruct struct_data
Definition: rz_type.h:118

References rz_base_type_t::kind, rz_base_type_struct_t::members, rz_type_struct_member_t::name, rz_type_struct_member_t::offset, RZ_BASE_TYPE_KIND_STRUCT, rz_return_val_if_fail, rz_type_db_get_base_type(), rz_vector_foreach, and rz_base_type_t::struct_data.

Referenced by rz_debug_dmp_init(), and winkd_build_profile().

◆ rz_type_db_struct_member_packed_offset()

RZ_API ut64 rz_type_db_struct_member_packed_offset ( RZ_NONNULL const RzTypeDB typedb,
RZ_NONNULL const char *  name,
RZ_NONNULL const char *  member 
)

Returns the packed offset in bits of the structure member if there is a match.

Parameters
typedbTypes Database instance
nameThe structure type name
nameThe structure member name

Definition at line 244 of file path.c.

244  {
245  rz_return_val_if_fail(typedb && name && member, 0);
246  RzBaseType *btype = rz_type_db_get_base_type(typedb, name);
247  if (!btype || btype->kind != RZ_BASE_TYPE_KIND_STRUCT) {
248  return 0;
249  }
250  RzTypeStructMember *memb;
251  ut64 result = 0;
252  rz_vector_foreach(&btype->struct_data.members, memb) {
253  if (!strcmp(memb->name, member)) {
254  return result;
255  break;
256  }
257  result += rz_type_db_get_bitsize(typedb, memb->type);
258  }
259  return result;
260 }

References rz_base_type_t::kind, rz_base_type_struct_t::members, rz_type_struct_member_t::name, RZ_BASE_TYPE_KIND_STRUCT, rz_return_val_if_fail, rz_type_db_get_base_type(), rz_type_db_get_bitsize(), rz_vector_foreach, rz_base_type_t::struct_data, rz_type_struct_member_t::type, and ut64().

Referenced by path_walker().

◆ rz_type_offset_by_path()

RZ_API st64 rz_type_offset_by_path ( const RzTypeDB typedb,
RZ_NONNULL const char *  path 
)

Returns the offset of the member given path.

Resolves the path in the form of "a.b[20].c" where "b" is a member of "a" and "c" is a member of "b" array and located inside the 20-th element, and calculates the offset. Opposite function of "rz_type_path_by_offset"

Parameters
typeRzTypePath

Definition at line 120 of file path.c.

120  {
121  rz_return_val_if_fail(typedb && path, -1);
122  return path_walker(typedb, path);
123 }
static st64 path_walker(const RzTypeDB *typedb, const char *path)
Definition: path.c:39

References path, path_walker(), and rz_return_val_if_fail.

◆ rz_type_path_by_offset()

RZ_API RZ_OWN RzList* rz_type_path_by_offset ( const RzTypeDB typedb,
RzBaseType btype,
ut64  offset 
)

Returns the list of all type paths matching the offset.

Parameters
typedbTypes Database instance
btypeThe base type
offsetThe offset of the path to match against

Definition at line 176 of file path.c.

176  {
178  if (btype->kind == RZ_BASE_TYPE_KIND_STRUCT) {
179  RzType *t = rz_type_identifier_of_base_type(typedb, btype, false);
180  RzTypeStructMember *memb;
181  ut64 memb_offset = 0;
182  rz_vector_foreach(&btype->struct_data.members, memb) {
183  if (memb_offset == offset) {
184  RzTypePath *tpath = rz_type_path_new(t, rz_str_newf("%s.%s", btype->name, memb->name));
185  if (tpath) {
186  rz_list_append(list, tpath);
187  }
188  }
189  // We go into the nested structures/unions if they are members of the structure
190  char *path = rz_str_newf("%s.%s", btype->name, memb->name);
191  structured_member_walker(typedb, list, t, memb->type, path, memb_offset + offset);
192  memb_offset += rz_type_db_get_bitsize(typedb, memb->type) / 8;
193  free(path);
194  }
195  } else if (btype->kind == RZ_BASE_TYPE_KIND_UNION) {
196  // This function makes sense only for structures since union
197  // members have exact same offset
198  // But if the union has compound members, e.g. structures, their
199  // internal offsets can be different
200  RzType *t = rz_type_identifier_of_base_type(typedb, btype, false);
201  RzTypeUnionMember *memb;
202  rz_vector_foreach(&btype->union_data.members, memb) {
203  char *path = rz_str_newf("%s.%s", btype->name, memb->name);
204  structured_member_walker(typedb, list, t, memb->type, path, offset);
205  free(path);
206  }
207  } else {
209  }
210  return list;
211 }
RZ_API RZ_OWN RzType * rz_type_identifier_of_base_type(const RzTypeDB *typedb, RZ_NONNULL const RzBaseType *btype, bool is_const)
Creates a new RzType indentifier from the given RzBaseType.
Definition: helpers.c:15
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
#define rz_warn_if_reached()
Definition: rz_assert.h:29
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
char * name
Definition: rz_type.h:112
RzBaseTypeUnion union_data
Definition: rz_type.h:120
RzVector members
Definition: rz_type.h:104
static bool structured_member_walker(const RzTypeDB *typedb, RzList *list, RzType *parent, RzType *type, char *path, ut64 offset)
Definition: path.c:126
RZ_API RZ_OWN RzTypePath * rz_type_path_new(RZ_BORROW RZ_NONNULL RzType *type, RZ_OWN RZ_NONNULL char *path)
Creates a new instance of RzTypePath.
Definition: path.c:13

References free(), rz_base_type_t::kind, list(), rz_base_type_struct_t::members, rz_base_type_union_t::members, rz_type_struct_member_t::name, rz_type_union_member_t::name, rz_base_type_t::name, path, RZ_BASE_TYPE_KIND_STRUCT, RZ_BASE_TYPE_KIND_UNION, rz_list_append(), rz_list_newf(), rz_str_newf(), rz_type_db_get_bitsize(), rz_type_identifier_of_base_type(), rz_type_path_free(), rz_type_path_new(), rz_vector_foreach, rz_warn_if_reached, rz_base_type_t::struct_data, structured_member_walker(), rz_type_struct_member_t::type, rz_type_union_member_t::type, rz_base_type_t::union_data, and ut64().

Referenced by rz_type_db_get_by_offset(), type_paths_collect_by_address_cb(), and type_paths_collect_by_offset_cb().

◆ rz_type_path_free()

RZ_API void rz_type_path_free ( RZ_NULLABLE RzTypePath tpath)

Frees the RzTypePath.

Doesn't free the underlying RzBaseType, only the path.

Parameters
typeRzTypePath

Definition at line 31 of file path.c.

31  {
32  if (!tpath) {
33  return;
34  }
35  free(tpath->path);
36  free(tpath);
37 }

References free().

Referenced by rz_type_db_get_by_offset(), and rz_type_path_by_offset().

◆ rz_type_path_new()

RZ_API RZ_OWN RzTypePath* rz_type_path_new ( RZ_BORROW RZ_NONNULL RzType type,
RZ_OWN RZ_NONNULL char *  path 
)

Creates a new instance of RzTypePath.

Parameters
typeRzType pointer
pathString representation of type path

Definition at line 13 of file path.c.

13  {
15  RzTypePath *tpath = RZ_NEW0(RzTypePath);
16  if (!tpath) {
17  return NULL;
18  }
19  tpath->typ = type;
20  tpath->path = path;
21  return tpath;
22 }
int type
Definition: mipsasm.c:17
#define RZ_NEW0(x)
Definition: rz_types.h:284
RzType * typ
Definition: rz_type.h:175
char * path
Definition: rz_type.h:176

References NULL, rz_type_path_t::path, path, RZ_NEW0, rz_return_val_if_fail, rz_type_path_t::typ, and type.

Referenced by rz_type_path_by_offset(), and structured_member_walker().

◆ structured_member_walker()

static bool structured_member_walker ( const RzTypeDB typedb,
RzList list,
RzType parent,
RzType type,
char *  path,
ut64  offset 
)
static

Definition at line 126 of file path.c.

126  {
127  rz_return_val_if_fail(list && type, false);
128  if (type->kind != RZ_TYPE_KIND_IDENTIFIER) {
129  return false;
130  }
131  rz_return_val_if_fail(type->identifier.name, false);
132  bool result = true;
133  if (type->identifier.kind == RZ_TYPE_IDENTIFIER_KIND_STRUCT) {
134  // Get the base type
135  RzBaseType *btype = rz_type_db_get_base_type(typedb, type->identifier.name);
136  if (!btype) {
137  return false;
138  }
139  RzTypeStructMember *memb;
140  ut64 memb_offset = 0;
141  rz_vector_foreach(&btype->struct_data.members, memb) {
142  if (memb_offset == offset) {
143  RzTypePath *tpath = rz_type_path_new(parent, rz_str_newf("%s.%s.%s", path, btype->name, memb->name));
144  if (tpath) {
145  rz_list_append(list, tpath);
146  }
147  }
148  char *newpath = rz_str_newf("%s.%s", path, memb->name);
149  result &= structured_member_walker(typedb, list, parent, memb->type, newpath, memb_offset + offset);
150  memb_offset += rz_type_db_get_bitsize(typedb, memb->type) / 8;
151  free(newpath);
152  }
153  } else if (type->identifier.kind == RZ_TYPE_IDENTIFIER_KIND_UNION) {
154  // Get the base type
155  RzBaseType *btype = rz_type_db_get_base_type(typedb, type->identifier.name);
156  if (!btype) {
157  return false;
158  }
159  RzTypeUnionMember *memb;
160  rz_vector_foreach(&btype->union_data.members, memb) {
161  char *newpath = rz_str_newf("%s.%s", path, memb->name);
162  result &= structured_member_walker(typedb, list, parent, memb->type, path, offset);
163  free(newpath);
164  }
165  }
166  return result;
167 }

References free(), list(), rz_base_type_struct_t::members, rz_base_type_union_t::members, rz_type_struct_member_t::name, rz_type_union_member_t::name, rz_base_type_t::name, path, rz_list_append(), rz_return_val_if_fail, rz_str_newf(), rz_type_db_get_base_type(), rz_type_db_get_bitsize(), RZ_TYPE_IDENTIFIER_KIND_STRUCT, RZ_TYPE_IDENTIFIER_KIND_UNION, RZ_TYPE_KIND_IDENTIFIER, rz_type_path_new(), rz_vector_foreach, rz_base_type_t::struct_data, type, rz_type_struct_member_t::type, rz_type_union_member_t::type, rz_base_type_t::union_data, and ut64().

Referenced by rz_type_path_by_offset().