Rizin
unix-like reverse engineering framework and cli tools
le.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2019 GustavoLCR <gugulcr@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "le.h"
5 #include <rz_bin.h>
6 
8  switch (bin->header->mflags & M_TYPE_MASK) {
9  case M_TYPE_EXE: return "Program module (EXE)";
10  case M_TYPE_DLL: return "Library module (DLL)";
11  case M_TYPE_PDD: return "Physical Device Driver";
12  case M_TYPE_VDD: return "Virtual Device Driver";
13  default: return "Unknown";
14  }
15 }
16 
18  switch (bin->header->os) {
19  case 1: return "OS/2";
20  case 2: return "Windows";
21  case 3: return "DOS 4.x";
22  case 4: return "Windows 386";
23  case 5: return "IBM Microkernel Personality Neutral";
24  default: return "Unknown";
25  }
26 }
27 
29  switch (bin->header->cpu) {
30  case 1: return "80286";
31  case 2: return "80386";
32  case 3: return "80486";
33  case 0x20: return "N10";
34  case 0x21: return "N11";
35  case 0x40: return "R3000";
36  case 0x41: return "R6000";
37  case 0x42: return "R4000";
38  default: return "Unknown";
39  }
40 }
41 
43  switch (bin->header->cpu) {
44  case 1:
45  case 2:
46  case 3:
47  return "x86";
48  case 0x20:
49  case 0x21:
50  return "i860";
51  case 0x40:
52  case 0x41:
53  case 0x42:
54  return "mips";
55  default:
56  return "Unknown";
57  }
58 }
59 
61  ut8 size;
62  if (!rz_buf_read8_at(buf, *offset, &size)) {
63  return NULL;
64  }
65 
66  size &= 0x7F; // Max is 127
67  if (!size) {
68  return NULL;
69  }
70  (*offset)++;
71  char *str = calloc((ut64)size + 1, sizeof(char));
73  *offset += size;
74  return str;
75 }
76 
79  if (!sym) {
80  return NULL;
81  }
83  if (!name) {
84  rz_bin_symbol_free(sym);
85  return NULL;
86  }
87  sym->name = name;
88  ut16 entry_idx;
89  if (!rz_buf_read_le16_offset(bin->buf, offset, &entry_idx)) {
90  rz_bin_symbol_free(sym);
91  return NULL;
92  }
93  sym->ordinal = entry_idx;
94  return sym;
95 }
96 
98  ut64 offset = (ut64)bin->header->enttab + bin->headerOff;
99  RzList *l = rz_list_newf(free);
100  if (!l) {
101  return NULL;
102  }
103  while (true) {
105  LE_entry_bundle_entry e;
106  ut64 off = offset;
107  if (!(rz_buf_read8_offset(bin->buf, &off, &header.count) &&
108  rz_buf_read8_offset(bin->buf, &off, &header.type) &&
109  rz_buf_read_le16_offset(bin->buf, &off, &header.objnum))) {
110  break;
111  }
112  if (!header.count) {
113  break;
114  }
116  offset += sizeof(header.type) + sizeof(header.count);
117  while (header.count) {
118  rz_list_append(l, strdup("")); // (ut64 *)-1);
119  header.count--;
120  }
121  continue;
122  }
123  offset += sizeof(LE_entry_bundle_header);
124  bool typeinfo = header.type & ENTRY_PARAMETER_TYPING_PRESENT;
125  int i;
126  for (i = 0; i < header.count; i++) {
127  ut64 entry = -1;
128  rz_buf_read_at(bin->buf, offset, (ut8 *)&e, sizeof(e));
129  switch (header.type & ~ENTRY_PARAMETER_TYPING_PRESENT) {
130  case ENTRY16:
131  if ((header.objnum - 1) < bin->header->objcnt) {
132  entry = (ut64)e.entry_16.offset + bin->objtbl[header.objnum - 1].reloc_base_addr;
133  }
134  offset += sizeof(e.entry_16);
135  if (typeinfo) {
136  offset += (ut64)(e.entry_16.flags & ENTRY_PARAM_COUNT_MASK) * 2;
137  }
138  break;
139  case CALLGATE:
140  if ((header.objnum - 1) < bin->header->objcnt) {
141  entry = (ut64)e.callgate.offset + bin->objtbl[header.objnum - 1].reloc_base_addr;
142  }
143  offset += sizeof(e.callgate);
144  if (typeinfo) {
145  offset += (ut64)(e.callgate.flags & ENTRY_PARAM_COUNT_MASK) * 2;
146  }
147  break;
148  case ENTRY32:
149  if ((header.objnum - 1) < bin->header->objcnt) {
150  entry = (ut64)e.entry_32.offset + bin->objtbl[header.objnum - 1].reloc_base_addr;
151  }
152  offset += sizeof(e.entry_32);
153  if (typeinfo) {
154  offset += (ut64)(e.entry_32.flags & ENTRY_PARAM_COUNT_MASK) * 2;
155  }
156  break;
157  case FORWARDER:
158  offset += sizeof(e.forwarder);
159  break;
160  }
161  if (entry != UT64_MAX) {
163  }
164  }
165  }
166  return l;
167 }
168 
170  while (offset < end) {
172  if (!sym) {
173  break;
174  }
175  if (sym->ordinal) {
176  const char *n = rz_list_get_n(entl, sym->ordinal - 1);
177  if (n) {
178  sym->vaddr = rz_num_get(NULL, n);
180  sym->type = RZ_BIN_TYPE_FUNC_STR;
181  rz_list_append(syml, sym);
182  } else {
183  rz_bin_symbol_free(sym);
184  }
185  } else {
186  rz_bin_symbol_free(sym);
187  }
188  }
189 }
190 
194  LE_image_header *h = bin->header;
195  ut64 offset = (ut64)h->restab + bin->headerOff;
196  ut32 end = h->enttab + bin->headerOff;
198  offset = h->nrestab;
199  end = h->nrestab + h->cbnrestab;
202  return l;
203 }
204 
207  if (!l) {
208  return NULL;
209  }
210  LE_image_header *h = bin->header;
211  ut64 offset = (ut64)h->impproc + bin->headerOff + 1; // First entry is a null string
212  ut64 end = (ut64)h->fixupsize + h->fpagetab + bin->headerOff;
213  while (offset < end) {
215  if (!imp) {
216  break;
217  }
219  if (!imp->name) {
220  rz_bin_import_free(imp);
221  break;
222  }
223  imp->type = RZ_BIN_TYPE_FUNC_STR;
224  rz_list_append(l, imp);
225  }
226  return l;
227 }
228 
231  if (!l) {
232  return NULL;
233  }
235  if (entry) {
236  if ((bin->header->startobj - 1) < bin->header->objcnt) {
237  entry->vaddr = (ut64)bin->objtbl[bin->header->startobj - 1].reloc_base_addr + bin->header->eip;
238  }
239  }
240  rz_list_append(l, entry);
241 
242  return l;
243 }
244 
247  if (!l) {
248  return NULL;
249  }
250  LE_image_header *h = bin->header;
251  ut64 offset = (ut64)h->impmod + bin->headerOff;
252  ut64 end = offset + h->impproc - h->impmod;
253  while (offset < end) {
255  if (!name) {
256  break;
257  }
258  rz_list_append(l, name);
259  }
260  return l;
261 }
262 
263 /*
264  * Creates & appends to l iter_n sections with the same paddr for each iter record.
265  * page->size is the total size of iter records that describe the page
266  * TODO: Don't do this
267  */
268 static void __create_iter_sections(RzList *l, rz_bin_le_obj_t *bin, RzBinSection *sec, LE_object_page_entry *page, ut64 vaddr, int cur_page) {
269  rz_return_if_fail(l && bin && sec && page);
270  LE_image_header *h = bin->header;
271  ut32 offset = (h->itermap + (page->offset << (bin->is_le ? 0 : h->pageshift)));
272 
273  // Gets the first iter record
274  ut16 iter_n;
275  if (!rz_buf_read_ble16_at(bin->buf, offset, &iter_n, h->worder)) {
276  return;
277  }
278 
279  offset += sizeof(ut16);
280  ut16 data_size;
281  if (!rz_buf_read_ble16_at(bin->buf, offset, &data_size, h->worder)) {
282  return;
283  }
284 
285  offset += sizeof(ut16);
286 
287  ut64 tot_size = 0;
288  int iter_cnt = 0;
289  ut64 bytes_left = page->size;
290  while (iter_n && bytes_left > 0) {
291  int i;
292  for (i = 0; i < iter_n; i++) {
294  if (!s) {
295  break;
296  }
297  s->name = rz_str_newf("%s.page.%d.iter.%d", sec->name, cur_page, iter_cnt);
298  s->bits = sec->bits;
299  s->perm = sec->perm;
300  s->size = data_size;
301  s->vsize = data_size;
302  s->paddr = offset;
303  s->vaddr = vaddr;
304  vaddr += data_size;
305  tot_size += data_size;
306  rz_list_append(l, s);
307  iter_cnt++;
308  }
309  bytes_left -= sizeof(ut16) * 2 + data_size;
310  // Get the next iter record
311  offset += data_size;
312 
313  if (!rz_buf_read_ble16_at(bin->buf, offset, &iter_n, h->worder)) {
314  return;
315  }
316  offset += sizeof(ut16);
317 
318  if (!rz_buf_read_ble16_at(bin->buf, offset, &data_size, h->worder)) {
319  return;
320  }
321  offset += sizeof(ut16);
322  }
323  if (tot_size < h->pagesize) {
325  if (!s) {
326  return;
327  }
328  s->name = rz_str_newf("%s.page.%d.iter.zerofill", sec->name, cur_page);
329  s->bits = sec->bits;
330  s->perm = sec->perm;
331  s->vsize = h->pagesize - tot_size;
332  s->vaddr = vaddr;
333  rz_list_append(l, s);
334  }
335 }
336 
337 // TODO: Compressed page
340  if (!l) {
341  return NULL;
342  }
343  LE_image_header *h = bin->header;
344  ut32 pages_start_off = h->datapage;
345  int i;
346  for (i = 0; i < h->objcnt; i++) {
348  if (!sec) {
349  return l;
350  }
351  LE_object_entry *entry = &bin->objtbl[i];
352  sec->name = rz_str_newf("obj.%d", i + 1);
353  sec->vsize = entry->virtual_size;
354  sec->vaddr = entry->reloc_base_addr;
355  if (entry->flags & O_READABLE) {
356  sec->perm |= RZ_PERM_R;
357  }
358  if (entry->flags & O_WRITABLE) {
359  sec->perm |= RZ_PERM_W;
360  }
361  if (entry->flags & O_EXECUTABLE) {
362  sec->perm |= RZ_PERM_X;
363  }
364  if (entry->flags & O_BIG_BIT) {
365  sec->bits = RZ_SYS_BITS_32;
366  } else {
367  sec->bits = RZ_SYS_BITS_16;
368  }
369  sec->is_data = entry->flags & O_RESOURCE || !(sec->perm & RZ_PERM_X);
370  if (!entry->page_tbl_entries) {
371  rz_list_append(l, sec);
372  }
373  int j;
374  ut32 page_size_sum = 0;
375  ut32 next_idx = i < h->objcnt - 1 ? bin->objtbl[i + 1].page_tbl_idx - 1 : UT32_MAX;
376  ut32 objmaptbloff = h->objmap + bin->headerOff;
377  ut64 objpageentrysz = bin->is_le ? sizeof(ut32) : sizeof(LE_object_page_entry);
378  for (j = 0; j < entry->page_tbl_entries; j++) {
381  if (!s) {
382  rz_bin_section_free(sec);
383  return l;
384  }
385  s->name = rz_str_newf("%s.page.%d", sec->name, j);
386  s->is_data = sec->is_data;
387 
388  int cur_idx = entry->page_tbl_idx + j - 1;
389  ut64 page_entry_off = objpageentrysz * cur_idx + objmaptbloff;
390  ut64 offset = page_entry_off;
391  if (!(rz_buf_read_le32_offset(bin->buf, &offset, &page.offset) &&
394  RZ_LOG_WARN("Cannot read out of bounds page table entry.\n");
396  break;
397  }
398  if (cur_idx < next_idx) { // If not true rest of pages will be zeroes
399  if (bin->is_le) {
400  // Why is it big endian???
401  ut32 tmp_offset;
402  if (!rz_buf_read_be32_at(bin->buf, page_entry_off, &tmp_offset)) {
404  break;
405  }
406 
407  ut64 offset = tmp_offset >> 8;
408  s->paddr = (offset - 1) * h->pagesize + pages_start_off;
409  if (entry->page_tbl_idx + j == h->mpages) {
410  page.size = h->pageshift;
411  } else {
412  page.size = h->pagesize;
413  }
414  } else if (page.flags == P_ITERATED) {
415  ut64 vaddr = sec->vaddr + page_size_sum;
416  __create_iter_sections(l, bin, sec, &page, vaddr, j);
418  page_size_sum += h->pagesize;
419  continue;
420  } else if (page.flags == P_COMPRESSED) {
421  // TODO
422  RZ_LOG_WARN("Compressed page not handled: %s", s->name);
423  } else if (page.flags != P_ZEROED) {
424  s->paddr = ((ut64)page.offset << h->pageshift) + pages_start_off;
425  }
426  }
427  s->vsize = h->pagesize;
428  s->vaddr = sec->vaddr + page_size_sum;
429  s->perm = sec->perm;
430  s->size = page.size;
431  s->bits = sec->bits;
432  rz_list_append(l, s);
433  page_size_sum += s->vsize;
434  }
435  if (entry->page_tbl_entries) {
436  rz_bin_section_free(sec);
437  }
438  }
439  return l;
440 }
441 
443  char *modname = NULL;
444  ut64 off = (ut64)bin->header->impmod + bin->headerOff;
445  while (ordinal > 0) {
446  free(modname);
447  modname = le_read_nonnull_str_at(bin->buf, &off);
448  ordinal--;
449  }
450  return modname;
451 }
452 
455  if (!l) {
456  return NULL;
457  }
460  LE_image_header *h = bin->header;
461  ut64 cur_page = 0;
462  const ut64 fix_rec_tbl_off = (ut64)h->frectab + bin->headerOff;
463  ut32 tmp_offset;
464  if (!rz_buf_read_ble32_at(bin->buf, (ut64)h->fpagetab + bin->headerOff + cur_page * sizeof(ut32), &tmp_offset, h->worder)) {
465  rz_list_free(l);
468  return NULL;
469  }
470 
471  ut64 offset = tmp_offset + fix_rec_tbl_off;
472 
473  ut32 tmp_end;
474  if (!rz_buf_read_ble32_at(bin->buf, (ut64)h->fpagetab + bin->headerOff + (cur_page + 1) * sizeof(ut32), &tmp_end, h->worder)) {
475  rz_list_free(l);
478  return NULL;
479  }
480  ut64 end = tmp_end + fix_rec_tbl_off;
481 
482  const RzBinSection *cur_section = (RzBinSection *)rz_list_get_n(sections, cur_page);
483  ut64 cur_page_offset = cur_section ? cur_section->vaddr : 0;
484  while (cur_page < h->mpages) {
485  RzBinReloc *rel = RZ_NEW0(RzBinReloc);
486  bool rel_appended = false; // whether rel has been appended to l and must not be freed
487  if (!rel) {
488  break;
489  }
491  int ret = rz_buf_read_at(bin->buf, offset, (ut8 *)&header, sizeof(header));
492  if (ret != sizeof(header)) {
493  RZ_LOG_WARN("Cannot read out of bounds relocation.\n");
494  free(rel);
495  break;
496  }
497  offset += sizeof(header);
498  switch (header.source & F_SOURCE_TYPE_MASK) {
499  case BYTEFIXUP:
500  rel->type = RZ_BIN_RELOC_8;
501  break;
502  case SELECTOR16:
503  case OFFSET16:
504  rel->type = RZ_BIN_RELOC_16;
505  break;
506  case OFFSET32:
507  case POINTER32:
508  case SELFOFFSET32:
509  rel->type = RZ_BIN_RELOC_32;
510  break;
511  case POINTER48:
512  rel->type = 48;
513  break;
514  }
515  ut8 repeat = 0;
516  ut16 source = 0;
517  if (header.source & F_SOURCE_LIST) {
518  if (!rz_buf_read8_at(bin->buf, offset, &repeat)) {
519  rz_bin_reloc_free(rel);
520  break;
521  }
522  offset += sizeof(ut8);
523  } else {
524  if (!rz_buf_read_ble16_at(bin->buf, offset, &source, h->worder)) {
525  rz_bin_reloc_free(rel);
526  break;
527  }
528  offset += sizeof(ut16);
529  }
530  ut32 ordinal;
531  if (header.target & F_TARGET_ORD16) {
532  ut16 tmp;
533  if (!rz_buf_read_ble16_at(bin->buf, offset, &tmp, h->worder)) {
534  rz_bin_reloc_free(rel);
535  break;
536  }
537  ordinal = tmp;
538  offset += sizeof(ut16);
539  } else {
540  ut8 tmp;
541  if (!rz_buf_read8_at(bin->buf, offset, &tmp)) {
542  rz_bin_reloc_free(rel);
543  break;
544  }
545  ordinal = tmp;
546  offset += sizeof(ut8);
547  }
548  switch (header.target & F_TARGET_TYPE_MASK) {
549  case INTERNAL:
550  if ((ordinal - 1) < bin->header->objcnt) {
551  rel->addend = bin->objtbl[ordinal - 1].reloc_base_addr;
552  if ((header.source & F_SOURCE_TYPE_MASK) != SELECTOR16) {
553  if (header.target & F_TARGET_OFF32) {
554  ut32 tmp;
555  if (!rz_buf_read_ble32_offset(bin->buf, &offset, &tmp, h->worder)) {
556  rz_bin_reloc_free(rel);
557  continue;
558  }
559  rel->addend += tmp;
560  } else {
561  ut16 tmp;
562  if (!rz_buf_read_ble16_offset(bin->buf, &offset, &tmp, h->worder)) {
563  rz_bin_reloc_free(rel);
564  continue;
565  }
566  rel->addend += tmp;
567  }
568  }
569  }
570  break;
571  case IMPORTORD: {
573  if (!imp) {
574  break;
575  }
576  char *mod_name = le_get_modname_by_ord(bin, ordinal);
577  if (!mod_name) {
578  rz_bin_import_free(imp);
579  break;
580  }
581 
582  if (header.target & F_TARGET_ORD8) {
583  ut8 tmp;
584  if (!rz_buf_read8_at(bin->buf, offset, &tmp)) {
585  rz_bin_import_free(imp);
586  break;
587  }
588  ordinal = tmp;
589  offset += sizeof(ut8);
590  } else if (header.target & F_TARGET_OFF32) {
591  if (!rz_buf_read_ble32_offset(bin->buf, &offset, &ordinal, h->worder)) {
592  rz_bin_import_free(imp);
593  break;
594  }
595  } else {
596  ut16 tmp;
597  if (!rz_buf_read_ble16_offset(bin->buf, &offset, &tmp, h->worder)) {
598  rz_bin_import_free(imp);
599  break;
600  }
601  ordinal = tmp;
602  }
603  imp->name = rz_str_newf("%s.%u", mod_name, ordinal);
604  imp->ordinal = ordinal;
605  rel->import = imp;
606  free(mod_name);
607  break;
608  }
609  case IMPORTNAME: {
611  if (!imp) {
612  break;
613  }
614  ut32 nameoff;
615  if (header.target & F_TARGET_OFF32) {
616  if (!rz_buf_read_ble32_offset(bin->buf, &offset, &nameoff, h->worder)) {
617  rz_bin_import_free(imp);
618  break;
619  }
620  } else {
621  ut16 tmp;
622  if (!rz_buf_read_ble16_offset(bin->buf, &offset, &tmp, h->worder)) {
623  rz_bin_import_free(imp);
624  break;
625  }
626  nameoff = tmp;
627  }
628  ut64 off = (ut64)h->impproc + nameoff + bin->headerOff;
629  char *proc_name = le_read_nonnull_str_at(bin->buf, &off);
630  char *mod_name = le_get_modname_by_ord(bin, ordinal);
631  imp->name = rz_str_newf("%s.%s", mod_name ? mod_name : "", proc_name ? proc_name : "");
632  rel->import = imp;
633  break;
634  }
635  case INTERNALENTRY:
636  rel->addend = (ut64)(size_t)rz_list_get_n(entries, ordinal - 1);
637  break;
638  }
639  if (header.target & F_TARGET_ADDITIVE) {
640  ut32 additive = 0;
641  if (header.target & F_TARGET_ADD32) {
642  if (!rz_buf_read_ble32_offset(bin->buf, &offset, &additive, h->worder)) {
643  rz_bin_reloc_free(rel);
644  break;
645  }
646  } else {
647  ut16 tmp;
648  if (!rz_buf_read_ble16_offset(bin->buf, &offset, &tmp, h->worder)) {
649  rz_bin_reloc_free(rel);
650  break;
651  }
652  additive = tmp;
653  }
654  rel->addend += additive;
655  }
656  if (!repeat) {
657  rel->vaddr = cur_page_offset + source;
658  rel->paddr = cur_section ? cur_section->paddr + source : 0;
659  rz_list_append(l, rel);
660  rel_appended = true;
661  }
662 
663  if (header.target & F_TARGET_CHAIN) {
664  ut32 fixupinfo;
665  if (!rz_buf_read_ble32_at(bin->buf, cur_page_offset + source, &fixupinfo, h->worder)) {
666  break;
667  }
668 
669  ut64 base_target_address = rel->addend - (fixupinfo & 0xFFFFF);
670  do {
671  if (!rz_buf_read_ble32_at(bin->buf, cur_page_offset + source, &fixupinfo, h->worder)) {
672  break;
673  }
674  RzBinReloc *new = RZ_NEW0(RzBinReloc);
675  *new = *rel;
676  new->addend = base_target_address + (fixupinfo & 0xFFFFF);
677  rz_list_append(l, new);
678  source = (fixupinfo >> 20) & 0xFFF;
679  } while (source != 0xFFF);
680  }
681 
682  while (repeat) {
683  ut16 off;
684  if (!rz_buf_read_ble16_offset(bin->buf, &offset, &off, h->worder)) {
685  break;
686  }
687  rel->vaddr = cur_page_offset + off;
688  rel->paddr = cur_section ? cur_section->paddr + off : 0;
689  RzBinReloc *new = RZ_NEW0(RzBinReloc);
690  *new = *rel;
691  rz_list_append(l, new);
692  repeat--;
693  }
694  while (offset >= end) {
695  cur_page++;
696  if (cur_page >= h->mpages) {
697  break;
698  }
699  ut64 at = h->fpagetab + bin->headerOff;
700  ut32 w0;
701  if (!rz_buf_read_ble32_at(bin->buf, at + cur_page * sizeof(ut32), &w0, h->worder)) {
702  break;
703  }
704  ut32 w1;
705  if (!rz_buf_read_ble32_at(bin->buf, at + (cur_page + 1) * sizeof(ut32), &w1, h->worder)) {
706  break;
707  }
708  offset = fix_rec_tbl_off + w0;
709  end = fix_rec_tbl_off + w1;
710  if (offset < end) {
711  cur_section = (RzBinSection *)rz_list_get_n(sections, cur_page);
712  cur_page_offset = cur_section ? cur_section->vaddr : 0;
713  }
714  }
715  if (!rel_appended) {
716  rz_bin_reloc_free(rel);
717  }
718  }
721  return l;
722 }
723 
725  if (!rz_buf_read_at(buf, bin->headerOff, (ut8 *)bin->header, 4)) {
726  return false;
727  }
728  ut64 offset = bin->headerOff + 4; /* skip magic, border, and worder */
729  return rz_buf_read_le32_offset(buf, &offset, &bin->header->level) &&
730  rz_buf_read_le16_offset(buf, &offset, &bin->header->cpu) &&
731  rz_buf_read_le16_offset(buf, &offset, &bin->header->os) &&
732  rz_buf_read_le32_offset(buf, &offset, &bin->header->ver) &&
733  rz_buf_read_le32_offset(buf, &offset, &bin->header->mflags) &&
734  rz_buf_read_le32_offset(buf, &offset, &bin->header->mpages) &&
735  rz_buf_read_le32_offset(buf, &offset, &bin->header->startobj) &&
736  rz_buf_read_le32_offset(buf, &offset, &bin->header->eip) &&
737  rz_buf_read_le32_offset(buf, &offset, &bin->header->stackobj) &&
738  rz_buf_read_le32_offset(buf, &offset, &bin->header->esp) &&
739  rz_buf_read_le32_offset(buf, &offset, &bin->header->pagesize) &&
740  rz_buf_read_le32_offset(buf, &offset, &bin->header->pageshift) &&
741  rz_buf_read_le32_offset(buf, &offset, &bin->header->fixupsize) &&
742  rz_buf_read_le32_offset(buf, &offset, &bin->header->fixupsum) &&
743  rz_buf_read_le32_offset(buf, &offset, &bin->header->ldrsize) &&
744  rz_buf_read_le32_offset(buf, &offset, &bin->header->ldrsum) &&
745  rz_buf_read_le32_offset(buf, &offset, &bin->header->objtab) &&
746  rz_buf_read_le32_offset(buf, &offset, &bin->header->objcnt) &&
747  rz_buf_read_le32_offset(buf, &offset, &bin->header->objmap) &&
748  rz_buf_read_le32_offset(buf, &offset, &bin->header->itermap) &&
749  rz_buf_read_le32_offset(buf, &offset, &bin->header->rsrctab) &&
750  rz_buf_read_le32_offset(buf, &offset, &bin->header->rsrccnt) &&
751  rz_buf_read_le32_offset(buf, &offset, &bin->header->restab) &&
752  rz_buf_read_le32_offset(buf, &offset, &bin->header->enttab) &&
753  rz_buf_read_le32_offset(buf, &offset, &bin->header->dirtab) &&
754  rz_buf_read_le32_offset(buf, &offset, &bin->header->dircnt) &&
755  rz_buf_read_le32_offset(buf, &offset, &bin->header->fpagetab) &&
756  rz_buf_read_le32_offset(buf, &offset, &bin->header->frectab) &&
757  rz_buf_read_le32_offset(buf, &offset, &bin->header->impmod) &&
758  rz_buf_read_le32_offset(buf, &offset, &bin->header->impmodcnt) &&
759  rz_buf_read_le32_offset(buf, &offset, &bin->header->impproc) &&
760  rz_buf_read_le32_offset(buf, &offset, &bin->header->pagesum) &&
761  rz_buf_read_le32_offset(buf, &offset, &bin->header->datapage) &&
762  rz_buf_read_le32_offset(buf, &offset, &bin->header->preload) &&
763  rz_buf_read_le32_offset(buf, &offset, &bin->header->nrestab) &&
764  rz_buf_read_le32_offset(buf, &offset, &bin->header->cbnrestab) &&
765  rz_buf_read_le32_offset(buf, &offset, &bin->header->nressum) &&
766  rz_buf_read_le32_offset(buf, &offset, &bin->header->autodata) &&
767  rz_buf_read_le32_offset(buf, &offset, &bin->header->debuginfo) &&
768  rz_buf_read_le32_offset(buf, &offset, &bin->header->debuglen) &&
769  rz_buf_read_le32_offset(buf, &offset, &bin->header->instpreload) &&
770  rz_buf_read_le32_offset(buf, &offset, &bin->header->instdemand) &&
771  rz_buf_read_le32_offset(buf, &offset, &bin->header->heapsize) &&
772  rz_buf_read_le32_offset(buf, &offset, &bin->header->stacksize);
773 }
774 
776  ut8 magic[2];
777  rz_buf_read_at(buf, 0, magic, sizeof(magic));
778  if (!memcmp(&magic, "MZ", 2)) {
779  ut16 tmp;
780  if (!rz_buf_read_le16_at(buf, 0x3c, &tmp)) {
781  return false;
782  }
783  bin->headerOff = tmp;
784  } else {
785  bin->headerOff = 0;
786  }
787  bin->header = RZ_NEW0(LE_image_header);
788  if (!bin->header) {
789  RZ_LOG_ERROR("Failed to allocate memory");
790  return false;
791  }
792  return read_le_header_aux(bin, buf);
793 }
794 
797  free(bin->header);
798  free(bin->objtbl);
799  free(bin->filename);
800  free(bin);
801 }
802 
805  if (!bin) {
806  return NULL;
807  }
808 
810  LE_image_header *h = bin->header;
811  if (!memcmp("LE", h->magic, 2)) {
812  bin->is_le = true;
813  }
814  bin->type = le_get_module_type(bin);
815  bin->cpu = le_get_cpu_type(bin);
816  bin->os = le_get_os_type(bin);
817  bin->arch = le_get_arch(bin);
818  bin->objtbl = calloc(h->objcnt, sizeof(LE_object_entry));
819  if (!bin->objtbl) {
821  return NULL;
822  }
823  ut64 offset = (ut64)bin->headerOff + h->restab;
824  bin->filename = le_read_nonnull_str_at(buf, &offset);
825  offset = (ut64)bin->headerOff + h->objtab;
826  for (ut32 i = 0; i < h->objcnt; i++) {
827  LE_object_entry *le_obj_entry = bin->objtbl + i;
828  rz_buf_read_le32_offset(buf, &offset, &le_obj_entry->virtual_size);
830  rz_buf_read_le32_offset(buf, &offset, &le_obj_entry->flags);
831  rz_buf_read_le32_offset(buf, &offset, &le_obj_entry->page_tbl_idx);
833  rz_buf_read_le32_offset(buf, &offset, &le_obj_entry->reserved);
834  }
835  bin->buf = buf;
836  return bin;
837 }
#define e(frag)
lzma_index ** i
Definition: index.h:629
RZ_API void rz_bin_symbol_free(RzBinSymbol *sym)
Definition: bin.c:175
RZ_API void rz_bin_import_free(RzBinImport *imp)
Definition: bin.c:137
RZ_API void rz_bin_section_free(RzBinSection *bs)
Definition: bin.c:1116
RZ_API void rz_bin_reloc_free(RzBinReloc *reloc)
Definition: bin.c:188
RzList * entries(RzBinFile *bf)
Definition: bin_ne.c:98
RzList * sections(RzBinFile *bf)
Definition: bin_ne.c:110
#define NULL
Definition: cris-opc.c:27
#define ut8
Definition: dcpu16.h:8
uint16_t ut16
uint32_t ut32
static ut32 next_idx(ut32 idx)
Definition: ht_inc.c:52
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
RzList * rz_bin_le_get_symbols(rz_bin_le_obj_t *bin)
Definition: le.c:191
RzList * rz_bin_le_get_imports(rz_bin_le_obj_t *bin)
Definition: le.c:205
void rz_bin_le_free(rz_bin_le_obj_t *bin)
Definition: le.c:795
static void __create_iter_sections(RzList *l, rz_bin_le_obj_t *bin, RzBinSection *sec, LE_object_page_entry *page, ut64 vaddr, int cur_page)
Definition: le.c:268
RzList * rz_bin_le_get_libs(rz_bin_le_obj_t *bin)
Definition: le.c:245
static RzBinSymbol * le_get_symbol(rz_bin_le_obj_t *bin, ut64 *offset)
Definition: le.c:77
RzList * le_get_entries(rz_bin_le_obj_t *bin)
Definition: le.c:97
const char * le_get_module_type(rz_bin_le_obj_t *bin)
Definition: le.c:7
const char * le_get_arch(rz_bin_le_obj_t *bin)
Definition: le.c:42
static char * le_read_nonnull_str_at(RzBuffer *buf, ut64 *offset)
Definition: le.c:60
static bool le_init_header(rz_bin_le_obj_t *bin, RzBuffer *buf)
Definition: le.c:775
static void le_get_symbols_at(rz_bin_le_obj_t *bin, RzList *syml, RzList *entl, ut64 offset, ut64 end)
Definition: le.c:169
RzList * rz_bin_le_get_entrypoints(rz_bin_le_obj_t *bin)
Definition: le.c:229
char * le_get_modname_by_ord(rz_bin_le_obj_t *bin, ut32 ordinal)
Definition: le.c:442
RzList * rz_bin_le_get_sections(rz_bin_le_obj_t *bin)
Definition: le.c:338
RzList * rz_bin_le_get_relocs(rz_bin_le_obj_t *bin)
Definition: le.c:453
static bool read_le_header_aux(rz_bin_le_obj_t *bin, RzBuffer *buf)
Definition: le.c:724
const char * le_get_cpu_type(rz_bin_le_obj_t *bin)
Definition: le.c:28
rz_bin_le_obj_t * rz_bin_le_new_buf(RzBuffer *buf)
Definition: le.c:803
const char * le_get_os_type(rz_bin_le_obj_t *bin)
Definition: le.c:17
#define O_BIG_BIT
Definition: le_specs.h:129
#define F_SOURCE_LIST
Definition: le_specs.h:81
#define F_TARGET_ORD16
Definition: le_specs.h:100
@ POINTER32
Definition: le_specs.h:87
@ BYTEFIXUP
Definition: le_specs.h:84
@ SELFOFFSET32
Definition: le_specs.h:92
@ SELECTOR16
Definition: le_specs.h:86
@ POINTER48
Definition: le_specs.h:90
@ OFFSET32
Definition: le_specs.h:91
@ OFFSET16
Definition: le_specs.h:89
#define F_TARGET_TYPE_MASK
Definition: le_specs.h:95
@ IMPORTORD
Definition: le_specs.h:105
@ INTERNALENTRY
Definition: le_specs.h:107
@ IMPORTNAME
Definition: le_specs.h:106
@ INTERNAL
Definition: le_specs.h:104
#define P_ITERATED
Definition: le_specs.h:143
#define O_EXECUTABLE
Definition: le_specs.h:117
#define F_SOURCE_TYPE_MASK
Definition: le_specs.h:79
#define O_READABLE
Definition: le_specs.h:115
@ CALLGATE
Definition: le_specs.h:11
@ ENTRY32
Definition: le_specs.h:12
@ FORWARDER
Definition: le_specs.h:13
@ ENTRY16
Definition: le_specs.h:10
@ UNUSED_ENTRY
Definition: le_specs.h:9
#define F_TARGET_ADD32
Definition: le_specs.h:99
#define M_TYPE_PDD
Definition: le_specs.h:167
struct LE_entry_bundle_header_s LE_entry_bundle_header
#define F_TARGET_OFF32
Definition: le_specs.h:98
#define O_RESOURCE
Definition: le_specs.h:118
#define M_TYPE_MASK
Definition: le_specs.h:163
#define ENTRY_PARAM_COUNT_MASK
Definition: le_specs.h:51
#define F_TARGET_ADDITIVE
Definition: le_specs.h:96
#define ENTRY_PARAMETER_TYPING_PRESENT
Definition: le_specs.h:42
#define F_TARGET_CHAIN
Definition: le_specs.h:97
#define O_WRITABLE
Definition: le_specs.h:116
#define M_TYPE_DLL
Definition: le_specs.h:165
#define M_TYPE_EXE
Definition: le_specs.h:164
#define P_COMPRESSED
Definition: le_specs.h:147
#define F_TARGET_ORD8
Definition: le_specs.h:101
#define P_ZEROED
Definition: le_specs.h:145
#define M_TYPE_VDD
Definition: le_specs.h:168
uint8_t ut8
Definition: lh5801.h:11
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 RZ_BORROW void * rz_list_get_n(RZ_NONNULL const RzList *list, ut32 n)
Returns the N-th element of the list.
Definition: list.c:574
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
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
const char * source
Definition: lz4.h:699
#define header(is_bt, len_min, ret_op)
while(len< limit &&buf1[len]==buf2[len])++len
int n
Definition: mipsasm.c:19
const char * name
Definition: op.c:541
int off
Definition: pal.c:13
static void repeat(struct parse *, sopno, int, int)
Definition: regcomp.c:1155
static RzSocket * s
Definition: rtr.c:28
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
@ RZ_BIN_RELOC_32
Definition: rz_bin.h:176
@ RZ_BIN_RELOC_16
Definition: rz_bin.h:174
@ RZ_BIN_RELOC_8
Definition: rz_bin.h:173
#define RZ_BIN_BIND_GLOBAL_STR
Definition: rz_bin.h:107
#define RZ_BIN_TYPE_FUNC_STR
Definition: rz_bin.h:119
#define rz_buf_read_le16_at(b, addr, result)
Definition: rz_buf.h:270
#define rz_buf_read_le16_offset(b, offset, result)
Definition: rz_buf.h:276
RZ_API bool rz_buf_read8_at(RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *result)
Read a byte at the specified address in the buffer.
Definition: buf.c:876
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
#define rz_buf_read_be32_at(b, addr, result)
Definition: rz_buf.h:285
#define rz_buf_read_le32_offset(b, offset, result)
Definition: rz_buf.h:277
#define rz_buf_read8_offset(b, offset, result)
Definition: rz_buf.h:274
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
@ RZ_SYS_BITS_32
Definition: rz_sys.h:20
@ RZ_SYS_BITS_16
Definition: rz_sys.h:19
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_PERM_W
Definition: rz_types.h:94
#define RZ_PERM_X
Definition: rz_types.h:95
#define PFMT64x
Definition: rz_types.h:393
#define UT32_MAX
Definition: rz_types_base.h:99
#define UT64_MAX
Definition: rz_types_base.h:86
#define h(i)
Definition: sha256.c:48
Definition: le_specs.h:44
Definition: le_specs.h:133
ut32 flags
Definition: le_specs.h:136
ut32 page_tbl_entries
Definition: le_specs.h:138
ut32 reloc_base_addr
Definition: le_specs.h:135
ut32 page_tbl_idx
Definition: le_specs.h:137
ut32 reserved
Definition: le_specs.h:139
ut32 virtual_size
Definition: le_specs.h:134
Definition: le_specs.h:149
ut16 flags
Definition: le_specs.h:152
ut16 size
Definition: le_specs.h:151
ut32 offset
Definition: le_specs.h:150
Definition: malloc.c:26
unsigned char * buf
Definition: gzjoin.c:83
Definition: zipcmp.c:77
Definition: z80asm.h:102
const char * type
Definition: rz_bin.h:704
ut32 ordinal
Definition: rz_bin.h:707
char * name
Definition: rz_bin.h:701
ut64 paddr
the paddr where the value should be patched into
Definition: rz_bin.h:717
RzBinRelocType type
Definition: rz_bin.h:712
ut64 vaddr
the vaddr where the value should be patched into
Definition: rz_bin.h:716
RzBinImport * import
Definition: rz_bin.h:714
st64 addend
Definition: rz_bin.h:715
char * name
Definition: rz_bin.h:619
const char * bind
Definition: rz_bin.h:681
const char * type
Definition: rz_bin.h:682
char * name
Definition: rz_bin.h:675
ut32 ordinal
Definition: rz_bin.h:692
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
ut64(WINAPI *w32_GetEnabledXStateFeatures)()