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

📄 bdiff.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                stats( "\n" );
                return( 0 );
            }
        }
    }
    AddDiff( new_blk->start, new_blk->length );
    stats( " (changed)\n" );
    return( 0 );
}

int only_new_walker( exe_blk *new_blk, void *parm )
{
    fpos_t len;
    walker_data *last;
    exe_mod *new_mod;
    auto exe_mod tmp_mod;

    last = parm;
    tmp_mod.mod_offset = new_blk->mod_offset;
    new_mod = SymFind( new.mods_by_offset, &tmp_mod );
    if( new_mod == NULL ) {
        fatal( MSG_DEBUG_INFO );
    }
    if( last->last_offset != new_blk->start ) {
        len = new_blk->start - last->last_offset;
        stats( "[%lx-%lx) ???",last->last_offset, last->last_offset + len );
        if( FindBlockInOld( last->last_offset, len ) ) {
            stats( "\n" );
        } else {
            stats( " (NOT found)\n" );
        }
    }
    last->last_offset = new_blk->start + new_blk->length;
    stats( "[%lx-%lx) ", new_blk->start, last->last_offset );
    printd( new_mod->name );
    if( new_blk->start >= EndNew ) {
        stats( " (BSS block ignored)\n" );
        return( 0 );
    }
    if( FindBlockInOld( new_blk->start, new_blk->length ) ) {
        stats( "\n" );
    } else {
        stats( " (NOT found)\n" );
    }
    return( 0 );
}

fpos_t ExeOverlayAccess( exe_form_t exe, uint_16 section, uint_16 *seg )
{
    exe = exe;
    return( section - *seg );
}

//#ifdef USE_DBGINFO
void ProcessExe( char *name, char *sym_name, exe_info *exe )
{
    unsigned num_blks;
    exe_mod *new_mod;
    exe_mod *found_mod;
    exe_blk *new_blk;
    fpos_t first_section;
    fpos_t mod_list;
    fpos_t addr_list;
    fpos_t curr_offset;
    fpos_t debug_header;
    addr48_ptr seg_addr;
    auto master_dbg_header dbg_head;
    auto section_dbg_header section_head;
    auto seg_info seg_desc;
    auto mod_info mod_name;
    auto addr_info seg_chunk;
    auto exe_mod tmp_mod;
    char msgbuf[80];

    _splitpath( name, drive, dir, fname, ext );
    if( ext[0] == '\0' ) {
        strcpy( ext, ".exe" );
    }
    _makepath( buff, drive, dir, fname, ext );
    exe->fd = open( buff, O_RDONLY|O_BINARY );
    if( exe->fd == -1 ) {
        IOError( buff );
    }
    _splitpath( sym_name, drive, dir, fname, ext );
    if( ext[0] == '\0' ) {
        strcpy( ext, ".sym" );
    }
    _makepath( buff, drive, dir, fname, ext );
    exe->sym.fd = open( buff, O_RDONLY|O_BINARY );
    if( exe->sym.fd == -1 ) {
        IOError( buff );
    }
    xseek( exe->sym.fd, - sizeof( dbg_head ), SEEK_END );
    debug_header = lseek( exe->sym.fd, 0, SEEK_CUR );
    xread( exe->sym.fd, &dbg_head, sizeof( dbg_head ) );
    if( dbg_head.signature != VALID_SIGNATURE           ||
        dbg_head.exe_major_ver != EXE_MAJOR_VERSION     ||
        dbg_head.exe_minor_ver > EXE_MINOR_VERSION      ||
        dbg_head.obj_major_ver != OBJ_MAJOR_VERSION     ||
        dbg_head.obj_minor_ver > OBJ_MINOR_VERSION      ) {
        fatal( MSG_DEBUG_INFO );
    }
    exe->sym.start = lseek( exe->sym.fd, 0, SEEK_END ) - dbg_head.debug_size;
    /* get segment positions in executable */
    first_section = exe->sym.start + dbg_head.lang_size + dbg_head.segment_size;
    xseek( exe->sym.fd, first_section, SEEK_SET );
    xread( exe->sym.fd, &section_head, sizeof( section_head ) );
    if( section_head.mod_offset >= section_head.gbl_offset      ||
        section_head.gbl_offset >= section_head.addr_offset     ||
        section_head.addr_offset >= section_head.section_size ) {
        fatal( MSG_DEBUG_INFO );
    }
    exe->mods_by_offset = SymInit( cmp_mod_offset );
    exe->mods_by_name = SymInit( cmp_mod_name );
    mod_list = first_section + section_head.mod_offset;
    xseek( exe->sym.fd, mod_list, SEEK_SET );
    curr_offset = section_head.mod_offset;
    while( curr_offset != section_head.gbl_offset ) {
        xread( exe->sym.fd, &mod_name, sizeof( mod_name ) );
        new_mod = _allocate( sizeof( exe_mod ) + mod_name.name[0] );
        if( new_mod == NULL ) {
            GetMsg( msgbuf, ERR_MEMORY_OUT );
            puts( msgbuf );
            MsgFini();
            exit( EXIT_FAILURE );
        }
        new_mod->blocks = NULL;
        new_mod->mod_offset = curr_offset - section_head.mod_offset;
        new_mod->name[0] = mod_name.name[0];
        xread( exe->sym.fd, &new_mod->name[1], mod_name.name[0] );
        SymAdd( exe->mods_by_offset, new_mod );
        SymAdd( exe->mods_by_name, new_mod );
        curr_offset += sizeof( mod_name ) + mod_name.name[0];
    }
    if( exe == &new ) {
        new.blks = SymInit( cmp_blk );
    }
    if( first_section + section_head.section_size != debug_header ) {
        fatal( MSG_OVERLAYS );
    }
    exe->form = ExeForm( exe->fd, 0, exe );
    addr_list = first_section + section_head.addr_offset;
    xseek( exe->sym.fd, addr_list, SEEK_SET );
    curr_offset = section_head.addr_offset;
    while( curr_offset != section_head.section_size ) {
        xread( exe->sym.fd, &seg_desc, sizeof(seg_info) - sizeof(addr_info) );
        curr_offset += sizeof( seg_info ) - sizeof( addr_info );
        num_blks = seg_desc.num;
        seg_addr = seg_desc.base;
        while( num_blks != 0 ) {
            xread( exe->sym.fd, &seg_chunk, sizeof( seg_chunk ) );
            curr_offset += sizeof( seg_chunk );
            tmp_mod.mod_offset = seg_chunk.mod;
            found_mod = SymFind( exe->mods_by_offset, &tmp_mod );
            if( found_mod == NULL ) {
                fatal( MSG_DEBUG_INFO );
            }
            new_blk = _allocate( sizeof( *new_blk ) );
            if( new_blk == NULL ) {
                GetMsg( msgbuf, ERR_MEMORY_OUT );
                puts( msgbuf );
                MsgFini();
                exit( EXIT_FAILURE );
            }
            new_blk->next = found_mod->blocks;
            found_mod->blocks = new_blk;
            new_blk->start = ExeTransformAddr( exe->form,
                                seg_addr.segment, seg_addr.offset,
                                section_head.section_id );
            seg_addr.offset += seg_chunk.size;
            new_blk->length = seg_chunk.size;
            new_blk->mod_offset = found_mod->mod_offset;
            if( exe == &new ) {
                SymAdd( new.blks, new_blk );
            }
            --num_blks;
        }
    }
}

