Rizin
unix-like reverse engineering framework and cli tools
bin_nro.c File Reference
#include <rz_types.h>
#include <rz_util.h>
#include <rz_lib.h>
#include <rz_bin.h>
#include "nxo/nxo.h"

Go to the source code of this file.

Classes

struct  NROHeader
 

Macros

#define NRO_OFF(x)   (sizeof(NXOStart) + rz_offsetof(NROHeader, x))
 
#define NRO_OFFSET_MODMEMOFF   rz_offsetof(NXOStart, mod_memoffset)
 

Functions

static ut64 baddr (RzBinFile *bf)
 
static bool check_buffer (RzBuffer *b)
 
static bool load_buffer (RzBinFile *bf, RzBinObject *obj, RzBuffer *b, Sdb *sdb)
 
static RzBinAddrbinsym (RzBinFile *bf, RzBinSpecialSymbol type)
 
static RzListentries (RzBinFile *bf)
 
static Sdbget_sdb (RzBinFile *bf)
 
static RzListmaps (RzBinFile *bf)
 
static RzListsections (RzBinFile *bf)
 
static RzListsymbols (RzBinFile *bf)
 
static RzListimports (RzBinFile *bf)
 
static RzListlibs (RzBinFile *bf)
 
static RzBinInfoinfo (RzBinFile *bf)
 

Variables

RzBinPlugin rz_bin_plugin_nro
 
RZ_API RzLibStruct rizin_plugin
 

Macro Definition Documentation

◆ NRO_OFF

#define NRO_OFF (   x)    (sizeof(NXOStart) + rz_offsetof(NROHeader, x))

Definition at line 11 of file bin_nro.c.

◆ NRO_OFFSET_MODMEMOFF

#define NRO_OFFSET_MODMEMOFF   rz_offsetof(NXOStart, mod_memoffset)

Definition at line 12 of file bin_nro.c.

Function Documentation

◆ baddr()

static ut64 baddr ( RzBinFile bf)
static

Definition at line 30 of file bin_nro.c.

30  {
31  if (!bf) {
32  return 0;
33  }
34 
35  ut32 result;
36  if (!rz_buf_read_le32_at(bf->buf, NRO_OFFSET_MODMEMOFF, &result)) {
37  return 0;
38  }
39 
40  return result;
41 }
#define NRO_OFFSET_MODMEMOFF
Definition: bin_nro.c:12
uint32_t ut32
#define rz_buf_read_le32_at(b, addr, result)
Definition: rz_buf.h:271
RzBuffer * buf
Definition: rz_bin.h:303

References rz_bin_file_t::buf, NRO_OFFSET_MODMEMOFF, and rz_buf_read_le32_at.

Referenced by entries(), load_buffer(), maps(), and sections().

◆ binsym()

static RzBinAddr* binsym ( RzBinFile bf,
RzBinSpecialSymbol  type 
)
static

Definition at line 73 of file bin_nro.c.

73  {
74  return NULL; // TODO
75 }
#define NULL
Definition: cris-opc.c:27

References NULL.

◆ check_buffer()

static bool check_buffer ( RzBuffer b)
static

Definition at line 43 of file bin_nro.c.

43  {
44  ut8 magic[4];
45  if (rz_buf_read_at(b, NRO_OFF(magic), magic, sizeof(magic)) == 4) {
46  return fileType(magic) != NULL;
47  }
48  return false;
49 }
#define NRO_OFF(x)
Definition: bin_nro.c:11
uint8_t ut8
Definition: lh5801.h:11
const char * fileType(const ut8 *buf)
Definition: nxo.c:24
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 b(i)
Definition: sha256.c:42

References b, fileType(), NRO_OFF, NULL, and rz_buf_read_at().

◆ entries()

static RzList* entries ( RzBinFile bf)
static

Definition at line 77 of file bin_nro.c.

