static struct r_bin_pe_export_t* parse_symbol_table(struct PE_(r_bin_pe_obj_t)* bin, 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;
	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 (!bin || !bin->nt_headers) {
		return NULL;
	}

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

	sections = PE_(r_bin_pe_get_sections) (bin);
	for (i = 0; i < bin->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;
		}
	}
	free (sections);
	symctr = 0;
	if (r_buf_read_at (bin->b, sym_tbl_off, (ut8*) buf, bufsz)) {
		for (i = 0; i < shsz; i += srsz) {
			sr = (SymbolRecord*) (buf + i);
			//bprintf ("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 = (ut32*) (buf + i + 4);
						if (r_buf_read_at (bin->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].vaddr = bin_pe_rva_to_va (bin, 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(struct PE_(r_bin_pe_obj_t)* bin, 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;
	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 (!bin || !bin->nt_headers) {
		return NULL;
	}

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

	sections = PE_(r_bin_pe_get_sections) (bin);
	for (i = 0; i < bin->num_sections; i++) {
		 
		if (!strcmp ((char*) sections[i].name, ".text")) {
			text_rva = sections[i].vaddr;
			text_off = sections[i].paddr;
			textn = i + 1;
		}
	}
	free (sections);
	symctr = 0;
	if (r_buf_read_at (bin->b, sym_tbl_off, (ut8*) buf, bufsz)) {
		for (i = 0; i < shsz; i += srsz) {
			sr = (SymbolRecord*) (buf + i);
			 
			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 = (ut32*) (buf + i + 4);
						if (r_buf_read_at (bin->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].vaddr = bin_pe_rva_to_va (bin, 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;
}