Example #1
0
/*
 * AdjustMods - adjust the demand info offsets in all the modules
 *            - allocate module index table
 *            - allocate demand load link table
 */
dip_status AdjustMods( section_info *inf, unsigned long adjust )
{
    info_block          *blk;
    unsigned            count;
    unsigned            mod_off;
    mod_table           *tbl;
    mod_info            *mod;
    dword               num_links;
    dword               first_link;
    dword               last_link;
    demand_kind         dk;
    unsigned            num;
    pointer_int         *lnk;
    pointer_int         **lnk_tbl;
    unsigned long       off;
    dip_status          ok;

    last_link = 0;
    first_link = (dword)-1L;
    num_links = 1;
    for( blk = inf->mod_info; blk != NULL; blk = blk->next ) {
        mod = (mod_info *)blk->info;
        count = 0;
        for( mod_off = 0; mod_off < blk->size; mod_off += MODINFO_SIZE( (byte *)mod + mod_off ) ) {
            ++count;
        }
        tbl = DCAlloc( sizeof( mod_table ) + ( count - 1 ) * sizeof( mod_info * ) );
        if( tbl == NULL ) {
            DCStatus( DS_ERR|DS_NO_MEM );
            return( DS_ERR|DS_NO_MEM );
        }
        tbl->count = count;
        blk->link = tbl;
        count = 0;
        for( mod_off = 0; mod_off < blk->size; mod_off += MODINFO_SIZE( mod ) ) {
            tbl->mod_off[count++] = mod_off;
            mod = (mod_info *)((byte *)blk->info + mod_off);
            for( dk = 0; dk < MAX_DMND; ++dk ) {
                if( inf->ctl->v2 ) {
                    if( mod->di[dk].u.size != 0 ) {
                        ++num_links;
                    }
                } else {
                    if( mod->di[dk].u.entries != 0 ) {
                        num_links = mod->di[dk].info_off;
                        if( first_link > num_links ) {
                            first_link = num_links;
                        }
                        num_links += mod->di[dk].u.entries * sizeof( pointer_int );
                        if( last_link < num_links ) {
                            last_link = num_links;
                        }
                    }
                }
            }
        }
    }
    if( !inf->ctl->v2 ) {
        off = first_link + adjust;
        if( DCSeek( inf->ctl->sym_fid, off, DIG_ORG) != off ) {
            DCStatus( DS_ERR|DS_FSEEK_FAILED );
            return( DS_ERR|DS_FSEEK_FAILED );
        }
        num_links = (last_link - first_link) / sizeof( pointer_int ) + 2;
    }
    ok = AllocLinkTable( inf, num_links, first_link );
    if( ok != DS_OK )
        return( ok );
    num = 0;
    lnk_tbl = inf->dmnd_link;
    lnk = *lnk_tbl;
    for( ; num_links-- > 0; ) {
        if( num >= MAX_LINK_ENTRIES ) {
            lnk = *++lnk_tbl;
            num = 0;
        }
        /*
         * shift over one bit so as to leave the lower bit
         * clear for testing if it is allocated or not
         */
        lnk[num] = (lnk[num] + adjust) << 1;
        ++num;
    }
    return( DS_OK );
}
Example #2
0
void *VMBlock( imp_image_handle *ii, virt_mem start, size_t len )
{
    unsigned            dir_idx;
    unsigned            pg_idx;
    unsigned            tmp_idx;
    int                 i;
    int                 j;
    unsigned            num_pages;
    virt_mem            pg_start;
    virt_page           *pg;
    virt_page           *zero;
    loaded_block        *block;

    dir_idx = GET_DIR( start );
    if( ii->virt[dir_idx] == NULL ) {
        if( !InitPageDir( ii, dir_idx ) ) {
            return( NULL );
        }
    }
    pg_idx = GET_PAGE( start );
    len += start % VM_PAGE_SIZE;
    pg_start = start & ~(virt_mem)(VM_PAGE_SIZE - 1);
    pg = ii->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( ;; ) {
                ii->virt[tmp_idx][i] = NULL;
                if( pg->offset == 0 )
                    break;
                if( i == 0 ) {
                    --tmp_idx;
                    i = DIR_SIZE;
                }
                --i;
                --pg;
            }
            vmFreeBlock( ii, 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( ii->virt[tmp_idx] == NULL ) {
                if( !InitPageDir( ii, 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;
                        }
                        ii->virt[dir_idx][pg_idx] = NULL;
                    }
                    DCFree( pg );
                    return( NULL );
                }
            }
            if( ii->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( ii, tmp_idx, j );
            }
            ii->virt[tmp_idx][j] = &pg[i];
        }
        /* read in new block */
        len = num_pages * VM_PAGE_SIZE;
        block->len = len;
        block->first_dtor = NULL;
        pg_start += ii->bias;
        if( DCSeek( ii->sym_file, pg_start, DIG_ORG ) != pg_start ) {
            DCStatus( DS_ERR | DS_FSEEK_FAILED );
            return( NULL );
        }
        /* last block might be a short read */
        if( DCRead( ii->sym_file, pg->block->data, len ) == DIG_READ_ERROR ) {
            DCStatus( DS_ERR | DS_FREAD_FAILED );
            return( NULL );
        }
        pg = ii->virt[dir_idx][pg_idx];
    }
    ++TimeStamp;
    if( TimeStamp == 0 ) {
        /* deal with wrap-around */
        for( ii = ImageList; ii != NULL; ii = ii->next_image ) {
            if( ii->virt != NULL ) {
                for( i = ii->vm_dir_num-1; i >= 0; --i ) {
                    if( ii->virt[i] != NULL ) {
                        for( j = DIR_SIZE-1; j >= 0; --j ) {
                            zero = ii->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 ] );
}