static int bin_sections(RCore *r, int mode, ut64 laddr, int va, ut64 at, const char *name, const char *chksum) {
	char *str = NULL;
	RBinSection *section;
	RBinInfo *info = NULL;
	RList *sections;
	RListIter *iter;
	int i = 0;
	int fd = -1;
	bool printHere = false;
	sections = r_bin_get_sections (r->bin);
	bool inDebugger = r_config_get_i (r->config, "cfg.debug");
	SdbHash *dup_chk_ht = ht_new (NULL, NULL, NULL);
	bool ret = false;

	if (!dup_chk_ht) {
		return false;
	}
	
	if (chksum && *chksum == '.') {
		printHere = true;
	}
	if (IS_MODE_JSON (mode) && !printHere) r_cons_printf ("[");
	else if (IS_MODE_RAD (mode) && !at) r_cons_printf ("fs sections\n");
	else if (IS_MODE_NORMAL (mode) && !at && !printHere) r_cons_printf ("[Sections]\n");
	else if (IS_MODE_NORMAL (mode) && printHere) r_cons_printf("Current section\n");
	else if (IS_MODE_SET (mode)) {
		fd = r_core_file_cur_fd (r);
		r_flag_space_set (r->flags, "sections");
	}
	r_list_foreach (sections, iter, section) {
		char perms[] = "----";
		int va_sect = va;
		ut64 addr;

		if (va && !(section->srwx & R_BIN_SCN_READABLE)) {
			va_sect = VA_NOREBASE;
		}
		addr = rva (r->bin, section->paddr, section->vaddr, va_sect);

		if (name && strcmp (section->name, name)) {
			continue;
		}

		if ((printHere && !(section->paddr <= r->offset && r->offset < (section->paddr + section->size)))
				&& (printHere && !(addr <= r->offset && r->offset < (addr + section->size)))) {
			continue;
		}

		r_name_filter (section->name, sizeof (section->name));
		if (at && (!section->size || !is_in_range (at, addr, section->size))) {
			continue;
		}

		if (section->srwx & R_BIN_SCN_SHAREABLE) perms[0] = 's';
		if (section->srwx & R_BIN_SCN_READABLE) perms[1] = 'r';
		if (section->srwx & R_BIN_SCN_WRITABLE) perms[2] = 'w';
		if (section->srwx & R_BIN_SCN_EXECUTABLE) perms[3] = 'x';

		if (IS_MODE_SET (mode)) {
#if LOAD_BSS_MALLOC
			if (!strcmp (section->name, ".bss")) {
				// check if there's already a file opened there
				int loaded = 0;
				RListIter *iter;
				RIOMap *m;
				r_list_foreach (r->io->maps, iter, m) {
					if (m->from == addr) {
						loaded = 1;
					}
				}
				if (!loaded && !inDebugger) {
					r_core_cmdf (r, "on malloc://%d 0x%"PFMT64x" # bss\n",
						section->vsize, addr);
				}
			}
#endif
			r_name_filter (section->name, 128);
			if (section->format) {
				// This is damn slow if section vsize is HUGE
				if (section->vsize < 1024 * 1024 * 2) {
					r_core_cmdf (r, "%s @ 0x%"PFMT64x, section->format, section->vaddr);
				}
			}
			if (r->bin->prefix) {
				str = r_str_newf ("%s.section.%s", r->bin->prefix, section->name);
			} else {
				str = r_str_newf ("section.%s", section->name);

			}
			r_flag_set (r->flags, str, addr, section->size);
			R_FREE (str);

			if (r->bin->prefix) {
				str = r_str_newf ("%s.section_end.%s", r->bin->prefix, section->name);
			} else {
				str = r_str_newf ("section_end.%s", section->name);
			}
			r_flag_set (r->flags, str, addr + section->vsize, 0);
			R_FREE (str);

			if (section->arch || section->bits) {
				const char *arch = section->arch;
				int bits = section->bits;
				if (info) {
					if (!arch) {
						arch = info->arch;
					}
					if (!bits) {
						bits = info->bits;
					}
				}
				//r_io_section_set_archbits (r->io, addr, arch, bits);
			}
			char *pfx = r->bin->prefix;
			str = r_str_newf ("[%02d] %s section size %" PFMT64d" named %s%s%s",
				i, perms, section->size,
				pfx? pfx: "", pfx? ".": "", section->name);
			r_meta_add (r->anal, R_META_TYPE_COMMENT, addr, addr, str);
			R_FREE (str);
			if (section->add) {
				str = r_str_newf ("%"PFMT64x".%"PFMT64x".%"PFMT64x".%"PFMT64x".%"PFMT32u".%s.%"PFMT32u".%d",
					section->paddr, addr, section->size, section->vsize, section->srwx, section->name, r->bin->cur->id, fd);
				if (!ht_find (dup_chk_ht, str, NULL) && r_io_section_add (r->io, section->paddr, addr,
						section->size, section->vsize,
						section->srwx, section->name,
						r->bin->cur->id, fd)) {
					ht_insert (dup_chk_ht, str, NULL);
				}
				R_FREE (str);
			}
		} else if (IS_MODE_SIMPLE (mode)) {
			char *hashstr = NULL;
			if (chksum) {
				ut8 *data = malloc (section->size);
				if (!data) {
					goto out;
				}
				ut32 datalen = section->size;
				r_io_pread_at (r->io, section->paddr, data, datalen);
				hashstr = build_hash_string (mode, chksum,
							data, datalen);
				free (data);
			}
			r_cons_printf ("0x%"PFMT64x" 0x%"PFMT64x" %s %s%s%s\n",
				addr, addr + section->size,
				perms,
				hashstr ? hashstr : "", hashstr ? " " : "",
				section->name
			);
			free (hashstr);
		} else if (IS_MODE_JSON (mode)) {
			char *hashstr = NULL;
			if (chksum) {
				ut8 *data = malloc (section->size);
				if (!data) {
					goto out;
				}
				ut32 datalen = section->size;
				r_io_pread_at (r->io, section->paddr, data, datalen);
				hashstr = build_hash_string (mode, chksum,
							data, datalen);
				free (data);

			}
			r_cons_printf ("%s{\"name\":\"%s\","
				"\"size\":%"PFMT64d","
				"\"vsize\":%"PFMT64d","
				"\"flags\":\"%s\","
				"%s"
				"\"paddr\":%"PFMT64d","
				"\"vaddr\":%"PFMT64d"}",
				(iter->p && !printHere)?",":"",
				section->name,
				section->size,
				section->vsize,
				perms,
				hashstr ? hashstr : "",
				section->paddr,
				addr);
			free (hashstr);
		} else if (IS_MODE_RAD (mode)) {
			if (!strcmp (section->name, ".bss") && !inDebugger) {
#if LOAD_BSS_MALLOC
				r_cons_printf ("on malloc://%d 0x%"PFMT64x" # bss\n",
						section->vsize, addr);
#endif
			}
			if (r->bin->prefix) {
				r_cons_printf ("S 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"PFMT64x" %s.%s %d\n",
					section->paddr, addr, section->size, section->vsize,
					r->bin->prefix, section->name, (int)section->srwx);
			} else {
				r_cons_printf ("S 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"PFMT64x" %s %d\n",
					section->paddr, addr, section->size, section->vsize,
					section->name, (int)section->srwx);

			}
			if (section->arch || section->bits) {
				const char *arch = section->arch;
				int bits = section->bits;
				if (info) {
					if (!arch) arch = info->arch;
					if (!bits) bits = info->bits;
				}
				if (!arch) {
					arch = r_config_get (r->config, "asm.arch");
				}
				r_cons_printf ("Sa %s %d @ 0x%08"
					PFMT64x"\n", arch, bits, addr);
			}
			if (r->bin->prefix) {
				r_cons_printf ("f %s.section.%s %"PFMT64d" 0x%08"PFMT64x"\n",
						r->bin->prefix, section->name, section->size, addr);
				r_cons_printf ("f %s.section_end.%s 1 0x%08"PFMT64x"\n",
						r->bin->prefix, section->name, addr + section->vsize);
				r_cons_printf ("CC section %i va=0x%08"PFMT64x" pa=0x%08"PFMT64x" sz=%"PFMT64d" vsz=%"PFMT64d" "
						"rwx=%s %s.%s @ 0x%08"PFMT64x"\n",
						i, addr, section->paddr, section->size, section->vsize,
						perms, r->bin->prefix, section->name, addr);

			} else {
				r_cons_printf ("f section.%s %"PFMT64d" 0x%08"PFMT64x"\n",
						section->name, section->size, addr);
				r_cons_printf ("f section_end.%s 1 0x%08"PFMT64x"\n",
						section->name, addr + section->vsize);
				r_cons_printf ("CC section %i va=0x%08"PFMT64x" pa=0x%08"PFMT64x" sz=%"PFMT64d" vsz=%"PFMT64d" "
						"rwx=%s %s @ 0x%08"PFMT64x"\n",
						i, addr, section->paddr, section->size, section->vsize,
						perms, section->name, addr);
			}
		} else {
			char *hashstr = NULL, str[128];
			if (chksum) {
				ut8 *data = malloc (section->size);
				if (!data) {
					goto out;
				}
				ut32 datalen = section->size;
				// VA READ IS BROKEN?
				r_io_pread_at (r->io, section->paddr, data, datalen);
				hashstr = build_hash_string (mode, chksum,
							data, datalen);
				free (data);
			}
			if (section->arch || section->bits) {
				const char *arch = section->arch;
				int bits = section->bits;
				if (!arch && info) {
					arch = info->arch;
					if (!arch) {
						arch = r_config_get (r->config, "asm.arch");
					}
				}
				if (!bits) {
					bits = info? info->bits: R_SYS_BITS;
				}
				snprintf (str, sizeof (str), "arch=%s bits=%d ",
					r_str_get2 (arch), bits);
			} else {
				str[0] = 0;
			}
			if (r->bin->prefix) {
#if 0
				r_cons_printf ("idx=%02i vaddr=0x%08"PFMT64x" paddr=0x%08"PFMT64x" sz=%"PFMT64d" vsz=%"PFMT64d" "
					"perm=%s %s%sname=%s.%s\n",
					i, addr, section->paddr, section->size, section->vsize,
					perms, str, hashstr ?hashstr : "", r->bin->prefix, section->name);
#endif
				// r_cons_printf ("%02i 0x%08"PFMT64x" %10"PFMT64d" 0x%08"PFMT64x" %10"PFMT64d" "
				r_cons_printf ("%02i 0x%08"PFMT64x" %5"PFMT64d" 0x%08"PFMT64x" %5"PFMT64d" "
					"%s %s% %s.%s\n",
					i, section->paddr, section->size, addr, section->vsize,
					perms, str, hashstr ?hashstr : "", r->bin->prefix, section->name);
			} else {
#if 0
				r_cons_printf ("idx=%02i vaddr=0x%08"PFMT64x" paddr=0x%08"PFMT64x" sz=%"PFMT64d" vsz=%"PFMT64d" "
					"perm=%s %s%sname=%s\n",
					i, addr, section->paddr, section->size, section->vsize,
					perms, str, hashstr ?hashstr : "", section->name);
#endif
				// r_cons_printf ("%02i 0x%08"PFMT64x" %10"PFMT64d" 0x%08"PFMT64x" %10"PFMT64d" "
				r_cons_printf ("%02i 0x%08"PFMT64x" %5"PFMT64d" 0x%08"PFMT64x" %5"PFMT64d" "
					"%s %s%s%s\n",
					i, section->paddr, (ut64)section->size, addr, (ut64)section->vsize,
					perms, str, hashstr ?hashstr : "", section->name);
			}
			free (hashstr);
		}
		i++;
		if (printHere) {
			break;
		}
	}
	if (r->bin && r->bin->cur && r->io && !r_io_desc_is_dbg (r->io->desc)) {
		r_io_section_apply_bin (r->io, r->bin->cur->id, R_IO_SECTION_APPLY_FOR_ANALYSIS);
	}
	if (IS_MODE_JSON (mode) && !printHere) {
		r_cons_println ("]");
	} else if (IS_MODE_NORMAL (mode) && !at && !printHere) {
		// r_cons_printf ("\n%i sections\n", i);
	}

	ret = true;
out:
	ht_free (dup_chk_ht);
	return ret;
}