void SymbolicDiff( algorithm alg, char *old_exe, char *new_exe )
{
    auto walker_data data;

    data.last_offset = 0;
    ProcessExe( new_exe, NewSymName, &new );
    if( alg == ALG_BOTH ) {
        ProcessExe( old_exe, OldSymName, &old );
        SymWalk( new.blks, &data, both_walker );
        close( old.fd );
        close( old.sym.fd );
    } else {
        SymWalk( new.blks, &data, only_new_walker );
    }
    close( new.fd );
    close( new.sym.fd );
}
#endif


void VerifyCorrect( char *name )
{

    /* Try the patch file and ensure it produces new from old */

    char        *real_new;
    foff        offset;

    memset( NewFile, 0x00, EndNew );
    Execute( NewFile );
    _free( OldFile );
    real_new = ReadIn( name, EndNew, EndNew );
    if( real_new != NULL ) {
        if( memcmp( real_new, NewFile, EndNew ) != 0 ) {
            offset = 0;
            for(;;) {
                if( *real_new != *NewFile ) {
                    PatchError( ERR_PATCH_BUNGLED, offset, *real_new, *NewFile );
                }
                ++offset;
                if( offset >= EndNew ) break;
                ++real_new;
                ++NewFile;
            }
        }
        _free( real_new );
    }
}

int HoleCompare(const void *_h1, const void *_h2)
{
    const region *h1 = _h1;
    const region *h2 = _h2;

    if( h1->diff < h2->diff ) return( -1 );
    if( h1->diff > h2->diff ) return( 1 );
    if( h1->new_start < h2->new_start ) return( -1 );
    if( h1->new_start > h2->new_start ) return( 1 );
    return( 0 );
}


#define OutPatch( val, type ) {CheckPatch( sizeof(type) );*(type*)CurrPatch=(val);CurrPatch+=sizeof(type);}

/*
 * Output the offset to the next hole with the same difference value.
 * as follows:
 * 0xxxxxxx                     - value xxxxxxx                 ( 0 .. 127 )
 * 10xxxxxx yyyyyyyy            - value xxxxxxyyyyyyyy          ( 0 .. 16383 )
 * 11xxxxxx yyyyyyyy zzzzzzzz   - value xxxxxxyyyyyyyyzzzzzzzz  ( 0 .. 2**30-1 )
 */

