1 #include <r_bin.h>
2 #include <r_core.h>
3 #include <r_anal.h>
4 #include "../bin/pdb/types.h"
5 #include "base_types.h"
6
is_parsable_type(const ELeafType type)7 static bool is_parsable_type(const ELeafType type) {
8 return (type == eLF_STRUCTURE ||
9 type == eLF_UNION ||
10 type == eLF_ENUM ||
11 type == eLF_CLASS);
12 }
13
14 /**
15 * @brief Create a type name from offset
16 *
17 * @param offset
18 * @return char* Name or NULL if error
19 */
create_type_name_from_offset(ut64 offset)20 static char *create_type_name_from_offset(ut64 offset) {
21 int offset_length = snprintf (NULL, 0, "type_0x%" PFMT64x, offset);
22 char *str = malloc (offset_length + 1);
23 snprintf (str, offset_length + 1, "type_0x%" PFMT64x, offset);
24 return str;
25 }
26
27 /**
28 * @brief Parses class/struct/union member
29 *
30 * @param type_info Current type info (member)
31 * @param types List of all types
32 * @return RAnalStructMember* parsed member, NULL if fail
33 */
parse_member(STypeInfo * type_info,RList * types)34 static RAnalStructMember *parse_member(STypeInfo *type_info, RList *types) {
35 r_return_val_if_fail (type_info && types, NULL);
36 if (type_info->leaf_type != eLF_MEMBER) {
37 return NULL;
38 }
39 r_return_val_if_fail (type_info->get_name &&
40 type_info->get_print_type && type_info->get_val, NULL);
41 char *name = NULL;
42 char *type = NULL;
43 int offset = 0;
44
45 type_info->get_val (type_info, &offset); // gets offset
46 type_info->get_name (type_info, &name);
47 type_info->get_print_type (type_info, &type);
48 RAnalStructMember *member = R_NEW0 (RAnalStructMember);
49 if (!member) {
50 goto cleanup;
51 }
52 char *sname = r_str_sanitize_sdb_key (name);
53 member->name = sname;
54 member->type = strdup (type); // we assume it's sanitized
55 member->offset = offset;
56 return member;
57 cleanup:
58 return NULL;
59 }
60
61 /**
62 * @brief Parse enum case
63 *
64 * @param type_info Current type info (enum case)
65 * @param types List of all types
66 * @return RAnalEnumCase* parsed enum case, NULL if fail
67 */
parse_enumerate(STypeInfo * type_info,RList * types)68 static RAnalEnumCase *parse_enumerate(STypeInfo *type_info, RList *types) {
69 r_return_val_if_fail (type_info && types && type_info->leaf_type == eLF_ENUMERATE, NULL);
70 r_return_val_if_fail (type_info->get_val && type_info->get_name, NULL);
71
72 char *name = NULL;
73 int value = 0;
74 // sometimes, the type doesn't have get_val for some reason
75 type_info->get_val (type_info, &value);
76 type_info->get_name (type_info, &name);
77 RAnalEnumCase *cas = R_NEW0 (RAnalEnumCase);
78 if (!cas) {
79 goto cleanup;
80 }
81 char *sname = r_str_sanitize_sdb_key (name);
82 cas->name = sname;
83 cas->val = value;
84 return cas;
85 cleanup:
86 return NULL;
87 }
88
89 /**
90 * @brief Parses enum into BaseType and saves it into SDB
91 *
92 * @param anal
93 * @param type Current type
94 * @param types List of all types
95 */
parse_enum(const RAnal * anal,SType * type,RList * types)96 static void parse_enum(const RAnal *anal, SType *type, RList *types) {
97 r_return_if_fail (anal && type && types);
98 STypeInfo *type_info = &type->type_data;
99 // assert all member functions we need info from
100 r_return_if_fail (type_info->get_members &&
101 type_info->get_name &&
102 type_info->get_utype);
103
104 RAnalBaseType *base_type = r_anal_base_type_new (R_ANAL_BASE_TYPE_KIND_ENUM);
105 if (!base_type) {
106 return;
107 }
108
109 char *name = NULL;
110 type_info->get_name (type_info, &name);
111 bool to_free_name = false;
112 if (!name) {
113 name = create_type_name_from_offset (type->tpi_idx);
114 to_free_name = true;
115 }
116 type_info->get_utype (type_info, (void **)&type);
117 int size = 0;
118 char *type_name = NULL;
119 if (type && type->type_data.type_info) {
120 SLF_SIMPLE_TYPE *base_type = type->type_data.type_info;
121 type_name = base_type->type;
122 size = base_type->size;
123 }
124 RList *members;
125 type_info->get_members (type_info, &members);
126
127 RListIter *it = r_list_iterator (members);
128 while (r_list_iter_next (it)) {
129 STypeInfo *member_info = r_list_iter_get (it);
130 RAnalEnumCase *enum_case = parse_enumerate (member_info, types);
131 if (!enum_case) {
132 continue; // skip it, move forward
133 }
134 void *element = r_vector_push (&base_type->struct_data.members, enum_case);
135 if (!element) {
136 goto cleanup;
137 }
138 }
139 char *sname = r_str_sanitize_sdb_key (name);
140 base_type->name = sname;
141 base_type->size = size;
142 base_type->type = strdup (type_name); // we assume it's sanitized
143
144 r_anal_save_base_type (anal, base_type);
145 cleanup:
146 if (to_free_name) {
147 R_FREE (name);
148 }
149 r_anal_base_type_free (base_type);
150 return;
151 }
152
153 /**
154 * @brief Parses classes, unions and structures into BaseType and saves them into SDB
155 *
156 * @param anal
157 * @param type Current type
158 * @param types List of all types
159 */
parse_structure(const RAnal * anal,SType * type,RList * types)160 static void parse_structure(const RAnal *anal, SType *type, RList *types) {
161 r_return_if_fail (anal && type && types);
162 STypeInfo *type_info = &type->type_data;
163 // assert all member functions we need info from
164 r_return_if_fail (type_info->get_members &&
165 type_info->is_fwdref &&
166 type_info->get_name &&
167 type_info->get_val);
168
169 RAnalBaseType *base_type = r_anal_base_type_new (R_ANAL_BASE_TYPE_KIND_STRUCT);
170 if (!base_type) {
171 return;
172 }
173
174 char *name = NULL;
175 type_info->get_name (type_info, &name);
176 bool to_free_name = false;
177 if (!name) {
178 name = create_type_name_from_offset (type->tpi_idx);
179 to_free_name = true;
180 }
181 int size;
182 type_info->get_val (type_info, &size); // gets size
183
184 RList *members;
185 type_info->get_members (type_info, &members);
186
187 RListIter *it = r_list_iterator (members);
188 while (r_list_iter_next (it)) {
189 STypeInfo *member_info = r_list_iter_get (it);
190 RAnalStructMember *struct_member = parse_member (member_info, types);
191 if (!struct_member) {
192 continue; // skip the failure
193 }
194 void *element = r_vector_push (&base_type->struct_data.members, struct_member);
195 if (!element) {
196 goto cleanup;
197 }
198 }
199 if (type_info->leaf_type == eLF_STRUCTURE || type_info->leaf_type == eLF_CLASS) {
200 base_type->kind = R_ANAL_BASE_TYPE_KIND_STRUCT;
201 } else { // union
202 base_type->kind = R_ANAL_BASE_TYPE_KIND_UNION;
203 }
204 char *sname = r_str_sanitize_sdb_key (name);
205 base_type->name = sname;
206 base_type->size = size;
207 r_anal_save_base_type (anal, base_type);
208 cleanup:
209 if (to_free_name) {
210 R_FREE (name);
211 }
212 r_anal_base_type_free (base_type);
213 return;
214 }
215
216 /**
217 * @brief Delegate the type parsing to appropriate function
218 *
219 * @param anal
220 * @param type Current type
221 * @param types List of all types
222 */
parse_type(const RAnal * anal,SType * type,RList * types)223 static void parse_type (const RAnal *anal, SType *type, RList *types) {
224 r_return_if_fail (anal && type && types);
225
226 int is_forward_decl;
227 if (type->type_data.is_fwdref) {
228 type->type_data.is_fwdref (&type->type_data, &is_forward_decl);
229 if (is_forward_decl) { // we skip those, atleast for now
230 return;
231 }
232 }
233 switch (type->type_data.leaf_type) {
234 case eLF_CLASS:
235 case eLF_STRUCTURE:
236 case eLF_UNION:
237 parse_structure (anal, type, types);
238 break;
239 case eLF_ENUM:
240 parse_enum (anal, type, types);
241 break;
242 default:
243 // shouldn't happen, happens when someone modifies leafs that get here
244 // but not how they should be parsed
245 eprintf ("Unknown type record");
246 break;
247 }
248 }
249
250 /**
251 * @brief Saves PDB types from TPI stream into the SDB
252 *
253 * @param anal
254 * @param pdb PDB information
255 */
r_parse_pdb_types(const RAnal * anal,const RPdb * pdb)256 R_API void r_parse_pdb_types(const RAnal *anal, const RPdb *pdb) {
257 r_return_if_fail (anal && pdb);
258 RList *plist = pdb->pdb_streams;
259 // getting the TPI stream from the streams list
260 STpiStream *tpi_stream = r_list_get_n (plist, ePDB_STREAM_TPI);
261 if (!tpi_stream) { // no TPI stream found
262 return;
263 }
264 // Types should be DAC - only references previous records
265 RListIter *iter = r_list_iterator (tpi_stream->types);
266 while (r_list_iter_next (iter)) { // iterate all types
267 SType *type = r_list_iter_get (iter);
268 if (type && is_parsable_type (type->type_data.leaf_type)) {
269 parse_type (anal, type, tpi_stream->types);
270 }
271 }
272 }
273