struct r_bin_pe_addr_t* PE_(r_bin_pe_get_entrypoint)(RBinPEObj* pe) {
	struct r_bin_pe_addr_t* entry = NULL;
	static bool debug = false;
	int i;
	ut64 base_addr = PE_(r_bin_pe_get_image_base) (pe);
	if (!pe || !pe->optional_header) {
		return NULL;
	}
	if (!(entry = malloc (sizeof (struct r_bin_pe_addr_t)))) {
		r_sys_perror ("malloc (entrypoint)");
		return NULL;
	}
	PE_DWord pe_entry = pe->optional_header->AddressOfEntryPoint;
	entry->vaddr = bin_pe_rva_to_va (pe, pe_entry);
	entry->paddr = PE_(va2pa) (pe, pe_entry);
	// haddr is the address of AddressOfEntryPoint in header.
	entry->haddr = pe->dos_header->e_lfanew + 4 + sizeof (PE_(image_file_header)) + 16;

	if (entry->paddr >= pe->size) {
		struct r_bin_pe_section_t* sections = pe->sections;
		ut64 paddr = 0;
		if (!debug) {
			pe_printf ("Warning: Invalid entrypoint ... "
				"trying to fix it but i do not promise nothing\n");
		}
		for (i = 0; i < pe->num_sections; i++) {
			if (sections[i].perm & PE_IMAGE_SCN_MEM_EXECUTE) {
				entry->paddr = sections[i].paddr;
				entry->vaddr = sections[i].vaddr + base_addr;
				paddr = 1;
				break;
			}

		}
		if (!paddr) {
			ut64 min_off = -1;
			for (i = 0; i < pe->num_sections; i++) {
				//get the lowest section's paddr
				if (sections[i].paddr < min_off) {
					entry->paddr = sections[i].paddr;
					entry->vaddr = sections[i].vaddr + base_addr;
					min_off = sections[i].paddr;
				}
			}
			if (min_off == -1) {
				//no section just a hack to try to fix entrypoint
				//maybe doesn't work always
				int sa = R_MAX (pe->optional_header->SectionAlignment, 0x1000);
				entry->paddr = pe_entry & ((sa << 1) - 1);
				entry->vaddr = entry->paddr + base_addr;
			}
		}
	}
	if (!entry->paddr) {
		if (!debug) {
			pe_printf ("Warning: NULL entrypoint\n");
		}
		struct r_bin_pe_section_t* sections = pe->sections;
		for (i = 0; i < pe->num_sections; i++) {
			//If there is a section with x without w perm is a good candidate to be the entrypoint
			if (sections[i].perm & PE_IMAGE_SCN_MEM_EXECUTE && !(sections[i].perm & PE_IMAGE_SCN_MEM_WRITE)) {
				entry->paddr = sections[i].paddr;
				entry->vaddr = sections[i].vaddr + base_addr;
				break;
			}

		}
	}

	if (is_arm (pe) && entry->vaddr & 1) {
		entry->vaddr--;
		if (entry->paddr & 1) {
			entry->paddr--;
		}
	}
	if (!debug) {
		debug = true;
	}
	return entry;
}
struct r_bin_pe_addr_t* PE_(r_bin_pe_get_entrypoint)(RBinPEObj* pe) {
	struct r_bin_pe_addr_t* entry = NULL;
	static bool debug = false;
	int i;
	ut64 base_addr = PE_(r_bin_pe_get_image_base) (pe);
	if (!pe || !pe->optional_header) {
		return NULL;
	}
	if (!(entry = malloc (sizeof (struct r_bin_pe_addr_t)))) {
		r_sys_perror ("malloc (entrypoint)");
		return NULL;
	}
	PE_DWord pe_entry = pe->optional_header->AddressOfEntryPoint;
	entry->vaddr = bin_pe_rva_to_va (pe, pe_entry);
	entry->paddr = PE_(va2pa) (pe, pe_entry);
	 
	entry->haddr = pe->dos_header->e_lfanew + 4 + sizeof (PE_(image_file_header)) + 16;

	if (entry->paddr >= pe->size) {
		struct r_bin_pe_section_t* sections = pe->sections;
		ut64 paddr = 0;
		if (!debug) {
			pe_printf ("Warning: Invalid entrypoint ... "
				"trying to fix it but i do not promise nothing\n");
		}
		for (i = 0; i < pe->num_sections; i++) {
			if (sections[i].perm & PE_IMAGE_SCN_MEM_EXECUTE) {
				entry->paddr = sections[i].paddr;
				entry->vaddr = sections[i].vaddr + base_addr;
				paddr = 1;
				break;
			}

		}
		if (!paddr) {
			ut64 min_off = -1;
			for (i = 0; i < pe->num_sections; i++) {
				 
				if (sections[i].paddr < min_off) {
					entry->paddr = sections[i].paddr;
					entry->vaddr = sections[i].vaddr + base_addr;
					min_off = sections[i].paddr;
				}
			}
			if (min_off == -1) {
				 
				 
				int sa = R_MAX (pe->optional_header->SectionAlignment, 0x1000);
				entry->paddr = pe_entry & ((sa << 1) - 1);
				entry->vaddr = entry->paddr + base_addr;
			}
		}
	}
	if (!entry->paddr) {
		if (!debug) {
			pe_printf ("Warning: NULL entrypoint\n");
		}
		struct r_bin_pe_section_t* sections = pe->sections;
		for (i = 0; i < pe->num_sections; i++) {
			 
			if (sections[i].perm & PE_IMAGE_SCN_MEM_EXECUTE && !(sections[i].perm & PE_IMAGE_SCN_MEM_WRITE)) {
				entry->paddr = sections[i].paddr;
				entry->vaddr = sections[i].vaddr + base_addr;
				break;
			}

		}
	}

	if (is_arm (pe) && entry->vaddr & 1) {
		entry->vaddr--;
		if (entry->paddr & 1) {
			entry->paddr--;
		}
	}
	if (!debug) {
		debug = true;
	}
	return entry;
}