📄 loadsomcofflib.c
字号:
mask = 0x1fffff; break; case i_exp11: value = de_low_sign_ext (value, 11); mask = 0x7ff; break; case i_rel17: case i_abs17: value = de_assemble_17 (value >> 2); mask = 0x001f1ffd; break; case i_rel12: value = de_assemble_12 (value >> 2); mask = 0x1ffd; break; case i_data: mask = 0xffffffff; break; case i_milli: case i_break: default: mask = 0; break; } *adrs = ((*adrs) & ~mask) | (value & mask); }/********************************************************************************* linkSubspaces - perform linker fixup commands for relocation.** RETURNS: OK or ERROR*/static STATUS linkSubspaces ( UCHAR * pRelCmds, /* list of relocation commands */ SUBSPACE *pSubspace, /* subspace dictionary */ int nSubs, /* number of subspaces */ SUB_INFO *pSubInfo, /* load information for the subspaces */ SYMREC * pSym, /* symbols dictionary */ int numSyms, /* number of symbols */ SYMTAB_ID pSymTab, /* VxWorks symbol table */ SYMREC * pSymGlobal, /* pointer to '$global$' entry */ MODULE_ID moduleId /* module being linked */ ) { int status = OK; /* function return value */ /* * generic fixup variables * * For each subspace, we must process a stream of fixup requests * in order to complete the relocation. The fixup requests are * variable size, and there are no "markers" to separate the * fixups - so ya gotta be real careful. The first byte of each * fixup request is called the opCode. */ int ix; /* index of subspace being fixed up */ UCHAR * pThisFixup; /* start of relocation fixup stream */ UCHAR * pLastFixup; /* end of stream */ UCHAR opCode; /* the type of fixup request */ char *relAdr; /* address that need fixing */ int relValue; /* value to apply (e.g., a function address) */ /* * Variables for maintaining the REPEAT_PREV_FIXUP list. * * The linker maintains a list of the last 4 multibyte * fixup requests. When a REPEAT_PREV_FIXUP fixup occurs, * we repeat one of the fixups from our list. */ LIST prevFixupList; /* previous fixup list */ PREV_FIXUP prevFixupNodes[4]; /* the nodes in the list */ PREV_FIXUP *pPrevFixupNode; /* pointer to some node in the list */ UCHAR *pOldFixup = 0; /* before executing a previous fixup, we save * our current place in the fixup stream */ BOOL usingPrevFixup; /* are we currently are using a queued fixup? */ /* * variables for fixups that manipulate the expession stack. * * An expession stack is used to evaluate complex combinations of values. * The R_COMPX fixups either push a value on the expression stack or * modifies what is on top of the stack (e.g., it might pop the top * two elements, and push their sum). * These fixups have a secondary opCode which describes what to do. * The value at the top of the expession stack is used in the * R_DATA_EXPR and R_CODE_EXPR fixups. * XXX - these have not been tested yet. */ UCHAR opCode2; /* 2nd opcode for stack manipulation fixups */ int * pExpStack; /* initial stack pointer */ int * sp; /* current stack pointer */ int top1; /* first item on stack */ int top2; /* second item on stack */ int C; /* condition code for stack operation */ /* * variables to hold the fixup request parameters. * * Most fixup requests pass us parameters (e.g., the symbol number * which we need to branch to). The parameters passed depend on * the fixup. The way the parameters are encoded in the fixup stream * also depends on the fixup. */ int L; /* number of bytes to relocate */ int S; /* symbol index used */ int R = 0; /* parameter relocation bits */ int V = 0; /* variable or fix up constant */ int U; /* stack unwind bits */ int F; /* procedure stack frame size */ int D; /* difference of operation code */ int X; /* previous fixup index */ int M; /* number of bytes for R_REPEATED_INIT */ int N; /* statement number in R_STATEMENT */ /* * variables for handling the rounding mode during fixups * * Many fixups come in pairs, where we move the left (high order) * bits of a value in the first fixup, and the right (low order) * bits in the next fixup. Before applying a fixup value * at an address, it must be rounded. * The rounded constant is then applied to the address. * * The field selector specifies if we should apply the * left bits (LSEL), the right bits (RSEL), or everything (FSEL). * The field selector depends on the current instruction, but * can be overridden with a feild selector override fixup. * * The interpretation of the field selector depends on the current * rounding mode. The rounding mode selector can be * round down (N_MODE), round to nearest page (S_MODE), round up (D_MODE), * or round down with adjusted constant (R_MODE). * The rounding mode is persistent until explicity changed by * a mode select fixup request. The default at the begining of each * subspace is N_MODE. * * The function fieldGetDefault() computes the field selector * (and adjusted constant if we are in R_MODE) based on the current * instruction and rounding mode. It also computes how to * apply the rounded constant to a given instruction. */ int fixConstant; /* adjusted constant used in R_MODE rounding */ int modeSel; /* mode select */ int fieldSel; /* field select */ int fieldOverride; /* field select override flag */ int dataOverride; /* data override flag */ int relFormat; /* how to apply the rounded constant */ /* * variables for stub manipulation. * * The linker must generate "long branch stubs" and "parameter * relocation stubs" whenever needed. Read the INTERNAL * comments at the begining of the file for more info. * The long branch stubs are generated per subspace, while * the parameter relocation stubs are generated per module. */ LIST stubList; /* list of current long branch stubs */ char *pLongBranchStubs; /* starting address this subspaces stubs */ char *pStub; /* address of current stub */ int stubIx; /* current stubs index in the list */ LIST argRelocStubList; /* list of argument relocation stubs */ /* * variables for stack unwind generation * * The PA-RISC has no frame pointer. To calculate the frame pointer, * the linker must generate an array of stack unwind descriptors * which, for each function, specifies its starting address, ending * address, and the amount of stack space it requires. */ LIST unwindList; /* linked list of unwind descriptors */ UNWIND_NODE *pUnwindNode = NULL; /* pointer to an unwind descriptor */ /* scratch variables */ char *tmpBuf; /* tempoaray buffer */ int bufSize; /* size of temporary buffer */ /* create the expression stack */ if ((pExpStack = (int *) calloc (1, REL_STACK_SIZE)) == NULL) { printErr ("ld error: unable to allocate relocation stack\n"); return (ERROR); } /* Initialize the previous fixup queue */ lstInit (&prevFixupList); for (ix = 0; ix < 4; ix++) { lstAdd (&prevFixupList, &(prevFixupNodes[ix].node)); prevFixupNodes[ix].pFixup = NULL; } /* initialize the list of long branch and parameter relocation stubs */ lstInit (&stubList); lstInit (&argRelocStubList); /* initialize the stack unwind list */ lstInit (&unwindList); /* perform linker fixups on each subspace */ for (ix = 0; ix < nSubs; ix ++, pSubspace++) { if (!pSubspace->is_loadable) { DBG_PUT ("linker: skipping fixups for unloadable subspace\n"); continue; } if (pSubspace->fixup_request_quantity == 0) { continue; } DBG_PUT ("\n\n\nsubSpace: 0x%x - 0x%x\n", (int)(pSubInfo[ix].loadAddr), (int)(pSubInfo[ix].loadAddr) + pSubspace->subspace_length); /* Initialize the long branch stub list for this subspace to be empty */ lstFree (&stubList); pLongBranchStubs = pSubInfo[ix].loadAddr + pSubspace->subspace_length; pLongBranchStubs = (char *)ROUND_UP (pLongBranchStubs, pSubspace->alignment); /* get the starting address for this subspace */ relAdr = (pSubInfo + ix)->loadAddr; /* get the list of fixup requests for this subspace */ pThisFixup = pRelCmds + pSubspace->fixup_request_index; pLastFixup = pThisFixup + pSubspace->fixup_request_quantity; /* set some default modes */ modeSel = R_N_MODE; /* default rounding mode for each subspace */ fieldSel = R_FSEL; /* default field selector. XXX - needed? */ dataOverride = FALSE; fieldOverride = FALSE; usingPrevFixup = FALSE; sp = pExpStack; /* each subspace starts with a fresh * expression stack. XXX - added */ /* process this subspaces fixups in a huge switch statement */ while (pThisFixup < pLastFixup) { opCode = *pThisFixup; DBG_PUT ("opCode (0x%x) = %d. relAdr = 0x%x.\n", (int)pThisFixup, opCode, (int)relAdr); /* keep track of the last 4 multibyte fixup requests */ if (fixupLen[opCode] > 1) { pPrevFixupNode = (PREV_FIXUP *)lstNth (&prevFixupList, 4); lstDelete (&prevFixupList, &(pPrevFixupNode->node)); pPrevFixupNode->pFixup = pThisFixup; lstInsert (&prevFixupList, NULL, &(pPrevFixupNode->node)); } pThisFixup++; /* perform the fixup based on the opCode */ if (/* opCode >= R_NO_RELOCATION && */ opCode < R_ZEROES ) { /* 00-1f: n words, not relocatable */ if (opCode < 24) { D = opCode - R_NO_RELOCATION; L = (D + 1) * 4; } else if (opCode >= 24 && opCode < 28) { D = opCode - 24; L = ((D << 8) + B1 + 1) * 4; } else if (opCode >= 28 && opCode < 31) { D = opCode - 28; L = ((D << 16) + B2 + 1) * 4; } else { D = opCode - 31; L = B3 + 1; } DBG_PUT ("R_NO_RELOCATION: 0x%x bytes\n", L); relAdr += L; } else if (opCode >= R_ZEROES && opCode < R_UNINIT) { /* 20-21: n words, all zero */ if (opCode == R_ZEROES) { L = (B1 + 1) * 4; } else { L = B3 + 1; } /* insert L bytes zero */ bufSize = (int)(pSubInfo+ix)->loadAddr + pSubspace->subspace_length - (int)relAdr; tmpBuf = malloc (bufSize); if (tmpBuf == NULL) printErr ("ld error: reloc malloc failed\n"); DBG_PUT ("inserting %d zeros at 0x%x\n", L, (int)relAdr); bcopy (relAdr, tmpBuf, bufSize); bzero (relAdr, L); relAdr += L; bcopy (tmpBuf, relAdr, bufSize - L); free ((char *) tmpBuf); } else if (opCode >= R_UNINIT && opCode < R_RELOCATION) { /* 22-23: n words, uninitialized */ if (opCode == R_UNINIT) { L = (B1 + 1) * 4; } else { L = B3 + 1; } /* skip L bytes */ bufSize = (int)(pSubInfo+ix)->loadAddr + pSubspace->subspace_length - (int)relAdr; tmpBuf = malloc (bufSize); if (tmpBuf == NULL) printErr ("ld error: reloc malloc failed\n"); DBG_PUT ("skipping %d bytes at 0x%x.\n", L, (int)relAdr); bcopy ((char *) relAdr, tmpBuf, bufSize); bzero (relAdr, L); relAdr += L; bcopy (tmpBuf, relAdr, bufSize - L); free ((char *) tmpBuf); } else if (opCode == R_RELOCATION) { /* XXX - untested */ /* 24: 1 word relocatable data */ relValue = *(int *)relAdr + (int)(pSubInfo[ix].loadAddr); *((unsigned int *)(relAdr)) = relValue; WARN ("Warning: R_RELOCATION fixup is untested\n"); WARN ("address = 0x%x\n", (int)relAdr); relAdr += 4; } else if (opCode >= R_DATA_ONE_SYMBOL && opCode < R_DATA_PLABEL) { /* 25-26: 1 word, data external reference */ if (opCode == R_DATA_ONE_SYMBOL) { S = B1; } else { S = B3; } relValue = *(int *)relAdr + (pSym + S)->symbol_value; *((int *)relAdr) = relValue; DBG_PUT ("R_DATA_ONE_SYMBOL: relAdr = 0x%x\n", (int)relAdr); relAdr +=4; } else if (opCode >= R_DATA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -