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 ); }
/* * Adds a destructor to a block. */ dip_status VMAddDtor( imp_image_handle *ii, virt_mem start, void ( *dtor )( imp_image_handle *ii, void *user ), void *user ) { unsigned dir_idx; unsigned pg_idx; virt_page *pg; /* locate the block. */ dir_idx = GET_DIR( start ); if( ii->virt[dir_idx] != NULL ) { pg_idx = GET_PAGE( start ); pg = ii->virt[dir_idx][pg_idx]; if( pg != NULL ) { /* create a new dtor node and link it in */ vm_dtor *node = DCAlloc( sizeof( *node ) ); if( node != NULL ) { node->user = user; node->dtor = dtor; node->next = pg->block->first_dtor; pg->block->first_dtor = node; return( DS_OK ); } return( DS_ERR | DS_NO_MEM ); } } return( DS_ERR | DS_FAIL ); }
dip_status InitDemand( imp_image_handle *ii ) { struct walk_demand d; d.max_size = 0; MyWalkModList( ii, WlkDmnd, &d ); if( d.max_size >= (0x10000UL - sizeof( demand_ctrl )) ) { DCStatus( DS_ERR|DS_INFO_INVALID ); return( DS_ERR|DS_INFO_INVALID ); } if( d.max_size <= LastDmndSize ) return( DS_OK ); if( LastDemand != NULL ) { Unload( LastDemand ); DCFree( LastDemand ); } LastDmndSize = d.max_size; LastDemand = DCAlloc( _demand_size( d.max_size ) ); if( LastDemand == NULL ) { DCStatus( DS_ERR|DS_NO_MEM ); return( DS_ERR|DS_NO_MEM ); } LastDemand->link = NULL; LastDemand->owner = NULL; LastDemand->clear = NULL; LastDemand->locks = 0; return( DS_OK ); }
static int InitPageDir( imp_image_handle *iih, unsigned dir_idx ) { iih->virt[dir_idx] = DCAlloc( sizeof( virt_page * ) * DIR_SIZE ); if( iih->virt[dir_idx] == NULL ) { DCStatus( DS_ERR | DS_NO_MEM ); return( 0 ); } memset( iih->virt[dir_idx], 0, sizeof( virt_page * ) * DIR_SIZE ); return( 1 ); }
dip_status VMInit( imp_image_handle *iih, unsigned long size ) { iih->vm_dir_num = BLOCK_FACTOR( size, DIR_SIZE * VM_PAGE_SIZE ); iih->virt = DCAlloc( iih->vm_dir_num * sizeof( *iih->virt ) ); if( iih->virt == NULL ) { DCStatus( DS_ERR | DS_NO_MEM ); return( DS_ERR | DS_NO_MEM ); } memset( iih->virt, 0, iih->vm_dir_num * sizeof( *iih->virt ) ); return( DS_OK ); }
static bool ACueFile( void *_info, dr_line_file *curr ) /*****************************************************/ { file_walk_name *info = _info; bool cont; int i; cont = true; if( info->index == curr->index ) { if( curr->name != NULL ) { if( curr->dir != 0) { for( i = 0; i < info->num_dirs; i++ ) { if( info->dirs[i].index == curr->dir ) { break; } } if( i < info->num_dirs ) { info->ret = DCAlloc( strlen( curr->name ) + strlen( info->dirs[i].name ) + 2 ); strcpy( info->ret, info->dirs[i].name ); strcat( info->ret, "/"); strcat( info->ret, curr->name ); } else { /* This should be an error, but it isn't fatal as we should * never get here in practice. */ info->ret = DCAlloc( strlen( curr->name ) + 1 ); strcpy( info->ret, curr->name ); } } else { info->ret = DCAlloc( strlen( curr->name ) + 1 ); strcpy( info->ret, curr->name ); } } else { info->ret = NULL; } cont = false; } return( cont ); }
/* * 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 ); }
static bool ACueDir( void *_info, dr_line_dir *curr ) /***************************************************/ { file_walk_name *info = _info; if( info != NULL ) { info->dirs = DCRealloc( info->dirs, sizeof( dr_line_dir ) * (info->num_dirs + 1) ); info->dirs[info->num_dirs].index = curr->index; info->dirs[info->num_dirs].name = DCAlloc( strlen( curr->name ) + 1 ); strcpy( info->dirs[info->num_dirs].name, curr->name ); info->num_dirs++; } return( true ); }
static dip_status LoadMapping( imp_image_handle *ii ) { cv_directory_entry *cde; cv_sst_seg_map *map; size_t size; cde = FindDirEntry( ii, IMH_GBL, sstSegMap ); if( cde == NULL ) return( DS_ERR|DS_INFO_INVALID ); map = VMBlock( ii, cde->lfo, cde->cb ); if( map == NULL ) return( DS_ERR|DS_FAIL ); size = map->cSegLog * sizeof( map->segdesc[0] ); ii->mapping = DCAlloc( size ); if( ii->mapping == NULL ) return( DS_ERR|DS_NO_MEM ); map = VMBlock( ii, cde->lfo, cde->cb ); /* malloc might have unloaded */ memcpy( ii->mapping, &map->segdesc[0], size ); ii->map_count = map->cSegLog; return( DS_OK ); }
static bool AddBase( drmem_hdl base, inh_vbase **lnk ) /****************************************************/ //if base not in list add return false { inh_vbase *cur; while( (cur = *lnk) != NULL ){ if( base <= cur->base ){ if( base == cur->base ){ return( false ); } break; } lnk = &cur->next; } cur = DCAlloc( sizeof( *cur ) ); cur->base = base; cur->next = *lnk; *lnk = cur; return( true ); }
static bool AddBase( dr_handle base, inh_vbase **lnk ) /****************************************************/ //if base not in list add return FALSE { inh_vbase *cur; while( (cur = *lnk) != NULL ) { if( base <= cur->base ) { if( base == cur->base ) { return( FALSE); } break; } lnk = &cur->next; } cur = DCAlloc( sizeof( *cur ) ); cur->base = base; cur->next = *lnk; *lnk = cur; return( TRUE ); }
static void *HunkAlloc( imp_image_handle *ii, size_t size ) { exp_hunk *hunk; size_t alloc; size = ROUND_UP( size, sizeof( void * ) ); hunk = ii->hunks; if( hunk == NULL || size > hunk->left ) { alloc = HUNK_SIZE; if( alloc < size ) alloc = size; hunk = DCAlloc( (sizeof( *hunk ) - HUNK_SIZE) + alloc ); if( hunk == NULL ) return( NULL ); hunk->next = ii->hunks; ii->hunks = hunk; hunk->left = alloc; } hunk->left -= size; return( &hunk->data[ hunk->left ] ); }
seg_cue *InitSegCue( cue_list *ctl, addr_seg seg, addr_off offset ) /*****************************************************************/ /* Keep in asending order seg:offset */ { seg_cue *curr; seg_cue **lnk; for( lnk = &ctl->head; (curr = *lnk) != NULL; lnk = &curr->next ) { if( seg < curr->seg || ( seg == curr->seg && offset < curr->low ) ) { break; } } curr = DCAlloc( sizeof( *curr ) ); curr->seg = seg; curr->low = offset; curr->high = offset; curr->count = 0; curr->head = NULL; curr->next = *lnk; *lnk = curr; return( curr ); }
static bool ModFill( void *_mod, dr_handle mod_handle ) /*****************************************************/ // fill in mod_handle for dip to dwarf mod map // pick up general info about mod while here for later calls { mod_list *mod = _mod; char fname[MAX_PATH]; char *name; char *path; dr_handle cu_tag; dr_model model; mod_info *modinfo; modinfo = NextModInfo( mod ); modinfo->mod_handle = mod_handle; InitAddrSym( modinfo->addr_sym ); modinfo->addr_size = DRGetAddrSize( mod_handle ); cu_tag = DRGetCompileUnitTag( mod_handle ); modinfo->cu_tag = cu_tag; modinfo->stmts = DRGetStmtList( cu_tag ); path = DRGetName( cu_tag ); if( path != NULL ) { GetModName( path, fname ); DCFree( path ); name = DCAlloc( strlen( fname ) + 1 ); strcpy( name, fname ); } else { name = NULL; } path = DRGetProducer( cu_tag ); if( path != NULL ) { df_ver version; if( strcmp( path, "V2.0 WATCOM" ) == 0 ) { version = VER_V3; } else if( strcmp( path, "V1.0 WATCOM" ) == 0 ) { version = VER_V2; } else if( strcmp( path, "WATCOM" ) == 0 ) { version = VER_V1; } else { version = VER_NONE; } if( mod->version == VER_NONE ) { mod->version = version; } else if( mod->version != version ) { mod->version = VER_ERROR; } DCFree( path ); } modinfo->name = name; model = DRGetMemModelAT( cu_tag ); if( DCCurrMAD() == MAD_X86 ) { switch( model ) { case DR_MODEL_NONE: case DR_MODEL_FLAT: modinfo->is_segment = FALSE; break; default: modinfo->is_segment = TRUE; break; } } else { modinfo->is_segment = FALSE; } modinfo->model = model; modinfo->lang = DRGetLanguageAT( cu_tag ); modinfo->dbg_pch = DRDebugPCHDef( cu_tag ); modinfo->has_pubnames = FALSE; return( TRUE ); }
/* * 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 ); }
/* * 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 ); }
/* * 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 ); }
/* * 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; unsigned long num_links; unsigned long first_link; unsigned long last_link; unsigned d; unsigned num; dword *lnk; dword **lnk_tbl; unsigned long off; dip_status ok; last_link = 0; first_link = ~0; num_links = 1; for( blk = inf->mod_info; blk != NULL; blk = blk->next ) { count = 0; for( mod_off = 0; mod_off < blk->size; mod_off += sizeof( mod_info ) + mod->name[0] ) { ++count; mod = (mod_info *)((byte *)blk->info + mod_off); } 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 += sizeof( mod_info ) + mod->name[0] ) { tbl->mod_off[count++] = mod_off; mod = (mod_info *)((byte *)blk->info + mod_off); for( d = DMND_FIRST; d < DMND_NUM; ++d ) { if( inf->ctl->v2 ) { if( mod->di[d].u.size != 0 ) ++num_links; } else { if( mod->di[d].u.entries != 0 ) { num_links = mod->di[d].info_off; if( num_links < first_link ) { first_link = num_links; } num_links += mod->di[d].u.entries * sizeof(dword); if( num_links > last_link ) { last_link = num_links; } } } } } } if( !inf->ctl->v2 ) { off = first_link + adjust; if( DCSeek( inf->ctl->sym_file, off, DIG_ORG) != off ) { DCStatus( DS_ERR|DS_FSEEK_FAILED ); return( DS_ERR|DS_FSEEK_FAILED ); } num_links = (last_link - first_link) / sizeof( dword ) + 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( ;; ) { if( num_links == 0 ) break; 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; --num_links; } return( DS_OK ); }
unsigned DIPENTRY DIPImpCueFile( imp_image_handle *ii, imp_cue_handle *ic, char *buff, unsigned max ) /********************************************************************/ { char *name; char *dir_path; file_walk_name wlk; unsigned len; unsigned dir_len; im_idx imx; dr_handle stmts; dr_handle cu_handle; int i; imx = ic->imx; DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */ stmts = ii->mod_map[imx].stmts; if( stmts == 0 ) { DCStatus( DS_FAIL ); return( 0 ); } cu_handle = ii->mod_map[imx].cu_tag; if( cu_handle == 0 ) { DCStatus( DS_FAIL ); return( 0 ); } wlk.index = ic->fno; wlk.ret = NULL; wlk.num_dirs = 0; wlk.dirs = NULL; DRWalkLFiles( stmts, ACueFile, &wlk, ACueDir, &wlk ); name = wlk.ret; // Free directory and file table information for( i = 0; i < wlk.num_dirs; i++) DCFree(wlk.dirs[i].name); DCFree(wlk.dirs); if( name == NULL ) { DCStatus( DS_FAIL ); return( 0 ); } // If compilation unit has a DW_AT_comp_dir attribute, we need to // stuff that in front of the file pathname, unless that is absolute dir_len = DRGetCompDirBuff( cu_handle, NULL, 0 ); if( (dir_len > 1) && IsRelPathname( name ) ) { // Ignore empty comp dirs if( max == 0 ) { len = NameCopy( buff, name, max ) + dir_len; } else { dir_path = DCAlloc( dir_len ); if( dir_path == NULL ) { DCStatus( DS_FAIL ); return( 0 ); } DRGetCompDirBuff( cu_handle, dir_path, dir_len ); len = NameCopy( buff, dir_path, max ); DCFree( dir_path ); if( max > len + 1 ) { len += NameCopy( buff + len, "/", 1 + 1 ); len += NameCopy( buff + len, name, max - len ); } } } else { len = NameCopy( buff, name, max ); } DCFree( name ); return( len ); }
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] ); }
/* * 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 ); }
/* * Load debug info if it's in the HLL/CV format. */ dip_status DIGENTRY DIPImpLoadInfo( dig_fhandle h, imp_image_handle *ii ) { dip_status rc; /* Init the module handle. */ memset( ii, 0, sizeof( *ii ) ); ii->mad = MAD_X86; /* No known non-x86 support */ ii->sym_file = h; ii->is_32bit = 1; ii->format_lvl = HLL_LVL_NB04; ii->next_image = ImageList; ImageList = ii; /* Read basic HLL and executable image bits. */ rc = FindHLL( ii ); if( rc == DS_OK ) { rc = VMInit( ii, ii->size ); } /* Make sure we've got segment mappings. (FIXME: scan module headers) */ if( rc == DS_OK && !ii->segments ) { ii->seg_count = 2; ii->segments = DCAlloc( sizeof( hllinfo_seg ) * ii->seg_count ); if( ii->segments != NULL ) { memset( ii->segments, 0, sizeof( hllinfo_seg ) * ii->seg_count ); ii->segments[0].is_executable = 1; ii->segments[0].map.segment = 1; ii->segments[1].map.segment = 2; ii->segments[0].size = ii->segments[1].size = 0x00400000; /* 4MB */ ii->segments[0].address = ii->segments[1].address = 0; } else{ rc = DS_ERR | DS_NO_MEM; } } /* Locate global types. If none, we've types per module. */ if( rc == DS_OK ) { /* FIXME hll_debug_dir *cde; cde = FindDirEntry( ii, IMH_GBL, sstGlobalTypes ); if( cde != NULL ) { hdr = VMBlock( ii, cde->lfo, sizeof( *hdr ) ); if( hdr == NULL ) { Cleanup( ii ); return( DS_ERR | DS_FAIL ); } ii->types_base = cde->lfo + offsetof( cv_sst_global_types_header, offType ) + hdr->cType * sizeof( hdr->offType[0] ); } */ } /* We're done - clean up on failure. */ if( rc != DS_OK ) { DCStatus( rc ); Cleanup( ii ); } return( rc ); }
/* * 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 ); }
void *InfoLoad( imp_image_handle *ii, imp_mod_handle im, unsigned item, unsigned entry, void (*clear)(void *, void *) ) { demand_ctrl *section; demand_info *info; section_info *sect; unsigned long tmpoff; pointer_int *lnk; unsigned size; ++TimeStamp; if( TimeStamp == 0 ) { /* TimeStamp wrapped */ TimeStamp = 1; for(section = DemandList; section != NULL; section = section->link) { section->time_stamp = 0; } } info = &ModPointer( ii, im )->di[ item ]; if( entry >= info->u.entries ) return( NULL ); entry += info->info_off; sect = FindInfo( ii, im ); lnk = &GET_LINK( sect, entry ); if( IS_RESIDENT( *lnk ) ) { section = MK_DMND_PTR( *lnk ); } else { /* section not loaded */ size = DMND_SIZE( sect, entry ); if( (LastDemand->owner == NULL || LastDemand->size < size) && LastDemand->locks == 0 ) { /* keep largest section in LastDemand */ section = LastDemand; Unload( LastDemand ); } else { /* allocate some memory */ section = DCAlloc( _demand_size( size ) ); if( section == NULL ) { if( LastDemand->locks != 0 ) return( NULL ); /* no memory, use last chance */ section = LastDemand; Unload( LastDemand ); } } tmpoff = MK_DMND_OFFSET( *lnk ); if( InfoRead( sect, tmpoff, size, section->buff ) != DS_OK ) { if( section != LastDemand ) DCFree( section ); return( NULL ); } section->size = size; section->locks = 0; section->clear = clear; section->owner = lnk; section->save = *lnk; *lnk = STASH_DMND_PTR( section ); if( section != LastDemand ) { section->link = DemandList; DemandList = section; } } section->time_stamp = TimeStamp; /* for removal priority */ section->locks++; return( section->buff ); }
static bool ModFill( void *_mod, drmem_hdl mod_handle ) /*****************************************************/ // fill in mod_handle for dip to dwarf mod map // pick up general info about mod while here for later calls { mod_list *mod = _mod; char fname[MAX_PATH]; char *name; char *path; drmem_hdl cu_tag; dr_model model; mod_info *modinfo; modinfo = NextModInfo( mod ); modinfo->mod_handle = mod_handle; InitAddrSym( modinfo->addr_sym ); modinfo->addr_size = DRGetAddrSize( mod_handle ); cu_tag = DRGetCompileUnitTag( mod_handle ); modinfo->cu_tag = cu_tag; modinfo->stmts = DRGetStmtList( cu_tag ); path = DRGetName( cu_tag ); if( path != NULL ) { GetModName( path, fname ); DCFree( path ); name = DCAlloc( strlen( fname ) + 1 ); strcpy( name, fname ); } else { name = NULL; } path = DRGetProducer( cu_tag ); if( path != NULL ) { df_ver wat_producer_ver; if( memcmp( path, DWARF_WATCOM_PRODUCER_V3, sizeof( DWARF_WATCOM_PRODUCER_V3 ) - 1 ) == 0 ) { wat_producer_ver = VER_V3; } else if( memcmp( path, DWARF_WATCOM_PRODUCER_V2, sizeof( DWARF_WATCOM_PRODUCER_V2 ) - 1 ) == 0 ) { wat_producer_ver = VER_V2; } else if( memcmp( path, DWARF_WATCOM_PRODUCER_V1, sizeof( DWARF_WATCOM_PRODUCER_V1 ) - 1 ) == 0 ) { wat_producer_ver = VER_V1; } else { wat_producer_ver = VER_NONE; } if( mod->wat_producer_ver == VER_NONE ) { mod->wat_producer_ver = wat_producer_ver; } else if( mod->wat_producer_ver != wat_producer_ver ) { mod->wat_producer_ver = VER_ERROR; } DCFree( path ); } modinfo->name = name; model = DRGetMemModelAT( cu_tag ); if( DCCurrMAD() == MAD_X86 ) { switch( model ) { case DR_MODEL_NONE: case DR_MODEL_FLAT: modinfo->is_segment = false; break; default: modinfo->is_segment = true; break; } } else { modinfo->is_segment = false; } modinfo->model = model; modinfo->lang = DRGetLanguageAT( cu_tag ); modinfo->dbg_pch = DRDebugPCHDef( cu_tag ); modinfo->has_pubnames = false; return( true ); }