Rizin
unix-like reverse engineering framework and cli tools
ne.c File Reference
#include "ne.h"

Go to the source code of this file.

Functions

static char * __get_target_os (rz_bin_ne_obj_t *bin)
 
static int __translate_perms (int flags)
 
static char * __read_nonnull_str_at (RzBuffer *buf, ut64 offset)
 
static char * __func_name_from_ord (char *module, ut16 ordinal)
 
RzListrz_bin_ne_get_segments (rz_bin_ne_obj_t *bin)
 
static int __find_symbol_by_paddr (const void *paddr, const void *sym)
 
static void ne_sanitize_name (char *name, ut16 count)
 
RzListrz_bin_ne_get_symbols (rz_bin_ne_obj_t *bin)
 
static char * __resource_type_str (int type)
 
static void __free_resource_entry (void *entry)
 
static void __free_resource (void *resource)
 
static bool __ne_get_resources (rz_bin_ne_obj_t *bin)
 
RzListrz_bin_ne_get_imports (rz_bin_ne_obj_t *bin)
 
RzListrz_bin_ne_get_entrypoints (rz_bin_ne_obj_t *bin)
 
RzListrz_bin_ne_get_relocs (rz_bin_ne_obj_t *bin)
 
bool rz_bin_ne_buf_init (RzBuffer *buf, rz_bin_ne_obj_t *bin)
 
void rz_bin_ne_free (rz_bin_ne_obj_t *bin)
 
rz_bin_ne_obj_trz_bin_ne_new_buf (RzBuffer *buf, bool verbose)
 

Function Documentation

◆ __find_symbol_by_paddr()

static int __find_symbol_by_paddr ( const void *  paddr,
const void *  sym 
)
static

Definition at line 108 of file ne.c.

108  {
109  return (int)!(*(ut64 *)paddr == ((RzBinSymbol *)sym)->paddr);
110 }
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References ut64().

Referenced by rz_bin_ne_get_symbols().

◆ __free_resource()

static void __free_resource ( void *  resource)
static

Definition at line 285 of file ne.c.

