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