radare2/libr/io/section.c

595 lines
15 KiB
C
Raw Normal View History

/* radare2 - LGPL - Copyright 2008-2016 - pancake, nibble */
#include "r_io.h"
// no link
#include "r_cons.h"
R_API void r_io_section_init(RIO *io) {
io->next_section_id = 0;
io->enforce_rwx = 0; // do not enforce RWX section permissions by default
io->enforce_seek = 0; // do not limit seeks out of the file by default
io->sections = r_list_new ();
if (!io->sections) {
return;
}
io->sections->free = r_io_section_free;
}
#if 0
static int cmpaddr (void *_a, void *_b) {
RIOSection *a = _a, *b = _b;
return (a->vaddr > b->vaddr);
}
#endif
R_API RIOSection *r_io_section_get_name(RIO *io, const char *name) {
RListIter *iter;
RIOSection *s;
if (name)
r_list_foreach (io->sections, iter, s) {
if (!strcmp (name, s->name)) {
return s;
}
}
return NULL;
}
2016-01-03 00:40:09 +00:00
// update name and rwx, size is experimental
static RIOSection *findMatching (RIO *io, ut64 paddr, ut64 vaddr, ut64 size, ut64 vsize, int rwx, const char *name) {
RListIter *iter;
RIOSection *s;
r_list_foreach (io->sections, iter, s) {
if (s->offset != paddr) continue;
if (s->vaddr != vaddr) continue;
2016-01-03 00:40:09 +00:00
#if 1
if (s->size != size) continue;
if (s->vsize != vsize) continue;
#else
s->size = size;
s->vsize = vsize;
2016-01-03 00:40:09 +00:00
#endif
s->rwx = rwx;
if (name && strcmp (name, s->name)) {
s->name = strdup (name);
}
return s;
}
return NULL;
}
R_API RIOSection *r_io_section_add(RIO *io, ut64 offset, ut64 vaddr, ut64 size, ut64 vsize, int rwx, const char *name, ut32 bin_id, int fd) {
int update = 0;
RIOSection *s;
if (!size || size == UT64_MAX || size == UT32_MAX) { //hacky things which might give bad output in case size == UT32_MAX for 64bit elf. Check on basis of size, offset and file size would be a good idea.
#if 0
eprintf ("Invalid size (0x%08" PFMT64x
") for section '%s' at 0x%08" PFMT64x "\n",
size, name, vaddr);
#endif
return NULL;
}
s = findMatching (io, offset, vaddr, size, vsize, rwx, name);
if (s) {
return s;
}
s = r_io_section_get_name (io, name);
if (!s) {
s = R_NEW0 (RIOSection);
s->id = io->next_section_id++;
} else {
update = 1;
}
s->offset = offset;
s->vaddr = vaddr;
s->size = size;
s->vsize = vsize;
s->rwx = rwx;
s->arch = s->bits = 0;
s->bin_id = bin_id;
s->fd = fd;
if (!update) {
if (name) s->name = strdup (name);
else s->name = strdup ("");
r_list_append (io->sections, s);
}
return s;
}
R_API RIOSection *r_io_section_get_i(RIO *io, int idx) {
RListIter *iter;
RIOSection *s;
2016-01-22 15:38:12 +00:00
if (!io || !io->sections)
return NULL;
r_list_foreach (io->sections, iter, s) {
if (s->id == idx)
return s;
}
return NULL;
}
R_API int r_io_section_rm(RIO *io, int idx) {
2016-01-22 15:38:12 +00:00
RListIter *iter;
RIOSection *s;
if (!io || !io->sections) {
2016-01-22 15:38:12 +00:00
return false;
}
2016-01-22 15:38:12 +00:00
r_list_foreach (io->sections, iter, s) {
if (s->id == idx) {
r_list_delete (io->sections, iter);
return true;
}
}
return false;
}
R_API int r_io_section_rm_all (RIO *io, int fd) {
RIOSection *section;
RListIter *iter, *ator;
if (!io || !io->sections) {
2015-09-14 00:08:31 +00:00
return false;
}
r_list_foreach_safe (io->sections, iter, ator, section) {
if (section->fd == fd || fd == -1)
r_list_delete (io->sections, iter);
}
2015-09-14 00:08:31 +00:00
return true;
}
R_API void r_io_section_free(void *ptr) {
RIOSection *s = (RIOSection*)ptr;
if (s) {
free (s->name);
free (s);
}
}
R_API void r_io_section_clear(RIO *io) {
r_list_free (io->sections);
io->sections = r_list_new ();
if (!io->sections) {
return;
}
io->sections->free = r_io_section_free;
}
// TODO: implement as callback
R_API void r_io_section_list(RIO *io, ut64 offset, int rad) {
int i = 0;
RListIter *iter;
RIOSection *s;
if (io->va || io->debug)
offset = r_io_section_vaddr_to_maddr_try (io, offset);
// XXX - Should this print the section->id or the location in the
// rio sections array?
r_list_foreach (io->sections, iter, s) {
if (rad) {
char *n = strdup (s->name);
r_name_filter (n, strlen (n));
io->cb_printf ("f section.%s %"PFMT64d" 0x%"PFMT64x"\n",
n, s->size, s->vaddr);
io->cb_printf ("S 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"
PFMT64x" 0x%08"PFMT64x" %s %s\n", s->offset,
s->vaddr, s->size, s->vsize, n, r_str_rwx_i (s->rwx));
} else {
io->cb_printf ("[%02d] %c 0x%08"PFMT64x" %s va=0x%08"PFMT64x
" sz=0x%04"PFMT64x" vsz=0x%04"PFMT64x" %s",
i, (offset>=s->offset && offset<s->offset+s->size)?'*':'.',
s->offset, r_str_rwx_i (s->rwx), s->vaddr, s->size, s->vsize, s->name);
if (s->arch && s->bits)
io->cb_printf (" ; %s %d\n", r_sys_arch_str (s->arch), s->bits);
else io->cb_printf ("\n");
}
i++;
}
}
2015-01-27 14:35:42 +00:00
2015-10-13 18:48:14 +00:00
#define PRINT_CURRENT_SEEK \
if (i > 0 && len != 0) { \
if (seek == UT64_MAX) seek = 0; \
io->cb_printf ("=> 0x%08"PFMT64x" |", seek); \
for (j = 0; j < width; j++) { \
io->cb_printf ( \
((j*mul) + min >= seek && \
(j*mul) + min <= seek + len) \
? "^" : "-"); \
} \
io->cb_printf ("| 0x%08"PFMT64x"\n", seek+len); \
}
static void list_section_visual_vaddr (RIO *io, ut64 seek, ut64 len, int use_color, int cols) {
ut64 mul, min = -1, max = -1;
RListIter *iter;
RIOSection *s;
2015-10-13 18:48:14 +00:00
int j, i = 0;
int width = cols - 60;
2015-10-11 20:52:53 +00:00
if (width < 1) width = 30;
2015-10-13 18:48:14 +00:00
r_list_foreach (io->sections, iter, s) {
if (min == -1 || s->vaddr < min) {
2015-10-13 18:48:14 +00:00
min = s->vaddr;
}
if (max == -1 || s->vaddr+s->size > max) {
2015-10-13 18:48:14 +00:00
max = s->vaddr+s->size;
}
2015-10-13 18:48:14 +00:00
}
mul = (max-min) / width;
if (min != -1 && mul != 0) {
const char * color = "", *color_end = "";
char buf[128];
i = 0;
r_list_foreach (io->sections, iter, s) {
r_num_units (buf, s->size);
if (use_color) {
color_end = Color_RESET;
if (s->rwx & 1) { // exec bit
color = Color_GREEN;
} else if (s->rwx & 2) { // write bit
color = Color_RED;
} else {
color = "";
color_end = "";
}
} else {
color = "";
color_end = "";
}
2015-10-15 19:56:17 +00:00
io->cb_printf ("%02d%c %s0x%08"PFMT64x"%s |", i,
2015-10-13 18:48:14 +00:00
(seek >= s->vaddr && seek < s->vaddr + s->size) ? '*' : ' ',
//(seek>=s->vaddr && seek<s->vaddr+s->size)?'*':' ',
2015-10-15 19:56:17 +00:00
color, s->vaddr, color_end);
2015-10-13 18:48:14 +00:00
for (j = 0; j < width; j++) {
ut64 pos = min + (j * mul);
ut64 npos = min + ((j + 1) * mul);
if (s->vaddr < npos && (s->vaddr + s->size) > pos)
io->cb_printf ("#");
else io->cb_printf ("-");
}
2015-10-15 19:56:17 +00:00
io->cb_printf ("| %s0x%08"PFMT64x"%s %s %s %04s\n",
2015-10-13 18:48:14 +00:00
color, s->vaddr + s->size, color_end,
2015-10-15 19:56:17 +00:00
r_str_rwx_i (s->rwx), s->name, buf);
2015-10-13 18:48:14 +00:00
i++;
}
2015-10-13 18:48:14 +00:00
PRINT_CURRENT_SEEK;
}
}
static void list_section_visual_paddr (RIO *io, ut64 seek, ut64 len, int use_color, int cols) {
2015-10-13 18:48:14 +00:00
ut64 mul, min = -1, max = -1;
RListIter *iter;
RIOSection *s;
int j, i = 0;
int width = cols - 60;
2015-10-13 18:48:14 +00:00
if (width < 1) width = 30;
seek = r_io_section_vaddr_to_maddr_try (io, seek);
r_list_foreach (io->sections, iter, s) {
if (min == -1 || s->offset < min)
min = s->offset;
if (max == -1 || s->offset+s->size > max)
max = s->offset+s->size;
}
mul = (max-min) / width;
if (min != -1 && mul != 0) {
const char * color = "", *color_end = "";
2015-10-13 10:55:38 +00:00
char buf[128];
i = 0;
r_list_foreach (io->sections, iter, s) {
2015-10-13 10:55:38 +00:00
r_num_units (buf, s->size);
if (use_color) {
color_end = Color_RESET;
if (s->rwx & 1) { // exec bit
color = Color_GREEN;
} else if (s->rwx & 2) { // write bit
color = Color_RED;
} else {
color = "";
color_end = "";
}
} else {
color = "";
color_end = "";
}
2015-10-15 19:56:17 +00:00
io->cb_printf ("%02d%c %s0x%08"PFMT64x"%s |", i,
2015-10-13 18:48:14 +00:00
(seek >= s->offset && seek < s->offset + s->size) ? '*' : ' ',
2015-10-15 19:56:17 +00:00
color, s->offset, color_end);
2015-10-11 20:52:53 +00:00
for (j = 0; j < width; j++) {
ut64 pos = min + (j * mul);
ut64 npos = min + ((j + 1) * mul);
if (s->offset < npos && (s->offset + s->size) > pos)
io->cb_printf ("#");
else io->cb_printf ("-");
}
2015-10-15 19:56:17 +00:00
io->cb_printf ("| %s0x%08"PFMT64x"%s %s %s %04s\n",
2015-10-13 18:48:14 +00:00
color, s->offset+s->size, color_end,
2015-10-15 19:56:17 +00:00
r_str_rwx_i (s->rwx), s->name, buf);
2015-10-13 18:48:14 +00:00
i++;
}
2015-10-13 18:48:14 +00:00
PRINT_CURRENT_SEEK;
}
}
2015-10-13 18:48:14 +00:00
/* TODO: move to print ??? support pretty print of ranges following an array of offsetof */
R_API void r_io_section_list_visual(RIO *io, ut64 seek, ut64 len, int use_color, int cols) {
if (io->va) list_section_visual_vaddr (io, seek, len, use_color, cols);
else list_section_visual_paddr (io, seek, len, use_color, cols);
2015-10-13 18:48:14 +00:00
}
R_API RIOSection *r_io_section_vget(RIO *io, ut64 vaddr) {
RListIter *iter;
RIOSection *s;
r_list_foreach (io->sections, iter, s) {
if (vaddr >= s->vaddr && vaddr < s->vaddr + s->vsize)
return s;
}
return NULL;
}
// maddr == section->offset
R_API RIOSection *r_io_section_mget_in(RIO *io, ut64 maddr) {
RIOSection *s;
RListIter *iter;
r_list_foreach (io->sections, iter, s) {
if ((maddr >= s->offset && maddr < (s->offset + s->size)))
return s;
}
return NULL;
}
Fix for bug 3788 - `r_io_read` calls `r_io_read_at` with vaddrs, and not with maddr - `r_io_section_maddr_to_vaddr` uses a reverse iterator to check the sections - adds `r_io_section_mget_prev`: this function can be removed if the behavior of `r_io_section_mget` is changed to use a reverse iterator Squashed commit of the following: commit a31d359bf1c79b92f518fa8237c7f9d4cf146577 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Wed Dec 9 11:40:54 2015 -0800 fetches sections starting from the back commit 0b687439ea6225c8db9f387cc93bc53300e297a7 Merge: 8485676 92c1631 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Dec 8 23:40:35 2015 -0800 Merge branch 'master' of https://github.com/radare/radare2 into revert_3788 commit 8485676cf5c042d8c4e10c798b4fadb1a43df50c Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Dec 8 23:09:05 2015 -0800 This seems to be the "correct" patch... ...but it breaks some tests... apprently searches a few bytes out of the section creating some false-positives hits I'm just commiting this PR to give an idea of where the bug is commit 2e4b8de397a4ef23c02c3e08113cf6b984479275 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Dec 8 22:46:29 2015 -0800 not good... reverting commit 324afba7e2853ddb72750f7f8b38bf59af310873 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Dec 8 22:09:25 2015 -0800 workaround for bug 3788 commit 6e6283eaa18edcca1987a8f4227f163a6926c430 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Dec 8 15:14:12 2015 -0800 Reverts fix for bug #3788 please, reopen bug #3788
2015-12-09 20:17:49 +00:00
R_API RIOSection *r_io_section_mget_prev(RIO *io, ut64 maddr) {
RIOSection *s;
RListIter *iter;
r_list_foreach_prev (io->sections, iter, s) {
if ((maddr >= s->offset && maddr < (s->offset + s->size)))
return s;
}
return NULL;
}
2014-05-31 10:14:49 +00:00
// XXX: rename this
R_API ut64 r_io_section_get_offset(RIO *io, ut64 maddr) {
RIOSection *s = r_io_section_mget_in (io, maddr);
return s? s->offset: UT64_MAX;
}
2014-05-31 10:14:49 +00:00
// XXX: must be renamed, this is confusing
R_API ut64 r_io_section_get_vaddr(RIO *io, ut64 maddr) {
RIOSection *s = r_io_section_mget_in (io, maddr);
return s? s->vaddr: UT64_MAX;
}
// TODO: deprecate
R_API int r_io_section_get_rwx(RIO *io, ut64 offset) {
RIOSection *s = r_io_section_mget_in (io, offset);
return s?s->rwx:R_IO_READ|R_IO_WRITE|R_IO_EXEC;
}
R_API int r_io_section_overlaps(RIO *io, RIOSection *s) {
int i = 0;
RListIter *iter;
RIOSection *s2;
r_list_foreach (io->sections, iter, s2) {
if (!(s->rwx & R_IO_MAP)) continue;
if (s != s2) {
if (s->offset >= s2->offset) {
if (s2->offset+s2->size < s->offset)
return i;
} else {
if (s->offset+s->size < s2->offset)
return i;
}
}
i++;
}
return -1;
}
/* returns the conversion from vaddr to maddr if the given vaddr is in a mapped
* region, otherwise it returns the original address */
R_API ut64 r_io_section_vaddr_to_maddr_try(RIO *io, ut64 vaddr) {
ut64 res = r_io_section_vaddr_to_maddr (io, vaddr);
return res == UT64_MAX ? vaddr : res;
}
/* returns the conversion from vaddr to maddr if the given vaddr is in a mapped
* region, UT64_MAX otherwise */
R_API ut64 r_io_section_vaddr_to_maddr(RIO *io, ut64 vaddr) {
RListIter *iter;
RIOSection *s;
r_list_foreach (io->sections, iter, s) {
if (!(s->rwx & R_IO_MAP)) continue;
if (vaddr >= s->vaddr && vaddr < s->vaddr + s->vsize) {
return (vaddr - s->vaddr + s->offset);
}
}
return UT64_MAX;
}
/* returns the conversion from file offset to vaddr if the given offset is
* mapped somewhere, UT64_MAX otherwise */
R_API ut64 r_io_section_maddr_to_vaddr(RIO *io, ut64 offset) {
Fix for bug 3788 - `r_io_read` calls `r_io_read_at` with vaddrs, and not with maddr - `r_io_section_maddr_to_vaddr` uses a reverse iterator to check the sections - adds `r_io_section_mget_prev`: this function can be removed if the behavior of `r_io_section_mget` is changed to use a reverse iterator Squashed commit of the following: commit a31d359bf1c79b92f518fa8237c7f9d4cf146577 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Wed Dec 9 11:40:54 2015 -0800 fetches sections starting from the back commit 0b687439ea6225c8db9f387cc93bc53300e297a7 Merge: 8485676 92c1631 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Dec 8 23:40:35 2015 -0800 Merge branch 'master' of https://github.com/radare/radare2 into revert_3788 commit 8485676cf5c042d8c4e10c798b4fadb1a43df50c Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Dec 8 23:09:05 2015 -0800 This seems to be the "correct" patch... ...but it breaks some tests... apprently searches a few bytes out of the section creating some false-positives hits I'm just commiting this PR to give an idea of where the bug is commit 2e4b8de397a4ef23c02c3e08113cf6b984479275 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Dec 8 22:46:29 2015 -0800 not good... reverting commit 324afba7e2853ddb72750f7f8b38bf59af310873 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Dec 8 22:09:25 2015 -0800 workaround for bug 3788 commit 6e6283eaa18edcca1987a8f4227f163a6926c430 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Dec 8 15:14:12 2015 -0800 Reverts fix for bug #3788 please, reopen bug #3788
2015-12-09 20:17:49 +00:00
/* Use reverse iterator, since sections that are at the
* end of the list are usually the bigger ones */
RIOSection *s = r_io_section_mget_prev (io, offset);
if (s) {
io->section = s;
return (s->vaddr + offset - s->offset);
}
return UT64_MAX;
}
// TODO: deprecate ?
R_API int r_io_section_exists_for_paddr (RIO *io, ut64 paddr, int hasperm) {
RIOSection *s = r_io_section_mget_in (io, paddr);
if (s) {
if (hasperm) {
return (s->rwx & hasperm);
}
return true;
}
return false;
2014-05-22 06:58:03 +00:00
}
// TODO: deprecate ?
R_API int r_io_section_exists_for_vaddr (RIO *io, ut64 vaddr, int hasperm) {
RIOSection *s = r_io_section_vget (io, vaddr);
if (s) {
if (hasperm) {
return (s->rwx & hasperm);
}
return true;
}
return false;
2014-05-22 06:58:03 +00:00
}
// dupped in vio.c
R_API ut64 r_io_section_next(RIO *io, ut64 o) {
RListIter *iter;
RIOSection *s;
ut64 addr, newsec = UT64_MAX;
r_list_foreach (io->sections, iter, s) {
addr = s->vaddr;
if (s->vaddr > o && s->vaddr < newsec) {
newsec = s->vaddr;
}
addr = s->vaddr + s->vsize;
if (addr > o && addr < newsec) {
newsec = s->vaddr;
}
}
return newsec;
}
R_API RList *r_io_section_get_in_paddr_range(RIO *io, ut64 addr, ut64 endaddr) {
RIOSection *s;
RListIter *iter;
RList *sections = r_list_new ();
2016-05-24 20:22:15 +00:00
if (!sections) return NULL;
sections->free = r_io_section_free;
ut64 sec_from, sec_to;
r_list_foreach (io->sections, iter, s) {
if (!(s->rwx & R_IO_MAP)) continue;
sec_from = s->offset;
sec_to = sec_from + s->size;
if (sec_from <= addr && addr < sec_to) r_list_append (sections, s);
if (sec_from < endaddr && endaddr < sec_to) r_list_append (sections, s);
if (addr <= sec_from && sec_to <= endaddr) r_list_append (sections, s);
}
return sections;
}
R_API RList *r_io_section_get_in_vaddr_range(RIO *io, ut64 addr, ut64 endaddr) {
RIOSection *s;
RListIter *iter;
RList *sections = r_list_new ();
2016-05-24 20:22:15 +00:00
if (!sections) return NULL;
//Here section->free is not needed and wrong since we are appending into
//the list sections from io->sections that are widely used so just free the
//list but not the elements to avoid UAF. r_io_free will free sections for us
ut64 sec_from, sec_to;
r_list_foreach (io->sections, iter, s) {
if (!(s->rwx & R_IO_MAP)) {
continue;
}
sec_from = s->vaddr;
sec_to = sec_from + s->vsize;
if (sec_from <= addr && addr < sec_to) r_list_append (sections, s);
if (sec_from < endaddr && endaddr < sec_to) r_list_append (sections, s);
if (addr <= sec_from && sec_to <= endaddr) r_list_append (sections, s);
}
return sections;
}
2014-05-22 06:58:03 +00:00
R_API RIOSection * r_io_section_get_first_in_paddr_range(RIO *io, ut64 addr, ut64 endaddr) {
RIOSection *s= NULL;
2014-05-22 06:58:03 +00:00
RListIter *iter;
ut64 sec_from, sec_to;
r_list_foreach (io->sections, iter, s) {
if (!(s->rwx & R_IO_MAP)) {
continue;
}
sec_to = s->offset + s->size;
sec_from = s->offset;
2014-05-22 06:58:03 +00:00
if (sec_from <= addr && addr < sec_to) break;
//if (map->from == addr && endaddr == sec_to) r_list_append(maps, map);
if (sec_from < endaddr && endaddr < sec_to) break;
if (addr <= sec_from && sec_to <= endaddr) break;
s = NULL;
2014-05-22 06:58:03 +00:00
}
return s;
2014-05-22 06:58:03 +00:00
}
R_API RIOSection * r_io_section_get_first_in_vaddr_range(RIO *io, ut64 addr, ut64 endaddr) {
RIOSection *s= NULL;
2014-05-22 06:58:03 +00:00
RListIter *iter;
ut64 sec_from, sec_to;
r_list_foreach (io->sections, iter, s) {
if (!(s->rwx & R_IO_MAP)) continue;
sec_to = s->vaddr + s->vsize;
sec_from = s->vaddr;
2014-05-22 06:58:03 +00:00
if (sec_from <= addr && addr < sec_to) break;
//if (map->from == addr && endaddr == sec_to) r_list_append(maps, map);
if (sec_from < endaddr && endaddr < sec_to) break;
if (addr <= sec_from && sec_to <= endaddr) break;
s = NULL;
2014-05-22 06:58:03 +00:00
}
return s;
2014-05-22 06:58:03 +00:00
}
R_API int r_io_section_set_archbits(RIO *io, ut64 addr, const char *arch, int bits) {
RIOSection *s = r_io_section_vget (io, addr);
2015-09-14 00:08:31 +00:00
if (!s) return false;
if (arch) {
s->arch = r_sys_arch_id (arch);
s->bits = bits;
} else {
s->arch = 0;
s->bits = 0;
}
2015-09-14 00:08:31 +00:00
return true;
}
R_API const char *r_io_section_get_archbits(RIO* io, ut64 addr, int *bits) {
RIOSection *s = r_io_section_vget (io, addr);
if (!s || !s->bits || !s->arch) {
return NULL;
}
if (bits) {
*bits = s->bits;
}
return r_sys_arch_str (s->arch);
}
R_API RIOSection *r_io_section_getv_bin_id(RIO *io, ut64 vaddr, ut32 bin_id) {
RListIter *iter;
RIOSection *s;
r_list_foreach (io->sections, iter, s) {
if (!(s->rwx & R_IO_MAP) || s->bin_id != bin_id) {
continue;
}
if (vaddr >= s->vaddr && vaddr < s->vaddr + s->vsize) {
return s;
}
}
return NULL;
}
R_API int r_io_section_set_archbits_bin_id(RIO *io, ut64 addr, const char *arch, int bits, ut32 bin_id) {
RIOSection *s = r_io_section_getv_bin_id (io, addr, bin_id);
if (s) {
if (arch) {
s->arch = r_sys_arch_id (arch);
s->bits = bits;
} else {
s->arch = 0;
s->bits = 0;
}
return true;
}
return false;
}