init.c

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

C
866
字号
           return( ORL_ERROR );
    }
    return( ORL_OKAY );
}


static void openError( char * file_name ) {
// TODO: merge again when Linux clib supports perror()
#ifdef __LINUX__
    printf( "File Open Error: %s\n", file_name );
#else
    perror( file_name );
#endif
    exit( 1 );
}

static void openFiles( void )
{
    int objhdl;

    objhdl = open( ObjFileName, OBJ_FILE_FLAGS );
    if( objhdl != -1 ) {
        if( ListFileName ) {
            OutputDest = open( ListFileName, LIST_FILE_FLAGS, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP );
            if( OutputDest == -1 ) openError( ListFileName );
            ChangePrintDest( OutputDest );
        } else {
            OutputDest = STDOUT_FILENO;
        }
        objFileLen = filelength( objhdl );
        if( objFileLen == 0 ) {
            LeaveProgram( OKAY, WHERE_OBJ_ZERO_LEN );
        }
        objFileBuf = MemAlloc( objFileLen );
        objFilePos = 0;
        if( read( objhdl, objFileBuf, objFileLen ) == -1 ) {
            openError( ObjFileName );
        }
        close( objhdl );
    } else {
        openError( ObjFileName );
    }
}

static void * objRead( void *hdl, size_t len )
/*****************************************/
{
    void *      retval;

    hdl = hdl;
    if( objFilePos + len > objFileLen ) return NULL;
    retval = objFileBuf + objFilePos;
    objFilePos += len;
    return retval;
}

static long objSeek( void *hdl, long pos, int where )
/***************************************************/
{
    hdl = hdl;
    if( where == SEEK_SET ) {
        objFilePos = pos;
    } else if( where == SEEK_CUR ) {
        objFilePos += pos;
    } else {
        objFilePos = objFileLen - pos;
    }
    return objFilePos;
}

extern void CloseObjFile( void )
/******************************/
{
    MemFree( ObjFileName );
    MemFree( objFileBuf );
}

static void initGlobals( void )
{
    Sections.first = NULL;
    Sections.last = NULL;
    Publics.label_lists = NULL;
    Publics.public_symbols = NULL;
    Publics.number = 0;
}

static return_val createHashTables( void )
{
    HandleToSectionTable = HashTableCreate( HANDLE_TO_SECTION_TABLE_SIZE, HASH_NUMBER, NumberCmp );
    if( HandleToSectionTable ) {
        HandleToLabelListTable = HashTableCreate( HANDLE_TO_LIST_TABLE_SIZE, HASH_NUMBER, NumberCmp );
        if( HandleToLabelListTable ) {
            HandleToRefListTable = HashTableCreate( HANDLE_TO_LIST_TABLE_SIZE, HASH_NUMBER, NumberCmp );
            if( HandleToRefListTable ) {
                SymbolToLabelTable = HashTableCreate( SYMBOL_TO_LABEL_TABLE_SIZE, HASH_NUMBER, NumberCmp );
                if( SymbolToLabelTable ) {
                    NameRecognitionTable = HashTableCreate( RECOGNITION_TABLE_SIZE, HASH_STRING, (hash_table_comparison_func) stricmp );
                    if( !NameRecognitionTable ) {
                        HashTableFree( HandleToSectionTable );
                        HashTableFree( HandleToSectionTable );
                        HashTableFree( HandleToLabelListTable );
                        HashTableFree( HandleToRefListTable );
                        HashTableFree( SymbolToLabelTable );
                        return( OUT_OF_MEMORY );
                    }
                } else {
                    HashTableFree( HandleToSectionTable );
                    HashTableFree( HandleToLabelListTable );
                    HashTableFree( HandleToRefListTable );
                    return( OUT_OF_MEMORY );
                }
            } else {
                HashTableFree( HandleToSectionTable );
                HashTableFree( HandleToLabelListTable );
                return( OUT_OF_MEMORY );
            }
        } else {
            HashTableFree( HandleToSectionTable );
            return( OUT_OF_MEMORY );
        }
    } else {
        return( OUT_OF_MEMORY );
    }
    return( OKAY );
}

static return_val initHashTables( void )
{
    int         loop;
    return_val  error;

    error = createHashTables();
    if( error == OKAY ) {
        for( loop = 0; loop < NUM_ELTS( RecognizedName ); loop++ ) {
            HashTableInsert( NameRecognitionTable, (hash_value) RecognizedName[loop].name, RecognizedName[loop].type );
        }
    }
    return( error );
}

orl_machine_type GetMachineType( void )
{
    return( ORLFileGetMachineType( ObjFileHnd ) );
}

/*
 *  Functions to convert data from the file format to the host format where the data may be byte swapped.
 *  If the ORL file is not marked as the opposite endianness as that of the host, then the data will
 *  not be byte swapped. This may not always be the correct behaviour, but if the data is not marked as
 *  a particular endianness, what are we to do about it?
 */

