exe2bin.c

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

C
485
字号
        }
    }

    return( header );
}


// allocate a relocation-table for the exe-file stream making use of the
// passed header. populate the table using the local endianess. the caller
// owns the returned memory.

reloc_table *get_reltab( FILE *stream, dos_exe_header *header )
{
    unsigned_16     rel_num;
    reloc_offset    rel_off;
    reloc_table     *reltab;
    int             i;

    rel_num = header->num_relocs;
    reltab  = malloc( sizeof( reloc_table ) + rel_num * sizeof( unsigned_32 ) );
    if( reltab ) {
        reltab->num = rel_num;
        if( fseek( stream, header->reloc_offset, SEEK_SET ) ) {
            free( reltab );
            reltab = NULL;
        } else {
            for( i = 0; i < rel_num; i++ ) {
                if( !fread( &rel_off, sizeof( reloc_offset ), 1, stream ) ) {
                    free( reltab );
                    reltab = NULL;
                    break;
                } else {
                    reltab->reloc[i] = (GET_LE_16( rel_off.segment ) << 4)
                                      + GET_LE_16( rel_off.offset  );
                }
            }
        }
    }

    return( reltab );
}


// parse the command-line and initialize/populate the argument-structure arg.

int parse_cmdline( arguments *arg, int argc, char *argv[] )
{
    char    tmp_path[ _MAX_PATH2 ];
    char    *drive;
    char    *dir;
    char    *fname;
    char    *ext;
    int     i;

    arg->opt.be_ext   = 0;
    arg->opt.be_quiet = 0;
    arg->opt.disp_h   = 0;
    arg->opt.disp_r   = 0;
    arg->opt.have_l   = 0;

    // process the passed options
    i = 1;
    while( (i < argc) && ((*argv[i] == '-') || (*argv[i] == '/')) ) {
        switch( argv[i][1] ) {
        case 'q':
            arg->opt.be_quiet = 1;
            break;
        case 'h':
            arg->opt.disp_h   = 1;
            break;
        case 'r':
            arg->opt.disp_r   = 1;
            break;
        case 'l':
            if( argv[i][2] != '=' ) {
                return( ERR_USAGE );
            }
            arg->opt.lseg     = (unsigned_16)strtol( argv[i] + 3, NULL, 0 );
            arg->opt.have_l   = 1;
            break;
        case 'x':
            arg->opt.be_ext   = 1;
            break;
        default :
            return( ERR_USAGE );
        }
        i++;
    }

    // process file-name(s)
    if( i < argc ) {
        _splitpath2( argv[i], tmp_path, &drive, &dir, &fname, &ext );
        if( *ext == '\0' ) {
            strcpy( ext, "exe" );
        }
        _makepath( arg->iname, drive, dir, fname, ext );
        i++;
        if( i < argc ) {
            strncpy( arg->oname, argv[i], _MAX_PATH );
        }
        else {
            strcpy( ext, "bin" );
            _makepath( arg->oname, drive, dir, fname, ext );
        }
    }
    else {
        return( ERR_USAGE );
    }

    return( ERR_NONE );
}



int main( int argc, char *argv[] )
{
    arguments       arg;
    dos_exe_header  *header;
    reloc_table     *reltab;
    unsigned_32     bin_size;
    unsigned_32     tot_skip;
    int             result;

    result = parse_cmdline( &arg, argc, argv );
    if( !arg.opt.be_quiet ) {
        puts( banner1w( "EXE to Binary Converter", _EXE2BIN_VERSION_ ) );
        puts( banner2( "2001" ) );
        puts( banner3 );
        puts( banner3a );
    }
    if( result ) {
        puts( "Usage:   exe2bin [options] exe_file[.exe] [bin_file]\n"
               "Options: -q        suppress informational messages\n"
               "         -h        display exe-header\n"
               "         -r        display relocations\n"
               "         -l=<seg>  relocate exe_file to segment <seg>\n"
               "         -x        extended behaviour, e.g. files > 64KB" );
        return( EXIT_FAILURE );
    }

    if( (arg.ifile = fopen( arg.iname, "rb" )) == NULL ) {
        printf( "Error opening %s for reading.\n", arg.iname );
        return( EXIT_FAILURE );
    }

    if( !(header = get_header( arg.ifile )) || (header->signature != DOS_SIGNATURE) ) {
        printf( "Error. %s has no valid exe-header.\n", arg.iname );
        return( EXIT_FAILURE );
    }

    if( !(reltab = get_reltab( arg.ifile, header )) ) {
        printf( "Error allocating/reading reloc-table.\n" );
        free( header );
        return( EXIT_FAILURE );
    }
    reltab->lseg = arg.opt.lseg;

    if( arg.opt.disp_h ) {
        printf( "Header of %s (all numbers in hex)\n", arg.iname );
        disp_header( header );
    }

    if( arg.opt.disp_r ) {
        disp_reltab( reltab );
    }

    if( reltab->num && !arg.opt.have_l ) {
        printf( "Error. Option \"-l=<seg>\" mandatory (there are "
                "relocations).\n" );
        free( header );
        free( reltab );
        return( EXIT_FAILURE );
    }

    tot_skip  = header->hdr_size << 4;
    bin_size  = header->mod_size + ( (header->file_size - 1) << 9) - tot_skip;
    bin_size += header->mod_size ? 0: 512;

    // if we do not operate in extended mode check the various restrictions
    // of the original exe2bin. For com-files skip another 0x100 bytes.
    if( !arg.opt.be_ext ) {
        result = ERR_NONE;
        if( bin_size > 0x10000 ) {
            printf( "Error: Binary part exceeds 64 KBytes.\n" );
            result = ERR_RESTRIC;
        }
        if( header->SS_offset || header->SP ) {
            printf( "Error: Stack segment defined.\n" );
            result = ERR_RESTRIC;
        }
        if( header->CS_offset || (header->IP != 0x0000 && header->IP != 0x0100) ) {
            printf( "Error: CS:IP neither 0x0000:0x0000 nor 0x0000:0x0100.\n" );
            result = ERR_RESTRIC;
        }
        if( header->IP == 0x0100 && reltab->num != 0 ) {
            printf( "Error: com-file must not have relocations.\n" );
            result = ERR_RESTRIC;
        }
        if( result != ERR_NONE ) {
            free( header );
            free( reltab );
            return( EXIT_FAILURE );
        }
        if( header->IP == 0x0100 ) {
            tot_skip += 0x100;
            bin_size -= 0x100;
        }
    }

    if( (arg.ofile = fopen( arg.oname, "wb" )) == NULL ) {
        printf( "Error opening %s for writing.\n", arg.oname );
        free( header );
        free( reltab );
        return( EXIT_FAILURE );
    }

    if( (result = copy_bindata( arg.ifile, arg.ofile, bin_size, tot_skip,
                                reltab )) ) {
        switch( result ) {
        case ERR_ALLOC:
            printf( "Error allocating file I/O buffer.\n" );
            break;
        case ERR_READ:
            printf( "Error reading while copying data.\n" );
            break;
        case ERR_WRITE:
            printf( "Error writing while copying data.\n" );
            break;
        }
        free( header );
        free( reltab );
        fclose( arg.ofile );
        remove( arg.oname );
        return( EXIT_FAILURE );
    }

    free( header );
    free( reltab );

    return( EXIT_SUCCESS );
}

⌨️ 快捷键说明

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