285  {
286  rz_ne_resource *res = (rz_ne_resource *)resource;
287  free(res->name);
288  rz_list_free(res->entry);
289  free(res);
290 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
char * name
Definition: ne.h:19
RzList * entry
Definition: ne.h:20

References rz_ne_resource::entry, free(), rz_ne_resource::name, and rz_list_free().

Referenced by __ne_get_resources().

◆ __free_resource_entry()

static void __free_resource_entry ( void *  entry)
static

Definition at line 279 of file ne.c.

279  {
281  free(en->name);
282  free(en);
283 }
Definition: zipcmp.c:77
Definition: ne.h:12
char * name
Definition: ne.h:13

References free(), and rz_ne_resource_entry::name.

Referenced by __ne_get_resources().

◆ __func_name_from_ord()

static char* __func_name_from_ord ( char *  module,
ut16  ordinal 
)
static

Definition at line 55 of file ne.c.

55  {
56  char *formats_dir = rz_path_system(RZ_SDB_FORMAT);
57  char *path = rz_str_newf(RZ_JOIN_3_PATHS("%s", "dll", "%s.sdb"), formats_dir, module);
58  free(formats_dir);
59  char *ord = rz_str_newf("%d", ordinal);
60  char *name;
61  if (rz_file_exists(path)) {
62  Sdb *sdb = sdb_new(NULL, path, 0);
63  name = sdb_get(sdb, ord, NULL);
64  if (!name) {
65  name = ord;
66  } else {
67  free(ord);
68  }
69  sdb_close(sdb);
70  free(sdb);
71  } else {
72  name = ord;
73  }
74  free(path);
75  return name;
76 }
#define NULL
Definition: cris-opc.c:27
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
const char * name
Definition: op.c:541
RZ_API bool rz_file_exists(const char *str)
Definition: file.c:192
RZ_API RZ_OWN char * rz_path_system(RZ_NULLABLE const char *path)
Return the full system path of the given subpath path.
Definition: path.c:162
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_JOIN_3_PATHS(p1, p2, p3)
Definition: rz_types.h:225
#define RZ_SDB_FORMAT
Definition: rz_userconf.h:87
RZ_API Sdb * sdb_new(const char *path, const char *name, int lock)
Definition: sdb.c:47
RZ_API void sdb_close(Sdb *s)
Definition: sdb.c:416
RZ_API char * sdb_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:290
Definition: sftypes.h:77
Definition: z80asm.h:102
Definition: sdb.h:63

References free(), name, NULL, path, rz_file_exists(), RZ_JOIN_3_PATHS, rz_path_system(), RZ_SDB_FORMAT, rz_str_newf(), sdb_close(), sdb_get(), and sdb_new().

Referenced by rz_bin_ne_get_relocs().

◆ __get_target_os()

static char* __get_target_os ( rz_bin_ne_obj_t bin)
static

Definition at line 6 of file ne.c.

6  {
7  switch (bin->ne_header->targOS) {
8  case 1:
9  return "OS/2";
10  case 2:
11  return "Windows";
12  case 3:
13  return "European MS-DOS 4.x";
14  case 4:
15  return "Windows 386";
16  case 5:
17  return "BOSS (Borland Operating System Services)";
18  default:
19  return "Unknown";
20  }
21 }
Definition: malloc.c:26

Referenced by rz_bin_ne_buf_init().

◆ __ne_get_resources()

static bool __ne_get_resources ( rz_bin_ne_obj_t bin)
static

Definition at line 292 of file ne.c.

292  {
293  if (!bin->resources) {
294  bin->resources = rz_list_newf(__free_resource);
295  }
296  ut16 resoff = bin->ne_header->ResTableOffset + bin->header_offset;
297 
298  ut16 alignment;
299  if (!rz_buf_read_le16_at(bin->buf, resoff, &alignment) || alignment > 31) {
300  return false;
301  }
302 
303  ut32 off = resoff + 2;
304  while (true) {
305  NE_image_typeinfo_entry ti = { 0 };
307  if (!res) {
308  break;
309  }
311  if (!res->entry) {
312  break;
313  }
314  rz_buf_read_at(bin->buf, off, (ut8 *)&ti, sizeof(ti));
315  if (!ti.rtTypeID) {
316  break;
317  } else if (ti.rtTypeID & 0x8000) {
318  res->name = __resource_type_str(ti.rtTypeID & ~0x8000);
319  } else {
320  // Offset to resident name table
321  res->name = __read_nonnull_str_at(bin->buf, (ut64)resoff + ti.rtTypeID);
322  }
323  off += sizeof(NE_image_typeinfo_entry);
324  int i;
325  for (i = 0; i < ti.rtResourceCount; i++) {
328  if (!ren) {
329  break;
330  }
331  rz_buf_read_at(bin->buf, off, (ut8 *)&ni, sizeof(NE_image_nameinfo_entry));
332  ren->offset = ni.rnOffset << alignment;
333  ren->size = ni.rnLength;
334  if (ni.rnID & 0x8000) {
335  ren->name = rz_str_newf("%d", ni.rnID & ~0x8000);
336  } else {
337  // Offset to resident name table
338  ren->name = __read_nonnull_str_at(bin->buf, (ut64)resoff + ni.rnID);
339  }
340  rz_list_append(res->entry, ren);
341  off += sizeof(NE_image_nameinfo_entry);
342  }
343  rz_list_append(bin->resources, res);
344  }
345  return true;
346 }
lzma_index ** i
Definition: index.h:629
uint16_t ut16
uint32_t ut32
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 RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
static void __free_resource(void *resource)
Definition: ne.c:285
static char * __read_nonnull_str_at(RzBuffer *buf, ut64 offset)
Definition: ne.c:38
static void __free_resource_entry(void *entry)
Definition: ne.c:279
static char * __resource_type_str(int type)
Definition: ne.c:204
struct _TYPEINFO NE_image_typeinfo_entry
struct _NAMEINFO NE_image_nameinfo_entry
int off
Definition: pal.c:13
#define rz_buf_read_le16_at(b, addr, result)
Definition: rz_buf.h:270
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_NEW0(x)
Definition: rz_types.h:284
ut16 rnID
Definition: ne_specs.h:77
ut16 rnLength
Definition: ne_specs.h:75
ut16 rnOffset
Definition: ne_specs.h:74
ut16 rtTypeID
Definition: ne_specs.h:83
ut16 rtResourceCount
Definition: ne_specs.h:84
unsigned char * buf
Definition: gzjoin.c:83
ut32 offset
Definition: ne.h:14
ut32 size
Definition: ne.h:15

References __free_resource(), __free_resource_entry(), __read_nonnull_str_at(), __resource_type_str(), bin::buf, rz_ne_resource::entry, i, rz_ne_resource_entry::name, rz_ne_resource::name, off, rz_ne_resource_entry::offset, _NAMEINFO::rnID, _NAMEINFO::rnLength, _NAMEINFO::rnOffset, _TYPEINFO::rtResourceCount, _TYPEINFO::rtTypeID, rz_buf_read_at(), rz_buf_read_le16_at, rz_list_append(), rz_list_newf(), RZ_NEW0, rz_str_newf(), rz_ne_resource_entry::size, and ut64().

Referenced by rz_bin_ne_buf_init().

◆ __read_nonnull_str_at()

static char* __read_nonnull_str_at ( RzBuffer buf,
ut64  offset 
)
static

Definition at line 38 of file ne.c.

38  {
39  ut8 sz;
40  if (!rz_buf_read8_at(buf, offset, &sz)) {
41  return NULL;
42  }
43  if (!sz) {
44  return NULL;
45  }
46  char *str = malloc((ut64)sz + 1);
47  if (!str) {
48  return NULL;
49  }
50  rz_buf_read_at(buf, offset + 1, (ut8 *)str, sz);
51  str[sz] = '\0';
52  return str;
53 }
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
void * malloc(size_t size)
Definition: malloc.c:123
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

References malloc(), NULL, rz_buf_read8_at(), rz_buf_read_at(), cmd_descs_generate::str, and ut64().

Referenced by __ne_get_resources(), and rz_bin_ne_get_relocs().

◆ __resource_type_str()

static char* __resource_type_str ( int  type)
static

Definition at line 204 of file ne.c.

204  {
205  char *typeName;
206  switch (type) {
207  case 1:
208  typeName = "CURSOR";
209  break;
210  case 2:
211  typeName = "BITMAP";
212  break;
213  case 3:
214  typeName = "ICON";
215  break;
216  case 4:
217  typeName = "MENU";
218  break;
219  case 5:
220  typeName = "DIALOG";
221  break;
222  case 6:
223  typeName = "STRING";
224  break;
225  case 7:
226  typeName = "FONTDIR";
227  break;
228  case 8:
229  typeName = "FONT";
230  break;
231  case 9:
232  typeName = "ACCELERATOR";
233  break;
234  case 10:
235  typeName = "RCDATA";
236  break;
237  case 11:
238  typeName = "MESSAGETABLE";
239  break;
240  case 12:
241  typeName = "GROUP_CURSOR";
242  break;
243  case 14:
244  typeName = "GROUP_ICON";
245  break;
246  case 15:
247  typeName = "NAMETABLE";
248  break;
249  case 16:
250  typeName = "VERSION";
251  break;
252  case 17:
253  typeName = "DLGINCLUDE";
254  break;
255  case 19:
256  typeName = "PLUGPLAY";
257  break;
258  case 20:
259  typeName = "VXD";
260  break;
261  case 21:
262  typeName = "ANICURSOR";
263  break;
264  case 22:
265  typeName = "ANIICON";
266  break;
267  case 23:
268  typeName = "HTML";
269  break;
270  case 24:
271  typeName = "MANIFEST";
272  break;
273  default:
274  return rz_str_newf("UNKNOWN (%d)", type);
275  }
276  return strdup(typeName);
277 }
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")
int type
Definition: mipsasm.c:17

References rz_str_newf(), strdup(), and type.

Referenced by __ne_get_resources().

◆ __translate_perms()

static int __translate_perms ( int  flags)
static

Definition at line 23 of file ne.c.

23  {
24  int perms = 0;
25  if (flags & IS_RX) {
26  if (flags & IS_DATA) {
27  perms = RZ_PERM_R;
28  } else {
29  perms = RZ_PERM_X;
30  }
31  }
32  if (!perms) {
33  perms = RZ_PERM_RWX;
34  }
35  return perms;
36 }
@ IS_RX
Definition: ne_specs.h:56
@ IS_DATA
Definition: ne_specs.h:51
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_PERM_X
Definition: rz_types.h:95
#define RZ_PERM_RWX
Definition: rz_types.h:98
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123

References flags, IS_DATA, IS_RX, RZ_PERM_R, RZ_PERM_RWX, and RZ_PERM_X.

Referenced by rz_bin_ne_get_segments().

◆ ne_sanitize_name()

static void ne_sanitize_name ( char *  name,
ut16  count 
)
static

Definition at line 112 of file ne.c.

112  {
113  // expect to have names in ASCII format.
114  for (ut16 i = 0; i < count && name[i]; ++i) {
115  if (!IS_PRINTABLE(name[i])) {
116  name[i] = '?';
117  }
118  }
119 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
#define IS_PRINTABLE(x)
Definition: rz_str_util.h:10

References count, i, and IS_PRINTABLE.

Referenced by rz_bin_ne_get_symbols().

◆ rz_bin_ne_buf_init()

bool rz_bin_ne_buf_init ( RzBuffer buf,
rz_bin_ne_obj_t bin 
)

Definition at line 616 of file ne.c.

616  {
617  if (!rz_buf_read_le16_at(buf, 0x3c, &bin->header_offset)) {
618  return false;
619  }
620 
621  bin->ne_header = RZ_NEW0(NE_image_header);
622  if (!bin->ne_header) {
623  return false;
624  }
625  bin->buf = buf;
626  rz_buf_read_at(buf, bin->header_offset, (ut8 *)bin->ne_header, sizeof(NE_image_header));
627  if (bin->ne_header->FileAlnSzShftCnt > 31) {
628  return false;
629  }
630  bin->alignment = 1 << bin->ne_header->FileAlnSzShftCnt;
631  if (!bin->alignment) {
632  bin->alignment = 1 << 9;
633  }
634  bin->os = __get_target_os(bin);
635 
636  ut16 offset = bin->ne_header->SegTableOffset + bin->header_offset;
637  ut16 size = bin->ne_header->SegCount * sizeof(NE_image_segment_entry);
638  if (!size) {
639  return false;
640  }
641  bin->segment_entries = calloc(bin->ne_header->SegCount, sizeof(NE_image_segment_entry));
642  if (!bin->segment_entries) {
643  return false;
644  }
645  rz_buf_read_at(buf, offset, (ut8 *)bin->segment_entries, size);
646  if (!bin->ne_header->EntryTableLength) {
647  return false;
648  }
649  bin->entry_table = calloc(1, bin->ne_header->EntryTableLength);
650  if (!bin->entry_table) {
651  return false;
652  }
653  rz_buf_read_at(buf, (ut64)bin->header_offset + bin->ne_header->EntryTableOffset, bin->entry_table, bin->ne_header->EntryTableLength);
654  bin->imports = rz_bin_ne_get_imports(bin);
656  return true;
657 }
voidpf void uLong size
Definition: ioapi.h:138
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static char * __get_target_os(rz_bin_ne_obj_t *bin)
Definition: ne.c:6
RzList * rz_bin_ne_get_imports(rz_bin_ne_obj_t *bin)
Definition: ne.c:348
static bool __ne_get_resources(rz_bin_ne_obj_t *bin)
Definition: ne.c:292
struct _SEGMENT NE_image_segment_entry

References __get_target_os(), __ne_get_resources(), bin::buf, calloc(), rz_bin_ne_get_imports(), rz_buf_read_at(), rz_buf_read_le16_at, RZ_NEW0, and ut64().

Referenced by rz_bin_ne_new_buf().

◆ rz_bin_ne_free()

void rz_bin_ne_free ( rz_bin_ne_obj_t bin)

Definition at line 659 of file ne.c.

659  {
660  if (!bin) {
661  return;
662  }
663  // rz_list_free (bin->imports); // double free
664  rz_list_free(bin->resources);
665  free(bin->entry_table);
666  free(bin->ne_header);
667  free(bin->resident_name_table);
668  free(bin->segment_entries);
669  free(bin);
670 }

References free(), and rz_list_free().

Referenced by destroy(), and rz_bin_ne_new_buf().

◆ rz_bin_ne_get_entrypoints()

RzList* rz_bin_ne_get_entrypoints ( rz_bin_ne_obj_t bin)

Definition at line 384 of file ne.c.

384  {
386  if (!entries) {
387  return NULL;
388  }
389  RzBinAddr *entry;
390  RzList *segments = rz_bin_ne_get_segments(bin);
391  if (!segments) {
393  return NULL;
394  }
395  if (bin->ne_header->csEntryPoint) {
397  if (!entry) {
399  return NULL;
400  }
401  entry->bits = 16;
402  RzBinSection *s = rz_list_get_n(segments, bin->ne_header->csEntryPoint - 1);
403  entry->paddr = bin->ne_header->ipEntryPoint + (s ? s->paddr : 0);
405  }
406  ut32 off = 0;
407  while (off < bin->ne_header->EntryTableLength) {
408  ut8 bundle_length = *(ut8 *)(bin->entry_table + off);
409  if (!bundle_length) {
410  break;
411  }
412  off++;
413  if (off >= bin->ne_header->EntryTableLength) {
414  break;
415  }
416  ut8 bundle_type = *(ut8 *)(bin->entry_table + off);
417  off++;
418  int i;
419  for (i = 0; i < bundle_length; i++) {
421  if (!entry) {
423  return NULL;
424  }
425  off++;
426  if (!bundle_type) { // Skip
427  off--;
428  free(entry);
429  break;
430  } else if (bundle_type == 0xFF) { // Moveable
431  off += 2;
432  ut8 segnum = *(bin->entry_table + off);
433  off++;
434  ut16 segoff = *(ut16 *)(bin->entry_table + off);
435  if (!segnum) {
436  free(entry);
437  continue;
438  }
439  entry->paddr = (ut64)bin->segment_entries[segnum - 1].offset * bin->alignment + segoff;
440  } else { // Fixed
441  ut16 *p = (ut16 *)(bin->entry_table + off);
442  if (off >= bin->ne_header->EntryTableLength || bundle_type > bin->ne_header->SegCount) {
443  free(entry);
444  continue;
445  }
446  entry->paddr = (ut64)bin->segment_entries[bundle_type - 1].offset * bin->alignment + (*p);
447  }
448  off += 2;
450  }
451  }
452  rz_list_free(segments);
453  bin->entries = entries;
454  return entries;
455 }
RzList * entries(RzBinFile *bf)
Definition: bin_ne.c:98
void * p
Definition: libc.cpp:67
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
RzList * rz_bin_ne_get_segments(rz_bin_ne_obj_t *bin)
Definition: ne.c:78
static RzSocket * s
Definition: rtr.c:28

References entries(), free(), i, NULL, off, p, rz_bin_ne_get_segments(), rz_list_append(), rz_list_free(), rz_list_get_n(), rz_list_newf(), RZ_NEW0, s, and ut64().

Referenced by entries(), and rz_bin_ne_get_symbols().

◆ rz_bin_ne_get_imports()

RzList* rz_bin_ne_get_imports ( rz_bin_ne_obj_t bin)

Definition at line 348 of file ne.c.

348  {
350  if (!imports) {
351  return NULL;
352  }
353  ut16 off = bin->ne_header->ImportNameTable + bin->header_offset + 1;
354  int i;
355  for (i = 0; i < bin->ne_header->ModRefs; i++) {
357  if (!imp) {
358  break;
359  }
360  ut8 sz;
361  if (!rz_buf_read8_at(bin->buf, off, &sz)) {
362  break;
363  }
364  if (!sz) {
365  rz_bin_import_free(imp);
366  break;
367  }
368  off++;
369  char *name = malloc((ut64)sz + 1);
370  if (!name) {
371  break;
372  }
373  rz_buf_read_at(bin->buf, off, (ut8 *)name, sz);
374  name[sz] = '\0';
375  imp->name = name;
376  imp->ordinal = i + 1;
377  rz_list_append(imports, imp);
378  off += sz;
379  }
380  bin->imports = imports;
381  return imports;
382 }
RZ_API void rz_bin_import_free(RzBinImport *imp)
Definition: bin.c:137
RzList * imports(RzBinFile *bf)
Definition: bin_ne.c:106
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
ut32 ordinal
Definition: rz_bin.h:707
char * name
Definition: rz_bin.h:701

References bin::buf, i, imports(), malloc(), name, rz_bin_import_t::name, NULL, off, rz_bin_import_t::ordinal, rz_bin_import_free(), rz_buf_read8_at(), rz_buf_read_at(), rz_list_append(), rz_list_newf(), RZ_NEW0, and ut64().

Referenced by imports(), and rz_bin_ne_buf_init().

◆ rz_bin_ne_get_relocs()

RzList* rz_bin_ne_get_relocs ( rz_bin_ne_obj_t bin)

Definition at line 457 of file ne.c.

457  {
458  RzList *segments = bin->segments;
459  if (!segments) {
460  return NULL;
461  }
462  RzList *entries = bin->entries;
463  if (!entries) {
464  return NULL;
465  }
466  RzList *symbols = bin->symbols;
467  if (!symbols) {
468  return NULL;
469  }
470 
471  ut16 *modref = calloc(bin->ne_header->ModRefs, sizeof(ut16));
472  if (!modref) {
473  return NULL;
474  }
475  rz_buf_read_at(bin->buf, (ut64)bin->ne_header->ModRefTable + bin->header_offset, (ut8 *)modref, bin->ne_header->ModRefs * sizeof(ut16));
476 
478  if (!relocs) {
479  free(modref);
480  return NULL;
481  }
482 
483  ut64 bufsz = rz_buf_size(bin->buf);
484  RzListIter *it;
485  RzBinSection *seg;
486  int index = -1;
487  rz_list_foreach (segments, it, seg) {
488  index++;
489  if (!(bin->segment_entries[index].flags & RELOCINFO)) {
490  continue;
491  }
492  ut32 off, start = off = seg->paddr + seg->size;
493  if ((ut64)off + 2 > bufsz) {
494  continue;
495  }
496  ut16 length;
497  if (!rz_buf_read_le16_at(bin->buf, off, &length)) {
498  continue;
499  }
500 
501  if (!length) {
502  continue;
503  }
504  off += 2;
505  while (off < start + length * sizeof(NE_image_reloc_item) && off + sizeof(NE_image_reloc_item) <= bufsz) {
506  RzBinReloc *reloc = RZ_NEW0(RzBinReloc);
507  if (!reloc) {
508  return NULL;
509  }
511  rz_buf_read_at(bin->buf, off, (ut8 *)&rel, sizeof(rel));
512  reloc->paddr = seg->paddr + rel.offset;
513  switch (rel.type) {
514  case LOBYTE:
515  reloc->type = RZ_BIN_RELOC_8;
516  break;
517  case SEL_16:
518  case OFF_16:
519  reloc->type = RZ_BIN_RELOC_16;
520  break;
521  case POI_32:
522  case OFF_32:
523  reloc->type = RZ_BIN_RELOC_32;
524  break;
525  case POI_48:
526  reloc->type = RZ_BIN_RELOC_64;
527  break;
528  }
529 
530  ut32 offset;
531  if (rel.flags & (IMPORTED_ORD | IMPORTED_NAME)) {
533  if (!imp) {
534  free(reloc);
535  break;
536  }
537  char *name = NULL;
538  if (rel.index > bin->ne_header->ModRefs || !rel.index) {
539  name = rz_str_newf("UnknownModule%d_%x", rel.index, off); // ????
540  } else {
541  offset = modref[rel.index - 1] + bin->header_offset + bin->ne_header->ImportNameTable;
543  }
544  if (rel.flags & IMPORTED_ORD) {
545  imp->ordinal = rel.func_ord;
546  imp->name = rz_str_newf("%s.%s", name, __func_name_from_ord(name, rel.func_ord));
547  } else {
548  offset = bin->header_offset + bin->ne_header->ImportNameTable + rel.name_off;
549  char *func = __read_nonnull_str_at(bin->buf, offset);
550  imp->name = rz_str_newf("%s.%s", name, func);
551  free(func);
552  }
553  free(name);
554  reloc->import = imp;
555  } else if (rel.flags & OSFIXUP) {
556  // TODO
557  } else {
558  if (strstr(seg->name, "FIXED")) {
559  RzBinSection *s = rz_list_get_n(segments, rel.segnum - 1);
560  if (s) {
561  offset = s->paddr + rel.segoff;
562  } else {
563  offset = -1;
564  }
565  } else {
567  if (entry) {
568  offset = entry->paddr;
569  } else {
570  offset = -1;
571  }
572  }
573  reloc->addend = offset;
574  RzBinSymbol *sym = NULL;
575  RzListIter *sit;
576  rz_list_foreach (symbols, sit, sym) {
577  if (sym->paddr == reloc->addend) {
578  reloc->symbol = sym;
579  break;
580  }
581  }
582  }
583 
584  if (rel.flags & ADDITIVE) {
585  reloc->additive = 1;
586  rz_list_append(relocs, reloc);
587  } else {
588  do {
589  rz_list_append(relocs, reloc);
590  ut16 tmp_offset;
591  if (!rz_buf_read_le16_at(bin->buf, reloc->paddr, &tmp_offset)) {
592  reloc = NULL;
593  break;
594  }
595 
596  offset = tmp_offset;
597 
598  RzBinReloc *tmp = reloc;
599  reloc = RZ_NEW0(RzBinReloc);
600  if (!reloc) {
601  break;
602  }
603  *reloc = *tmp;
604  reloc->paddr = seg->paddr + offset;
605  } while (offset != 0xFFFF);
606  free(reloc);
607  }
608 
609  off += sizeof(NE_image_reloc_item);
610  }
611  }
612  free(modref);
613  return relocs;
614 }
RzList * symbols(RzBinFile *bf)
Definition: bin_ne.c:102
RzList * relocs(RzBinFile *bf)
Definition: bin_ne.c:114
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
static char * __func_name_from_ord(char *module, ut16 ordinal)
Definition: ne.c:55
@ RELOCINFO
Definition: ne_specs.h:55
@ SEL_16
Definition: ne_specs.h:9
@ POI_48
Definition: ne_specs.h:12
@ POI_32
Definition: ne_specs.h:10
@ OFF_16
Definition: ne_specs.h:11
@ LOBYTE
Definition: ne_specs.h:8
@ OFF_32
Definition: ne_specs.h:13
@ IMPORTED_ORD
Definition: ne_specs.h:18
@ ADDITIVE
Definition: ne_specs.h:21
@ OSFIXUP
Definition: ne_specs.h:20
@ IMPORTED_NAME
Definition: ne_specs.h:19
struct _RELOC NE_image_reloc_item
@ RZ_BIN_RELOC_32
Definition: rz_bin.h:176
@ RZ_BIN_RELOC_16
Definition: rz_bin.h:174
@ RZ_BIN_RELOC_64
Definition: rz_bin.h:177
@ RZ_BIN_RELOC_8
Definition: rz_bin.h:173
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
ut16 index
Definition: ne_specs.h:29
ut16 func_ord
Definition: ne_specs.h:41
ut16 segoff
Definition: ne_specs.h:33
ut8 flags
Definition: ne_specs.h:26
ut8 segnum
Definition: ne_specs.h:31
ut16 offset
Definition: ne_specs.h:27
ut16 entry_ordinal
Definition: ne_specs.h:37
ut8 type
Definition: ne_specs.h:25
ut16 name_off
Definition: ne_specs.h:45
ut64 paddr
the paddr where the value should be patched into
Definition: rz_bin.h:717
RzBinRelocType type
Definition: rz_bin.h:712
RzBinImport * import
Definition: rz_bin.h:714
bool additive
Definition: rz_bin.h:720
st64 addend
Definition: rz_bin.h:715
RzBinSymbol * symbol
Definition: rz_bin.h:713
char * name
Definition: rz_bin.h:619

References __func_name_from_ord(), __read_nonnull_str_at(), rz_bin_reloc_t::addend, ADDITIVE, rz_bin_reloc_t::additive, bin::buf, calloc(), entries(), _RELOC::entry_ordinal, _RELOC::flags, free(), _RELOC::func_ord, rz_bin_reloc_t::import, IMPORTED_NAME, IMPORTED_ORD, _RELOC::index, length, LOBYTE, rz_bin_section_t::name, rz_bin_import_t::name, _RELOC::name_off, NULL, off, OFF_16, OFF_32, _RELOC::offset, rz_bin_import_t::ordinal, OSFIXUP, rz_bin_section_t::paddr, rz_bin_symbol_t::paddr, rz_bin_reloc_t::paddr, POI_32, POI_48, RELOCINFO, relocs(), RZ_BIN_RELOC_16, RZ_BIN_RELOC_32, RZ_BIN_RELOC_64, RZ_BIN_RELOC_8, rz_buf_read_at(), rz_buf_read_le16_at, rz_buf_size(), rz_list_append(), rz_list_get_n(), rz_list_newf(), RZ_NEW0, rz_str_newf(), s, _RELOC::segnum, _RELOC::segoff, SEL_16, rz_bin_section_t::size, start, rz_bin_reloc_t::symbol, symbols(), autogen_x86imm::tmp, _RELOC::type, rz_bin_reloc_t::type, and ut64().

Referenced by relocs().

◆ rz_bin_ne_get_segments()

RzList* rz_bin_ne_get_segments ( rz_bin_ne_obj_t bin)

Definition at line 78 of file ne.c.

78  {
79  int i;
80  if (!bin) {
81  return NULL;
82  }
84  if (!segments) {
85  return NULL;
86  }
87  for (i = 0; i < bin->ne_header->SegCount; i++) {
89  NE_image_segment_entry *se = &bin->segment_entries[i];
90  if (!bs || !se) {
91  free(bs);
92  return segments;
93  }
94  bs->size = se->length;
95  bs->vsize = se->minAllocSz ? se->minAllocSz : 64000;
96  bs->bits = RZ_SYS_BITS_16;
97  bs->is_data = se->flags & IS_DATA;
98  bs->perm = __translate_perms(se->flags);
99  bs->paddr = (ut64)se->offset * bin->alignment;
100  bs->name = rz_str_newf("%s.%" PFMT64d, se->flags & IS_MOVEABLE ? "MOVEABLE" : "FIXED", bs->paddr);
101  bs->is_segment = true;
102  rz_list_append(segments, bs);
103  }
104  bin->segments = segments;
105  return segments;
106 }
RZ_API void rz_bin_section_free(RzBinSection *bs)
Definition: bin.c:1116
static int __translate_perms(int flags)
Definition: ne.c:23
@ IS_MOVEABLE
Definition: ne_specs.h:52
@ RZ_SYS_BITS_16
Definition: rz_sys.h:19
#define PFMT64d
Definition: rz_types.h:394
ut16 offset
Definition: ne_specs.h:67
ut16 minAllocSz
Definition: ne_specs.h:70
ut16 flags
Definition: ne_specs.h:69
ut16 length
Definition: ne_specs.h:68
bool is_segment
Definition: rz_bin.h:634

References __translate_perms(), rz_bin_section_t::bits, _SEGMENT::flags, free(), i, IS_DATA, rz_bin_section_t::is_data, IS_MOVEABLE, rz_bin_section_t::is_segment, _SEGMENT::length, _SEGMENT::minAllocSz, rz_bin_section_t::name, NULL, _SEGMENT::offset, rz_bin_section_t::paddr, rz_bin_section_t::perm, PFMT64d, rz_bin_section_free(), rz_list_append(), rz_list_newf(), RZ_NEW0, rz_str_newf(), RZ_SYS_BITS_16, rz_bin_section_t::size, ut64(), and rz_bin_section_t::vsize.

Referenced by rz_bin_ne_get_entrypoints(), and sections().

◆ rz_bin_ne_get_symbols()

RzList* rz_bin_ne_get_symbols ( rz_bin_ne_obj_t bin)

Definition at line 121 of file ne.c.

121  {
122  RzBinSymbol *sym;
123  ut16 off = bin->ne_header->ResidNamTable + bin->header_offset;
125  if (!symbols) {
126  return NULL;
127  }
129  bool resident = true, first = true;
130  while (true) {
131  ut8 sz;
132  if (!rz_buf_read8_at(bin->buf, off, &sz)) {
133  break;
134  }
135  if (!sz) {
136  first = true;
137  if (resident) {
138  resident = false;
139  off = bin->ne_header->OffStartNonResTab;
140  if (!rz_buf_read8_at(bin->buf, off, &sz)) {
141  break;
142  }
143  if (!sz) {
144  break;
145  }
146  } else {
147  break;
148  }
149  }
150  char *name = malloc((ut64)sz + 1);
151  if (!name) {
152  break;
153  }
154  off++;
155  rz_buf_read_at(bin->buf, off, (ut8 *)name, sz);
156  name[sz] = '\0';
157  off += sz;
158  sym = RZ_NEW0(RzBinSymbol);
159  if (!sym) {
160  break;
161  }
162  ne_sanitize_name(name, sz);
163  sym->name = name;
164  if (!first) {
166  }
167  ut16 entry_off;
168  if (!rz_buf_read_le16_at(bin->buf, off, &entry_off)) {
169  rz_bin_symbol_free(sym);
170  break;
171  }
172  off += 2;
173  RzBinAddr *entry = rz_list_get_n(entries, entry_off);
174  if (entry) {
175  sym->paddr = entry->paddr;
176  } else {
177  sym->paddr = -1;
178  }
179  sym->ordinal = entry_off;
180  rz_list_append(symbols, sym);
181  first = false;
182  }
183  RzListIter *it;
184  RzBinAddr *en;
185  int i = 1;
186  rz_list_foreach (entries, it, en) {
188  sym = RZ_NEW0(RzBinSymbol);
189  if (!sym) {
190  break;
191  }
192  sym->name = rz_str_newf("entry%d", i - 1);
193  sym->paddr = en->paddr;
195  sym->ordinal = i;
196  rz_list_append(symbols, sym);
197  }
198  i++;
199  }
200  bin->symbols = symbols;
201  return symbols;
202 }
RZ_API void rz_bin_symbol_free(RzBinSymbol *sym)
Definition: bin.c:175
RZ_API RZ_BORROW RzListIter * rz_list_find(RZ_NONNULL const RzList *list, const void *p, RZ_NONNULL RzListComparator cmp)
Returns RzListIter element which matches via the RzListComparator.
Definition: list.c:620
static void ne_sanitize_name(char *name, ut16 count)
Definition: ne.c:112
RzList * rz_bin_ne_get_entrypoints(rz_bin_ne_obj_t *bin)
Definition: ne.c:384
static int __find_symbol_by_paddr(const void *paddr, const void *sym)
Definition: ne.c:108
#define RZ_BIN_BIND_GLOBAL_STR
Definition: rz_bin.h:107
ut64 paddr
Definition: rz_bin.h:187
const char * bind
Definition: rz_bin.h:681
char * name
Definition: rz_bin.h:675
ut32 ordinal
Definition: rz_bin.h:692

References __find_symbol_by_paddr(), rz_bin_symbol_t::bind, bin::buf, entries(), free(), i, malloc(), name, rz_bin_symbol_t::name, ne_sanitize_name(), NULL, off, rz_bin_symbol_t::ordinal, rz_bin_addr_t::paddr, rz_bin_symbol_t::paddr, RZ_BIN_BIND_GLOBAL_STR, rz_bin_ne_get_entrypoints(), rz_bin_symbol_free(), rz_buf_read8_at(), rz_buf_read_at(), rz_buf_read_le16_at, rz_list_append(), rz_list_find(), rz_list_get_n(), rz_list_newf(), RZ_NEW0, rz_str_newf(), symbols(), and ut64().

Referenced by symbols().

◆ rz_bin_ne_new_buf()

rz_bin_ne_obj_t* rz_bin_ne_new_buf ( RzBuffer buf,
bool  verbose 
)

Definition at line 672 of file ne.c.

672  {
674  if (!bin) {
675  return NULL;
676  }
677  if (!rz_bin_ne_buf_init(buf, bin)) {
679  return NULL;
680  }
681  return bin;
682 }
void rz_bin_ne_free(rz_bin_ne_obj_t *bin)
Definition: ne.c:659
bool rz_bin_ne_buf_init(RzBuffer *buf, rz_bin_ne_obj_t *bin)
Definition: ne.c:616

References NULL, rz_bin_ne_buf_init(), rz_bin_ne_free(), and RZ_NEW0.

Referenced by load_buffer().