Rizin
unix-like reverse engineering framework and cli tools
yank.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2019 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2009-2019 dso <dso@rice.edu>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_core.h>
6 #include <rz_util.h>
7 #include <rz_io.h>
8 
9 #include "core_private.h"
10 
11 /* \brief Maps in a file and yank from \p offset the number of \p len bytes from \p filename.
12  *
13  * If the len is -1, the all the bytes are mapped into the yank buffer.
14  */
15 static int perform_mapped_file_yank(RzCore *core, ut64 offset, ut64 len, const char *filename) {
16  // grab the current file descriptor, so we can reset core and io state
17  // after our io op is done
18  RzIODesc *yankdesc = NULL;
19  ut64 fd = core->file ? core->file->fd : -1, yank_file_sz = 0, addr = offset;
20  int res = false;
21 
23  ut64 load_align = rz_config_get_i(core->config, "file.loadalign");
24  yankdesc = rz_io_open_nomap(core->io, filename, RZ_PERM_R, 0644);
25  // map the file in for IO operations.
26  if (yankdesc && load_align) {
27  yank_file_sz = rz_io_size(core->io);
28  ut64 addr = rz_io_map_next_available(core->io, 0, yank_file_sz, load_align);
29  RzIOMap *map = rz_io_map_new(core->io, yankdesc->fd, RZ_PERM_R, 0, addr, yank_file_sz);
30  if (!map || map->itv.addr == -1) {
31  eprintf("Unable to map the opened file: %s", filename);
32  rz_io_desc_close(yankdesc);
33  yankdesc = NULL;
34  }
35  }
36  }
37 
38  // if len is -1 then we yank in everything
39  if (len == -1) {
40  len = yank_file_sz;
41  }
42 
43  // this wont happen if the file failed to open or the file failed to
44  // map into the IO layer
45  if (yankdesc) {
46  ut64 res = rz_io_seek(core->io, addr, RZ_IO_SEEK_SET);
47  ut64 actual_len = len <= yank_file_sz ? len : 0;
48  ut8 *buf = NULL;
49  if (actual_len > 0 && res == addr) {
50  buf = malloc(actual_len);
51  rz_io_read_at(core->io, addr, buf, actual_len);
52  rz_core_yank_set(core, RZ_CORE_FOREIGN_ADDR, buf, len);
53  } else if (res != addr) {
54  eprintf(
55  "ERROR: Unable to yank data from file: (loadaddr (0x%" PFMT64x ") (addr (0x%" PFMT64x ") > file_sz (0x%" PFMT64x ")\n", res, addr,
56  yank_file_sz);
57  } else if (actual_len == 0) {
58  eprintf(
59  "ERROR: Unable to yank from file: addr+len (0x%" PFMT64x ") > file_sz (0x%" PFMT64x ")\n", addr + len,
60  yank_file_sz);
61  }
62  rz_io_desc_close(yankdesc);
63  free(buf);
64  }
65  if (fd != -1) {
66  rz_io_use_fd(core->io, fd);
67  core->switch_file_view = 1;
68  rz_core_block_read(core);
69  }
70  return res;
71 }
72 
73 /* \brief Sets the contents of the yank clipboard
74  *
75  * Function sets the contents of the yank clibpoards as the raw bytes
76  *
77  * \p core RzCore instance
78  * \p addr Address "where" the information was yanked from
79  * \p buf Contents of the buffer to be set as the clipboard
80  * \p len Length of the buffer
81  */
83  rz_return_val_if_fail(buf, false);
84  if (!len) {
85  return false;
86  }
88  core->yank_addr = addr;
89  return true;
90 }
91 
92 /* \brief Sets the contents of the yank clipboard
93  *
94  * Function sets the contents of the yank clibpoards as the NULL-terminated string
95  *
96  * \p core RzCore instance
97  * \p addr Address "where" the information was yanked from
98  * \p str Zero-terminated string to be set as the clipboard
99  * \p len Length of the buffer
100  */
102  rz_return_val_if_fail(str, false);
103  size_t len = strlen(str) + 1;
104  bool res = rz_core_yank_set(core, addr, (ut8 *)str, len);
105  if (res == true) {
106  ut8 zero = 0;
107  rz_buf_write_at(core->yank_buf, len - 1, &zero, sizeof(zero));
108  }
109  return res;
110 }
111 
112 /* \brief Yank the data at address \p addr into the clipboard
113  *
114  * \p core RzCore instance
115  * \p addr Address we yank the data from
116  * \p len Length of the data to be yanked
117  */
119  if (len == 0) {
120  len = core->blocksize;
121  }
122  ut64 curseek = core->offset;
123  ut8 *buf = malloc(len);
124  if (!buf) {
125  return false;
126  }
127  if (addr != core->offset) {
128  rz_core_seek(core, addr, true);
129  }
130  rz_io_read_at(core->io, addr, buf, len);
131  rz_core_yank_set(core, addr, buf, len);
132  if (curseek != addr) {
133  rz_core_seek(core, curseek, true);
134  }
135  free(buf);
136  return true;
137 }
138 
139 /* \brief Copy a zero-terminated string to the clipboard.
140  *
141  * Limited either by \p maxlen or the block size
142  *
143  * \p core RzCore instance
144  * \p addr Address we yank the data from
145  * \p maxlen Maximum length of the string
146  */
148  ut64 curseek = core->offset;
149  if (addr != core->offset) {
150  rz_core_seek(core, addr, true);
151  }
152  /* Ensure space and safe termination for largest possible string allowed */
153  ut8 *buf = calloc(1, core->blocksize + 1);
154  if (!buf) {
155  return false;
156  }
157  buf[core->blocksize] = 0;
158  rz_io_read_at(core->io, addr, buf, core->blocksize);
159  if (maxlen == 0) {
160  maxlen = rz_str_nlen((const char *)buf, core->blocksize);
161  } else if (maxlen > core->blocksize) {
162  maxlen = core->blocksize;
163  }
164  rz_core_yank_set(core, addr, buf, maxlen);
165  if (curseek != addr) {
166  rz_core_seek(core, curseek, true);
167  }
168  free(buf);
169  return true;
170 }
171 
172 /* \brief Paste \p len bytes from the clipboard to the \p addr address
173  */
175  if (len == 0 || len >= rz_buf_size(core->yank_buf)) {
176  len = rz_buf_size(core->yank_buf);
177  }
178  ut8 *buf = RZ_NEWS(ut8, len);
179  if (!buf) {
180  return false;
181  }
182  rz_buf_read_at(core->yank_buf, 0, buf, len);
183  bool res = rz_core_write_at(core, addr, buf, len);
184  free(buf);
185  return res;
186 }
187 
188 /* \brief Yanks data from the current offset to the specified offset
189  *
190  * At first, it copies the \p len bytes from the current offset,
191  * then it pastes the same amount of bytes to the specified \p addr address
192  */
194  bool res = false;
195  if (rz_core_yank(core, core->offset, len) == true) {
196  res = rz_core_yank_paste(core, addr, len);
197  }
198  return res;
199 }
200 
201 /* \brief Represents yank clipboard contents as hexadecimal string starting from the \p pos position
202  */
204  int i = 0;
205  RzStrBuf *buf = rz_strbuf_new("");
206  for (i = pos; i < rz_buf_size(core->yank_buf); i++) {
207  ut8 tmp;
208  if (!rz_buf_read8_at(core->yank_buf, i, &tmp)) {
210  return NULL;
211  }
212  rz_strbuf_appendf(buf, "%02x", tmp);
213  }
214  return rz_strbuf_drain(buf);
215 }
216 
217 /* \brief Prints yank clipboard contents starting from the \p pos position in various modes
218  */
220  RzOutputMode mode = state->mode;
221  PJ *pj = state->d.pj;
222  int ybl = rz_buf_size(core->yank_buf);
223  if (ybl <= 0) {
224  RZ_LOG_ERROR("No buffer yanked already\n");
225  return false;
226  }
227  if (pos >= ybl) {
228  RZ_LOG_ERROR("Position exceeds buffer length.\n");
229  return false;
230  }
231  char *str = rz_core_yank_as_string(core, pos);
232  if (!str) {
233  return false;
234  }
235 
236  switch (mode) {
239  break;
240  case RZ_OUTPUT_MODE_JSON: {
241  pj_o(pj);
242  pj_kn(pj, "addr", core->yank_addr);
243  pj_ks(pj, "bytes", str);
244  pj_end(pj);
245  break;
246  }
248  rz_cons_printf("wx %s", str);
249  rz_cons_newline();
250  break;
252  rz_cons_printf("0x%08" PFMT64x " %" PFMT64d " ",
253  core->yank_addr + pos,
254  rz_buf_size(core->yank_buf) - pos);
256  break;
257  default:
259  break;
260  }
261  free(str);
262  return true;
263 }
264 
265 /* \brief Shows yank clipboard contents as columns of hexadecimal output with headers
266  */
268  int ybl = rz_buf_size(core->yank_buf);
269  if (ybl <= 0) {
270  RZ_LOG_ERROR("No buffer yanked already\n");
271  return false;
272  }
273  if (pos >= ybl) {
274  RZ_LOG_ERROR("Position exceeds buffer length.\n");
275  return false;
276  }
277  ut8 *buf = RZ_NEWS(ut8, ybl - pos);
278  if (!buf) {
279  return false;
280  }
281  rz_buf_read_at(core->yank_buf, pos, buf, ybl - pos);
282  rz_core_print_hexdump(core, pos, buf, ybl - pos, 16, 1, 1);
283  return true;
284 }
285 
286 /* \brief Shows yank clipboard contents as raw string starting from the \p pos position
287  */
289  int ybl = rz_buf_size(core->yank_buf);
290  if (ybl <= 0) {
291  RZ_LOG_ERROR("No buffer yanked already\n");
292  return false;
293  }
294  if (pos >= ybl) {
295  RZ_LOG_ERROR("Position exceeds buffer length.\n");
296  return false;
297  }
298  ut64 sz = ybl - pos;
299  char *buf = RZ_NEWS(char, sz);
300  if (!buf) {
301  return false;
302  }
303  rz_buf_read_at(core->yank_buf, pos, (ut8 *)buf, sz);
304  rz_cons_memcat(buf, sz);
305  rz_cons_newline();
306  return true;
307 }
308 
309 /* \brief Shows yank clipboard contents as zero-terminated string starting from the \p pos position
310  */
312  int ybl = rz_buf_size(core->yank_buf);
313  if (ybl <= 0) {
314  RZ_LOG_ERROR("No buffer yanked already\n");
315  return false;
316  }
317  if (pos >= ybl) {
318  RZ_LOG_ERROR("Position exceeds buffer length.\n");
319  return false;
320  }
321  size_t sz = ybl - pos;
322  char *buf = RZ_NEWS(char, sz);
323  if (!buf) {
324  return false;
325  }
326  rz_buf_read_at(core->yank_buf, pos, (ut8 *)buf, sz);
327  int len = rz_str_nlen(buf, sz);
329  rz_cons_newline();
330  return true;
331 }
332 
333 RZ_API bool rz_core_yank_hud_file(RzCore *core, const char *input) {
334  if (RZ_STR_ISEMPTY(input)) {
335  return false;
336  }
337  char *buf = rz_cons_hud_file(input);
338  if (RZ_STR_ISEMPTY(buf)) {
339  return false;
340  }
341  bool res = rz_core_yank_set_str(core, RZ_CORE_FOREIGN_ADDR, buf);
342  free(buf);
343  return res;
344 }
345 
346 RZ_API bool rz_core_yank_hud_path(RzCore *core, const char *input, int dir) {
347  if (RZ_STR_ISEMPTY(input)) {
348  return false;
349  }
350  char *buf = rz_cons_hud_path(input, dir);
351  if (RZ_STR_ISEMPTY(buf)) {
352  free(buf);
353  return false;
354  }
355  bool res = rz_core_yank_set_str(core, RZ_CORE_FOREIGN_ADDR, buf);
356  free(buf);
357  return res;
358 }
359 
360 /* \brief Set the yank clipboard contents to the hexadecimal string
361  */
362 RZ_API bool rz_core_yank_hexpair(RzCore *core, const char *str) {
363  if (RZ_STR_ISEMPTY(str)) {
364  return false;
365  }
366  char *out = strdup(str);
367  int len = rz_hex_str2bin(str, (ut8 *)str);
368  if (len > 0) {
369  rz_core_yank_set(core, core->offset, (ut8 *)out, len);
370  }
371  free(out);
372  return true;
373 }
374 
375 /* \brief Yank the data from the file into the clipboard
376  *
377  * Reads \p len bytes from the \p filename starting at the \p addr position.
378  *
379  * \p core RzCore instance
380  * \p len Length of the data to be yanked
381  * \p addr Address we yank the data from (offset in the file)
382  * \p filename File we yank the data from
383  */
384 RZ_API bool rz_core_yank_file(RzCore *core, ut64 len, ut64 addr, const char *filename) {
385  if (RZ_STR_ISEMPTY(filename)) {
386  return false;
387  }
388  return perform_mapped_file_yank(core, addr, len, filename);
389 }
390 
391 /* \brief Yank all the data from the file into the clipboard
392  *
393  * Reads everything from the \p filename starting at the 0 position.
394  *
395  * \p core RzCore instance
396  * \p filename File we yank the data from
397  */
398 RZ_API bool rz_core_yank_file_all(RzCore *core, const char *filename) {
399  if (RZ_STR_ISEMPTY(filename)) {
400  return false;
401  }
402  return perform_mapped_file_yank(core, 0, -1, filename);
403 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
RZ_API bool rz_core_write_at(RzCore *core, ut64 addr, const ut8 *buf, int size)
Definition: cio.c:145
RZ_API int rz_core_block_read(RzCore *core)
Definition: cio.c:243
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:119
RZ_API int rz_cons_memcat(const char *str, int len)
Definition: cons.c:1224
RZ_API void rz_cons_newline(void)
Definition: cons.c:1274
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API void rz_cons_println(const char *str)
Definition: cons.c:233
#define RZ_API
RZ_IPI void rz_core_print_hexdump(RZ_NONNULL RzCore *core, ut64 addr, RZ_NONNULL const ut8 *buf, int len, int base, int step, size_t zoomsz)
Definition: cprint.c:161
#define NULL
Definition: cris-opc.c:27
size_t map(int syms, int left, int len)
Definition: enough.c:237
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API char * rz_cons_hud_path(const char *path, int dir)
Definition: hud.c:285
RZ_API char * rz_cons_hud_file(const char *f)
Definition: hud.c:10
const char * filename
Definition: ioapi.h:137
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * malloc(size_t size)
Definition: malloc.c:123
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")
#define eprintf(x, y...)
Definition: rlcc.c:7
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API st64 rz_buf_write_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL const ut8 *buf, ut64 len)
Write len bytes of the buffer at the specified address.
Definition: buf.c:1197
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
RZ_API bool rz_buf_set_bytes(RZ_NONNULL RzBuffer *b, RZ_NONNULL const ut8 *buf, ut64 len)
Replace the content of the buffer with the bytes array.
Definition: buf.c:905
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
RZ_API int rz_hex_str2bin(const char *in, ut8 *out)
Convert an input string in into the binary form in out.
Definition: hex.c:444
RZ_API ut64 rz_io_seek(RzIO *io, ut64 offset, int whence)
Definition: io.c:632
RZ_API bool rz_io_read_at(RzIO *io, ut64 addr, ut8 *buf, int len)
Definition: io.c:300
RZ_API ut64 rz_io_map_next_available(RzIO *io, ut64 addr, ut64 size, ut64 load_align)
Definition: io_map.c:347
RZ_API ut64 rz_io_size(RzIO *io)
Definition: io.c:399
#define RZ_IO_SEEK_SET
Definition: rz_io.h:15
RZ_API RzIODesc * rz_io_open_nomap(RzIO *io, const char *uri, int flags, int mode)
Definition: io.c:145
RZ_API bool rz_io_use_fd(RzIO *io, int fd)
Definition: io_fd.c:118
RZ_API RzIOMap * rz_io_map_new(RzIO *io, int fd, int flags, ut64 delta, ut64 addr, ut64 size)
Definition: io_map.c:50
RZ_API bool rz_io_desc_close(RzIODesc *desc)
Definition: io_desc.c:165
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
Definition: pj.c:121
#define RZ_STR_ISNOTEMPTY(x)
Definition: rz_str.h:68
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
RZ_API size_t rz_str_nlen(const char *s, size_t n)
Definition: str.c:1949
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
#define RZ_NEWS(x, y)
Definition: rz_types.h:283
#define PFMT64d
Definition: rz_types.h:394
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NONNULL
Definition: rz_types.h:64
RzOutputMode
Enum to describe the way data are printed.
Definition: rz_types.h:38
@ RZ_OUTPUT_MODE_JSON
Definition: rz_types.h:40
@ RZ_OUTPUT_MODE_QUIET
Definition: rz_types.h:42
@ RZ_OUTPUT_MODE_RIZIN
Definition: rz_types.h:41
@ RZ_OUTPUT_MODE_STANDARD
Definition: rz_types.h:39
#define PFMT64x
Definition: rz_types.h:393
RZ_API bool rz_core_seek(RzCore *core, ut64 addr, bool rb)
Seek to addr.
Definition: seek.c:116
Definition: rz_pj.h:12
Represent the output state of a command handler.
Definition: rz_cmd.h:91
ut64 yank_addr
Definition: rz_core.h:307
RzBuffer * yank_buf
Definition: rz_core.h:306
ut64 offset
Definition: rz_core.h:301
RzIO * io
Definition: rz_core.h:313
ut8 switch_file_view
Definition: rz_core.h:364
RzCoreFile * file
Definition: rz_core.h:314
ut32 blocksize
Definition: rz_core.h:303
RzConfig * config
Definition: rz_core.h:300
int fd
Definition: rz_io.h:96
Definition: dis.h:43
int pos
Definition: main.c:11
ut64 maxlen
Definition: core.c:76
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
RZ_API bool rz_core_yank_to(RzCore *core, ut64 len, ut64 addr)
Definition: yank.c:193
RZ_API bool rz_core_yank_hud_file(RzCore *core, const char *input)
Definition: yank.c:333
RZ_API bool rz_core_yank(RzCore *core, ut64 addr, ut64 len)
Definition: yank.c:118
RZ_API bool rz_core_yank_set_str(RzCore *core, ut64 addr, RZ_NONNULL const char *str)
Definition: yank.c:101
RZ_API bool rz_core_yank_set(RzCore *core, ut64 addr, RZ_NONNULL const ut8 *buf, ut64 len)
Definition: yank.c:82
RZ_API bool rz_core_yank_hexpair(RzCore *core, const char *str)
Definition: yank.c:362
RZ_API bool rz_core_yank_file_all(RzCore *core, const char *filename)
Definition: yank.c:398
RZ_API bool rz_core_yank_hud_path(RzCore *core, const char *input, int dir)
Definition: yank.c:346
static int perform_mapped_file_yank(RzCore *core, ut64 offset, ut64 len, const char *filename)
Definition: yank.c:15
RZ_API bool rz_core_yank_file(RzCore *core, ut64 len, ut64 addr, const char *filename)
Definition: yank.c:384
RZ_API bool rz_core_yank_string(RzCore *core, ut64 addr, ut64 maxlen)
Definition: yank.c:147
RZ_API bool rz_core_yank_print_string(RzCore *core, ut64 pos)
Definition: yank.c:311
RZ_API bool rz_core_yank_dump(RzCore *core, ut64 pos, RzCmdStateOutput *state)
Definition: yank.c:219
RZ_API bool rz_core_yank_paste(RzCore *core, ut64 addr, ut64 len)
Definition: yank.c:174
RZ_API bool rz_core_yank_print(RzCore *core, ut64 pos)
Definition: yank.c:288
RZ_API RZ_OWN char * rz_core_yank_as_string(RzCore *core, ut64 pos)
Definition: yank.c:203
RZ_API bool rz_core_yank_print_hexdump(RzCore *core, ut64 pos)
Definition: yank.c:267
static const z80_opcode fd[]
Definition: z80_tab.h:997
static int addr
Definition: z80asm.c:58
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)