示例#1
0
char *AddPath( char *old_list, const char *path_list )
/***************************************************/
{
    size_t          len;
    size_t          old_len;
    char            *new_list;
    char            *p;

    new_list = old_list;
    if( path_list != NULL && *path_list != NULLCHAR ) {
        len = strlen( path_list );
        if( old_list == NULL ) {
            p = new_list = ProfAlloc( len + 1 );
        } else {
            old_len = strlen( old_list );
            new_list = ProfAlloc( old_len + 1 + len + 1 );
            memcpy( new_list, old_list, old_len );
            ProfFree( old_list );
            p = new_list + old_len;
        }
        while( *path_list != NULLCHAR ) {
            if( p != new_list )
                *p++ = PATH_LIST_SEP;
            path_list = GetPathElement( path_list, NULL, &p );
        }
        *p = NULLCHAR;
    }
    return( new_list );
}
示例#2
0
STATIC void procAddrBlock( uint_16 total_len, samp_data * data )
/**************************************************************/
{
    image_info *    curr_image;
    int             map_count;
    int             new_count;
    int             i;
    int             j;
    map_to_actual   *map;

    total_len -= offsetof( samp_block, d.map );
    new_count = total_len / sizeof( mapping );
    curr_image = CurrSIOData->curr_image;
    map_count = curr_image->map_count + new_count;
    map = curr_image->map_data;
    if( map == NULL ) {
        map = ProfAlloc( map_count * sizeof(*map) );
    } else {
        map = ProfRealloc( map, map_count * sizeof(*map) );
    }
    for( i = 0, j = curr_image->map_count; i < new_count; ++i, ++j ) {
        map[j].map.mach.segment    = data->map.data[i].map.segment;
        map[j].map.mach.offset     = data->map.data[i].map.offset;
        map[j].actual.mach.segment = data->map.data[i].actual.segment;
        map[j].actual.mach.offset  = data->map.data[i].actual.offset;
        map[j].length              = 0xffff; //NYI: get from executable....
    }
    curr_image->map_count = map_count;
    curr_image->map_data = map;
}
示例#3
0
extern char * WPSourceGetLine( a_window * wnd, int line )
/*******************************************************/
{
    sio_data *      curr_sio;
    wp_srcfile *    wp_src;
    int             buff_len;

    curr_sio = WndExtra( wnd );
    wp_src = curr_sio->src_file;
    if( wp_src->src_buff_len == 0 ) {
        wp_src->src_buff = ProfAlloc( 100 );
        wp_src->src_buff_len = 100;
    }
    for( ;; ) {
        buff_len = FReadLine( wp_src->src_file, line, 0, wp_src->src_buff,
                              wp_src->src_buff_len );
        if( buff_len != wp_src->src_buff_len ) break;
        wp_src->src_buff_len += 120;
        wp_src->src_buff = ProfRealloc( wp_src->src_buff,
                                        wp_src->src_buff_len );
    }
    if( buff_len < 0 ) {
        wp_src->src_eof = P_TRUE;
        return( NULL );
    }
    wp_src->src_eof = P_FALSE;
    wp_src->src_buff[buff_len] = NULLCHAR;
    return( wp_src->src_buff );
}
示例#4
0
STATIC bool initCurrSIO( void )
/*****************************/
{
    image_info      *new_image;
    file_handle     fh;
    int             name_len;

    fh = open( SamplePath, O_RDONLY | O_BINARY, S_IREAD );
    if( fh == (file_handle) -1 ) {
        ErrorMsg( LIT( Cannot_Open_Smp_File ), SamplePath );
        return( false );
    }
    CurrSIOData = ProfCAlloc( sizeof(sio_data) );
    CurrSIOData->fh = fh;
    name_len = strlen( SamplePath ) + 1;
    CurrSIOData->samp_file_name = ProfAlloc( name_len );
    memcpy( CurrSIOData->samp_file_name, SamplePath, name_len );
    CurrSIOData->images = ProfAlloc( 2*sizeof(pointer) );
    new_image = ProfCAlloc( sizeof(image_info) );
    name_len = strlen( LIT( Unknown_Image ) ) + 1;
    new_image->name = ProfAlloc( name_len );
    memcpy( new_image->name, LIT( Unknown_Image ), name_len );
    new_image->unknown_image = true;
    CurrSIOData->images[0] = new_image;
    CurrSIOData->curr_image = new_image;
    new_image = ProfCAlloc( sizeof(image_info) );
    name_len = strlen( LIT( Gathered_Images ) ) + 1;
    new_image->name = ProfAlloc( name_len );
    memcpy( new_image->name, LIT( Gathered_Images ), name_len );
    new_image->ignore_gather = true;
    new_image->gather_image = true;
    CurrSIOData->images[1] = new_image;
    CurrSIOData->image_count = 2;
    CurrSIOData->curr_display_row = -WND_MAX_ROW;
    return( true );
}
示例#5
0
STATIC walk_result loadRoutineInfo( sym_walk_info swi, sym_handle *sym,
                                                      void *_new_mod )
