⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loadecofflib.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	            goto error;		    }		}	    }        /* flush instruction cache before execution */	if (optHdr.tsize != NULL)	    cacheTextUpdate (pText, optHdr.tsize);	}    if (externalsBuf != NULL)        {        free ((char *) externalsBuf);   /* finished with externalsBuf */        externalsBuf = NULL;        }    /*      * free memory that was used (free should be as early as possible to     * allow memory reuse, which is very important for large object modules)      */    for (ix = 0; ix < MAX_SCNS; ix++)	if (relsPtr[ix] != NULL)	    {	    free((char *) relsPtr[ix]);	    relsPtr[ix] = NULL;	    }    /* return load addresses, where called for */    if (ppText != NULL)        *ppText = pText;    if (ppData != NULL)        *ppData = pData;    if (ppBss != NULL)        *ppBss = pBss;    /* clear out bss */    bzero (pBss, (int) seg.sizeBss);    /*     * Add the segments to the module.     * This has to happen after the relocation gets done.     * If the relocation happens first, the checksums won't be     * correct.     */    moduleSegAdd (moduleId, SEGMENT_TEXT, pText, seg.sizeText, seg.flagsText);    moduleSegAdd (moduleId, SEGMENT_DATA, pData, seg.sizeData, seg.flagsData);    moduleSegAdd (moduleId, SEGMENT_BSS, pBss, seg.sizeBss, seg.flagsBss);		    if (status == OK)        return (moduleId);    else        return (NULL);    /* error:     * clean up dynamically allocated temporary buffers and return ERROR */error:    for (ix = 0; ix < MAX_SCNS; ix++)	{	if (sectPtr[ix] != NULL)	    free((char *) sectPtr[ix]);	if (relsPtr[ix] != NULL)	    free((char *) relsPtr[ix]);	}    if (stringsBuf != NULL)	free (stringsBuf);    if (externalsBuf != NULL)	free ((char *) externalsBuf);    if (externalSyms != NULL)	free ((char *) externalSyms);    moduleDelete (moduleId);    return (NULL);    }/********************************************************************************* rdEcoffSymTab -** This is passed a pointer to an ecoff symbol table and processes* each of the external symbols defined therein.  This processing performs* two functions:*  1) defined symbols are entered in the system symbol table as*     specified by the "symFlag" argument:*	ALL_SYMBOLS	= all defined symbols (LOCAL and GLOBAL) are added,*	GLOBAL_SYMBOLS	= only external (GLOBAL) symbols are added,*	NO_SYMBOLS	= no symbols are added;*  2) any undefined externals are looked up in the system table, and*     if found, entered in the specified 'externals' array.  This array*     is indexed by the symbol number (position in the symbol table).*     Note that only undefined externals are filled in in 'externals' and*     that values for all other types of symbols are unchanged (i.e. left*     as garbage!).  This is ok because 'externals' is only used to *     perform relocations relative to previously undefined externals.*     Note that "common" symbols have type undefined external - the value*     field of the symbol will be non-zero for type common, indicating*     the size of the object.** If more than the specified maximum number of symbols are found in the* symbol table, the externals array is extended to accomodate the additional* symbols.* If an undefined external cannot be found in the system symbol table,* an error message is printed, but ERROR is not returned until the entire* symbol table has been read, which allows all undefined externals to be* looked up.* Stabs and absolute symbols are automatically discarded.** RETURNS: OK or ERROR** INTERNAL* Local symbols are currently ignored.*/LOCAL STATUS rdEcoffSymTab     (    EXTR * pExtSyms,		/* pointer to mips external symbols */    FAST int nEnts,		/* # of entries in symbol table */    char ***externals,		/* pointer to pointer to array to fill in 				   values of undef externals */    int max_symbols,		/* max symbols that can be put in 'externals' */    int symFlag,		/* symbols to be added to table 				 *   ([NO|GLOBAL|ALL]_SYMBOLS) */    SEG_INFO *pSeg,		/* pointer to segment information */    char *symStrings,		/* symbol string table (only meaningful in				   BSD 4.2) */    SYMTAB_ID symTbl,		/* symbol table to use */    char *pNextCommon, 		/* next common address in bss */    int group			/* symbol group */    )    {    FAST char *name;		/* symbol name (plus EOS) */    EXTR symbol;		/* symbol value */    SYM_TYPE vxSymType;		/* ecoff symbol translation */    int sym_num = 0;		/* symbol index */    int status  = OK;		/* return status */    char *adrs;			/* table resident symbol address */    SYM_TYPE type;		/* ecoff symbol type */    char *bias;			/* section relatilve address */    ULONG bssAlignment;		/* alignment value of common type */    /* pass 1: process defined symbols */    for (sym_num = 0; sym_num < nEnts; sym_num ++)	{	/* read in next entry - symbol definition and name string */	symbol = pExtSyms [sym_num];	/* add requested symbols to symbol table */        if ((!COFF_ABS(&symbol)) &&	/* throw away absolute symbols */	    (!COFF_UNDF(&symbol)) && (!COFF_COMM(&symbol)) &&	    (symFlag & LOAD_GLOBAL_SYMBOLS) && COFF_EXT(&symbol))	    {	    /*	     * symbol name string is in symStrings array indexed 	     * by symbol.iss	     */	    name = symStrings + symbol.asym.iss;	    /*	     *  I'm not sure the symbol type can tell us what section the 	     *  symbol is in so we look at the address.  This should be 	     *  investigated at a later date.	     */	    if (symbol.U_SYM_VALUE < (long) pSeg->sizeText)		bias = (char *) pSeg->addrText;	    else if (symbol.U_SYM_VALUE		< ((long) pSeg->sizeText + (long) pSeg->sizeData))		bias = (char *) (		       (long) pSeg->addrData		     - (long) pSeg->sizeText);	    else		bias = (char *) ((long) pSeg->addrBss - pSeg->sizeText - 		    pSeg->sizeData);	    if (ecoffToVxSym (&symbol, &vxSymType) == ERROR)		printErr (cantConvSymbolType, name, errnoGet());	    if (symSAdd (symTbl, name, symbol.U_SYM_VALUE + bias, 		vxSymType, group) != OK)		printErr (cantAddSymErrMsg, name, errnoGet());	    /*	     * add symbol address to externals table, but first	     * check for enough room in 'externals' table	     */	    	    if (sym_num == max_symbols)		{		/*		 * no more room in symbol table -		 * make externals table half again as big		 */				max_symbols += max_symbols / 2;				*externals = (char **) realloc ((char *) *externals,		    max_symbols * sizeof (char *));		if (*externals == NULL)		    return (ERROR);		}	    /* enter address in table used by relSegment */	    (*externals) [sym_num] = symbol.U_SYM_VALUE + bias;	    }	}    /* pass 2: process undefined symbols (including commons) */    for (sym_num = 0; sym_num < nEnts; sym_num ++)	{	/* read in next entry - symbol definition and name string */	symbol = pExtSyms [sym_num];        if ((!(COFF_ABS(&symbol))) && 	/* throw away absolute symbols */	    ((COFF_UNDF(&symbol)) || (COFF_COMM(&symbol))))	    {	    /*	     * symbol name string is in symStrings array indexed 	     * by symbol.iss             */	    name = symStrings + symbol.asym.iss;	    /*	     * undefined external symbol or "common" symbol -	     *   common symbol type is denoted by undefined external with	     *   the value set to non-zero.	     *	     * if symbol is a common, then allocate space and add to	     * symbol table as BSS	     */	    /* common symbol - create new symbol */	    if (COFF_COMM(&symbol)		&& (symbol.U_SYM_VALUE != 0)) 	/* do we really need this ? */		{                /* 		 *  common symbol - create new symbol 		 *		 *  Common symbols are now tacked to the end of the bss		 *  section.  This portion of code reads the symbol value		 *  which contains the symbol size and places it appropriately		 *  in the bss section.  The function sizeEcoffCommons is used		 *  with the address of the last common added to determine		 *  proper alignment.		 */		adrs = pNextCommon;		bssAlignment = sizeEcoffCommons (&symbol, (ULONG) adrs);		bssAlignment -= (ULONG) symbol.U_SYM_VALUE;		adrs += bssAlignment;		pNextCommon += (symbol.U_SYM_VALUE + bssAlignment);		if (symSAdd (symTbl, name, adrs, (N_BSS | N_EXT), group) != OK)		    printErr (cantAddSymErrMsg, name, errnoGet());		}	    /* look up undefined external symbol in symbol table */	    else if (symFindByNameAndType (symTbl, name, &adrs, &type,					   N_EXT, N_EXT) != OK)		{		/* symbol not found in symbol table */		printErr ("undefined symbol: %s\n", name);		adrs = NULL;		status = ERROR;		}	    /*	     * add symbol address to externals table, but first	     * check for enough room in 'externals' table	     */	    if (sym_num == max_symbols)		{		/*		 * no more room in symbol table -		 * make externals table half again as big		 */		max_symbols += max_symbols / 2;		*externals = (char **) realloc ((char *) *externals, 		    max_symbols * sizeof (char *));		if (*externals == NULL)		    return (ERROR);		}	    (*externals) [sym_num] = adrs;	/* enter address in table */	    }	}    return (status);    }/********************************************************************************* relSegmentR3k - perform relocation commands for a MIPS segment** This routine reads the specified relocation command segment and performs* all the relocations specified therein.* External relocations are looked up in the 'externals' table.* All other relocations are relative to how much a particular segment has moved.** That was the short explanation.  The following is more specific:* Each relocation command is identified as being external or local; * external symbols require the use of the 'externals' table to perform* the relocation while local symbols are relocated relative to a segment* (text or data).** There are the following types of external relocation entries:*	-R_REFWORD for externally defined pointers,* 	-R_HALFWORD ?? would be a 16 bit external pointer but thus far* 	 	has not been seen from the MIPS C compiler,*       -R_JMPADDR for calls to externalC functions,* 	-R_REFHI/R_REFLO pairs for accessing and external data* 		value, and*	-unsupported GP (global pointer) relative relocation types which * 		cause an error to be returned.*		* There are local versions of these relocation entries also:*	-R_REFWORD for static pointers and arrays,*	-R_HALFWORD should be similar to R_REFWORD but have not been *		able to get the C compiler to generate it,*	-R_JMPADDR for relative jumps to functions (references to functions* 		located within the load module.* 	-R_REFHI/R_REFLO combinations for accesses to objects  defined in *     		this file and with local visibility (i.e. static data * 		structure references).*	-unsupported GP (global pointer) relative relocation types which * 		cause an error to be returned.*** RETURNS: OK or ERROR*/LOCAL STATUS relSegmentR3k     (    RELOC *pRelCmds,		/* list of mips relocation commands */    SCNHDR *pScnHdr,		/* section header for relocation */    char **pExternals,		/* addresses of external symbols */    int section,		/* section number TEXT, RDATA, BSS ... */    SEG_INFO *pSeg 		/* section addresses and sizes */    )    {    FAST long *pAddress;	/* relocation address */    FAST long *pNextAddress;	/* next relocation address */    long refhalfSum;		/* refhalf sum */    long targetAddr;		/* relocation target address */    long relocOffset; 		/* relocation offset */    long relocConstant;		/* general reloc constant */    long relSegment;		/* RTEXT, RDATA, ... */    long segment;		/* segment we are relocating */    unsigned short nCmds;	/* # reloc commands for seg */    RELOC relocCmd;		/* relocation structure */    RELOC nextRelocCmd;		/* next relocation structure */    long refhiConstant = 0;	/* last REFHI constant */    nCmds = pScnHdr->s_nreloc;    while ( nCmds > 0 )	{	/* read relocation command */	relocCmd = *pRelCmds++;	nCmds -= 1;	/* 	 * Calculate actual address in memory that needs relocation	 * and perform external or segment relative relocation 	 */        if ((section == R_SN_TEXT) || (section == R_SN_INIT))	    {	    pAddress = (long *) ((long) pSeg->addrText + relocCmd.r_vaddr);	    segment = RTEXT;	    }	else	    {	    pAddress = (long *) ((long) pSeg->addrData + 		(relocCmd.r_vaddr - pSeg->sizeText));	    segment = RDATA;	    }	/* note: should check for valid pAddress here XXXX */	if (relocCmd.r_extern)	/* globlal relocation */	    {	    switch (relocCmd.r_type)	        {	        case R_REFWORD:		/*		*  This relocation is performed by adding the 32 bit address		*  of the symbol to the contents of pAddress.		*  See IDT Assembly language programmers guide pg. 10-16		*/ 		    *pAddress = (*pAddress + 			(long) pExternals[relocCmd.r_symndx]);		    break;	        case R_REFHALF:	/* WARNING: UNTESTED */		/* 		*  This case is not well documented by MIPS, and has never		*  been generated.  REFWORD and REFHALF relocation entries		*  are generally used for pointers, and a case where you have		*  a 16 bit pointer is very unlikely to occur on a 32 bit		*  architecture.		*/		    refhalfSum = ((LS16BITS & *pAddress) + 			(long) pExternals[relocCmd.r_symndx]);		    if (refhalfSum >= OVERFLOW)		        refhalfSum &= LS16BITS;		    *pAddress = (MS16BITS & *pAddress) | 			(LS16BITS & refhalfSum);		    break;	        case R_JMPADDR:		/* 		*  For this relocation type the loader determines the address		*  for the jump, shifts the address right two bits, and adds 		*  the lower 26 bits of the result to the low 26 bits of the 		*  instruction at pAddress (after sign extension).  The		*  results go back into the low 26 bits at pAddress.		*  The initial check is to see if the jump is within range.  		*  The current address is incremented by 4 because the jump		*  actually takes place in the branch delay slot of the		*  current address.		*  See IDT Assembly language programmers guide pg. 10-16		*/		    if ((MS4BITS & ((long) pAddress + sizeof(INSTR))) != 			(MS4BITS & (long) pExternals[relocCmd.r_symndx]))			{	    		errnoSet (S_loadEcoffLib_JMPADDR_ERROR);		        return (ERROR);			}		    targetAddr = (LS26BITS & *pAddress) + (LS26BITS &			((unsigned) pExternals[relocCmd.r_symndx] >> 2));		    *pAddress = (MS6BITS & *pAddress) | (LS26BITS & targetAddr);		    break;	        case R_REFHI:		/*		*  A refhi relocation is done by reading the next relocation		*  entry (always the coresponding reflo entry).  This least		*  significant 16 bits are taken from the refhi instruction 		*  and shifted left to form a 32 bit value.  This value is 		*  added to the least significant 16 bits of the reflo 		*  instruction (taking into account sign extention) to form 		*  a 32 bit reference pointer.  The target address is added 		*  to this constant and placed back in the least significant 		*  16 bits of each instruction address.  The contents of the 		*  lower 16 bits of pAddress (refhiConstant) are saved for any 		*  other reflo entries that the refhi entry may correspond to.		*  See IDT Assembly language programmers guide pg. 10-16		*/		    refhiConstant = (*pAddress << 16);		    nextRelocCmd = *pRelCmds++;	   	    nCmds -= 1;	    	    if (nextRelocCmd.r_type != R_REFLO) 			{	    		errnoSet (S_loadEcoffLib_NO_REFLO_PAIR);		        return (ERROR);			}        	    if (segment == RTEXT)			{	    	        pNextAddress = (long *) ((long) pSeg->addrText + 			    nextRelocCmd.r_vaddr);			}		    else /* segment == RDATA */			{	    		pNextAddress = (long *) ((long) pSeg->addrData + 			    (nextRelocCmd.r_vaddr - 			    (long) pSeg->sizeText));			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -