elfexe.c

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

C
786
字号
/****************************************************************************
*
*                            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:  ELF dumping routines.
*
****************************************************************************/


#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include <stdlib.h>

#include "wdglb.h"
#include "wdfunc.h"


#ifdef __BIG_ENDIAN__
    #define NATIVE_ENDIAN   2
#else
    #define NATIVE_ENDIAN   1
#endif

static  char    *elf_exe_msg[] = {
    "2file type (i.e. object, executable file)    = ",
    "2required architecture                       = ",
    "4version of the file                         = ",
    "4program entry point                         = ",
    "4program header offset                       = ",
    "4section header offset                       = ",
    "4processor specific flags                    = ",
    "2ELF header size                             = ",
    "2program header entry size                   = ",
    "2number of program header entries            = ",
    "2section header entry size                   = ",
    "2number of section header entries            = ",
    "2section name string table index             = ",
    NULL
};

static  char    *elf_prog_msg[] = {
    "4type of segment                             = ",
    "4offset of segment from beginning of file    = ",
    "4segment virtual address                     = ",
    "4segment physical address                    = ",
    "4size of segment in file                     = ",
    "4size of segment in memory                   = ",
    "4flags                                       = ",
    "4segment align value (in mem & file)         = ",
    NULL
};

static  char    *elf_sec_msg[] = {
    "4name of the section                         = ",
    "4section type                                = ",
    "4flags                                       = ",
    "4starting address of section in image        = ",
    "4start of section in file                    = ",
    "4size of section in file                     = ",
    "4section header table index link             = ",
    "4extra information                           = ",
    "4address alignment                           = ",
    "4entry size for sects with fixed sized ents  = ",
    NULL
};


/*
 * Dump the segment type.
 */
static void dmp_hdr_type( unsigned_16 type )
/******************************************/
{
    Wdputs( "file type:                                  " );
    switch( type ) {
    case ET_NONE:
        Wdputs( "No file type" );
        break;
    case ET_REL:
        Wdputs( "Relocatable file" );
        break;
    case ET_EXEC:
        Wdputs( "Executable file" );
        break;
    case ET_DYN:
        Wdputs( "Shared object file" );
        break;
    case ET_CORE:
        Wdputs( "Core file" );
        break;
    case ET_LOPROC:
        Wdputs( "Processor specific" );
        break;
    }
    Wdputslc( "\n" );
}

/*
 * Dump the string table section.
 */
static void dmp_sec_strtab( unsigned_32 offset, unsigned_32 size )
/****************************************************************/
{
    char    *string_table, *ptr;

    string_table = Wmalloc( size );
    Wlseek( offset );
    Wread( string_table, size );

    ptr = string_table;
    while( ptr < (string_table + size) ) {
        if( *ptr ) {
            Puthex( ptr - string_table, 8 );
            Wdputslc( ": " );
            Wdputs( ptr );
            Wdputslc( "\n" );
            ptr += strlen( ptr );
        } else {
            ptr++;
        }
    }

    free( string_table );
}

#define     ELF_ROUND   (sizeof( Elf32_Word ) - 1)

/*
 * Dump a note section.
 */
static void dmp_sec_note( unsigned_32 offset, unsigned_32 size )
/**************************************************************/
{
    Elf_Note        note;
    unsigned_32     read = 0;
    unsigned_32     skip;
    char            *ptr;

    Wlseek( offset );
    while( read < size ) {
        Wdputslc( "\n" );
        Wread( &note, sizeof( note ) );
        read += sizeof( note );
        if( Byte_swap ) {
            SWAP_32( note.n_namesz );
            SWAP_32( note.n_descsz );
            SWAP_32( note.n_type );
        }
        ptr = Wmalloc( note.n_namesz );
        Wread( ptr, note.n_namesz );
        Wdputs( "    note name:                              " );
        Wdputs( ptr );
        Wdputslc( "\n" );
        Wdputs( "    descriptor length:                      " );
        Puthex( note.n_descsz, 8 );
        Wdputslc( "H\n" );
        Wdputs( "    note type:                              " );
        switch( note.n_type ) {
        case NT_PRSTATUS:
            Wdputs( "process status" );
            break;
        case NT_FPREGSET:
            Wdputs( "floating-point registers" );
            break;
        case NT_PRPSINFO:
            Wdputs( "process info" );
            break;
        default:
            Wdputs( "unknown (" );
            Puthex( note.n_type, 8 );
            Wdputs( "H)" );
        }
        Wdputslc( "\n" );
        free( ptr );

        /* Calculate rounded up note name length */
        skip = (note.n_namesz + ELF_ROUND) & ~ELF_ROUND;
        read += skip;
        Wlseek( offset + read );
        /* Calculate rounded up note descriptor length */
        skip = (note.n_descsz + ELF_ROUND) & ~ELF_ROUND;
        read += skip;
        Wlseek( offset + read );
    }
}

/*
 * Dump a progbits section.
 */
static void dmp_sec_progbits( char *name,
    unsigned_32 offset, unsigned_32 size )
/****************************************/
{
    const char  *ptr;
    uint        sect;

    if( name == NULL ) {
        Dmp_seg_data( offset, size );
    } else {
        ptr = Wmalloc( size );
        Wlseek( offset );
        Wread( (char *)ptr, size );
        sect = Lookup_section_name( name );
        Dump_specific_section( sect, ptr, size );
        free( (void *)ptr );
    }
}

/*
 * Dump the segment type.
 */
static void dmp_prog_type( unsigned_32 type )
/*******************************************/
{
    Wdputs( "segment type:                               " );
    switch( type ) {
    case PT_NULL:
        Wdputs( "unused segment" );
        break;
    case PT_LOAD:
        Wdputs( "loadable segment" );
        break;
    case PT_DYNAMIC:
        Wdputs( "dynamic linking info" );
        break;
    case PT_INTERP:
        Wdputs( "program interpreter" );
        break;
    case PT_NOTE:
        Wdputs( "comments & auxiliary info" );
        break;
    case PT_SHLIB:
        Wdputs( "unspecified semantics" );
        break;
    case PT_PHDR:
        Wdputs( "address of progam header" );
        break;
    case PT_LOPROC:
        Wdputs( "processor specific" );
        break;
    }
    Wdputslc( "\n" );
}

/*
 * Dump the section type.
 */
static void dmp_sec_type( unsigned_32 type )
/******************************************/
{
    Wdputs( "section type:                               " );
    switch( type ) {
    case SHT_NULL:
        Wdputs( "inactive" );
        break;
    case SHT_PROGBITS:
        Wdputs( "defined by program" );
        break;
    case SHT_SYMTAB:
        Wdputs( "symbol table" );
        break;
    case SHT_STRTAB:
        Wdputs( "string table" );
        break;
    case SHT_RELA:
        Wdputs( "reloc entries with explicit addends" );
        break;
    case SHT_HASH:
        Wdputs( "symbol hash table" );
        break;
    case SHT_DYNAMIC:
        Wdputs( "dynamic linking info" );
        break;
    case SHT_NOTE:
        Wdputs( "comment info" );
        break;
    case SHT_NOBITS:
        Wdputs( "no space in file" );
        break;
    case SHT_REL:
        Wdputs( "reloc entries" );
        break;
    case SHT_SHLIB:
        Wdputs( "reserved (SHT_SHLIB)" );
        break;
    case SHT_DYNSYM:
        Wdputs( "dynamic link symbol table" );
        break;
    case SHT_LOPROC:
        Wdputs( "processor specific" );
        break;
    }
    Wdputslc( "\n" );
}

/*
 * dump the program flag word
 */
static void dmp_prog_flgs( unsigned_32 flags )
/********************************************/
{
    char    name[128];

    name[0] = 0;
    if( flags & PF_X ) {
        strcat( name, " EXECUTABLE |" );
    }
    if( flags & PF_W ) {
        strcat( name, " WRITABLE |" );
    }
    if( flags & PF_R ) {
        strcat( name, " READABLE |" );
    }
    if( name[strlen(name)-1] == '|' ) {
        name[strlen(name)-1] = 0;
    }
    Wdputs( "flags = " );
    Wdputs( name );
    Wdputslc( "\n" );
}

/*
 * dump the section flag word
 */
static void dmp_sec_flgs( unsigned_32 flags )
/*******************************************/
{
    char    name[128];

    name[0] = 0;
    if( flags & SHF_WRITE ) {
        strcat( name, " WRITABLE |" );
    }
    if( flags & SHF_ALLOC ) {
        strcat( name, " ALLOC_SPACE |" );
    }
    if( flags & SHF_EXECINSTR ) {
        strcat( name, " EXEC_INSTR |" );
    }
    if( name[strlen(name)-1] == '|' ) {
        name[strlen(name)-1] = 0;
    }
    Wdputs( "flags = " );
    Wdputs( name );
    Wdputslc( "\n" );
}

/*
 * byte swap ELF section header
 */
static void swap_shdr( Elf32_Shdr *elf_sec )
/******************************************/
{
    if( Byte_swap ) {
        SWAP_32( elf_sec->sh_name );
        SWAP_32( elf_sec->sh_type );
        SWAP_32( elf_sec->sh_flags );
        SWAP_32( elf_sec->sh_addr );
        SWAP_32( elf_sec->sh_offset );
        SWAP_32( elf_sec->sh_size );
        SWAP_32( elf_sec->sh_link );
        SWAP_32( elf_sec->sh_info );
        SWAP_32( elf_sec->sh_addralign );
        SWAP_32( elf_sec->sh_entsize );
    }
}

/*
 * byte swap ELF program header
 */

⌨️ 快捷键说明

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