//PrettyPrinting type names PCCOR_SIGNATURE PrettyPrintType( PCCOR_SIGNATURE typePtr, // type to convert, CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI, // ptr to IMDInternal class with ComSig DWORD formatFlags /*= formatILDasm*/) { mdToken tk; const char* str; int typ; CQuickBytes tmp; CQuickBytes Appendix; BOOL Reiterate; int n; do { Reiterate = FALSE; switch(typ = *typePtr++) { case ELEMENT_TYPE_VOID : str = "void"; goto APPEND; case ELEMENT_TYPE_BOOLEAN : str = "bool"; goto APPEND; case ELEMENT_TYPE_CHAR : str = "char"; goto APPEND; case ELEMENT_TYPE_I1 : str = "int8"; goto APPEND; case ELEMENT_TYPE_U1 : str = "uint8"; goto APPEND; case ELEMENT_TYPE_I2 : str = "int16"; goto APPEND; case ELEMENT_TYPE_U2 : str = "uint16"; goto APPEND; case ELEMENT_TYPE_I4 : str = "int32"; goto APPEND; case ELEMENT_TYPE_U4 : str = "uint32"; goto APPEND; case ELEMENT_TYPE_I8 : str = "int64"; goto APPEND; case ELEMENT_TYPE_U8 : str = "uint64"; goto APPEND; case ELEMENT_TYPE_R4 : str = "float32"; goto APPEND; case ELEMENT_TYPE_R8 : str = "float64"; goto APPEND; case ELEMENT_TYPE_U : str = "native uint"; goto APPEND; case ELEMENT_TYPE_I : str = "native int"; goto APPEND; case ELEMENT_TYPE_OBJECT : str = "object"; goto APPEND; case ELEMENT_TYPE_STRING : str = "string"; goto APPEND; case ELEMENT_TYPE_TYPEDBYREF : str = "typedref"; goto APPEND; APPEND: appendStr(out, (char*)str); break; case ELEMENT_TYPE_VALUETYPE : if ((formatFlags & FormatKwInNames) != 0) str = "valuetype "; else str = ""; goto DO_CLASS; case ELEMENT_TYPE_CLASS : if ((formatFlags & FormatKwInNames) != 0) str = "class "; else str = ""; goto DO_CLASS; DO_CLASS: appendStr(out, (char*)str); typePtr += CorSigUncompressToken(typePtr, &tk); if(IsNilToken(tk)) { appendStr(out, "[ERROR! NIL TOKEN]"); } else PrettyPrintClass(out, tk, pIMDI, formatFlags); break; case ELEMENT_TYPE_SZARRAY : insertStr(&Appendix,"[]"); Reiterate = TRUE; break; case ELEMENT_TYPE_ARRAY : { typePtr = PrettyPrintType(typePtr, out, pIMDI, formatFlags); unsigned rank = CorSigUncompressData(typePtr); // <TODO> what is the syntax for the rank 0 case? </TODO> if (rank == 0) { appendStr(out, "[BAD: RANK == 0!]"); } else { _ASSERTE(rank != 0); #ifdef _PREFAST_ #pragma warning(push) #pragma warning(disable:22009) // "Suppress PREfast warnings about integer overflow" // PREFAST warns about using _alloca in a loop. However when we're in this switch case we do NOT // set Reiterate to true, so we only execute through the loop once! #pragma warning(disable:6263) // "Suppress PREfast warnings about stack overflow due to _alloca in a loop." #endif int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank); int* sizes = &lowerBounds[rank]; memset(lowerBounds, 0, sizeof(int)*2*rank); unsigned numSizes = CorSigUncompressData(typePtr); _ASSERTE(numSizes <= rank); unsigned i; for(i =0; i < numSizes; i++) sizes[i] = CorSigUncompressData(typePtr); unsigned numLowBounds = CorSigUncompressData(typePtr); _ASSERTE(numLowBounds <= rank); for(i = 0; i < numLowBounds; i++) typePtr+=CorSigUncompressSignedInt(typePtr,&lowerBounds[i]); appendChar(out, '['); if (rank == 1 && numSizes == 0 && numLowBounds == 0) appendStr(out, "..."); else { for(i = 0; i < rank; i++) { //if (sizes[i] != 0 || lowerBounds[i] != 0) { if (lowerBounds[i] == 0 && i < numSizes) appendStrNum(out, sizes[i]); else { if(i < numLowBounds) { appendStrNum(out, lowerBounds[i]); appendStr(out, "..."); if (/*sizes[i] != 0 && */i < numSizes) appendStrNum(out, lowerBounds[i] + sizes[i] - 1); } } } if (i < rank-1) appendChar(out, ','); } } appendChar(out, ']'); #ifdef _PREFAST_ #pragma warning(pop) #endif } } break; case ELEMENT_TYPE_VAR : appendChar(out, '!'); n = CorSigUncompressData(typePtr); appendStrNum(out, n); break; case ELEMENT_TYPE_MVAR : appendChar(out, '!'); appendChar(out, '!'); n = CorSigUncompressData(typePtr); appendStrNum(out, n); break; case ELEMENT_TYPE_FNPTR : appendStr(out, "method "); appendStr(out, "METHOD"); // was: typePtr = PrettyPrintSignature(typePtr, 0x7FFF, "*", out, pIMDI, NULL); break; case ELEMENT_TYPE_GENERICINST : { typePtr = PrettyPrintType(typePtr, out, pIMDI, formatFlags); if ((formatFlags & FormatSignature) == 0) break; if ((formatFlags & FormatAngleBrackets) != 0) appendStr(out, "<"); else appendStr(out,"["); unsigned numArgs = CorSigUncompressData(typePtr); bool needComma = false; while(numArgs--) { if (needComma) appendChar(out, ','); typePtr = PrettyPrintType(typePtr, out, pIMDI, formatFlags); needComma = true; } if ((formatFlags & FormatAngleBrackets) != 0) appendStr(out, ">"); else appendStr(out,"]"); break; } case ELEMENT_TYPE_PINNED : str = " pinned"; goto MODIFIER; case ELEMENT_TYPE_PTR : str = "*"; goto MODIFIER; case ELEMENT_TYPE_BYREF : str = "&"; goto MODIFIER; MODIFIER: insertStr(&Appendix, str); Reiterate = TRUE; break; default: case ELEMENT_TYPE_SENTINEL : case ELEMENT_TYPE_END : //_ASSERTE(!"Unknown Type"); if(typ) { char sz[64]; sprintf_s(sz,COUNTOF(sz),"/* UNKNOWN TYPE (0x%X)*/",typ); appendStr(out, sz); } break; } // end switch } while(Reiterate); if (Appendix.Size() > 0) appendStr(out,asString(&Appendix)); return(typePtr); }
HRESULT _CountBytesOfOneArg( PCCOR_SIGNATURE pbSig, ULONG *pcbTotal) // Initially, *pcbTotal contains the remaining size of the sig blob { ULONG cb; ULONG cbTotal=0; ULONG cbTotalMax; CorElementType ulElementType; ULONG ulData; ULONG ulTemp; int iData; mdToken tk; ULONG cArg; ULONG callingconv; ULONG cArgsIndex; HRESULT hr = NOERROR; if(pcbTotal==NULL) return E_FAIL; cbTotalMax = *pcbTotal; CHECK_REMAINDER; cbTotal = CorSigUncompressElementType(pbSig, &ulElementType); while (CorIsModifierElementType((CorElementType) ulElementType)) { CHECK_REMAINDER; cbTotal += CorSigUncompressElementType(&pbSig[cbTotal], &ulElementType); } switch (ulElementType) { case ELEMENT_TYPE_SZARRAY: case 0x1e /* obsolete */: // skip over base type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; break; case ELEMENT_TYPE_FNPTR: CHECK_REMAINDER; cbTotal += CorSigUncompressData (&pbSig[cbTotal], &callingconv); // remember number of bytes to represent the arg counts CHECK_REMAINDER; cbTotal += CorSigUncompressData (&pbSig[cbTotal], &cArg); // how many bytes to represent the return type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg( &pbSig[cbTotal], &cb) ); cbTotal += cb; // loop through argument for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++) { CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg( &pbSig[cbTotal], &cb) ); cbTotal += cb; } break; case ELEMENT_TYPE_ARRAY: // syntax : ARRAY BaseType <rank> [i size_1... size_i] [j lowerbound_1 ... lowerbound_j] // skip over base type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; // Parse for the rank CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); // if rank == 0, we are done if (ulData == 0) break; // any size of dimension specified? CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); while (ulData--) { CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulTemp); } // any lower bound specified? CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); while (ulData--) { CHECK_REMAINDER; cbTotal += CorSigUncompressSignedInt(&pbSig[cbTotal], &iData); } break; case ELEMENT_TYPE_VALUETYPE: case ELEMENT_TYPE_CLASS: case ELEMENT_TYPE_CMOD_REQD: case ELEMENT_TYPE_CMOD_OPT: // count the bytes for the token compression CHECK_REMAINDER; cbTotal += CorSigUncompressToken(&pbSig[cbTotal], &tk); if ( ulElementType == ELEMENT_TYPE_CMOD_REQD || ulElementType == ELEMENT_TYPE_CMOD_OPT) { // skip over base type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; } break; default: break; } *pcbTotal = cbTotal; ErrExit: return hr; }
// // _skipTypeInSignature -- skip past a type in a given signature. // Returns the number of bytes used by the type in the signature. // // ULONG _skipTypeInSignature(PCCOR_SIGNATURE sig, bool *pfPassedVarArgSentinel) { ULONG cb = 0; ULONG elementType; if (pfPassedVarArgSentinel != NULL) *pfPassedVarArgSentinel = false; cb += _skipFunkyModifiersInSignature(&sig[cb]); if (_detectAndSkipVASentinel(&sig[cb])) { cb += _detectAndSkipVASentinel(&sig[cb]); // Recursively deal with the real type. cb += _skipTypeInSignature(&sig[cb], pfPassedVarArgSentinel); if (pfPassedVarArgSentinel != NULL) *pfPassedVarArgSentinel = true; } else { cb += CorSigUncompressData(&sig[cb], &elementType); if ((elementType == ELEMENT_TYPE_CLASS) || (elementType == ELEMENT_TYPE_VALUETYPE)) { // Skip over typeref. mdToken typeRef; cb += CorSigUncompressToken(&sig[cb], &typeRef); } else if ((elementType == ELEMENT_TYPE_PTR) || (elementType == ELEMENT_TYPE_BYREF) || (elementType == ELEMENT_TYPE_PINNED) || (elementType == ELEMENT_TYPE_SZARRAY)) { // Skip over extra embedded type. cb += _skipTypeInSignature(&sig[cb]); } else if (elementType == ELEMENT_TYPE_ARRAY) { // Skip over extra embedded type. cb += _skipTypeInSignature(&sig[cb]); // Skip over rank ULONG rank; cb += CorSigUncompressData(&sig[cb], &rank); if (rank > 0) { // how many sizes? ULONG sizes; cb += CorSigUncompressData(&sig[cb], &sizes); // read out all the sizes unsigned int i; for (i = 0; i < sizes; i++) { ULONG dimSize; cb += CorSigUncompressData(&sig[cb], &dimSize); } // how many lower bounds? ULONG lowers; cb += CorSigUncompressData(&sig[cb], &lowers); // read out all the lower bounds. for (i = 0; i < lowers; i++) { int lowerBound; cb += CorSigUncompressSignedInt(&sig[cb], &lowerBound); } } } else if ( (elementType == ELEMENT_TYPE_FNPTR) ) { // We've got a method signature within this signature, // so traverse it // Run past the calling convetion, then get the // arg count, and return type ULONG cArgs; cb += _skipMethodSignatureHeader(&sig[cb], &cArgs); ULONG i; for(i = 0; i < cArgs; i++) { cb += _skipTypeInSignature(&sig[cb]); } } } return (cb); }
unsigned SizeOfField(PCCOR_SIGNATURE *ppSig, ULONG cSig, IMDInternalImport* pImport) { unsigned ret = 0xFFFFFFFF; if(ppSig && *ppSig && cSig && pImport) { unsigned callConv = CorSigUncompressData(*ppSig); if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD)) { mdToken tk; int typ; BOOL Reiterate; unsigned uElementNumber = 1; PCCOR_SIGNATURE pSigOrig = *ppSig; PCCOR_SIGNATURE pSigEnd = *ppSig+cSig; do { Reiterate = FALSE; switch(typ = *(*ppSig)++) { case ELEMENT_TYPE_VOID : return 0; case ELEMENT_TYPE_I1 : case ELEMENT_TYPE_U1 : case ELEMENT_TYPE_BOOLEAN : return uElementNumber; case ELEMENT_TYPE_CHAR : case ELEMENT_TYPE_I2 : case ELEMENT_TYPE_U2 : return (uElementNumber << 1); case ELEMENT_TYPE_I4 : case ELEMENT_TYPE_U4 : case ELEMENT_TYPE_R4 : return (uElementNumber << 2); case ELEMENT_TYPE_I8 : case ELEMENT_TYPE_U8 : case ELEMENT_TYPE_R8 : return (uElementNumber << 3); //case ELEMENT_TYPE_R : // return (uElementNumber * sizeof(float)); case ELEMENT_TYPE_OBJECT : case ELEMENT_TYPE_STRING : case ELEMENT_TYPE_FNPTR : case ELEMENT_TYPE_CLASS : case ELEMENT_TYPE_PTR : case ELEMENT_TYPE_BYREF : //case ELEMENT_TYPE_VAR : case ELEMENT_TYPE_U : case ELEMENT_TYPE_I : return (uElementNumber * sizeof(void*)); case ELEMENT_TYPE_TYPEDBYREF : // pair of ptrs return (uElementNumber * sizeof(void*)<<1); case ELEMENT_TYPE_VALUETYPE : *ppSig += CorSigUncompressToken(*ppSig, &tk); ret = SizeOfValueType(tk,pImport); if(ret != 0xFFFFFFFF) ret *= uElementNumber; return ret; // Modifiers or depedant types // uncomment when and if this type is supported by the Runtime //case ELEMENT_TYPE_VALUEARRAY : case ELEMENT_TYPE_ARRAY : ret = SizeOfField(ppSig, cSig-(unsigned)((*ppSig)-pSigOrig), pImport); if(ret != 0xFFFFFFFF) { unsigned rank = CorSigUncompressData(*ppSig); if (rank == 0) ret = 0xFFFFFFFF; else { int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank); int* sizes = &lowerBounds[rank]; memset(lowerBounds, 0, sizeof(int)*2*rank); unsigned numSizes = CorSigUncompressData(*ppSig); _ASSERTE(numSizes <= rank); unsigned i; for(i =0; i < numSizes; i++) sizes[i] = CorSigUncompressData(*ppSig); unsigned numLowBounds = CorSigUncompressData(*ppSig); _ASSERTE(numLowBounds <= rank); for(i = 0; i < numLowBounds; i++) *ppSig+=CorSigUncompressSignedInt(*ppSig,&lowerBounds[i]); for(i = 0; i < numSizes; i++) { if (sizes[i]) uElementNumber *= sizes[i]; } ret *= uElementNumber; } } return ret; case ELEMENT_TYPE_CMOD_OPT : case ELEMENT_TYPE_CMOD_REQD : *ppSig += CorSigUncompressToken(*ppSig, &tk); case ELEMENT_TYPE_PINNED : case ELEMENT_TYPE_SZARRAY : // uElementNumber doesn't change if(*ppSig < pSigEnd) Reiterate = TRUE; break; default: case ELEMENT_TYPE_SENTINEL : case ELEMENT_TYPE_END : break; } // end switch } while(Reiterate); } // end if(CALLCONV_FIELD) } // end if(signature && import) return ret; }
//***************************************************************************** // walk one type and mark tokens embedded in the signature //***************************************************************************** HRESULT FilterManager::MarkFieldSignature( PCCOR_SIGNATURE pbSig, // [IN] point to the current byte to visit in the signature ULONG cbSig, // [IN] count of bytes available. ULONG *pcbUsed) // [OUT] count of bytes consumed. { HRESULT hr = NOERROR; // A result. ULONG cb; // Bytes in one signature element. ULONG cbUsed = 0; // Total bytes consumed from signature. CorElementType ulElementType; // ELEMENT_TYPE_xxx from signature. ULONG ulData; // Some data (like a count) from the signature. ULONG ulTemp; // Unused data. mdToken token; // A token from the signature. int iData; // Integer data from signature. VALIDATE_SIGNATURE_LEN( CorSigUncompressElementType(pbSig, &ulElementType) ); // Skip the modifiers... while (CorIsModifierElementType((CorElementType) ulElementType)) { VALIDATE_SIGNATURE_LEN( CorSigUncompressElementType(pbSig, &ulElementType) ); } // Examine the signature element switch (ulElementType) { case ELEMENT_TYPE_SZARRAY: // syntax: SZARRAY <BaseType> // conver the base type for the SZARRAY or GENERICARRAY VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); break; case ELEMENT_TYPE_CMOD_REQD: case ELEMENT_TYPE_CMOD_OPT: // syntax: {CMOD_REQD|CMOD_OPT} <token> <signature> // now get the embedded token VALIDATE_SIGNATURE_LEN( CorSigUncompressToken(pbSig, &token) ); // Mark the token IfFailGo( Mark(token) ); // mark the base type VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); break; case ELEMENT_TYPE_VAR: case ELEMENT_TYPE_MVAR: // syntax: VAR <index> VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulData) ); break; case ELEMENT_TYPE_ARRAY: // syntax: ARRAY BaseType <rank> [i size_1... size_i] [j lowerbound_1 ... lowerbound_j] VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); // Parse for the rank VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulData) ); // if rank == 0, we are done if (ulData == 0) break; // Any size of dimension specified? VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulData) ); // Consume sizes of dimension. while (ulData--) { VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulTemp) ); } // Any lower bounds specified? VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulData) ); // Consume lower bounds. while (ulData--) { VALIDATE_SIGNATURE_LEN( CorSigUncompressSignedInt(pbSig, &iData) ); } break; case ELEMENT_TYPE_FNPTR: // function pointer is followed by another complete signature VALIDATE_SIGNATURE_LEN_HR( MarkSignature(pbSig, cbSig - cbUsed, &cb) ); break; case ELEMENT_TYPE_VALUETYPE: case ELEMENT_TYPE_CLASS: // syntax: {CLASS | VALUECLASS} <token> VALIDATE_SIGNATURE_LEN( CorSigUncompressToken(pbSig, &token) ); // Mark it. IfFailGo( Mark(token) ); break; case ELEMENT_TYPE_GENERICINST: // syntax: ELEMENT_TYPE_GEENRICINST <ELEMENT_TYPE_CLASS | ELEMENT_TYPE_VALUECLASS> <token> <n> <n params> VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); // Get the number of generic parameters VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulData) ); // Get the generic parameters while (ulData--) { VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); } break; default: // If valid element (I4, etc), great. Otherwise, return error. if ((ulElementType >= ELEMENT_TYPE_MAX) || (ulElementType == ELEMENT_TYPE_PTR) || (ulElementType == ELEMENT_TYPE_BYREF) || (ulElementType == ELEMENT_TYPE_VALUEARRAY_UNSUPPORTED)) { IfFailGo(META_E_BAD_SIGNATURE); } break; } ErrExit: *pcbUsed = cbUsed; return hr; } // HRESULT FilterManager::MarkFieldSignature()