init.c

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

C
866
字号
/****************************************************************************
*
*                            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:  Standalone disassembler initialization routines.
*
****************************************************************************/


#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if defined( __WATCOMC__ )
    #include <process.h>
#endif

#include "dis.h"
#include "init.h"
#include "buffer.h"
#include "memfuncs.h"
#include "hashtabl.h"
#include "publics.h"
#include "args.h"
#include "print.h"
#include "labproc.h"
#include "refproc.h"
#include "msg.h"
#include "main.h"
#include "identsec.h"
#include "fini.h"
#include "formasm.h"


struct recognized_struct {
    char                *name;
    section_type        type;
};

typedef struct recognized_struct recognized_struct;

#define SEC_NAME_LEN 8
#define OBJ_FILE_FLAGS O_RDONLY | O_BINARY
#define LIST_FILE_FLAGS O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU

#define HANDLE_TO_SECTION_TABLE_SIZE 53
#define HANDLE_TO_LIST_TABLE_SIZE 53
#define SYMBOL_TO_LABEL_TABLE_SIZE 53
#define RECOGNITION_TABLE_SIZE 29

#define CPP_COMMENT_STRING "// "
#define MASM_COMMENT_STRING "; "

char    *CommentString  = CPP_COMMENT_STRING;

extern wd_options       Options;
extern char             LabelChar;
extern char             QuoteChar;
extern int              OutputDest;
extern char *           ListFileName;

extern orl_handle       ORLHnd;
extern orl_file_handle  ObjFileHnd;
extern char *           ObjFileName;

extern dis_handle       DHnd;

extern hash_table       HandleToSectionTable;
extern hash_table       HandleToLabelListTable;
extern hash_table       HandleToRefListTable;
extern hash_table       SymbolToLabelTable;
extern hash_table       NameRecognitionTable;
extern hash_table       SkipRefTable;

extern section_list_struct      Sections;
extern publics_struct           Publics;

extern orl_sec_handle           debugHnd;

// sections that require name-checking should be inserted in this array
recognized_struct RecognizedName[] = {
    {".pdata", SECTION_TYPE_PDATA}, {".drectve", SECTION_TYPE_DRECTVE},
    {".bss", SECTION_TYPE_BSS}, {".text", SECTION_TYPE_TEXT},
    {".debug_line", SECTION_TYPE_LINES},
};

static char *intelSkipRefList[] = { "FIWRQQ", // boundary relocs
                                    "FIDRQQ",
                                    "FIERQQ",
                                    "FICRQQ",
                                    "FISRQQ",
                                    "FIARQQ",
                                    "FIFRQQ",
                                    "FIGRQQ",
                                    "FJCRQQ", // boundary + 1 relocs
                                    "FJSRQQ",
                                    "FJARQQ",
                                    "FJFRQQ",
                                    "FJGRQQ",
                                    NULL };

#define NUM_ELTS( a )   (sizeof(a) / sizeof((a)[0]))

static orl_sec_handle           symbolTable;
static orl_sec_handle           drectveSection;
static orl_funcs                oFuncs;
static section_list_struct      relocSections;
static char *                   objFileBuf;
static unsigned long            objFilePos;
static unsigned long            objFileLen;


int IsIntelx86( void )
{
    switch( GetMachineType() ) {
    case( ORL_MACHINE_TYPE_I386 ):
    case( ORL_MACHINE_TYPE_I8086 ):
        return( 1 );
    default:
        return( 0 );
    }
}

orl_file_format GetFormat( void )
{
    return( ORLFileGetFormat( ObjFileHnd ) );
}

static orl_return nopCallBack( char *str, void *cookie  )
{
    str = str;
    cookie = cookie;
    return( ORL_OKAY );
}

static orl_return scanTabCallBack( orl_sec_handle sh, orl_sec_offset start,
                                   orl_sec_offset end, void *cookie )
{
    section_ptr         sec;
    hash_data           *dp;
    scantab_ptr         sp;
    scantab_ptr         tmp;
    scantab_struct      senitel;

    cookie = cookie;
    if( !sh ) return( ORL_OKAY );
    if( start >= end ) return( ORL_OKAY );
    dp = HashTableQuery( HandleToSectionTable, (hash_value) sh );
    if( !dp ) return( ORL_OKAY );
    sec = (section_ptr) *dp;
    if( !sec ) return( ORL_OKAY );

    sp = MemAlloc( sizeof( scantab_struct ) );
    if( !sp ) return( ORL_OUT_OF_MEMORY );
    memset( sp, 0, sizeof( scantab_struct ) );
    sp->start = start;
    sp->end = end;

    senitel.next = sec->scan;
    tmp = &senitel;
    while( tmp->next && ( tmp->next->end < start ) ) {
        tmp = tmp->next;
    }

    if( tmp->next ) {
        if( end < tmp->next->start ) {
            sp->next = tmp->next;
            tmp->next = sp;
        } else {
            // The two records will be merged into one
            if( end > tmp->next->end ) {
                tmp->next->end = end;
            }
            if( start < tmp->next->start ) {
                tmp->next->start = start;
            }
            MemFree( sp );

            // check if we must do additional merging
            sp = tmp->next;
            while( sp->next && ( sp->end > sp->next->start ) ) {
                if( sp->end < sp->next->end ) {
                    sp->end = sp->next->end;
                }
                tmp = sp->next;
                sp->next = tmp->next;
                MemFree( tmp );
            }
        }
    } else {
        tmp->next = sp;
    }

    // restore the list
    sec->scan = senitel.next;

    return( ORL_OKAY );
}

