ovlsupp.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 835 行 · 第 1/2 页
C
835 行
if( sym->p.seg == NULL )
return;
/* at this point, we know it has already been defined, but does */
/* not have an overlay vector, and is not data */
ovl_num = sym->p.seg->u.leader->class->section->ovl_num;
if( IsAncestor( ovl_num, CurrSect ) )
return;
/* overlay vector necessary */
Vectorize( sym );
}
}
extern void TryRefVector( symbol * sym )
/**************************************/
{
if( !( FmtData.type & MK_OVERLAYS ) )
return;
if( ( LinkState & SEARCHING_LIBRARIES ) && FmtData.u.dos.distribute ) {
RefDistribSym( sym );
} else {
OvlRefVector( sym );
}
}
extern void OvlUseVector( symbol * sym, extnode *newnode )
/********************************************************/
{
if( !( FmtData.type & MK_OVERLAYS ) )
return;
if( IS_SYM_COMMUNAL( sym ) )
return;
if( ( sym->u.d.ovlstate & OVL_VEC_MASK ) != OVL_MAKE_VECTOR )
return;
if( IsAncestor( sym->p.seg->u.leader->class->section->ovl_num, CurrSect ) ) {
return;
}
/* use overlay vector for all calls */
newnode->ovlref = sym->u.d.ovlref;
}
extern void IndirectCall( symbol *sym )
/*************************************/
{
unsigned_16 ovl_num;
if( !( FmtData.type & MK_OVERLAYS ) )
return;
if( NO_VECTOR( sym ) )
return;
if( sym->info & SYM_DEFINED ) {
if( sym->info & SYM_DISTRIB ) {
DistIndCall( sym );
} else if( sym->p.seg != NULL ) {
ovl_num = sym->p.seg->u.leader->class->section->ovl_num;
if( ( ovl_num != 0 ) && sym->p.seg->iscode ) {
Vectorize( sym );
}
}
} else {
// indicate a reference from the root for purposes of vector generation
sym->u.d.ovlstate |= OVL_REF;
sym->u.d.ovlref = 0;
}
}
extern void GetVecAddr( int vecnum, targ_addr *addr )
/***************************************************/
/* return address of overlay vector in canonical form */
{
*addr = OvlvecAddr;
if( FmtData.u.dos.ovl_short ) {
/* short address -- fits into 16 bits */
addr->off += ( vecnum - 1 ) * sizeof( svector ) + ( addr->seg << FmtData.SegShift );
addr->seg = 0;
} else {
addr->off += ( vecnum - 1 ) * sizeof( lvector );
}
}
extern bool CheckOvlClass( char *clname, bool *isovlclass )
/*********************************************************/
/* check if among overlay classes, and return TRUE if it is code. */
{
list_of_names * cnamelist;
bool retval;
retval = IsCodeClass( clname, strlen( clname ) );
cnamelist = OvlClasses;
if( cnamelist == NULL ) { /* check for anything ending in code */
*isovlclass = retval;
return( retval );
} else {
do {
if( stricmp( clname, cnamelist->name ) == 0 ) {
*isovlclass = TRUE;
return( retval );
}
cnamelist = cnamelist->next_name;
} while( cnamelist != NULL );
}
*isovlclass = FALSE;
return( FALSE );
}
extern section * CheckOvlSect( char *clname )
/*******************************************/
{
section * sect;
bool dummy;
sect = DBIGetSect( clname );
if( sect == NULL ) {
if( CheckOvlClass( clname, &dummy ) ) {
sect = CurrSect;
} else {
sect = NonSect;
}
}
return( sect );
}
extern void EmitOvlVectors( void )
/********************************/
{
symbol * symptr;
dos_addr addr;
char * loader_name;
bool isshort;
/* output relocation items for overlay table */
addr.seg = OvlGroup->grp_addr.seg;
addr.off = OvltabAddr.off + offsetof( ovltab_prolog, start.seg );
WriteReloc( OvlGroup, addr.off, &addr, sizeof( dos_addr ) );
addr.off = OvltabAddr.off + offsetof( ovltab_prolog, delta );
WriteReloc( OvlGroup, addr.off, &addr, sizeof( dos_addr ) );
isshort = FALSE;
if( FmtData.u.dos.dynamic ) {
loader_name = _DynamicOvlldr;
} else if( FmtData.u.dos.ovl_short ) {
loader_name = _ShortOvlldr;
isshort = TRUE;
} else {
loader_name = _LongOvlldr;
}
symptr = RefISymbol( loader_name );
if( !( symptr->info & SYM_DEFINED ) ) {
LnkMsg( ERR+MSG_NO_OVERLAY_LOADER, NULL );
} else if( isshort ) {
ShortVectors( symptr );
} else {
LongVectors( symptr );
}
}
static void ShortVectors( symbol *loadsym )
/*****************************************/
{
vecnode *vec;
unsigned vect_off;
unsigned_32 loadval;
unsigned_32 temp;
signed_32 diff;
int vecnum;
svector template;
vect_off = OvlvecAddr.off;
temp = MK_REAL_ADDR( OvlvecAddr.seg, OvlvecAddr.off );
/* get loader address */
loadval = MK_REAL_ADDR( loadsym->addr.seg, loadsym->addr.off );
/* fill in overlay vector template */
template.call_op = 0xe8;
template.jmp_op = 0xe9;
vecnum = 1;
for( vec = OvlVectors; vec != NULL; vec = vec->next ) {
temp = vect_off + offsetof( svector, ldr_addr ) + sizeof( unsigned_16 );
diff = loadval - temp;
if( ( diff < -32768 ) || ( diff > 32767 ) ) {
LnkMsg( ERR+MSG_SHORT_VECT_RANGE, "d", vecnum );
}
_HostU16toTarg( diff, template.ldr_addr );
loadsym = vec->entry;
_HostU16toTarg( loadsym->p.seg->u.leader->class->section->ovl_num,
template.sec_num );
temp = vect_off + offsetof( svector, target ) + sizeof( unsigned_16 );
diff = MK_REAL_ADDR( loadsym->addr.seg, loadsym->addr.off ) - temp;
if( ( diff < -32768 ) || ( diff > 32767 ) ) {
LnkMsg( ERR+MSG_SHORT_VECT_RANGE, "d", vecnum );
}
_HostU16toTarg( diff, template.target );
PutOvlInfo( vect_off, &template, sizeof( svector ) );
vect_off += sizeof( svector );
++vecnum;
}
}
static void LongVectors( symbol *loadsym )
/****************************************/
{
vecnode *vec;
unsigned vect_off;
lvector template;
dos_addr addr;
signed_32 diff;
unsigned_32 loadval;
unsigned_32 temp;
int vecnum;
vect_off = OvlvecAddr.off;
/* fill in overlay vector template */
template.u.v.call_op = 0xe8;
template.jmp_op = 0xea;
loadval = loadsym->addr.off;
addr.seg = OvlGroup->grp_addr.seg;
vecnum = 1;
for( vec = OvlVectors; vec != NULL; vec = vec->next ) {
temp = vect_off + offsetof( lvector, u.v.ldr_addr ) + sizeof( unsigned_16 );
diff = loadval - temp;
if( ( diff < -32768 ) || ( diff > 32767 ) ) {
LnkMsg( ERR+MSG_SHORT_VECT_RANGE, "d", vecnum );
}
_HostU16toTarg( diff, template.u.v.ldr_addr );
loadsym = vec->entry;
_HostU16toTarg( loadsym->p.seg->u.leader->class->section->ovl_num,
template.u.v.sec_num );
_HostU16toTarg( loadsym->addr.off, template.target.off );
if( FmtData.u.dos.dynamic ) {
_HostU16toTarg( loadsym->addr.seg
- loadsym->p.seg->u.leader->group->grp_addr.seg,
template.target.seg );
} else {
_HostU16toTarg( loadsym->addr.seg, template.target.seg );
addr.off = vect_off + offsetof( lvector, target.seg );
WriteReloc( OvlGroup, addr.off, &addr, sizeof( dos_addr ) );
}
PutOvlInfo( vect_off, &template, sizeof( lvector ) );
vect_off += sizeof( lvector );
vecnum++;
}
}
extern void SetOvlStartAddr( void )
/*********************************/
{
symbol * sym;
/* stuff overlay init routine address in header */
Stash = StartInfo.addr;
if( FmtData.u.dos.dynamic ) {
sym = FindISymbol( _DynamicInitRtn );
} else if( FmtData.u.dos.ovl_short ) {
sym = FindISymbol( _ShortOvlInitRtn );
} else {
sym = FindISymbol( _LongOvlInitRtn );
}
if( sym == NULL )
return;
if( sym->info & SYM_DEFINED ) {
StartInfo.addr = sym->addr;
}
}
extern void OvlPass1( void )
/**************************/
{
symbol * sym;
ProcAllOvl( LoadObjFiles );
/* define symbols for overlay table */
OverlayTable = DefISymbol( _OvltabName );
OverlayTableEnd = DefISymbol( _OvltabEndName );
OvlVecStart = DefISymbol( _OvlVecStartName );
OvlVecEnd = DefISymbol( _OvlVecEndName );
OvlSeg = InitLeader( "", 0 );
OvlSeg->class = FindClass( Root, OvlMgrClass, 0, 1 );
OvlSeg->combine = COMBINE_INVALID;
OvlSegData = AllocSegData();
OvlSegData->u.leader = OvlSeg;
OverlayTable->p.seg = OvlSegData;
OverlayTableEnd->p.seg = OvlSegData;
OvlVecStart->p.seg = OvlSegData;
OvlVecEnd->p.seg = OvlSegData;
/* generate reference for overlay loader */
if( FmtData.u.dos.dynamic ) {
RefISymbol( _DynamicInitRtn );
sym = RefISymbol( _DynamicOvlldr );
} else if( FmtData.u.dos.ovl_short ) {
RefISymbol( _ShortOvlInitRtn );
sym = RefISymbol( _ShortOvlldr );
} else {
RefISymbol( _LongOvlInitRtn );
sym = RefISymbol( _LongOvlldr );
}
sym->u.d.ovlref = 0;
sym->u.d.ovlstate |= OVL_REF;
}
static unsigned EmitOvlEntry( unsigned off, section *sect )
/*********************************************************/
{
ovltab_entry entry;
offset len;
unsigned_16 flags_anc;
unsigned_16 start_para;
_HostU16toTarg( 0, entry.code_handle );
for( ; sect != NULL; sect = sect->next_sect ) {/* write out table entry */
flags_anc = sect->parent->ovl_num;
if( sect == NonSect ) {
flags_anc |= OVE_FLAG_PRELOAD;/* pre-load the data area */
}
_HostU16toTarg( sect->outfile->ovlfnoff, entry.fname );
_HostU16toTarg( sect->relocs, entry.relocs );
_HostU16toTarg( flags_anc, entry.flags_anc );
start_para = sect->sect_addr.seg + ( sect->sect_addr.off >> FmtData.SegShift );
_HostU16toTarg( start_para, entry.start_para );
len = sect->size + 15 >> 4;
_HostU16toTarg( len, entry.num_paras );
_HostU32toTarg( sect->u.file_loc, entry.disk_addr );
PutOvlInfo( off, &entry, sizeof( entry ) );
off += sizeof( ovltab_entry );
off = EmitOvlAreaEntry( off, sect->areas );
}
return( off );
}
static unsigned EmitOvlAreaEntry( unsigned off, OVL_AREA *area )
{
for( ; area != NULL; area = area->next_area ) {
off = EmitOvlEntry( off, area->sections );
}
return( off );
}
extern void EmitOvlTable( void )
/******************************/
/* generate overlay table */
{
unsigned off;
ovltab_prolog template;
unsigned_16 u16;
int len;
outfilelist * fnode;
off = OvltabAddr.off;
/*
Generate prolog :
*/
template.major = OVL_MAJOR_VERSION;
template.minor = OVL_MINOR_VERSION;
/*
output start address for program
reloc for this was emitted by EmitOvlVectors
*/
_HostU16toTarg( Stash.off, template.start.off );
_HostU16toTarg( Stash.seg, template.start.seg );
/*
this should give us the paragraph of the load module start
reloc for this was emitted by EmitOvlVectors
*/
_HostU16toTarg( 0, template.delta );
_HostU16toTarg( AreaSize, template.ovl_size );
PutOvlInfo( off, &template, sizeof( template ) );
/*
Generate entries :
*/
off += sizeof( template );
off = EmitOvlAreaEntry( off, Root->areas );
/*
Generate epilog :
*/
u16 = OVLTAB_TERMINATOR;
PutOvlInfo( off, &u16, sizeof( unsigned_16 ) );
off += sizeof( unsigned_16 );
/* generate overlay filenames, including NULLCHARS*/
fnode = OutFiles;
while( fnode != NULL ) {
len = strlen( fnode->fname ) + 1;
PutOvlInfo( off, fnode->fname, len );
off += len;
fnode = fnode->next;
}
}
extern void PadOvlFiles( void )
/*****************************/
// The overlay files must contain a complete paragraph at the end of the file
// for the overlay loader to be able to correctly read it.
{
outfilelist * fnode;
unsigned pad;
fnode = OutFiles;
for( fnode = OutFiles; fnode != NULL; fnode = fnode->next ) {
pad = FmtData.SegMask + 1 - ( fnode->file_loc & FmtData.SegMask );
if( pad != 16 ) {
if( fnode->handle == NIL_HANDLE ) {
OpenOvlFile( fnode );
}
PadBuffFile( fnode, pad );
}
}
}
static void PutOvlInfo( unsigned off, void *src, unsigned len )
/*************************************************************/
{
PutInfo( OvlSegData->data + off - OvlGroup->grp_addr.off, src, len );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?