1 #include "omf.h"
2 
is_valid_omf_type(ut8 type)3 static bool is_valid_omf_type(ut8 type) {
4 	int ct = 0;
5 	ut8 types[] = {
6 		OMF_THEADR, OMF_LHEADR, OMF_COMENT, OMF_MODEND, OMF_MODEND32,
7 		OMF_EXTDEF, OMF_PUBDEF, OMF_PUBDEF32, OMF_LINNUM,
8 		OMF_LINNUM32, OMF_LNAMES, OMF_LNAMES, OMF_SEGDEF,
9 		OMF_SEGDEF32, OMF_GRPDEF, OMF_FIXUPP, OMF_FIXUPP32,
10 		OMF_LEDATA, OMF_LEDATA32, OMF_LIDATA, OMF_LIDATA32,
11 		OMF_COMDEF, OMF_BAKPAT, OMF_BAKPAT32, OMF_LEXTDEF,
12 		OMF_LPUBDEF, OMF_LPUBDEF32, OMF_LCOMDEF, OMF_CEXTDEF,
13 		OMF_COMDAT, OMF_COMDAT32, OMF_LINSYM, OMF_LINSYM32,
14 		OMF_ALIAS, OMF_NBKPAT, OMF_NBKPAT32, OMF_LLNAMES, OMF_VERNUM,
15 		OMF_VENDEXT, 0};
16 	for (; types[ct]; ct++) {
17 		if (type == types[ct]) {
18 			return true;
19 		}
20 	}
21 	// eprintf ("Invalid record type\n");
22 	return false;
23 }
24 
r_bin_checksum_omf_ok(const ut8 * buf,ut64 buf_size)25 bool r_bin_checksum_omf_ok(const ut8 *buf, ut64 buf_size) {
26 	ut16 size;
27 	ut8 checksum = 0;
28 
29 	if (buf_size < 3) {
30 		eprintf ("Invalid record (too short)\n");
31 		return false;
32 	}
33 	size = ut8p_bw (buf + 1);
34 	if (buf_size < size + 3) {
35 		eprintf ("Invalid record (too short)\n");
36 		return false;
37 	}
38 	//Some compiler set checksum to 0
39 	if (!buf[size + 2]) {
40 		return true;
41 	}
42 	size += 3;
43 	for (; size; size--) {
44 		if (buf_size < size) {
45 			eprintf ("Invalid record (too short)\n");
46 			return false;
47 		}
48 		checksum += buf[size - 1];
49 	}
50 	if (checksum) {
51 		// eprintf ("Invalid record checksum\n");
52 	}
53 	return !checksum ? true : false;
54 }
55 
omf_get_idx(const ut8 * buf,int buf_size)56 static ut16 omf_get_idx(const ut8 *buf, int buf_size) {
57 	if (buf_size < 2) {
58 		return 0;
59 	}
60 	if (*buf & 0x80) {
61 		return (ut16)((*buf & 0x7f) * 0x100 + buf[1]);
62 	}
63 	return *buf;
64 }
65 
free_lname(OMF_multi_datas * lname)66 static void free_lname(OMF_multi_datas *lname) {
67 	ut32 ct = 0;
68 
69 	while (ct < lname->nb_elem) {
70 		R_FREE (((char **)lname->elems)[ct]);
71 		ct++;
72 	}
73 	R_FREE (lname->elems);
74 	R_FREE (lname);
75 }
76 
load_omf_lnames(OMF_record * record,const ut8 * buf,ut64 buf_size)77 static bool load_omf_lnames(OMF_record *record, const ut8 *buf, ut64 buf_size) {
78 	ut32 tmp_size = 0;
79 	ut32 ct_name = 0;
80 	OMF_multi_datas *ret = NULL;
81 	char **names;
82 	if (!record || !buf) {
83 		return false;
84 	}
85 
86 	if (!(ret = R_NEW0 (OMF_multi_datas))) {
87 		return false;
88 	}
89 	record->content = ret;
90 
91 	while ((int)tmp_size < (int)(record->size - 1)) {
92 		int next;
93 		ret->nb_elem++;
94 		next = buf[3 + tmp_size] + 1;
95 		if (next < 1) {
96 			break;
97 		}
98 		tmp_size += next;
99 	}
100 	if (!(ret->elems = R_NEWS0 (char *, ret->nb_elem + 1))) {
101 		R_FREE (ret);
102 		return false;
103 	}
104 	names = (char **)ret->elems;
105 	tmp_size = 0;
106 	while ((int)tmp_size < (int)(record->size - 1)) {
107 		if (ct_name >= ret->nb_elem) {
108 			eprintf ("load_omf_lnames: prevent overflow\n");
109 			break;
110 		}
111 		// sometimes there is a name with a null size so we just skip it
112 		char cb = buf[3 + tmp_size];
113 		if (cb < 1) {
114 			names[ct_name++] = NULL;
115 			tmp_size++;
116 			continue;
117 		}
118 		if (record->size + 3 < tmp_size + cb) {
119 			eprintf ("Invalid Lnames record (bad size)\n");
120 			free (ret);
121 			return false;
122 		}
123 		if (!(names[ct_name] = R_NEWS0 (char, cb + 1))) {
124 			free_lname (ret);
125 			return false;
126 		}
127 		if ((tmp_size + 4 + cb) < buf_size) {
128 			memcpy (names[ct_name], buf + 3 + tmp_size + 1, cb);
129 		}
130 		ct_name++;
131 		tmp_size += cb + 1; //buf[3 + tmp_size] + 1;
132 	}
133 	return true;
134 }
135 
load_omf_segdef(OMF_record * record,const ut8 * buf,ut64 buf_size)136 static int load_omf_segdef(OMF_record *record, const ut8 *buf, ut64 buf_size) {
137 	OMF_segment *ret = NULL;
138 	int off_add;
139 
140 	if (!(ret = R_NEW0 (OMF_segment))) {
141 		return false;
142 	}
143 	record->content = ret;
144 
145 	if (record->size < 2) {
146 		eprintf ("Invalid Segdef record (bad size)\n");
147 		return false;
148 	}
149 	off_add = buf[3] & 0xe ? 0 : 3;
150 
151 	if (record->type == OMF_SEGDEF32) {
152 		if (record->size < 5 + off_add) {
153 			eprintf ("Invalid Segdef record (bad size)\n");
154 			return false;
155 		}
156 		ret->name_idx = omf_get_idx (buf + 8 + off_add, buf_size - 8 - off_add);
157 		if (buf[3] & 2) {
158 			ret->size = UT32_MAX;
159 		} else {
160 			ret->size = r_read_le32 (buf + 4 + off_add);
161 		}
162 	} else {
163 		if (record->size < 3 + off_add) {
164 			eprintf ("Invalid Segdef record (bad size)\n");
165 			return false;
166 		}
167 		ret->name_idx = omf_get_idx (buf + 6 + off_add, buf_size - 6 - off_add);
168 		if (buf[3] & 2) {
169 			ret->size = UT16_MAX;
170 		}
171 		ret->size = r_read_le16 (buf + 4 + off_add);
172 	}
173 
174 	ret->bits = (buf[3] & 1)? 32: 16;
175 
176 	// tricks to keep the save index when copying content from record
177 	record->type = OMF_SEGDEF;
178 
179 	return true;
180 }
181 
omf_count_symb(ut16 total_size,ut32 ct,const ut8 * buf,int bits)182 static ut32 omf_count_symb(ut16 total_size, ut32 ct, const ut8 *buf, int bits) {
183 	ut32 nb_symb = 0;
184 	while (ct < total_size - 1) {
185 		ct += buf[ct] + 1 + (bits == 32 ? 4 : 2);
186 		if (ct > total_size - 1) {
187 			return nb_symb;
188 		}
189 		if (buf[ct] & 0x80) {
190 			ct += 2;
191 		} else {
192 			ct++;
193 		}
194 		nb_symb++;
195 	}
196 	return nb_symb;
197 }
198 
load_omf_symb(OMF_record * record,ut32 ct,const ut8 * buf,int buf_size,int bits,ut16 seg_idx)199 static int load_omf_symb(OMF_record *record, ut32 ct, const ut8 *buf, int buf_size, int bits, ut16 seg_idx) {
200 	ut32 nb_symb = 0;
201 	ut8 str_size = 0;
202 	OMF_symbol *symbol;
203 
204 	while (nb_symb < ((OMF_multi_datas *)record->content)->nb_elem) {
205 		symbol = ((OMF_symbol *)((OMF_multi_datas *)record->content)->elems) + nb_symb;
206 
207 		if (record->size - 1 < ct - 2) {
208 			eprintf ("Invalid Pubdef record (bad size)\n");
209 			return false;
210 		}
211 		str_size = buf[ct];
212 
213 		if (bits == 32) {
214 			if (ct + 1 + str_size + 4 - 3 > record->size) {
215 				eprintf ("Invalid Pubdef record (bad size)\n");
216 				return false;
217 			}
218 			symbol->offset = r_read_le32 (buf + ct + 1 + str_size);
219 		} else {
220 			if (ct + 1 + str_size + 2 - 3 > record->size) {
221 				eprintf ("Invalid Pubdef record (bad size)\n");
222 				return false;
223 			}
224 			symbol->offset = r_read_le16 (buf + ct + 1 + str_size);
225 		}
226 
227 		symbol->seg_idx = seg_idx;
228 
229 		if (!(symbol->name = R_NEWS0 (char, str_size + 1))) {
230 			return false;
231 		}
232 		symbol->name[str_size] = 0;
233 		memcpy (symbol->name, buf + ct + 1, sizeof(char) * str_size);
234 
235 		ct += 1 + str_size + (bits == 32 ? 4 : 2);
236 		if (ct >= buf_size) {
237 			return false;
238 		}
239 		if (buf[ct] & 0x80) { //type index
240 			ct += 2;
241 		} else {
242 			ct++;
243 		}
244 		nb_symb++;
245 	}
246 	return true;
247 }
248 
load_omf_pubdef(OMF_record * record,const ut8 * buf,int buf_size)249 static int load_omf_pubdef(OMF_record *record, const ut8 *buf, int buf_size) {
250 	OMF_multi_datas *ret = NULL;
251 	ut16 seg_idx;
252 	ut16 ct = 0;
253 	ut16 base_grp;
254 
255 	if (record->size < 2) {
256 		eprintf ("Invalid Pubdef record (bad size)\n");
257 		return false;
258 	}
259 
260 	ct = 3;
261 	base_grp = omf_get_idx (buf + ct, buf_size - ct);
262 	if (buf[ct] & 0x80) { // sizeof base groups index
263 		ct += 2;
264 	} else {
265 		ct++;
266 	}
267 
268 	if (record->size < ct - 2) {
269 		eprintf ("Invalid Pubdef record (bad size)\n");
270 		return false;
271 	}
272 
273 	seg_idx = omf_get_idx (buf + ct, buf_size - ct);
274 
275 	if (buf[ct] & 0x80) { // sizeof base segment index
276 		ct += 2;
277 	} else {
278 		ct++;
279 	}
280 
281 	if (!base_grp && !seg_idx) {
282 		ct += 2;
283 	}
284 	if (record->size < ct - 2) {
285 		eprintf ("Invalid Pubdef record (bad size)\n");
286 		return false;
287 	}
288 
289 	if(!(ret = R_NEW0 (OMF_multi_datas))) {
290 		return false;
291 	}
292 	record->content = ret;
293 
294 	if (!(record->type & 1)) { // 16 bit addr
295 		ret->nb_elem = omf_count_symb (record->size + 3, ct, buf, 16);
296 		if (ret->nb_elem > 0) {
297 			if (!(ret->elems = R_NEWS0 (OMF_symbol, ret->nb_elem))) {
298 				return false;
299 			}
300 		}
301 		if (!load_omf_symb (record, ct, buf, buf_size, 16, seg_idx)) {
302 			return false;
303 		}
304 	} else { // 32 bit addr
305 		ret->nb_elem = omf_count_symb (record->size + 3, ct, buf, 32);
306 		if (ret->nb_elem > 0) {
307 			if (!(ret->elems = R_NEWS0 (OMF_symbol, ret->nb_elem))) {
308 				return false;
309 			}
310 		}
311 		if (!load_omf_symb (record, ct, buf, buf_size, 32, seg_idx)) {
312 			return false;
313 		}
314 	}
315 
316 	// tricks to keep the save index when copying content from record
317 	record->type = OMF_PUBDEF;
318 	return true;
319 }
320 
load_omf_data(const ut8 * buf,int buf_size,OMF_record * record,ut64 global_ct)321 static int load_omf_data(const ut8 *buf, int buf_size, OMF_record *record, ut64 global_ct) {
322 	ut16 seg_idx;
323 	ut32 offset;
324 	ut16 ct = 4;
325 	OMF_data *ret;
326 
327 	if ((!(record->type & 1) && record->size < 4) || (record->size < 6)) {
328 		eprintf ("Invalid Ledata record (bad size)\n");
329 		return false;
330 	}
331 	seg_idx = omf_get_idx (buf + 3, buf_size - 3);
332 	if (seg_idx & 0xff00) {
333 		if ((!(record->type & 1) && record->size < 5) || (record->size < 7)) {
334 			eprintf ("Invalid Ledata record (bad size)\n");
335 			return false;
336 		}
337 		ct++;
338 	}
339 	if (record->type == OMF_LEDATA32) {
340 		offset = r_read_le32 (buf + ct);
341 		ct += 4;
342 	} else {
343 		offset = r_read_le16 (buf + ct);
344 		ct += 2;
345 	}
346 	if (!(ret = R_NEW0 (OMF_data))) {
347 		return false;
348 	}
349 	record->content = ret;
350 
351 	ret->size = record->size - 1 - (ct - 3);
352 	ret->paddr = global_ct + ct;
353 	ret->offset = offset;
354 	ret->seg_idx = seg_idx;
355 	ret->next = NULL;
356 	record->type = OMF_LEDATA;
357 
358 	return true;
359 }
360 
361 
load_omf_content(OMF_record * record,const ut8 * buf,ut64 global_ct,ut64 buf_size)362 static int load_omf_content(OMF_record *record, const ut8 *buf, ut64 global_ct, ut64 buf_size) {
363 	if (record->type == OMF_LNAMES) {
364 		return load_omf_lnames (record, buf, buf_size);
365 	}
366 	if (record->type == OMF_SEGDEF || record->type == OMF_SEGDEF32) {
367 		return load_omf_segdef (record, buf, buf_size);
368 	}
369 	if (record->type == OMF_PUBDEF || record->type == OMF_PUBDEF32 || record->type == OMF_LPUBDEF || record->type == OMF_LPUBDEF32) {
370 		return load_omf_pubdef (record, buf, buf_size);
371 	}
372 	if (record->type == OMF_LEDATA || record->type == OMF_LEDATA32) {
373 		return load_omf_data (buf, buf_size, record, global_ct);
374 	}
375 	// generic loader just copy data from buf to content
376 	if (!record->size) {
377 		eprintf("Invalid record (size to short)\n");
378 		return false;
379 	}
380 	if (!(record->content = R_NEWS0 (char, record->size))) {
381 		return false;
382 	}
383 	((char *)record->content)[record->size - 1] = 0;
384 	return true;
385 }
386 
load_record_omf(const ut8 * buf,ut64 global_ct,ut64 buf_size)387 static OMF_record_handler *load_record_omf(const ut8 *buf, ut64 global_ct, ut64 buf_size){
388 	OMF_record_handler *new = NULL;
389 
390 	if (is_valid_omf_type (*buf) && r_bin_checksum_omf_ok (buf, buf_size)) {
391 		if (!(new = R_NEW0 (OMF_record_handler))) {
392 			return NULL;
393 		}
394 		((OMF_record *)new)->type = *buf;
395 		((OMF_record *)new)->size = r_read_le16 (buf + 1);
396 
397 		// at least a record have a type a size and a checksum
398 		if (((OMF_record *)new)->size > buf_size - 3 || buf_size < 4) {
399 		  eprintf("Invalid record (too short)\n");
400 		  R_FREE(new);
401 		  return NULL;
402 		}
403 
404 		if (!(load_omf_content ((OMF_record *)new, buf, global_ct, buf_size))) {
405 		  R_FREE(new);
406 		  return NULL;
407 		}
408 		((OMF_record *)new)->checksum = buf[2 + ((OMF_record *)new)->size];
409 		new->next = NULL;
410 	}
411 	return new;
412 }
413 
load_all_omf_records(r_bin_omf_obj * obj,const ut8 * buf,ut64 size)414 static int load_all_omf_records(r_bin_omf_obj *obj, const ut8 *buf, ut64 size) {
415 	ut64 ct = 0;
416 	OMF_record_handler *new_rec = NULL;
417 	OMF_record_handler *tmp = NULL;
418 
419 	while (ct < size) {
420 		if (!(new_rec = load_record_omf (buf + ct, ct, size - ct))) {
421 			return false;
422 		}
423 
424 		// the order is important because some link are made by index
425 		if (!tmp) {
426 			obj->records = new_rec;
427 			tmp = obj->records;
428 		} else {
429 			tmp->next = new_rec;
430 			tmp = tmp->next;
431 		}
432 		ct += 3 + ((OMF_record *)tmp)->size;
433 	}
434 	return true;
435 }
436 
count_omf_record_type(r_bin_omf_obj * obj,ut8 type)437 static ut32 count_omf_record_type(r_bin_omf_obj *obj, ut8 type) {
438 	OMF_record_handler *tmp = obj->records;
439 	ut32 ct = 0;
440 
441 	while (tmp) {
442 		if (((OMF_record *)tmp)->type == type) {
443 			ct++;
444 		}
445 		tmp = tmp->next;
446 	}
447 	return ct;
448 }
449 
count_omf_multi_record_type(r_bin_omf_obj * obj,ut8 type)450 static ut32 count_omf_multi_record_type(r_bin_omf_obj *obj, ut8 type) {
451 	OMF_record_handler *tmp = obj->records;
452 	ut32 ct = 0;
453 
454 	while (tmp) {
455 		if (((OMF_record *)tmp)->type == type) {
456 			ct += ((OMF_multi_datas *)((OMF_record *)tmp)->content)->nb_elem;
457 		}
458 		tmp = tmp->next;
459 	}
460 	return ct;
461 }
462 
get_next_omf_record_type(OMF_record_handler * tmp,ut8 type)463 static OMF_record_handler *get_next_omf_record_type(OMF_record_handler *tmp, ut8 type) {
464 	while (tmp) {
465 		if (((OMF_record *)tmp)->type == type) {
466 			return (tmp);
467 		}
468 		tmp = tmp->next;
469 	}
470 	return NULL;
471 }
472 
cpy_omf_names(r_bin_omf_obj * obj)473 static int cpy_omf_names(r_bin_omf_obj *obj) {
474 	OMF_record_handler *tmp = obj->records;
475 	OMF_multi_datas	*lname;
476 	int ct_obj = 0;
477 	int ct_rec;
478 
479 	while ((tmp = get_next_omf_record_type(tmp, OMF_LNAMES))) {
480 		lname = (OMF_multi_datas *)((OMF_record *)tmp)->content;
481 
482 		ct_rec = -1;
483 		while (++ct_rec < lname->nb_elem) {
484 			if (!((char **)lname->elems)[ct_rec]) {
485 				obj->names[ct_obj++] = NULL;
486 			} else if (!(obj->names[ct_obj++] = strdup(((char **)lname->elems)[ct_rec]))) {
487 				return false;
488 			}
489 		}
490 		tmp = tmp->next;
491 	}
492 	return true;
493 }
494 
get_omf_section_info(r_bin_omf_obj * obj)495 static void get_omf_section_info(r_bin_omf_obj *obj) {
496 	OMF_record_handler *tmp = obj->records;
497 	ut32 ct_obj = 0;
498 
499 	while ((tmp = get_next_omf_record_type (tmp, OMF_SEGDEF))) {
500 		obj->sections[ct_obj] = ((OMF_record *)tmp)->content;
501 		((OMF_record *)tmp)->content = NULL;
502 
503 		if (!ct_obj) {
504 			obj->sections[ct_obj]->vaddr = 0;
505 		} else {
506 			obj->sections[ct_obj]->vaddr =  obj->sections[ct_obj - 1]->vaddr +
507 											obj->sections[ct_obj - 1]->size;
508 		}
509 		ct_obj++;
510 		tmp = tmp->next;
511 	 }
512 }
513 
get_omf_symbol_info(r_bin_omf_obj * obj)514 static int get_omf_symbol_info(r_bin_omf_obj *obj) {
515 	OMF_record_handler	*tmp = obj->records;
516 	OMF_multi_datas	*symbols;
517 	int ct_obj = 0;
518 	int			ct_rec = 0;
519 
520 	while ((tmp = get_next_omf_record_type(tmp, OMF_PUBDEF))) {
521 		symbols = (OMF_multi_datas *)((OMF_record *)tmp)->content;
522 
523 		ct_rec = -1;
524 		while (++ct_rec < symbols->nb_elem) {
525 			if (!(obj->symbols[ct_obj] = R_NEW0 (OMF_symbol))) {
526 				return false;
527 			}
528 			memcpy(obj->symbols[ct_obj], ((OMF_symbol *)symbols->elems) + ct_rec, sizeof(*(obj->symbols[ct_obj])));
529 			obj->symbols[ct_obj]->name = strdup(((OMF_symbol *)symbols->elems)[ct_rec].name);
530 			ct_obj++;
531 		 }
532 		tmp = tmp->next;
533 	 }
534 	return true;
535 }
536 
get_omf_data_info(r_bin_omf_obj * obj)537 static int get_omf_data_info(r_bin_omf_obj *obj) {
538 	OMF_record_handler *tmp = obj->records;
539 	OMF_data *tmp_data;
540 
541 	while ((tmp = get_next_omf_record_type (tmp, OMF_LEDATA))) {
542 		if (((OMF_data *)((OMF_record *)tmp)->content)->seg_idx - 1 >= obj->nb_section) {
543 			eprintf ("Invalid Ledata record (bad segment index)\n");
544 			return false;
545 		}
546 		OMF_segment *os = obj->sections[((OMF_data *)((OMF_record *)tmp)->content)->seg_idx - 1];
547 		if (os && (tmp_data = os->data)) {
548 			while (tmp_data->next) {
549 				tmp_data = tmp_data->next;
550 			}
551 			tmp_data->next = ((OMF_record *)tmp)->content;
552 		} else {
553 			obj->sections[((OMF_data *)((OMF_record *)tmp)->content)->seg_idx - 1]->data = ((OMF_record *)tmp)->content;
554 		}
555 		((OMF_record *)tmp)->content = NULL;
556 		tmp = tmp->next;
557 	}
558 	return true;
559 }
560 
get_omf_infos(r_bin_omf_obj * obj)561 static int get_omf_infos(r_bin_omf_obj *obj) {
562 	// get all name defined in lnames records
563 	obj->nb_name = count_omf_multi_record_type (obj, OMF_LNAMES);
564 	if (obj->nb_name>0) {
565 		if (!(obj->names = R_NEWS0 (char *, obj->nb_name))) {
566 			return false;
567 		}
568 		if (!cpy_omf_names (obj)) {
569 			return false;
570 		}
571 	}
572 	// get all sections (segdef record)
573 	obj->nb_section = count_omf_record_type (obj, OMF_SEGDEF);
574 	if (obj->nb_section>0) {
575 		if (!(obj->sections = R_NEWS0 (OMF_segment *, obj->nb_section))) {
576 			return false;
577 		}
578 		get_omf_section_info (obj);
579 	}
580 	// get all data (ledata record)
581 	get_omf_data_info (obj);
582 	// get all symbols (pubdef + lpubdef)
583 	obj->nb_symbol = count_omf_multi_record_type (obj, OMF_PUBDEF);
584 	if (obj->nb_symbol>0) {
585 		if (!(obj->symbols = R_NEWS0 (OMF_symbol *, obj->nb_symbol))) {
586 			return false;
587 		}
588 		if (!get_omf_symbol_info (obj)) {
589 			return false;
590 		}
591 	}
592 	return true;
593 }
594 
free_pubdef(OMF_multi_datas * datas)595 static void free_pubdef(OMF_multi_datas *datas) {
596 #if 0
597 	while (ct_rec < datas->nb_elem) {
598 		R_FREE (((OMF_symbol *)(datas->elems + ct_rec++))->name);
599 	}
600 #endif
601 	R_FREE (datas->elems);
602 	R_FREE (datas);
603 }
604 
free_all_omf_records(r_bin_omf_obj * obj)605 static void free_all_omf_records(r_bin_omf_obj *obj) {
606 	OMF_record_handler *tmp = NULL;
607 	OMF_record_handler *rec = obj->records;
608 
609 	while (rec) {
610 		if (((OMF_record *)rec)->type == OMF_LNAMES) {
611 			free_lname((OMF_multi_datas *)((OMF_record *)rec)->content);
612 		} else if (((OMF_record *)rec)->type == OMF_PUBDEF) {
613 			free_pubdef((OMF_multi_datas *)((OMF_record *)rec)->content);
614 		} else {
615 			R_FREE (((OMF_record *)rec)->content);
616 		}
617 		tmp = rec->next;
618 		R_FREE(rec);
619 		rec = tmp;
620 	}
621 	obj->records = NULL;
622 }
623 
free_all_omf_sections(r_bin_omf_obj * obj)624 static void free_all_omf_sections(r_bin_omf_obj *obj) {
625 	ut32 ct = 0;
626 	OMF_data *data;
627 
628 	while (ct < obj->nb_section) {
629 		while (obj->sections[ct]->data) {
630 			data = obj->sections[ct]->data->next;
631 			R_FREE(obj->sections[ct]->data);
632 			obj->sections[ct]->data = data;
633 		}
634 		R_FREE (obj->sections[ct]);
635 		ct++;
636 	}
637 	R_FREE (obj->sections);
638 }
639 
free_all_omf_symbols(r_bin_omf_obj * obj)640 static void free_all_omf_symbols(r_bin_omf_obj *obj) {
641 	ut32 ct = 0;
642 	while (ct < obj->nb_symbol) {
643 		R_FREE(obj->symbols[ct]->name);
644 		R_FREE(obj->symbols[ct]);
645 
646 		ct++;
647 	}
648 	R_FREE (obj->symbols);
649 }
650 
free_all_omf_names(r_bin_omf_obj * obj)651 static void free_all_omf_names(r_bin_omf_obj *obj) {
652 	ut32 ct = 0;
653 
654 	while (ct < obj->nb_name) {
655 		R_FREE (obj->names[ct]);
656 		ct++;
657 	}
658 	R_FREE(obj->names);
659 }
660 
r_bin_free_all_omf_obj(r_bin_omf_obj * obj)661 void r_bin_free_all_omf_obj(r_bin_omf_obj *obj) {
662 	if (obj) {
663 		if (obj->records) {
664 			free_all_omf_records (obj);
665 		}
666 		if (obj->sections) {
667 			free_all_omf_sections (obj);
668 		}
669 		if (obj->symbols) {
670 			free_all_omf_symbols (obj);
671 		}
672 		if (obj->names) {
673 			free_all_omf_names (obj);
674 		}
675 		free (obj);
676 	}
677 }
678 
r_bin_internal_omf_load(const ut8 * buf,ut64 size)679 r_bin_omf_obj *r_bin_internal_omf_load(const ut8 *buf, ut64 size) {
680 	r_bin_omf_obj *ret = NULL;
681 
682 	if (!(ret = R_NEW0 (r_bin_omf_obj))) {
683 		return NULL;
684 	}
685 	if (!load_all_omf_records(ret, buf, size)) {
686 		r_bin_free_all_omf_obj(ret);
687 		return NULL;
688 	}
689 	if(!(get_omf_infos(ret))) {
690 		r_bin_free_all_omf_obj(ret);
691 		return NULL;
692 	}
693 	free_all_omf_records(ret);
694 	return ret;
695 }
696 
r_bin_omf_get_entry(r_bin_omf_obj * obj,RBinAddr * addr)697 bool r_bin_omf_get_entry(r_bin_omf_obj *obj, RBinAddr *addr) {
698 	ut32 ct_sym = 0;
699 	OMF_data *data;
700 	ut32 offset = 0;
701 
702 	if (!obj) {
703 		return false;
704 	}
705 	while (ct_sym < obj->nb_symbol) {
706 		if (!strcmp (obj->symbols[ct_sym]->name, "_start")) {
707 			if (obj->symbols[ct_sym]->seg_idx - 1 > obj->nb_section) {
708 				eprintf ("Invalid segment index for symbol _start\n");
709 				return false;
710 			}
711 			addr->vaddr = obj->sections[obj->symbols[ct_sym]->seg_idx - 1]->vaddr + obj->symbols[ct_sym]->offset + OMF_BASE_ADDR;
712 			data = obj->sections[obj->symbols[ct_sym]->seg_idx - 1]->data;
713 			while (data) {
714 				offset += data->size;
715 				if (obj->symbols[ct_sym]->offset < offset) {
716 					addr->paddr = (obj->symbols[ct_sym]->offset - data->offset) + data->paddr;
717 					return true;
718 				}
719 				data = data->next;
720 			}
721 		}
722 		ct_sym++;
723 	}
724 	return false;
725 }
726 
r_bin_omf_get_bits(r_bin_omf_obj * obj)727 int r_bin_omf_get_bits(r_bin_omf_obj *obj) {
728 	ut32 ct_sec = 0;
729 	if (!obj) {
730 		return 32;
731 	}
732 
733 	// we assume if one segdef define a 32 segment all opcodes are 32bits
734 	while (ct_sec < obj->nb_section) {
735 		if (obj->sections[ct_sec++]->bits == 32) {
736 			return 32;
737 		}
738 	}
739 	return 16;
740 }
741 
r_bin_omf_send_sections(RList * list,OMF_segment * section,r_bin_omf_obj * obj)742 int r_bin_omf_send_sections(RList *list, OMF_segment *section, r_bin_omf_obj *obj) {
743 	RBinSection *new;
744 	OMF_data *data = section->data;
745 	ut32 ct_name = 1;
746 
747 	while (data) {
748 		if (!(new = R_NEW0 (RBinSection))) {
749 			return false;
750 		}
751 
752 		// if index == 0, it's mean there is no name
753 		if (section->name_idx && section->name_idx - 1 < obj->nb_name) {
754 			new->name = r_str_newf ("%s_%d", obj->names[section->name_idx - 1], ct_name++);
755 		} else {
756 			new->name = r_str_newf ("no_name_%d", ct_name++);
757 		}
758 
759 		new->size = data->size;
760 		new->vsize = data->size;
761 		new->paddr = data->paddr;
762 		new->vaddr = section->vaddr + data->offset + OMF_BASE_ADDR;
763 		new->perm = R_PERM_RWX;
764 		new->add = true;
765 		r_list_append (list, new);
766 		data = data->next;
767 	}
768 	return true;
769 }
770 
r_bin_omf_get_paddr_sym(r_bin_omf_obj * obj,OMF_symbol * sym)771 ut64 r_bin_omf_get_paddr_sym(r_bin_omf_obj *obj, OMF_symbol *sym) {
772 	ut64 offset = 0;
773 	if (!obj->sections) {
774 		return 0LL;
775 	}
776 	if (sym->seg_idx - 1 > obj->nb_section) {
777 		return 0LL;
778 	}
779 	int sidx = sym->seg_idx - 1;
780 	if (sidx >= obj->nb_section) {
781 		return 0LL;
782 	}
783 	OMF_data *data = obj->sections[sidx]->data;
784 	while (data) {
785 		offset += data->size;
786 		if (sym->offset < offset) {
787 			return sym->offset - data->offset + data->paddr;
788 		}
789 		data = data->next;
790 	}
791 	return 0;
792 }
793 
r_bin_omf_get_vaddr_sym(r_bin_omf_obj * obj,OMF_symbol * sym)794 ut64 r_bin_omf_get_vaddr_sym(r_bin_omf_obj *obj, OMF_symbol *sym) {
795 	if (!obj->sections) {
796 		return 0LL;
797 	}
798 	if (sym->seg_idx >= obj->nb_section) {
799 		eprintf ("Invalid segment index for symbol %s\n", sym->name);
800 		return 0;
801 	}
802 	if (sym->seg_idx == 0) {
803 		return 0;
804 	}
805 	return obj->sections[sym->seg_idx - 1]->vaddr + sym->offset + OMF_BASE_ADDR;
806 }
807