static return_val processDrectveSection( orl_sec_handle shnd )
{
    orl_return          o_error;
    orl_note_callbacks  cb;

    if( !shnd ) return( OKAY );

    cb.export_fn = nopCallBack;
    cb.deflib_fn = nopCallBack;
    cb.entry_fn = nopCallBack;
    cb.scantab_fn = scanTabCallBack;

    o_error = ORLNoteSecScan( shnd, &cb, NULL );
    if( o_error != ORL_OKAY ) {
        if( o_error == ORL_OUT_OF_MEMORY ) {
            return( OUT_OF_MEMORY );
        } else {
            return( ERROR );
        }
    }
    return( OKAY );
}

static return_val addRelocSection( orl_sec_handle shnd )
{
    section_ptr         sec;

    if( relocSections.first && ( GetFormat() == ORL_OMF ) ) return( ORL_OKAY );

    sec = MemAlloc( sizeof( section_struct ) );
    if( sec ) {
        memset( sec, 0, sizeof( section_struct ) );
        sec->shnd = shnd;
        sec->next = NULL;
        if( relocSections.first ) {
            relocSections.last->next = sec;
            relocSections.last = sec;
        } else {
            relocSections.first = sec;
            relocSections.last = sec;
        }
    } else {
        return( OUT_OF_MEMORY );
    }
    return( OKAY );
}

static return_val registerSec( orl_sec_handle shnd, section_type type )
{
    section_ptr         sec;
    return_val          error;

    sec = MemAlloc( sizeof( section_struct ) );
    if( sec ) {
        error = HashTableInsert( HandleToSectionTable, (hash_value) shnd, (hash_data) sec );
        if( error == OKAY ) {
            memset( sec, 0, sizeof( section_struct ) );
            sec->shnd = shnd;
            sec->name = ORLSecGetName( shnd );
            sec->type = type;
            sec->next = NULL;
            if( Sections.first ) {
                Sections.last->next = sec;
                Sections.last = sec;
            } else {
                Sections.first = sec;
                Sections.last = sec;
            }
        } else {
            MemFree( sec );
            return( OUT_OF_MEMORY );
        }
    } else {
        return( OUT_OF_MEMORY );
    }
    return( OKAY );
}

static return_val addListToPublics( label_list list )
{
    label_list_ptr      list_ptr;

    list_ptr = (label_list_ptr) MemAlloc( sizeof( label_list_ptr_struct ) );
    if( list_ptr ) {
        list_ptr->list = list;
        if( Publics.label_lists == NULL ) {
            list_ptr->next = NULL;
            Publics.label_lists = list_ptr;
        } else {
            list_ptr->next = Publics.label_lists;
            Publics.label_lists = list_ptr;
        }
    } else {
        return( OUT_OF_MEMORY );
    }
    return( OKAY );
}

static return_val createLabelList( orl_sec_handle shnd )
{
    label_list          list;
    return_val          error;

    list = MemAlloc( sizeof( label_list_struct ) );
    if( list ) {
        list->first = NULL;
        list->last = NULL;
        error = HashTableInsert( HandleToLabelListTable, (hash_value) shnd, (hash_data) list );
        if( error == OKAY ) {
            if( (Options & PRINT_PUBLICS) && shnd != 0 ) {
                error = addListToPublics( list );
                if( error != OKAY ) {
                    MemFree( list );
                }
            }
        } else {
            MemFree( list );
        }
    } else {
        error = OUT_OF_MEMORY;
    }
    return( error );
}

static return_val createRefList( orl_sec_handle shnd )
{
    ref_list    list;
    return_val  error;

    list = MemAlloc( sizeof( ref_list_struct ) );
    if( list ) {
        list->first = NULL;
        list->last = NULL;
        error = HashTableInsert( HandleToRefListTable, (hash_value) shnd, (hash_data) list );
        if( error != OKAY ) {
            MemFree( list );
        }
    } else {
        error = OUT_OF_MEMORY;
    }
    return( error );
}

static return_val textOrDataSectionInit( orl_sec_handle shnd )
{
    return_val          error;
    orl_sec_handle      reloc_sec;

    error = createLabelList( shnd );
    if( error == OKAY ) {
        error = createRefList( shnd );
        if( error == OKAY ) {
            reloc_sec = ORLSecGetRelocTable( shnd );
            if( reloc_sec ) {
                error = addRelocSection( reloc_sec );
            }
        }
    }
    return( error );
}

static orl_return sectionInit( orl_sec_handle shnd )
{
    section_type        type;
    return_val          error = OKAY;

    type = IdentifySec( shnd );
    switch( type ) {
        case SECTION_TYPE_SYM_TABLE:
            symbolTable = shnd;
            // Might have a label or relocation in symbol section
            error = registerSec( shnd, type );
            if( error == OKAY ) {
                error = createLabelList( shnd );
            }
            break;
        case SECTION_TYPE_DRECTVE:
            if( GetFormat() == ORL_OMF ) {
                drectveSection = shnd;
                break;
            } // else fall through
        case SECTION_TYPE_BSS:
            error = registerSec( shnd, type );
            if( error == OKAY ) {
                error = createLabelList( shnd );
            }
            break;
        case SECTION_TYPE_RELOCS:
            // Ignore OMF relocs section
            break;
        case SECTION_TYPE_LINES:
            debugHnd = shnd;
            type = SECTION_TYPE_DATA;
            // fall through
        case SECTION_TYPE_TEXT:
        case SECTION_TYPE_PDATA:
        case SECTION_TYPE_DATA:
        default: // Just in case we get a label or relocation in these sections
            error = registerSec( shnd, type );
            if( error == OKAY ) {
                error = textOrDataSectionInit( shnd );
            }
            break;
    }
    switch( error ) {
        case OUT_OF_MEMORY:
           return( ORL_OUT_OF_MEMORY );
        case ERROR:

⌨️ 快捷键说明

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