/*********************************************************************/
{
    mod_info        *new_mod = _new_mod;
    sym_info        sinfo;
    file_info       *sym_file;
    rtn_info        *new_rtn;
    int             rtn_count;
    int             name_len;
    int             sym_size;
    int             demangle_type;

    if( swi != SWI_SYMBOL ) {
        return( WR_CONTINUE );
    }
    SymInfo( sym, NULL, &sinfo );
    if( sinfo.kind != SK_CODE && sinfo.kind != SK_PROCEDURE ) {
        return( WR_CONTINUE );
    }
    sym_file = loadFileInfo( new_mod, sym );
    name_len = SymName( sym, NULL, SN_DEMANGLED, NULL, 0 );
    if( name_len == 0 ) {
        name_len = SymName( sym, NULL, SN_SOURCE, NULL, 0 );
        demangle_type = SN_SOURCE;
    } else {
        demangle_type = SN_DEMANGLED;
    }
    new_rtn = ProfCAlloc( sizeof( rtn_info ) + name_len );
    SymName( sym, NULL, demangle_type, new_rtn->name, name_len + 1 );
    sym_size = DIPHandleSize( HK_SYM );
    new_rtn->sh = ProfAlloc( sym_size );
    memcpy( new_rtn->sh, sym, sym_size );
    rtn_count = sym_file->rtn_count;
    sym_file->rtn_count++;
    sym_file->routine = ProfRealloc( sym_file->routine, sym_file->rtn_count * sizeof( pointer ) );
    sym_file->routine[rtn_count] = new_rtn;
    return( WR_CONTINUE );
}
示例#6
0
STATIC void procImageBlock( samp_data *data, bool main_exe )
/**********************************************************/
{
    image_info      *new_image;
    int             name_len;
    int             image_index;

    name_len = strlen( data->code.name ) + 1;
    new_image = ProfCAlloc( sizeof(image_info) );
    image_index = CurrSIOData->image_count;
    CurrSIOData->image_count++;
    CurrSIOData->images = ProfRealloc( CurrSIOData->images,
                                     CurrSIOData->image_count*sizeof(pointer));
    CurrSIOData->images[image_index] = new_image;
    CurrSIOData->curr_image = new_image;
    new_image->name = ProfAlloc( name_len );
    memcpy( new_image->name, data->code.name, name_len );
    new_image->overlay_table.mach.segment = data->code.ovl_tab.segment;
    new_image->overlay_table.mach.offset = data->code.ovl_tab.offset;
    new_image->time_stamp = data->code.time_stamp;
    new_image->main_load = main_exe;
}
示例#7
0
wp_asmline * WPGetAsmLoc( wp_asmfile * wpasm_file, int row,
                                    int * group_loc, int * row_loc )
