Alien-LibJIT

 view release on metacpan or  search on metacpan

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


	/* 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;

		/* Clear the left-over ".bss" bits that did not get cleared above */
		for(index = 0; index < readelf->ehdr.e_phnum; ++index)
		{
			phdr = get_phdr(readelf, index);
			if(phdr && phdr->p_filesz < phdr->p_memsz)
			{
				temp_start = phdr->p_vaddr + phdr->p_filesz;
				start = (temp_start % page_size);
				temp_start -= start;
				if(start != 0)
				{
					segment_address =
						((unsigned char *)base_address) +
						(jit_nuint)temp_start;
					mprotect(segment_address, (size_t)page_size,
							 PROT_READ | PROT_WRITE);
					jit_memzero(segment_address + (jit_nuint)start,
							    (unsigned int)(page_size - 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;
					}
					mprotect(segment_address, (size_t)page_size, prot);
				}
			}
		}
	}
failed_mmap:
#endif /* JIT_USE_MMAP_TO_LOAD */

	/* If we haven't mapped the file yet, then fall back to "malloc" */
	if(!base_address)
	{
		base_address = _jit_malloc_exec(memory_size);
		if(!base_address)
		{
			return 0;
		}
		for(index = 0; index < readelf->ehdr.e_phnum; ++index)
		{
			phdr = get_phdr(readelf, index);
			if(phdr)
			{
				segment_address = ((unsigned char *)base_address) +
								  (jit_nuint)(phdr->p_vaddr);
				if(lseek(fd, (off_t)(phdr->p_offset), 0) !=
						(off_t)(phdr->p_offset) ||
	               read(fd, segment_address, (size_t)(phdr->p_filesz))
				   		!= (int)(size_t)(phdr->p_filesz))
				{
					_jit_free_exec(base_address, memory_size);
					return 0;
				}
			}
		}
	}

	/* Record the mapped address and size for later */
	readelf->map_address = base_address;
	readelf->map_size = memory_size;
	return 1;
}

/*
 * Map an auxillary section into memory and return its base address.
 * Returns NULL if we ran out of memory.
 */
static void *map_section(int fd, Elf_Off offset, Elf_Xword file_size,
						 Elf_Xword memory_size, Elf_Word flags)
{
	void *address;
	if(memory_size < file_size)
	{
		memory_size = file_size;
	}
	address = _jit_malloc_exec(memory_size);
	if(!address)
	{
		return 0;
	}
	if(lseek(fd, (off_t)offset, 0) != (off_t)offset)
	{
		_jit_free_exec(address, memory_size);
		return 0;
	}
	if(read(fd, address, (size_t)file_size) != (int)(size_t)file_size)
	{
		_jit_free_exec(address, memory_size);
		return 0;
	}
	return address;
}

/*
 * Unmap an auxillary section from memory.
 */
static void unmap_section(void *address, Elf_Xword file_size,
						  Elf_Xword memory_size, Elf_Word flags)
{
	if(memory_size < file_size)
	{
		memory_size = file_size;
	}
	if((flags & JIT_ELF_IS_MALLOCED) != 0)
	{
		_jit_free_exec(address, (unsigned int)memory_size);
	}
}

/*
 * Iterate over the contents of the ".dynamic" section.
 */
typedef struct
{
	Elf_Dyn    *dyn;
	jit_nuint	size;

} jit_dynamic_iter_t;
static void dynamic_iter_init(jit_dynamic_iter_t *iter, jit_readelf_t readelf)
{
	iter->dyn = jit_readelf_get_section_by_type
		(readelf, SHT_DYNAMIC, &(iter->size));
}
static int dynamic_iter_next
	(jit_dynamic_iter_t *iter, jit_uint *type, Elf_Addr *value)
{
	if(iter->size >= sizeof(Elf_Dyn))
	{
		*type = (jit_uint)(iter->dyn->d_tag);
		*value = iter->dyn->d_un.d_ptr;
		if(*type == DT_NULL)
		{
			/* Explicitly-marked end of the list */
			return 0;
		}
		++(iter->dyn);
		iter->size -= sizeof(Elf_Dyn);
		return 1;
	}
	else
	{
		/* Implicitly-marked end of the list */
		return 0;
	}
}
static int dynamic_for_type
	(jit_readelf_t readelf, jit_uint type, Elf_Addr *value)
{
	Elf_Addr temp_value;
	jit_dynamic_iter_t iter;
	jit_uint iter_type;
	dynamic_iter_init(&iter, readelf);
	while(dynamic_iter_next(&iter, &iter_type, &temp_value))
	{
		if(iter_type == type)
		{
			if(value)
			{
				*value = temp_value;
			}
			return 1;
		}
	}
	return 0;
}

/*
 * Load interesting values from the ".dynamic" section, for quicker lookups.
 */
static void load_dynamic_section(jit_readelf_t readelf, int flags)
{
	Elf_Addr value;
	Elf_Addr value2;
	jit_dynamic_iter_t iter;
	jit_uint type;
	jit_nuint size;

	/* Get the position and size of the dynamic string table */
	if(dynamic_for_type(readelf, DT_STRTAB, &value) &&
	   dynamic_for_type(readelf, DT_STRSZ, &value2))
	{
		readelf->dynamic_strings = jit_readelf_map_vaddr
			(readelf, (jit_nuint)value);
		if(readelf->dynamic_strings)
		{
			readelf->dynamic_strings_size = (jit_nuint)value2;
		}
	}

	/* Get the position and size of the dynamic symbol table */
	readelf->symbol_table = jit_readelf_get_section_by_type
		(readelf, SHT_DYNSYM, &size);
	if(readelf->symbol_table)
	{
		if(dynamic_for_type(readelf, DT_SYMENT, &value) &&
		   value == sizeof(Elf_Sym))
		{
			readelf->symbol_table_size = size / sizeof(Elf_Sym);
			readelf->symbol_hash = jit_readelf_get_section_by_type
				(readelf, SHT_HASH, &size);
			if(readelf->symbol_hash)
			{
				readelf->symbol_hash_size = size / sizeof(Elf_Word);
				if(readelf->symbol_hash_size >= 2)
				{
					readelf->symbol_hash_buckets = readelf->symbol_hash[0];
				}
			}
		}
		else
		{
			readelf->symbol_table = 0;
		}
	}

	/* Bail out if we don't need to print debugging information */
	if((flags & JIT_READELF_FLAG_DEBUG) == 0)
	{
		return;
	}

	/* Iterate through the ".dynamic" section, dumping all that we find */
	dynamic_iter_init(&iter, readelf);
	while(dynamic_iter_next(&iter, &type, &value))
	{
		switch(type)
		{
			case DT_NEEDED:
			{
				printf("needed library: %s\n", get_dyn_string(readelf, value));
			}
			break;

			case DT_PLTRELSZ:
			{
				printf("total size of PLT relocs: %ld\n", (long)value);
			}
			break;

			case DT_PLTGOT:
			{
				printf("address of PLTGOT table: 0x%lx\n", (long)value);
			}
			break;

			case DT_HASH:
			{
				printf("address of symbol hash table: 0x%lx\n", (long)value);
			}
			break;

			case DT_STRTAB:
			{
				printf("address of string table: 0x%lx\n", (long)value);
			}
			break;

			case DT_SYMTAB:
			{
				printf("address of symbol table: 0x%lx\n", (long)value);
			}
			break;

			case DT_STRSZ:
			{
				printf("size of string table: %ld\n", (long)value);
			}
			break;

			case DT_SYMENT:
			{
				printf("size of one symbol table entry: %ld\n", (long)value);
			}
			break;

			case DT_INIT:
			{

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

				printf("address of PLT relocs: 0x%lx\n", (long)value);
			}
			break;

			default:
			{
				printf("dynamic info of type 0x%x: 0x%lx\n",
					   (int)type, (long)value);
			}
			break;
		}
	}

	/* Iterate through the symbol table, dumping all of the entries */
	for(size = 0; size < readelf->symbol_table_size; ++size)
	{
		printf("%08lX %02X%02X %2d %s\n",
			   (long)(readelf->symbol_table[size].st_value),
			   (int)(readelf->symbol_table[size].st_info),
			   (int)(readelf->symbol_table[size].st_other),
			   (int)(readelf->symbol_table[size].st_shndx),
			   get_dyn_string(readelf, readelf->symbol_table[size].st_name));
	}
	printf("number of symbols: %ld\n", (long)(readelf->symbol_table_size));
	printf("number of symbol hash entries: %ld\n",
		   (long)(readelf->symbol_hash_size));
}

/*@
 * @deftypefun int jit_readelf_open (jit_readelf_t *@var{readelf}, const char *@var{filename}, int @var{force})
 * Open the specified @var{filename} and load the ELF binary that is
 * contained within it.  Returns one of the following result codes:
 *
 * @table @code
 * @vindex JIT_READELF_OK
 * @item JIT_READELF_OK
 * The ELF binary was opened successfully.
 *
 * @vindex JIT_READELF_CANNOT_OPEN
 * @item JIT_READELF_CANNOT_OPEN
 * Could not open the file at the filesystem level (reason in @code{errno}).
 *
 * @vindex JIT_READELF_NOT_ELF
 * @item JIT_READELF_NOT_ELF
 * The file was opened, but it is not an ELF binary.
 *
 * @vindex JIT_READELF_WRONG_ARCH
 * @item JIT_READELF_WRONG_ARCH
 * The file is an ELF binary, but it does not pertain to the architecture
 * of this machine.
 *
 * @vindex JIT_READELF_BAD_FORMAT
 * @item JIT_READELF_BAD_FORMAT
 * The file is an ELF binary, but the format is corrupted in some fashion.
 *
 * @vindex JIT_READELF_MEMORY
 * @item JIT_READELF_MEMORY
 * There is insufficient memory to open the ELF binary.
 * @end table
 *
 * The following flags may be supplied to alter the manner in which
 * the ELF binary is loaded:
 *
 * @table @code
 * @vindex JIT_READELF_FLAG_FORCE
 * @item JIT_READELF_FLAG_FORCE
 * Force @code{jit_readelf_open} to open the ELF binary, even if
 * the architecture does not match this machine.  Useful for debugging.
 *
 * @vindex JIT_READELF_FLAG_DEBUG
 * @item JIT_READELF_FLAG_DEBUG
 * Print additional debug information to stdout.
 * @end table
 * @end deftypefun
@*/
int jit_readelf_open(jit_readelf_t *_readelf, const char *filename, int flags)
{
	int fd;
	Elf_Ehdr ehdr;
	Elf_Phdr *phdr;
	Elf_Shdr *shdr;
	jit_elf_info_t elf_info;
	jit_readelf_t readelf;
	unsigned int phdr_size;
	unsigned int shdr_size;
	unsigned int index;
	void *address;
	union
	{
		jit_ushort value;
		unsigned char bytes[2];

	} un;

	/* Get the machine and ABI values that we expect in the header */
	_jit_gen_get_elf_info(&elf_info);

	/* Open the file and read the ELF magic number information */
	if((fd = sys_open(filename, O_RDONLY | O_BINARY, 0)) < 0)
	{
		return JIT_READELF_CANNOT_OPEN;
	}
	if(sys_read(fd, ehdr.e_ident, EI_NIDENT) != EI_NIDENT)
	{
		sys_close(fd);
		return JIT_READELF_NOT_ELF;
	}

	/* Determine if the magic number matches what we expect to see */
	if(ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
	   ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3)
	{
		sys_close(fd);
		return JIT_READELF_NOT_ELF;
	}
#ifdef JIT_NATIVE_INT32
	if(ehdr.e_ident[EI_CLASS] != ELFCLASS32)
	{
		sys_close(fd);
		return JIT_READELF_WRONG_ARCH;
	}
#else
	if(ehdr.e_ident[EI_CLASS] != ELFCLASS64)
	{
		sys_close(fd);
		return JIT_READELF_WRONG_ARCH;
	}
#endif
	un.value = 0x0102;
	if(un.bytes[0] == 0x01)
	{
		/* Looking for a big-endian binary */
		if(ehdr.e_ident[EI_DATA] != ELFDATA2MSB)
		{
			sys_close(fd);
			return JIT_READELF_WRONG_ARCH;
		}
	}
	else
	{
		/* Looking for a little-endian binary */
		if(ehdr.e_ident[EI_DATA] != ELFDATA2LSB)
		{
			sys_close(fd);
			return JIT_READELF_WRONG_ARCH;
		}
	}
	if(ehdr.e_ident[EI_VERSION] != EV_CURRENT)
	{
		sys_close(fd);
		return JIT_READELF_BAD_FORMAT;
	}

	/* Read the rest of the ELF header and validate it */
	if(sys_read(fd, &(ehdr.e_type), sizeof(Elf_Ehdr) - EI_NIDENT)
			!= (sizeof(Elf_Ehdr) - EI_NIDENT))
	{
		sys_close(fd);
		return JIT_READELF_BAD_FORMAT;
	}
	if(ehdr.e_type != ET_DYN)
	{
		/* We can only load files that are marked as dynamic shared objects */
		sys_close(fd);
		return JIT_READELF_WRONG_ARCH;
	}
	if((flags & JIT_READELF_FLAG_FORCE) == 0)
	{
		if(ehdr.e_machine != elf_info.machine ||
		   ehdr.e_ident[EI_OSABI] != elf_info.abi ||
		   ehdr.e_ident[EI_ABIVERSION] != elf_info.abi_version)
		{
			/* The ELF binary does not pertain to this machine or ABI type */
			sys_close(fd);
			return JIT_READELF_WRONG_ARCH;
		}
	}
	if(ehdr.e_version != EV_CURRENT)
	{
		sys_close(fd);
		return JIT_READELF_BAD_FORMAT;
	}
	if(ehdr.e_ehsize < sizeof(ehdr))
	{
		sys_close(fd);
		return JIT_READELF_BAD_FORMAT;
	}

	/* Allocate space for the ELF reader object */
	if((readelf = jit_cnew(struct jit_readelf)) == 0)
	{
		sys_close(fd);
		return JIT_READELF_MEMORY;
	}
	readelf->ehdr = ehdr;
	phdr_size = ((unsigned int)(ehdr.e_phnum)) *
				((unsigned int)(ehdr.e_phentsize));
	shdr_size = ((unsigned int)(ehdr.e_shnum)) *
				((unsigned int)(ehdr.e_shentsize));
	if(phdr_size > 0)
	{
		readelf->phdrs = (unsigned char *)jit_malloc(phdr_size);
		if(!(readelf->phdrs))
		{
			jit_free(readelf);
			sys_close(fd);
			return JIT_READELF_MEMORY;
		}
	}
	if(shdr_size > 0)
	{
		readelf->shdrs = (unsigned char *)jit_malloc(shdr_size);
		if(!(readelf->shdrs))
		{
			jit_free(readelf->phdrs);
			jit_free(readelf);
			sys_close(fd);
			return JIT_READELF_MEMORY;
		}
	}

	/* Seek to the program and section header tables and read them */
	if(phdr_size > 0)
	{
		if(lseek(fd, (off_t)(ehdr.e_phoff), 0) != (off_t)(ehdr.e_phoff) ||
		   read(fd, readelf->phdrs, phdr_size) != (int)phdr_size)
		{
			jit_free(readelf->shdrs);
			jit_free(readelf->phdrs);
			jit_free(readelf);
			sys_close(fd);
			return JIT_READELF_BAD_FORMAT;
		}
	}
	if(shdr_size > 0)
	{
		if(lseek(fd, (off_t)(ehdr.e_shoff), 0) != (off_t)(ehdr.e_shoff) ||
		   read(fd, readelf->shdrs, shdr_size) != (int)shdr_size)
		{
			jit_free(readelf->shdrs);
			jit_free(readelf->phdrs);
			jit_free(readelf);
			sys_close(fd);
			return JIT_READELF_BAD_FORMAT;
		}
	}

	/* Load the program segments */
	if(!map_program(readelf, fd))
	{
		jit_readelf_close(readelf);
		sys_close(fd);
		return JIT_READELF_MEMORY;
	}

	/* Load the auxillary sections */
	if(shdr_size > 0)
	{
		for(index = 0; index < ehdr.e_shnum; ++index)
		{
			shdr = get_shdr(readelf, index);
			if(!shdr)
			{
				continue;
			}
			if((shdr->sh_flags & SHF_ALLOC) != 0 || shdr->sh_addr != 0)
			{
				/* This may be mapped inside one of the program segments.
				   If so, we don't want to load a second copy of it */
				address = jit_readelf_map_vaddr(readelf, shdr->sh_addr);
				if(address)
				{
					continue;
				}
			}
			if(shdr->sh_size == 0)
			{
				/* Ignore zero-sized segments */
				continue;
			}
			address = map_section
				(fd, shdr->sh_offset, shdr->sh_size, shdr->sh_size,
				 ((shdr->sh_flags & SHF_WRITE) != 0 ? (PF_W | PF_R) : PF_R));
			if(!address)
			{
				jit_readelf_close(readelf);
				sys_close(fd);
				return JIT_READELF_MEMORY;
			}
			shdr->sh_offset = (Elf_Off)(jit_nuint)address;
			shdr->sh_flags |= JIT_ELF_IS_MALLOCED;
		}
	}

	/* Close the file descriptor because we don't need it any more */
	sys_close(fd);

	/* Find the regular string table */
	shdr = get_shdr(readelf, ehdr.e_shstrndx);
	if(shdr)
	{
		if((shdr->sh_flags & JIT_ELF_IS_MALLOCED) != 0)
		{
			readelf->regular_strings = (char *)(jit_nuint)(shdr->sh_offset);
		}
		else
		{
			readelf->regular_strings =
				(char *)jit_readelf_map_vaddr(readelf, shdr->sh_addr);
		}
		if(readelf->regular_strings)
		{
			readelf->regular_strings_size = (jit_nuint)(shdr->sh_size);
		}
	}

	/* Dump debug information about the program segments and sections */
	if((flags & JIT_READELF_FLAG_DEBUG) != 0)
	{
		printf("header: machine=%d, abi=%d, abi_version=%d\n",
			   (int)(ehdr.e_machine), (int)(ehdr.e_ident[EI_OSABI]),
			   (int)(ehdr.e_ident[EI_ABIVERSION]));
		for(index = 0; index < ehdr.e_phnum; ++index)
		{
			phdr = get_phdr(readelf, index);
			if(phdr)
			{
				printf("program segment: type=%d, flags=0x%x, "
							"vaddr=0x%lx, file_size=%ld, memory_size=%ld\n",
				       (int)(phdr->p_type),
				       (int)(phdr->p_flags & ~JIT_ELF_IS_MALLOCED),
				       (long)(phdr->p_vaddr),
				       (long)(phdr->p_filesz),
				       (long)(phdr->p_memsz));
			}
		}
		for(index = 0; index < ehdr.e_shnum; ++index)
		{
			shdr = get_shdr(readelf, index);
			if(shdr)
			{
				printf("section %2d: name=\"%s\", type=%d, flags=0x%x, "
							"vaddr=0x%lx, size=%ld\n",
					   index,
				       get_string(readelf, shdr->sh_name),
				       (int)(shdr->sh_type),
				       (int)(shdr->sh_flags & ~JIT_ELF_IS_MALLOCED),
				           (long)(shdr->sh_addr),
				       (long)(shdr->sh_size));
			}
		}
	}

	/* Get the relocation function for this machine type */
	readelf->reloc_func = get_reloc((unsigned int)(ehdr.e_machine));

	/* Load useful values from the dynamic section that we want to cache */
	load_dynamic_section(readelf, flags);

	/* The ELF binary is loaded and ready to go */
	*_readelf = readelf;
	return JIT_READELF_OK;
}

/*@
 * @deftypefun void jit_readelf_close (jit_readelf_t @var{readelf})
 * Close an ELF reader, reclaiming all of the memory that was used.
 * @end deftypefun
@*/
void jit_readelf_close(jit_readelf_t readelf)
{
	unsigned int index;
	Elf_Shdr *shdr;
	if(!readelf)
	{
		return;
	}
#ifdef JIT_USE_MMAP_TO_LOAD
	if(readelf->free_with_munmap)
	{
		munmap(readelf->map_address, (size_t)(readelf->map_size));
	}
	else
#endif
	{
		_jit_free_exec(readelf->map_address, readelf->map_size);
	}
	for(index = 0; index < readelf->ehdr.e_shnum; ++index)
	{
		shdr = get_shdr(readelf, index);
		if(shdr && (shdr->sh_flags & JIT_ELF_IS_MALLOCED) != 0)
		{
			unmap_section
				((void *)(jit_nuint)(shdr->sh_offset),
				 shdr->sh_size, shdr->sh_size, shdr->sh_flags);
		}
	}
	jit_free(readelf->phdrs);
	jit_free(readelf->shdrs);
	jit_free(readelf);
}

/*@
 * @deftypefun {const char *} jit_readelf_get_name (jit_readelf_t @var{readelf})
 * Get the library name that is embedded inside an ELF binary.
 * ELF binaries can refer to each other using this name.
 * @end deftypefun
@*/
const char *jit_readelf_get_name(jit_readelf_t readelf)
{
	Elf_Addr value;
	if(dynamic_for_type(readelf, DT_SONAME, &value))
	{
		return get_dyn_string(readelf, value);
	}
	else
	{
		return 0;
	}
}

/*@
 * @deftypefun void *jit_readelf_get_symbol (jit_readelf_t @var{readelf}, const char *@var{name})
 * Look up the symbol called @var{name} in the ELF binary represented
 * by @var{readelf}.  Returns NULL if the symbol is not present.
 *
 * External references from this ELF binary to others are not resolved
 * until the ELF binary is loaded into a JIT context using
 * @code{jit_readelf_add_to_context} and @code{jit_readelf_resolve_all}.
 * You should not call functions within this ELF binary until after you
 * have fully resolved it.
 * @end deftypefun
@*/
void *jit_readelf_get_symbol(jit_readelf_t readelf, const char *name)
{
	unsigned long hash;
	unsigned long temp;
	unsigned int index;
	jit_nuint num_symbols;
	Elf_Sym *symbol;
	const char *symbol_name;

	/* Bail out if we have insufficient information to resolve the name */
	if(!readelf || !name || !(readelf->symbol_table))
	{
		return 0;
	}

	/* Hash the name to get the starting index in the symbol hash */
	hash = 0;
	index = 0;
	while(name[index] != 0)
	{
		hash = (hash << 4) + (unsigned long)(name[index] & 0xFF);
		temp = (hash & 0xF0000000);

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

		num_symbols > 0; --num_symbols)
	{
		symbol_name = get_dyn_string(readelf, symbol->st_name);
		if(symbol_name && !jit_strcmp(symbol_name, name))
		{
			/* Ignore symbols in section 0, as they are external */
			if(symbol->st_shndx)
			{
				return jit_readelf_map_vaddr
					(readelf, (jit_nuint)(symbol->st_value));
			}
		}
		++symbol;
	}
	return 0;
}

/*@
 * @deftypefun {void *} jit_readelf_get_section (jit_readelf_t @var{readelf}, const char *@var{name}, jit_nuint *@var{size})
 * Get the address and size of a particular section from an ELF binary.
 * Returns NULL if the section is not present in the ELF binary.
 *
 * The virtual machine may have stored auxillary information
 * in the section when the binary was first generated.  This function
 * allows the virtual machine to retrieve its auxillary information.
 *
 * Examples of such information may be version numbers, timestamps,
 * checksums, and other identifying information for the bytecode that
 * was previously compiled by the virtual machine.  The virtual machine
 * can use this to determine if the ELF binary is up to date and
 * relevant to its needs.
 *
 * It is recommended that virtual machines prefix their special sections
 * with a unique string (e.g. @code{.foovm}) to prevent clashes with
 * system-defined section names.  The prefix @code{.libjit} is reserved
 * for use by @code{libjit} itself.
 * @end deftypefun
@*/
void *jit_readelf_get_section
	(jit_readelf_t readelf, const char *name, jit_nuint *size)
{
	unsigned int index;
	Elf_Shdr *shdr;
	const char *temp_name;
	if(!readelf || !name)
	{
		return 0;
	}
	for(index = 0; index < readelf->ehdr.e_shnum; ++index)
	{
		shdr = get_shdr(readelf, index);
		if(shdr)
		{
			temp_name = get_string(readelf, shdr->sh_name);
			if(temp_name && !jit_strcmp(name, temp_name))
			{
				if(size)
				{
					*size = (jit_nuint)(shdr->sh_size);
				}
				if((shdr->sh_flags & JIT_ELF_IS_MALLOCED) != 0)
				{
					return (void *)(jit_nuint)(shdr->sh_offset);
				}
				else
				{
					return jit_readelf_map_vaddr
						(readelf, (jit_nuint)(shdr->sh_addr));
				}
			}
		}
	}
	return 0;
}

/*@
 * @deftypefun {void *} jit_readelf_get_section_by_type (jit_readelf_t @var{readelf}, jit_int @var{type}, jit_nuint *@var{size})
 * Get a particular section using its raw ELF section type (i.e. one of
 * the @code{SHT_*} constants in @code{jit-elf-defs.h}).  This is mostly
 * for internal use, but some virtual machines may find it useful for
 * debugging purposes.
 * @end deftypefun
@*/
void *jit_readelf_get_section_by_type
	(jit_readelf_t readelf, jit_int type, jit_nuint *size)
{
	unsigned int index;
	Elf_Shdr *shdr;
	if(!readelf)
	{
		return 0;
	}
	for(index = 0; index < readelf->ehdr.e_shnum; ++index)
	{
		shdr = get_shdr(readelf, index);
		if(shdr && type == (jit_int)(shdr->sh_type))
		{
			if(size)
			{
				*size = (jit_nuint)(shdr->sh_size);
			}
			if((shdr->sh_flags & JIT_ELF_IS_MALLOCED) != 0)
			{
				return (void *)(jit_nuint)(shdr->sh_offset);
			}
			else
			{
				return jit_readelf_map_vaddr
					(readelf, (jit_nuint)(shdr->sh_addr));
			}
		}
	}
	return 0;
}

/*@
 * @deftypefun {void *} jit_readelf_map_vaddr (jit_readelf_t @var{readelf}, jit_nuint @var{vaddr})
 * Map a virtual address to an actual address in a loaded ELF binary.
 * Returns NULL if @var{vaddr} could not be mapped.
 * @end deftypefun
@*/
void *jit_readelf_map_vaddr(jit_readelf_t readelf, jit_nuint vaddr)
{
	unsigned int index;
	Elf_Phdr *phdr;
	if(!readelf)
	{
		return 0;
	}
	for(index = 0; index < readelf->ehdr.e_phnum; ++index)
	{
		phdr = get_phdr(readelf, index);
		if(phdr && vaddr >= phdr->p_vaddr &&
		   vaddr < (phdr->p_vaddr + phdr->p_memsz))
		{
			return (void *)(((unsigned char *)(readelf->map_address)) + vaddr);
		}
	}
	return 0;
}

/*@
 * @deftypefun {unsigned int} jit_readelf_num_needed (jit_readelf_t @var{readelf})
 * Get the number of dependent libraries that are needed by this
 * ELF binary.  The virtual machine will normally need to arrange
 * to load these libraries with @code{jit_readelf_open} as well,
 * so that all of the necessary symbols can be resolved.
 * @end deftypefun
@*/
unsigned int jit_readelf_num_needed(jit_readelf_t readelf)
{
	jit_dynamic_iter_t iter;
	unsigned int count = 0;
	jit_int type;
	Elf_Addr value;
	dynamic_iter_init(&iter, readelf);
	while(dynamic_iter_next(&iter, &type, &value))
	{
		if(type == DT_NEEDED)
		{
			++count;
		}



( run in 0.635 second using v1.01-cache-2.11-cpan-796a6f069b2 )