📄 elfload.c
字号:
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Top level ELF loading code, parses ELF headers.
*
****************************************************************************/
#include "elfload.h"
// fixme: finish making ELF SPECIFIC (see next fixme)
static void fix_ehdr_byte_order( elf_file_handle elf_file_hnd, Elf32_Ehdr *e_hdr )
{
// note that one of the branches will always get compiled out,
// depending on host endianness
if( elf_file_hnd->flags & ORL_FILE_FLAG_BIG_ENDIAN ) {
CONV_BE_16( e_hdr->e_type );
CONV_BE_16( e_hdr->e_machine );
CONV_BE_32( e_hdr->e_version );
CONV_BE_32( e_hdr->e_entry );
CONV_BE_32( e_hdr->e_phoff );
CONV_BE_32( e_hdr->e_shoff );
CONV_BE_32( e_hdr->e_flags );
CONV_BE_16( e_hdr->e_ehsize );
CONV_BE_16( e_hdr->e_phentsize );
CONV_BE_16( e_hdr->e_phnum );
CONV_BE_16( e_hdr->e_shentsize );
CONV_BE_16( e_hdr->e_shnum );
CONV_BE_16( e_hdr->e_shstrndx );
} else {
CONV_LE_16( e_hdr->e_type );
CONV_LE_16( e_hdr->e_machine );
CONV_LE_32( e_hdr->e_version );
CONV_LE_32( e_hdr->e_entry );
CONV_LE_32( e_hdr->e_phoff );
CONV_LE_32( e_hdr->e_shoff );
CONV_LE_32( e_hdr->e_flags );
CONV_LE_16( e_hdr->e_ehsize );
CONV_LE_16( e_hdr->e_phentsize );
CONV_LE_16( e_hdr->e_phnum );
CONV_LE_16( e_hdr->e_shentsize );
CONV_LE_16( e_hdr->e_shnum );
CONV_LE_16( e_hdr->e_shstrndx );
}
}
static void fix_shdr_byte_order( elf_file_handle elf_file_hnd, Elf32_Shdr *e_shdr )
{
// note that one of the branches will always get compiled out,
// depending on host endianness
if( elf_file_hnd->flags & ORL_FILE_FLAG_BIG_ENDIAN ) {
CONV_BE_32( e_shdr->sh_name );
CONV_BE_32( e_shdr->sh_type );
CONV_BE_32( e_shdr->sh_flags );
CONV_BE_32( e_shdr->sh_addr );
CONV_BE_32( e_shdr->sh_offset );
CONV_BE_32( e_shdr->sh_size );
CONV_BE_32( e_shdr->sh_link );
CONV_BE_32( e_shdr->sh_info );
CONV_BE_32( e_shdr->sh_addralign );
CONV_BE_32( e_shdr->sh_entsize );
} else {
CONV_LE_32( e_shdr->sh_name );
CONV_LE_32( e_shdr->sh_type );
CONV_LE_32( e_shdr->sh_flags );
CONV_LE_32( e_shdr->sh_addr );
CONV_LE_32( e_shdr->sh_offset );
CONV_LE_32( e_shdr->sh_size );
CONV_LE_32( e_shdr->sh_link );
CONV_LE_32( e_shdr->sh_info );
CONV_LE_32( e_shdr->sh_addralign );
CONV_LE_32( e_shdr->sh_entsize );
}
}
// This function needs to be run before anything else, because it determines
// how the rest of the data is to be interpreted
static void determine_file_class( elf_file_handle elf_file_hnd, Elf32_Ehdr *e_hdr )
{
elf_file_hnd->flags = 0;
switch( e_hdr->e_ident[EI_DATA] ) {
case ELFLITTLEENDIAN:
elf_file_hnd->flags |= ORL_FILE_FLAG_LITTLE_ENDIAN;
break;
case ELFBIGENDIAN:
elf_file_hnd->flags |= ORL_FILE_FLAG_BIG_ENDIAN;
break;
}
switch( e_hdr->e_ident[EI_CLASS] ) {
case ELFCLASS32:
elf_file_hnd->flags |= ORL_FILE_FLAG_32BIT_MACHINE;
break;
case ELFCLASS64:
elf_file_hnd->flags |= ORL_FILE_FLAG_64BIT_MACHINE;
break;
}
}
static void determine_file_specs( elf_file_handle elf_file_hnd, Elf32_Ehdr *e_hdr )
{
switch( e_hdr->e_machine ) {
case EM_M32:
elf_file_hnd->machine_type = ORL_MACHINE_TYPE_WE_2100;
break;
case EM_SPARC:
elf_file_hnd->machine_type = ORL_MACHINE_TYPE_SPARC;
break;
case EM_386:
elf_file_hnd->machine_type = ORL_MACHINE_TYPE_I386;
break;
case EM_68K:
elf_file_hnd->machine_type = ORL_MACHINE_TYPE_M68000;
break;
case EM_88K:
elf_file_hnd->machine_type = ORL_MACHINE_TYPE_M88000;
break;
case EM_860:
elf_file_hnd->machine_type = ORL_MACHINE_TYPE_I860;
break;
case EM_PPC:
elf_file_hnd->machine_type = ORL_MACHINE_TYPE_PPC601;
break;
case EM_MIPS:
elf_file_hnd->machine_type = ORL_MACHINE_TYPE_R3000;
break;
default:
elf_file_hnd->machine_type = ORL_MACHINE_TYPE_NONE;
}
switch( e_hdr->e_type ) {
case ET_REL:
elf_file_hnd->type = ORL_FILE_TYPE_OBJECT;
break;
case ET_EXEC:
elf_file_hnd->type = ORL_FILE_TYPE_EXECUTABLE;
break;
case ET_DYN:
elf_file_hnd->type = ORL_FILE_TYPE_SHARED_OBJECT;
break;
case ET_CORE:
elf_file_hnd->type = ORL_FILE_TYPE_CORE;
break;
default:
elf_file_hnd->type = ORL_FILE_TYPE_NONE;
break;
}
// fixme: add computer-specific (PPC) flags, if any!
}
static void determine_section_specs( elf_sec_handle elf_sec_hnd, Elf32_Shdr * s_hdr )
{
elf_sec_hnd->flags = ORL_SEC_FLAG_READ_PERMISSION;
switch( s_hdr->sh_type ) {
case SHT_PROGBITS:
elf_sec_hnd->type = ORL_SEC_TYPE_PROG_BITS;
elf_sec_hnd->flags |= ORL_SEC_FLAG_INITIALIZED_DATA;
break;
case SHT_SYMTAB:
elf_sec_hnd->type = ORL_SEC_TYPE_SYM_TABLE;
break;
case SHT_STRTAB:
elf_sec_hnd->type = ORL_SEC_TYPE_STR_TABLE;
break;
case SHT_RELA:
elf_sec_hnd->type = ORL_SEC_TYPE_RELOCS_EXPADD;
break;
case SHT_HASH:
elf_sec_hnd->type = ORL_SEC_TYPE_HASH;
break;
case SHT_DYNAMIC:
elf_sec_hnd->type = ORL_SEC_TYPE_DYNAMIC;
break;
case SHT_NOTE:
elf_sec_hnd->type = ORL_SEC_TYPE_NOTE;
break;
case SHT_NOBITS:
elf_sec_hnd->type = ORL_SEC_TYPE_NO_BITS;
elf_sec_hnd->flags |= ORL_SEC_FLAG_UNINITIALIZED_DATA;
break;
case SHT_REL:
elf_sec_hnd->type = ORL_SEC_TYPE_RELOCS;
break;
case SHT_DYNSYM:
elf_sec_hnd->type = ORL_SEC_TYPE_DYN_SYM_TABLE;
break;
case SHT_OS:
case SHT_OS_O:
elf_sec_hnd->type = ORL_SEC_TYPE_PROG_BITS;
break;
case SHT_IMPORTS:
case SHT_IMPORTS_O:
elf_sec_hnd->type = ORL_SEC_TYPE_IMPORT;
break;
case SHT_EXPORTS:
case SHT_EXPORTS_O:
elf_sec_hnd->type = ORL_SEC_TYPE_EXPORT;
break;
case SHT_RES:
case SHT_RES_O:
elf_sec_hnd->type = ORL_SEC_TYPE_PROG_BITS;
break;
default:
elf_sec_hnd->type = ORL_SEC_TYPE_NONE;
break;
}
if( s_hdr->sh_flags & SHF_WRITE ) {
elf_sec_hnd->flags |= ORL_SEC_FLAG_WRITE_PERMISSION;
}
if( !(s_hdr->sh_flags & SHF_ALLOC) ) {
elf_sec_hnd->flags |= ORL_SEC_FLAG_REMOVE;
}
if( s_hdr->sh_flags & SHF_EXECINSTR ) {
// set execute permission also?
elf_sec_hnd->flags |= ORL_SEC_FLAG_EXEC;
}
}
static void free_elf_sec_handles( elf_file_handle elf_file_hnd, int num_alloced )
{
int loop;
if( elf_file_hnd->elf_sec_hnd != NULL ) {
for( loop = 0; loop < num_alloced; loop++ ) {
_ClientFree( elf_file_hnd, elf_file_hnd->elf_sec_hnd[loop] );
}
_ClientFree( elf_file_hnd, elf_file_hnd->elf_sec_hnd );
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -