static void SetupImpLib( void ) /*****************************/ { const char *fname; size_t namelen; ImpLib.bufsize = 0; ImpLib.handle = NIL_FHANDLE; ImpLib.buffer = NULL; ImpLib.dllname = NULL; ImpLib.didone = false; if( FmtData.make_implib ) { _ChkAlloc( ImpLib.buffer, IMPLIB_BUFSIZE ); if( FmtData.make_impfile ) { ImpLib.fname = ChkStrDup( FmtData.implibname ); ImpLib.handle = QOpenRW( ImpLib.fname ); } else { ImpLib.handle = OpenTempFile( &ImpLib.fname ); } /* GetBaseName results in the filename only * * it trims both the path, and the extension */ fname = GetBaseName( Root->outfile->fname, 0, &namelen ); ImpLib.dlllen = namelen; /* * increase length to restore full extension if not OS2 * sometimes the extension of the output name is important */ ImpLib.dlllen += strlen( fname + namelen ); _ChkAlloc( ImpLib.dllname, ImpLib.dlllen ); memcpy( ImpLib.dllname, fname, ImpLib.dlllen ); } }
static void *OS2PagedRelocInit( offset size, int unitsize ) /***************************************************************/ /* For some OS/2 formats we have to split up the structure off the grp_relocs * field up into small bits to ensure that we don't get structure allocations * > 64K. This is stored basically as a 2-d array */ { void ** mem; void ** start; offset pageidx; offset idxhigh; unsigned idxlow; unsigned allocsize; pageidx = OSF_PAGE_COUNT( size ); idxhigh = OSF_RLIDX_HIGH( pageidx ); _PermAlloc( mem, ( idxhigh + 1 ) * sizeof( void * ) ); start = mem; allocsize = OSF_RLIDX_MAX * unitsize; while( idxhigh > 0 ) { _ChkAlloc( *mem, allocsize ); memset( *mem, 0, allocsize ); mem++; idxhigh--; } idxlow = OSF_RLIDX_LOW( pageidx ); if( idxlow != 0 ) { allocsize = idxlow * unitsize; _ChkAlloc( *mem, allocsize ); memset( *mem, 0, allocsize ); } return( start ); }
void InitModTable( void ) /******************************/ { CurrModThere = INITIAL_MOD_ALLOC; _ChkAlloc( ModTable, INITIAL_MOD_ALLOC * sizeof( mod_entry * ) ); CurrModHandle = 0; ArcBufLen = INITIAL_ARC_ALLOC; _ChkAlloc( ArcBuffer, sizeof(arcdata) + (INITIAL_ARC_ALLOC - 1) * sizeof(dist_arc)); MakePass1Blocks(); }
static void * MakeArray( unsigned size ) /**************************************/ { nodearray * nodes; _ChkAlloc( nodes, sizeof( nodearray ) ); nodes->num = 0; nodes->elsize = size; nodes->arraymax = 0; size *= NODE_ARRAY_SIZE; _ChkAlloc( nodes->array[0], size ); memset( nodes->array[0], 0, size ); return( nodes ); }
static int ReadOMFDict( file_list *list, unsigned_8 *header, bool makedict ) /***************************************************************************/ { omf_dict_entry *omf_dict; unsigned reclength; header += sizeof( unsigned_8 ); reclength = _ReadLittleEndian16UN( header ) + 3; if( makedict ) { if( list->u.dict == NULL ) { _ChkAlloc( list->u.dict, sizeof( dict_entry ) ); } omf_dict = &list->u.dict->o; omf_dict->cache = NULL; header += sizeof( unsigned_16 ); omf_dict->start = _ReadLittleEndian32UN( header ); header += sizeof( unsigned_32 ); omf_dict->pages = _ReadLittleEndian16UN( header ); header += sizeof( unsigned_16 ); if( omf_dict->start == 0 || omf_dict->pages == 0 ) { BadLibrary( list ); return( -1 ); } omf_dict->rec_length = reclength; } return( reclength ); }
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 ); }
static void ImpProcSymbol( segnode *snode, orl_symbol_type type, char *name, size_t namelen ) /***************************************************************************/ { if( type & ORL_SYM_TYPE_UNDEFINED ) { if( namelen > sizeof(CoffImportRefName) - 1 ) { namelen -= sizeof(CoffImportRefName) - 1; if( memicmp( name + namelen, CoffImportRefName, sizeof(CoffImportRefName) - 1 ) == 0 ) { _ChkAlloc( ImpModName, namelen + 5 ); memcpy( ImpModName, name, namelen ); if( memicmp( CurrMod->name + strlen(CurrMod->name) - 4, ".drv", 4 ) == 0 ) { //KLUDGE!! memcpy( ImpModName + namelen, ".drv", 5 ); } else { memcpy( ImpModName + namelen, ".dll", 5 ); } } } } else if( snode != NULL && (snode->info & SEG_CODE) ) { if( FirstCodeSymName == NULL ) { FirstCodeSymName = name; } } else { if( FirstDataSymName == NULL && memcmp( name, ImportSymPrefix, PREFIX_LEN ) == 0 ) { FirstDataSymName = name + PREFIX_LEN; } } }
static image_entry *DoCreateImage( const char *exe, const char *symfile ) { image_entry *image; image_entry **owner; size_t len; len = ( exe == NULL ) ? 0 : strlen( exe ); _ChkAlloc( image, sizeof( *image ) + len, LIT_ENG( ERR_NO_MEMORY_FOR_DEBUG ) ); if( image == NULL ) return( NULL ); memset( image, 0, sizeof( *image ) ); if( len != 0 ) memcpy( image->image_name, exe, len + 1 ); if( symfile != NULL ) { _Alloc( image->symfile_name, strlen( symfile ) + 1 ); if( image->symfile_name == NULL ) { _Free( image ); Error( ERR_NONE, LIT_ENG( ERR_NO_MEMORY_FOR_DEBUG ) ); return( NULL ); } strcpy( image->symfile_name, symfile ); } image->mapper = MapAddrSystem; for( owner = &DbgImageList; *owner != NULL; owner = &(*owner)->link ) ; *owner = image; return( image ); }
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 CarveRestart( carve_t cv, unsigned num ) /**************************************************/ { unsigned numblks; unsigned remainder; unsigned index; blk_t * block; if( num == 0 ) return; numblks = (num + cv->elm_count - 1) / cv->elm_count; for( index = 0; index < numblks; index++ ) { newBlk( cv ); } _ChkAlloc( cv->blk_map, numblks * sizeof( blk_t * ) ); index = numblks - 1; for( block = cv->blk_list; block != NULL; block = block->next ) { cv->blk_map[ index ] = block; index -= 1; } remainder = num % cv->elm_count; if( remainder != 0 ) { MakeFreeList( cv, cv->blk_map[0], remainder * cv->elm_size ); } cv->insert = NULL; }
void * CachePermRead( file_list *list, unsigned long pos, unsigned len ) /*****************************************************************************/ { char * buf; char * result; buf = CacheRead( list, pos, len ); if( list->file->flags & INSTAT_FULL_CACHE ) return buf; if( Multipage ) { _LnkReAlloc( result, buf, len ); _ChkAlloc( TokBuff, TokSize ); Multipage = FALSE; // indicate that last read is permanent. } else { _ChkAlloc( result, len ); memcpy( result, buf, len ); } return result; }
char *ChkToString( void *mem, unsigned len ) /******************************************/ { char *str; _ChkAlloc( str, len + 1 ); memcpy( str, mem, len ); str[ len ] = '\0'; return( str ); }
void NumberSections( void ) /********************************/ { if( ( FmtData.type & MK_OVERLAYS ) && FmtData.u.dos.distribute ) { _ChkAlloc( SectOvlTab, sizeof( section * ) * ( OvlNum + 1 ) ); SectOvlTab[0] = Root; } OvlNum = 1; WalkAllOvl( &NumASect ); }
static void AllocNewArray( nodearray *list ) /******************************************/ { unsigned size; list->arraymax++; size = list->elsize * NODE_ARRAY_SIZE; _ChkAlloc( list->array[list->arraymax], size ); memset( list->array[list->arraymax], 0, size ); }
static stringblock * AllocNewBlock( stringtable *strtab ) /*******************************************************/ { stringblock *blk; _ChkAlloc( blk, sizeof(stringblock) ); blk->next = NULL; RingAppend( &strtab->data, blk ); blk->size = 0; return blk; }
char *ChkStrDup( char *str ) /**************************/ { size_t len; char *copy; len = strlen( str ) + 1; _ChkAlloc( copy, len ); memcpy( copy, str, len ); return( copy ); }
f_handle OpenTempFile( char **fname ) /***********************************/ { const char *ptr; size_t tlen; char *tptr; f_handle fhdl; ptr = GetEnvString( "WLINKTMP" ); if( ptr == NULL ) ptr = GetEnvString( "TMP" ); if( ptr == NULL ) ptr = GetEnvString( "TMPDIR" ); if( ptr == NULL ) { _ChkAlloc( tptr, TEMPFNAME_SIZE ); *fname = tptr; } else { tlen = strlen( ptr ); _ChkAlloc( tptr, tlen + 1 + TEMPFNAME_SIZE ); memcpy( tptr, ptr, tlen ); *fname = tptr; tptr += tlen; if( !IS_PATH_SEP( tptr[-1] ) ) { *tptr++ = DIR_SEP; } } tptr = MakeTempName( tptr ); tlen = 0; for( ;; ) { if( tlen >= 26 ) { LnkMsg( FTL+MSG_CANT_OPEN_SPILL, NULL ); } *tptr += 1; // change temp file extension fhdl = TempFileOpen( *fname ); if( fhdl == NIL_FHANDLE ) break; QClose( fhdl, *fname ); ++tlen; } return( QOpenRW( *fname ) ); }
static void SetHeaders( ElfHdr *hdr ) /***********************************/ { memcpy( hdr->eh.e_ident, ELF_SIGNATURE, ELF_SIGNATURE_LEN ); hdr->eh.e_ident[EI_CLASS] = ELFCLASS32; #ifdef __BIG_ENDIAN__ hdr->eh.e_ident[EI_DATA] = ELFDATA2MSB; #else hdr->eh.e_ident[EI_DATA] = ELFDATA2LSB; #endif hdr->eh.e_ident[EI_VERSION] = EV_CURRENT; hdr->eh.e_ident[EI_OSABI] = FmtData.u.elf.abitype; hdr->eh.e_ident[EI_ABIVERSION] = FmtData.u.elf.abiversion; memset( &hdr->eh.e_ident[EI_PAD], 0, EI_NIDENT - EI_PAD ); hdr->eh.e_type = ET_EXEC; if( LinkState & HAVE_PPC_CODE ) { hdr->eh.e_machine = EM_PPC; } else if( LinkState & HAVE_MIPS_CODE ) { hdr->eh.e_machine = EM_MIPS; } else if( LinkState & HAVE_X64_CODE ) { hdr->eh.e_machine = EM_X86_64; } else { hdr->eh.e_machine = EM_386; } hdr->eh.e_version = EV_CURRENT; if( StartInfo.type == START_UNDEFED ) { hdr->eh.e_entry = 0; } else { hdr->eh.e_entry = FindLinearAddr2( &StartInfo.addr ); } hdr->eh.e_flags = 0; hdr->eh.e_ehsize = sizeof(Elf32_Ehdr); hdr->eh.e_phentsize = sizeof(Elf32_Phdr); hdr->eh.e_shentsize = sizeof(Elf32_Shdr); hdr->eh.e_phnum = NumGroups + 1; hdr->eh.e_phoff = sizeof(Elf32_Ehdr); hdr->ph_size = sizeof(Elf32_Phdr) * hdr->eh.e_phnum; _ChkAlloc( hdr->ph, hdr->ph_size ); hdr->ph->p_type = PT_PHDR; hdr->ph->p_offset = sizeof(Elf32_Ehdr); hdr->ph->p_vaddr = sizeof(Elf32_Ehdr) + FmtData.base; hdr->ph->p_paddr = 0; hdr->ph->p_filesz = hdr->ph_size; hdr->ph->p_memsz = hdr->ph_size; hdr->ph->p_flags = PF_R | PF_X; hdr->ph->p_align = 0; InitStringTable( &hdr->secstrtab, FALSE ); AddCharStringTable( &hdr->secstrtab, '\0' ); InitSections( hdr ); hdr->curr_off = hdr->eh.e_ehsize + hdr->ph_size; hdr->curr_off = ROUND_UP( hdr->curr_off, 0x100 ); SeekLoad( hdr->curr_off ); }
void SymResolve( stack_entry *entry ) { item_mach tmp; sym_handle *sh; if( entry->flags & SF_SYM ) { sh = entry->v.sh; entry->flags &= ~SF_FORM_MASK; if( SymLocation( sh, entry->lc, &entry->v.loc ) == DS_OK ) { entry->flags |= SF_LOCATION; if( entry->v.loc.e[0].type == LT_ADDR ) { entry->flags |= SF_IMP_ADDR; } GetTrueEntry( entry ); } else { if( entry->info.kind == TK_STRING ) { _ChkAlloc( entry->v.string.allocated, entry->info.size, LIT( ERR_NO_MEMORY_FOR_EXPR ) ); LocationCreate( &entry->v.string.loc, LT_INTERNAL, entry->v.string.allocated ); if( SymValue( sh, entry->lc, entry->v.string.allocated ) != DS_OK ) { Error( ERR_NONE, LIT( ERR_NO_ACCESS ) ); } } else { if( SymValue( sh, entry->lc, &tmp ) != DS_OK ) { Error( ERR_NONE, LIT( ERR_NO_ACCESS ) ); } FromItem( &tmp, entry ); } } switch( entry->info.kind ) { case TK_CODE: case TK_ADDRESS: if( !(entry->flags & SF_LOCATION) ) { ExprSetAddrInfo( entry, FALSE ); /* This was here before, but that messes up things like 'do x=0:0' where 'x' is a newly created debugger variable. I can't think of any reason why you'd want to do this. If it turns out that there is a reason, talk to me. Brian. } else { LocationToAddr( entry ); */ } entry->th = NULL; break; } } }
static void *ORLRead( void *_list, size_t len ) /**********************************************/ { file_list *list = _list; void *result; readcache *cache; result = CachePermRead( list, ORLFilePos + ORLPos, len ); ORLPos += len; _ChkAlloc( cache, sizeof( readcache ) ); cache->next = ReadCacheList; ReadCacheList = cache; cache->data = result; return( result ); }
static blk_t * newBlk( cv_t *cv ) /*******************************/ { blk_t * newblk; blk_t ** blklist; _ChkAlloc( newblk, sizeof( blk_t ) - 1 + cv->blk_size ); for( blklist = &cv->blk_list; *blklist > newblk; ) { // keep list sorted by memory address blklist = &(*blklist)->next; // biggest first. } newblk->next = *blklist; *blklist = newblk; cv->blk_count++; cv->size_chg = TRUE; return newblk; }
static void WriteQNXResource( void ) /**********************************/ { unsigned long len; lmf_record rec; f_handle file; lmf_resource resource; void * buf; if( FmtData.resource != NULL ) { rec.reserved = 0; rec.spare = 0; rec.rec_type = LMF_RESOURCE_REC; memset( &resource, 0, sizeof( lmf_resource ) ); if( FmtData.res_name_only ) { file = QObjOpen( FmtData.resource ); if( file == NIL_FHANDLE ) { PrintIOError( WRN+MSG_CANT_OPEN_NO_REASON, "s", FmtData.resource ); return; } len = QFileSize( file ); if( len + sizeof(lmf_resource) > QNX_MAX_REC_SIZE ) { LnkMsg( WRN+MSG_RESOURCE_TOO_BIG, "s", FmtData.resource ); return; } _ChkAlloc( buf, len ); rec.data_nbytes = len + sizeof( lmf_resource ); WriteLoad( &rec, sizeof( lmf_record ) ); WriteLoad( &resource, sizeof( lmf_resource ) ); QRead( file, buf, len, FmtData.resource ); WriteLoad( buf, len ); _LnkFree( buf ); QClose( file, FmtData.resource ); } else { len = strlen( FmtData.resource ); FmtData.resource[len] = '\n'; len++; rec.data_nbytes = len + sizeof( lmf_resource ); WriteLoad( &rec, sizeof( lmf_record ) ); WriteLoad( &resource, sizeof( lmf_resource ) ); WriteLoad( FmtData.resource, len ); } } }
static bool ReadARDict( file_list *list, unsigned long *loc, bool makedict ) /**************************************************************************/ { ar_header *ar_hdr; unsigned long size; int numdicts; numdicts = 0; if( makedict ) { if( list->u.dict == NULL ) { _ChkAlloc( list->u.dict, sizeof( dict_entry ) ); } } for( ;; ) { ar_hdr = CacheRead( list, *loc, sizeof( ar_header ) ); size = GetARValue( ar_hdr->size, AR_SIZE_LEN ); if( ar_hdr->name[0] == '/' && ar_hdr->name[1] == ' ' ) { ++numdicts; *loc += sizeof( ar_header ); if( makedict ) ReadARDictData( list, loc, size, numdicts ); *loc += MAKE_EVEN( size ); } else if( ar_hdr->name[0] == '/' && ar_hdr->name[1] == '/' ) { *loc += sizeof( ar_header ); ReadARStringTable( list, loc, size ); *loc += MAKE_EVEN( size ); } else { break; // found an actual object file } } if( makedict ) { if( numdicts == 0 ) { Locator( list->file->name, NULL, 0 ); LnkMsg( ERR+MSG_NO_DICT_FOUND, NULL ); _LnkFree( list->u.dict ); list->u.dict = NULL; return( FALSE ); } if( !(LinkFlags & CASE_FLAG) || numdicts == 1 ) { SortARDict( &list->u.dict->a ); } } return( TRUE ); }
static void InitSections( ElfHdr *hdr) /************************************/ { int num; group_entry *group; num = 1; memset( &hdr->i, 0, sizeof hdr->i ); hdr->i.secstr = num++; hdr->eh.e_shstrndx = hdr->i.secstr; hdr->i.grpbase = num; hdr->i.grpnum = NumGroups; if( FmtData.dgroupsplitseg != NULL ) { hdr->i.grpnum++; if( StackSegPtr != NULL ) { hdr->i.grpnum++; } } num += hdr->i.grpnum; hdr->i.relbase = num; for( group = Groups; group != NULL; group = group->next_group ) { if( group->g.grp_relocs != NULL ) { hdr->i.relnum++; } } num += hdr->i.relnum; hdr->i.symtab = num++; hdr->i.symstr = num++; hdr->i.symhash = num++; if( INJECT_DEBUG ) { hdr->i.dbgnum = DwarfCountDebugSections(); } hdr->i.dbgbegin = num; num += hdr->i.dbgnum; num += FmtData.u.elf.extrasects; hdr->eh.e_shnum = num; hdr->sh_size = sizeof(Elf32_Shdr) * hdr->eh.e_shnum; _ChkAlloc( hdr->sh, hdr->sh_size ); memset( hdr->sh, 0, hdr->sh_size ); AddSecIdxName(hdr, hdr->i.symtab, ".symtab"); }
void SetPharFmt( void ) /****************************/ { Extension = E_PROTECT; LinkState &= ~MAKE_RELOCS; // do not generate relocations. _ChkAlloc( FmtData.u.phar.params, sizeof( *FmtData.u.phar.params ) ); FmtData.u.phar.mindata = 0; FmtData.u.phar.maxdata = 0xFFFFFFFF; FmtData.u.phar.breaksym = NULL; FmtData.u.phar.stub = NULL; // FmtData.u.phar.pack = false; FmtData.u.phar.params->minreal = 0; FmtData.u.phar.params->maxreal = 0; FmtData.u.phar.params->callbufs = 0; FmtData.u.phar.params->realbreak = 0; FmtData.u.phar.params->minibuf = 1; FmtData.u.phar.params->maxibuf = 4; FmtData.u.phar.params->nistack = 4; FmtData.u.phar.params->istksize = 1; FmtData.u.phar.params->extender_flags = 0; FmtData.u.phar.params->unpriv = 0; ChkBase(4*1024); }
carve_t CarveCreate( unsigned elm_size, unsigned blk_size ) /******************************************************/ { cv_t * cv; elm_size = ROUND_UP( elm_size, sizeof( int ) ); if( elm_size < sizeof( free_t ) ) { elm_size = sizeof( free_t ); } _ChkAlloc( cv, sizeof( *cv ) ); cv->elm_size = elm_size; cv->blk_size = blk_size; cv->elm_count = cv->blk_size / cv->elm_size; cv->blk_top = cv->elm_count * elm_size; cv->blk_count = 0; cv->blk_list = NULL; cv->free_list = NULL; cv->blk_map = NULL; cv->size_chg = FALSE; DbgAssert( cv->elm_size >= 2 * sizeof(void *) ); DbgAssert( cv->elm_count != 0 ); DbgVerify( cv->blk_top < 0x10000, "carve: size * #/block > 64k" ); return( cv ); }
void InitSym( void ) /*************************/ { _ChkAlloc( GlobalSymPtrs, GLOBAL_TABALLOC ); _ChkAlloc( StaticSymPtrs, STATIC_TABALLOC ); }
void *CacheRead( file_list *list, unsigned long pos, unsigned len ) /**************************************************************************/ /* read len bytes out of the cache. */ { unsigned bufnum; unsigned startnum; unsigned offset; unsigned amtread; char *result; char **cache; unsigned long newpos; infilelist *file; if( list->file->flags & INSTAT_FULL_CACHE ) { if( pos + len > list->file->len ) return( NULL ); return( (char *)list->file->cache + pos ); } Multipage = FALSE; file = list->file; offset = pos % CACHE_PAGE_SIZE; amtread = CACHE_PAGE_SIZE - offset; startnum = pos / CACHE_PAGE_SIZE; bufnum = startnum; cache = file->cache; for( ;; ) { if( cache[ bufnum ] == NULL ) { // make sure page is in. _ChkAlloc( cache[ bufnum ], CACHE_PAGE_SIZE ); newpos = (unsigned long)bufnum * CACHE_PAGE_SIZE; if( file->currpos != newpos ) { QSeek( file->handle, newpos, file->name ); } file->currpos = newpos + CACHE_PAGE_SIZE; QRead( file->handle, cache[ bufnum ], CACHE_PAGE_SIZE, file->name ); } if( amtread >= len ) break; amtread += CACHE_PAGE_SIZE; // it spans pages. bufnum++; Multipage = TRUE; } if( !Multipage ) { result = cache[ startnum ] + offset; } else { if( len > TokSize ) { TokSize = ROUND_UP( len, SECTOR_SIZE ); _LnkReAlloc( TokBuff, TokBuff, TokSize ); } amtread = CACHE_PAGE_SIZE - offset; memcpy( TokBuff, cache[ startnum ] + offset, amtread ); len -= amtread; result = TokBuff + amtread; for( ;; ) { startnum++; if( len <= CACHE_PAGE_SIZE ) { memcpy( result, cache[ startnum ], len ); break; } else { memcpy( result, cache[ startnum ], CACHE_PAGE_SIZE ); len -= CACHE_PAGE_SIZE; result += CACHE_PAGE_SIZE; } } result = TokBuff; } return( result ); }
static void SortARDict( ar_dict_entry *ar_dict ) /**********************************************/ { index_type *index_tab; index_type ix; index_type ix_next; index_type ix1; char *symb_save; unsigned_32 offset_save; ar_dict_entry d; if( ar_dict->num_entries < 2 ) return; d = *ar_dict; // store the dictionary pointer into memory so we can fetch ar_dict in ARCompI d_symbtab = d.symbtab; // Create an index table that we will sort to match the // case-insensitive sort order that we want for our symbol names. _ChkAlloc( index_tab, sizeof( index_type ) * d.num_entries ); for( ix = 0; ix < d.num_entries; ix++ ) { index_tab[ix] = ix; } // Sort the index table using the corresponding symbol names // to determine the sort order (see ARCompI() for more info). if( LinkFlags & CASE_FLAG ) { qsort( index_tab, d.num_entries, sizeof( index_type ), ARComp ); } else { qsort( index_tab, d.num_entries, sizeof( index_type ), ARCompI ); } // Reorder the function name table (a vector of pointers to // symbol names) and the offset table (a vector of 16-bit offsets // into the file position table) (see ReadARDict() for info). for( ix = 0; ix < d.num_entries; ++ix ) { // If this entry hasn't been corrected // then move out the entry that is present // so that we can correct it. if( ix != index_tab[ix] ) { symb_save = d.symbtab[ix]; if( d.offsettab == NULL ) { offset_save = d.filepostab[ix]; } else { offset_save = d.offsettab[ix]; } // Correct all the entries in this sequence for( ix1 = ix; (ix_next = index_tab[ix1]) != ix; ix1 = ix_next ) { d.symbtab[ix1] = d.symbtab[ix_next]; if( d.offsettab == NULL ) { d.filepostab[ix1] = d.filepostab[ix_next]; } else { d.offsettab[ix1] = d.offsettab[ix_next]; } index_tab[ix1] = ix1; } // Update this final entry in the sequence from the // values we set aside. d.symbtab[ix1] = symb_save; if( d.offsettab == NULL ) { d.filepostab[ix1] = offset_save; } else { d.offsettab[ix1] = offset_save; } index_tab[ix1] = ix1; } } _LnkFree( index_tab ); }
static void ReadARDictData( file_list *list, unsigned long *loc, unsigned size, int numdicts ) /********************************************************************************************/ { ar_dict_entry *dict; char *data; unsigned_32 num; unsigned_32 index; /* a dictionary in an AR archive commonly starts with a header marked with '/ '. Be careful, more AR formats exists, GNU, BSD and COFF. Each handle dictionaries a little bit different way. GNU (Linux) and BSD AR archives commonly have only one dictionary which is of the form: (all numbers in *big* endian format) unsigned_32: number of entries (num) num unsigned_32's: offset within AR file of the object file that the symbol name belongs too. num zero terminated strings: the symbols themselves (unsorted). COFF AR archieves however use two dictionaries. First one is the same as for GNU and BSD, but WLINK uses second one, more efficient dictionary: (all numbers in *little* endian format) unsigned_32: number of files in object nfiles unsigned_32's: offsets of the files within the archive unsigned_32: number of entries (num) num unsigned_16's: the file number that the symbol belongs to num zero terminated strings: the symbols themselves (sorted case-sensitively). however WLINK needs to be able to parse both kinds. (dict->offsettab == NULL) means that we only know about an unsorted dictionary and it will be sorted later. */ dict = &list->u.dict->a; data = CachePermRead( list, *loc, size ); if( numdicts == 1 ) { num = _ReadBigEndian32UN( data ); /* number of symbols */ data += sizeof( unsigned_32 ); dict->filepostab = (unsigned_32 *)data; for( index = 0; index < num; index++ ) { dict->filepostab[index] = _ReadBigEndian32UN( data ); data += sizeof( unsigned_32 ); } dict->num_entries = num; dict->offsettab = NULL; dict->symbtab = NULL; if( num > 0 ) { _ChkAlloc( dict->symbtab, sizeof( char * ) * num ); } } else /* if( numdicts == 2 ) */ { num = _ReadLittleEndian32UN( data ); /* number of files */ data += sizeof( unsigned_32 ); dict->filepostab = (unsigned_32 *)data; /* first file off */ for( index = 0; index < num; index++ ) { dict->filepostab[index] = _ReadLittleEndian32UN( data ); data += sizeof( unsigned_32 ); } num = _ReadLittleEndian32UN( data ); /* number of symbols */ data += sizeof( unsigned_32 ); dict->offsettab = (unsigned_16 *)data; /* first offset */ for( index = 0; index < num; index++ ) { dict->offsettab[index] = _ReadLittleEndian16UN( data ); data += sizeof( unsigned_16 ); } dict->num_entries = num; if( num > 0 && dict->symbtab == NULL ) { _ChkAlloc( dict->symbtab, sizeof( char * ) * num ); } } for( index = 0; index < num; index++ ) { dict->symbtab[index] = data; data += strlen( data ) + 1; } }