77  {
78  RzList *ret;
79  RzBinAddr *ptr = NULL;
80  if (!(ret = rz_list_new())) {
81  return NULL;
82  }
83  ret->free = free;
84  if ((ptr = RZ_NEW0(RzBinAddr))) {
85  ptr->paddr = 0x80;
86  ptr->vaddr = ptr->paddr + baddr(bf);
87  rz_list_append(ret, ptr);
88  }
89  return ret;
90 }
static ut64 baddr(RzBinFile *bf)
Definition: bin_nro.c:30
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
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
#define RZ_NEW0(x)
Definition: rz_types.h:284
ut64 vaddr
Definition: rz_bin.h:186
ut64 paddr
Definition: rz_bin.h:187
RzListFree free
Definition: rz_list.h:21

References baddr(), rz_list_t::free, free(), NULL, rz_bin_addr_t::paddr, rz_list_append(), rz_list_new(), RZ_NEW0, and rz_bin_addr_t::vaddr.

◆ get_sdb()

static Sdb* get_sdb ( RzBinFile bf)
static

Definition at line 92 of file bin_nro.c.

92  {
93  Sdb *kv = sdb_new0();
94  sdb_num_set(kv, "nro_start.offset", 0, 0);
95  sdb_num_set(kv, "nro_start.size", 16, 0);
96  sdb_set(kv, "nro_start.format", "xxq unused mod_memoffset padding", 0);
97  sdb_num_set(kv, "nro_header.offset", 16, 0);
98  sdb_num_set(kv, "nro_header.size", 0x70, 0);
99  sdb_set(kv, "nro_header.format", "xxxxxxxxxxxx magic unk size unk2 text_offset text_size ro_offset ro_size data_offset data_size bss_size unk3", 0);
100  sdb_ns_set(bf->sdb, "info", kv);
101  return kv;
102 }
RZ_API int sdb_ns_set(Sdb *s, const char *name, Sdb *r)
Definition: ns.c:156
RZ_API int sdb_num_set(Sdb *s, const char *key, ut64 v, ut32 cas)
Definition: num.c:25
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
RZ_API Sdb * sdb_new0(void)
Definition: sdb.c:43
RZ_DEPRECATE Sdb * sdb
deprecated, put info in C structures instead of this
Definition: rz_bin.h:315
Definition: sdb.h:63

References rz_bin_file_t::sdb, sdb_new0(), sdb_ns_set(), sdb_num_set(), and sdb_set().

◆ imports()

static RzList* imports ( RzBinFile bf)
static

Definition at line 281 of file bin_nro.c.

281  {
282  RzBinNXOObj *bin;
283  if (!bf || !bf->o || !bf->o->bin_obj) {
284  return NULL;
285  }
286  bin = (RzBinNXOObj *)bf->o->bin_obj;
287  return bin->imports_list;
288 }
Definition: malloc.c:26
RzBinObject * o
Definition: rz_bin.h:305
void * bin_obj
Definition: rz_bin.h:293

References rz_bin_object_t::bin_obj, NULL, and rz_bin_file_t::o.

◆ info()

static RzBinInfo* info ( RzBinFile bf)
static

Definition at line 294 of file bin_nro.c.

294  {
295  RzBinInfo *ret = RZ_NEW0(RzBinInfo);
296  if (!ret) {
297  return NULL;
298  }
299  ut8 magic[4];
300  rz_buf_read_at(bf->buf, NRO_OFF(magic), magic, sizeof(magic));
301  const char *ft = fileType(magic);
302  if (!ft) {
303  ft = "nro";
304  }
305  ret->file = strdup(bf->file);
306  ret->rclass = strdup(ft);
307  ret->os = strdup("switch");
308  ret->arch = strdup("arm");
309  ret->machine = strdup("Nintendo Switch");
310  ret->subsystem = strdup(ft);
311  if (!strncmp(ft, "nrr", 3)) {
312  ret->bclass = strdup("program");
313  ret->type = strdup("EXEC (executable file)");
314  } else if (!strncmp(ft, "nro", 3)) {
315  ret->bclass = strdup("object");
316  ret->type = strdup("OBJECT (executable code)");
317  } else { // mod
318  ret->bclass = strdup("library");
319  ret->type = strdup("MOD (executable library)");
320  }
321  ret->bits = 64;
322  ret->has_va = true;
323  ret->big_endian = false;
324  ret->dbg_info = 0;
325  ret->dbg_info = 0;
326  return ret;
327 }
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")
char * file
Definition: rz_bin.h:299
int has_va
Definition: rz_bin.h:228
char * type
Definition: rz_bin.h:211
char * os
Definition: rz_bin.h:219
char * subsystem
Definition: rz_bin.h:220
char * machine
Definition: rz_bin.h:216
char * bclass
Definition: rz_bin.h:212
char * file
Definition: rz_bin.h:210
ut64 dbg_info
Definition: rz_bin.h:240
char * rclass
Definition: rz_bin.h:213
char * arch
Definition: rz_bin.h:214
int big_endian
Definition: rz_bin.h:235

