void AddEdge( segdata * seg, symbol * sym ) /************************************************/ /* reference from a segment to a symbol */ { edgelist * edge; if( sym->info & SYM_DEFINED ) { if( !IS_SYM_IMPORTED(sym) && seg != sym->p.seg && sym->p.seg != NULL ) { if( seg->isrefd || !seg->iscode ) { RefSeg( sym->p.seg ); } else if( !sym->p.seg->isrefd ) { edge = AllocEdge(); edge->u.seg = sym->p.seg; edge->issym = FALSE; edge->next = seg->a.refs; seg->a.refs = edge; } } } else { /* symbol is undefined */ if( seg->isrefd || !seg->iscode ) { sym->info |= SYM_DCE_REF; PruneNonSymEdges( sym ); } else { edge = AllocEdge(); edge->u.seg = seg; edge->next = sym->p.edges; edge->issym = FALSE; edge->reverse_dir = TRUE; sym->p.edges = edge; } } }
void XWriteImports( void ) /*******************************/ { symbol * sym; for( sym = HeadSym; sym != NULL; sym = sym->link ) { if( IS_SYM_IMPORTED(sym) && sym->p.import != NULL ) { if( !(FmtData.type & MK_NOVELL) || sym->p.import != DUMMY_IMPORT_PTR ) { if(sym->prefix && (strlen(sym->prefix) > 0)) WriteFormat( 0, "%s@%s", sym->prefix, sym->name); else WriteFormat( 0, "%s", sym->name ); #ifdef _OS2 if( FmtData.type & (MK_OS2|MK_PE|MK_WIN_VXD) ) { WriteFormat( 36, "%s", ImpModuleName( sym->p.import ) ); } #endif WriteMapNL( 1 ); } } } }
static void KillASym( void *_sym ) /********************************/ { symbol *sym = _sym; sym->info |= SYM_KILL; if( IS_SYM_IMPORTED( sym ) ) { KillDependantSyms( sym ); } }
static void FixSymAddr( void *_sym ) /**********************************/ { symbol *sym = _sym; if( !IS_SYM_IMPORTED(sym) && !(sym->info & SYM_DEAD) && sym->addr.off > 0 && sym->p.seg != NULL ) { sym->addr.off -= sym->p.seg->u.leader->seg_addr.off; sym->addr.off -= sym->p.seg->a.delta; } }
void CVGenGlobal( symbol * sym, section *sect ) /****************************************************/ // called during symbol address calculation (between pass 1 & pass 2) // also called by loadpe between passes { s_pub16 pub16; s_pub32 pub32; unsigned size; unsigned pad; unsigned_32 buf; byte namelen; sect = sect; if( sym->info & SYM_STATIC ) return; namelen = strlen( sym->name ); size = namelen + 1; if( ( sym->p.seg == NULL ) || IS_SYM_IMPORTED( sym ) || sym->p.seg->is32bit ) { size += sizeof( s_pub32 ); pub32.common.length = ROUND_UP( size, 4 ); pad = pub32.common.length - size; pub32.common.length -= 2; pub32.common.code = S_PUB32; pub32.f.offset = sym->addr.off; pub32.f.segment = GetCVSegment( sym->p.seg->u.leader ); pub32.f.type = 0; DumpInfo( CVSECT_MISC, &pub32, sizeof( s_pub32 ) ); } else { size += sizeof( s_pub16 ); pub16.common.length = ROUND_UP( size, 4 ); pad = pub16.common.length - size; pub16.common.length -= 2; pub16.common.code = S_PUB16; pub16.f.offset = sym->addr.off; pub16.f.segment = GetCVSegment( sym->p.seg->u.leader ); pub16.f.type = 0; DumpInfo( CVSECT_MISC, &pub16, sizeof( s_pub16 ) ); } DumpInfo( CVSECT_MISC, &namelen, 1 ); DumpInfo( CVSECT_MISC, sym->name, namelen ); if( pad > 0 ) { buf = 0; DumpInfo( CVSECT_MISC, &buf, pad ); } }
void DataRef( symbol * sym ) /*********************************/ /* symbol referenced from data, so make sure it is included */ { if( (LinkState & HAVE_PPC_CODE) && (FmtData.type & MK_PE) ) { unsigned len = strlen( sym->name ) + 3; char *s = alloca( len ); s[ 0 ] = s[ 1 ] = '.'; strcpy( s + 2, sym->name ); sym = SymOp( ST_FIND, s, len - 1 ); } if( sym->info & SYM_DEFINED && !IS_SYM_IMPORTED( sym ) ) { RefSeg( sym->p.seg ); } sym->info |= SYM_DCE_REF; }
static void PrepSymbol( void *_sym, void *info ) /**********************************************/ { symbol *sym = _sym; char *save; symbol *mainsym; if( sym->info & SYM_IS_FREE ) { *((unsigned_32 *)sym) = CARVE_INVALID_INDEX; return; } sym->hash = CarveGetIndex( CarveSymbol, sym->hash ); sym->link = CarveGetIndex( CarveSymbol, sym->link ); sym->publink = CarveGetIndex( CarveSymbol, sym->publink ); if( sym->info & SYM_IS_ALTDEF ) { mainsym = sym->e.mainsym; if( !(mainsym->info & SYM_NAME_XLATED) ) { mainsym->name = GetString( info, mainsym->name ); mainsym->info |= SYM_NAME_XLATED; } sym->name = mainsym->name; } else if( !(sym->info & SYM_NAME_XLATED) ) { sym->name = GetString( info, sym->name ); sym->info |= SYM_NAME_XLATED; } sym->mod = CarveGetIndex( CarveModEntry, sym->mod ); if( IS_SYM_ALIAS( sym ) ) { save = sym->p.alias; sym->p.alias = GetString( info, sym->p.alias ); if( sym->info & SYM_FREE_ALIAS ) { _LnkFree( save ); } } else if( IS_SYM_IMPORTED(sym) ) { if( FmtData.type & (MK_OS2 | MK_PE) ) { sym->p.import = CarveGetIndex( CarveDLLInfo, sym->p.import ); } } else if( !(sym->info & SYM_IS_ALTDEF) || IS_SYM_COMDAT(sym) ) { sym->p.seg = CarveGetIndex( CarveSegData, sym->p.seg ); sym->u.altdefs = CarveGetIndex( CarveSymbol, sym->u.altdefs ); } if( sym->info & SYM_EXPORTED ) { if( FmtData.type & (MK_OS2 | MK_PE | MK_WIN_VXD) ) { sym->e.export = CarveGetIndex( CarveExportInfo, sym->e.export ); } } else if( sym->e.def != NULL ) {
static void WipeSym( symbol *sym ) /********************************/ { if( IS_SYM_IMPORTED(sym) && !(FmtData.type & MK_ELF) ) { if( FmtData.type & MK_NOVELL ) { if( sym->p.import != DUMMY_IMPORT_PTR ) { _LnkFree( sym->p.import ); } } else { FreeImport( sym->p.import ); } sym->p.import = NULL; } else if( IS_SYM_ALIAS(sym) ) { if( sym->info & SYM_FREE_ALIAS ) { _LnkFree( sym->p.alias ); } sym->u.aliaslen = 0; // make sure this is nulled again } }
void XReportSymAddr( symbol *sym ) /***************************************/ { char star; if( sym->info & SYM_REFERENCED ) { if( IS_SYM_IMPORTED(sym) || (FmtData.type & MK_ELF && IsSymElfImported(sym)) ) { star = 'i'; } else { star = ' '; } } else if( sym->info & SYM_LOCAL_REF ) { star = '+'; } else { star = '*'; } WriteSym( sym, star ); WriteMapNL( 1 ); }
void CVAddGlobal( symbol *sym ) /************************************/ // called during pass 1 symbol definition { unsigned size; if( !( sym->info & SYM_STATIC ) ) { if( ( sym->p.seg == NULL ) || IS_SYM_IMPORTED( sym ) || sym->p.seg->is32bit ) { size = sizeof( s_pub32 ); } else { size = sizeof( s_pub16 ); } size = ROUND_UP( size + strlen( sym->name ) + 1, 4 ); CurrMod->d.cv->pubsize += size; SectAddrs[CVSECT_MISC] += size; } }
static void ConvertTocEntryId( TocEntryId *e ) /********************************************/ { if( e->sdata != NULL ) { // do nothing: already in sdata/offset form } else { symbol *sym = e->u.sym; segdata *seg = sym->p.seg; if( IS_SYM_IMPORTED( sym ) || seg == NULL ) { // do not convert; keep symbol around } else { e->sdata = seg; e->u.off = sym->addr.off - seg->a.delta - seg->u.leader->seg_addr.off; } } return; }
void AddSymSegEdge( symbol *srcsym, segdata *targsdata ) /*********************************************************/ /* make a reference from symbol to segment */ { edgelist * edge; if( IS_SYM_IMPORTED(srcsym) ) { RefSeg(targsdata); return; } edge = AllocEdge(); edge->u.seg = targsdata; edge->issym = FALSE; if( srcsym->info & SYM_DEFINED ) { edge->next = targsdata->a.refs; targsdata->a.refs = edge; } else { edge->next = srcsym->p.edges; srcsym->p.edges = edge; } }
void ResolveUndefined( void ) /**********************************/ { symbol *sym; file_list *lib; bool keepgoing; LnkMsg( INF+MSG_SEARCHING_LIBS, NULL ); if( (FmtData.type & MK_OVERLAYS) && FmtData.u.dos.distribute ) { LinkState |= CAN_REMOVE_SEGMENTS; InitModTable(); } CurrSect = Root; ResolveVFExtdefs(); do { LinkState &= ~LIBRARIES_ADDED; for( lib = ObjLibFiles; lib != NULL; lib = lib->next_file ) { if( lib->status & STAT_SEEN_LIB ) { lib->status |= STAT_OLD_LIB; } else { lib->status |= STAT_SEEN_LIB; } } for( sym = HeadSym; sym != NULL; sym = sym->link ) { if( ( !(sym->info & SYM_DEFINED) && !IS_SYM_WEAK_REF( sym ) || (FmtData.type & MK_NOVELL) && IS_SYM_IMPORTED( sym ) && (sym->info & (SYM_REFERENCED | SYM_LOCAL_REF)) ) && !(sym->info & SYM_IS_ALTDEF) ) { LibFind( sym->name, (sym->info & SYM_CHECKED) != 0 ); } sym->info |= SYM_CHECKED; } keepgoing = ResolveVFExtdefs(); } while( keepgoing || LinkState & LIBRARIES_ADDED ); BurnLibs(); PrintBadTraces(); }
static unsigned_32 WriteNovImports( fixed_header *header ) /********************************************************/ { nov_import * import; unsigned_32 count; char * name; unsigned_8 namelen; unsigned_32 wrote; unsigned_32 refs; virt_mem * vmem_array; symbol * sym; wrote = count = 0; for( sym = HeadSym; sym != NULL; sym = sym->link ) { if( !( IS_SYM_IMPORTED( sym ) ) ) continue; /* so SymFini doesn't try to free it */ if( sym->p.import == DUMMY_IMPORT_PTR ) sym->p.import = NULL; import = sym->p.import; if( import != NULL ) { count++; name = sym->name; namelen = strlen( name ); /* // netware prefix support */ if( sym->prefix ) { namelen += ( strlen( sym->prefix ) + 1); WriteLoad( &namelen, sizeof( unsigned_8 ) ); WriteLoad( sym->prefix, strlen( sym->prefix ) ); WriteLoad( "@", 1 ); WriteLoad( name, strlen( sym->name ) ); } else { WriteLoad( &namelen, sizeof( unsigned_8 ) ); WriteLoad( name, namelen ); } wrote += namelen + sizeof( unsigned_8 ) + sizeof( unsigned_32 ); if( import->contents <= MAX_IMP_INTERNAL ) { refs = import->contents; WriteLoad( &refs, sizeof( unsigned_32 ) ); refs *= sizeof( unsigned_32 ); WriteLoad( &import->num_relocs, refs ); } else { // imports are in virtual memory. refs = import->num_relocs; WriteLoad( &refs, sizeof( unsigned_32 ) ); vmem_array = import->vm_ptr; for( ; refs > IMP_NUM_VIRT; refs -= IMP_NUM_VIRT ) { WriteInfoLoad( *vmem_array, IMP_VIRT_ALLOC_SIZE ); vmem_array++; } WriteInfoLoad( *vmem_array, refs * sizeof( unsigned_32 ) ); refs = import->num_relocs * sizeof( unsigned_32 ); } wrote += refs; } } header->numberOfExternalReferences = count; return( wrote ); }