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 )