/******************************************************************/
{
    wp_asmline *    asm_line;
    int             asm_row;
    int             asm_group;

    asm_group = row / MAX_ASM_LINE_INDEX;
    asm_row = row - (asm_group * MAX_ASM_LINE_INDEX);
    if( asm_group != 0 && asm_row == 0 && asm_group > wpasm_file->asm_groups ) {
        wpasm_file->asm_data = ProfRealloc( wpasm_file->asm_data,
                                     sizeof(wp_asm_groups)*(asm_group+1) );
        wpasm_file->asm_data[asm_group].asm_lines
                 = ProfAlloc( MAX_ASM_LINE_SIZE );
        wpasm_file->asm_groups++;
    }
    *group_loc = asm_group;
    *row_loc = asm_row;
    asm_line = &wpasm_file->asm_data[asm_group].asm_lines[asm_row];
    return( asm_line );
}
示例#8
0
extern void AddPath( path_list **path_var, char *path_data )
/**********************************************************/
{
    char            path[_MAX_PATH];
    path_list *     path_tail;
    path_list *     path_item;
    int             index;

    if( path_data == NULL ) return;
    path_tail = *path_var;
    for(;;) {
        if( *path_data == '\0' ) break;
        index = 0;
        while( *path_data != NULLCHAR ) {
            if( *path_data == LIST_SEPARATOR ) break;
            path[index++] = *path_data++;
        }
        if( index != 0 ) {
            if( path[index-1] != PATH_SEPARATOR ) {
                path[index++] = PATH_SEPARATOR;
            }
            path_item = ProfAlloc( sizeof(path_list)+index+1 );
            memcpy( path_item->path_data, path, index );
            path_item->path_data[index] = NULLCHAR;
            if( path_tail == NULL ) {
                path_item->next = path_item;
            } else {
                path_item->next = path_tail->next;
                path_tail->next = path_item;
            }
            path_tail = path_item;
        }
        if( *path_data == LIST_SEPARATOR ) {
            ++path_data;
        }
    }
    *path_var = path_tail;
}
示例#9
0
void DlgAbout( void )
/*******************/
{
    char        *about_data;
    char        *about_rover;
    size_t      about_len;
    int         index;

    about_len = 0;
    for( index = 0; index < AboutSize; ++index ) {
        about_len += strlen( AboutMessage[index] ) + 1;
    }
    about_data = ProfAlloc( about_len+1 );
    about_rover = about_data;
    for( index = 0; index < AboutSize; ++index ) {
        about_len = strlen( AboutMessage[index] );
        memcpy( about_rover, AboutMessage[index], about_len );
        about_rover += about_len;
        *about_rover++ = '\r';
    }
    *about_rover = NULLCHAR;
    WndDisplayMessage( about_data, LIT( About_WPROF ), GUI_INFORMATION );
    ProfFree( about_data );
}
示例#10
0
STATIC void calcAggregates( void )
/********************************/
{
    unsigned            index;
    unsigned            index2;
    int                 cmp_result;
    unsigned            *sorted_idx;
    address             ***sorted_vect;
    massgd_sample_addr  **massgd_data;
//    unsigned            mbuckets;
    unsigned            curr_mbucket;
    unsigned            curr_midx;
    thread_data         *thd;
    unsigned            buckets;
    unsigned            base;
    unsigned            best;
    unsigned            end;
    massgd_sample_addr  *curr;

    ClearMassaged( CurrSIOData );
    buckets = 0;
    for( thd = CurrSIOData->samples; thd != NULL; thd = thd->next ) {
        buckets += RAW_BUCKET_IDX( thd->end_time - thd->start_time ) + 1;
    }
    sorted_idx = ProfCAlloc( buckets * sizeof( *sorted_idx ) );
    sorted_vect = ProfAlloc( buckets * sizeof(*thd->raw_bucket) );
    base = 0;
    for( thd = CurrSIOData->samples; thd != NULL; thd = thd->next ) {
        end = RAW_BUCKET_IDX( thd->end_time - thd->start_time ) + 1;
        for( index = 0; index < end; ++index, ++base ) {
            sorted_vect[base] = ProfAlloc( MAX_RAW_BUCKET_INDEX * sizeof( **sorted_vect ) );
            for( index2 = 0; index2 < MAX_RAW_BUCKET_INDEX; ++index2 ) {
                sorted_vect[base][index2]
                    = &thd->raw_bucket[index][index2];
            }
            qsort( sorted_vect[base], MAX_RAW_BUCKET_INDEX, sizeof(**sorted_vect), rawSampCmp );
        }
    }
    /* skip over all the 0:0 samples */
    for( index = 0; index < buckets; ++index ) {
        index2 = 0;
        for( ;; ) {
            if( index2 >= MAX_RAW_BUCKET_INDEX ) break;
            if( !(sorted_vect[index][index2]->mach.segment == 0
             && sorted_vect[index][index2]->mach.offset == 0) ) break;
            ++index2;
        }
        sorted_idx[index] = index2;
    }
    curr = NULL;
    curr_mbucket = 0;
    curr_midx = -1;
//    mbuckets = 1;
    massgd_data = ProfAlloc( sizeof( *massgd_data ) );
    massgd_data[0] = ProfCAlloc( MAX_MASSGD_BUCKET_SIZE );
    for( ;; ) {
        best = -1U;
        for( index = 0; index < buckets; ++index ) {
            index2 = sorted_idx[index];
            if( index2 >= MAX_RAW_BUCKET_INDEX ) continue;
            if( best == -1U ) best = index;
            cmp_result = AddrCmp( sorted_vect[index][index2],
                                  sorted_vect[best][sorted_idx[best]] );
            if( cmp_result < 0 ) best = index;
        }
        if( best == -1U ) break;
        if( curr == NULL || AddrCmp( sorted_vect[best][sorted_idx[best]], curr->raw ) != 0 ) {
            if( ++curr_midx >= MAX_MASSGD_BUCKET_INDEX ) {
                ++curr_mbucket;
                massgd_data = ProfRealloc( massgd_data, (curr_mbucket+1) * sizeof(*massgd_data) );
                massgd_data[curr_mbucket] = ProfCAlloc( MAX_MASSGD_BUCKET_SIZE );
                curr_midx = 0;
            }
            curr = &massgd_data[curr_mbucket][curr_midx];
            curr->raw = sorted_vect[best][sorted_idx[best]];
        }
        curr->hits++;
        sorted_idx[best]++;
    }

    CurrSIOData->massaged_sample = massgd_data;
    CurrSIOData->number_massaged = 1 + curr_midx
                + (curr_mbucket * (unsigned long)MAX_MASSGD_BUCKET_INDEX);
    CurrSIOData->massaged_mapped = true;
    for( index = 0; index < buckets; ++index ) {
        ProfFree( sorted_vect[index] );
    }
    ProfFree( sorted_vect );
    ProfFree( sorted_idx );
}
示例#11
0
STATIC void loadImageInfo( image_info * curr_image )
/**************************************************/
{
    int             name_len;
    int             object_file;
    int             sym_file;
    struct stat     file_status;

    sym_file = -1;
    object_file = -1;
    curr_image->dip_handle = NO_MOD;
    if( curr_image->sym_deleted ) {
    } else if( curr_image->sym_name != NULL ) {
        sym_file = open( curr_image->sym_name, O_RDONLY|O_BINARY );
        if( sym_file != -1 ) {
            curr_image->dip_handle = WPDipLoadInfo( sym_file,
                                       curr_image->sym_name, curr_image,
                                       sizeof(image_info), DIP_PRIOR_MIN, DIP_PRIOR_MAX );
        }
    } else {
        name_len = strlen( curr_image->name ) + 1;
        memcpy( FNameBuff, curr_image->name, name_len );
        ReplaceExt( FNameBuff, ".sym" );
        name_len = strlen( FNameBuff ) + 1;
        curr_image->sym_name = ProfAlloc( name_len );
        memcpy( curr_image->sym_name, FNameBuff, name_len );
        sym_file = open( curr_image->sym_name, O_RDONLY|O_BINARY );
        if( sym_file != -1 ) {
            curr_image->dip_handle = WPDipLoadInfo( sym_file,
                                      curr_image->sym_name, curr_image,
                                      sizeof(image_info), DIP_PRIOR_MIN, DIP_PRIOR_MAX );
        }
        if( curr_image->dip_handle == NO_MOD ) {
            ProfFree( curr_image->sym_name );
            curr_image->sym_name = NULL;
        }
    }
    object_file = open( curr_image->name, O_RDONLY|O_BINARY );
    if( object_file == -1 ) {
        curr_image->exe_not_found = true;
        if( curr_image->main_load ) {
            ErrorMsg( LIT( Exe_Not_Found ), curr_image->name );
        }
    } else if( curr_image->time_stamp == 0 ) {
        /*
           If sample timestamp is 0, the sampler couldn't figure out
           the right value. Assume it's OK.
        */
    } else if( fstat( object_file, &file_status ) == 0 ) {
        /* QNX creation dates and time stamps tend to be 1 */
        /* unit different, so do not test for equality */
        if( file_status.st_mtime - curr_image->time_stamp > 1 ) {
            curr_image->exe_changed = true;
            if( curr_image->main_load ) {
                ErrorMsg( LIT( Exe_Has_Changed ), curr_image->name );
            }
        }
    }
    if( curr_image->dip_handle == NO_MOD && !curr_image->sym_deleted
     && object_file != -1 ) {
        curr_image->dip_handle = WPDipLoadInfo( object_file,
                                   curr_image->name, curr_image,
                                   sizeof(image_info), DIP_PRIOR_MIN, DIP_PRIOR_MAX );
    }
    if( curr_image->dip_handle == NO_MOD ) {
        if( sym_file != -1 ) {
            close( sym_file );
        }
        if( object_file != -1 ) {
            close( object_file );
        }
    }
    initModuleInfo( curr_image );
    if( curr_image->dip_handle != NO_MOD ) {
        WalkModList( curr_image->dip_handle, &loadModuleInfo, curr_image );
    }
}
示例#12
0
STATIC bool readSampleFile( void )
/********************************/
{
    file_handle             fh;
    uint_16                 size;
    void                    *buff;
    int                     buff_len;
    off_t                   start_position;
    bool                    main_exe;
    samp_block_prefix       prefix;
    samp_block_prefix       *next_prefix;

/* we can add error checking for things like */
/**/
/*    - number of samples match the info # of samples */
/*    - main exe load if there is an overlay table */
/**/
    fh = CurrSIOData->fh;
    start_position = lseek( fh, CurrSIOData->header.sample_start, SEEK_SET );
    if( start_position == (off_t) -1 ) {
        ErrorMsg( LIT( Smp_File_IO_Err ), CurrSIOData->samp_file_name );
        return( false );
    }
    if( read( fh, &prefix, SIZE_PREFIX ) != SIZE_PREFIX ) {
        ErrorMsg( LIT( Smp_File_IO_Err ), CurrSIOData->samp_file_name );
        return( false );
    }
    buff = ProfAlloc( SIZE_DATA );
    buff_len = SIZE_DATA;
    main_exe = false;
    while( prefix.kind != SAMP_LAST ) {
        size = prefix.length;
        if( buff_len < size ) {
            buff = ProfRealloc( buff, size );
            buff_len = size;
        }
        /* reads data & next prefix */
        if( BigRead( fh, buff, size ) != size ) {
            ErrorMsg( LIT( Smp_File_IO_Err ), CurrSIOData->samp_file_name );
            ProfFree( buff );
            return( false );
        }
        next_prefix = (void *)( ((char *) buff) + ( size - SIZE_PREFIX ));

        /* if we're reading a sample record from a callgraph sample */
        /* file, the next record should contain callgraph information */
        /* which we will also want stored in memory for processing */
        /* 16-jul-92 CMS */

//        if( CallGraph && prefix.kind == SAMP_SAMPLES &&
//                         next_prefix->kind == SAMP_CALLGRAPH ) {
//            size = next_prefix->length;
//            /* reads callgraph data & next prefix   */
//            if( BigRead( fh, next_prefix, size ) != size ) {
//                errorIO();
//                ProfFree( buff );
//                ErrorMsg( LIT( Smp_File_IO_Err ), CurrSIOData->samp_file_name );
//                return( false );
//            }
//            next_prefix = (void *)( ((char *) next_prefix) + ( size - SIZE_PREFIX ));
//        }

        switch( prefix.kind ) {
        case SAMP_INFO:
            procInfoBlock( prefix.tick, buff );
            break;
        case SAMP_SAMPLES:
            if( !procSampleBlock( prefix.tick, prefix.length, buff ) ) {
                return( false );
            }
            break;
        case SAMP_MARK:
            procMarkBlock( prefix.tick, buff );
            break;
        case SAMP_OVL_LOAD:
            procOverlayBlock( prefix.tick, buff );
            break;
        case SAMP_ADDR_MAP:
            procAddrBlock( prefix.length, buff );
            break;
        case SAMP_MAIN_LOAD:
            main_exe = true;
            /* fall through */
        case SAMP_CODE_LOAD:
            procImageBlock( buff, main_exe );
            main_exe = false;
            break;
        case SAMP_REMAP_SECTION:
            procRemapBlock( prefix.tick, prefix.length, buff );
            break;
        case SAMP_CALLGRAPH:
//            printf( "sample callgraph\n" );
            break;
        }
        prefix = *next_prefix;
    }
    ProfFree( buff );
    return( true );
}
示例#13
0
STATIC bool procSampleBlock( clicks_t tick, uint_16 total_len,
                                              samp_data *data )
