Alien-LibJIT

 view release on metacpan or  search on metacpan

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


	/* Look for "before" symbols that are registered with the context */
	for(index = 0; index < context->num_registered_symbols; ++index)
	{
		if(!jit_strcmp(symbol_name, context->registered_symbols[index]->name) &&
		   !(context->registered_symbols[index]->after))
		{
			return context->registered_symbols[index]->value;
		}
	}

	/* Search all loaded ELF libraries for the name */
	library = context->elf_binaries;
	while(library != 0)
	{
		value = jit_readelf_get_symbol(library, symbol_name);
		if(value)
		{
			return value;
		}
		library = library->next;
	}

	/* Look for libjit internal symbols (i.e. intrinsics) */
	left = 0;
	right = _jit_num_internal_symbols - 1;
	while(left <= right)
	{
		index = (left + right) / 2;
		cmp = jit_strcmp(symbol_name, _jit_internal_symbols[index].name);
		if(cmp == 0)
		{
			return _jit_internal_symbols[index].value;
		}
		else if(cmp < 0)
		{
			right = index - 1;
		}
		else
		{
			left = index + 1;
		}
	}

	/* Look for "after" symbols that are registered with the context */
	for(index = 0; index < context->num_registered_symbols; ++index)
	{
		if(!jit_strcmp(symbol_name, context->registered_symbols[index]->name) &&
		   context->registered_symbols[index]->after)
		{
			return context->registered_symbols[index]->value;
		}
	}

	/* If we get here, then we could not resolve the symbol */
	printf("%s: could not resolve `%s'\n", name, symbol_name);
	return 0;
}

/*
 * Perform a DT_REL style relocation on an ELF binary.
 */
static int perform_rel
	(jit_context_t context, jit_readelf_t readelf, 
	 int print_failures, const char *name, Elf_Rel *reloc)
{
	void *address;
	void *value;

	/* Get the address to apply the relocation at */
	address = jit_readelf_map_vaddr(readelf, (jit_nuint)(reloc->r_offset));
	if(!address)
	{
		if(print_failures)
		{
			printf("%s: cannot map virtual address 0x%lx\n",
				   name, (long)(reloc->r_offset));
		}
		return 0;
	}

	/* Resolve the designated symbol to its actual value */
	value = resolve_symbol
		(context, readelf, print_failures, name,
		 (jit_nuint)ELF_R_SYM(reloc->r_info));
	if(!value)
	{
		return 0;
	}

	/* Perform the relocation */
	if(!(*(readelf->reloc_func))
		(readelf, address, (int)(ELF_R_TYPE(reloc->r_info)),
		 (jit_nuint)value, 0, 0))
	{
		if(print_failures)
		{
			printf("%s: relocation type %d was not recognized\n",
				   name, (int)(ELF_R_TYPE(reloc->r_info)));
		}
		return 0;
	}
	return 1;
}

/*
 * Perform a DT_RELA style relocation on an ELF binary.
 */
static int perform_rela
	(jit_context_t context, jit_readelf_t readelf,
	 int print_failures, const char *name, Elf_Rela *reloc)
{
	void *address;
	void *value;

	/* Get the address to apply the relocation at */
	address = jit_readelf_map_vaddr(readelf, (jit_nuint)(reloc->r_offset));
	if(!address)
	{
		if(print_failures)
		{
			printf("%s: cannot map virtual address 0x%lx\n",
				   name, (long)(reloc->r_offset));
		}
		return 0;
	}

	/* Resolve the designated symbol to its actual value */
	value = resolve_symbol
		(context, readelf, print_failures, name,
		 (jit_nuint)ELF_R_SYM(reloc->r_info));
	if(!value)
	{
		return 0;
	}

	/* Perform the relocation */
	if(!(*(readelf->reloc_func))
		(readelf, address, (int)(ELF_R_TYPE(reloc->r_info)),
		 (jit_nuint)value, 1, (jit_nuint)(reloc->r_addend)))
	{
		if(print_failures)
		{
			printf("%s: relocation type %d was not recognized\n",
				   name, (int)(ELF_R_TYPE(reloc->r_info)));
		}
		return 0;
	}
	return 1;
}

/*
 * Perform relocations on an ELF binary.  Returns zero on failure.
 */
static int perform_relocations
	(jit_context_t context, jit_readelf_t readelf, int print_failures)
{
	Elf_Addr address;
	Elf_Addr table_size;
	Elf_Addr entry_size;
	unsigned char *table;
	const char *name;
	int ok = 1;

	/* Get the library name, for printing diagnostic messages */
	name = jit_readelf_get_name(readelf);
	if(!name)
	{
		name = "unknown-elf-binary";
	}

	/* Bail out if we don't know how to perform relocations */
	if(!(readelf->reloc_func))
	{
		if(print_failures)
		{
			printf("%s: do not know how to perform relocations\n", name);
		}
		return 0;
	}

	/* Apply the "Rel" relocations in the dynamic section */
	if(dynamic_for_type(readelf, DT_REL, &address) &&
	   dynamic_for_type(readelf, DT_RELSZ, &table_size) &&
	   dynamic_for_type(readelf, DT_RELENT, &entry_size) && entry_size)
	{
		table = (unsigned char *)jit_readelf_map_vaddr
			(readelf, (jit_nuint)address);
		while(table && table_size >= entry_size)
		{
			if(!perform_rel(context, readelf, print_failures, name,
					        (Elf_Rel *)table))
			{
				ok = 0;
			}
			table += (jit_nuint)entry_size;
			table_size -= entry_size;
		}
	}

	/* Apply the "Rela" relocations in the dynamic section */
	if(dynamic_for_type(readelf, DT_RELA, &address) &&
	   dynamic_for_type(readelf, DT_RELASZ, &table_size) &&
	   dynamic_for_type(readelf, DT_RELAENT, &entry_size) && entry_size)
	{
		table = (unsigned char *)jit_readelf_map_vaddr
			(readelf, (jit_nuint)address);
		while(table && table_size >= entry_size)
		{
			if(!perform_rela(context, readelf, print_failures, name,
					         (Elf_Rela *)table))
			{
				ok = 0;
			}
			table += (jit_nuint)entry_size;
			table_size -= entry_size;
		}
	}

	/* Apply the "PLT" relocations in the dynamic section, which
	   may be either DT_REL or DT_RELA style relocations */
	if(dynamic_for_type(readelf, DT_JMPREL, &address) &&
	   dynamic_for_type(readelf, DT_PLTRELSZ, &table_size) &&
	   dynamic_for_type(readelf, DT_PLTREL, &entry_size))
	{
		if(entry_size == DT_REL)
		{
			if(dynamic_for_type(readelf, DT_RELENT, &entry_size) && entry_size)
			{
				table = (unsigned char *)jit_readelf_map_vaddr
					(readelf, (jit_nuint)address);
				while(table && table_size >= entry_size)
				{
					if(!perform_rel(context, readelf, print_failures, name,
							        (Elf_Rel *)table))
					{
						ok = 0;
					}
					table += (jit_nuint)entry_size;
					table_size -= entry_size;
				}
			}
		}
		else if(entry_size == DT_RELA)
		{
			if(dynamic_for_type(readelf, DT_RELAENT, &entry_size) && entry_size)
			{
				table = (unsigned char *)jit_readelf_map_vaddr
					(readelf, (jit_nuint)address);
				while(table && table_size >= entry_size)
				{
					if(!perform_rela(context, readelf, print_failures, name,
							         (Elf_Rela *)table))
					{
						ok = 0;
					}
					table += (jit_nuint)entry_size;
					table_size -= entry_size;
				}
			}
		}
	}

	/* Return to the caller */
	return ok;
}

/*@
 * @deftypefun int jit_readelf_resolve_all (jit_context_t @var{context}, int @var{print_failures})
 * Resolve all of the cross-library symbol references in ELF binaries
 * that have been added to @var{context} but which were not resolved
 * in the previous call to this function.  If @var{print_failures}
 * is non-zero, then diagnostic messages will be written to stdout
 * for any symbol resolutions that fail.
 *
 * Returns zero on failure, or non-zero if all symbols were successfully
 * resolved.  If there are no ELF binaries awaiting resolution, then
 * this function will return a non-zero result.
 * @end deftypefun
@*/
int jit_readelf_resolve_all(jit_context_t context, int print_failures)



( run in 0.323 second using v1.01-cache-2.11-cpan-e93a5daba3e )