Rizin
unix-like reverse engineering framework and cli tools
io_srec.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 Manolache183 <manolache.alexandru8@gmail.com>
2 // SPDX-FileCopyrightText: 2021 swym <0xfd000000@gmail.com>
3 // SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 /* Motorola S-record file format
7  * +--------+------------+---------+------+----------+----+
8  * | S type | byte count | address | data | checksum | \n |
9  * +--------+------------+---------+------+----------+----+
10  * 0 1 2 4 N N+1 N+2
11  *
12  * https://en.wikipedia.org/wiki/SREC_(file_format)
13  */
14 
15 #include <rz_io.h>
16 #include <rz_lib.h>
17 #include <rz_util.h>
18 
19 #define SREC_SIZE 64
20 #define NMAX 100
21 #define SREC_PATH_PREFIX "srec://"
22 
23 typedef struct srec_t {
27 
28 static void write_S3_record(FILE *fd, ut32 address, const ut8 *buffer, ut16 size) {
30 
31  ut8 record_size = 4 + size + 1;
32  ut8 checksum = record_size;
33  checksum += address & 0xff;
34  checksum += (address >> 8) & 0xff;
35  checksum += (address >> 16) & 0xff;
36  checksum += address >> 24;
37 
38  fprintf(fd, "S3%02x%08x", record_size, address);
39 
40  for (ut16 j = 0; j < size; j++) {
41  checksum += buffer[j];
42  fprintf(fd, "%02x", buffer[j]);
43  }
44 
45  fprintf(fd, "%02x\n", checksum);
46 }
47 
48 static st32 __write(RzIO *io, RzIODesc *fd, const ut8 *buf, st32 count) {
49  rz_return_val_if_fail(fd && fd->data && fd->perm & RZ_PERM_W && count > 0, -1);
50 
51  const char *pathname = NULL;
52  FILE *out = NULL;
53  SRecord *srec = NULL;
54  ut32 address = 0, size = 0;
55  ut8 n_bytes = 0;
56  size_t chunks_count = 0;
57  const RzBufferSparseChunk *chunks = NULL;
58  const RzBufferSparseChunk *sparse = NULL;
59 
60  srec = (SRecord *)fd->data;
61  pathname = fd->name + strlen(SREC_PATH_PREFIX);
62  out = rz_sys_fopen(pathname, "w");
63 
64  if (!out) {
65  RZ_LOG_ERROR("srec:write(): cannot open '%s' for writing\n", pathname);
66  return -1;
67  }
68 
69  // starting record, contains "rizin-srec\0"
70  fprintf(out, "S00E000072697A696E2D7372656300EB\n");
71 
72  /* mem write */
73  if (rz_buf_write_at(srec->buf, io->off, buf, count) != count) {
74  RZ_LOG_ERROR("srec:write(): cannot write into buffer\n");
75  fclose(out);
76  return -1;
77  }
78 
80  chunks = rz_buf_sparse_get_chunks(srec->buf, &chunks_count);
81 
82  for (size_t i = 0; i < chunks_count; i++) {
83  sparse = &chunks[i];
84  size = sparse->to - sparse->from;
85  for (ut32 offset = 0; offset < size; offset += SREC_SIZE) {
86  address = sparse->from + offset;
87  n_bytes = SREC_SIZE;
88  if (offset + SREC_SIZE > size) {
89  n_bytes = size - offset;
90  }
91  write_S3_record(out, address, sparse->data + offset, n_bytes);
92  }
93  }
94 
95  // termination
96  fprintf(out, "S70500000000FA\n");
97  fclose(out);
98  out = NULL;
99  return 0;
100 }
101 
102 static st32 __read(RzIO *io, RzIODesc *fd, ut8 *buf, st32 count) {
103  rz_return_val_if_fail(io && fd && fd->data && buf && count > 0, -1);
104 
105  SRecord *srec = (SRecord *)fd->data;
106  memset(buf, io->Oxff, count);
107  st32 r = rz_buf_read_at(srec->buf, io->off, buf, count);
108  if (r >= 0) {
109  rz_buf_seek(srec->buf, r, RZ_BUF_CUR);
110  }
111  // sparse read return >= 0 but < count still means everything was read successfully,
112  // just maybe not entirely populated by chunks:
113  return r < 0 ? -1 : count;
114 }
115 
117  rz_return_val_if_fail(fd && fd->data, -1);
118 
119  SRecord *srec = (SRecord *)fd->data;
120  rz_buf_free(srec->buf);
121  free(srec);
122  fd->data = NULL;
123  return 0;
124 }
125 
126 static ut64 __lseek(struct rz_io_t *io, RzIODesc *fd, ut64 offset, st32 whence) {
127  rz_return_val_if_fail(fd && fd->data, 0);
128  SRecord *srec = (SRecord *)fd->data;
129  io->off = rz_buf_seek(srec->buf, offset, whence);
130  return io->off;
131 }
132 
133 static bool __plugin_open(RzIO *io, const char *pathname, bool many) {
134  return (!strncmp(pathname, SREC_PATH_PREFIX, strlen(SREC_PATH_PREFIX)));
135 }
136 
137 static bool srecord_parse(RzBuffer *buf, char *str) {
138  if (!str || *str != 'S') {
139  return false;
140  }
141  ut8 *record_data = NULL;
142  ut32 record_size = 0;
143  ut32 record_begin = 0;
144  ut32 record_addr = 0;
145  ut32 record_next = 0;
146  char record_type = 0;
147  char *eol = NULL;
148  ut8 cksum = 0;
149  st32 byte_count = 0;
150  st32 byte = 0, i = 0, counter = 0;
151  int line = 0;
152 
153  record_data = malloc(UT16_MAX);
154  if (!record_data) {
155  goto fail;
156  }
157 
158  do {
159  line++;
160  if (sscanf(str, "S%c%02x", &record_type, &byte_count) != 2) {
161  RZ_LOG_ERROR("srec:parse(): invalid data in motorola srecord file at line %d\n", line);
162  goto fail;
163  }
164 
165  byte_count &= 0xff;
166 
167  switch (record_type) {
168  case '0': // Header with 16-bit address
169  counter = byte_count - 3;
170  if (sscanf(str + 4, "%04x", &record_addr) != 1) {
171  RZ_LOG_ERROR("srec:parse(): invalid header hexadecimal address 16-bit at line %d\n", line);
172  goto fail;
173  }
174  record_addr &= 0xffff;
175 
176  cksum = byte_count;
177  cksum += record_addr & 0xff;
178  cksum += record_addr >> 8;
179 
180  for (i = 0; i < counter; i++) {
181  if (sscanf(str + 8 + (i * 2), "%02x", &byte) != 1) {
182  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value! at line %d\n", line);
183  goto fail;
184  }
185  cksum += byte;
186  }
187  cksum = ~cksum;
188 
189  if (sscanf(str + 2 + (byte_count * 2), "%02x", &byte) != 1) {
190  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value! at line %d\n", line);
191  goto fail;
192  } else if (cksum != byte) {
193  RZ_LOG_ERROR("srec:parse(): checksum check failed (got %02x expected %02x) at line %d\n", byte, cksum, line);
194  goto fail;
195  }
196 
197  str = strchr(str + 1, 'S');
198  break;
199 
200  case '1': // Data with 16-bit address
201  counter = byte_count - 3;
202  if (sscanf(str + 4, "%04x", &record_addr) != 1) {
203  RZ_LOG_ERROR("srec:parse(): invalid data hexadecimal address 16-bit at line %d\n", line);
204  goto fail;
205  }
206  record_addr &= 0xffff;
207 
208  cksum = byte_count;
209  cksum += record_addr & 0xff;
210  cksum += record_addr >> 8;
211 
212  if ((record_next != record_addr) || ((record_size + counter) > UT16_MAX)) {
213  if (record_size && record_size < UT16_MAX) {
214  if (rz_buf_write_at(buf, record_begin, record_data, (st32)record_size) != record_size) {
215  RZ_LOG_ERROR("srec:parse(): cannot write buffer at 0x%x\n", record_begin);
216  goto fail;
217  }
218  }
219  record_begin = record_addr;
220  record_next = record_addr;
221  record_size = 0;
222  }
223 
224  for (i = 0; i < byte_count - 3; i++) {
225  if (sscanf(str + 8 + (i * 2), "%02x", &byte) != 1) {
226  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
227  goto fail;
228  }
229  if (record_size + i < UT16_MAX) {
230  record_data[record_size + i] = (ut8)byte & 0xff;
231  }
232  cksum += byte;
233  }
234  cksum = ~cksum;
235  record_size += counter;
236  record_next += counter;
237 
238  if (sscanf(str + 2 + (byte_count * 2), "%02x", &byte) != 1) {
239  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
240  goto fail;
241  } else if (cksum != byte) {
242  RZ_LOG_ERROR("srec:parse(): checksum check failed (got %02x expected %02x) at line %d\n", byte, cksum, line);
243  goto fail;
244  }
245 
246  str = strchr(str + 1, 'S');
247  break;
248 
249  case '5': // Count with 16-bit address
250  if (sscanf(str + 4, "%04x", &record_addr) != 1) {
251  RZ_LOG_ERROR("srec:parse(): invalid count hexadecimal address 16-bit at line %d\n", line);
252  goto fail;
253  }
254  record_addr &= 0xffff;
255 
256  cksum = byte_count;
257  cksum += record_addr & 0xff;
258  cksum += record_addr >> 8;
259  cksum = ~cksum;
260 
261  if (sscanf(str + 2 + (byte_count * 2), "%02x", &byte) != 1) {
262  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
263  goto fail;
264  } else if (cksum != byte) {
265  RZ_LOG_ERROR("srec:parse(): checksum check failed (got %02x expected %02x) at line %d\n", byte, cksum, line);
266  goto fail;
267  }
268 
269  str = strchr(str + 1, 'S');
270  break;
271 
272  case '9': // Terminator with 16-bit address
273  if (sscanf(str + 4, "%04x", &record_addr) != 1) {
274  RZ_LOG_ERROR("srec:parse(): invalid terminator hexadecimal address 16-bit at line %d\n", line);
275  goto fail;
276  }
277  record_addr &= 0xffff;
278 
279  cksum = byte_count;
280  cksum += record_addr & 0xff;
281  cksum += record_addr >> 8;
282  cksum = ~cksum;
283 
284  if (sscanf(str + 2 + (byte_count * 2), "%02x", &byte) != 1) {
285  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
286  goto fail;
287  } else if (cksum != byte) {
288  RZ_LOG_ERROR("srec:parse(): checksum check failed (got %02x expected %02x) at line %d\n", byte, cksum, line);
289  goto fail;
290  }
291 
292  str = strchr(str + 1, 'S');
293  break;
294  case '2': // Data with 24-bit address
295  counter = byte_count - 4;
296  if (sscanf(str + 4, "%06x", &record_addr) != 1) {
297  RZ_LOG_ERROR("srec:parse(): invalid data hexadecimal address 24-bit at line %d\n", line);
298  goto fail;
299  }
300  record_addr &= 0xffffff;
301 
302  cksum = byte_count;
303  cksum += record_addr & 0xff;
304  cksum += (record_addr >> 8) & 0xff;
305  cksum += record_addr >> 16;
306 
307  if ((record_next != record_addr) || ((record_size + counter) > UT16_MAX)) {
308  if (record_size && record_size < UT16_MAX) {
309  if (rz_buf_write_at(buf, record_begin, record_data, (st32)record_size) != record_size) {
310  RZ_LOG_ERROR("srec:parse(): cannot write buffer at 0x%x\n", record_begin);
311  goto fail;
312  }
313  }
314  record_begin = record_addr;
315  record_next = record_addr;
316  record_size = 0;
317  }
318 
319  for (i = 0; i < byte_count - 4; i++) {
320  if (sscanf(str + 10 + (i * 2), "%02x", &byte) != 1) {
321  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
322  goto fail;
323  }
324  if (record_size + i < UT16_MAX) {
325  record_data[record_size + i] = (ut8)byte & 0xff;
326  }
327  cksum += byte;
328  }
329  cksum = ~cksum;
330  record_size += counter;
331  record_next += counter;
332 
333  if (sscanf(str + 2 + (byte_count * 2), "%02x", &byte) != 1) {
334  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
335  goto fail;
336  } else if (cksum != byte) {
337  RZ_LOG_ERROR("srec:parse(): checksum check failed (got %02x expected %02x) at line %d\n", byte, cksum, line);
338  goto fail;
339  }
340 
341  str = strchr(str + 1, 'S');
342  break;
343 
344  case '6': // Count with 24-bit address
345  if (sscanf(str + 4, "%06x", &record_addr) != 1) {
346  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal address 24-bit at line %d\n", line);
347  goto fail;
348  }
349  record_addr &= 0xffffff;
350 
351  cksum = byte_count;
352  cksum += record_addr & 0xff;
353  cksum += (record_addr >> 8) & 0xff;
354  cksum += record_addr >> 16;
355  cksum = ~cksum;
356 
357  if (sscanf(str + 2 + (byte_count * 2), "%02x", &byte) != 1) {
358  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
359  goto fail;
360  } else if (cksum != byte) {
361  RZ_LOG_ERROR("srec:parse(): checksum check failed (got %02x expected %02x) at line %d\n", byte, cksum, line);
362  goto fail;
363  }
364 
365  str = strchr(str + 1, 'S');
366  break;
367 
368  case '8': // Terminator with 24-bit address
369  if (sscanf(str + 4, "%06x", &record_addr) != 1) {
370  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal address 24-bit at line %d\n", line);
371  goto fail;
372  }
373  record_addr &= 0xffffff;
374 
375  eol = strchr(str + 1, 'S');
376  if (eol) {
377  *eol = 0;
378  }
379 
380  cksum = byte_count;
381  cksum += record_addr & 0xff;
382  cksum += (record_addr >> 8) & 0xff;
383  cksum += record_addr >> 16;
384  cksum = ~cksum;
385 
386  if (sscanf(str + 2 + (byte_count * 2), "%02x", &byte) != 1) {
387  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
388  goto fail;
389  } else if (cksum != byte) {
390  RZ_LOG_ERROR("srec:parse(): checksum check failed (got %02x expected %02x) at line %d\n", byte, cksum, line);
391  goto fail;
392  }
393 
394  str = strchr(str + 1, 'S');
395  break;
396 
397  case '3': // Data with 32-bit address
398  counter = byte_count - 5;
399  if (sscanf(str + 4, "%08x", &record_addr) != 1) {
400  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal address 32-bit at line %d\n", line);
401  goto fail;
402  }
403  record_addr &= 0xffffffff;
404 
405  eol = strchr(str + 1, 'S');
406  if (eol) {
407  *eol = 0;
408  }
409 
410  cksum = byte_count;
411  cksum += record_addr & 0xff;
412  cksum += (record_addr >> 8) & 0xff;
413  cksum += (record_addr >> 16) & 0xff;
414  cksum += record_addr >> 24;
415 
416  if ((record_next != record_addr) || ((record_size + counter) > UT16_MAX)) {
417  if (record_size && record_size < UT16_MAX) {
418  if (rz_buf_write_at(buf, record_begin, record_data, (st32)record_size) != record_size) {
419  RZ_LOG_ERROR("srec:parse(): cannot write buffer at 0x%x\n", record_begin);
420  goto fail;
421  }
422  }
423  record_begin = record_addr;
424  record_next = record_addr;
425  record_size = 0;
426  }
427 
428  for (i = 0; i < byte_count - 5; i++) {
429  if (sscanf(str + 12 + (i * 2), "%02x", &byte) != 1) {
430  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
431  goto fail;
432  }
433  if (record_size + i < UT16_MAX) {
434  record_data[record_size + i] = (ut8)byte & 0xff;
435  }
436  cksum += byte;
437  }
438  cksum = ~cksum;
439  record_size += counter;
440  record_next += counter;
441 
442  if (sscanf(str + 2 + (byte_count * 2), "%02x", &byte) != 1) {
443  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
444  goto fail;
445  } else if (cksum != byte) {
446  RZ_LOG_ERROR("srec:parse(): checksum check failed (got %02x expected %02x) at line %d\n", byte, cksum, line);
447  goto fail;
448  }
449 
450  str = strchr(str + 1, 'S');
451  break;
452 
453  case '7': // Terminator with 32-bit address
454  if (sscanf(str + 4, "%08x", &record_addr) != 1) {
455  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal address 32-bit at line %d\n", line);
456  goto fail;
457  }
458  record_addr &= 0xffffffff;
459 
460  eol = strchr(str + 1, 'S');
461  if (eol) {
462  *eol = 0;
463  }
464 
465  cksum = byte_count;
466  cksum += record_addr & 0xff;
467  cksum += (record_addr >> 8) & 0xff;
468  cksum += (record_addr >> 16) & 0xff;
469  cksum += record_addr >> 24;
470  cksum = ~cksum;
471 
472  if (sscanf(str + 2 + (byte_count * 2), "%02x", &byte) != 1) {
473  RZ_LOG_ERROR("srec:parse(): invalid hexadecimal value at line %d\n", line);
474  goto fail;
475  } else if (cksum != byte) {
476  RZ_LOG_ERROR("srec:parse(): checksum check failed (got %02x expected %02x) at line %d\n", byte, cksum, line);
477  goto fail;
478  }
479 
480  str = strchr(str + 1, 'S');
481  break;
482 
483  case '4':
484  break;
485  default:
486  RZ_LOG_ERROR("srec:parse(): invalid motorola srecord type '%c' at line %d\n", record_type, line);
487  goto fail;
488  }
489  } while (str);
490 
491  if (record_size && record_size < UT16_MAX) {
492  if (rz_buf_write_at(buf, record_begin, record_data, (st32)record_size) != record_size) {
493  RZ_LOG_ERROR("srec:parse(): cannot write buffer at 0x%x\n", record_begin);
494  goto fail;
495  }
496  }
497 
498  free(record_data);
499  return true;
500 fail:
501  free(record_data);
502  return false;
503 }
504 
505 static RzIODesc *__open(RzIO *io, const char *pathname, st32 rw, st32 mode) {
507 
508  SRecord *mal = NULL;
509  char *str = NULL;
510  if (__plugin_open(io, pathname, 0)) {
511  str = rz_file_slurp(pathname + 7, NULL);
512  if (!str) {
513  return NULL;
514  }
515  mal = RZ_NEW0(SRecord);
516  if (!mal) {
517  free(str);
518  return NULL;
519  }
520  mal->buf = rz_buf_new_sparse(io->Oxff);
521  if (!mal->buf) {
522  free(str);
523  free(mal);
524  return NULL;
525  }
526  if (!srecord_parse(mal->buf, str)) {
527  RZ_LOG_ERROR("srec: failed to parse file\n");
528  free(str);
529  rz_buf_free(mal->buf);
530  free(mal);
531  return NULL;
532  }
533  free(str);
534  return rz_io_desc_new(io, &rz_io_plugin_srec, pathname, rw, mode, mal);
535  }
536  return NULL;
537 }
538 
539 static bool __resize(RzIO *io, RzIODesc *fd, ut64 size) {
540  rz_return_val_if_fail(fd && fd->data, false);
541 
542  SRecord *srec = (SRecord *)fd->data;
543  if (srec) {
544  return rz_buf_resize(srec->buf, size);
545  }
546  return false;
547 }
548 
550  .name = "srec",
551  .desc = "Motorola S-record file format",
552  .uris = SREC_PATH_PREFIX,
553  .license = "LGPL-3",
554  .open = __open,
555  .close = __close,
556  .read = __read,
557  .check = __plugin_open,
558  .lseek = __lseek,
559  .write = __write,
560  .resize = __resize
561 };
562 
563 #ifndef RZ_PLUGIN_INCORE
565  .type = RZ_LIB_TYPE_IO,
566  .data = &rz_io_plugin_srec,
568 };
569 #endif
lzma_index ** i
Definition: index.h:629
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
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 ut8
Definition: dcpu16.h:8
uint16_t ut16
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
static st32 __write(RzIO *io, RzIODesc *fd, const ut8 *buf, st32 count)
Definition: io_srec.c:48
static st32 __close(RzIODesc *fd)
Definition: io_srec.c:116
#define SREC_PATH_PREFIX
Definition: io_srec.c:21
static bool __plugin_open(RzIO *io, const char *pathname, bool many)
Definition: io_srec.c:133
#define SREC_SIZE
Definition: io_srec.c:19
RzIOPlugin rz_io_plugin_srec
Definition: io_srec.c:549
static bool __resize(RzIO *io, RzIODesc *fd, ut64 size)
Definition: io_srec.c:539
RZ_API RzLibStruct rizin_plugin
Definition: io_srec.c:564
static RzIODesc * __open(RzIO *io, const char *pathname, st32 rw, st32 mode)
Definition: io_srec.c:505
struct srec_t SRecord
static ut64 __lseek(struct rz_io_t *io, RzIODesc *fd, ut64 offset, st32 whence)
Definition: io_srec.c:126
static void write_S3_record(FILE *fd, ut32 address, const ut8 *buffer, ut16 size)
Definition: io_srec.c:28
static st32 __read(RzIO *io, RzIODesc *fd, ut8 *buf, st32 count)
Definition: io_srec.c:102
static bool srecord_parse(RzBuffer *buf, char *str)
Definition: io_srec.c:137
voidpf void uLong size
Definition: ioapi.h:138
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
return memset(p, 0, total)
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char pathname
Definition: sflib.h:66
string FILE
Definition: benchmark.py:21
line
Definition: setup.py:34
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API bool rz_buf_resize(RZ_NONNULL RzBuffer *b, ut64 newsize)
Resize the buffer size.
Definition: buf.c:890
RZ_API st64 rz_buf_seek(RZ_NONNULL RzBuffer *b, st64 addr, int whence)
Modify the current cursor position in the buffer.
Definition: buf.c:1166
#define RZ_BUF_CUR
Definition: rz_buf.h:15
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 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 const RzBufferSparseChunk * rz_buf_sparse_get_chunks(RzBuffer *b, RZ_NONNULL size_t *count)
Only for sparse RzBuffers, get all sparse data chunks currently populated.
Definition: buf_sparse.c:313
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
RZ_API RZ_OWN RzBuffer * rz_buf_new_sparse(ut8 Oxff)
Creates a sparse buffer.
Definition: buf.c:408
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
RZ_API RzIODesc * rz_io_desc_new(RzIO *io, RzIOPlugin *plugin, const char *uri, int flags, int mode, void *data)
Definition: io_desc.c:11
@ RZ_LIB_TYPE_IO
Definition: rz_lib.h:69
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API FILE * rz_sys_fopen(const char *path, const char *mode)
Definition: sys.c:1815
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_PERM_W
Definition: rz_types.h:94
#define st32
Definition: rz_types_base.h:12
#define UT16_MAX
#define RZ_VERSION
Definition: rz_version.h:8
Definition: buffer.h:15
ut8 * data
size == to - from + 1
Definition: rz_buf.h:56
ut64 from
inclusive
Definition: rz_buf.h:54
ut64 to
inclusive, there can't be chunks with size == 0
Definition: rz_buf.h:55
const char * name
Definition: rz_io.h:115
const char * version
Definition: rz_io.h:117
Definition: rz_io.h:59
int Oxff
Definition: rz_io.h:65
ut64 off
Definition: rz_io.h:61
Definition: io_srec.c:23
st32 fd
Definition: io_srec.c:24
RzBuffer * buf
Definition: io_srec.c:25
char * name
Definition: z80_tab.h:24
int64_t counter
Definition: main.c:4
#define fail(test)
Definition: tests.h:29
static struct @626 mal
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const z80_opcode fd[]
Definition: z80_tab.h:997