#ifdef __BIG_ENDIAN__
#define ENDIANNESS_TEST     ORL_FILE_FLAG_LITTLE_ENDIAN
#else
#define ENDIANNESS_TEST     ORL_FILE_FLAG_BIG_ENDIAN
#endif 
 
unsigned_16 FileU16toHostU16(unsigned_16 value)
{
    orl_file_flags  flags = ORLFileGetFlags( ObjFileHnd );
    if( flags & ENDIANNESS_TEST )
        return ( SWAPNC_16( value ) );
    return value;
}

unsigned_32 FileU32toHostU32(unsigned_32 value)
{
    orl_file_flags  flags = ORLFileGetFlags( ObjFileHnd );
    if( flags & ENDIANNESS_TEST )
        return ( SWAPNC_32( value ) );
    return value;
}

unsigned_64 FileU64toHostU64(unsigned_64 value)
{
    orl_file_flags  flags = ORLFileGetFlags( ObjFileHnd );
    if( flags & ENDIANNESS_TEST ){
        unsigned_64 new_value;        
        new_value.u._64[0] = SWAPNC_64( value.u._64[0] );
        return new_value;
    }
    return value;
}

static return_val initORL( void )
{
    orl_file_flags      flags;
    orl_machine_type    machine_type;
    orl_return          error = OKAY;
    orl_file_format     type;
    bool                byte_swap;

    oFuncs.alloc = &MemAlloc;
    oFuncs.free = &MemFree;
    oFuncs.read = &objRead;
    oFuncs.seek = &objSeek;
    ORLHnd = ORLInit( &oFuncs );
    if( ORLHnd ) {
        type = ORLFileIdentify( ORLHnd, NULL );
        if( type == ORL_UNRECOGNIZED_FORMAT ) {
            PrintErrorMsg( OKAY, WHERE_NOT_COFF_ELF );
            return( ERROR );
        }
        ObjFileHnd = ORLFileInit( ORLHnd, NULL, type );
        if( ObjFileHnd ) {
            // check byte order
            flags = ORLFileGetFlags( ObjFileHnd );
            byte_swap = FALSE;
#ifdef __BIG_ENDIAN__
            if( flags & ORL_FILE_FLAG_LITTLE_ENDIAN ) {
                byte_swap = TRUE;
            }
#else
            if( flags & ORL_FILE_FLAG_BIG_ENDIAN ) {
                byte_swap = TRUE;
            }
#endif

            // check intended machine type
            machine_type = GetMachineType();
            switch( machine_type ) {
            // If there's no machine specific code, the CPU we choose shouldn't
            // matter; there are some object files like this.
            case ORL_MACHINE_TYPE_NONE:
            case ORL_MACHINE_TYPE_ALPHA:
                if( DisInit( DISCPU_axp, &DHnd, byte_swap ) != DR_OK ) {
                    ORLFini( ORLHnd );
                    PrintErrorMsg( OKAY, WHERE_UNSUPPORTED_PROC );
                    return( ERROR );
                }
                break;
            case ORL_MACHINE_TYPE_PPC601:
                if( DisInit( DISCPU_ppc, &DHnd, byte_swap ) != DR_OK ) {
                    ORLFini( ORLHnd );
                    PrintErrorMsg( OKAY, WHERE_UNSUPPORTED_PROC );
                    return( ERROR );
                }
                // PAS assembler expects "", not \" for quotes.
                if( !(Options & METAWARE_COMPATIBLE) ) {
                    QuoteChar = '\"';
                }
                break;
            case ORL_MACHINE_TYPE_R3000:
            case ORL_MACHINE_TYPE_R4000:
                if( DisInit( DISCPU_mips, &DHnd, byte_swap ) != DR_OK ) {
                    ORLFini( ORLHnd );
                    PrintErrorMsg( OKAY, WHERE_UNSUPPORTED_PROC );
                    return( ERROR );
                }
                break;
            case ORL_MACHINE_TYPE_I386:
            case ORL_MACHINE_TYPE_I8086:
                if( DisInit( DISCPU_x86, &DHnd, byte_swap ) != DR_OK ) {
                    ORLFini( ORLHnd );
                    PrintErrorMsg( OKAY, WHERE_UNSUPPORTED_PROC );
                    return( ERROR );
                }
                break;
            case ORL_MACHINE_TYPE_AMD64:
                if( DisInit( DISCPU_x64, &DHnd, byte_swap ) != DR_OK ) {
                    ORLFini( ORLHnd );
                    PrintErrorMsg( OKAY, WHERE_UNSUPPORTED_PROC );
                    return( ERROR );
                }
                break;
            case ORL_MACHINE_TYPE_SPARC:
                if( DisInit( DISCPU_sparc, &DHnd, byte_swap ) != DR_OK ) {
                    ORLFini( ORLHnd );
                    PrintErrorMsg( OKAY, WHERE_UNSUPPORTED_PROC );
                    return( ERROR );
                }
                break;
            default:
                    ORLFini( ORLHnd );
                    PrintErrorMsg( OKAY, WHERE_UNSUPPORTED_PROC );
                    return( ERROR );
            }
        } else {
            error = ORLGetError( ORLHnd );
            // An "out of memory" error is not necessarily what it seems.
            // The ORL returns this error when encountering a bad or
            // unrecognized object file record.
            if( error == ORL_OUT_OF_MEMORY ) {
                PrintErrorMsg( OUT_OF_MEMORY, WHERE_OPENING_ORL );
            } else {
                PrintErrorMsg( ERROR, WHERE_OPENING_ORL );
            }
        }
        if( error != OKAY ) {
            ORLFini( ORLHnd );
        }
    } else {
        error = OUT_OF_MEMORY;
    }
    return( error );
}

static return_val initServicesUsed( void )
{
    return( initORL() );
}

static return_val initSectionTables( void )
{
    return_val          error;
    orl_return          o_error;
    section_ptr         sec;

    // list for references to external functions, etc.
    error = createLabelList( 0 );
    if( error == OKAY ) {
        o_error = ORLFileScan( ObjFileHnd, NULL, &sectionInit );
        if( o_error == ORL_OKAY && symbolTable ) {
            o_error = DealWithSymbolSection( symbolTable );
            if( o_error == ORL_OKAY ) {
                sec = relocSections.first;
                while( sec ) {
                    o_error = DealWithRelocSection( sec->shnd );
                    if( o_error != ORL_OKAY ) {
                        if( o_error == ORL_OUT_OF_MEMORY ) {
                            return( OUT_OF_MEMORY );
                        } else {
                            return( ERROR );
                        }
                    }
                    relocSections.first = sec->next;
                    MemFree( sec );
                    sec = relocSections.first;
                }
                error = processDrectveSection( drectveSection );
            } else {
                if( o_error == ORL_OUT_OF_MEMORY ) {
                    return( OUT_OF_MEMORY );
                } else {
                    return( ERROR );
                }
            }
        }
    }
    return( error );
}

void PrintErrorMsg( return_val exit_code, int where )
{
    ChangePrintDest( STDERR_FILENO );
    if( exit_code == OUT_OF_MEMORY ) {
        BufferMsg( OUT_OF_MEMORY );
    } else if( exit_code == ERROR ) {
        BufferMsg( ERROR_OCCURRED );
    }
    BufferMsg( where );
    BufferConcatNL();
    BufferPrint();
    ChangePrintDest( OutputDest );
}

void LeaveProgram( return_val exit_code, int message )
{
    PrintErrorMsg( exit_code, message );
    exit( exit_code );
}

void Init( void )
{
    char                cmd_line[ CMD_LINE_LEN ];
    return_val          error;
    char                **list;

    relocSections.first = NULL;
    relocSections.last = NULL;
    if( !MsgInit() ) {
        // MsgInit does its own error message printing
        exit( -1 );
    }
    MemOpen();

    getcmd( cmd_line );
    HandleArgs( cmd_line );

    openFiles();
    initGlobals();
    error = initHashTables();
    if( error == OKAY ) {
        error = initServicesUsed();
        if( error == OKAY ) {
            error = initSectionTables();
            if( error != OKAY ) {
                // free hash tables and services
                MemClose();
                LeaveProgram( error, WHERE_CREATE_SEC_TABLES );
            }
        } else {
            // free hash tables
            CloseFiles();
            FreeHashTables();
            // initServicesUsed does its own error message printing
            exit( error );
        }
    } else {
        CloseFiles();
        MemClose();
        LeaveProgram( error, WHERE_INIT_HASH_TABLES );
    }
    if( Options & PRINT_PUBLICS ) {
        CreatePublicsArray();
    }
    if( IsMasmOutput() ) {
        CommentString = MASM_COMMENT_STRING;
    }
    if( IsIntelx86() ) {
        SkipRefTable = HashTableCreate( RECOGNITION_TABLE_SIZE, HASH_STRING,
                                        (hash_table_comparison_func) stricmp );
        if( SkipRefTable ) {
            list = intelSkipRefList;
            while( *list ) {
                error = HashTableInsert( SkipRefTable, (hash_value) *list,
                                         (hash_data) *list );
                if( error != OKAY ) break;
                list++;
            }
        }
    }

    if( !LabelChar ) {
        if( IsMasmOutput() ) {
            LabelChar = 'L';
        } else {
            LabelChar = 'X';
        }
    }
}

⌨️ 快捷键说明

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