owcoff.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 820 行 · 第 1/2 页
C
820 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "owlpriv.h"
#include "owreloc.h"
#include <time.h>
#include <string.h>
#define FIRST_USER_SECTION 0
// must correspond to owl_cpu enums in owl.h - first entry is for POWER PC
static uint_16 cpuTypes[] = {
IMAGE_FILE_MACHINE_POWERPC,
IMAGE_FILE_MACHINE_ALPHA,
IMAGE_FILE_MACHINE_R4000,
IMAGE_FILE_MACHINE_I386};
#define _OWLIndexToCOFFIndex( x ) ( (x) + FIRST_USER_SECTION )
#define _OWLStringIndexToCOFFStringIndex( x ) ( (x) + 4 )
#define _FuncHasDebugInfo( y ) ( (y)->x.func != NULL )
static unsigned numFuncAuxSymbols( owl_func_info *info ){
//*******************************************************
owl_func_file *curr;
unsigned num_aux_syms;
unsigned file_aux_syms;
num_aux_syms = 0;
curr = info->head;
while( curr != NULL ){
num_aux_syms += 2; //.file .lf
file_aux_syms = strlen( curr->name ) + sizeof( coff_symbol ) - 1;
file_aux_syms /= sizeof( coff_symbol );
num_aux_syms += file_aux_syms;
curr = curr->next;
}
return( num_aux_syms );
}
static unsigned numAuxSymbols( owl_symbol_handle sym) {
//*****************************************************
unsigned num_aux_syms;
num_aux_syms = 0;
switch( sym->type ) {
case OWL_TYPE_SECTION:
num_aux_syms = 1;
break;
case OWL_TYPE_FILE:
num_aux_syms = strlen( OWLStringText( sym->name ) ) + sizeof( coff_symbol ) - 1;
num_aux_syms /= sizeof( coff_symbol );
break;
case OWL_TYPE_FUNCTION:
if( sym->linkage != OWL_SYM_UNDEFINED ) {
owl_func_info *info;
info = sym->x.func;
if( info != NULL ) {
// for .bf+aux, .lf .ef+aux
num_aux_syms = 6;
num_aux_syms += numFuncAuxSymbols( info );// .file + *aux + .lf
}
}
break;
case OWL_TYPE_OBJECT:
if( sym->linkage == OWL_SYM_WEAK ){
num_aux_syms = 1;
}
break;
}
return( num_aux_syms );
}
static int symComdat( owl_symbol_handle sym ) {
//*********************************************
if( sym->section != NULL ) {
if( sym->section->comdat_sym == sym ) {
return( TRUE );
}
}
return( FALSE );
}
static owl_symbol_index symRelocRefIndex( owl_symbol_handle sym ) {
//*****************************************************************
if( symComdat( sym ) ) {
return( sym->comdat );
}
return( sym->index );
}
static void calcNumSymbols( owl_file_handle file ) {
//**************************************************
unsigned num_syms;
owl_symbol_handle sym;
num_syms = 0;
for( sym = file->symbol_table->head; sym != NULL; sym = sym->next ) {
if( sym->flags & OWL_SYM_DEAD ) continue;
sym->index = num_syms;
num_syms += numAuxSymbols( sym ) + 1;
if( symComdat( sym ) ) {
sym->comdat = num_syms;
num_syms += 1;
}
}
file->num_symbols = num_syms;
}
static void calcLineNumSymbolIndices( owl_file_handle file ) {
//************************************************************
owl_symbol_handle sym;
for( sym = file->symbol_table->head; sym != NULL; sym = sym->next ) {
if( sym->flags & OWL_SYM_DEAD ) continue;
if( sym->type != OWL_TYPE_FUNCTION ) continue;
if( _FuncHasDebugInfo( sym ) ) {
// Symbol has some sort of debugging info
// - patch up index in first linenum record
assert( sym->section != NULL );
assert( sym->section->linenum_buffer != NULL );
OWLBufferSeek( sym->section->linenum_buffer, sym->x.func->linenum_offset );
OWLBufferWrite( sym->section->linenum_buffer, (const char *)&sym->index, sizeof( sym->index ) );
}
}
}
static unsigned numSymbols( owl_file_handle file ) {
//**************************************************
return( file->num_symbols );
}
static unsigned numSections( owl_file_handle file ) {
//***************************************************
return( _OWLIndexToCOFFIndex( file->next_index ) );
}
static unsigned numRelocs( owl_section_handle section ) {
//*******************************************************
return( section->num_relocs );
}
static unsigned numLineNums( owl_section_handle section ) {
//*********************************************************
return( section->num_linenums );
}
static coff_offset sectionFileSize( owl_section_handle section ) {
//****************************************************************
if( section->type & OWL_SEC_ATTR_BSS ) return( 0 );
assert( section->size == OWLBufferSize( section->buffer ) );
return( section->size );
}
static coff_offset sectionVirtSize( owl_section_handle section ) {
//****************************************************************
return( section->size );
}
static void emitFileHeader( owl_file_handle file ) {
//**************************************************
coff_file_header header;
header.cpu_type = cpuTypes[ file->info->cpu ];
header.num_sections = numSections( file );
header.time_stamp = time( NULL );
header.sym_table = file->x.coff.symbol_table_offset;
header.num_symbols = numSymbols( file );
header.opt_hdr_size = 0;
// header.flags = IMAGE_FILE_BYTES_REVERSED_LO | IMAGE_FILE_32BIT_MACHINE;
header.flags = 0;
if( file->type == OWL_FILE_EXE || file->type == OWL_FILE_DLL ) {
header.flags |= IMAGE_FILE_EXECUTABLE_IMAGE;
}
_ClientWrite( file, (const char *)&header, sizeof( header ) );
}
static void formatSectionName( owl_section_handle section, char *buffer ) {
//*************************************************************************
coff_offset name_offset;
char name[ 8 ];
char *curr;
unsigned count;
// this name stuff is SO hokey....
#if 0 // mjc might fix right
count = strlen( section->name->text );
if( count <= 8 ){
memcpy( buffer, section->name->text, count );
}else{
#endif
name_offset = _OWLStringIndexToCOFFStringIndex( OWLStringOffset( section->name ) );
buffer[ 0 ] = '/';
count = 0;
curr = &name[ 7 ];
while( name_offset != 0 ) {
*curr-- = '0' + ( name_offset % 10 );
name_offset /= 10;
count++;
}
memcpy( &buffer[ 1 ], curr + 1, count );
#if 0
}
#endif
}
static uint_32 sectionFlags( owl_section_type type ) {
//****************************************************
uint_32 flags = 0;
if( type & OWL_SEC_ATTR_CODE ) flags |= IMAGE_SCN_CNT_CODE;
if( type & OWL_SEC_ATTR_DATA ) flags |= IMAGE_SCN_CNT_INITIALIZED_DATA;
if( type & OWL_SEC_ATTR_BSS ) flags |= IMAGE_SCN_CNT_UNINITIALIZED_DATA;
if( type & OWL_SEC_ATTR_INFO ) flags |= IMAGE_SCN_LNK_INFO;
if( type & OWL_SEC_ATTR_DISCARDABLE ) flags |= IMAGE_SCN_MEM_DISCARDABLE;
if( type & OWL_SEC_ATTR_REMOVE ) flags |= IMAGE_SCN_LNK_REMOVE;
if( type & OWL_SEC_ATTR_COMDAT ) flags |= IMAGE_SCN_LNK_COMDAT;
if( type & OWL_SEC_ATTR_PERM_READ ) flags |= IMAGE_SCN_MEM_READ;
if( type & OWL_SEC_ATTR_PERM_WRITE ) flags |= IMAGE_SCN_MEM_WRITE;
if( type & OWL_SEC_ATTR_PERM_EXEC ) flags |= IMAGE_SCN_MEM_EXECUTE;
if( type & OWL_SEC_ATTR_PERM_SHARE ) flags |= IMAGE_SCN_MEM_SHARED;
return( flags );
}
static uint_32 sectionAlignmentFlags( owl_section_info *section ) {
//*****************************************************************
uint_32 flags;
switch( section->align ) {
case 1:
flags = IMAGE_SCN_ALIGN_1BYTES;
break;
case 2:
flags = IMAGE_SCN_ALIGN_2BYTES;
break;
case 4:
flags = IMAGE_SCN_ALIGN_4BYTES;
break;
case 8:
flags = IMAGE_SCN_ALIGN_8BYTES;
break;
case 16:
flags = IMAGE_SCN_ALIGN_16BYTES;
break;
case 32:
flags = IMAGE_SCN_ALIGN_32BYTES;
break;
case 64:
flags = IMAGE_SCN_ALIGN_64BYTES;
break;
default:
flags = 0;
break;
}
return( flags );
}
static void formatSectionHeader( owl_section_handle section, coff_section_header *header ) {
//*******************************************************************************
memset( header, 0, sizeof( coff_section_header ) );
formatSectionName( section, &header->name[ 0 ] );
header->size = sectionVirtSize( section );
if( section->type & OWL_SEC_ATTR_BSS ) {
header->rawdata_ptr = 0;
header->reloc_ptr = 0;
header->num_relocs = 0;
assert( numRelocs( section ) == 0 );
} else {
header->rawdata_ptr = section->x.coff.section_offset;
header->reloc_ptr = section->x.coff.relocs_offset;
header->num_relocs = numRelocs( section );
}
header->virtsize = 0;
header->offset = 0;
header->lineno_ptr = section->x.coff.linenum_offset;
header->num_lineno = section->num_linenums;
header->flags = sectionFlags( section->type );
header->flags |= sectionAlignmentFlags( section );
}
static void emitSectionHeaders( owl_file_handle file ) {
//******************************************************
uint_32 section_table_size;
coff_section_header *section_table;
unsigned count;
owl_section_info *curr;
section_table_size = numSections( file ) * sizeof( coff_section_header );
if( section_table_size != 0 ) {
section_table = _ClientAlloc( file, section_table_size );
count = 0;
for( curr = file->sections; curr != NULL; curr = curr->next ) {
formatSectionHeader( curr, §ion_table[ curr->index ] );
curr->index = count++;
}
_ClientWrite( file, (const char *)section_table, section_table_size );
_ClientFree( file, section_table );
}
}
static owl_offset sectionPadding( owl_section_handle section, owl_offset offset ) {
//*********************************************************************************
owl_offset mod;
owl_offset padding;
padding = 0;
if( section->align != 0 ) {
mod = offset % section->align;
if( mod != 0 ) {
padding = section->align - mod;
}
}
section->x.coff.alignment_padding = padding;
return( padding );
}
static void calcSectionOffsets( owl_file_handle file ) {
//*******************************************************
owl_offset next;
owl_section_handle section;
int nums;
file->x.coff.header_table_offset = sizeof( coff_file_header );
next = sizeof( coff_file_header ) +
numSections( file ) * sizeof( coff_section_header );
for( section = file->sections; section != NULL; section = section->next ) {
next += sectionPadding( section, next );
nums = sectionFileSize( section );
if( nums == 0 ){
section->x.coff.section_offset = 0;
}else{
section->x.coff.section_offset = next;
}
next += nums;
nums = numRelocs( section );
if( nums == 0 ){
section->x.coff.relocs_offset = 0;
}else{
section->x.coff.relocs_offset = next;
}
next += nums * sizeof( coff_reloc );
nums = numLineNums( section );
if( nums == 0 ){
section->x.coff.linenum_offset = 0;
}else{
section->x.coff.linenum_offset = next;
}
next += nums * sizeof( coff_line_num );
}
file->x.coff.symbol_table_offset = next;
next += numSymbols( file ) * sizeof( coff_symbol );
file->x.coff.string_table_offset = next;
}
#define _CoffSectionIndex( x ) ( (x) + 1 )
// WARNING: Must correspond to stuff in owl_sym_type and owl_sym_linkage enums
static uint_8 complexType[] = {
IMAGE_SYM_DTYPE_FUNCTION,
IMAGE_SYM_DTYPE_NULL
};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?