📄 loadpecofflib.c
字号:
vxSymType = VX_DATA; } else if (scnFlags & STYP_BSS) { bias = (char *) scnAddr; vxSymType = VX_BSS; } else if (scnFlags & STYP_DRECTVE) { /* Ignore this section */ continue; } else { /* * Lets not print error messages for debug-related symbols * that are not flagged as N_DEBUG... */ if (!strcmp (name, ".stab") || !strcmp (name, ".stabstr")) continue; printErr (cantConvSymbolType, name, errnoGet()); continue; } /* * Since, in the VxWorks simulator's image all the symbols' values * are offsets from zero a bias has to be introduced to get the * real (post-installation) addresses of these symbols in * Windows' memory space. The bias computation is however * different from the one for the regular object modules and must * overwrite whatever has been computed just above: the bias is * the base address of the simulator in Windows' memory space * plus the offset to the section which holds the symbol. * * Note: the section header's s_vaddr field holds this offset * _not_ a real virtual address... */ if (fullyLinked) bias = (char *)(pScnHdr->s_vaddr + imageBase); /* Determine if symbol should be put into symbol table */ if (((symFlag & LOAD_LOCAL_SYMBOLS) && !PECOFF_EXT(symbol)) || ((symFlag & LOAD_GLOBAL_SYMBOLS) && PECOFF_EXT(symbol))) { if (PECOFF_EXT(symbol)) vxSymType |= VX_EXT; /* Add symbol to symbol table but cut out Local tags */ if (name[0] != '$') if (symSAdd (symTbl, name, symbol->U_SYM_VALUE + bias, vxSymType, group) != OK) printErr (cantAddSymErrMsg, name, errnoGet()); } /* Add symbol address to externals table. * For PECOFF, we add all symbol addresses into the externals * table, not only those symbols saved in the vxWorks symbol * table. */ (*externals) [symNum] = symbol->U_SYM_VALUE + bias; } else { /* Undefined external symbol or "common" symbol * * A common symbol type is denoted by undefined external * with its 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 (PECOFF_COMM(symbol)) { if (symFlag == LOAD_NO_SYMBOLS) ; else { /* * common symbol - create new symbol * * Common symbols are now tacked to the end of the bss * section. This is done to accomodate systems that have * multiple boards sharing memory with common symbols * over the system bus. * This portion of code checks for a matching * common symbol. If a matching common symbol is not * found the symbol value is read * (which contains the symbol size) and the symbol is * placed in the bss section. The function dataAlign uses * the next possible address for a common symbol to * determine the proper alignment. */ if (loadPecoffCommonManage (name, symTbl, (void *) &adrs, &vxSymType, symFlag) != OK) { adrs = pNextCommon; bssAlignment = dataAlign (symbol->U_SYM_VALUE, (ULONG)adrs); adrs += bssAlignment; pNextCommon += (symbol->U_SYM_VALUE + bssAlignment); if (symSAdd (symTbl, name, adrs, (VX_BSS | VX_EXT), group) != OK) printErr (cantAddSymErrMsg, name, errnoGet()); } } } /* look up undefined external symbol in symbol table */ else if (symFindByNameAndType (symTbl, name, &adrs, &vxSymType, VX_EXT, VX_EXT) != OK) { /* Symbol not found in symbol table */ printErr ("undefined symbol: %s\n", name); adrs = NULL; status = ERROR; } /* Add symbol address to externals table */ (*externals) [symNum] = adrs; } } return status; }/********************************************************************************* pecoffRelSegmentI386 - perform relocation for the I386 family** This routine reads the specified relocation command segment and performs* all the relocation specified therein.* Absuolute symbol addresses are looked up in the 'externals' table.** This function handles the following types of relocation commands for the* I386 family of processor:* IMAGE_REL_I386_DIR32 - direct 32 bit relocation* IMAGE_REL_I386_REL32 - relative 32b bit relocation** RETURNS: OK or ERROR*/LOCAL STATUS pecoffRelSegmentI386 ( RELOC * pRelCmds, /* list of relocation commands */ SCNHDR * pScnHdrArray, /* array of section headers */ char ** pExternals, /* array of absolute symbols values */ SYMENT * pExtSyms, /* pointer to object file symbols */ SEG_INFO * pSeg, /* section addresses and sizes */ int section /* section number -1 for relocation */ ) { long * pAdrs = NULL; /* relocation address */ int nCmds; /* # reloc commands for seg */ RELOC relocCmd; /* relocation structure */ SCNHDR * pScnHdr; /* section header for relocation */ STATUS status = OK; pScnHdr = pScnHdrArray + section; for (nCmds = pScnHdr->s_nreloc; nCmds > 0; nCmds--) { /* read relocation command */ relocCmd = *pRelCmds++; /* * Calculate actual address in memory that needs relocation. * XXX PAD - we now apply the fix for SPR 70767 */ if (pScnHdr->s_flags & STYP_TEXT) { if (!(pScnHdr->s_flags & STYP_LIT)) { pAdrs = (long *)((long) pSeg->addrText + relocCmd.r_vaddr); } else { printf ("STYP_LIT type sections are unsupported.\n"); return ERROR; } } else /* * The computation of the address of relocable data symbol * should take into account the offset from the beginning of the * file that the compiler toolchain may require to account for * in some cases. The code was fixed to substract this offset * for data symbol, SPR 73145. */ { pAdrs = (long *)((long) pSeg->addrData + (relocCmd.r_vaddr - pScnHdr->s_vaddr)); } /* do relocations */ switch (relocCmd.r_type) { case IMAGE_REL_I386_DIR32: /* * This relocation is preformed by adding the absolute address * of the symbol to the relocation value in the code. */ *pAdrs += (INT32) pExternals [relocCmd.r_symndx]; break; case IMAGE_REL_I386_REL32: /* * Call near, displacement relative to the next instruction. * First, find the next instruction addr, then subtract it from * the addr of the found symbol to obtain the relocation addr. */ *pAdrs = (UINT32)pExternals[relocCmd.r_symndx] - ((UINT32)pAdrs + 4); break; default: printf("Unknown Relocation Error\n"); errnoSet (S_loadLib_UNRECOGNIZED_RELOCENTRY); status = ERROR; break; } } return status; }/********************************************************************************* pecoffHdrRead - read in PECOFF header and swap if necessary* * Note: To maintain code portability, we can not just read sizeof(FILHDR) * bytes. Compilers pad structures differently,* resulting in different structure sizes.* So, we read the structure in an element at a time, using the size* of each element.*/LOCAL STATUS pecoffHdrRead ( int fd, FILHDR *pHdr, BOOL *pSwap ) { int status; int i; struct dosheader dhead; *pSwap = 0; ioctl(fd, FIOSEEK, 0); if (fioRead (fd, (char *) &(pHdr->f_magic), sizeof (pHdr->f_magic)) != sizeof (pHdr->f_magic)) { errnoSet (S_loadLib_FILE_READ_ERROR); return ERROR; } switch (pHdr->f_magic) { case (SWAB_SHORT(IMAGE_DOS_SIGNATURE)): *pSwap = TRUE; case (IMAGE_DOS_SIGNATURE): /* Remove DOS EXE header */ fioRead(fd,(char *)&dhead + 2,sizeof(dhead)-2); lseek (fd, dhead.e_lfanew, SEEK_SET); /* Check for NT SIGNATURE */ fioRead (fd, (char *)&i, 4); if ( i != IMAGE_NT_SIGNATURE ) { printf("Bad Image Signature %x %x\n",i,IMAGE_NT_SIGNATURE); errnoSet (S_loadLib_HDR_READ); return ERROR; } fioRead (fd, (char *)&pHdr->f_magic, 2); break; case (SWAB_SHORT(IMAGE_FILE_MACHINE_I386)): *pSwap = TRUE; break; case (IMAGE_FILE_MACHINE_I386): *pSwap = FALSE; break; default:#ifndef MULTIPLE_LOADERS printErr (fileTypeUnsupported, pHdr->f_magic);#endif errnoSet (S_loadLib_FILE_ENDIAN_ERROR); return ERROR; break; } status = fileRead (fd, &pHdr->f_nscns, sizeof(pHdr->f_nscns), *pSwap); status |= fileRead (fd, &pHdr->f_timdat, sizeof(pHdr->f_timdat), *pSwap); status |= fileRead (fd, &pHdr->f_symptr, sizeof(pHdr->f_symptr), *pSwap); status |= fileRead (fd, &pHdr->f_nsyms, sizeof(pHdr->f_nsyms), *pSwap); status |= fileRead (fd, &pHdr->f_opthdr, sizeof(pHdr->f_opthdr), *pSwap); status |= fileRead (fd, &pHdr->f_flags, sizeof(pHdr->f_flags), *pSwap); max_scns = pHdr->f_nscns; return status; }/********************************************************************************* pecoffOpthdrRead - read in PECOFF optional header and swap if necessary* */LOCAL STATUS pecoffOpthdrRead ( int fd, PEOPTION *pOptHdr, BOOL swapTables ) { int status; status = fileRead(fd, &pOptHdr->magic, sizeof(pOptHdr->magic), swapTables); status |= fileRead(fd, &pOptHdr->vstamp, sizeof(pOptHdr->vstamp), swapTables); status |= fileRead(fd, &pOptHdr->tsize, sizeof(pOptHdr->tsize), swapTables); status |= fileRead(fd, &pOptHdr->dsize, sizeof(pOptHdr->dsize), swapTables); status |= fileRead(fd, &pOptHdr->bsize, sizeof(pOptHdr->bsize), swapTables); status |= fileRead(fd, &pOptHdr->entry, sizeof(pOptHdr->entry), swapTables); status |= fileRead(fd, &pOptHdr->text_start, sizeof(pOptHdr->text_start), swapTables); status |= fileRead(fd, &pOptHdr->data_start, sizeof(pOptHdr->data_start), swapTables); status |= fileRead(fd, &pOptHdr->image_base, sizeof(pOptHdr->image_base), swapTables); status |= fileRead(fd, &pOptHdr->section_align, sizeof(pOptHdr->section_align), swapTables); status |= fileRead(fd, &pOptHdr->file_align, sizeof(pOptHdr->file_align), swapTables); return (status); }/********************************************************************************* pecoffSecHdrRead - read in PECOFF section header and swap if necessary* */LOCAL STATUS pecoffSecHdrRead ( int fd, SCNHDR *pScnHdr, FILHDR *pHdr, BOOL swapTables ) { int ix; int status = 0; /* check for correct section count */ if (pHdr->f_nscns > MAX_SCNS) { return (ERROR); } for (ix = 0; ix < pHdr->f_nscns; ix++) { status = fileRead(fd, pScnHdr->s_name, sizeof(pScnHdr->s_name), FALSE); status |= fileRead(fd, &pScnHdr->s_paddr, sizeof(pScnHdr->s_paddr), swapTables); status |= fileRead(fd, &pScnHdr->s_vaddr, sizeof(pScnHdr->s_vaddr), swapTables); status |= fileRead(fd, &pScnHdr->s_size, sizeof(pScnHdr->s_size), swapTables); status |= fileRead(fd, &pScnHdr->s_scnptr, sizeof(pScnHdr->s_scnptr), swapTables); status |= fileRead(fd, &pScnHdr->s_relptr, sizeof(pScnHdr->s_relptr), swapTables); status |= fileRead(fd, &pScnHdr->s_lnnoptr, sizeof(pScnHdr->s_lnnoptr), swapTables); status |= fileRead(fd, &pScnHdr->s_nreloc, sizeof(pScnHdr->s_nreloc), swapTables); status |= fileRead(fd, &pScnHdr->s_nlnno, sizeof(pScnHdr->s_nlnno), swapTables); status |= fileRead(fd, &pScnHdr->s_flags, sizeof(pScnHdr->s_flags), swapTables); /* * In order to comply with an obscure requirement from Microsoft, the * GNU toolchain puts the size of the bss section in the section * header's physical address field. This piece of code addresses the * SPR 70767 by reseting the s_size field as appropriate for the rest * of the loader code. */ if (pScnHdr->s_flags & STYP_BSS) { if ((pScnHdr->s_size == 0) && (pScnHdr->s_paddr != 0)) pScnHdr->s_size = pScnHdr->s_paddr; } pScnHdr++; } return (status); }/********************************************************************************* pecoffReadRelocInfo - read in PECOFF relocation info and swap if necessary* * Assumptions: The file pointer is positioned at the start of the relocation* records.** The relocation records are ordered by section.*/LOCAL STATUS pecoffReadRelocInfo ( int fd, SCNHDR *pScnHdr, RELOC **pRelsPtr, BOOL swapTables ) { int ix; int iy; int relocSize; int status = OK; RELOC *pRels; /* pointer to single reloc entry */ for (ix = 0; ix < max_scns; ix++) { if (pScnHdr->s_nreloc > 0) { relocSize = (int) pScnHdr->s_nreloc * RELSZ; if ((*pRelsPtr = (RELOC *)malloc (relocSize)) == NULL) { return (ERROR); } if (lseek (fd, pScnHdr->s_relptr, SEEK_SET) == ERROR) { return (ERROR); } for (iy = 0, pRels = *pRelsPtr; (iy < (int) pScnHdr->s_nreloc) && (status == OK); iy++, pRels++) { status = fileRead(fd, &pRels->r_vaddr, sizeof(pRels->r_vaddr), swapTables); status |= fileRead(fd, &pRels->r_symndx, sizeof(pRels->r_symndx), swapTables); status |= fileRead(fd, &pRels->r_type, sizeof(pRels->r_type), swapTables); } if (status != OK) return(status); } pScnHdr++; pRelsPtr++; } return (OK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -