Beispiel #1
0
/*
 * Finds a subsection directory entry for a specific module.
 */
hll_dir_entry *hllFindDirEntry( imp_image_handle *ii, imp_mod_handle im, hll_sst sst )
{
    unsigned            i;
    unsigned            block;
    unsigned            full_blocks;
    unsigned            remainder;
    hll_dir_entry       *p;

    full_blocks = BLOCK_FACTOR( ii->dir_count, DIRECTORY_BLOCK_ENTRIES ) - 1;
    for( block = 0; block < full_blocks; ++block ) {
        for( i = 0; i < DIRECTORY_BLOCK_ENTRIES; ++i ) {
            p = &ii->directory[block][i];
            if( p->iMod == im && p->subsection == sst) {
                return( p );
            }
        }
    }
    remainder = ii->dir_count - (full_blocks * DIRECTORY_BLOCK_ENTRIES);
    for( i = 0; i < remainder; ++i ) {
        p = &ii->directory[block][i];
        if( p->iMod == im && p->subsection == sst) {
            return( p );
        }
    }
    return( NULL );
}
Beispiel #2
0
/*
 * Walks the subsection directory.
 *
 * Use 'sst' to limit the callbacks to one specific type. A 'sst' of 0
 * means everything.
 */
walk_result hllWalkDirList( imp_image_handle *ii, hll_sst sst, DIR_WALKER *wk, void *d )
{
    unsigned            i;
    unsigned            block;
    unsigned            full_blocks;
    unsigned            remainder;
    walk_result         wr;
    hll_dir_entry       *p;

    full_blocks = BLOCK_FACTOR( ii->dir_count, DIRECTORY_BLOCK_ENTRIES ) - 1;
    for( block = 0; block < full_blocks; ++block ) {
        for( i = 0; i < DIRECTORY_BLOCK_ENTRIES; ++i ) {
            p = &ii->directory[block][i];
            if( p->subsection == sst || sst == 0) {
                wr = wk( ii, p, d );
                if( wr != WR_CONTINUE ) {
                    return( wr );
                }
            }
        }
    }
    remainder = ii->dir_count - (full_blocks * DIRECTORY_BLOCK_ENTRIES);
    for( i = 0; i < remainder; ++i ) {
        p = &ii->directory[block][i];
        if( p->subsection == sst || sst == 0) {
            wr = wk( ii, p, d );
            if( wr != WR_CONTINUE ) {
                return( wr );
            }
        }
    }
    return( WR_CONTINUE );
}
Beispiel #3
0
/*
 * Frees resources associated with a image handle.
 */
static void Cleanup( imp_image_handle *ii )
{
    imp_image_handle    **owner;
    imp_image_handle    *curr;
    unsigned            blocks;
    unsigned            i;

    /* unlink it */
    owner = &ImageList;
    for( ;; ) {
        curr = *owner;
        if( curr == ii ) {
            break;
        }
        owner = &curr->next_image;
    }
    *owner = ii->next_image;

    /* free memory */
    if( ii->directory != NULL ) {
        blocks = BLOCK_FACTOR( ii->dir_count, DIRECTORY_BLOCK_ENTRIES );
        for( i = 0; i < blocks; ++i ) {
            if( ii->directory[i] != NULL ) {
                DCFree( ii->directory[i] );
            }
        }
        DCFree( ii->directory );
    }
    DCFree( ii->segments );
    VMFini( ii );
}
Beispiel #4
0
dip_status VMInit( imp_image_handle *ii, unsigned long size )
{
    ii->vm_dir_num = BLOCK_FACTOR( size, DIR_SIZE * VM_PAGE_SIZE );
    ii->virt = DCAllocZ( ii->vm_dir_num * sizeof( ii->virt ) );
    if( ii->virt == NULL ) {
        DCStatus( DS_ERR|DS_NO_MEM );
        return( DS_ERR|DS_NO_MEM );
    }
    return( DS_OK );
}
Beispiel #5
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 );
}
Beispiel #6
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 );
}
Beispiel #7
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] );
}