owelf.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 481 行 · 第 1/2 页

C
481
字号
/****************************************************************************
*
*                            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:  Emit ELF object.
*
****************************************************************************/


#include "owlpriv.h"
#include "owreloc.h"

#define MAX_SECTION_NAME        128

#define ELF_UNDEF_INDEX         0
#define ELF_STRING_INDEX        1       /* index of string table section */
#define ELF_SYMBOL_INDEX        2       /* index of symbol table section */
#define FIRST_USER_SECTION      3

#define _OWLIndexToELFIndex( x )        ( (x) + FIRST_USER_SECTION )

static int useRela;                     // Use .rela or .rel

static unsigned numSections( owl_file_handle file ) {
//***************************************************

    return( _OWLIndexToELFIndex( file->next_index ) );
}

static unsigned numSymbols( owl_file_handle file ) {
//**************************************************

    return( file->symbol_table->num_global_symbols +
                file->symbol_table->num_local_symbols );
}

// must correspond to owl_cpu in owl.h
static Elf32_Half machineTypes[] = { EM_PPC, EM_ALPHA, EM_MIPS, EM_386 };

static void writeFileHeader( owl_file_handle file ) {
//***************************************************

    Elf32_Ehdr          header;

    memset( &header.e_ident[ 0 ], 0, sizeof( header.e_ident ) );
    header.e_ident[ EI_MAG0 ] = ELFMAG0;
    header.e_ident[ EI_MAG1 ] = ELFMAG1;
    header.e_ident[ EI_MAG2 ] = ELFMAG2;
    header.e_ident[ EI_MAG3 ] = ELFMAG3;
    header.e_ident[ EI_CLASS ] = ELFCLASS32;
#if defined( __BIG_ENDIAN__ )
    header.e_ident[ EI_DATA ] = ELFDATA2MSB;
#else
    header.e_ident[ EI_DATA ] = ELFDATA2LSB;
#endif
    header.e_ident[ EI_VERSION ] = EV_CURRENT;
    header.e_type = ET_REL;
    header.e_machine = machineTypes[ file->info->cpu ];
    header.e_version = EV_CURRENT;
    header.e_entry = 0;                 // fixme - should allow client to set this
    header.e_phoff = 0;
    header.e_shoff = sizeof( header );  // follows immediately after the file header
    header.e_flags = 0;                 // FIXME - get right stuff from IBM buttheads
    header.e_ehsize = sizeof( header );
    header.e_phentsize = sizeof( Elf32_Phdr );
    header.e_phnum = 0;
    header.e_shentsize = sizeof( Elf32_Shdr );
    header.e_shnum = numSections( file );
    header.e_shstrndx = ELF_STRING_INDEX;
    _ClientWrite( file, (const char *)&header, sizeof( header ) );
}

static void prepareStringTable( owl_file_handle file, elf_special_section *str_sect ) {
//*************************************************************************************
// Before we can use indices for owl_string_handles, we
// have to write the string table into a temporary buffer

    str_sect->length = OWLStringTableSize( file->string_table );
    str_sect->buffer = _ClientAlloc( file,  str_sect->length );
    OWLStringEmit( file->string_table, str_sect->buffer );
}

// must correspond to owl_sym_linkage in owl.h
static Elf32_Half elfBinding[] = { STB_GLOBAL, STB_LOCAL, STB_LOCAL, STB_GLOBAL, STB_WEAK };

// must correspond to owl_sym_type in owl.h
static Elf32_Half elfType[] = { STT_FUNC, STT_OBJECT, STT_SECTION, STT_FILE };

static void emitElfSymbol( owl_symbol_info *symbol, Elf32_Sym *elf_sym ) {
//************************************************************************

    elf_sym->st_name = OWLStringOffset( symbol->name );
    elf_sym->st_value = symbol->offset;
    elf_sym->st_size = 0;
    elf_sym->st_info = ELF32_ST_INFO( elfBinding[ symbol->linkage ], elfType[ symbol->type ] );
    elf_sym->st_other = 0;
    elf_sym->st_shndx = SHN_UNDEF;
    if( symbol->section != NULL ) {
        elf_sym->st_shndx = _OWLIndexToELFIndex( symbol->section->index );
    }
}

static void emitBogusSymbol( Elf32_Sym *elf_sym ) {
//*************************************************

    elf_sym->st_name = 0;
    elf_sym->st_value = 0;
    elf_sym->st_size = 0;
    elf_sym->st_info = 0;
    elf_sym->st_other = 0;
    elf_sym->st_shndx = SHN_UNDEF;
}

static void prepareSymbolTable( owl_file_handle file, elf_special_section *sym_sect ) {
//*************************************************************************************
// Same as for prepareStringTable, but with symbols instead of strings. Since symbol
// table entries are format-specific, we don't have a handy OWLSymbol call to do all
// our work for us, so we just run the table converting everything

    owl_symbol_info     *sym;
    unsigned            next_local_index;
    unsigned            next_global_index;
    Elf32_Sym           *elf_syms;

    sym_sect->length = ( numSymbols( file ) + 1 ) * sizeof( Elf32_Sym );
    sym_sect->buffer = _ClientAlloc( file, sym_sect->length );
    elf_syms = (Elf32_Sym *)sym_sect->buffer;
    emitBogusSymbol( elf_syms );
    next_local_index = 1;
    next_global_index = file->symbol_table->num_global_symbols + file->symbol_table->num_local_symbols;
    for( sym = file->symbol_table->head; sym != NULL; sym = sym->next ) {
        if( sym->flags & OWL_SYM_DEAD ) continue;
        if( !(_OwlLinkageGlobal(sym->linkage)) ) {
            sym->index = next_local_index++;
        } else {
            sym->index = next_global_index--;
        }
        emitElfSymbol( sym, &elf_syms[ sym->index ] );
    }
    assert( ( next_global_index + 1 ) == next_local_index );
    assert( next_local_index == ( file->symbol_table->num_local_symbols + 1 ) );
}

static void initSectionHeader( Elf32_Shdr *header, Elf32_Word type, Elf32_Word flags ) {
//**************************************************************************************

    header->sh_name = 0;
    header->sh_type = type;
    header->sh_flags = flags;
    header->sh_addr = 0;
    header->sh_offset = 0;
    header->sh_size = 0;
    header->sh_link = SHN_UNDEF;
    header->sh_info  = 0;
    header->sh_addralign = 0;
    header->sh_entsize = 0;
}

static void formatBogusUndefHeader( owl_file_handle file, Elf32_Shdr *header ) {
//******************************************************************************

    file = file;
    initSectionHeader( header, SHT_NULL, 0 );
}

static void formatStringTableHeader( owl_file_handle file, Elf32_Shdr *header ) {
//*******************************************************************************

    initSectionHeader( header, SHT_STRTAB, 0 );
    header->sh_name = OWLStringOffset( file->x.elf.string_table.name );
    header->sh_offset = file->x.elf.next_section;
    header->sh_size = file->x.elf.string_table.length;
    file->x.elf.next_section += file->x.elf.string_table.length;
}

static void formatSymbolTableHeader( owl_file_handle file, Elf32_Shdr *header ) {
//*******************************************************************************

    elf_special_section *sym_tab;

    sym_tab = &file->x.elf.symbol_table;
    initSectionHeader( header, SHT_SYMTAB, 0 );
    header->sh_name = OWLStringOffset( sym_tab->name );
    header->sh_link = ELF_STRING_INDEX;
    header->sh_info = file->symbol_table->num_local_symbols + 1;
    header->sh_entsize = sizeof( Elf32_Sym );
    header->sh_offset = file->x.elf.next_section;
    header->sh_size = sym_tab->length;
    file->x.elf.next_section += sym_tab->length;
}


static Elf32_Word sectionTypes( owl_section_type type ) {
//*******************************************************

    if( type & OWL_SEC_ATTR_CODE ) return( SHT_PROGBITS );
    if( type & OWL_SEC_ATTR_DATA ) return( SHT_PROGBITS );
    if( type & OWL_SEC_ATTR_BSS ) return( SHT_NOBITS );
    if( type & OWL_SEC_ATTR_INFO ) return( SHT_NOTE );
    return( SHT_NULL );
}

static Elf32_Word sectionFlags( owl_section_type type ) {
//*******************************************************

    uint_32 flags = 0;

    if( type & OWL_SEC_ATTR_CODE ) flags |= SHF_ALLOC;
    if( type & OWL_SEC_ATTR_DATA ) flags |= SHF_ALLOC;
    if( type & OWL_SEC_ATTR_BSS ) flags |= SHF_ALLOC;
    if( type & OWL_SEC_ATTR_PERM_WRITE ) flags |= SHF_WRITE;
    if( type & OWL_SEC_ATTR_PERM_EXEC ) flags |= SHF_EXECINSTR;
    return( flags );
}

static uint_32 sectionAlignment( owl_section_info *section )
//**********************************************************
{
    uint_32     alignment = 0;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?