Esempio n. 1
0
int gb_set_reg_profile(emu *e)
{
	int ret = r_anal_set_reg_profile (e->anal);
	e->reg = e->anal->reg;
	r_reg_set_value (e->reg, r_reg_get (e->reg,"mpc",-1), ((RBinAddr *) r_list_get_n (r_bin_get_entries (e->bin), 0))->offset);
	r_reg_set_value (e->reg, r_reg_get (e->reg,"sp",-1), 0xfffe);
	r_reg_set_value (e->reg, r_reg_get (e->reg,"af",-1), 0x01b0);
	r_reg_set_value (e->reg, r_reg_get (e->reg,"bc",-1), 0x0013);
	r_reg_set_value (e->reg, r_reg_get (e->reg,"de",-1), 0x00d8);
	r_reg_set_value (e->reg, r_reg_get (e->reg,"hl",-1), 0x014d);
	r_reg_set_value (e->reg, r_reg_get (e->reg,"ime",-1), R_TRUE);
	return ret;
}
Esempio n. 2
0
static int disassemble (RAsm *a, RAsmOp *opstruct, const ut8 *buf, int len) {
	RList *interned_table = NULL;
	RList *shared = NULL;
	RList *cobjs = NULL;

	RBin *bin = a->binb.bin;
	ut64 pc = a->pc;
  
	RBinPlugin *plugin = bin && bin->cur && bin->cur->o ?
		bin->cur->o->plugin : NULL;

	if (plugin) {
		if (!strcmp (plugin->name, "pyc")) {
			shared = bin->cur->o->bin_obj;
		}
	}
	cobjs = r_list_get_n (shared, 0);
	interned_table = r_list_get_n (shared, 1);
	int r = r_pyc_disasm (opstruct, buf, cobjs, interned_table, pc);
	opstruct->size = r;
	return r;
}
Esempio n. 3
0
static pyc_object *get_ref_object(RBuffer *buffer) {
	pyc_object *ret;
	pyc_object *obj;
	bool error = false;
	ut32 index = get_ut32 (buffer, &error);
	if (error || index >= r_list_length (refs))
		return NULL;
	obj = r_list_get_n (refs, index);
	if (!obj)
		return NULL;
	ret = copy_object (obj);
	if (!ret)
		free (obj);
	return ret;
}
Esempio n. 4
0
int omap_remap(void *stream, int address)
{
	SOmapStream *omap_stream = (SOmapStream *) stream;
	SOmapEntry *omap_entry = 0;
	RListIter *it = 0;
	int i = 0;
	int pos = 0;
	int len = 0;

	if (!omap_stream) {
		return address;
	}

	len = r_list_length(omap_stream->omap_entries);

	if (omap_stream->froms == 0) {
		omap_stream->froms = (unsigned int *) malloc(4 * len);
		it = r_list_iterator(omap_stream->omap_entries);
		while (r_list_iter_next(it)) {
			omap_entry = (SOmapEntry *) r_list_iter_get(it);
			omap_stream->froms[i] = omap_entry->from;
			i++;
		}
	}

	// mb (len -1) ???
	pos = binary_search(omap_stream->froms, address, 0, (len));

	if (omap_stream->froms[pos] != address) {
		pos -= 1;
	}

	omap_entry = (SOmapEntry *) r_list_get_n(omap_stream->omap_entries, pos);
	if (!omap_entry) {
		return -1;
	}
	if (omap_entry->to == 0) {
		return omap_entry->to;
	} else {
		return omap_entry->to + (address - omap_entry->from);
	}
}
Esempio n. 5
0
File: xml.c Progetto: agatti/radare2
static int gdbr_parse_target_xml(libgdbr_t *g, char *xml_data, ut64 len) {
	char *regstr, *flagstr, *tmp, *profile = NULL, pc_alias[64], flag_bits[65];
	RList *flags, *regs;
	RListIter *iter;
	gdbr_xml_flags_t *tmpflag;
	gdbr_xml_reg_t *tmpreg;
	ut64 profile_len = 0, profile_max_len, regnum = 0, regoff = 0;
	pc_alias[0] = '\0';
	gdb_reg_t *arch_regs = NULL;
	if (_resolve_arch (g, xml_data) < 0) {
		return -1;
	}
	if (!(flagstr = strstr (xml_data, "<feature"))) {
		return -1;
	}
	regstr = flagstr;
	if (!(flags = _extract_flags (flagstr))) {
		return -1;
	}
	if (!(regs = _extract_regs (regstr, flags, pc_alias))) {
		r_list_free (flags);
		return -1;
	}
	if (!(arch_regs = malloc (sizeof (gdb_reg_t) * (r_list_length (regs) + 1)))) {
		goto exit_err;
	}
	// approximate per-reg size estimates
	profile_max_len = r_list_length (regs) * 128 + r_list_length (flags) * 128;
	if (!(profile = malloc (profile_max_len))) {
		goto exit_err;
	}
	r_list_foreach (regs, iter, tmpreg) {
		if (!tmpreg) {
			continue;
		}
		// regsize > 64 not supported by r2 currently
		if (tmpreg->size > 8) {
			regoff += tmpreg->size;
			continue;
		}
		memcpy (arch_regs[regnum].name, tmpreg->name, sizeof (tmpreg->name));
		arch_regs[regnum].size = tmpreg->size;
		arch_regs[regnum].offset = regoff;
		if (profile_len + 128 >= profile_max_len) {
			if (!(tmp = realloc (profile, profile_max_len + 512))) {
				goto exit_err;
			}
			profile = tmp;
			profile_max_len += 512;
		}
		flag_bits[0] = '\0';
		tmpflag = NULL;
		if (tmpreg->flagnum < r_list_length (flags)) {
			tmpflag = r_list_get_n (flags, tmpreg->flagnum);
			_write_flag_bits (flag_bits, tmpflag);
		}
		profile_len += snprintf (profile + profile_len, 128, "%s\t%s\t"
					".%u\t%"PFMT64d"\t0\t%s\n", tmpreg->type,
					tmpreg->name, tmpreg->size * 8, regoff, flag_bits);
		// TODO write flag subregisters
		if (tmpflag) {
			int i;
			for (i = 0; i < tmpflag->num_fields; i++) {
				if (profile_len + 128 >= profile_max_len) {
					if (!(tmp = realloc (profile, profile_max_len + 512))) {
						goto exit_err;
					}
					profile = tmp;
					profile_max_len += 512;
				}
				profile_len += snprintf (profile + profile_len, 128, "gpr\t%s\t"
							".%u\t.%"PFMT64d"\t0\n", tmpflag->fields[i].name,
							tmpflag->fields[i].sz, tmpflag->fields[i].bit_num + (regoff * 8));
			}
		}
		regnum++;
		regoff += tmpreg->size;
	}
	// Difficult to parse these out from xml. So manually added from gdb's xml files
	switch (g->target.arch) {
	case R_SYS_ARCH_ARM:
		switch (g->target.bits) {
		case 32:
			if (!(profile = r_str_prefix (profile,
							"=PC	r15\n"
							"=SP	r14\n" // XXX
							"=A0	r0\n"
							"=A1	r1\n"
							"=A2	r2\n"
							"=A3	r3\n"
						      ))) {
				goto exit_err;
			}
			break;
		case 64:
			if (!(profile = r_str_prefix (profile,
							"=PC	pc\n"
							"=SP	sp\n"
							"=BP	x29\n"
							"=A0	x0\n"
							"=A1	x1\n"
							"=A2	x2\n"
							"=A3	x3\n"
							"=ZF	zf\n"
							"=SF	nf\n"
							"=OF	vf\n"
							"=CF	cf\n"
							"=SN	x8\n"
						      ))) {
				goto exit_err;
			}
		}
		break;
		break;
	case R_SYS_ARCH_X86:
		switch (g->target.bits) {
		case 32:
			if (!(profile = r_str_prefix (profile,
						     "=PC	eip\n"
						     "=SP	esp\n"
						     "=BP	ebp\n"))) {
				goto exit_err;
			}
			break;
		case 64:
			if (!(profile = r_str_prefix (profile,
						     "=PC	rip\n"
						     "=SP	rsp\n"
						     "=BP	rbp\n"))) {
				goto exit_err;
			}
		}
		break;
	case R_SYS_ARCH_MIPS:
		if (!(profile = r_str_prefix (profile,
						"=PC	pc\n"
						"=SP	r29\n"))) {
			goto exit_err;
		}
		break;
	default:
		// TODO others
		if (*pc_alias) {
			if (!(profile = r_str_prefix (profile, pc_alias))) {
				goto exit_err;
			}
		}
	}
	// Special case for MIPS, since profile doesn't separate 32/64 bit MIPS
	if (g->target.arch == R_SYS_ARCH_MIPS) {
		if (arch_regs && arch_regs[0].size == 8) {
			g->target.bits = 64;
		}
	}
	r_list_free (flags);
	r_list_free (regs);
	free (g->target.regprofile);
	if (profile) {
		g->target.regprofile = strdup (profile);
		free (profile);
	}
	g->target.valid = true;
	g->registers = arch_regs;
	return 0;

exit_err:
	r_list_free (flags);
	r_list_free (regs);
	free (profile);
	free (arch_regs);
	return -1;
}
Esempio n. 6
0
static int cmd_seek(void *data, const char *input) {
	RCore *core = (RCore *) data;
	char *cmd, *p;
	ut64 off;

	if (!*input) {
		r_cons_printf ("0x%"PFMT64x "\n", core->offset);
		return 0;
	}
	char *ptr;
	if ((ptr = strstr (input, "+.")) != NULL) {
		char *dup = strdup (input);
		dup[ptr - input] = '\x00';
		off = r_num_math (core->num, dup + 1);
		core->offset = off;
		free (dup);
	}
	const char *inputnum = strchr (input, ' ');
	{
		const char *u_num = inputnum? inputnum + 1: input + 1;
		off = r_num_math (core->num, u_num);
		if (*u_num == '-') {
			off = -off;
		}
	}
	int sign = 1;
	if (input[0] == ' ') {
		switch (input[1]) {
		case '-':
			sign = -1;
			/* pass thru */
		case '+':
			input++;
			break;
		}
	}
	bool silent = false;
	if (*input == 's') {
		silent = true;
		input++;
		if (*input == '?') {
			const char *help_message[] = {
				"Usage: ss", "", " # Seek silently (not recorded in the seek history)",
				"s?", "", "Works with all s subcommands",
				NULL
			};
			r_core_cmd_help (core, help_message);
			return 0;
		}
	}

	switch (*input) {
	case 'r':
		if (input[1] && input[2]) {
			seek_to_register (core, input + 2, silent);
		} else {
			eprintf ("|Usage| 'sr PC' seek to program counter register\n");
		}
		break;
	case 'C':
		if (input[1] == '*') {
			r_core_cmd0 (core, "C*~^\"CC");
		} else if (input[1] == ' ') {
			typedef struct {
				ut64 addr;
				char *str;
			} MetaCallback;
			int count = 0;
			MetaCallback cb = {
				0, NULL
			};
			ut64 addr;
			char key[128];
			const char *val, *comma;
			char *list = sdb_get (core->anal->sdb_meta, "meta.C", 0);
			char *str, *next, *cur = list;
			if (list) {
				for (;;) {
					cur = sdb_anext (cur, &next);
					addr = sdb_atoi (cur);
					snprintf (key, sizeof (key) - 1, "meta.C.0x%"PFMT64x, addr);
					val = sdb_const_get (core->anal->sdb_meta, key, 0);
					if (val) {
						comma = strchr (val, ',');
						if (comma) {
							str = (char *) sdb_decode (comma + 1, 0);
							if (strstr (str, input + 2)) {
								r_cons_printf ("0x%08"PFMT64x "  %s\n", addr, str);
								count++;
								cb.addr = addr;
								free (cb.str);
								cb.str = str;
							} else {
								free (str);
							}
						}
					} else {
						eprintf ("sdb_const_get key not found '%s'\n", key);
					}
					if (!next) {
						break;
					}
					cur = next;
				}
			}

			switch (count) {
			case 0:
				eprintf ("No matching comments\n");
				break;
			case 1:
				off = cb.addr;
				if (!silent) {
					r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print));
				}
				r_core_seek (core, off, 1);
				r_core_block_read (core);
				break;
			default:
				eprintf ("Too many results\n");
				break;
			}
			free (cb.str);
		} else {
			const char *help_msg[] = {
				"Usage:", "sC", "Comment grep",
				"sC", "*", "List all comments",
				"sC", " str", "Seek to the first comment matching 'str'",
				NULL
			};
			r_core_cmd_help (core, help_msg);
		}
		break;
	case ' ':
		if (!silent) {
			r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print));
		}
		r_core_seek (core, off * sign, 1);
		r_core_block_read (core);
		break;
	case '/':
	{
		const char *pfx = r_config_get (core->config, "search.prefix");
		ut64 from = r_config_get_i (core->config, "search.from");
// kwidx cfg var is ignored
		int kwidx = core->search->n_kws; // (int)r_config_get_i (core->config, "search.kwidx")-1;
		if (kwidx < 0) {
			kwidx = 0;
		}
		switch (input[1]) {
		case ' ':
		case 'v':
		case 'V':
		case 'w':
		case 'W':
		case 'z':
		case 'm':
		case 'c':
		case 'A':
		case 'e':
		case 'E':
		case 'i':
		case 'R':
		case 'r':
		case '/':
		case 'x':
			r_config_set_i (core->config, "search.from", core->offset + 1);
			r_config_set_i (core->config, "search.count", 1);
			r_core_cmdf (core, "s+1; %s; s-1; s %s%d_0; f-%s%d_0",
				input, pfx, kwidx, pfx, kwidx, pfx, kwidx);
			r_config_set_i (core->config, "search.from", from);
			r_config_set_i (core->config, "search.count", 0);
			break;
		case '?':
			eprintf ("Usage: s/.. arg.\n");
			r_cons_printf ("/?\n");
			break;
		default:
			eprintf ("unknown search method\n");
			break;
		}
	}
	break;
	case '.':
		for (input++; *input == '.'; input++) {
			;
		}
		r_core_seek_base (core, input);
		break;
	case 'j':  // sj
		{
			RList /*<ut64 *>*/ *addrs = r_list_newf (free);
			RList /*<char *>*/ *names = r_list_newf (free);
			RList *list = r_io_sundo_list (core->io, '!');
			ut64 lsz = 0;
			ut64 i;
			RListIter *iter;
			RIOUndos *undo;
			if (list) {
				r_list_foreach (list, iter, undo) {
					char *name = NULL;

					core->flags->space_strict = true;
					RFlagItem *f = r_flag_get_at (core->flags, undo->off, true);
					core->flags->space_strict = false;
					if (f) {
						if (f->offset != undo->off) {
							name = r_str_newf ("%s + %d\n", f->name,
									(int)(undo->off- f->offset));
						} else {
							name = strdup (f->name);
						}
					}
					if (!name) {
						name = strdup ("");
					}
					ut64 *val = malloc (sizeof (ut64));
					if (!val) {
						free (name);
						break;
					}
					*val = undo->off;
					r_list_append (addrs, val);
					r_list_append (names, strdup (name));
					lsz++;
					free (name);
				}
				r_list_free (list);
			}
			r_cons_printf ("[");
			for (i = 0; i < lsz; ++i) {
				ut64 *addr = r_list_get_n (addrs, i);
				const char *name = r_list_get_n (names, i);
				// XXX(should the "name" field be optional? That might make
				// a bit more sense.
				r_cons_printf ("{\"offset\":%"PFMT64d",\"symbol\":\"%s\"}", *addr, name);
				if (i != lsz - 1) {
					r_cons_printf (",");
				}
			}
			r_cons_printf ("]\n");
			r_list_free (addrs);
			r_list_free (names);
		}
		break;
	case '*':
	case '=':
	case '!':
		{
			RList *list = r_io_sundo_list (core->io, input[0]);
			RListIter *iter;
			RIOUndos *undo;
			if (list) {
				r_list_foreach (list, iter, undo) {
					char *name = NULL;

					core->flags->space_strict = true;
					RFlagItem *f = r_flag_get_at (core->flags, undo->off, true);
					core->flags->space_strict = false;
					if (f) {
						if (f->offset != undo->off) {
							name = r_str_newf ("%s + %d\n", f->name,
									(int)(undo->off- f->offset));
						} else {
							name = strdup (f->name);
						}
					}
					if (!name) {
						name = strdup ("");
					}
					r_cons_printf ("0x%"PFMT64x" %s\n", undo->off, name);
					free (name);
				}
				r_list_free (list);
			}
		}
