home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / corhlpr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  17.0 KB  |  432 lines

  1. /****************************************************************************
  2.  **                                                                        **
  3.  ** Corhlpr.h - signature helpers.                                         **
  4.  **                                                                        **
  5.  ** Copyright (c) 1996-2000 Microsoft Corporation.  All Rights Reserved.   **
  6.  **                                                                        **
  7.  ****************************************************************************/
  8.  
  9. #include "corhlpr.h"
  10. #include <stdlib.h>
  11.  
  12. /*************************************************************************************
  13. *
  14. * get number of bytes consumed by one argument/return type
  15. *
  16. *************************************************************************************/
  17.  
  18. HRESULT _CountBytesOfOneArg(
  19.     PCCOR_SIGNATURE pbSig, 
  20.     ULONG       *pcbTotal)
  21. {
  22.     ULONG       cb;
  23.     ULONG       cbTotal = 0;
  24.     CorElementType ulElementType;
  25.     ULONG       ulData;
  26.     ULONG       ulTemp;
  27.     int         iData;
  28.     mdToken     tk;
  29.     ULONG       cArg;
  30.     ULONG       callingconv;
  31.     ULONG       cArgsIndex;
  32.     HRESULT     hr = NOERROR;
  33.  
  34.     _ASSERTE(pcbTotal);
  35.  
  36.     cbTotal += CorSigUncompressElementType(&pbSig[cbTotal], &ulElementType);
  37.     while (CorIsModifierElementType((CorElementType) ulElementType))
  38.     {
  39.         cbTotal += CorSigUncompressElementType(&pbSig[cbTotal], &ulElementType);
  40.     }
  41.     switch (ulElementType)
  42.     {
  43.         case ELEMENT_TYPE_VALUEARRAY:
  44.             // syntax for SDARRAY = BaseType <an integer for size>
  45.             // skip over base type
  46.             IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) );
  47.             cbTotal += cb;
  48.  
  49.             // Parse for the rank
  50.             cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData);
  51.  
  52.             break;
  53.  
  54.         case ELEMENT_TYPE_COPYCTOR:
  55.         case ELEMENT_TYPE_SZARRAY:
  56.         case ELEMENT_TYPE_GENERICARRAY:
  57.             // skip over base type
  58.             IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) );
  59.             cbTotal += cb;
  60.             break;
  61.  
  62.         case ELEMENT_TYPE_FNPTR:
  63.             cbTotal += CorSigUncompressData (&pbSig[cbTotal], &callingconv);
  64.  
  65.             // remember number of bytes to represent the arg counts
  66.             cbTotal += CorSigUncompressData (&pbSig[cbTotal], &cArg);
  67.  
  68.             // how many bytes to represent the return type
  69.             IfFailGo( _CountBytesOfOneArg( &pbSig[cbTotal], &cb) );
  70.             cbTotal += cb;
  71.     
  72.             // loop through argument
  73.             for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++)
  74.             {
  75.                 IfFailGo( _CountBytesOfOneArg( &pbSig[cbTotal], &cb) );
  76.                 cbTotal += cb;
  77.             }
  78.  
  79.             break;
  80.  
  81.         case ELEMENT_TYPE_ARRAY:
  82.             // syntax : ARRAY BaseType <rank> [i size_1... size_i] [j lowerbound_1 ... lowerbound_j]
  83.  
  84.             // skip over base type
  85.             IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) );
  86.             cbTotal += cb;
  87.  
  88.             // Parse for the rank
  89.             cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData);
  90.  
  91.             // if rank == 0, we are done
  92.             if (ulData == 0)
  93.                 break;
  94.  
  95.             // any size of dimension specified?
  96.             cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData);
  97.             while (ulData--)
  98.             {
  99.                 cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulTemp);
  100.             }
  101.  
  102.             // any lower bound specified?
  103.             cbTotal = CorSigUncompressData(&pbSig[cbTotal], &ulData);
  104.  
  105.             while (ulData--)
  106.             {
  107.                 cbTotal += CorSigUncompressSignedInt(&pbSig[cbTotal], &iData);
  108.             }
  109.  
  110.             break;
  111.         case ELEMENT_TYPE_VALUETYPE:
  112.         case ELEMENT_TYPE_CLASS:
  113.         case ELEMENT_TYPE_CMOD_REQD:
  114.         case ELEMENT_TYPE_CMOD_OPT:
  115.             // count the bytes for the token compression
  116.             cbTotal += CorSigUncompressToken(&pbSig[cbTotal], &tk);
  117.             if ( ulElementType == ELEMENT_TYPE_CMOD_REQD ||
  118.                  ulElementType == ELEMENT_TYPE_CMOD_OPT)
  119.             {
  120.                 // skip over base type
  121.                 IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) );
  122.                 cbTotal += cb;
  123.             }
  124.             break;
  125.         default:
  126.             break;
  127.     }
  128.  
  129.     *pcbTotal = cbTotal;
  130. ErrExit:
  131.     return hr;
  132. }
  133.  
  134.  
  135. //*****************************************************************************
  136. // copy fixed part of VarArg signature to a buffer
  137. //*****************************************************************************
  138. HRESULT _GetFixedSigOfVarArg(           // S_OK or error.
  139.     PCCOR_SIGNATURE pvSigBlob,          // [IN] point to a blob of COM+ method signature
  140.     ULONG   cbSigBlob,                  // [IN] size of signature
  141.     CQuickBytes *pqbSig,                // [OUT] output buffer for fixed part of VarArg Signature
  142.     ULONG   *pcbSigBlob)                // [OUT] number of bytes written to the above output buffer
  143. {
  144.     HRESULT     hr = NOERROR;
  145.     ULONG       cbCalling;
  146.     ULONG       cbArgsNumber;           // number of bytes to store the original arg count
  147.     ULONG       cbArgsNumberTemp;       // number of bytes to store the fixed arg count
  148.     ULONG       cbTotal = 0;            // total of number bytes for return type + all fixed arguments
  149.     ULONG       cbCur = 0;              // index through the pvSigBlob
  150.     ULONG       cb;
  151.     ULONG       cArg;
  152.     ULONG       callingconv;
  153.     ULONG       cArgsIndex;
  154.     CorElementType ulElementType;
  155.     BYTE        *pbSig;
  156.  
  157.     _ASSERTE (pvSigBlob && pcbSigBlob);
  158.  
  159.     // remember the number of bytes to represent the calling convention
  160.     cbCalling = CorSigUncompressData (pvSigBlob, &callingconv);
  161.     _ASSERTE (isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_VARARG));
  162.     cbCur += cbCalling;
  163.  
  164.     // remember number of bytes to represent the arg counts
  165.     cbArgsNumber= CorSigUncompressData (&pvSigBlob[cbCur], &cArg);
  166.     cbCur += cbArgsNumber;
  167.  
  168.     // how many bytes to represent the return type
  169.     IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) );
  170.     cbCur += cb;
  171.     cbTotal += cb;
  172.     
  173.     // loop through argument until we found ELEMENT_TYPE_SENTINEL or run
  174.     // out of arguments
  175.     for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++)
  176.     {
  177.         _ASSERTE(cbCur < cbSigBlob);
  178.  
  179.         // peak the outter most ELEMENT_TYPE_*
  180.         CorSigUncompressElementType (&pvSigBlob[cbCur], &ulElementType);
  181.         if (ulElementType == ELEMENT_TYPE_SENTINEL)
  182.             break;
  183.         IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) );
  184.         cbTotal += cb;
  185.         cbCur += cb;
  186.     }
  187.  
  188.     cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &cArg);
  189.  
  190.     // now cbCalling : the number of bytes needed to store the calling convention
  191.     // cbArgNumberTemp : number of bytes to store the fixed arg count
  192.     // cbTotal : the number of bytes to store the ret and fixed arguments
  193.  
  194.     *pcbSigBlob = cbCalling + cbArgsNumberTemp + cbTotal;
  195.  
  196.     // resize the buffer
  197.     IfFailGo( pqbSig->ReSize(*pcbSigBlob) );
  198.     pbSig = (BYTE *)pqbSig->Ptr();
  199.  
  200.     // copy over the calling convention
  201.     cb = CorSigCompressData(callingconv, pbSig);
  202.  
  203.     // copy over the fixed arg count
  204.     cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &pbSig[cb]);
  205.  
  206.     // copy over the fixed args + ret type
  207.     memcpy(&pbSig[cb + cbArgsNumberTemp], &pvSigBlob[cbCalling + cbArgsNumber], cbTotal);
  208.  
  209. ErrExit:
  210.     return hr;
  211. }
  212.  
  213.  
  214.  
  215.  
  216.  
  217. //*****************************************************************************
  218. //
  219. //***** File format helper classes
  220. //
  221. //*****************************************************************************
  222.  
  223. extern "C" {
  224.  
  225. /***************************************************************************/
  226. /* Note that this construtor does not set the LocalSig, but has the
  227.    advantage that it does not have any dependancy on EE structures.
  228.    inside the EE use the FunctionDesc constructor */
  229.  
  230. void __stdcall DecoderInit(void * pThis, COR_ILMETHOD* header) 
  231. {
  232.     memset(pThis, 0, sizeof(COR_ILMETHOD_DECODER));
  233.     if (header->Tiny.IsTiny()) {
  234.         ((COR_ILMETHOD_DECODER*)pThis)->MaxStack = header->Tiny.GetMaxStack();
  235.         ((COR_ILMETHOD_DECODER*)pThis)->Code = header->Tiny.GetCode();
  236.         ((COR_ILMETHOD_DECODER*)pThis)->CodeSize = header->Tiny.GetCodeSize();
  237.         ((COR_ILMETHOD_DECODER*)pThis)->Flags |= CorILMethod_TinyFormat;
  238.         return;
  239.     }
  240.     if (header->Fat.IsFat()) {
  241.         _ASSERTE((((size_t) header) & 3) == 0);        // header is aligned
  242.         *((COR_ILMETHOD_FAT*) pThis) = header->Fat;
  243.         ((COR_ILMETHOD_DECODER*)pThis)->Code = header->Fat.GetCode();
  244.         _ASSERTE(header->Fat.Size >= 3);        // Size if valid
  245.         ((COR_ILMETHOD_DECODER*)pThis)->Sect = header->Fat.GetSect();
  246.         if (((COR_ILMETHOD_DECODER*)pThis)->Sect != 0 && ((COR_ILMETHOD_DECODER*)pThis)->Sect->Kind() == CorILMethod_Sect_EHTable) {
  247.             ((COR_ILMETHOD_DECODER*)pThis)->EH = (COR_ILMETHOD_SECT_EH*) ((COR_ILMETHOD_DECODER*)pThis)->Sect;
  248.             ((COR_ILMETHOD_DECODER*)pThis)->Sect = ((COR_ILMETHOD_DECODER*)pThis)->Sect->Next();
  249.         }
  250.         return;
  251.     }
  252.     _ASSERTE(!"Unknown format");
  253. }
  254.  
  255. // Calculate the total method size. First get address of end of code. If there are no sections, then
  256. // the end of code addr marks end of COR_ILMETHOD. Otherwise find addr of end of last section and use it
  257. // to mark end of COR_ILMETHD. Assumes that the code is directly followed
  258. // by each section in the on-disk format
  259. int __stdcall DecoderGetOnDiskSize(void * pThis, COR_ILMETHOD* header)
  260. {
  261.     BYTE *lastAddr = (BYTE*)((COR_ILMETHOD_DECODER*)pThis)->Code + ((COR_ILMETHOD_DECODER*)pThis)->CodeSize;    // addr of end of code
  262.     const COR_ILMETHOD_SECT *sect = ((COR_ILMETHOD_DECODER*)pThis)->EH;
  263.     if (sect != 0 && sect->Next() == 0)
  264.         lastAddr = (BYTE *)(§->Data()[sect->DataSize()]);
  265.     else
  266.     {
  267.         const COR_ILMETHOD_SECT *nextSect;
  268.         for (sect = ((COR_ILMETHOD_DECODER*)pThis)->Sect; 
  269.              sect; sect = nextSect) {
  270.             nextSect = sect->Next();
  271.             if (nextSect == 0) {
  272.                 // sect points to the last section, so set lastAddr
  273.                 lastAddr = (BYTE *)(§->Data()[sect->DataSize()]);
  274.                 break;
  275.             }
  276.         }
  277.     }
  278.     return (int)(lastAddr - (BYTE*)header);
  279. }
  280.  
  281. /*********************************************************************/
  282. /* APIs for emitting sections etc */
  283.  
  284. unsigned __stdcall IlmethodSize(COR_ILMETHOD_FAT* header, BOOL moreSections)
  285. {
  286.     if (header->MaxStack <= 8 && header->Flags == 0
  287.         && header->LocalVarSigTok == 0 && header->CodeSize < 64 && !moreSections)
  288.         return(sizeof(COR_ILMETHOD_TINY));
  289.  
  290.     return(sizeof(COR_ILMETHOD_FAT));
  291. }
  292.  
  293. /*********************************************************************/
  294.         // emit the header (bestFormat) return amount emitted   
  295. unsigned __stdcall IlmethodEmit(unsigned size, COR_ILMETHOD_FAT* header, 
  296.                   BOOL moreSections, BYTE* outBuff)
  297. {
  298.     BYTE* origBuff = outBuff;
  299.     if (size == 1) {
  300.             // Tiny format
  301.         *outBuff++ = (BYTE) (CorILMethod_TinyFormat | (header->CodeSize << 2));
  302.     }
  303.     else {
  304.             // Fat format
  305.         _ASSERTE((((size_t) outBuff) & 3) == 0);               // header is dword aligned
  306.         COR_ILMETHOD_FAT* fatHeader = (COR_ILMETHOD_FAT*) outBuff;
  307.         outBuff += sizeof(COR_ILMETHOD_FAT);
  308.         *fatHeader = *header;
  309.         fatHeader->Flags |= CorILMethod_FatFormat;
  310.         _ASSERTE((fatHeader->Flags & CorILMethod_FormatMask) == CorILMethod_FatFormat);
  311.         if (moreSections)
  312.             fatHeader->Flags |= CorILMethod_MoreSects;
  313.         fatHeader->Size = sizeof(COR_ILMETHOD_FAT) / 4;
  314.     }
  315.     _ASSERTE(&origBuff[size] == outBuff);
  316.     return(size);
  317. }
  318.  
  319. /*********************************************************************/
  320. /* static */
  321. IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* __stdcall SectEH_EHClause(void *pSectEH, unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff)
  322. {    
  323.     if (((COR_ILMETHOD_SECT_EH *)pSectEH)->IsFat()) 
  324.         return(&(((COR_ILMETHOD_SECT_EH *)pSectEH)->Fat.Clauses[idx])); 
  325.  
  326.     // mask to remove sign extension - cast just wouldn't work 
  327.     buff->Flags         = (CorExceptionFlag)((((COR_ILMETHOD_SECT_EH *)pSectEH)->Small.Clauses[idx].Flags)&0x0000ffff); 
  328.     buff->ClassToken    = ((COR_ILMETHOD_SECT_EH *)pSectEH)->Small.Clauses[idx].ClassToken;    
  329.     buff->TryOffset     = ((COR_ILMETHOD_SECT_EH *)pSectEH)->Small.Clauses[idx].TryOffset;   
  330.     buff->TryLength     = ((COR_ILMETHOD_SECT_EH *)pSectEH)->Small.Clauses[idx].TryLength; 
  331.     buff->HandlerLength = ((COR_ILMETHOD_SECT_EH *)pSectEH)->Small.Clauses[idx].HandlerLength;
  332.     buff->HandlerOffset = ((COR_ILMETHOD_SECT_EH *)pSectEH)->Small.Clauses[idx].HandlerOffset; 
  333.     return(buff);   
  334. }   
  335. /*********************************************************************/
  336.         // compute the size of the section (best format)    
  337.         // codeSize is the size of the method   
  338.     // deprecated
  339. unsigned __stdcall SectEH_SizeWithCode(unsigned ehCount, unsigned codeSize)
  340. {
  341.     return((ehCount)? SectEH_SizeWorst(ehCount) : 0);
  342. }
  343.  
  344.     // will return worse-case size and then Emit will return actual size
  345. unsigned __stdcall SectEH_SizeWorst(unsigned ehCount)
  346. {
  347.     return((ehCount)? (COR_ILMETHOD_SECT_EH_FAT::Size(ehCount)) : 0);
  348. }
  349.  
  350.     // will return exact size which will match the size returned by Emit
  351. unsigned __stdcall SectEH_SizeExact(unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses)
  352. {
  353.     if (ehCount == 0)
  354.         return(0);
  355.  
  356.     unsigned smallSize = COR_ILMETHOD_SECT_EH_SMALL::Size(ehCount);
  357.     if (smallSize > COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE)
  358.             return(COR_ILMETHOD_SECT_EH_FAT::Size(ehCount));
  359.     for (unsigned i = 0; i < ehCount; i++) {
  360.         if (clauses[i].TryOffset > 0xFFFF ||
  361.                 clauses[i].TryLength > 0xFF ||
  362.                 clauses[i].HandlerOffset > 0xFFFF ||
  363.                 clauses[i].HandlerLength > 0xFF) {
  364.             return(COR_ILMETHOD_SECT_EH_FAT::Size(ehCount));
  365.         }
  366.     }
  367.     return smallSize;
  368. }
  369.  
  370. /*********************************************************************/
  371.  
  372.         // emit the section (best format);  
  373. unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount,   
  374.                   IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses,   
  375.                   BOOL moreSections, BYTE* outBuff)
  376. {
  377.     if (size == 0)
  378.        return(0);
  379.  
  380.     _ASSERTE((((size_t) outBuff) & 3) == 0);               // header is dword aligned
  381.     BYTE* origBuff = outBuff;
  382.     if (ehCount <= 0)
  383.         return 0;
  384.  
  385.     if (COR_ILMETHOD_SECT_EH_SMALL::Size(ehCount) < COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE) {
  386.         COR_ILMETHOD_SECT_EH_SMALL* EHSect = (COR_ILMETHOD_SECT_EH_SMALL*) outBuff;
  387.         for (unsigned i = 0; i < ehCount; i++) {
  388.             if (clauses[i].TryOffset > 0xFFFF ||
  389.                     clauses[i].TryLength > 0xFF ||
  390.                     clauses[i].HandlerOffset > 0xFFFF ||
  391.                     clauses[i].HandlerLength > 0xFF) {
  392.                 break;  // fall through and generate as FAT
  393.             }
  394.             _ASSERTE((clauses[i].Flags & ~0xFFFF) == 0);
  395.             _ASSERTE((clauses[i].TryOffset & ~0xFFFF) == 0);
  396.             _ASSERTE((clauses[i].TryLength & ~0xFF) == 0);
  397.             _ASSERTE((clauses[i].HandlerOffset & ~0xFFFF) == 0);
  398.             _ASSERTE((clauses[i].HandlerLength & ~0xFF) == 0);
  399.             EHSect->Clauses[i].Flags         = (CorExceptionFlag) clauses[i].Flags;
  400.             EHSect->Clauses[i].TryOffset     = (WORD) clauses[i].TryOffset;
  401.             EHSect->Clauses[i].TryLength     = (WORD) clauses[i].TryLength;
  402.             EHSect->Clauses[i].HandlerOffset = (WORD) clauses[i].HandlerOffset;
  403.             EHSect->Clauses[i].HandlerLength = (WORD) clauses[i].HandlerLength;
  404.             EHSect->Clauses[i].ClassToken    = clauses[i].ClassToken;
  405.         }
  406.         if (i >= ehCount) {
  407.             // if actually got through all the clauses and they are small enough
  408.             EHSect->Kind = CorILMethod_Sect_EHTable;
  409.             if (moreSections)
  410.                 EHSect->Kind |= CorILMethod_Sect_MoreSects;
  411.             EHSect->DataSize = EHSect->Size(ehCount);
  412.             _ASSERTE(EHSect->DataSize == EHSect->Size(ehCount)); // make sure didn't overflow
  413.             outBuff = (BYTE*) &EHSect->Clauses[ehCount];
  414.             return(size);
  415.         }
  416.     }
  417.     // either total size too big or one of constituent elements too big (eg. offset or length)
  418.     COR_ILMETHOD_SECT_EH_FAT* EHSect = (COR_ILMETHOD_SECT_EH_FAT*) outBuff;
  419.     EHSect->Kind = CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat;
  420.     if (moreSections)
  421.         EHSect->Kind |= CorILMethod_Sect_MoreSects;
  422.     EHSect->DataSize = EHSect->Size(ehCount);
  423.     memcpy(EHSect->Clauses, clauses, ehCount * sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
  424.     outBuff = (BYTE*) &EHSect->Clauses[ehCount];
  425.     _ASSERTE(&origBuff[size] == outBuff);
  426.     return(size);
  427. }
  428.  
  429. } // extern "C"
  430.  
  431.  
  432.