예제 #1
0
static unsigned BRead( dig_fhandle h, void *b, unsigned s )
{
    unsigned    got;
    unsigned    want;

    if( s > sizeof( Buff.data ) ) {
        Buff.fpos = DCSeek( h, Buff.fpos + Buff.off - Buff.len, DIG_ORG );
        Buff.len = 0;
        Buff.off = 0;
        if( Buff.fpos == -1UL ) return( 0 );
        got = DCRead( h, b, s );
        Buff.fpos += got;
        return( got );
    }
    want = s;
    got = Buff.len - Buff.off;
    if( got > want ) got = want;
    memcpy( b, &Buff.data[Buff.off], got );
    Buff.off += got;
    want -= got;
    if( want > 0 ) {
        Buff.len = DCRead( h, &Buff.data[0], sizeof( Buff.data ) );
        if( Buff.len == (unsigned)-1 ) {
            Buff.fpos = -1UL;
            Buff.off = 0;
            Buff.len = 0;
            return( (unsigned)-1 );
        }
        Buff.fpos += Buff.len;
        b = (unsigned_8 *)b + got;
        memcpy( b, &Buff.data[0], want );
        Buff.off = want;
    }
    return( s );
}
예제 #2
0
static dip_status LoadDirectory( imp_image_handle *ii, unsigned long off )
{
    unsigned_32                 directory;
    cv_subsection_directory     dir_header;
    unsigned                    block_count;
    unsigned                    i;
    unsigned                    left;
    size_t                      block_size;
    unsigned                    num;

    if( DCSeek( ii->sym_fid, off, DIG_ORG ) != off ) {
        return( DS_ERR|DS_FSEEK_FAILED );
    }
    if( DCRead( ii->sym_fid, &directory, sizeof( directory ) ) != sizeof( directory ) ) {
        return( DS_ERR|DS_FREAD_FAILED );
    }
    if( DCSeek( ii->sym_fid, ii->bias + directory, DIG_ORG ) != (ii->bias + directory) ) {
        return( DS_ERR|DS_FSEEK_FAILED );
    }
    if( DCRead( ii->sym_fid, &dir_header, sizeof( dir_header ) ) != sizeof( dir_header ) ) {
        return( DS_ERR|DS_FREAD_FAILED );
    }
    if( dir_header.cbDirHeader != sizeof( dir_header )
            || dir_header.cbDirEntry  != sizeof( cv_directory_entry ) ) {
        return( DS_ERR|DS_INFO_INVALID );
    }
    ii->dir_count = dir_header.cDir;
    block_count = BLOCK_FACTOR( ii->dir_count, DIRECTORY_BLOCK_ENTRIES );
    ii->directory = DCAlloc( block_count * sizeof( cv_directory_entry * ) );
    if( ii->directory == NULL ) {
        return( DS_ERR|DS_NO_MEM );
    }
    memset( ii->directory, 0, block_count * sizeof( cv_directory_entry * ) );
    i = 0;
    left = ii->dir_count;
    for( ;; ) {
        num = left;
        if( num > DIRECTORY_BLOCK_ENTRIES )
            num = DIRECTORY_BLOCK_ENTRIES;
        block_size = num * sizeof( cv_directory_entry );
        ii->directory[i] = DCAlloc( block_size );
        if( ii->directory[i] == NULL ) {
            return( DS_ERR|DS_NO_MEM );
        }
        if( DCRead( ii->sym_fid, ii->directory[i], block_size ) != block_size ) {
            return( DS_ERR|DS_FREAD_FAILED );
        }
        ++i;
        left -= num;
        if( left == 0 ) {
            break;
        }
    }
    return( DS_OK );
}
예제 #3
0
static dip_status FindCV( dig_fhandle fid, unsigned long *offp, unsigned long *sizep )
{
    char        sig[CV_SIG_SIZE];
    dip_status  ds;

    ds = TryFindPE( fid, offp, sizep );
    if( ds & DS_ERR )
        return( ds );
    if( ds != DS_OK ) {
        ds = TryFindTrailer( fid, offp, sizep );
        if( ds != DS_OK ) {
            return( ds );
        }
    }
    if( DCSeek( fid, *offp, DIG_ORG ) != *offp ) {
        return( DS_ERR|DS_FSEEK_FAILED );
    }
    if( DCRead( fid, sig, sizeof( sig ) ) != sizeof( sig ) ) {
        return( DS_ERR|DS_FREAD_FAILED );
    }
    if( memcmp( sig, CV4_NB09, sizeof( sig ) ) != 0 ) {
        return( DS_FAIL );
    }
    return( DS_OK );
}
예제 #4
0
static size_t BRead( FILE *fp, void *b, size_t s )
{
    size_t      got;
    size_t      want;

    if( s > sizeof( Buff.data ) ) {
        DCSeek( fp, Buff.fpos + Buff.off - Buff.len, DIG_ORG );
        Buff.fpos = DCTell( fp );
        Buff.len = 0;
        Buff.off = 0;
        if( Buff.fpos == DIG_SEEK_ERROR )
            return( 0 );
        got = DCRead( fp, b, s );
        Buff.fpos += got;
        return( got );
    }
    want = s;
    got = Buff.len - Buff.off;
    if( got > want )
        got = want;
    memcpy( b, &Buff.data[Buff.off], got );
    Buff.off += got;
    want -= got;
    if( want > 0 ) {
        size_t  len;

        len = DCRead( fp, &Buff.data[0], sizeof( Buff.data ) );
        if( len == DIG_RW_ERROR ) {
            Buff.fpos = DIG_SEEK_ERROR;
            Buff.off = 0;
            Buff.len = 0;
            return( DIG_RW_ERROR );
        }
        Buff.len = len;
        Buff.fpos += Buff.len;
        b = (unsigned_8 *)b + got;
        memcpy( b, &Buff.data[0], want );
        Buff.off = want;
    }
    return( s );
}
예제 #5
0
/*
 * Deals with LX and LE images.
 * We must try grab information from the object table.
 */
static dip_status FindHLLInLXImage( imp_image_handle *ii, unsigned long nh_off )
{
    union  {
        os2_flat_header flat;
        object_record   obj;
    }                   buf;
    dip_status          rc;

    /* read the header */
    rc = DCReadAt( ii->sym_file, &buf.flat, sizeof( buf.flat ), nh_off );
    if( rc & DS_ERR ) {
        return( rc );
    }
    rc = DS_FAIL;
    if( buf.flat.debug_off && buf.flat.debug_len ) {
        ii->is_32bit = 1;
        rc = FoundHLLSign( ii, buf.flat.debug_off, buf.flat.debug_len );
        if( rc == DS_OK ) {
            unsigned i;

            /*
             * Get segment info from the object table.
             */
            if ( DCSeek( ii->sym_file, buf.flat.objtab_off + nh_off, DIG_ORG )
              != buf.flat.objtab_off + nh_off ) {
                return( DS_ERR | DS_FSEEK_FAILED );
            }

            ii->seg_count = buf.flat.num_objects;
            ii->segments = DCAlloc( sizeof( hllinfo_seg ) * ii->seg_count );
            if( ii->segments == NULL ) {
                return( DS_ERR | DS_NO_MEM );
            }

            for( i = 0; i < ii->seg_count; i++ ) {
                if( DCRead( ii->sym_file, &buf.obj, sizeof( buf.obj ) )
                 != sizeof( buf.obj )) {
                    return( DS_ERR | DS_FREAD_FAILED );
                }
                ii->segments[i].is_executable = !!( buf.obj.flags & OBJ_EXECUTABLE );
                ii->segments[i].is_16bit = !( buf.obj.flags & OBJ_BIG );
                ii->segments[i].ovl = 0;
                ii->segments[i].map.offset = 0;
                ii->segments[i].map.segment = i + 1;
                ii->segments[i].size = buf.obj.size;
                ii->segments[i].address = buf.obj.addr;
            }
        }
    }
    return( rc );
}
예제 #6
0
/*
 * Checks if there is a tailing HLL signature in the file.
 *
 * This may work not work on executable images because of file alignments
 * imposed by the linker (ilink at least). However, TryFindInImage will
 * deal with those formats, so it doesn't really matter here.
 */
static dip_status TryFindTrailer( imp_image_handle *ii )
{
    hll_trailer         sig;
    unsigned long       pos;

    pos = DCSeek( ii->sym_file, DIG_SEEK_POSBACK( sizeof( sig ) ), DIG_END );
    if( pos == DIG_SEEK_ERROR ) {
        return( DS_ERR | DS_FSEEK_FAILED );
    }
    if( DCRead( ii->sym_file, &sig, sizeof( sig ) ) != sizeof( sig ) ) {
        return( DS_ERR | DS_FREAD_FAILED );
    }
    if( !IsHllSignature( &sig ) ) {
        return( DS_FAIL );
    }

    pos -= sig.offset - sizeof( sig );
    return( FoundHLLSign( ii, pos, sig.offset - sizeof( sig ) ) );
}
예제 #7
0
static dip_status TryFindTrailer( dig_fhandle fid, unsigned long *offp, unsigned long *sizep )
{
    cv_trailer          sig;
    unsigned long       pos;

    pos = DCSeek( fid, DIG_SEEK_POSBACK( sizeof( sig ) ), DIG_END );
    if( pos == DIG_SEEK_ERROR ) {
        return( DS_ERR|DS_FSEEK_FAILED );
    }
    if( DCRead( fid, &sig, sizeof( sig ) ) != sizeof( sig ) ) {
        return( DS_ERR|DS_FREAD_FAILED );
    }
    if( memcmp( sig.sig, CV4_NB09, sizeof( sig.sig ) ) != 0 ) {
        return( DS_FAIL );
    }
    *sizep = sig.offset - sizeof( sig );
    *offp = pos - *sizep;
    return( DS_OK );
}
예제 #8
0
/*
 * AllocLinkTable - allocate the demand load link table
 *
 */
static dip_status AllocLinkTable( section_info *inf, unsigned long num_links,
                                unsigned long first_link )
{
    dword               **lnk_tbl;
    dword               *lnk;
    mod_table           *tbl;
    unsigned            num;
    unsigned long       count;
    unsigned            i;
    unsigned            d;
    mod_info            *mod;
    unsigned            tbl_entries;
    dword               end;
    info_block          *blk;

    tbl_entries = ((num_links+(MAX_LINK_ENTRIES-1)) / MAX_LINK_ENTRIES) + 1;
    lnk_tbl = DCAlloc( tbl_entries * sizeof( dword * ) );
    if( lnk_tbl == NULL ) {
        DCStatus( DS_ERR|DS_NO_MEM );
        return( DS_ERR|DS_NO_MEM );
    }
    for( i = 0; i < tbl_entries; ++i ) lnk_tbl[i] = NULL;
    inf->dmnd_link = lnk_tbl;
    i = 0;
    count = num_links;
    while( count != 0 ) {
        num = (count>MAX_LINK_ENTRIES) ? MAX_LINK_ENTRIES : count;
        lnk = DCAlloc( num*sizeof(dword));
        if( lnk == NULL ) {
            DCStatus( DS_ERR|DS_NO_MEM );
            return( DS_ERR|DS_NO_MEM );
        }
        lnk_tbl[i++] = lnk;
        if( !inf->ctl->v2 ) {
            if( DCRead(inf->ctl->sym_file,lnk,num*sizeof(dword))!=num*sizeof(dword)) {
                DCStatus( DS_ERR|DS_FREAD_FAILED );
                return( DS_ERR|DS_FREAD_FAILED );
            }
        }
        count -= num;
    }
    lnk = *lnk_tbl;
    num = 0;
    count = 0;
    for( d = DMND_FIRST; d < DMND_NUM; ++d ) {
        for( blk = inf->mod_info; blk != NULL; blk = blk->next ) {
            tbl = blk->link;
            for( i = 0; i < tbl->count; ++i ) {
                mod = (mod_info *)((byte *)blk->info + tbl->mod_off[i]);
                if( inf->ctl->v2 ) {
                    if( mod->di[d].u.size != 0 ) {
                        if( num >= MAX_LINK_ENTRIES ) {
                            lnk = *++lnk_tbl;
                            num = 0;
                        }
                        lnk[num] = mod->di[d].info_off;
                        end = lnk[num] + mod->di[d].u.size;
                        mod->di[d].u.entries = 1;
                        mod->di[d].info_off = count;
                        ++num;
                        ++count;
                    }
                } else {
                    if( mod->di[d].u.entries != 0 ) {
                        mod->di[d].info_off =
                        (mod->di[d].info_off-first_link)/sizeof(dword);
                    }
                }
            }
        }
    }
    if( inf->ctl->v2 ) {
        if( num >= MAX_LINK_ENTRIES ) {
            lnk = *++lnk_tbl;
            num = 0;
        }
        lnk[num] = end;
    }
    return( DS_OK );
}
예제 #9
0
/*
 * Loads the HLL directory.
 *
 * 'offent' is the file offset of the first directory entry.
 */
static dip_status LoadDirectory( imp_image_handle *ii, unsigned long offent )
{
    unsigned                block_count;
    unsigned                i;
    unsigned                left;
    size_t                  block_size;
    unsigned                num;

    /*
     * Read the directory entries. We're using a two-level table here,
     * probably to avoid allocating big chunks of memory...
     */
    block_count = BLOCK_FACTOR( ii->dir_count, DIRECTORY_BLOCK_ENTRIES );
    ii->directory = DCAlloc( block_count * sizeof( void * ) );
    if( ii->directory == NULL ) {
        return( DS_ERR | DS_NO_MEM );
    }
    memset( ii->directory, 0, block_count * sizeof( void * ) );

    /* skip to the first entry */
    if( DCSeek( ii->sym_file, offent, DIG_ORG ) != offent) {
        return( DS_ERR | DS_FSEEK_FAILED );
    }

    i = 0;
    left = ii->dir_count;
    do {
        num = left;
        if( num > DIRECTORY_BLOCK_ENTRIES ) {
            num = DIRECTORY_BLOCK_ENTRIES;
        }
        block_size = num * sizeof( hll_dir_entry );
        ii->directory[i] = DCAlloc( block_size );
        if( ii->directory[i] == NULL ) {
            return( DS_ERR | DS_NO_MEM );
        }
        if( ii->format_lvl >= HLL_LVL_NB04 ) {
            if( DCRead( ii->sym_file, ii->directory[i], block_size ) != block_size ) {
                return( DS_ERR | DS_FREAD_FAILED );
            }
        } else {
            /* Slow but simple. */
            int             j;
            hll_dir_entry  *ent = ii->directory[i];

            for( j = 0; j < num; j++, ent++ ) {
                cv3_dir_entry cv3ent;
                if( DCRead( ii->sym_file, &cv3ent, sizeof( cv3ent ) ) != sizeof( cv3ent ) ) {
                    return( DS_ERR | DS_FREAD_FAILED );
                }
                ent->subsection = cv3ent.subsection;
                ent->iMod       = cv3ent.iMod;
                ent->lfo        = cv3ent.lfo;
                ent->cb         = cv3ent.cb;
            }
        }
        ++i;
        left -= num;
    } while( left != 0 );
    return( DS_OK );
}
예제 #10
0
/*
 * Deals with 32-bit PE images.
 */
static dip_status FindHLLInPEImage( imp_image_handle *ii, unsigned long nh_off )
{
    dip_status          rc;
    unsigned_32         debug_rva;
    unsigned_32         debug_len;
    unsigned_32         image_base;
    unsigned            i;
    unsigned_32         sh_off;
    union {
        char            sig[HLL_SIG_SIZE]; /* ASSUMES >= 4 */
        unsigned_16     sig_16;
        unsigned_32     sig_32;
        pe_header       pe;
        pe_object       sh;
        debug_directory dbg_dir;
    }                   buf;

    /* read the header */
    rc = DCReadAt( ii->sym_file, &buf.pe, sizeof( buf.pe ), nh_off );
    if( rc & DS_ERR ) {
        return( rc );
    }

    debug_rva = buf.pe.table[ PE_TBL_DEBUG ].rva;
    debug_len = buf.pe.table[ PE_TBL_DEBUG ].size;
    if( !debug_rva || !debug_len ) {
        return( DS_FAIL );
    }
    ii->is_32bit = 1;
    image_base = buf.pe.image_base;

    /*
     * Translate the rva to a file offset and read necessary
     * segment information at the same time.
     */
    ii->seg_count = buf.pe.num_objects;
    ii->segments = DCAlloc( sizeof( hllinfo_seg ) * buf.pe.num_objects );
    if( ii->segments == NULL ) {
        return( DS_ERR | DS_NO_MEM );
    }

    sh_off = nh_off /* vv -- watcom mixes the headers :-( */
           + offsetof( pe_header, flags ) + sizeof( buf.pe.flags )
           + buf.pe.nt_hdr_size;

    for ( i = 0; i < ii->seg_count; i++, sh_off += sizeof( buf.sh ) ) {
        rc = DCReadAt( ii->sym_file, &buf.sh, sizeof( buf.sh ), sh_off );
        if ( rc & DS_ERR ) {
            return( rc );
        }

        /* collect segment info. */
        ii->segments[i].is_executable = !!( buf.sh.flags & PE_OBJ_CODE );
        ii->segments[i].ovl = 0;
        ii->segments[i].map.offset = 0;
        ii->segments[i].map.segment = i + 1;
        ii->segments[i].size = buf.sh.virtual_size; // FIXME: alignment?
        ii->segments[i].address = buf.sh.rva + image_base;

        /* is the debug directory section? */
        if( !ii->bias
         && debug_rva - buf.sh.rva < buf.sh.virtual_size ) {
            unsigned_32 debug_off;
            int         left;
            debug_off = buf.sh.physical_offset + debug_rva - buf.sh.rva;

            /*
             * The IBM linker screw up here. It will omit the debug
             * directory and put the debug info there instead.
             * So, before scanning we'll have to check for any HLL sign.
             */
            rc = DCReadAt( ii->sym_file, &buf.dbg_dir, sizeof( buf.dbg_dir ), debug_off );
            if( rc & DS_ERR ) {
                return( rc );
            }
            if( IsHllSignature( &buf ) ) {
                rc = FoundHLLSign( ii, debug_off, debug_len );
            } else {
                left = debug_len / sizeof( debug_directory );
                if( left < 16 )
                    left = 16;
                for ( ;; ) {
                    if( buf.dbg_dir.debug_type == DEBUG_TYPE_CODEVIEW ) {
                        /* found something? */
                        rc = FoundHLLSign( ii, buf.dbg_dir.data_seek, buf.dbg_dir.data_seek );
                        if( rc == DS_OK || rc & DS_ERR ) {
                            break;
                        }
                    }

                    /* next */
                    --left;
                    if( left <= 0) {
                        break;
                    }
                    if ( DCRead( ii->sym_file, &buf.dbg_dir, sizeof( buf.dbg_dir ) ) != sizeof( buf.dbg_dir ) ) {
                        break;
                    }
                }
            }
            if( rc & DS_ERR ) {
                return( rc );
            }
        }
    }

    return( ii->bias ? DS_OK : DS_FAIL );
}
예제 #11
0
static dip_status TryFindPE( dig_fhandle h, unsigned long *offp,
                                unsigned long *sizep )
{
    union {
        dos_exe_header  dos;
        pe_header       pe;
    }                   hdr;
    pe_object           obj;
    unsigned_32         nh_off;
    unsigned_32         section_off;
    unsigned            i;
    unsigned_32         debug_rva;
    debug_directory     dir;

    if( DCSeek( h, 0, DIG_ORG ) != 0 ) {
        return( DS_ERR|DS_FSEEK_FAILED );
    }
    if( DCRead( h, &hdr.dos, sizeof( hdr.dos ) ) != sizeof( hdr.dos ) ) {
        return( DS_ERR|DS_FREAD_FAILED );
    }
    if( hdr.dos.signature != DOS_SIGNATURE ) {
        return( DS_FAIL );
    }
    if( DCSeek( h, NH_OFFSET, DIG_ORG ) != NH_OFFSET ) {
        return( DS_ERR|DS_FSEEK_FAILED );
    }
    if( DCRead( h, &nh_off, sizeof( nh_off ) ) != sizeof( nh_off ) ) {
        return( DS_ERR|DS_FREAD_FAILED );
    }
    if( DCSeek( h, nh_off, DIG_ORG ) != nh_off ) {
        return( DS_ERR|DS_FSEEK_FAILED );
    }
    if( DCRead( h, &hdr.pe, sizeof( hdr.pe ) ) != sizeof( hdr.pe ) ) {
        return( DS_FAIL );
    }
    if( hdr.pe.signature != PE_SIGNATURE ) {
        return( DS_FAIL );
    }
    if( hdr.pe.table[ PE_TBL_DEBUG ].rva == 0 ) {
        return( DS_FAIL );
    }
    debug_rva = (hdr.pe.table[ PE_TBL_DEBUG ].rva / hdr.pe.object_align)*
                                hdr.pe.object_align;

    section_off = nh_off + offsetof( pe_header, flags ) +
                        sizeof( hdr.pe.flags ) + hdr.pe.nt_hdr_size;

    if( DCSeek( h, section_off, DIG_ORG ) != section_off ) {
        return( DS_ERR|DS_FSEEK_FAILED );
    }
    for( i=0; i < hdr.pe.num_objects; i++ ) {
        if( DCRead( h, &obj, sizeof( obj ) ) != sizeof( obj ) ) {
            return( DS_ERR|DS_FREAD_FAILED );
        }
        if( obj.rva == debug_rva ) {
            debug_rva = obj.physical_offset +
                            hdr.pe.table[ PE_TBL_DEBUG ].rva - debug_rva;
            if( DCSeek( h, debug_rva, DIG_ORG ) != debug_rva ) {
                return( DS_ERR|DS_FSEEK_FAILED );
            }
            if( DCRead( h, &dir, sizeof( dir ) ) != sizeof( dir ) ) {
                return( DS_ERR|DS_FREAD_FAILED );
            }
            if( dir.debug_type != DEBUG_TYPE_CODEVIEW ) {
                return( DS_FAIL );
            }
            *offp = dir.data_seek;
            *sizep = dir.debug_size;
        }
    }
    return( DS_FAIL );
}
예제 #12
0
void *VMBlock( imp_image_handle *iih, virt_mem start, size_t len )
{
    unsigned            dir_idx;
    unsigned            pg_idx;
    unsigned            tmp_idx;
    unsigned            i;
    unsigned            j;
    unsigned            num_pages;
    virt_mem            pg_start;
    virt_page           *pg;
    virt_page           *zero;
    loaded_block        *block;

    dir_idx = GET_DIR( start );
    if( iih->virt[dir_idx] == NULL ) {
        if( !InitPageDir( iih, dir_idx ) ) {
            return( NULL );
        }
    }
    pg_idx = GET_PAGE( start );
    len += start % VM_PAGE_SIZE;
    pg_start = start & ~(virt_mem)(VM_PAGE_SIZE - 1);
    pg = iih->virt[dir_idx][pg_idx];
    if( pg == NULL || ( pg->block->len - pg->offset ) < len ) {
        /* unloaded previously loaded block */
        if( pg != NULL ) {
            tmp_idx = dir_idx;
            /* find first page of the block */
            i = pg_idx;
            for( ;; ) {
                iih->virt[tmp_idx][i] = NULL;
                if( pg->offset == 0 )
                    break;
                if( i == 0 ) {
                    --tmp_idx;
                    i = DIR_SIZE;
                }
                --i;
                --pg;
            }
            DCFree( pg );
        }
        num_pages = BLOCK_FACTOR( len, VM_PAGE_SIZE );
        pg = DCAlloc( num_pages * ( sizeof( *pg ) + VM_PAGE_SIZE ) + sizeof( loaded_block ) - 1 );
        if( pg == NULL ) {
            DCStatus( DS_ERR | DS_NO_MEM );
            return( NULL );
        }
        /* set up new page table entries */
        block = (loaded_block *)&pg[num_pages];
        tmp_idx = dir_idx;
        for( j = pg_idx, i = 0; i < num_pages; ++j, ++i ) {
            pg[i].block = block;
            pg[i].offset = i * VM_PAGE_SIZE;
            if( j >= DIR_SIZE ) {
                ++tmp_idx;
                j = 0;
            }
            if( iih->virt[tmp_idx] == NULL ) {
                if( !InitPageDir( iih, tmp_idx ) ) {
                    /* unwind the setup already done */
                    num_pages = i;
                    for( i = 0; i < num_pages; ++i, ++pg_idx ) {
                        if( pg_idx >= DIR_SIZE ) {
                            ++dir_idx;
                            pg_idx = 0;
                        }
                        iih->virt[dir_idx][pg_idx] = NULL;
                    }
                    DCFree( pg );
                    return( NULL );
                }
            }
            if( iih->virt[tmp_idx][j] != NULL ) {
                /*
                    We just ran into another allocated block, so we have
                    to kill all the pages mapped in by it. We know that
                    if the page pointer is non-NULL, it will be offset==0
                    since KillPages will clean out the others.
                */
                KillPages( iih, tmp_idx, j );
            }
            iih->virt[tmp_idx][j] = &pg[i];
        }
        /* read in new block */
        len = num_pages * VM_PAGE_SIZE;
        block->len = len;
        pg_start += iih->bias;
        if( DCSeek( iih->sym_fp, pg_start, DIG_ORG ) ) {
            DCStatus( DS_ERR | DS_FSEEK_FAILED );
            return( NULL );
        }
        /* last block might be a short read */
        if( DCRead( iih->sym_fp, pg->block->data, len ) == DIG_RW_ERROR ) {
            DCStatus( DS_ERR | DS_FREAD_FAILED );
            return( NULL );
        }
        pg = iih->virt[dir_idx][pg_idx];
    }
    ++TimeStamp;
    if( TimeStamp == 0 ) {
        /* deal with wrap-around */
        for( iih = ImageList; iih != NULL; iih = iih->next_image ) {
            if( iih->virt != NULL ) {
                for( i = iih->vm_dir_num; i-- > 0; ) {
                    if( iih->virt[i] != NULL ) {
                        for( j = DIR_SIZE; j-- > 0; ) {
                            zero = iih->virt[i][j];
                            if( zero != NULL ) {
                                zero->block->time_stamp = 0;
                            }
                        }
                    }
                }
            }
        }
        ++TimeStamp;
    }
    pg->block->time_stamp = TimeStamp;
    return( &pg->block->data[(start & (VM_PAGE_SIZE - 1)) + pg->offset] );
}
예제 #13
0
/*
 * AllocLinkTable - allocate the demand load link table
 *
 */
static dip_status AllocLinkTable( section_info *inf, dword num_links, dword first_link )
{
    pointer_int         **lnk_tbl;
    pointer_int         *lnk;
    mod_table           *tbl;
    unsigned            num;
    dword               count;
    unsigned            i;
    demand_kind         dk;
    mod_info            *mod;
    unsigned            tbl_entries;
    pointer_int         end = 0;
    info_block          *blk;
#if defined( _M_X64 )
    unsigned            j;
#endif

    tbl_entries = ( ( num_links + ( MAX_LINK_ENTRIES - 1 ) ) / MAX_LINK_ENTRIES ) + 1;
    lnk_tbl = DCAlloc( tbl_entries * sizeof( pointer_int * ) );
    if( lnk_tbl == NULL ) {
        DCStatus( DS_ERR|DS_NO_MEM );
        return( DS_ERR|DS_NO_MEM );
    }
    for( i = 0; i < tbl_entries; ++i )
        lnk_tbl[i] = NULL;
    inf->dmnd_link = lnk_tbl;
    i = 0;
    num = MAX_LINK_ENTRIES;
    for( count = num_links; count > 0; count -= num ) {
        if( num > count )
            num = count;
        lnk = DCAlloc( num * sizeof( pointer_int ) );
        if( lnk == NULL ) {
            DCStatus( DS_ERR|DS_NO_MEM );
            return( DS_ERR|DS_NO_MEM );
        }
        lnk_tbl[i++] = lnk;
        if( !inf->ctl->v2 ) {
            if( DCRead( inf->ctl->sym_fid, lnk, num * sizeof( dword ) ) != num * sizeof( dword ) ) {
                DCStatus( DS_ERR|DS_FREAD_FAILED );
                return( DS_ERR|DS_FREAD_FAILED );
            }
#if defined( _M_X64 )
            for( j = num; j-- > 0; ) {
                lnk[j] = ((dword *)lnk)[j];
            }
#endif
        }
    }
    lnk = *lnk_tbl;
    num = 0;
    count = 0;
    for( dk = 0; dk < MAX_DMND; ++dk ) {
        for( blk = inf->mod_info; blk != NULL; blk = blk->next ) {
            tbl = blk->link;
            for( i = 0; i < tbl->count; ++i ) {
                mod = (mod_info *)((byte *)blk->info + tbl->mod_off[i]);
                if( inf->ctl->v2 ) {
                    if( mod->di[dk].u.size != 0 ) {
                        if( num >= MAX_LINK_ENTRIES ) {
                            lnk = *++lnk_tbl;
                            num = 0;
                        }
                        lnk[num] = mod->di[dk].info_off;
                        end = lnk[num] + mod->di[dk].u.size;
                        mod->di[dk].u.entries = 1;
                        mod->di[dk].info_off = count;
                        ++num;
                        ++count;
                    }
                } else {
                    if( mod->di[dk].u.entries != 0 ) {
                        mod->di[dk].info_off =
                        ( mod->di[dk].info_off - first_link ) / sizeof( pointer_int );
                    }
                }
            }
        }
    }
    if( inf->ctl->v2 ) {
        if( num >= MAX_LINK_ENTRIES ) {
            lnk = *++lnk_tbl;
            num = 0;
        }
        lnk[num] = end;
    }
    return( DS_OK );
}