References rz_bin_info_t::arch, rz_bin_info_t::bclass, rz_bin_info_t::big_endian, rz_bin_info_t::bits, rz_bin_file_t::buf, rz_bin_info_t::dbg_info, rz_bin_info_t::file, rz_bin_file_t::file, fileType(), rz_bin_info_t::has_va, rz_bin_info_t::machine, NRO_OFF, NULL, rz_bin_info_t::os, rz_bin_info_t::rclass, rz_buf_read_at(), RZ_NEW0, strdup(), rz_bin_info_t::subsystem, and rz_bin_info_t::type.

◆ libs()

static RzList* libs ( RzBinFile bf)
static

Definition at line 290 of file bin_nro.c.

290  {
291  return NULL;
292 }

References NULL.

◆ load_buffer()

static bool load_buffer ( RzBinFile bf,
RzBinObject obj,
RzBuffer b,
Sdb sdb 
)
static

Definition at line 51 of file bin_nro.c.

51  {
52  ut32 mod0;
54  return false;
55  }
56 
57  // XX bf->buf vs b :D this load_b
59  if (!bin) {
60  return false;
61  }
62 
63  ut64 ba = baddr(bf);
66  bin->classes_list = rz_list_newf((RzListFree)free);
67  parseMod(b, bin, mod0, ba);
68  obj->bin_obj = bin;
69 
70  return true;
71 }
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 RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
void parseMod(RzBuffer *buf, RzBinNXOObj *bin, ut32 mod0, ut64 baddr)
Definition: nxo.c:130
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References b, baddr(), rz_bin_object_t::bin_obj, free(), NRO_OFFSET_MODMEMOFF, parseMod(), rz_bin_import_free(), rz_bin_symbol_free(), rz_buf_read_le32_at, rz_list_newf(), RZ_NEW0, and ut64().

◆ maps()

static RzList* maps ( RzBinFile bf)
static

Definition at line 104 of file bin_nro.c.

