static struct r_bin_pe_section_t* PE_(r_bin_pe_get_sections)(RBinPEObj* pe) {
	struct r_bin_pe_section_t* sections = NULL;
	int i, j, section_count = 0;

	if (!pe || !pe->nt_headers) {
		return NULL;
	}
	PE_(image_section_header) * shdr = pe->section_header;
	for (i = 0; i < pe->num_sections; i++) {
		//just allocate the needed
		if (shdr[i].SizeOfRawData || shdr[i].Misc.VirtualSize) {
			section_count++;
		}
	}
	sections = calloc (section_count + 1, sizeof (struct r_bin_pe_section_t));
	if (!sections) {
		r_sys_perror ("malloc (sections)");
		return NULL;
	}
	for (i = 0, j = 0; i < pe->num_sections; i++) {
		if (!shdr[i].SizeOfRawData && !shdr[i].Misc.VirtualSize) {
			continue;
		}
		if (shdr[i].Name[0] == '\0') {
			char* new_name = r_str_newf ("sect_%d", j);
			r_str_ncpy ((char*) sections[j].name, new_name, R_ARRAY_SIZE (sections[j].name) - 1);
			free (new_name);
		} else if (shdr[i].Name[0] == '/') {
			// section header is not null terminated, so use ndup
			char *n = r_str_ndup ((const char *)shdr[i].Name + 1, sizeof (shdr[i].Name) - 1);
			int idx = atoi (n);
			free (n);
			ut64 sym_tbl_off = pe->nt_headers->file_header.PointerToSymbolTable;
			int num_symbols = pe->nt_headers->file_header.NumberOfSymbols;
			st64 off = num_symbols * COFF_SYMBOL_SIZE;
			if (off > 0 && sym_tbl_off &&
			    sym_tbl_off + off + idx < pe->size &&
			    sym_tbl_off + off + idx > off) {
				int sz = PE_IMAGE_SIZEOF_SHORT_NAME * 3;
				char* buf[64] = {0};
				if (r_buf_read_at (pe->b,
						   sym_tbl_off + off + idx,
						   (ut8*)buf, 64)) {
					memcpy (sections[j].name, buf, sz);
					sections[j].name[sz - 1] = '\0';
				}
			}
		} else {
			memcpy (sections[j].name, shdr[i].Name, PE_IMAGE_SIZEOF_SHORT_NAME);
			sections[j].name[PE_IMAGE_SIZEOF_SHORT_NAME] = '\0';
		}
		sections[j].vaddr = shdr[i].VirtualAddress;
		sections[j].size = shdr[i].SizeOfRawData;
		if (shdr[i].Misc.VirtualSize) {
			sections[j].vsize = shdr[i].Misc.VirtualSize;
		} else {
			sections[j].vsize = shdr[i].SizeOfRawData;
		}
		sections[j].paddr = shdr[i].PointerToRawData;
		if (pe->optional_header) {
			ut32 sa = pe->optional_header->SectionAlignment;
			if (sa) {
				ut64 diff = sections[j].vsize % sa;
				if (diff) {
					sections[j].vsize += sa - diff;
				}
				if (sections[j].vaddr % sa) {
					pe_printf ("Warning: section %s not aligned to SectionAlignment.\n",
							sections[j].name);
				}
			}
			const ut32 fa = pe->optional_header->FileAlignment;
			if (fa) {
				const ut64 diff = sections[j].paddr % fa;
				if (diff) {
					pe_printf ("Warning: section %s not aligned to FileAlignment.\n", sections[j].name);
					sections[j].paddr -= diff;
					sections[j].size += diff;	
				}
			}
		}
		sections[j].perm = shdr[i].Characteristics;
		sections[j].last = 0;
		j++;
	}
	sections[j].last = 1;
	pe->num_sections = section_count;
	return sections;
}
static struct r_bin_pe_section_t* PE_(r_bin_pe_get_sections)(RBinPEObj* pe) {
	struct r_bin_pe_section_t* sections = NULL;
	int i, j, section_count = 0;

	if (!pe || !pe->nt_headers) {
		return NULL;
	}
	PE_(image_section_header) * shdr = pe->section_header;
	for (i = 0; i < pe->num_sections; i++) {
		 
		if (shdr[i].SizeOfRawData || shdr[i].Misc.VirtualSize) {
			section_count++;
		}
	}
	sections = calloc (section_count + 1, sizeof (struct r_bin_pe_section_t));
	if (!sections) {
		r_sys_perror ("malloc (sections)");
		return NULL;
	}
	for (i = 0, j = 0; i < pe->num_sections; i++) {
		if (!shdr[i].SizeOfRawData && !shdr[i].Misc.VirtualSize) {
			continue;
		}
		if (shdr[i].Name[0] == '\0') {
			char* new_name = r_str_newf ("sect_%d", j);
			r_str_ncpy ((char*) sections[j].name, new_name, R_ARRAY_SIZE (sections[j].name) - 1);
			free (new_name);
		} else if (shdr[i].Name[0] == '/') {
			 
			char *n = r_str_ndup ((const char *)shdr[i].Name + 1, sizeof (shdr[i].Name) - 1);
			int idx = atoi (n);
			free (n);
			ut64 sym_tbl_off = pe->nt_headers->file_header.PointerToSymbolTable;
			int num_symbols = pe->nt_headers->file_header.NumberOfSymbols;
			st64 off = num_symbols * COFF_SYMBOL_SIZE;
			if (off > 0 && sym_tbl_off &&
			    sym_tbl_off + off + idx < pe->size &&
			    sym_tbl_off + off + idx > off) {
				int sz = PE_IMAGE_SIZEOF_SHORT_NAME * 3;
				char* buf[64] = {0};
				if (r_buf_read_at (pe->b,
						   sym_tbl_off + off + idx,
						   (ut8*)buf, 64)) {
					memcpy (sections[j].name, buf, sz);
					sections[j].name[sz - 1] = '\0';
				}
			}
		} else {
			memcpy (sections[j].name, shdr[i].Name, PE_IMAGE_SIZEOF_SHORT_NAME);
			sections[j].name[PE_IMAGE_SIZEOF_SHORT_NAME] = '\0';
		}
		sections[j].vaddr = shdr[i].VirtualAddress;
		sections[j].size = shdr[i].SizeOfRawData;
		if (shdr[i].Misc.VirtualSize) {
			sections[j].vsize = shdr[i].Misc.VirtualSize;
		} else {
			sections[j].vsize = shdr[i].SizeOfRawData;
		}
		sections[j].paddr = shdr[i].PointerToRawData;
		if (pe->optional_header) {
			ut32 sa = pe->optional_header->SectionAlignment;
			if (sa) {
				ut64 diff = sections[j].vsize % sa;
				if (diff) {
					sections[j].vsize += sa - diff;
				}
				if (sections[j].vaddr % sa) {
					pe_printf ("Warning: section %s not aligned to SectionAlignment.\n",
							sections[j].name);
				}
			}
			const ut32 fa = pe->optional_header->FileAlignment;
			if (fa) {
				const ut64 diff = sections[j].paddr % fa;
				if (diff) {
					pe_printf ("Warning: section %s not aligned to FileAlignment.\n", sections[j].name);
					sections[j].paddr -= diff;
					sections[j].size += diff;	
				}
			}
		}
		sections[j].perm = shdr[i].Characteristics;
		sections[j].last = 0;
		j++;
	}
	sections[j].last = 1;
	pe->num_sections = section_count;
	return sections;
}