Esempio n. 7
0
///////////////////////////////////////////////////////////////////////////////
// TODO: need refactor
static void print_types(R_PDB *pdb, int mode) {
	ELeafType lt = eLF_MAX;
	char *command_field = 0;
	char *name_field = 0;
	char *flags_format_field = 0; // format for struct
	char **members_name_field = 0;
	char *type = 0;
	int members_amount = 0;
	int i = 0;
	int pos = 0;
	char sym = ' ';
	int is_first = 1;
	char *name = NULL;
	int val = 0;
	int offset = 0;
	SType *t = 0;
	STypeInfo *tf = 0;
	RListIter *it = 0, *it2 = 0;
	RList *plist = pdb->pdb_streams, *ptmp = NULL;
	STpiStream *tpi_stream = r_list_get_n (plist, ePDB_STREAM_TPI);

	if (!tpi_stream) {
		eprintf ("there is no tpi stream in current pdb\n");
		return;
	}

	if (mode == 'j') {
		pdb->cb_printf ("{\"%s\":[","types");
	}

	it = r_list_iterator(tpi_stream->types);
	while (r_list_iter_next(it)) {
		pos = 0;
		i = 0;
		members_amount = 0;
		val = 0;
		t = (SType *) r_list_iter_get(it);
		tf = &t->type_data;
		lt = tf->leaf_type;
		if ((tf->leaf_type == eLF_STRUCTURE) || (tf->leaf_type == eLF_UNION) || (tf->leaf_type == eLF_ENUM)) {
			if (tf->is_fwdref) {
				tf->is_fwdref (tf, &val);
				if (val == 1) {
					continue;
				}
			}
			if ((mode == 'j') && (is_first == 0)) {
				pdb->cb_printf (",");
			}
			is_first = 0;
			if (tf->get_name) {
				tf->get_name (tf, &name);
			}
			// val for STRUCT or UNION mean size
			if (tf->get_val) {
				tf->get_val (tf, &val);
			}
			if (tf->get_members) {
				tf->get_members (tf, &ptmp);
			}
			//pdb->cb_printf ("%s: size 0x%x\n", name, val);
			switch (mode) {
			case 'd': pdb->cb_printf ("%s: size 0x%x\n", name, val); break;
			case 'r':
				build_command_field (lt, &command_field);
				build_name_field (name, &name_field);
				if (!alloc_format_flag_and_member_fields (ptmp, &flags_format_field,
						&members_amount, &members_name_field)) {
					goto err;
				}
				break;
			case 'j':
				switch (lt) {
				case eLF_ENUM:
					pdb->cb_printf ("{\"type\":\"%s\", \"name\":\"%s\",\"%s\":[",
								"enum", name , "enums");
					break;
				case eLF_STRUCTURE:
				case eLF_UNION:
					pdb->cb_printf("{\"type\":\"%s\",\"name\":\"%s\",\"%s\":[",
								"structure", name, "members");
					break;
				default:
					continue;
				}

				break;
			}

			it2 = r_list_iterator (ptmp);
			while (r_list_iter_next (it2)) {
				if ((mode == 'j') && (i)) {
					pdb->cb_printf (",");
				}
				tf = (STypeInfo *) r_list_iter_get(it2);
				if (tf->get_name) {
					tf->get_name (tf, &name);
				}
				if (tf->get_val) {
					tf->get_val (tf, &offset);
				} else {
					offset = 0;
				}
				if (tf->get_print_type) {
					tf->get_print_type (tf, &type);
				}
				switch (mode) {
				case 'd':
					pdb->cb_printf ("  0x%x: %s type:", offset, name);
					pdb->cb_printf ("%s\n", type);
					break;
				case 'r':
					if (!build_flags_format_and_members_field(pdb, lt, name, type, i,
							&pos, offset, flags_format_field, members_name_field)) {
						R_FREE (type);
						goto err;
					}
					break;
				case 'j': // JSON
					switch (lt) {
					case eLF_ENUM:
						pdb->cb_printf ("{\"%s\":\"%s\",\"%s\":%d}",
								"enum_name", name, "enum_val", offset);
						break;
					case eLF_STRUCTURE:
					case eLF_UNION:
						pdb->cb_printf ("{\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":%d}",
								"member_type", type + strlen("(member)") + 1,
								"member_name", name, "offset", offset);
						break;
					default:
						break;
					}
					break;
				}
				R_FREE (type);
				i++;
			}

			if (mode == 'r') {
				pdb->cb_printf ("%s %s ", command_field, name_field);
				if (lt != eLF_ENUM) {
					pdb->cb_printf ("%s ", flags_format_field);
				} else {
					pdb->cb_printf ("%c ", '{');
				}
				sym = (lt == eLF_ENUM) ? ',' : ' ';
				for (i = 0; i < members_amount; i++) {
					pdb->cb_printf ("%s", members_name_field[i]);
					if ((i + 1) != members_amount) {
						pdb->cb_printf ("%c", sym);
					}
				}
				if (lt == eLF_ENUM) {
					pdb->cb_printf (" };\"\n");
				} else {
					pdb->cb_printf ("\n");
				}
			}
			if (mode == 'j') {
				pdb->cb_printf ("]}");
			}
err:
			if (mode == 'r') {
				R_FREE (command_field);
				R_FREE(name_field);
				R_FREE(flags_format_field);
				for (i = 0; i < members_amount; i++) {
					R_FREE (members_name_field[i]);
				}
				R_FREE (members_name_field);
			}
		}
	}

	if (mode == 'j') {
		pdb->cb_printf ("]}");
	}
}
Esempio n. 8
0
static void print_gvars(R_PDB *pdb, ut64 img_base, int format) {
	SStreamParseFunc *omap = 0, *sctns = 0, *sctns_orig = 0 , *gsym = 0, *tmp = 0;
	SIMAGE_SECTION_HEADER *sctn_header = 0;
	SGDATAStream *gsym_data_stream = 0;
	SPEStream *pe_stream = 0;
	SGlobal *gdata = 0;
	RListIter *it = 0;
	RList *l = 0;
	int is_first = 1;

	l = pdb->pdb_streams2;
	it = r_list_iterator (l);
	while (r_list_iter_next (it)) {
		tmp = (SStreamParseFunc *) r_list_iter_get(it);
		switch (tmp->type) {
		case ePDB_STREAM_SECT__HDR_ORIG:
			sctns_orig = tmp;
			break;
		case ePDB_STREAM_SECT_HDR:
			sctns = tmp;
			break;
		case ePDB_STREAM_OMAP_FROM_SRC:
			omap = tmp;
			break;
		case ePDB_STREAM_GSYM:
			gsym = tmp;
			break;
		default:
			break;
		}
	}
	if (!gsym) {
		eprintf ("there is no global symbols in current pdb\n");
		return;
	}
	if (format == 'j') {
		pdb->cb_printf ("{\"%s\":[","gvars");
	}
	gsym_data_stream = (SGDATAStream *) gsym->stream;
	if ((omap != 0) && (sctns_orig != 0)) {
		pe_stream = (SPEStream *) sctns_orig->stream;
	} else {
		pe_stream = (SPEStream *) sctns->stream;
	}
	it = r_list_iterator (gsym_data_stream->globals_list);
	while (r_list_iter_next (it)) {
		gdata = (SGlobal *) r_list_iter_get (it);
		sctn_header = r_list_get_n (pe_stream->sections_hdrs, (gdata->segment -1));
		if (sctn_header) {
			char *name = r_name_filter2 (gdata->name.name);
			switch (format) {
			case 2:
			case 'j': // JSON
				if (!is_first) {
					pdb->cb_printf (",");
				}
				pdb->cb_printf ("{\"%s\":%d,\"%s\":%d,\"%s\":\"%s\",\"%s\":\"%s\"}",
							"address", (ut64)(img_base + omap_remap((omap) ? (omap->stream) : 0, gdata->offset + sctn_header->virtual_address)),
							"symtype", gdata->symtype,
							"section_name", sctn_header->name,
							"gdata_name", name);
				break;
			case 1:
			case '*':
			case 'r':
				pdb->cb_printf ("f pdb.%s = 0x%"PFMT64x" # %d %s\n",
						name,
						(ut64)(img_base + omap_remap((omap) ? (omap->stream) : 0,
							gdata->offset + sctn_header->virtual_address)),
						gdata->symtype, sctn_header->name);
				break;
			case 'd':
			default:
				pdb->cb_printf ("0x%08"PFMT64x"  %d  %s  %s\n",
					(ut64) (img_base + omap_remap((omap) ? (omap->stream) : 0,
						gdata->offset + sctn_header->virtual_address)),
					gdata->symtype, sctn_header->name, gdata->name.name);
				break;
			}
			// TODO: implement MSVC C++ name demangle
			free (name);
		} else {
			eprintf ("Skipping %s, segment %d does not exist\n",
				   gdata->name.name, (gdata->segment -1));
		}
		is_first = 0;
	}
	if (format == 'j') {
		pdb->cb_printf ("]}");
	}
}