/* * Get the metadata size information for a program item, * both on-disk and in-memory. */ static void GetMetadataSize(ILSizeInfo *info, ILProgramItem *item) { ILImage *image = ILProgramItem_Image(item); if(!item) { return; } info->meta += image->tokenSize[ILProgramItem_Token(item) >> 24]; switch(ILProgramItem_Token(item) & IL_META_TOKEN_MASK) { case IL_META_TOKEN_MODULE: GetStringSize(info, ILModule_Name((ILModule *)item)); info->meta += 16; /* GUID size */ info->loadedMeta += sizeof(ILModule); break; case IL_META_TOKEN_MODULE_REF: GetStringSize(info, ILModule_Name((ILModule *)item)); info->loadedMeta += sizeof(ILModule); break; case IL_META_TOKEN_TYPE_REF: info->loadedMeta += sizeof(ILClass); info->loadedMeta += sizeof(ILProgramItemLink); GetClassNameSize(info, (ILClass *)item); break; case IL_META_TOKEN_TYPE_DEF: info->loadedMeta += sizeof(ILClass); GetClassNameSize(info, (ILClass *)item); break; case IL_META_TOKEN_FIELD_DEF: info->loadedMeta += sizeof(ILField); GetStringSize(info, ILMember_Name(item)); GetBlobSize(info, item, ((ILMember *)item)->signatureBlob); GetTypeSize(info, ILMember_Signature(item)); break; case IL_META_TOKEN_METHOD_DEF: info->loadedMeta += sizeof(ILMethod); GetStringSize(info, ILMember_Name(item)); GetBlobSize(info, item, ((ILMember *)item)->signatureBlob); GetTypeSize(info, ILMember_Signature(item)); break; case IL_META_TOKEN_PARAM_DEF: info->loadedMeta += sizeof(ILParameter); GetStringSize(info, ILParameter_Name((ILParameter *)item)); break; case IL_META_TOKEN_INTERFACE_IMPL: info->loadedMeta += sizeof(ILImplements); break; case IL_META_TOKEN_MEMBER_REF: if(ILMemberGetKind((ILMember *)item) == IL_META_MEMBERKIND_METHOD) { info->loadedMeta += sizeof(ILMethod); } else { info->loadedMeta += sizeof(ILField); } info->loadedMeta += sizeof(ILProgramItemLink); GetStringSize(info, ILMember_Name(item)); GetBlobSize(info, item, ((ILMember *)item)->signatureBlob); GetTypeSize(info, ILMember_Signature(item)); break; case IL_META_TOKEN_CONSTANT: info->loadedMeta += sizeof(ILConstant); GetBlobSize(info, item, ((ILConstant *)item)->value); break; case IL_META_TOKEN_CUSTOM_ATTRIBUTE: info->loadedMeta += sizeof(ILAttribute); GetBlobSize(info, item, ((ILAttribute *)item)->value); break; case IL_META_TOKEN_FIELD_MARSHAL: info->loadedMeta += sizeof(ILFieldMarshal); GetBlobSize(info, item, ((ILFieldMarshal *)item)->type); break; case IL_META_TOKEN_DECL_SECURITY: info->loadedMeta += sizeof(ILDeclSecurity); GetBlobSize(info, item, ((ILDeclSecurity *)item)->blob); break; case IL_META_TOKEN_CLASS_LAYOUT: info->loadedMeta += sizeof(ILClassLayout); break; case IL_META_TOKEN_FIELD_LAYOUT: info->loadedMeta += sizeof(ILFieldLayout); break; case IL_META_TOKEN_STAND_ALONE_SIG: info->loadedMeta += sizeof(ILStandAloneSig); GetBlobSize(info, item, ((ILStandAloneSig *)item)->typeBlob); GetTypeSize(info, ((ILStandAloneSig *)item)->type); break; case IL_META_TOKEN_EVENT_MAP: info->loadedMeta += sizeof(ILEventMap); break; case IL_META_TOKEN_EVENT: info->loadedMeta += sizeof(ILEvent); break; case IL_META_TOKEN_PROPERTY_MAP: info->loadedMeta += sizeof(ILPropertyMap); break; case IL_META_TOKEN_PROPERTY: info->loadedMeta += sizeof(ILProperty); break; case IL_META_TOKEN_METHOD_SEMANTICS: info->loadedMeta += sizeof(ILMethodSem); break; case IL_META_TOKEN_METHOD_IMPL: info->loadedMeta += sizeof(ILOverride); break; case IL_META_TOKEN_TYPE_SPEC: info->loadedMeta += sizeof(ILTypeSpec); GetBlobSize(info, item, ((ILTypeSpec *)item)->typeBlob); GetTypeSize(info, ((ILTypeSpec *)item)->type); break; case IL_META_TOKEN_IMPL_MAP: info->loadedMeta += sizeof(ILPInvoke); GetStringSize(info, ILPInvoke_Alias((ILPInvoke *)item)); break; case IL_META_TOKEN_FIELD_RVA: info->loadedMeta += sizeof(ILFieldRVA); break; case IL_META_TOKEN_ASSEMBLY: info->loadedMeta += sizeof(ILAssembly); GetStringSize(info, ILAssembly_Name((ILAssembly *)item)); GetStringSize(info, ILAssembly_Locale((ILAssembly *)item)); break; case IL_META_TOKEN_ASSEMBLY_REF: info->loadedMeta += sizeof(ILAssembly); info->loadedMeta += sizeof(ILProgramItemLink); GetStringSize(info, ILAssembly_Name((ILAssembly *)item)); GetStringSize(info, ILAssembly_Locale((ILAssembly *)item)); break; case IL_META_TOKEN_PROCESSOR_DEF: case IL_META_TOKEN_PROCESSOR_REF: info->loadedMeta += sizeof(ILProcessorInfo); break; case IL_META_TOKEN_OS_DEF: case IL_META_TOKEN_OS_REF: info->loadedMeta += sizeof(ILOSInfo); break; case IL_META_TOKEN_FILE: info->loadedMeta += sizeof(ILFileDecl); GetStringSize(info, ILFileDecl_Name((ILFileDecl *)item)); GetBlobSize(info, item, ((ILFileDecl *)item)->hash); break; case IL_META_TOKEN_EXPORTED_TYPE: info->loadedMeta += sizeof(ILExportedType); info->loadedMeta += sizeof(ILProgramItemLink); GetClassNameSize(info, (ILClass *)item); break; case IL_META_TOKEN_MANIFEST_RESOURCE: info->loadedMeta += sizeof(ILManifestRes); GetStringSize(info, ILManifestRes_Name((ILManifestRes *)item)); break; case IL_META_TOKEN_NESTED_CLASS: info->loadedMeta += sizeof(ILNestedInfo); break; case IL_META_TOKEN_GENERIC_PAR: info->loadedMeta += sizeof(ILGenericPar); GetStringSize(info, ILGenericPar_Name((ILGenericPar *)item)); break; case IL_META_TOKEN_METHOD_SPEC: info->loadedMeta += sizeof(ILMethodSpec); GetBlobSize(info, item, ((ILMethodSpec *)item)->typeBlob); GetTypeSize(info, ((ILMethodSpec *)item)->type); break; } }
/* * Inner version of "_ILConvertMethod", which detects the type of * exception to throw, but does not throw it. */ static unsigned char *ConvertMethod(ILExecThread *thread, ILMethod *method, int *errorCode, const char **errorInfo) { ILMethodCode code; ILPInvoke *pinv; ILCoder *coder = thread->process->coder; unsigned char *start; void *cif; void *ctorcif; int isConstructor; #ifdef IL_CONFIG_PINVOKE ILModule *module; const char *name; void *moduleHandle; #endif int result; ILInternalInfo fnInfo; ILInternalInfo ctorfnInfo; /* We need the metadata write lock */ METADATA_WRLOCK(thread); /* Handle locked methods while cctors are executed. */ if((start = (unsigned char *)ILCoderHandleLockedMethod(coder, method))) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_OK; return start; } /* Is the method already converted? */ if((start = (unsigned char *)(method->userData)) != 0) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_OK; return start; } #ifndef IL_CONFIG_VARARGS /* Vararg methods are not supported */ if((ILMethod_CallConv(method) & IL_META_CALLCONV_MASK) == IL_META_CALLCONV_VARARG) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_NOT_IMPLEMENTED; return 0; } #endif /* Make sure that we can lay out the method's class */ if(!_ILLayoutClass(_ILExecThreadProcess(thread), ILMethod_Owner(method))) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_TYPE_INIT; return 0; } /* Get the method code */ if(!ILMethodGetCode(method, &code)) { code.code = 0; } /* The conversion is different depending upon whether the method is written in IL or not */ if(code.code) { /* Use the bytecode verifier and coder to convert the method */ if(!_ILVerify(coder, &start, method, &code, ILImageIsSecure(ILProgramItem_Image(method)), thread)) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_VERIFY_FAILED; return 0; } } else { /* This is a "PInvoke", "internalcall", or "runtime" method */ pinv = ILPInvokeFind(method); fnInfo.func = 0; fnInfo.marshal = 0; ctorfnInfo.func = 0; ctorfnInfo.marshal = 0; isConstructor = ILMethod_IsConstructor(method); switch(method->implementAttrs & (IL_META_METHODIMPL_CODE_TYPE_MASK | IL_META_METHODIMPL_INTERNAL_CALL | IL_META_METHODIMPL_JAVA)) { case IL_META_METHODIMPL_IL: case IL_META_METHODIMPL_OPTIL: { /* If we don't have a PInvoke record, then we don't know what to map this method call to */ if(!pinv) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_ENTRY_POINT; return 0; } #ifdef IL_CONFIG_PINVOKE /* Find the module for the PInvoke record */ module = ILPInvoke_Module(pinv); if(!module) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_ENTRY_POINT; return 0; } name = ILModule_Name(module); if(!name || *name == '\0') { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_ENTRY_POINT; return 0; } moduleHandle = LocateExternalModule (thread->process, name, pinv); if(!moduleHandle) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_DLL_NOT_FOUND; *errorInfo = name; return 0; } /* Get the name of the function within the module */ name = ILPInvoke_Alias(pinv); if(!name || *name == '\0') { name = ILMethod_Name(method); } #ifdef IL_WIN32_PLATFORM if(!(pinv->member.attributes & IL_META_PINVOKE_NO_MANGLE)) { /* We have to append an A or W to the function */ /* name depending on the characterset used. */ /* On Windows we have only either Ansi or Utf16 */ int nameLength = strlen(name); ILUInt32 charSetUsed = ILPInvokeGetCharSet(pinv, method); char newName[nameLength + 2]; strcpy(newName, name); if(charSetUsed == IL_META_MARSHAL_UTF16_STRING) { newName[nameLength] = 'W'; } else { newName[nameLength] = 'A'; } newName[nameLength + 1] = '\0'; /* Look up the method within the module */ fnInfo.func = ILDynLibraryGetSymbol(moduleHandle, newName); } if(!fnInfo.func) { /* Look up the method within the module */ fnInfo.func = ILDynLibraryGetSymbol(moduleHandle, name); } #else /* !IL_WIN32_PLATFORM */ /* Look up the method within the module */ fnInfo.func = ILDynLibraryGetSymbol(moduleHandle, name); #endif /* !IL_WIN32_PLATFORM */ #else /* !IL_CONFIG_PINVOKE */ METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_NOT_IMPLEMENTED; return 0; #endif /* IL_CONFIG_PINVOKE */ } break; case IL_META_METHODIMPL_RUNTIME: case IL_META_METHODIMPL_IL | IL_META_METHODIMPL_INTERNAL_CALL: { /* "internalcall" and "runtime" methods must not have PInvoke records associated with them */ if(pinv) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_VERIFY_FAILED; return 0; } /* Look up the internalcall function details */ if(!_ILFindInternalCall(ILExecThreadGetProcess(thread), method, 0, &fnInfo)) { if(isConstructor) { if(!_ILFindInternalCall(ILExecThreadGetProcess(thread), method, 1, &ctorfnInfo)) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_NOT_IMPLEMENTED; return 0; } } else { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_NOT_IMPLEMENTED; return 0; } } else if(isConstructor) { _ILFindInternalCall(ILExecThreadGetProcess(thread), method, 1, &ctorfnInfo); } } break; default: { /* No idea how to invoke this method */ METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_VERIFY_FAILED; return 0; } /* Not reached */ } /* Bail out if we did not find the underlying native method */ if(!(fnInfo.func) && !(ctorfnInfo.func)) { METADATA_UNLOCK(thread); if(pinv) *errorCode = IL_CONVERT_ENTRY_POINT; else *errorCode = IL_CONVERT_NOT_IMPLEMENTED; return 0; } #if defined(HAVE_LIBFFI) /* Generate a "cif" structure to handle the native call details */ if(fnInfo.func) { /* Make the "cif" structure for the normal method entry */ cif = _ILMakeCifForMethod(_ILExecThreadProcess(thread), method, (pinv == 0)); if(!cif) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_OUT_OF_MEMORY; return 0; } } else { cif = 0; } if(ctorfnInfo.func) { /* Make the "cif" structure for the allocating constructor */ ctorcif = _ILMakeCifForConstructor(_ILExecThreadProcess(thread), method, (pinv == 0)); if(!ctorcif) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_OUT_OF_MEMORY; return 0; } } else { ctorcif = 0; } #else /* Use the marshalling function pointer as the cif if no libffi */ cif = fnInfo.marshal; ctorcif = ctorfnInfo.marshal; #endif /* Generate the coder stub for marshalling the call */ if(!isConstructor) { /* We only need the method entry point */ if(!ILCoderSetupExtern(coder, &start, method, fnInfo.func, cif, (pinv == 0))) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_OUT_OF_MEMORY; return 0; } while((result = ILCoderFinish(coder)) != IL_CODER_END_OK) { /* Do we need a coder restart due to cache overflow? */ if(result != IL_CODER_END_RESTART) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_OUT_OF_MEMORY; return 0; } if(!ILCoderSetupExtern(coder, &start, method, fnInfo.func, cif, (pinv == 0))) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_OUT_OF_MEMORY; return 0; } } } else { /* We need both the method and constructor entry points */ if(!ILCoderSetupExternCtor(coder, &start, method, fnInfo.func, cif, ctorfnInfo.func, ctorcif, (pinv == 0))) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_OUT_OF_MEMORY; return 0; } while((result = ILCoderFinish(coder)) != IL_CODER_END_OK) { /* Do we need a coder restart due to cache overflow? */ if(result != IL_CODER_END_RESTART) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_OUT_OF_MEMORY; return 0; } if(!ILCoderSetupExternCtor(coder, &start, method, fnInfo.func, cif, ctorfnInfo.func, ctorcif, (pinv == 0))) { METADATA_UNLOCK(thread); *errorCode = IL_CONVERT_OUT_OF_MEMORY; return 0; } } } } /* The method is converted now */ /* Run the needed cctors and unlock the metadata too */ ILCoderRunCCtors(coder, start); *errorCode = IL_CONVERT_OK; return start; }