104  {
105  RzBuffer *b = bf->buf;
107  if (!ret) {
108  return NULL;
109  }
110 
111  ut64 ba = baddr(bf);
112  ut64 bufsz = rz_buf_size(bf->buf);
113 
114  ut32 sig0;
115  if (!rz_buf_read_le32_at(bf->buf, 0x18, &sig0)) {
116  rz_list_free(ret);
117  return NULL;
118  }
119 
120  RzBinMap *map = NULL;
121  if (sig0 && sig0 + 8 < bufsz) {
122  map = RZ_NEW0(RzBinMap);
123  if (!map) {
124  return ret;
125  }
126 
127  ut32 sig0sz;
128  if (!rz_buf_read_le32_at(bf->buf, sig0 + 4, &sig0sz)) {
129  rz_list_free(ret);
130  ret = NULL;
131  goto maps_err;
132  }
133 
134  map->name = strdup("sig0");
135  map->paddr = sig0;
136  map->psize = sig0sz;
137  map->vsize = sig0sz;
138  map->vaddr = sig0 + ba;
139  map->perm = RZ_PERM_R;
140  rz_list_append(ret, map);
141  } else {
142  RZ_LOG_ERROR("Invalid SIG0 address\n");
143  }
144 
145  // add text segment
146  if (!(map = RZ_NEW0(RzBinMap))) {
147  return ret;
148  }
149  map->name = strdup("text");
150  ut32 tmp;
151  if (!rz_buf_read_le32_at(b, NRO_OFF(text_memoffset), &tmp)) {
152  goto maps_err;
153  }
154  map->paddr = tmp;
155 
156  if (!rz_buf_read_le32_at(b, NRO_OFF(text_size), &tmp)) {
157  goto maps_err;
158  }
159  map->psize = tmp;
160 
161  map->vsize = map->psize;
162  map->vaddr = map->paddr + ba;
163  map->perm = RZ_PERM_RX;
164  rz_list_append(ret, map);
165 
166  // add ro segment
167  if (!(map = RZ_NEW0(RzBinMap))) {
168  return ret;
169  }
170  map->name = strdup("ro");
171  if (!rz_buf_read_le32_at(b, NRO_OFF(ro_memoffset), &tmp)) {
172  goto maps_err;
173  }
174  map->paddr = tmp;
175 
176  if (!rz_buf_read_le32_at(b, NRO_OFF(ro_size), &tmp)) {
177  goto maps_err;
178  }
179  map->psize = tmp;
180 
181  map->vsize = map->psize;
182  map->vaddr = map->paddr + ba;
183  map->perm = RZ_PERM_R;
184  rz_list_append(ret, map);
185 
186  // add data segment
187  if (!(map = RZ_NEW0(RzBinMap))) {
188  return ret;
189  }
190  map->name = strdup("data");
191  if (!rz_buf_read_le32_at(b, NRO_OFF(data_memoffset), &tmp)) {
192  goto maps_err;
193  }
194  map->paddr = tmp;
195 
196  if (!rz_buf_read_le32_at(b, NRO_OFF(data_size), &tmp)) {
197  goto maps_err;
198  }
199  map->psize = tmp;
200 
201  map->vsize = map->psize;
202  map->vaddr = map->paddr + ba;
203  map->perm = RZ_PERM_RW;
204  rz_list_append(ret, map);
205  return ret;
206 
207 maps_err:
208  free(map);
209  return ret;
210 }
RZ_API void rz_bin_map_free(RzBinMap *map)
Definition: bin.c:1023
size_t map(int syms, int left, int len)
Definition: enough.c:237
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_PERM_RW
Definition: rz_types.h:96
#define RZ_PERM_RX
Definition: rz_types.h:97
Description of a single memory mapping into virtual memory from a binary.
Definition: rz_bin.h:602

References b, baddr(), rz_bin_file_t::buf, free(), map(), NRO_OFF, NULL, rz_bin_map_free(), rz_buf_read_le32_at, rz_buf_size(), rz_list_append(), rz_list_free(), rz_list_newf(), RZ_LOG_ERROR, RZ_NEW0, RZ_PERM_R, RZ_PERM_RW, RZ_PERM_RX, strdup(), autogen_x86imm::tmp, and ut64().

Referenced by sections().

◆ sections()

static RzList* sections ( RzBinFile bf)
static

Definition at line 212 of file bin_nro.c.

212  {
213  RzList *ret = NULL;
214  RzBinSection *ptr = NULL;
216  return NULL;
217  }
218 
219  ut64 ba = baddr(bf);
220 
221  if (!(ptr = RZ_NEW0(RzBinSection))) {
222  return ret;
223  }
224  ptr->name = strdup("header");
225  ptr->size = 0x80;
226  ptr->vsize = 0x80;
227  ptr->paddr = 0;
228  ptr->vaddr = 0;
229  ptr->perm = RZ_PERM_R;
230  rz_list_append(ret, ptr);
231 
232  int bufsz = rz_buf_size(bf->buf);
233 
234  ut32 mod0;
235  if (!rz_buf_read_le32_at(bf->buf, NRO_OFFSET_MODMEMOFF, &mod0)) {
236  free(ret);
237  return NULL;
238  }
239 
240  if (mod0 && mod0 + 8 < bufsz) {
241  if (!(ptr = RZ_NEW0(RzBinSection))) {
242  return ret;
243  }
244  ut32 mod0sz;
245  if (!rz_buf_read_le32_at(bf->buf, mod0 + 4, &mod0sz)) {
246  free(ret);
247  return NULL;
248  }
249  ptr->name = strdup("mod0");
250  ptr->size = mod0sz;
251  ptr->vsize = mod0sz;
252  ptr->paddr = mod0;
253  ptr->vaddr = mod0 + ba;
254  ptr->perm = RZ_PERM_R; // rw-
255  rz_list_append(ret, ptr);
256  } else {
257  RZ_LOG_ERROR("Invalid MOD0 address\n");
258  }
259 
260  RzList *mappies = maps(bf);
261  if (mappies) {
262  RzList *msecs = rz_bin_sections_of_maps(mappies);
263  if (msecs) {
264  rz_list_join(ret, msecs);
265  rz_list_free(msecs);
266  }
267  rz_list_free(mappies);
268  }
269  return ret;
270 }
RZ_API RzList * rz_bin_sections_of_maps(RzList *maps)
Create a list of RzBinSection from RzBinMaps.
Definition: bin.c:1084
RZ_API void rz_bin_section_free(RzBinSection *bs)
Definition: bin.c:1116
static RzList * maps(RzBinFile *bf)
Definition: bin_nro.c:104
RZ_API bool rz_list_join(RZ_NONNULL RzList *list1, RZ_NONNULL RzList *list2)
Joins 2 list into one (list2 pointer needs to be freed by the user)
Definition: list.c:209
char * name
Definition: rz_bin.h:619

References baddr(), rz_bin_file_t::buf, free(), maps(), rz_bin_section_t::name, NRO_OFFSET_MODMEMOFF, NULL, rz_bin_section_t::paddr, rz_bin_section_t::perm, rz_bin_section_free(), rz_bin_sections_of_maps(), rz_buf_read_le32_at, rz_buf_size(), rz_list_append(), rz_list_free(), rz_list_join(), rz_list_newf(), RZ_LOG_ERROR, RZ_NEW0, RZ_PERM_R, rz_bin_section_t::size, strdup(), ut64(), rz_bin_section_t::vaddr, and rz_bin_section_t::vsize.

◆ symbols()

static RzList* symbols ( RzBinFile bf)
static

Definition at line 272 of file bin_nro.c.

272  {
273  RzBinNXOObj *bin;
274  if (!bf || !bf->o || !bf->o->bin_obj) {
275  return NULL;
276  }
277  bin = (RzBinNXOObj *)bf->o->bin_obj;
278  return bin->methods_list;
279 }

References rz_bin_object_t::bin_obj, NULL, and rz_bin_file_t::o.

Variable Documentation

◆ rizin_plugin

RZ_API RzLibStruct rizin_plugin
Initial value:
= {
.type = RZ_LIB_TYPE_BIN,
}
RzBinPlugin rz_bin_plugin_nro
Definition: bin_nro.c:331
@ RZ_LIB_TYPE_BIN
Definition: rz_lib.h:75
#define RZ_VERSION
Definition: rz_version.h:8
char * version
Definition: rz_bin.h:512

Definition at line 350 of file bin_nro.c.

◆ rz_bin_plugin_nro

RzBinPlugin rz_bin_plugin_nro
Initial value:
= {
.name = "nro",
.desc = "Nintendo Switch NRO0 binaries",
.license = "MIT",
.load_buffer = &load_buffer,
.check_buffer = &check_buffer,
.baddr = &baddr,
.binsym = &binsym,
.entries = &entries,
.maps = &maps,
.sections = &sections,
.get_sdb = &get_sdb,
.symbols = &symbols,
.imports = &imports,
.info = &info,
.libs = &libs,
}
static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *b, Sdb *sdb)
Definition: bin_nro.c:51
static Sdb * get_sdb(RzBinFile *bf)
Definition: bin_nro.c:92
static RzList * symbols(RzBinFile *bf)
Definition: bin_nro.c:272
static RzBinAddr * binsym(RzBinFile *bf, RzBinSpecialSymbol type)
Definition: bin_nro.c:73
static RzList * libs(RzBinFile *bf)
Definition: bin_nro.c:290
static bool check_buffer(RzBuffer *b)
Definition: bin_nro.c:43
static RzBinInfo * info(RzBinFile *bf)
Definition: bin_nro.c:294
static RzList * entries(RzBinFile *bf)
Definition: bin_nro.c:77
static RzList * sections(RzBinFile *bf)
Definition: bin_nro.c:212
static RzList * imports(RzBinFile *bf)
Definition: bin_nro.c:281

Definition at line 331 of file bin_nro.c.