1 /* radare - LGPL - Copyright 2009-2019 - pancake & dso */
2
3 #include "r_core.h"
4 #include "r_util.h"
5 #include "r_io.h"
6
7 /*
8 * perform_mapped_file_yank will map in a file and yank from offset the number of len bytes from
9 * filename. if the len is -1, the all the bytes are mapped into the yank buffer.
10 */
11 static int perform_mapped_file_yank(RCore *core, ut64 offset, ut64 len, const char *filename);
12 static ut32 find_next_char(const char *input, char b);
13 static ut32 consume_chars(const char *input, char b);
14
find_next_char(const char * input,char b)15 static ut32 find_next_char(const char *input, char b) {
16 ut32 i = 0;
17 if (!input) {
18 return i;
19 }
20 for (; *input != b; i++, input++) {
21 /* nothing */
22 }
23 return i;
24 }
25
consume_chars(const char * input,char b)26 static ut32 consume_chars(const char *input, char b) {
27 ut32 i = 0;
28 if (!input) {
29 return i;
30 }
31 for (; *input == b; i++, input++) {
32 /* nothing */
33 }
34 return i;
35 }
36
perform_mapped_file_yank(RCore * core,ut64 offset,ut64 len,const char * filename)37 static int perform_mapped_file_yank(RCore *core, ut64 offset, ut64 len, const char *filename) {
38 // grab the current file descriptor, so we can reset core and io state
39 // after our io op is done
40 RIODesc *yankdesc = NULL;
41 ut64 fd = core->io->desc ? core->io->desc->fd: -1, yank_file_sz = 0,
42 loadaddr = 0, addr = offset;
43 int res = false;
44
45 if (filename && *filename) {
46 ut64 load_align = r_config_get_i (core->config, "file.loadalign");
47 RIOMap *map = NULL;
48 yankdesc = r_io_open_nomap (core->io, filename, R_PERM_R, 0644);
49 // map the file in for IO operations.
50 if (yankdesc && load_align) {
51 yank_file_sz = r_io_size (core->io);
52 ut64 addr = r_io_map_next_available (core->io, 0, yank_file_sz, load_align);
53 map = r_io_map_new (core->io, yankdesc->fd, R_PERM_R, 0, addr, yank_file_sz);
54 loadaddr = map? r_io_map_begin (map): -1;
55 if (yankdesc && map && loadaddr != -1) {
56 // ***NOTE*** this is important, we need to
57 // address the file at its physical address!
58 addr += loadaddr;
59 } else if (yankdesc) {
60 eprintf ("Unable to map the opened file: %s", filename);
61 r_io_desc_close (yankdesc);
62 yankdesc = NULL;
63 } else {
64 eprintf ("Unable to open the file: %s", filename);
65 }
66 }
67 }
68
69 // if len is -1 then we yank in everything
70 if (len == -1) {
71 len = yank_file_sz;
72 }
73
74 // this wont happen if the file failed to open or the file failed to
75 // map into the IO layer
76 if (yankdesc) {
77 ut64 res = r_io_seek (core->io, addr, R_IO_SEEK_SET);
78 ut64 actual_len = len <= yank_file_sz? len: 0;
79 ut8 *buf = NULL;
80 if (actual_len > 0 && res == addr) {
81 buf = malloc (actual_len);
82 if (!r_io_read_at (core->io, addr, buf, actual_len)) {
83 actual_len = 0;
84 }
85 r_core_yank_set (core, R_CORE_FOREIGN_ADDR, buf, len);
86 res = true;
87 } else if (res != addr) {
88 eprintf (
89 "ERROR: Unable to yank data from file: (loadaddr (0x%"
90 PFMT64x ") (addr (0x%"
91 PFMT64x ") > file_sz (0x%"PFMT64x ")\n", res, addr,
92 yank_file_sz );
93 } else if (actual_len == 0) {
94 eprintf (
95 "ERROR: Unable to yank from file: addr+len (0x%"
96 PFMT64x ") > file_sz (0x%"PFMT64x ")\n", addr + len,
97 yank_file_sz );
98 }
99 r_io_desc_close (yankdesc);
100 free (buf);
101 }
102 if (fd != -1) {
103 r_io_use_fd (core->io, fd);
104 core->switch_file_view = 1;
105 r_core_block_read (core);
106 }
107 return res;
108 }
109
r_core_yank_set(RCore * core,ut64 addr,const ut8 * buf,ut32 len)110 R_API int r_core_yank_set(RCore *core, ut64 addr, const ut8 *buf, ut32 len) {
111 // free (core->yank_buf);
112 if (buf && len) {
113 // FIXME: direct access to base should be avoided (use _sparse
114 // when you need buffer that starts at given addr)
115 r_buf_set_bytes (core->yank_buf, buf, len);
116 core->yank_addr = addr;
117 return true;
118 }
119 return false;
120 }
121
122 // Call set and then null terminate the bytes.
r_core_yank_set_str(RCore * core,ut64 addr,const char * str,ut32 len)123 R_API int r_core_yank_set_str(RCore *core, ut64 addr, const char *str, ut32 len) {
124 // free (core->yank_buf);
125 int res = r_core_yank_set (core, addr, (ut8 *)str, len);
126 if (res == true) {
127 ut8 zero = 0;
128 r_buf_write_at (core->yank_buf, len - 1, &zero, sizeof (zero));
129 }
130 return res;
131 }
132
r_core_yank(struct r_core_t * core,ut64 addr,int len)133 R_API int r_core_yank(struct r_core_t *core, ut64 addr, int len) {
134 ut64 curseek = core->offset;
135 ut8 *buf = NULL;
136 if (len < 0) {
137 eprintf ("r_core_yank: cannot yank negative bytes\n");
138 return false;
139 }
140 if (len == 0) {
141 len = core->blocksize;
142 }
143 buf = malloc (len);
144 if (!buf) {
145 return false;
146 }
147 if (addr != core->offset) {
148 r_core_seek (core, addr, true);
149 }
150 r_io_read_at (core->io, addr, buf, len);
151 r_core_yank_set (core, addr, buf, len);
152 if (curseek != addr) {
153 r_core_seek (core, curseek, true);
154 }
155 free (buf);
156 return true;
157 }
158
159 /* Copy a zero terminated string to the clipboard. Clamp to maxlen or blocksize. */
r_core_yank_string(RCore * core,ut64 addr,int maxlen)160 R_API int r_core_yank_string(RCore *core, ut64 addr, int maxlen) {
161 ut64 curseek = core->offset;
162 ut8 *buf = NULL;
163 if (maxlen < 0) {
164 eprintf ("r_core_yank_string: cannot yank negative bytes\n");
165 return false;
166 }
167 if (addr != core->offset) {
168 r_core_seek (core, addr, true);
169 }
170 /* Ensure space and safe termination for largest possible string allowed */
171 buf = calloc (1, core->blocksize + 1);
172 if (!buf) {
173 return false;
174 }
175 buf[core->blocksize] = 0;
176 r_io_read_at (core->io, addr, buf, core->blocksize);
177 if (maxlen == 0) {
178 // Don't use strnlen, see: http://sourceforge.net/p/mingw/bugs/1912/
179 maxlen = r_str_nlen ((const char *) buf, core->blocksize);
180 } else if (maxlen > core->blocksize) {
181 maxlen = core->blocksize;
182 }
183 r_core_yank_set (core, addr, buf, maxlen);
184 if (curseek != addr) {
185 r_core_seek (core, curseek, true);
186 }
187 free (buf);
188 return true;
189 }
190
r_core_yank_paste(RCore * core,ut64 addr,int len)191 R_API int r_core_yank_paste(RCore *core, ut64 addr, int len) {
192 if (len < 0) {
193 return false;
194 }
195 if (len == 0 || len >= r_buf_size (core->yank_buf)) {
196 len = r_buf_size (core->yank_buf);
197 }
198 ut8 *buf = R_NEWS (ut8, len);
199 if (!buf) {
200 return false;
201 }
202 r_buf_read_at (core->yank_buf, 0, buf, len);
203 if (!r_core_write_at (core, addr, buf, len)) {
204 return false;
205 }
206 return true;
207 }
208
r_core_yank_to(RCore * core,const char * _arg)209 R_API int r_core_yank_to(RCore *core, const char *_arg) {
210 ut64 len = 0;
211 ut64 pos = -1;
212 char *str, *arg;
213 int res = false;
214
215 while (*_arg == ' ') {
216 _arg++;
217 }
218 arg = strdup (_arg);
219 str = strchr (arg, ' ');
220 if (str) {
221 str[0] = '\0';
222 len = r_num_math (core->num, arg);
223 pos = r_num_math (core->num, str + 1);
224 str[0] = ' ';
225 }
226 if (!str || pos == -1 || len == 0) {
227 eprintf ("Usage: yt [len] [dst-addr]\n");
228 free (arg);
229 return res;
230 }
231 if (r_core_yank (core, core->offset, len) == true) {
232 res = r_core_yank_paste (core, pos, len);
233 }
234 free (arg);
235 return res;
236 }
237
r_core_yank_dump(RCore * core,ut64 pos,int format)238 R_API bool r_core_yank_dump(RCore *core, ut64 pos, int format) {
239 bool res = false;
240 int i = 0;
241 int ybl = r_buf_size (core->yank_buf);
242 if (ybl > 0) {
243 if (pos < ybl) {
244 switch (format) {
245 case 'q':
246 for (i = pos; i < r_buf_size (core->yank_buf); i++) {
247 r_cons_printf ("%02x", r_buf_read8_at (core->yank_buf, i));
248 }
249 r_cons_newline ();
250 break;
251 case 'j': {
252 PJ *pj = r_core_pj_new (core);
253 if (!pj) {
254 break;
255 }
256 pj_o (pj);
257 pj_kn (pj, "addr", core->yank_addr);
258 RStrBuf *buf = r_strbuf_new ("");
259 for (i = pos; i < r_buf_size (core->yank_buf); i++) {
260 r_strbuf_appendf (buf, "%02x", r_buf_read8_at (core->yank_buf, i));
261 }
262 pj_ks (pj, "bytes", r_strbuf_get (buf));
263 r_strbuf_free (buf);
264 pj_end (pj);
265 r_cons_println (pj_string (pj));
266 pj_free (pj);
267 break;
268 }
269 case '*':
270 //r_cons_printf ("yfx ");
271 r_cons_printf ("wx ");
272 for (i = pos; i < r_buf_size (core->yank_buf); i++) {
273 r_cons_printf ("%02x", r_buf_read8_at (core->yank_buf, i));
274 }
275 //r_cons_printf (" @ 0x%08"PFMT64x, core->yank_addr);
276 r_cons_newline ();
277 break;
278 default:
279 r_cons_printf ("0x%08" PFMT64x " %" PFMT64d " ",
280 core->yank_addr + pos,
281 r_buf_size (core->yank_buf) - pos);
282 for (i = pos; i < r_buf_size (core->yank_buf); i++) {
283 r_cons_printf ("%02x", r_buf_read8_at (core->yank_buf, i));
284 }
285 r_cons_newline ();
286 }
287 res = true;
288 } else {
289 eprintf ("Position exceeds buffer length.\n");
290 }
291 } else {
292 if (format == 'j') {
293 r_cons_printf ("{}\n");
294 } else {
295 eprintf ("No buffer yanked already\n");
296 }
297 }
298 return res;
299 }
300
r_core_yank_hexdump(RCore * core,ut64 pos)301 R_API int r_core_yank_hexdump(RCore *core, ut64 pos) {
302 int res = false;
303 int ybl = r_buf_size (core->yank_buf);
304 if (ybl > 0) {
305 if (pos < ybl) {
306 ut8 *buf = R_NEWS (ut8, ybl - pos);
307 if (!buf) {
308 return false;
309 }
310 r_buf_read_at (core->yank_buf, pos, buf, ybl - pos);
311 r_print_hexdump (core->print, pos,
312 buf, ybl - pos, 16, 1, 1);
313 res = true;
314 } else {
315 eprintf ("Position exceeds buffer length.\n");
316 }
317 } else {
318 eprintf ("No buffer yanked already\n");
319 }
320 return res;
321 }
322
r_core_yank_cat(RCore * core,ut64 pos)323 R_API int r_core_yank_cat(RCore *core, ut64 pos) {
324 int ybl = r_buf_size (core->yank_buf);
325 if (ybl > 0) {
326 if (pos < ybl) {
327 ut64 sz = ybl - pos;
328 char *buf = R_NEWS (char, sz);
329 if (!buf) {
330 return false;
331 }
332 r_buf_read_at (core->yank_buf, pos, (ut8 *)buf, sz);
333 r_cons_memcat (buf, sz);
334 r_cons_newline ();
335 return true;
336 }
337 eprintf ("Position exceeds buffer length.\n");
338 } else {
339 r_cons_newline ();
340 }
341 return false;
342 }
343
r_core_yank_cat_string(RCore * core,ut64 pos)344 R_API int r_core_yank_cat_string(RCore *core, ut64 pos) {
345 int ybl = r_buf_size (core->yank_buf);
346 if (ybl > 0) {
347 if (pos < ybl) {
348 ut64 sz = ybl - pos;
349 char *buf = R_NEWS (char, sz);
350 if (!buf) {
351 return false;
352 }
353 r_buf_read_at (core->yank_buf, pos, (ut8 *)buf, sz);
354 int len = r_str_nlen (buf, sz);
355 r_cons_memcat (buf, len);
356 r_cons_newline ();
357 return true;
358 }
359 eprintf ("Position exceeds buffer length.\n");
360 } else {
361 r_cons_newline ();
362 }
363 return false;
364 }
365
r_core_yank_hud_file(RCore * core,const char * input)366 R_API int r_core_yank_hud_file(RCore *core, const char *input) {
367 char *buf = NULL;
368 bool res = false;
369 ut32 len = 0;
370 if (!input || !*input) {
371 return false;
372 }
373 for (input++; *input == ' '; input++) {
374 /* nothing */
375 }
376 buf = r_cons_hud_file (input);
377 len = buf? strlen ((const char *) buf) + 1: 0;
378 res = r_core_yank_set_str (core, R_CORE_FOREIGN_ADDR, buf, len);
379 free (buf);
380 return res;
381 }
382
r_core_yank_hud_path(RCore * core,const char * input,int dir)383 R_API int r_core_yank_hud_path(RCore *core, const char *input, int dir) {
384 char *buf = NULL;
385 ut32 len = 0;
386 int res;
387 for (input++; *input == ' '; input++) {
388 /* nothing */
389 }
390 buf = r_cons_hud_path (input, dir);
391 len = buf? strlen ((const char *) buf) + 1: 0;
392 res = r_core_yank_set_str (core, R_CORE_FOREIGN_ADDR, buf, len);
393 free (buf);
394 return res;
395 }
396
r_core_yank_hexpair(RCore * core,const char * input)397 R_API bool r_core_yank_hexpair(RCore *core, const char *input) {
398 if (!input || !*input) {
399 return false;
400 }
401 char *out = strdup (input);
402 int len = r_hex_str2bin (input, (ut8 *)out);
403 if (len > 0) {
404 r_core_yank_set (core, core->offset, (ut8 *)out, len);
405 }
406 free (out);
407 return true;
408 }
409
r_core_yank_file_ex(RCore * core,const char * input)410 R_API bool r_core_yank_file_ex(RCore *core, const char *input) {
411 ut64 len = 0, adv = 0, addr = 0;
412 bool res = false;
413
414 if (!input) {
415 return res;
416 }
417 // get the number of bytes to yank
418 adv = consume_chars (input, ' ');
419 len = r_num_math (core->num, input + adv);
420 if (len == 0) {
421 eprintf ("ERROR: Number of bytes read must be > 0\n");
422 return res;
423 }
424 // get the addr/offset from in the file we want to read
425 adv += find_next_char (input + adv, ' ');
426 if (adv == 0) {
427 eprintf ("ERROR: Address must be specified\n");
428 return res;
429 }
430 adv++;
431
432 // XXX - bug, will fail if address needs to be computed and has spaces
433 addr = r_num_math (core->num, input + adv);
434
435 adv += find_next_char (input + adv, ' ');
436 if (adv == 0) {
437 eprintf ("ERROR: File must be specified\n");
438 return res;
439 }
440 adv++;
441
442 // grab the current file descriptor, so we can reset core and io state
443 // after our io op is done
444 return perform_mapped_file_yank (core, addr, len, input + adv);
445 }
446
r_core_yank_file_all(RCore * core,const char * input)447 R_API int r_core_yank_file_all(RCore *core, const char *input) {
448 ut64 adv = 0;
449 if (!input) {
450 return false;
451 }
452 adv = consume_chars (input, ' ');
453 return perform_mapped_file_yank (core, 0, -1, input + adv);
454 }
455