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