Exemple #1
0
/*
 * 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;
}