⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bdiff.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*
*                            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:  Mainline for binary diff utility.
*
****************************************************************************/


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

#include <unistd.h>
#include <fcntl.h>

#include "bdiff.h"
//#include "exeform.h"

#include "watcom.h"
#include "symtab.h"

#include "machtype.h"
#ifdef USE_DBGINFO
    #include "dbginfo.h"
#endif

typedef enum {
    ALG_NOTHING,        /* find differences without extra info */
    ALG_ONLY_NEW,       /* only the new exe's debugging info is available */
    ALG_BOTH,           /* both exe's have debugging info available */
} algorithm;

#define BUFF_SIZE       16384
#define NL              "\r\n"
#define NL_SIZE         2

typedef struct {
    fpos_t              last_offset;
} walker_data;

typedef struct exe_blk {
    struct exe_blk      *next;
    fpos_t              start;
    uint_32             length;
    uint_16             mod_offset;
} exe_blk;

typedef struct exe_mod {
    struct exe_blk      *blocks;
    unsigned_16         mod_offset;
    char                name[1];
} exe_mod;

#if 0
typedef struct exe_info {
    int                 fd;
    symbol_table        mods_by_offset;
    symbol_table        mods_by_name;
    symbol_table        blks;
    exe_form_t          form;
    struct {
        int             fd;
        fpos_t          start;          /* start of debugging info */
    } sym;
} exe_info;
#endif

char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];

char buff[BUFF_SIZE];

byte *OldSymName;
byte *NewSymName;

//exe_info old;
//exe_info new;

byte *PatchFile;
foff    PatchSize;
byte *OldFile;
byte *NewFile;
int     AppendPatchLevel;
char    *SyncString = NULL;

extern void     Execute( byte * );
extern void     GetMsg( char *, int );
extern void     FileCheck( int fd, char *name );
extern void     SeekCheck( long pos, char *name );
extern  void            MsgPrintf( int resourceid, va_list arglist );

#define MAX_DIFF        (1L<<17)
#define MIN_DIFF        (1L<<7)
#define MIN_EQUALITY    (1L<<6)

#if MIN_EQUALITY > MIN_DIFF / 2
    #error "No dice buddy. Try again!"
#endif

typedef struct region {
    struct region       *next;
    foff                old_start;
    foff                new_start;
    foff                size;
    hole                diff;
    int                 dependants;
} region;

static region   *SimilarRegions = NULL;
static region   *DiffRegions = NULL;
static region   *HoleRegions = NULL;
static region  *HoleArray;
static foff     SimilarSize = 0;
static foff     NumHoles = 0;
static foff     NumDiffs = 0;
static foff     DiffSize = 0;
static foff     HolesInRegion = 0;
static foff     NumSimilarities = 0;
static foff     HoleCount[3] = { 0, 0, 0 };
static foff     HoleHeaders = 0;

static byte *OldCurr;
static byte *NewCurr;
static byte *TestOld;
static byte *TestNew;
static byte *SaveOld;
static byte *SaveNew;
static foff EndOld;
static int  OldCorrection;
static foff EndNew;
static int  NewCorrection;
static byte *CurrPatch;
static int Verbose;
static char *NewName;
static char *CommentFile;
static char LevelBuff[64];

static foff SyncOld = (foff)-1;
static foff SyncNew = (foff)-1;


/*
 * Utility routines
 * ================
 */

static void Err( int format, va_list args )
{
    char        msgbuf[80];

    GetMsg( msgbuf, MSG_ERROR );
    printf( msgbuf );
    MsgPrintf( format, args);
}

void PatchError( int format, ... )
{
    va_list     args;

    va_start( args, format );
    Err( format, args );
    printf( "\n" );
    va_end( args );
    MsgFini();
    exit( EXIT_FAILURE );
}

void FilePatchError( int format, ... )
{
    va_list     args;
    int         err;

    va_start( args, format );
    err = errno;
    Err( format, args );
    printf( ": %s\n", strerror( err ) );
    va_end( args );
    MsgFini();
    exit( EXIT_FAILURE );
}

void stats( char *format, ... )
{
    va_list     arg;

    if( Verbose ) {
        va_start( arg, format );
        vprintf( format, arg );
        fflush( stdout );
        va_end( arg );
    }
}


void NotNull( void *p, char *str )
{
    if( p == NULL ) {
        PatchError( ERR_NO_MEMORY, str );
    }
}


void Usage( char *name )
{
    char msgbuf[80];
    int i;

    GetMsg( msgbuf, MSG_USAGE_LN_1 );
    printf( msgbuf, name );
    for( i = MSG_USAGE_LN_2; i <= MSG_USAGE_LN_6; i++ ) {
        GetMsg( msgbuf, i );
        puts( msgbuf );
    }
    MsgFini();
    exit( EXIT_FAILURE );
}

char *ReadIn( char *name, foff buff_size, foff read_size )
{
    int         fd;
    char        *buff;

    buff = _allocate( buff_size );
    NotNull( buff, "file buffer" );
    fd = open( name, O_RDONLY+O_BINARY, 0 );
    FileCheck( fd, name );
    if( read( fd, buff, read_size ) != read_size ) {
        FilePatchError( ERR_CANT_READ, name );
    }
    return( buff );
}


foff FileSize( char *name, int *correction )
{
    foff        size;
    int         fd;
    char        buff[ sizeof( LEVEL ) ];

    if( access( name, R_OK ) != 0 ) {
        PatchError( ERR_CANT_FIND, name );
    } else {
        fd = open( name, O_RDONLY+O_BINARY, 0 );
        FileCheck( fd, name );
        size = lseek( fd, 0, SEEK_END );
        SeekCheck( size, name );
        *correction = 0;
        if( size > sizeof( LEVEL ) ) {
            SeekCheck( lseek( fd, -(long)sizeof( LEVEL ), SEEK_END ), name );
            if( read( fd, buff, sizeof( LEVEL ) ) != sizeof( LEVEL ) ) {
                FilePatchError( ERR_CANT_READ, name );
            }
            if( memcmp( buff, LEVEL, LEVEL_HEAD_SIZE ) == 0 ) {
                size -= sizeof( LEVEL ); /* lie about size */
                *correction = sizeof( LEVEL );
            }
        }
        close( fd );
    }
    return( size );
}


/*
 * Routines to create "regions" and add them to their lists
 */

void AddRegion( region **owner, foff old_start, foff new_start, foff size )
{
    region      *reg;

    reg = _allocate( sizeof( region ) );
    NotNull( reg, "region" );
    reg->next = *owner;
    reg->old_start = old_start;
    reg->new_start = new_start;
    reg->size = size;
    *owner = reg;
}

void AddSimilar( foff old_start, foff new_start, foff size )
{
    SimilarSize += size;
    if( SimilarRegions ) {
        foff last_old;
        foff last_new;

        last_old = SimilarRegions->old_start + SimilarRegions->size;
        last_new = SimilarRegions->new_start + SimilarRegions->size;
        if( last_old == old_start && last_new == new_start ) {
            SimilarRegions->size += size;
            return;
        }
    }
    HolesInRegion = 0;
    NumSimilarities++;
    AddRegion( &SimilarRegions, old_start, new_start, size );
}

void AddSimilarDiff( foff old_start, foff new_start, foff size )
{
    if( SimilarRegions != NULL ) {
        if( old_start+size < EndOld || new_start+size < EndNew ) {
            if( SimilarRegions->new_start >= ( new_start + size ) ) {
                AddDiff( new_start + size,
                     SimilarRegions->new_start - ( new_start + size ) );
            }
        }
    }
    AddSimilar( old_start, new_start, size );
}


void AddDiff( foff new_start, foff size )
{
    if( size == 0 ) return;
    DiffSize += size;
    if( DiffRegions ) {
        foff last_new;

        last_new = DiffRegions->new_start + DiffRegions->size;
        if( last_new == new_start ) {
            DiffRegions->size += size;
            return;
        }
    }
    NumDiffs++;
    AddRegion( &DiffRegions, -1, new_start, size );
}


void AddHole( foff old_start, foff new_start )
{
    NumHoles++;
    HolesInRegion++;
    AddRegion( &HoleRegions, old_start, new_start, sizeof( hole ) );
    HoleRegions->diff = *(hole*)( NewFile + HoleRegions->new_start )
                      - *(hole*)( OldFile + HoleRegions->old_start );
}

/*
 * =====================================================================
 * Routines to compare the files ignoring "holes". A hole is a 1-4 byte
 * difference in the two files. These are handled specially in the patch
 * file, since these are the changed relocation items caused by a shift
 * in the code within the executable.
 * =====================================================================
 */

int TheSameIgnoringHoles( void )
{
    int         i;
    byte        *end_old;
    byte        *end_new;

    /* sync two file pointers up to an identical byte */

    for( i = 0; ; ++i ) {
        if( i == sizeof(hole)+1 ) {
            return( 0 );
        }
        if( *TestOld == *TestNew ) {
            break;
        }
        ++TestOld;
        ++TestNew;
    }

    /* find out if TestOld and TestNew are similar for length MIN_EQUALITY */

    end_old = TestOld + MIN_EQUALITY;
    end_new = TestNew + MIN_EQUALITY;
    for(;;) {
        if( TestOld >= end_old ) return( 1 );
        if( TestNew >= end_new ) return( 1 );
        if( *TestOld != *TestNew ) {
            if( TestOld[sizeof(hole)] != TestNew[sizeof(hole)] ) {
                if( TestOld[2*sizeof(hole)] != TestNew[2*sizeof(hole)] ) {
                    if( TestOld[3*sizeof(hole)] != TestNew[3*sizeof(hole)] ) {
                        return( 0 );
                    }
                    TestOld += sizeof(hole);
                    TestNew += sizeof(hole);
                }
                TestOld += sizeof(hole);
                TestNew += sizeof(hole);
            }
            TestOld += sizeof(hole)-1;
            TestNew += sizeof(hole)-1;
        }
        ++TestOld;
        ++TestNew;
    }
}

int AreasAreSimilar( foff_diff adjust, foff_diff backup_amt )
{
    byte *lastold;
    byte *lastnew;

    /*
     * Find out if there is a similar area (the same ignoring holes)
     * if we move OldCurr and NewCurr back by "backup_amt", adjusting
     * NewCurr by adjust (the shift between the two areas)
     */

#define AddAndCheck( size ) if( TestOld + size >= OldCurr ) break; \
                            if( TestNew + size >= NewCurr ) break; \

⌨️ 快捷键说明

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