objcalc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,292 行 · 第 1/3 页
C
1,292 行
/****************************************************************************
*
* 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: Address calculation for pass 2 of wlink.
*
****************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include "linkstd.h"
#include "pcobj.h"
#include "newmem.h"
#include "msg.h"
#include "alloc.h"
#include "specials.h"
#include "loados2.h"
#include "loadpe.h"
#include "loadqnx.h"
#include "loadelf.h"
#include "loadfile.h"
#include "wlnkmsg.h"
#include "overlays.h"
#include "dbgall.h"
#include "objcalc.h"
#include "ring.h"
#include "mapio.h"
#include "virtmem.h"
static struct {
char *name;
char idx;
} FloatNames[] = {
{ "FIWRQQ", FFIX_WR_SYMBOL },
{ "FIDRQQ", FFIX_DR_SYMBOL },
{ "FIERQQ", FFIX_ES_OVERRIDE },
{ "FICRQQ", FFIX_CS_OVERRIDE },
{ "FISRQQ", FFIX_SS_OVERRIDE },
{ "FIARQQ", FFIX_DS_OVERRIDE },
{ "FJCRQQ", FFIX_IGNORE },
{ "FJSRQQ", FFIX_IGNORE },
{ "FJARQQ", FFIX_IGNORE }
};
static unsigned long NumMapSyms;
static seg_leader * FindASeg( class_entry *, char * );
static void SortSegments( void );
static void ReOrderClasses( section *sec );
static void AllocSeg( void * );
static void AllocFileSegs( void );
static void ReallocFileSegs( void );
static void FindUninitDataStart( void );
static void CalcGrpAddr( group_entry *currgrp );
static void DefinePublics( void );
static void WriteSymArray( symbol ** symarray, unsigned num );
static void FillClassFlags( char *name, unsigned_16 flags );
static void FillTypeFlags( unsigned_16 flags, segflag_type type );
static void FindFloatSyms( void );
static void CheckClassUninitialized( class_entry * currcl );
static void SortClasses ( section *sec );
extern void CheckClassOrder( void )
/*********************************/
/* Reorder the classes if DOSSEG flag set or ORDER directive given */
{
SortSegments();
if( Root->orderlist != NULL ) {
SortClasses( Root );
}
else if( LinkState & DOSSEG_FLAG ) {
ReOrderClasses( Root );
}
}
static void ReOrderAreas( OVL_AREA *ovl )
/***************************************/
{
for( ; ovl != NULL; ovl = ovl->next_area ) {
ReOrderClasses( ovl->sections );
}
}
enum class_orders {
ORD_REALMODE,
ORD_BEGCODE,
ORD_CODE,
ORD_OVLMGR,
ORD_OTHER,
ORD_BEGDGROUP,
ORD_DATA,
ORD_INITDGROUP,
ORD_UNINITDGROUP,
ORD_BSS,
ORD_STACK,
ORD_LAST = ORD_STACK,
ORD_FIRST = 0
};
static void ReOrderClasses( section *sec )
/****************************************/
// rebuild the class list using the Microsoft DOS segment ordering.
// This builds various classes into separate rings, and then joins them
// together.
{
class_entry *rings[ORD_LAST+1];
class_entry *nextcl;
class_entry *currcl;
class_entry **owner;
seg_leader *currseg;
seg_leader *prevseg;
char *name;
int i;
int ord;
while( sec != NULL ) {
for( i = ORD_FIRST; i <= ORD_LAST; ++i ) {
rings[i] = NULL;
}
currcl = sec->classlist;
while( currcl != NULL ) {
nextcl = currcl->next_class;
currcl->next_class = NULL;
CheckClassUninitialized( currcl );
if( ( FmtData.type & ( MK_NOVELL | MK_PHAR_LAP | MK_OS2_LX ) )
&& !( currcl->flags & CLASS_32BIT ) ) {
ord = ORD_REALMODE;
} else {
name = currcl->name;
if( currcl->flags & CLASS_CODE ) {
if( stricmp( name, OvlMgrClass ) == 0 ) {
ord = ORD_OVLMGR;
} else if( stricmp( name, BegCodeClassName ) == 0 ) {
ord = ORD_BEGCODE;
} else {
ord = ORD_CODE;
}
} else if( ( currcl->segs == NULL )
|| ( currcl->segs->group == NULL )
|| ( currcl->segs->group != DataGroup ) ) {
ord = ORD_OTHER;
} else { // it's the DGROUP segments.
if( stricmp( name, BSSClassName ) == 0 ) {
ord = ORD_BSS;
} else if( stricmp( name, StackClassName ) == 0 ) {
ord = ORD_STACK;
} else if( stricmp( name, BegDataClassName ) == 0 ) {
ord = ORD_BEGDGROUP;
} else if( stricmp( name, DataClassName ) == 0 ) {
ord = ORD_DATA;
} else if( currcl->flags & CLASS_LXDATA_SEEN ) {
ord = ORD_INITDGROUP;
} else {
ord = ORD_UNINITDGROUP;
}
}
}
/* add the class to the appropriate ring */
/* 'rings[ord]' points to the _last_ element of the ring */
if( rings[ord] == NULL ) {
currcl->next_class = currcl;
} else {
currcl->next_class = rings[ord]->next_class;
rings[ord]->next_class = currcl;
}
rings[ord] = currcl;
currcl = nextcl;
}
/* move the BEGTEXT segment in CODE class to front of segment list */
currcl = rings[ORD_CODE];
if( currcl != NULL ) {
do {
prevseg = currcl->segs;
if( prevseg == NULL )
break;
currseg = prevseg->next_seg;
for( ;; ) {
if( stricmp( currseg->segname, BegTextSegName ) == 0 ) {
RingPromote( &currcl->segs, currseg, prevseg );
break;
}
if( currseg == currcl->segs )
break;
prevseg = currseg;
currseg = currseg->next_seg;
}
currcl = currcl->next_class;
} while( currcl != rings[ORD_CODE] );
}
/* now construct list out of the collected parts. */
owner = &sec->classlist;
for( i = ORD_FIRST; i <= ORD_LAST; ++i ) {
if( rings[i] != NULL ) {
*owner = rings[i]->next_class;
owner = &rings[i]->next_class;
}
}
*owner = NULL;
ReOrderAreas( sec->areas );
sec = sec->next_sect;
}
}
static void SortAreas( OVL_AREA *ovl )
/***************************************/
{
for( ; ovl != NULL; ovl = ovl->next_area ) {
SortClasses( ovl->sections );
}
}
static void SortClasses( section *sec )
/****************************************/
// rebuild the class list in the order specified by the ORDER directive
// This builds various classes into separate rings, and then joins them
// together. Pass class and segment address and output information
// to the class and segment structures. Sort segments in a class if
// information is provided.
{
class_entry *DefaultRing; // Where to put classes that don't match anything
class_entry *nextcl;
class_entry *currcl;
class_entry **NewRing;
class_entry **owner;
seg_leader *currseg;
seg_leader *prevseg;
ORDER_CLASS *MatchClass;
ORDER_SEGMENT *MatchSeg;
DefaultRing = NULL;
while( sec != NULL ) {
currcl = sec->classlist;
while( currcl != NULL ) {
nextcl = currcl->next_class; // Take class out of original ring
currcl->next_class = NULL;
CheckClassUninitialized( currcl );
NewRing = &DefaultRing; // In case no special class is found
for( MatchClass = sec->orderlist; MatchClass != NULL; MatchClass = MatchClass->NextClass ) {
if( stricmp( currcl->name, MatchClass->Name ) == 0 ) { // search order list for name match
NewRing = &(MatchClass->Ring); // if found save ptr to instance
if( MatchClass->FixedAddr) { // and copy any flags or address from it
currcl->flags |= CLASS_FIXED;
currcl->BaseAddr = MatchClass->Base;
FmtData.base = 0; // Otherwise PE will use default and blow up
}
if( MatchClass->NoEmit ) {
currcl->flags |= CLASS_NOEMIT;
}
break;
}
}
// add the class to front of ring attached to order class, or to default ring
if( *NewRing == NULL ) {
currcl->next_class = currcl;
}
else {
currcl->next_class = (*NewRing)->next_class;
(*NewRing)->next_class = currcl;
}
*NewRing = currcl;
currcl = nextcl;
}
// Now re-arrange segments in any order classes for which we have segments specified
for( MatchClass = sec->orderlist; MatchClass != NULL; MatchClass = MatchClass->NextClass ) {
for( MatchSeg = MatchClass->SegList; MatchSeg != NULL; MatchSeg = MatchSeg->NextSeg ) {
currcl = MatchClass->Ring;
do {
prevseg = currcl->segs;
if( prevseg == NULL )
break;
currseg = prevseg->next_seg;
for( ;; ) {
if( stricmp( currseg->segname, MatchSeg->Name ) == 0 ) {
if( MatchSeg->FixedAddr) { // and copy any flags or address from it
currseg->segflags |= SEG_FIXED;
currseg->seg_addr = MatchSeg->Base;
}
if( MatchSeg->NoEmit ) {
currseg->segflags |= SEG_NOEMIT;
}
RingPromote( &currcl->segs, currseg, prevseg );
break;
}
if( currseg == currcl->segs ) {
break;
}
prevseg = currseg;
currseg = currseg->next_seg;
}
currcl = currcl->next_class;
} while( currcl != MatchClass->Ring );
}
}
/* now construct list out of the collected parts. */
owner = &sec->classlist;
for( MatchClass = sec->orderlist; MatchClass != NULL; MatchClass = MatchClass->NextClass ) {
if( MatchClass->Ring != NULL ) {
*owner = MatchClass->Ring->next_class;
owner = &(MatchClass->Ring->next_class);
}
}
if( DefaultRing != NULL ) { // Finish with unmatched ones
*owner = DefaultRing->next_class;
owner = &(DefaultRing->next_class);
}
*owner = NULL;
// This has to happen after the class list is rebuilt, so it can be searched
for( MatchClass = sec->orderlist; MatchClass != NULL; MatchClass = MatchClass->NextClass ) {
if( MatchClass->Copy && MatchClass->Ring != NULL ) { // If this is a duplicate destination, find the source
for( currcl = sec->classlist; currcl != NULL; currcl = currcl->next_class ) {
if( stricmp( MatchClass->SrcName, currcl->name ) == 0 ) {
MatchClass->Ring->DupClass = currcl;
MatchClass->Ring->flags |= CLASS_COPY;
break;
}
}
}
}
SortAreas( sec->areas ); // Not tested, not sure if needed
sec = sec->next_sect;
}
}
static bool CheckLxdataSeen( void *_seg, void *dummy )
/****************************************************/
{
seg_leader *seg = _seg;
dummy = dummy;
if( seg->info & SEG_LXDATA_SEEN ) {
seg->class->flags |= CLASS_LXDATA_SEEN;
return( TRUE );
}
return( FALSE );
}
static void CheckClassUninitialized( class_entry * currcl )
/*********************************************************/
{
RingLookup( currcl->segs, CheckLxdataSeen, NULL );
}
static void InsertPrevRing( seg_leader **list, seg_leader *curr,
seg_leader *prev )
/**************************************************************/
{
if( prev == NULL ) {
RingPush( list, curr );
} else {
RingInsert( list, curr, prev );
}
}
static void SortSegments( void )
/******************************/
// reorder segments based on COFF name grouping
{
class_entry *currcl;
seg_leader *prev;
seg_leader *curr;
seg_leader *comp;
seg_leader *newlist;
char *dollarpos;
size_t currlen;
size_t complen;
bool foundgroup; // so we don't search for OMF only.
bool foundmatch;
bool added;
for( currcl = Root->classlist; currcl != NULL; currcl = currcl->next_class ){
foundgroup = FALSE;
newlist = NULL;
curr = RingPop( &currcl->segs );
while( curr != NULL ) {
dollarpos = strchr( curr->segname, '$' );
if( dollarpos != NULL ) {
currlen = dollarpos - curr->segname;
foundgroup = TRUE;
} else {
currlen = strlen( curr->segname );
}
added = FALSE;
if( foundgroup ) {
prev = NULL;
comp = RingStep( newlist, NULL );
foundmatch = FALSE;
while( comp != NULL ) {
complen = strcspn( comp->segname, "$" );
if( ( complen == currlen )
&& ( memcmp( comp->segname, curr->segname, complen ) == 0 ) ) {
foundmatch = TRUE;
if( strcmp( comp->segname + complen,
curr->segname + currlen ) > 0 ) {
InsertPrevRing( &newlist, curr, prev );
added = TRUE;
break;
}
} else if( foundmatch ) {
InsertPrevRing( &newlist, curr, prev );
added = TRUE;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?