/*************************************************************/
{
    thread_id   thread;
    unsigned    data_index;
    unsigned    index;
    unsigned    index2;
    unsigned    count;
    unsigned    buckets;
    clicks_t    end_tick;
    ldiv_t      div_result;
    thread_data *thd;
    thread_data **owner;
    address     *samp;

    thread = data->sample.thread_id;
    total_len -= offsetof( samp_block, d.sample );
    count = total_len / sizeof( samp_address );
    CurrSIOData->total_samples += count;
    end_tick = tick + count;
    owner = &CurrSIOData->samples;
    for( ;; ) {
        thd = *owner;
        if( thd == NULL ) {
            thd = ProfAlloc( sizeof( *thd ) );
            *owner = thd;
            thd->next = NULL;
            thd->thread = thread;
            thd->start_time = tick;
            thd->end_time = end_tick;
            buckets = RAW_BUCKET_IDX( count ) + 1;
            thd->raw_bucket = ProfAlloc( buckets * sizeof( *thd->raw_bucket ) );
            for( index = 0; index < buckets; ++index ) {
                thd->raw_bucket[index] = ProfCAlloc( MAX_RAW_BUCKET_SIZE );
            }
            break;

        }
        if( thd->thread == thread )
            break;
        owner = &thd->next;
    }
    if( end_tick > thd->end_time ) {
        index = RAW_BUCKET_IDX( thd->end_time - thd->start_time ) + 1;
        buckets = RAW_BUCKET_IDX( end_tick - thd->start_time ) + 1;
        if( buckets > index ) {
            thd->raw_bucket = ProfRealloc( thd->raw_bucket, buckets * sizeof( *thd->raw_bucket ) );
            for( ; index < buckets; ++index ) {
                thd->raw_bucket[index] = ProfCAlloc( MAX_RAW_BUCKET_SIZE );
            }
        }
        thd->end_time = end_tick;
    }


    div_result = ldiv( tick - thd->start_time, MAX_RAW_BUCKET_INDEX );
    index = div_result.quot;
    index2 = div_result.rem;
    data_index = 0;
    while( count > 0 ) {
        samp = &thd->raw_bucket[index][index2];
        samp->mach.segment = data->sample.sample[data_index].segment;
        samp->mach.offset  = data->sample.sample[data_index].offset;
        if( ++index2 >= MAX_RAW_BUCKET_INDEX ) {
            index2 = 0;
            ++index;
        }
        ++data_index;
        --count;
    }
    return( true );
}
示例#14
0
wp_asmfile *WPAsmOpen( sio_data * curr_sio, int src_row, bool quiet )
/*******************************************************************/
{
    wp_asmfile *        wpasm_file;
    cue_handle *        ch;
    cue_handle *        ch2;
    mod_info *          curr_mod;
    file_info *         curr_file;
    massgd_sample_addr * samp_data;
    wp_asmline *        asm_line;
    mod_handle          mh;
    file_handle         fh;
    address             addr;
    cue_fileid          fid;
    search_result       cue_find;
    int                 rows;
    int                 asm_group;
    int                 asm_row;
    int                 file_index;
    int                 addr_cmp;
    clicks_t            addr_tick_index;

    quiet=quiet;
    ch = alloca( DIPHandleSize( HK_CUE ) );
    ch2 = alloca( DIPHandleSize( HK_CUE ) );
    curr_file = curr_sio->curr_file;
    curr_mod = curr_sio->curr_mod;
    if( curr_file->fid == 0 || LineCue( curr_mod->mh, curr_sio->curr_file->fid,
                                        src_row, 0, ch2 ) == SR_NONE ) {
        ch2 = NULL;
    }
    fh = ExeOpen( curr_sio->curr_image->name );
    if( fh == -1 ) {
        ErrorMsg( LIT( Exe_Not_Found ), curr_sio->curr_image->name );
        return( NULL );
    }
    wpasm_file = ProfCAlloc( sizeof(wp_asmfile) );
    curr_sio->asm_file = wpasm_file;
    wpasm_file->asm_buff = ProfAlloc( MAX_ASM_BUFF_LEN );
    wpasm_file->asm_buff_len = MAX_ASM_BUFF_LEN;
    SetNumBytes( 0 );
    SetExeFile( fh, false );
    wpasm_file->fh = fh;
    addr = ModAddr( curr_mod->mh );
    SetExeOffset( addr );
    wpasm_file->max_time = 0;
    addr_tick_index = curr_mod->first_tick_index - 1;
    samp_data = WPGetMassgdSampData( curr_sio, addr_tick_index++ );
    wpasm_file->asm_data = ProfAlloc( sizeof(wp_asm_groups) );
    wpasm_file->asm_data[0].asm_lines = ProfAlloc( MAX_ASM_LINE_SIZE );
    wpasm_file->asm_groups = 0;
    rows = 0;
    for( ;; ) {
        mh = curr_mod->mh;
        if( EndOfSegment()
            || AddrMod( addr, &mh ) == SR_NONE || mh != curr_mod->mh ) break;
        cue_find = (AddrCue( curr_mod->mh, addr, ch ) == SR_EXACT);
        if( ch2 != NULL && CueCmp( ch, ch2 ) == 0 ) {
            wpasm_file->entry_line = rows;
            ch2 = NULL;
        }
        asm_line = WPGetAsmLoc( wpasm_file, rows, &asm_group, &asm_row );
        if( cue_find ) {
            asm_line->source_line = true;
            asm_line->u.src.line = CueLine( ch );
            asm_line->u.src.src_file = NULL;
            if( !curr_file->unknown_file ) {
                fid = CueFileId( ch );
                file_index = 0;
                while( file_index < curr_mod->file_count ) {
                    curr_file = curr_mod->mod_file[file_index];
                    if( curr_file->fid == fid ) {
                        asm_line->u.src.src_file =
                                FOpenSource( curr_file->name, mh, fid );
                        break;
                    }
                    file_index++;
                }
            }
            rows++;
            asm_line = WPGetAsmLoc( wpasm_file, rows, &asm_group, &asm_row );
        }
        asm_line = &wpasm_file->asm_data[asm_group].asm_lines[asm_row];
        asm_line->source_line = false;
        asm_line->u.asm_line.addr = addr;
        asm_line->u.asm_line.tick_count = 0;
        for( ;; ) {
            if( samp_data == NULL ) break;
            addr_cmp = AddrCmp( &addr, samp_data->raw );
            if( addr_cmp < 0 ) break;
            if( addr_cmp == 0 ) {
                asm_line->u.asm_line.tick_count = samp_data->hits;
                if( asm_line->u.asm_line.tick_count > wpasm_file->max_time ) {
                    wpasm_file->max_time = asm_line->u.asm_line.tick_count;
                }
            }
            samp_data = WPGetMassgdSampData( curr_sio, addr_tick_index++ );
        }
        rows++;
        CodeAdvance( &addr );
    }
    WPGetAsmLoc( wpasm_file, rows, &asm_group, &asm_row );
    wpasm_file->asm_data[asm_group].asm_lines =
            ProfRealloc( wpasm_file->asm_data[asm_group].asm_lines,
                         sizeof(wp_asmline)*(asm_row+1) );
    wpasm_file->asm_rows = rows;
    return( wpasm_file );
}