void ProcObjFiles( void ) /******************************/ /* Perform Pass 1 on all object files */ { CurrMod = NULL; if( LinkFlags & INC_LINK_FLAG ) { if( (LinkFlags & DWARF_DBI_FLAG) == 0 && (LinkFlags & ANY_DBI_FLAG) ) { LnkMsg( FTL+MSG_INC_ONLY_SUPPORTS_DWARF, NULL ); } if( LinkFlags & STRIP_CODE ) { LnkMsg( FTL+MSG_INC_AND_DCE_NOT_ALLOWED, NULL ); } if( LinkFlags & VF_REMOVAL ) { LnkMsg( FTL+MSG_INC_AND_VFR_NOT_ALLOWED, NULL ); } } LnkMsg( INF+MSG_LOADING_OBJECT, NULL ); if( LinkFlags & STRIP_CODE ) { LinkState |= CAN_REMOVE_SEGMENTS; } if( LinkState & GOT_PREV_STRUCTS ) { IncLoadObjFiles(); } else { LoadObjFiles( Root ); if( FmtData.type & MK_OVERLAYS ) { OvlPass1(); } } }
wio_size_t QWrite( f_handle file, void *buffer, wio_size_t len, char *name ) /**************************************************************************/ /* write from far memory */ { wio_size_t h; char rc_buff[RESOURCE_MAX_SIZE]; if( len == 0 ) return( 0 ); #ifdef _INT_DEBUG { wio_off_t pos = QPos(file); if( pos <= SpyWrite && SpyWrite <= pos+len && file == Root->outfile->handle) { DEBUG((DBG_ALWAYS, "About to write to %s (handle %d) %d bytes at position %d:", name, file, len, pos)); PrintMemDump(buffer, len, DUMP_BYTE); } } #endif CheckBreak(); h = write( file, buffer, len ); if( name != NULL ) { if( h == -1 ) { LnkMsg( ERR+MSG_IO_PROBLEM, "12", name, strerror( errno ) ); } else if( h != len ) { Msg_Get( MSG_IOERRLIST_7, rc_buff ); LnkMsg( (FTL+MSG_IO_PROBLEM) & ~OUT_MAP, "12", name, rc_buff ); } } return( h ); }
symbol *SymOpNWPfx( sym_flags op, char *name, size_t length, char * prefix, size_t prefixLen ) /**********************************************************************************************/ { symbol *retsym = SymOp( op, name, length ); if( NULL == retsym ) return( NULL ); if( ( NULL != prefix ) && ( 0 != prefixLen ) || ( NULL != CmdFile->symprefix ) ) { char *pfxname = alloca( 255 + 1 ); /* max len of PString - used to be prefixLen+1 */ if( NULL == pfxname ) { LnkMsg( ERR+MSG_SYMBOL_NAME_TOO_LONG, "s", prefix ); return( NULL ); } if( prefix ) { memcpy( pfxname, prefix, prefixLen ); pfxname[ prefixLen] = '\0'; } else { strcpy( pfxname, CmdFile->symprefix ); } if( NULL == (retsym->prefix = AddStringStringTable( &PrefixStrings, pfxname )) ) { LnkMsg( ERR+MSG_INTERNAL, "s", "no memory for prefix symbol"); return( NULL ); } } return( retsym ); }
void MakeSymAlias( char *name, size_t namelen, char *target, size_t targetlen ) /*****************************************************************************/ /* make a symbol table alias */ { symbol *sym; symbol *targ; if( namelen == targetlen && (*CmpRtn)( name, target, namelen ) == 0 ) { char *buff; buff = alloca( targetlen + 1 ); memcpy( buff, target, targetlen ); buff[ targetlen ] = '\0'; LnkMsg( WRN+MSG_CIRCULAR_ALIAS_FOUND, "s", buff ); return; // <--------- NOTE: premature return!!!! } sym = SymOp( ST_CREATE | ST_NOALIAS, name, namelen ); if( IS_SYM_ALIAS( sym ) ) { LnkMsg( WRN+MSG_MULTIPLE_ALIASES, "S", sym ); if( sym->info & SYM_FREE_ALIAS ) { _LnkFree( sym->p.alias ); } } else if( sym->info & SYM_DEFINED ) { return; // <--------- NOTE: premature return!!!! } sym->info |= SYM_FREE_ALIAS; /* * need to defined aliased symbol as well, so aliases in .obj files can be * hauled in from libraries */ targ = SymOp( ST_CREATE, target, targetlen ); SetSymAlias( sym, targ->name, targetlen ); }
static bool CheckFlags( orl_file_handle filehdl ) /***********************************************/ { orl_machine_type machtype; stateflag typemask; stateflag test; orl_file_flags flags; machtype = ORLFileGetMachineType( filehdl ); switch( machtype ) { case ORL_MACHINE_TYPE_I386: typemask = HAVE_I86_CODE; break; case ORL_MACHINE_TYPE_AMD64: typemask = HAVE_X64_CODE; break; case ORL_MACHINE_TYPE_ALPHA: typemask = HAVE_ALPHA_CODE; break; case ORL_MACHINE_TYPE_PPC601: typemask = HAVE_PPC_CODE; break; case ORL_MACHINE_TYPE_R3000: typemask = HAVE_MIPS_CODE; break; case ORL_MACHINE_TYPE_NONE: typemask = 0; break; default: typemask = HAVE_MACHTYPE_MASK; // trigger the error break; } test = (typemask | LinkState) & HAVE_MACHTYPE_MASK; test &= test - 1; // turn off one bit if( test != 0 ) { // multiple bits were turned on. LnkMsg( WRN+MSG_MACHTYPE_DIFFERENT, "s", CurrMod->f.source->file->name); } else { LinkState |= typemask; } if( ORLFileGetType( filehdl ) != ORL_FILE_TYPE_OBJECT ) { BadObject(); return( false ); } flags = ORLFileGetFlags( filehdl ); #if 0 if( flags & ORL_FILE_FLAG_BIG_ENDIAN ) { // MS lies about this. LnkMsg( ERR+LOC+MSG_NO_BIG_ENDIAN, NULL ); return( false ); } #endif if( flags & ORL_FILE_FLAG_64BIT_MACHINE ) { Set64BitMode(); } else if( flags & ORL_FILE_FLAG_16BIT_MACHINE ) { Set16BitMode(); } else { Set32BitMode(); } return( true ); }
void CheckBreak( void ) /****************************/ { #ifdef __OSI__ if( *_BreakFlagPtr ) { *_BreakFlagPtr = 0; LnkMsg( FTL+MSG_BREAK_HIT, NULL ); /* suicides */ } #else if( CaughtBreak ) { CaughtBreak = FALSE; /* prevent recursion */ LnkMsg( FTL+MSG_BREAK_HIT, NULL ); /* suicides */ } #endif }
static char *AddToStringTable( stringtable *strtab, void *data, unsigned len, bool addnullchar ) /**********************************************************************************************/ { stringblock *blk; unsigned diff; char * dest; if( addnullchar ) ++len; if( strtab->currbase & 1 && len > STR_BLOCK_SIZE ) { LnkMsg( ERR+MSG_SYMBOL_NAME_TOO_LONG, "s", data ); len = STR_BLOCK_SIZE; } for( blk = RingLast( strtab->data ); blk->size + len > STR_BLOCK_SIZE; blk = AllocNewBlock( strtab ) ) { diff = STR_BLOCK_SIZE - blk->size; if( diff != 0 ) { if( strtab->currbase & 1 ) { // then don't split memset( &blk->data[blk->size], 0, diff ); } else { memcpy( &blk->data[blk->size], data, diff ); len -= diff; data = (char *)data + diff; } } blk->size = STR_BLOCK_SIZE; strtab->currbase += STR_BLOCK_SIZE; } dest = &blk->data[blk->size]; blk->size += len; if( addnullchar ) dest[ --len ] = '\0'; memcpy( dest, data, len ); return( dest ); }
void ChkElfData( void ) /****************************/ { group_entry *group; symbol * sym; NumExports = NumImports = 0; for( sym = HeadSym; sym != NULL; sym = sym->link ) { if( IsSymElfImported(sym) ) { NumImports++; } else if( IsSymElfExported(sym) ) { if( !(sym->info & SYM_DEFINED) ) { LnkMsg( ERR+MSG_EXP_SYM_NOT_FOUND, "s", sym->name ); } NumExports++; } } InitStringTable( &SymStrTab, FALSE ); AddCharStringTable( &SymStrTab, '\0' ); ElfSymTab = CreateElfSymTable( NumImports + NumExports + NumGroups, &SymStrTab); for( group = Groups; group != NULL; group = group->next_group ) { if( group->totalsize != 0 ) { AddSymElfSymTable( ElfSymTab, group->sym ); } } for( sym = HeadSym; sym != NULL; sym = sym->link ) { if( IsSymElfImpExp(sym) ) { AddSymElfSymTable(ElfSymTab, sym); } } }
bool ProcCopyright( void ) /************************/ { struct tm *currtime; time_t thetime; unsigned year; char *copy_year; if( !GetToken( SEP_EQUALS, TOK_INCLUDE_DOT ) && !GetToken( SEP_NO, TOK_INCLUDE_DOT ) ) { if( FmtData.u.nov.copyright != NULL ) { _LnkFree( FmtData.u.nov.copyright ); // assume second is correct. } _ChkAlloc( FmtData.u.nov.copyright, DEFAULT_COPYRIGHT_LENGTH + 1 ); memcpy(FmtData.u.nov.copyright,DEFAULT_COPYRIGHT,DEFAULT_COPYRIGHT_LENGTH+1); copy_year = FmtData.u.nov.copyright + YEAR_OFFSET; thetime = time( NULL ); currtime = localtime( &thetime ); for( year = currtime->tm_year + 1900; year > 0; year /= 10 ) { *copy_year = '0' + (year % 10); copy_year--; } } else { if( Token.len > MAX_COPYRIGHT_LENGTH ) { LnkMsg( LOC+LINE+WRN+MSG_VALUE_TOO_LARGE, "s", "copyright" ); } else { if( FmtData.u.nov.copyright != NULL ) { _LnkFree( FmtData.u.nov.copyright ); // assume second is correct. } FmtData.u.nov.copyright = tostring(); } } return( true ); }
bool CacheOpen( file_list *list ) /**************************************/ { infilelist *file; unsigned numblocks; char **cache; if( list == NULL ) return( TRUE ); file = list->file; if( file->flags & INSTAT_IOERR ) return( FALSE ); if( DoObjOpen( file ) ) { file->flags |= INSTAT_IN_USE; } else { file->flags |= INSTAT_IOERR; return( FALSE ); } if( file->len == 0 ) { file->len = QFileSize( file->handle ); if( file->len == 0 ) { LnkMsg( ERR+MSG_BAD_OBJECT, "s", file->name ); file->flags |= INSTAT_IOERR; return( FALSE ); } } if( !(file->flags & INSTAT_SET_CACHE) ) { if( LinkFlags & CACHE_FLAG ) { file->flags |= INSTAT_FULL_CACHE; } else if( LinkFlags & NOCACHE_FLAG ) { file->flags |= INSTAT_PAGE_CACHE; } else { if( file->flags & INSTAT_LIBRARY ) { file->flags |= INSTAT_PAGE_CACHE; } else { file->flags |= INSTAT_FULL_CACHE; } } } if( file->cache == NULL ) { if( file->flags & INSTAT_FULL_CACHE ) { _ChkAlloc( file->cache, file->len ); if( file->currpos != 0 ) { QLSeek( file->handle, 0, SEEK_SET, file->name ); } QRead( file->handle, file->cache, file->len, file->name ); file->currpos = file->len; } else { numblocks = NumCacheBlocks( file->len ); _Pass1Alloc( file->cache, numblocks * sizeof( char * ) ); cache = file->cache; while( numblocks > 0 ) { *cache = NULL; cache++; numblocks--; } } } return( TRUE ); }
void EarlyEOF( void ) /**************************/ { CurrMod->f.source->file->flags |= INSTAT_IOERR; Locator( CurrMod->f.source->file->name, NULL, 0 ); LnkMsg( ERR+MSG_EARLY_EOF, NULL ); }
void ConvertLazyRefs( void ) /*********************************/ /* go through all symbols, & turn lazy refs to aliases to default sym. */ { symbol * defsym; symbol * sym; for( sym = HeadSym; sym != NULL; sym = sym->link ) { if( IS_SYM_A_REF(sym) ) { if( IS_SYM_VF_REF(sym) ) { defsym = *(sym->e.vfdata); _LnkFree( sym->e.vfdata ); } else { defsym = sym->e.def; if( sym->info & SYM_VF_MARKED ) { DefStripSym( sym, AllocSegData() ); // see note 1 below. } } WeldSyms( sym, defsym ); sym->info |= SYM_WAS_LAZY; if( LinkFlags & SHOW_DEAD ) { LnkMsg( MAP+MSG_SYMBOL_DEAD, "S", sym ); } } } }
static void WriteOS2Data( unsigned_32 stub_len, os2_exe_header *exe_head ) /************************************************************************/ /* copy code from extra memory to loadfile. */ { group_entry *group; unsigned group_num; unsigned long off; segment_record segrec; unsigned_32 seg_addr; unsigned long relocsize; DEBUG(( DBG_BASE, "Writing data" )); group_num = 0; for( group = Groups; group != NULL; group = group->next_group ) { if( group->totalsize == 0 ) continue; // DANGER DANGER DANGER <--!!! segrec.info = group->segflags; // write segment segrec.min = MAKE_EVEN( group->totalsize ); segrec.size = MAKE_EVEN( group->size ); if( segrec.size != 0 ) { off = NullAlign( 1 << FmtData.u.os2.segment_shift ); seg_addr = off >> FmtData.u.os2.segment_shift; if( seg_addr > 0xffff ) { LnkMsg( ERR+MSG_ALIGN_TOO_SMALL, NULL ); }; segrec.address = (unsigned_16)seg_addr; WriteGroupLoad( group ); NullAlign( 2 ); // segment must be even length relocsize = WriteOS2Relocs( group ); if( relocsize != 0 ) { segrec.info |= SEG_RELOC; } } else {
void InitLoadFile( void ) /***********************/ /* open the file, and write out header info */ { DEBUG(( DBG_OLD, "InitLoadFile()" )); LnkMsg( INF+MSG_CREATE_EXE, "f" ); }
static void PreAddrCalcFormatSpec( void ) /***************************************/ // format specific routines which need to be called before address calculation { #ifdef _OS2 if( FmtData.type & MK_PE ) { ChkPEData(); } else if( FmtData.type & (MK_OS2|MK_WIN_VXD) ) { if( IS_PPC_OS2) { // Development temporarly on hold: // ChkOS2ElfData(); } else { ChkOS2Data(); } } #endif #ifdef _NOVELL if( FmtData.type & MK_NOVELL ) { FindExportedSyms(); } #endif #ifdef _PHARLAP if( FmtData.type & MK_PHAR_FLAT && LinkState & HAVE_16BIT_CODE && !(CmdFlags & CF_HAVE_REALBREAK)) { LnkMsg( WRN+MSG_NO_REALBREAK_WITH_16BIT, NULL ); } #endif }
static void DoDefaultSystem( void ) /*********************************/ /* first hint about format being 32-bit vs. 16-bit (might distinguish between * os/2 v1 & os/2 v2), and if that doesn't decide it, haul in the default * system block */ { if( (LinkState & FMT_DECIDED) == 0 ) { if( LinkState & FMT_SEEN_64_BIT ) { HintFormat( MK_64BIT ); } else if( LinkState & FMT_SEEN_32_BIT ) { HintFormat( MK_32BIT ); } else { HintFormat( MK_16BIT | MK_QNX ); } if( (LinkState & FMT_DECIDED) == 0 ) { if( LinkState & FMT_SPECIFIED ) { LnkMsg( FTL+MSG_AMBIG_FORMAT, NULL ); } if( LinkState & FMT_SEEN_64_BIT ) { ExecSystem( "64bit" ); } else if( LinkState & FMT_SEEN_32_BIT ) { ExecSystem( "386" ); } else { ExecSystem( "286" ); /* no 386 obj's after this */ } } } }
static void WriteCOMFile( void ) /******************************/ // generate a DOS .COM file. { outfilelist *fnode; group_entry *group; bool repos; unsigned long root_size; signed long chop; if( StartInfo.addr.seg != 0 ) { LnkMsg( ERR+MSG_INV_COM_START_ADDR, NULL ); return; } if( ( StackAddr.seg != 0 ) || ( StackAddr.off != 0 ) ) { LnkMsg( WRN+MSG_STACK_SEG_IGNORED, NULL ); } OrderGroups( CompareDosSegments ); CurrSect = Root; // needed for WriteInfo. fnode = Root->outfile; fnode->file_loc = Root->u.file_loc = 0; Root->sect_addr = Groups->grp_addr; /* write groups */ for( group = Groups; group != NULL; group = group->next_group ) { chop = SUB_ADDR( group->grp_addr, StartInfo.addr ); if( chop > 0 ) { chop = 0; } if( (signed long)group->size + chop > 0 ) { repos = WriteCOMGroup( group, chop ); if( repos ) { SeekLoad( fnode->file_loc ); } } #if 0 if( loc < 0 ) { Root->u.file_loc += (unsigned long)loc; // adjust for missing code } #endif } root_size = fnode->file_loc; if( root_size > (64 * 1024L - 0x200) ) { LnkMsg( ERR+MSG_COM_TOO_LARGE, NULL ); } DBIWrite(); }
void CheckBreak( void ) /****************************/ { if( CaughtBreak == BREAK_DETECTED ) { CaughtBreak = BREAK_HANDLED; LnkMsg( FTL+MSG_BREAK_HIT, NULL ); /* suicides */ } }
void PrintIOError( unsigned msg, char *types, char *name ) /***************************************************************/ { char rc_buff[RESOURCE_MAX_SIZE]; Msg_Get( MSG_IOERRLIST_0 + LastResult, rc_buff ); LnkMsg( msg, types, name, rc_buff ); }
static void BadLibrary( file_list *list ) /***************************************/ { list->file->flags |= INSTAT_IOERR; _LnkFree( list->u.dict ); list->u.dict = NULL; Locator( list->file->name, NULL, 0 ); LnkMsg( ERR+MSG_LIB_FILE_ATTR, NULL ); }
void ReportMultiple( symbol *sym, char *name, unsigned len ) /*****************************************************************/ /* report a multiply-defined symbol */ { unsigned lev; if( LinkFlags & REDEFS_OK ) { lev = WRN; } else { lev = MILD_ERR; LinkState |= UNDEFED_SYM_ERROR; } if( CmpRtn( sym->name, name, len + 1 ) == 0 ) { LnkMsg( LOC+lev+MSG_MULT_DEF, "S", sym ); } else { LnkMsg( LOC+lev+MSG_MULT_DEF_BY, "12", sym->name, name ); } }
f_handle QOpenRW( char *name ) /***********************************/ { tiny_ret_t h; h = DoOpen( name, TRUE, TIO_NORMAL ); if( TINY_OK( h ) ) return( (f_handle)TINY_INFO( h ) ); LnkMsg( FTL+MSG_CANT_OPEN, "12", name, QErrMsg( TINY_INFO( h ) ) ); return( NIL_HANDLE ); }
void AutoGroup( void ) /********************/ { WalkAllSects( &AutoGroupSect ); SortGroupList(); FindSplitGroups(); if( NumGroups == 0 ) { LnkMsg( FTL+MSG_NO_CODE_OR_DATA, NULL ); } NumberNonAutos(); }
f_handle QOpenR( char *name ) /***************************/ { int h; h = DoOpen( name, O_RDONLY, false ); if( h != -1 ) return( h ); LnkMsg( FTL+MSG_CANT_OPEN, "12", name, strerror( errno ) ); return( NIL_FHANDLE ); }
static offset OffFromToc( offset off ) /***************************************/ { offset toff; toff = off - TocShift; if( (signed_16)toff != (signed_32)toff ) { LnkMsg( ERR+MSG_TOC_TOO_BIG, NULL ); } return( toff ); }
f_handle QOpenRW( char *name ) /***********************************/ { int h; h = DoOpen( name, O_RDWR | O_CREAT | O_TRUNC, FALSE ); if( h != -1 ) return( h ); LnkMsg( FTL+MSG_CANT_OPEN, "12", name, strerror( errno ) ); return( NIL_FHANDLE ); }
f_handle ExeOpen( char *name ) /***********************************/ { int h; h = DoOpen( name, O_RDWR, TRUE ); if( h != -1 ) return( h ); LnkMsg( FTL+MSG_CANT_OPEN, "12", name, strerror( errno ) ); return( NIL_FHANDLE ); }
symbol *DefISymbol( char * name ) /*******************************/ { symbol * sym; sym = RefISymbol( name ); if( sym->info & SYM_DEFINED && !(sym->info & SYM_LINK_GEN) ) { LnkMsg( ERR+MSG_RESERVED_SYM_DEFINED, "s", name ); } sym->info |= SYM_DEFINED | SYM_LINK_GEN; return sym; }
void QDelete( char *name ) /*******************************/ { int h; if( name == NULL ) return; h = remove( name ); if( h == -1 && errno != ENOENT ) { /* file not found is OK */ LnkMsg( ERR+MSG_IO_PROBLEM, "12", name, strerror( errno ) ); } }
wio_off_t QLSeek( f_handle file, wio_off_t position, int start, char *name ) /***********************************************************************/ { wio_off_t h; CheckBreak(); h = lseek( file, position, start ); if( h == -1 && name != NULL ) { LnkMsg( ERR+MSG_IO_PROBLEM, "12", name, strerror( errno ) ); } return( h ); }