Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/jit/jit-elf-read.c  view on Meta::CPAN

	Elf_Off memory_size;
	Elf_Off start, end;
	Elf_Phdr *phdr;
	unsigned int index;
	void *base_address;
	unsigned char *segment_address;

	/* Get the maximum file and memory sizes for the program.
	   The bytes between "file_size" and "memory_size" are bss */
	file_size = 0;
	memory_size = 0;
	for(index = 0; index < readelf->ehdr.e_phnum; ++index)
	{
		phdr = get_phdr(readelf, index);
		if(!phdr)
		{
			continue;
		}
		start = phdr->p_offset;
		end = start + phdr->p_filesz;
		if(end > file_size)
		{
			file_size = end;
		}
		start = phdr->p_vaddr;
		end = start + phdr->p_memsz;
		if(end > memory_size)
		{
			memory_size = end;
		}
	}
	if(memory_size < file_size)
	{
		memory_size = file_size;
	}

	/* Try to map the program segments into memory using mmap */
	base_address = 0;
#ifdef JIT_USE_MMAP_TO_LOAD
	{
		Elf_Off page_size;
		Elf_Off rounded_file_size;
		Elf_Off temp_start;
		Elf_Off temp_end;
		int zero_fd, prot;

		/* Round the total memory and file sizes up to the CPU page size */
		page_size = (Elf_Off)(jit_vmem_page_size());
		end = memory_size;
		if((end % page_size) != 0)
		{
			end += page_size - (end % page_size);
		}
		rounded_file_size = file_size;
		if((rounded_file_size % page_size) != 0)
		{
			rounded_file_size += page_size - (rounded_file_size % page_size);
		}

		/* Allocate memory for the program from /dev/zero.  Once we have
		   the memory, we will overlay the program segments on top */
		zero_fd = sys_open("/dev/zero", O_RDWR, 0);
		if(zero_fd < -1)
		{
			goto failed_mmap;
		}
		base_address = mmap(0, (size_t)end, PROT_READ | PROT_WRITE,
							MAP_ANON | MAP_PRIVATE, zero_fd, 0);
		close(zero_fd);
		if(base_address == (void *)(jit_nint)(-1))
		{
			base_address = 0;
			goto failed_mmap;
		}

		/* Lay down the program sections at their mapped locations */
		for(index = 0; index < readelf->ehdr.e_phnum; ++index)
		{
			phdr = get_phdr(readelf, index);
			if(phdr)
			{
				temp_start = phdr->p_offset;
				temp_end = temp_start + phdr->p_filesz;
				temp_start -= (temp_start % page_size);
				if((temp_end % page_size) != 0)
				{
					temp_end += page_size - (temp_end % page_size);
				}
				start = phdr->p_vaddr;
				start -= (start % page_size);
				if(temp_start < temp_end)
				{
					segment_address =
						((unsigned char *)base_address) + (jit_nuint)start;
					prot = 0;
					if((phdr->p_flags & PF_X) != 0)
					{
						prot |= PROT_EXEC;
					}
					if((phdr->p_flags & PF_W) != 0)
					{
						prot |= PROT_WRITE;
					}
					if((phdr->p_flags & PF_R) != 0)
					{
						prot |= PROT_READ;
					}
					if(mmap(segment_address, (size_t)(temp_end - temp_start),
						    prot, MAP_COPY | MAP_FILE | MAP_FIXED, fd,
							(off_t)temp_start) == (void *)(jit_nint)(-1))
					{
						munmap(base_address, (size_t)end);
						base_address = 0;
						goto failed_mmap;
					}
				}
			}
		}

		/* We need to free the memory with munmap when the program is closed */
		readelf->free_with_munmap = 1;



( run in 0.735 second using v1.01-cache-2.11-cpan-d59ab9ce9b0 )