int OutVar( foff value, int really )
{
    if( value <= 0x7f ) {
        if( really ) {
            OutPatch( value & 0x7f, byte );     /* top bit off */
        }
        return( 0 );
    } else if( value <= 0x3fff ) {      /* top bit on, next bit off */
        if( really ) {
            OutPatch( 0x80 | ( ( value >> 8 ) & 0x3f ), byte );
            OutPatch( value & 0xff, byte );
        }
        return( 1 );
    } else {                            /* top two on */
        if( really ) {
            OutPatch( 0xC0 | ( ( value >> 16 ) & 0x3f ), byte );
            OutPatch( ( value >> 8 ) & 0xff, byte );
            OutPatch( value & 0xff, byte );
        }
        return( 2 );
    }
}


void OutStr( char *str )
{
    for( ;; ) {
        if( *str == '\0' ) break;
        OutPatch( *str, char );
        ++str;
    }
}


#define MIN_ITERS (sizeof(patch_cmd)+sizeof(hole)+sizeof(foff)+sizeof(foff))

int FOffCompare(const void *_h1, const void *_h2)
{
    const region *h1 = _h1;
    const region *h2 = _h2;

    if( h1->new_start < h2->new_start ) return( -1 );
    if( h1->new_start > h2->new_start ) return( 1 );
    return( 0 );
}

#define RUN_SIZE 5

long HolesToDiffs( void )
{
    /* Find runs of holes which would be cheaper to represent as differences */

    region      *curr;
    region      *next;
    region      *end;
    region      *run_start;
    region      *run;
    long        hole_size;
    long        diff_size;
    long        dead_holes;
    long        savings;

    savings = 0;
    if( NumHoles != 0 ) {

        /* sort by file offset */

        qsort(HoleArray, NumHoles, sizeof( region ), FOffCompare );

        end = HoleArray + NumHoles - 1;
        next = HoleArray+1;
        curr = HoleArray;
        dead_holes = 0;
        savings = 0;

        /* going through the array in adjacent pairs, (curr, next) ... */

        for( ;; ) {

            /* find two holes which are the same small amount apart */

            for( ;; ) {
                if( curr >= end ) break;
                if( next->old_start - curr->old_start
                 != next->new_start - curr->new_start ) break;
                if( next->old_start - curr->old_start <= RUN_SIZE ) break;
                ++next;
                ++curr;
            }
            if( curr >= end ) break;

            /* extend this run while holes are the same small distance apart */

            run_start = curr;
            for( ;; ) {
                ++next;
                ++curr;
                if( curr >= end ) break;
                if( next->old_start - curr->old_start
                 != next->new_start - curr->new_start ) break;
                if( next->old_start - curr->old_start > RUN_SIZE ) break;
            }
            if( curr >= end ) break;

            /* convert to a difference region if it would make patch smaller */

            hole_size = 0;
            diff_size = 2*sizeof(foff)+sizeof(patch_cmd)
            + curr->new_start - run_start->new_start + sizeof(hole);
            for( run = run_start; run <= curr; ++run ) {
                if( run->dependants == 1 ) hole_size += run->size;
            }
            if( hole_size > diff_size ) {
                savings += hole_size - diff_size;
                AddRegion( &DiffRegions, run_start->old_start,
                           run_start->new_start,
                           curr->new_start-run_start->new_start+sizeof(hole) );
                for( run = run_start; run <= curr; ++run ) {
                    ++dead_holes;
                    run->diff = 0;
                    run->new_start = 0;
                }
                ++curr;
                next = curr+1;
            }
        }

        /* sort by difference amount. This moves dead holes to the front */

        SortHoleArray();

        /* Get rid of dead holes (Those converted to difference regions) */

        NumHoles -= dead_holes;
        memmove( HoleArray, HoleArray+dead_holes, NumHoles * sizeof( region ) );
    }
    return( savings );
}


void ProcessHoleArray( int write_holes )
{

    /* write holes out to the patch file, or just calculate file size needed */

    region      *curr;
    region      *curr_header;
    region      *end_iters;
    region      *prev;
    region      *end;
    hole        curr_diff;
    hole        diff;
    foff        curr_start;
    int         first;
    foff        iters;
    foff        incr;
    int         size;

    if( NumHoles != 0 ) {
        end = HoleArray + NumHoles - 1;
        first = 1;
        for( curr = HoleArray; curr <= end; ++curr ) {
            diff = curr->diff;
            prev = curr;
            curr->dependants = 1;
            incr = 0;
            iters = 1;
            for( end_iters = curr + 1; end_iters <= end; ++end_iters ) {
                if( diff != end_iters->diff ) break;
                if( incr != 0
                 && incr != end_iters->new_start - prev->new_start ) break;
                incr = end_iters->new_start - prev->new_start;
                ++iters;
                prev = end_iters;
            }
            if( iters > MIN_ITERS ) {
                if( write_holes ) {
                    if( !first ) {
                        OutPatch( 0, byte );
                    }
                    HoleHeaders++;

⌨️ 快捷键说明

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