📄 c-loader9.html
字号:
</dl><h4 class="EntityTitle"><a name="85514"><font face="Helvetica, sans-serif" size="-1" class="sans">Example 3-4: <b class="routine"><i class="routine">load</i></b><i class="term">Omf</i><b class="routine"><i class="routine">FmtManage</i></b><b>( )</b> </font></a></h4><dl class="margin"><dl class="margin"><dd><pre class="Code"><b><a name="86703">/************************************************************************ * * load<i class="textVariable">Omf</i>FmtManage - process an object module * * This routine is the routine underlying loadModuleAt(). This * interface allows specification of the symbol table used to resolve * undefined external references and to which to add new symbols. * * Three kinds of files can be handled : - relocatable files * - fully linked files * - "core" files * * For relocatable files, addresses of segments may or may not be * specified. Memory is allocated on the target if required (nothing * specified). For fully linked files, addresses of segments may or may * not be specified. Addresses are obtained from the file if nothing is * specified. Note however that if addresses are specified, all three * types must be set. For core files, addresses of segments must not be * specified. In any case, addresses are obtained from the file. * * RETURNS: OK, or ERROR if cannot process the file, not enough memory, or * illegal file format */ STATUS load<i class="textVariable">Omf</i>FmtManage ( char * pObjMod, /* pointer to the beginning of the module */ int loadFlag, /* control of loader behavior */ void ** ppText, /* load text segment at addr pointed to by */ /* this ptr, return load addr via this ptr */ void ** ppData, /* load data segment at addr pointed to by */ /* this ptr, return load addr via this ptr */ void ** ppBss, /* load bss segment at addr pointed to by */ /* this ptr, return load addr via this ptr */ SYMTAB_ID symTbl, /* symbol table to use */ MODULE_ID moduleId, /* module id */ SEG_INFO * pSeg /* info about loaded segments */ ) { <i class="textVariable">[local variable declarations] </i> /* Check the load flag combination */ if (LoadFlagCheck (loadFlag, ppText, ppData, ppBss) != OK) { wpwrLogErr ("Illegal combination of flags\n"); errno = WTX_ERR_LOADER_ILLEGAL_FLAGS_COMBINATION; return (ERROR); } /* * First, we check if the module is really <i class="textVariable">Omf</i>, and if it is * intended for the appropriate target architecture. * We also find out if the host and target byte orders are * identical. If not, we have to swap the header contents, the * symbol info, and the relocation commands. */ if (! load<i class="textVariable">Omf</i>ModuleIsOk (...) { wpwrLogErr ("Not an omf module for the %s architecture.\n", tgtCpuFamilyNameGet ()); return (ERROR); } /* Read object module header */ if (load<i class="textVariable">Omf</i>MdlHdrRd (...) != OK) return (ERROR); /* Allocate memory for the various tables */ <i class="textVariable">[in general array of symbols and array of symbol address] </i> /* Read in section headers */ if (load<i class="textVariable">Omf</i>ScnHdrRd (...) != OK)) goto error; /* Replace a null address by a dedicated flag (LOAD_NO_ADDRESS) */ pSeg->pAddrText = (ppText == NULL) ? LOAD_NO_ADDRESS : *ppText; pSeg->pAddrData = (ppData == NULL) ? LOAD_NO_ADDRESS : *ppData; pSeg->pAddrBss = (ppBss == NULL) ? LOAD_NO_ADDRESS : *ppBss; /* Determine segment sizes */ load<i class="textVariable">Omf</i>SegSizeGet (...); /* Read the module symbol table */ if (load<i class="textVariable">Omf</i>SymTabRd (...) != OK) goto error; /* Search information about compiler */ if (loadFlag & LOAD_CORE_FILE) load<i class="textVariable">Omf</i>ToolSignatureSearch (...); /* * Allocate the segments according to user requirements. * This allocates memory for the image on the host. */ if (!(loadFlag & LOAD_FULLY_LINKED) && (LoadSegmentAllocate (pSeg) != OK)) goto error; /* We are now about to store the segment contents in the cache */ if (load<i class="textVariable">Omf</i>SegStore (...) != OK) goto error; /* * Build or update the target server symbol table with symbols found * in the module symbol tables. */ if (load<i class="textVariable">Omf</i>SymTabProcess (...) != OK) goto error; /* Relocate text and data segments (if not already linked) */ if ((!(loadFlag & LOAD_FULLY_LINKED)) && (load<i class="textVariable">Omf</i>SegReloc (...) != OK)) goto error; /* clean up dynamically allocated temporary buffers */ <i class="textVariable">[free memory previously allocated] </i> /* return load addresses, where called for */ if (ppText != NULL) *ppText = pSeg->pAddrText; if (ppData != NULL) *ppData = pSeg->pAddrData; if (ppBss != NULL) *ppBss = pSeg->pAddrBss; /* Write segments in a file if required (testing session) */ if (loadFlag & LOAD_FILE_OUTPUT) return (LoadOutPutToFile (moduleId->name, pSeg)); /* * If file is relocatable, everything (text and data) is now flushed * to the target. * Note that in the case of a core file, we don't want to transfer * anything to the target memory (since the core file text and data * are already in the target). */ if ((!(loadFlag & LOAD_FULLY_LINKED)) && (load<i class="textVariable">Omf</i>CacheFlush (pSeg, textIsCached, dataIsCached) != OK)) goto error; /* If virtual memory management is on, apply write protection */ if ((!(loadFlag & LOAD_FULLY_LINKED) && (pSeg->flagsText & SEG_WRITE_PROTECTION)) && (TgtMemProtect (pSeg->pAddrText, pSeg->sizeProtectedText, TRUE) != OK)) goto error; return (OK); /* * error: * free target memory cache nodes, clean up dynamically allocated * temporary buffers and return ERROR */ error: wpwrLogErr ("Unrecoverable trouble while loading module.\n"); if (textIsCached) TgtMemCacheSet (pSeg->pAddrText, pSeg->sizeText, MEM_NONE, FALSE); if (dataIsCached) TgtMemCacheSet (pSeg->pAddrData, pSeg->sizeData, MEM_NONE, FALSE); <i class="textVariable">[free memory previously allocated] </i> return (ERROR); }</a></b></pre></dl></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H3"><i><a name="85578">3.9.6 Byte Order</a></i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="85580"> </a>The OMF manager manages the byte ordering in the object module. In a cross-development environment, the host byte order, which is the byte order of the target server, may be different than the target byte order. The cross-compiler usually produces object modules in target byte order; thus the headers, symbol table, and relocation entries may be the wrong byte order for the loader. Even the pieces that require relocation within the text and data segments may be affected since computation is done on the host for the target.</p><dd><p class="Body"><a name="85581"> </a>The OMF manager determines the byte ordering in the object module by reading a <i class="term">well known datum</i>, also known as the <i class="term">magic number</i>. If the OMF manager does not recognize this datum, it swaps the datum and tries again. If the OMF manager recognizes it after swapping, it knows that the object module is in the opposite byte order and requires that all information be swapped. However, if the datum is still not recognized after a swap, then the object module is probably not in the expected format.</p><dd><p class="Body"><a name="85583"> </a>Some cross-compilers produce structural information (headers, symbol table, relocation entries) in host byte order, but sections in target byte order. In this case, the OMF manager cannot find a well known datum within the sections. The programmer must address this case in the relocation routines.</p><dd><p class="Body"><a name="85584"> </a>Several macros in <b class="file">host.h</b> deal with byte ordering:</p></dl><dl class="margin"><dd><div class="Item"><a name="85586"> </a><b class="symbol_UC">SWAB_16</b> </div><dl class="margin"><dd><div class="Indent"><a name="85587"> </a>Swap 2 bytes: AB becomes BA.</div><br></dl><dd><div class="Item"><a name="85589"> </a><b class="symbol_UC">SWAB_32</b> </div><dl class="margin"><dd><div class="Indent"><a name="85590"> </a>Swap 4 bytes: ABCD becomes DCBA.</div><br></dl><dd><div class="Item"><a name="85592"> </a><b class="symbol_UC">SWAB_16_IF</b> </div><dl class="margin"><dd><div class="Indent"><a name="85593"> </a>Apply <b class="symbol_UC">SWAB_16</b> operation if a boolean is true.</div><br></dl><dd><div class="Item"><a name="85595"> </a><b class="symbol_UC">SWAB_32_IF</b> </div><dl class="margin"><dd><div class="Indent"><a name="85596"> </a>Apply <b class="symbol_UC">SWAB_32</b> operation if a boolean is true.</div><br></dl></dl><dl class="margin"><dd><p class="Body"><a name="85597"> </a>Note that the length of the string table, when written down in the module, may need to be swapped as well.</p></dl></dl><h4 class="EntityTitle"><a name="86582"><font face="Helvetica, sans-serif" size="-1" class="sans">Example 3-5: <b class="routine"><i class="routine">load</i></b><i class="term">Omf</i><b class="routine"><i class="routine">ModuleIsOk</i></b><b>( )</b> </font></a></h4><dl class="margin"><dl class="margin"><dd><pre class="Code"><b><a name="87056">/************************************************************************ * * load<i class="textVariable">Omf</i>ModuleIsOk - check the module format and target architecture * * This routine contains the heuristic required to determine if the object * file belongs to the OMF handled by this OMF reader, and is intended for * the proper target architecture. * It is the underlying routine for load<i class="textVariable">Omf</i>FmtCheck(). * It also checks if the module header is of the same byte order as the host. * If not, a swap is required whenever information is read in to be * processed on the host. * * RETURNS: TRUE or FALSE */ LOCAL BOOL load<i class="textVariable">Omf</i>ModuleIsOk ( UINT16 magicNumber, /* OMF magic number */ BOOL * pSwapIsRequired /* TRUE if header fields have to be swapped */ ) { BOOL moduleIsForTarget = FALSE; /* TRUE if intended for target*/ BOOL byteOrderDiffer = FALSE; /* TRUE if byte same order */ /* check if the module is in the correct OMF */ /* Your code here */ /* check if the module if for the current CPU */ return (<i class="textVariable">omf</i>ModuleVerify ((machType, pSwapIsRequired)); }</a></b></pre></dl></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H3"><i><a name="86591">3.9.7 OMF Header Processing</a></i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="85610"> </a>Object-module headers hold vital information about the whole module or pieces of the module. The numbers and characteristics of the headers depend on the OMF. For instance, a.out has one header for the whole module while COFF has a general header, an optional header, plus one header per section. The header information, which includes the section sizes, the number of symbols, and the number of relocation entries, is used for all module processing.</p><dd><p class="Body"><a name="85611"> </a>It is good programming practice to store the OMF description (the C objects that represent the OMF entities such as headers, symbol entries, relocation entries, and specific values) in a separate header file (<i class="textVariable">filename</i><b class="file">.h</b>). Headers then fit naturally into C structures. See <b class="file">a_out.h</b> for example.</p><dd><p class="Body"><a name="85612"> </a>Reading in the object-module headers involves reading values from the object-module image in memory into structure fields. Complicating issues include byte ordering, type abstraction, and data element size in both the header and the structure. For all these reasons, the object-module headers have to be read field by field, as shown in <a href="c-loader9.html#85618">Example 3-6</a>.</p><dd><p class="Body"><a name="85616"> </a>In the example, a pointer of type void * is used to access all fields of the header in memory. Because no size is associated with the type void, the pointer must be advanced with a cast operation. The type size used for this cast is related to the size of the header field that must be read.</p></dl></dl><h4 class="EntityTitle"><a name="85618"><font face="Helvetica, sans-serif" size="-1" class="sans">Example 3-6: <b class="routine"><i class="routine">load</i></b><i class="term">Omf</i><b class="routine"><i class="routine">MdlHdrRd</i></b><b>( )</b> </font></a></h4><dl class="margin"><dl class="margin"><dd><pre class="Code"><b><a name="87097">/************************************************************************ * load<i class="textVariable">Omf</i>MdlHdrRd - read in the module header. * * This routine fills a header structure with information from the object * module in memory. It swaps the bytes if this is required. * * RETURNS: OK always. */ LOCAL STATUS load<i class="textVariable">Omf</i>MdlHdrRd ( char * pObjMod, /* pointer to beginning of object file */ OMF_HDR * pHdr, /* pointer to header structure to fill */ BOOL swapIsRequired /* byte order must be swapped */ ) { void * pHeaderField = (void *) pObjMod; /* ptr to each field */ /* * Fields are read one by one since we must avoid compiler padding. * Type abstractions such INT32, UINT32 are used since we don't want * to be dependent on the host sizes for short, long, and so on. */ pHdr->firstField = *((INT32 *)pHeaderField); pHeaderField = (INT32 *)pHeaderField + 1; pHdr->secondField = *((UINT32 *)pHeaderField); pHeaderField = (UINT32 *)pHeaderField + 1; pHdr->thirdField = *((UINT16 *)pHeaderField); pHeaderField = (UINT16 *)pHeaderField + 1; pHdr->fouthField = *((UINT16 *)pHeaderField); /* Take care of byte order between host and target */ SWAB_32_IF (swapIsRequired, pHdr->firstField); SWAB_32_IF (swapIsRequired, pHdr->secondField); SWAB_16_IF (swapIsRequired, pHdr->thirdField); SWAB_16_IF (swapIsRequired, pHdr->fouthField); return (OK); }</a></b></pre></dl></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H3"><i><a name="85621">3.9.8 Determining the Size of the Segments</a></i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="85623"> </a>The OMF reader must determine the size of the three segments, which may consist of several sections of the same or equivalent type. In the simplest situation, when there is only one section per segment, the segment sizes can be determined immediately. Othe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -