Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-elf-read.c view on Meta::CPAN
{
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
(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 */
libjit/jit/jit-elf-read.c view on Meta::CPAN
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;
}
libjit/jit/jit-elf-read.c view on Meta::CPAN
* 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;
}
( run in 0.780 second using v1.01-cache-2.11-cpan-02777c243ea )