libr.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 739 行 · 第 1/2 页
C
739 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
/*
* LIB : search library file.
*
*/
#include <stdlib.h>
#include <string.h>
#include "linkstd.h"
#include "pcobj.h"
#include "msg.h"
#include "alloc.h"
#include "wlnkmsg.h"
#include "library.h"
#include "objnode.h"
#include "fileio.h"
#include "objio.h"
#include "objcache.h"
#include <ar.h>
typedef struct omf_dict_entry {
void ** cache; /* for extra memory store of dictionary */
unsigned_32 start; /* recno of start of dictionary */
unsigned_16 pages; /* number of pages in dictionary */
unsigned_16 rec_length; /* record alignment of obj recs */
byte * buffer;
} omf_dict_entry;
typedef struct ar_dict_entry {
unsigned_32 * filepostab;
unsigned_16 * offsettab;
char ** fnametab;
unsigned_32 num_entries;
} ar_dict_entry;
typedef union dict_entry {
omf_dict_entry o;
ar_dict_entry a;
} dict_entry;
#define PAGES_IN_CACHE 0x40U
static bool OMFSearchExtLib( file_list *, char *, unsigned long * );
static bool ARSearchExtLib( file_list *, char *, unsigned long * );
static unsigned_16 OMFCompName( char *, char *, unsigned_16 );
static void ** AllocDict( unsigned_16, unsigned_16 );
static void SetDict( file_list *, unsigned_16 );
#if (defined( __386__ ) || defined(M_I86)) && defined(__WATCOMC__)
#if defined( __386__ )
#define DATA16 0x66
#else
#define DATA16
#endif
unsigned_16 Rotr16( unsigned_16 value, unsigned_16 shift );
#pragma aux Rotr16 =\
DATA16 0xd3 0xc8 /* ror ax,cl */ \
parm [ax] [cx] \
value [ax];
unsigned_16 Rotl16( unsigned_16 value, unsigned_16 shift );
#pragma aux Rotl16 =\
DATA16 0xd3 0xc0 /* rol ax,cl */ \
parm [ax] [cx] \
value [ax];
#else
static unsigned_16 Rotr16( unsigned_16 value, unsigned_16 shift )
/***************************************************************/
{
return (value << (16 - shift)) | (value >> shift);
}
static unsigned_16 Rotl16( unsigned_16 value, unsigned_16 shift )
/***************************************************************/
{
return (value >> (16 - shift)) | (value << shift);
}
#endif
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 );
}
static unsigned_32 ReadBigEndian32( unsigned char *buf )
{
unsigned_32 res = 0;
res = buf[0];
res <<= 8;
res |= buf[1];
res <<= 8;
res |= buf[2];
res <<= 8;
res |= buf[3];
return res;
}
static bool ReadARDict( file_list *list, unsigned long *loc, unsigned *numdicts,
bool makedict )
/*****************************************************************************/
{
ar_header * ar_hdr;
unsigned long size;
ar_dict_entry * dict;
char * data;
unsigned_32 num;
unsigned index;
bool retval;
ar_hdr = CacheRead( list, *loc, sizeof(ar_header) );
size = GetARValue( ar_hdr->size, AR_SIZE_LEN );
retval = TRUE;
if( ar_hdr->name[0] == '/' && ar_hdr->name[1] == ' ' ) {
*numdicts += 1;
*loc += sizeof(ar_header);
if( makedict && (*numdicts == 1 || *numdicts == 2) ) {
/* a dictionary in an AR archive commonly starts with
a header marked with '/ '.
AR archives on Linux 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).
WLIB however calls this the "useless dictionary".
WLIB generates a second, 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 = ReadBigEndian32( data ); /* number of symbols */
data += sizeof(unsigned_32);
dict->filepostab = (unsigned_32 *) data;
for( index = 0; index < num; index++ ) {
dict->filepostab[index] = ReadBigEndian32(data);
data += sizeof(unsigned_32);
}
dict->num_entries = num;
dict->offsettab = NULL;
dict->fnametab = NULL;
if( num > 0 ) {
_ChkAlloc( dict->fnametab, sizeof(char *) * num );
}
} else /* if ( *numdicts == 2 ) */ {
num = *((unsigned_32 *)data); /* number of files */
data += sizeof(unsigned_32);
dict->filepostab = (unsigned_32 *) data; /* first file off */
data += num * sizeof(unsigned_32);
num = *((unsigned_32 *)data); /* number of symbols */
data += sizeof(unsigned_32);
dict->offsettab = (unsigned_16 *) data; /* first offset */
data += num * sizeof(unsigned_16);
dict->num_entries = num;
if( num > 0 && dict->fnametab == NULL ) {
_ChkAlloc( dict->fnametab, sizeof(char *) * num );
}
}
for( index = 0; index < num; index++ ) {
dict->fnametab[index] = data;
data = strchr( data, '\0' ) + 1;
}
}
*loc += MAKE_EVEN( size );
} else if( ar_hdr->name[0] == '/' && ar_hdr->name[1] == '/' ) {
*loc += sizeof(ar_header);
list->strtab = CachePermRead( list, *loc, size );
*loc += MAKE_EVEN( size );
} else {
retval = FALSE; // found an actual object file
}
return retval;
}
static ar_dict_entry *ARDict; /* pointer to AR dictionary structures */
static int ARCompI( const void *index1, const void *index2 )
/**********************************************************/
{
return stricmp( ARDict->fnametab[ *(unsigned_16 *)index1 ],
ARDict->fnametab[ *(unsigned_16 *)index2 ] );
}
static int ARComp( const void *index1, const void *index2 )
/**********************************************************/
{
return strcmp( ARDict->fnametab[ *(unsigned_16 *)index1 ],
ARDict->fnametab[ *(unsigned_16 *)index2 ] );
}
extern int CheckLibraryType( file_list *list, unsigned long *loc, bool makedict)
/******************************************************************************/
{
lib_header * omf_hdr;
unsigned_8 * header;
int reclength;
omf_dict_entry * omf_dict;
ar_dict_entry * ar_dict;
unsigned numdicts;
unsigned_16 * index_tab;
unsigned ix;
unsigned ix_next;
unsigned ix_save;
char * fname_save;
unsigned_32 offset_save;
omf_hdr = CacheRead( list, 0, sizeof(lib_header) );
header = (unsigned_8*) omf_hdr;
reclength = 0;
if( makedict ) {
_ChkAlloc( list->u.dict, sizeof(dict_entry) );
}
if( header[0] == 0xf0 && header[1] == 0x01 ) {
// COFF object for PPC
} else if( omf_hdr->cmd == LIB_HEADER_REC ) { // reading from a library
list->status |= STAT_OMF_LIB;
omf_dict = &list->u.dict->o;
_TargU16toHost( omf_hdr->length, reclength );
reclength += 3;
if( makedict ) {
omf_dict->cache = NULL;
if( omf_hdr->dict_start == 0 || omf_hdr->dict_size == 0 ) {
BadLibrary( list );
return -1;
}
_TargU16toHost( omf_hdr->dict_size, omf_dict->pages );
_TargU32toHost( omf_hdr->dict_start, omf_dict->start );
omf_dict->rec_length = reclength;
}
*loc = CalcAlign( sizeof(lib_header), reclength ) + sizeof(lib_header);
} else if( memcmp( (void *)omf_hdr, AR_IDENT, AR_IDENT_LEN ) == 0 ) {
list->status |= STAT_AR_LIB;
reclength = 2;
*loc = AR_IDENT_LEN;
numdicts = 0;
while( ReadARDict( list, loc, &numdicts, makedict ) ) {} // NULL loop
if( numdicts < 1 && makedict ) {
Locator( list->file->name, NULL, 0 );
LnkMsg( ERR+MSG_NO_DICT_FOUND, NULL );
_LnkFree( list->u.dict );
list->u.dict = NULL;
return -1;
}
ar_dict = &list->u.dict->a;
if( (!(LinkFlags & CASE_FLAG) || numdicts == 1) &&
(ar_dict->num_entries > 0) ) {
// 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(unsigned_16) * ar_dict->num_entries );
for( ix = 0; ix < ar_dict->num_entries; ix++ ) {
index_tab[ix] = ix;
}
// store the dictionary pointer into memory so we can fetch ar_dict in ARCompI
ARDict = ar_dict;
// 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, ar_dict->num_entries, sizeof(unsigned_16),
ARComp );
} else {
qsort( index_tab, ar_dict->num_entries, sizeof(unsigned_16),
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 < ar_dict->num_entries; ) {
ix_save = 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] ) {
fname_save = ar_dict->fnametab[ix];
if (ar_dict->offsettab == NULL)
offset_save = ar_dict->filepostab[ix];
else
offset_save = ar_dict->offsettab[ix];
// Correct all the entries in this sequence
for(;;) {
ix_next = index_tab[ix];
index_tab[ix] = ix;
if( ix_next == ix_save ) break;
ar_dict->fnametab[ix] = ar_dict->fnametab[ix_next];
if (ar_dict->offsettab == NULL)
ar_dict->filepostab[ix] = ar_dict->filepostab[ix_next];
else
ar_dict->offsettab[ix] = ar_dict->offsettab[ix_next];
ix = ix_next;
}
// Update this final entry in the sequence from the
// values we set aside.
ar_dict->fnametab[ix] = fname_save;
if (ar_dict->offsettab == NULL)
ar_dict->filepostab[ix] = offset_save;
else
ar_dict->offsettab[ix] = offset_save;
}
ix = ix_save + 1;
}
_LnkFree( index_tab );
}
}
return reclength;
}
extern mod_entry * SearchLib( file_list *lib, char *name )
/********************************************************/
/* Search the specified library file for the specified name & make a module */
{
mod_entry * obj;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?