static struct r_bin_pe_export_t* parse_symbol_table(RBinPEObj* pe, struct r_bin_pe_export_t* exports, int sz) {
	ut64 sym_tbl_off, num = 0;
	const int srsz = COFF_SYMBOL_SIZE; // symbol record size
	struct r_bin_pe_section_t* sections;
	struct r_bin_pe_export_t* exp;
	struct r_bin_pe_export_t* new_exports = NULL;
	const size_t export_t_sz = sizeof (struct r_bin_pe_export_t);
	int bufsz, i, shsz;
	SymbolRecord sr;
	ut64 text_off = 0LL;
	ut64 text_rva = 0LL;
	int textn = 0;
	int exports_sz;
	int symctr = 0;
	char* buf;

	if (!pe || !pe->nt_headers) {
		return NULL;
	}

	sym_tbl_off = pe->nt_headers->file_header.PointerToSymbolTable;
	num = pe->nt_headers->file_header.NumberOfSymbols;
	shsz = bufsz = num * srsz;
	if (bufsz < 1 || bufsz > pe->size) {
		return NULL;
	}
	buf = calloc (num, srsz);
	if (!buf) {
		return NULL;
	}
	exports_sz = export_t_sz * num;
	if (exports) {
		int osz = sz;
		sz += exports_sz;
		new_exports = realloc (exports, sz + export_t_sz);
		if (!new_exports) {
			free (buf);
			return NULL;
		}
		exports = new_exports;
		new_exports = NULL;
		exp = (struct r_bin_pe_export_t*) (((const ut8*) exports) + osz);
	} else {
		sz = exports_sz;
		exports = malloc (sz + export_t_sz);
		exp = exports;
	}

	sections = pe->sections;
	for (i = 0; i < pe->num_sections; i++) {
		//XXX search by section with +x permission since the section can be left blank
		if (!strcmp ((char*) sections[i].name, ".text")) {
			text_rva = sections[i].vaddr;
			text_off = sections[i].paddr;
			textn = i + 1;
		}
	}
	symctr = 0;
	if (r_buf_read_at (pe->b, sym_tbl_off, (ut8*) buf, bufsz) > 0) {
		for (i = 0; i < shsz; i += srsz) {
			// sr = (SymbolRecord*) (buf + i);
			if (i + sizeof (sr) >= bufsz) {
				break;
			}
			memcpy (&sr, buf + i, sizeof (sr));
			//pe_printf ("SECNUM %d\n", sr.secnum);
			if (sr.secnum == textn) {
				if (sr.symtype == 32) {
					char shortname[9];
					memcpy (shortname, &sr.shortname, 8);
					shortname[8] = 0;
					if (*shortname) {
						strncpy ((char*) exp[symctr].name, shortname, PE_NAME_LENGTH - 1);
					} else {
						char* longname, name[128];
						ut32 idx = r_read_le32 (buf + i + 4);
						if (r_buf_read_at (pe->b, sym_tbl_off + idx + shsz, (ut8*) name, 128)) { // == 128) {
							longname = name;
							name[sizeof (name) - 1] = 0;
							strncpy ((char*) exp[symctr].name, longname, PE_NAME_LENGTH - 1);
						} else {
							sprintf ((char*) exp[symctr].name, "unk_%d", symctr);
						}
					}
					exp[symctr].name[PE_NAME_LENGTH] = '\0';
					exp[symctr].libname[0] = '\0';
					exp[symctr].vaddr = bin_pe_rva_to_va (pe, text_rva + sr.value);
					exp[symctr].paddr = text_off + sr.value;
					exp[symctr].ordinal = symctr;
					exp[symctr].forwarder[0] = 0;
					exp[symctr].last = 0;
					symctr++;
				}
			}
		} // for
	} // if read ok
	exp[symctr].last = 1;
	free (buf);
	return exports;
}
static struct r_bin_pe_export_t* parse_symbol_table(RBinPEObj* pe, struct r_bin_pe_export_t* exports, int sz) {
	ut64 sym_tbl_off, num = 0;
	const int srsz = COFF_SYMBOL_SIZE;  
	struct r_bin_pe_section_t* sections;
	struct r_bin_pe_export_t* exp;
	struct r_bin_pe_export_t* new_exports = NULL;
	const size_t export_t_sz = sizeof (struct r_bin_pe_export_t);
	int bufsz, i, shsz;
	SymbolRecord sr;
	ut64 text_off = 0LL;
	ut64 text_rva = 0LL;
	int textn = 0;
	int exports_sz;
	int symctr = 0;
	char* buf;

	if (!pe || !pe->nt_headers) {
		return NULL;
	}

	sym_tbl_off = pe->nt_headers->file_header.PointerToSymbolTable;
	num = pe->nt_headers->file_header.NumberOfSymbols;
	shsz = bufsz = num * srsz;
	if (bufsz < 1 || bufsz > pe->size) {
		return NULL;
	}
	buf = calloc (num, srsz);
	if (!buf) {
		return NULL;
	}
	exports_sz = export_t_sz * num;
	if (exports) {
		int osz = sz;
		sz += exports_sz;
		new_exports = realloc (exports, sz + export_t_sz);
		if (!new_exports) {
			free (buf);
			return NULL;
		}
		exports = new_exports;
		new_exports = NULL;
		exp = (struct r_bin_pe_export_t*) (((const ut8*) exports) + osz);
	} else {
		sz = exports_sz;
		exports = malloc (sz + export_t_sz);
		exp = exports;
	}

	sections = pe->sections;
	for (i = 0; i < pe->num_sections; i++) {
		 
		if (!strcmp ((char*) sections[i].name, ".text")) {
			text_rva = sections[i].vaddr;
			text_off = sections[i].paddr;
			textn = i + 1;
		}
	}
	symctr = 0;
	if (r_buf_read_at (pe->b, sym_tbl_off, (ut8*) buf, bufsz) > 0) {
		for (i = 0; i < shsz; i += srsz) {
			 
			if (i + sizeof (sr) >= bufsz) {
				break;
			}
			memcpy (&sr, buf + i, sizeof (sr));
			 
			if (sr.secnum == textn) {
				if (sr.symtype == 32) {
					char shortname[9];
					memcpy (shortname, &sr.shortname, 8);
					shortname[8] = 0;
					if (*shortname) {
						strncpy ((char*) exp[symctr].name, shortname, PE_NAME_LENGTH - 1);
					} else {
						char* longname, name[128];
						ut32 idx = r_read_le32 (buf + i + 4);
						if (r_buf_read_at (pe->b, sym_tbl_off + idx + shsz, (ut8*) name, 128)) {  
							longname = name;
							name[sizeof (name) - 1] = 0;
							strncpy ((char*) exp[symctr].name, longname, PE_NAME_LENGTH - 1);
						} else {
							sprintf ((char*) exp[symctr].name, "unk_%d", symctr);
						}
					}
					exp[symctr].name[PE_NAME_LENGTH] = '\0';
					exp[symctr].libname[0] = '\0';
					exp[symctr].vaddr = bin_pe_rva_to_va (pe, text_rva + sr.value);
					exp[symctr].paddr = text_off + sr.value;
					exp[symctr].ordinal = symctr;
					exp[symctr].forwarder[0] = 0;
					exp[symctr].last = 0;
					symctr++;
				}
			}
		}  
	}  
	exp[symctr].last = 1;
	free (buf);
	return exports;
}