📄 cofflwlv.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: COFF symbol table and relocations processing.
*
****************************************************************************/
#include "cofflwlv.h"
#include "orlhash.h"
#include "walloca.h"
#ifdef _BSD_SOURCE
#define stricmp strcasecmp
#endif
orl_return CoffCreateSymbolHandles( coff_file_handle file_hnd )
{
int loop;
int prev;
int len;
uint_16 type; // type of CoffSymEnt
coff_symbol_handle current;
coff_sym_section * aux;
coff_sym_weak * weak;
coff_sec_handle sechdl;
if( file_hnd->num_symbols == 0 ){
file_hnd->symbol_handles = NULL;
return( ORL_OKAY );
}
file_hnd->symbol_handles = (coff_symbol_handle) _ClientAlloc( file_hnd, sizeof( coff_symbol_handle_struct ) * file_hnd->num_symbols );
if( !(file_hnd->symbol_handles) ) return( ORL_OUT_OF_MEMORY );
prev = 0;
for( loop = 0; loop < file_hnd->num_symbols; loop++ ) {
current = &(file_hnd->symbol_handles[loop]);
current->file_format = ORL_COFF;
current->coff_file_hnd = file_hnd;
current->symbol = (coff_symbol *) &(file_hnd->symbol_table->contents[sizeof( coff_symbol ) * loop]);
if( current->symbol->name.non_name.zeros == 0 ) {
current->name = file_hnd->string_table->contents + current->symbol->name.non_name.offset - sizeof( coff_sec_size );
current->name_alloced = COFF_FALSE;
} else {
len = strlen( current->symbol->name.name_string );
if( strlen( current->symbol->name.name_string ) >= COFF_SYM_NAME_LEN ) {
current->name = _ClientAlloc( file_hnd, COFF_SYM_NAME_LEN + 1 );
strncpy( current->name, current->symbol->name.name_string, COFF_SYM_NAME_LEN );
current->name[COFF_SYM_NAME_LEN] = '\0';
current->name_alloced = COFF_TRUE;
} else {
current->name = current->symbol->name.name_string;
current->name_alloced = COFF_FALSE;
}
}
if( memcmp( current->name, ".bf", 4 ) == 0 ) {
if( current->symbol->num_aux >= 1 ) {
file_hnd->symbol_handles[prev].has_bf = COFF_TRUE;
}
}
sechdl = NULL;
current->type = 0;
switch( current->symbol->sec_num ) {
case IMAGE_SYM_DEBUG:
current->type |= ORL_SYM_TYPE_DEBUG;
current->binding = ORL_SYM_BINDING_NONE;
break;
case IMAGE_SYM_ABSOLUTE:
current->type |= ORL_SYM_TYPE_ABSOLUTE;
current->binding = ORL_SYM_BINDING_NONE; // ?
break;
case IMAGE_SYM_UNDEFINED:
if( current->symbol->value == 0) {
current->type |= ORL_SYM_TYPE_UNDEFINED;
} else {
current->type |= ORL_SYM_TYPE_COMMON;
}
break;
default:
current->type |= ORL_SYM_TYPE_DEFINED;
sechdl = file_hnd->orig_sec_hnd[current->symbol->sec_num - 1];
if( sechdl->flags & ORL_SEC_FLAG_COMDAT ) {
current->type |= ORL_SYM_CDAT_MASK;
}
break;
}
switch( current->symbol->storage_class ) {
case IMAGE_SYM_CLASS_EXTERNAL:
case IMAGE_SYM_CLASS_LABEL:
case IMAGE_SYM_CLASS_UNDEFINED_LABEL:
case IMAGE_SYM_CLASS_WEAK_EXTERNAL:
if( current->symbol->storage_class
== IMAGE_SYM_CLASS_LABEL ) {
current->binding = ORL_SYM_BINDING_LOCAL;
} else if( (current->symbol->storage_class
== IMAGE_SYM_CLASS_EXTERNAL
|| current->symbol->storage_class
== IMAGE_SYM_CLASS_WEAK_EXTERNAL)
&& current->symbol->sec_num == IMAGE_SYM_UNDEFINED
&& current->symbol->value == 0
&& current->symbol->num_aux == 1 ) {
weak = (coff_sym_weak *) (current->symbol + 1);
switch( weak->characteristics ) {
case IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY:
current->binding = ORL_SYM_BINDING_WEAK;
break;
case IMAGE_WEAK_EXTERN_SEARCH_LIBRARY:
current->binding = ORL_SYM_BINDING_LAZY;
break;
case IMAGE_WEAK_EXTERN_SEARCH_ALIAS:
current->binding = ORL_SYM_BINDING_ALIAS;
break;
}
} else {
current->binding = ORL_SYM_BINDING_GLOBAL;
}
type = _CoffComplexType( current->symbol->type );
if( type & IMAGE_SYM_DTYPE_FUNCTION ) {
current->type |= ORL_SYM_TYPE_FUNCTION;
} else {
current->type |= ORL_SYM_TYPE_OBJECT;
}
break;
case IMAGE_SYM_CLASS_STATIC:
current->binding = ORL_SYM_BINDING_LOCAL;
if( current->symbol->num_aux == 0 ) {
if( sechdl != NULL
&& strcmp( sechdl->name, current->name ) == 0 ) {
current->type |= ORL_SYM_TYPE_SECTION;
} else {
type = _CoffComplexType( current->symbol->type );
if( type & IMAGE_SYM_DTYPE_FUNCTION ) {
current->type |= ORL_SYM_TYPE_FUNCTION;
} else {
current->type |= ORL_SYM_TYPE_OBJECT;
}
}
} else if( current->symbol->num_aux == 1
&& current->type & ORL_SYM_CDAT_MASK ) {
current->type |= ORL_SYM_TYPE_SECTION;
aux = (coff_sym_section *)(current->symbol + 1);
current->type &= ~ORL_SYM_CDAT_MASK;
current->type |= (aux->selection << ORL_SYM_CDAT_SHIFT)
& ORL_SYM_CDAT_MASK;
} else {
type = _CoffComplexType( current->symbol->type );
if( type & IMAGE_SYM_DTYPE_FUNCTION ) {
current->type |= ORL_SYM_TYPE_FUNCTION;
}
}
break;
case IMAGE_SYM_CLASS_FUNCTION:
// The .bf, .lf and .ef symbols are not regular symbols
// and their values in particular must not be interpreted
// as offsets/addresses.
if( !memcmp( current->name, ".bf", 4 )
|| !memcmp( current->name, ".lf", 4 )
|| !memcmp( current->name, ".ef", 4 ) )
current->binding = ORL_SYM_BINDING_NONE;
else
current->binding = ORL_SYM_BINDING_LOCAL;
current->type |= ORL_SYM_TYPE_FUNC_INFO;
break;
case IMAGE_SYM_CLASS_FILE:
current->binding = ORL_SYM_BINDING_LOCAL;
current->type |= ORL_SYM_TYPE_FILE;
break;
}
prev = loop;
loop += current->symbol->num_aux;
}
return( ORL_OKAY );
}
orl_return CoffBuildSecNameHashTable( coff_file_handle coff_file_hnd )
{
int loop;
orl_return error;
coff_file_hnd->sec_name_hash_table = ORLHashTableCreate( coff_file_hnd->coff_hnd->funcs, SEC_NAME_HASH_TABLE_SIZE, ORL_HASH_STRING, (orl_hash_comparison_func) stricmp );
if( !(coff_file_hnd->sec_name_hash_table) ) {
return( ORL_OUT_OF_MEMORY );
}
for( loop = 0; loop < coff_file_hnd->num_sections; loop++ ) {
error = ORLHashTableInsert( coff_file_hnd->sec_name_hash_table, (orl_hash_value) coff_file_hnd->coff_sec_hnd[loop]->name, coff_file_hnd->coff_sec_hnd[loop] );
if( error != ORL_OKAY ) return( error );
}
return( ORL_OKAY );
}
orl_reloc_type CoffConvertRelocType( coff_file_handle coff_file_hnd, coff_reloc_type coff_type ) {
if( coff_file_hnd->machine_type == ORL_MACHINE_TYPE_ALPHA ) {
switch( coff_type ) {
case IMAGE_REL_ALPHA_ABSOLUTE:
return( ORL_RELOC_TYPE_ABSOLUTE );
case IMAGE_REL_ALPHA_REFLONG:
case IMAGE_REL_ALPHA_REFQUAD:
return( ORL_RELOC_TYPE_WORD_32 );
case IMAGE_REL_ALPHA_BRADDR:
return( ORL_RELOC_TYPE_REL_21_SH );
case IMAGE_REL_ALPHA_REFHI:
case IMAGE_REL_ALPHA_INLINE_REFLONG:
return( ORL_RELOC_TYPE_HALF_HI );
case IMAGE_REL_ALPHA_REFLO:
return( ORL_RELOC_TYPE_HALF_LO );
case IMAGE_REL_ALPHA_PAIR:
return( ORL_RELOC_TYPE_PAIR );
case IMAGE_REL_ALPHA_SECTION:
return( ORL_RELOC_TYPE_SEGMENT );
case IMAGE_REL_ALPHA_SECREL:
return( ORL_RELOC_TYPE_SEC_REL );
case IMAGE_REL_ALPHA_REFLONGNB:
return( ORL_RELOC_TYPE_WORD_32_NB );
default:
return( ORL_RELOC_TYPE_NONE );
}
} else if( coff_file_hnd->machine_type == ORL_MACHINE_TYPE_I386 ) {
switch( coff_type ) {
case IMAGE_REL_I386_ABSOLUTE:
return( ORL_RELOC_TYPE_ABSOLUTE );
case IMAGE_REL_I386_DIR16:
return( ORL_RELOC_TYPE_WORD_16 );
case IMAGE_REL_I386_REL16:
return( ORL_RELOC_TYPE_REL_16 );
case IMAGE_REL_I386_DIR32:
return( ORL_RELOC_TYPE_WORD_32 );
case IMAGE_REL_I386_DIR32NB:
return( ORL_RELOC_TYPE_WORD_32_NB );
case IMAGE_REL_I386_REL32:
return( ORL_RELOC_TYPE_JUMP );
case IMAGE_REL_I386_SECTION:
return( ORL_RELOC_TYPE_SECTION );
case IMAGE_REL_I386_SECREL:
return( ORL_RELOC_TYPE_SEC_REL );
default:
return( ORL_RELOC_TYPE_NONE );
}
} else if( coff_file_hnd->machine_type == ORL_MACHINE_TYPE_AMD64 ) {
switch( coff_type ) {
case IMAGE_REL_AMD64_REL32: // 32-Bit PC-relative offset
return( ORL_RELOC_TYPE_REL_32 );
case IMAGE_REL_AMD64_ADDR32:
return( ORL_RELOC_TYPE_WORD_32 );
case IMAGE_REL_AMD64_REL32_1:
return( ORL_RELOC_TYPE_REL_32_ADJ1 );
case IMAGE_REL_AMD64_REL32_2:
return( ORL_RELOC_TYPE_REL_32_ADJ2 );
case IMAGE_REL_AMD64_REL32_3:
return( ORL_RELOC_TYPE_REL_32_ADJ3 );
case IMAGE_REL_AMD64_REL32_4:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -