bool MonoMethod::hasAttribute(MonoClass* monoClass) const { // TODO - Consider caching custom attributes or just initializing them all at load MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_method(mMethod); if (attrInfo == nullptr) return false; bool hasAttr = mono_custom_attrs_has_attr(attrInfo, monoClass->_getInternalClass()) != 0; mono_custom_attrs_free(attrInfo); return hasAttr; }
MonoObject* MonoMethod::getAttribute(MonoClass* monoClass) const { // TODO - Consider caching custom attributes or just initializing them all at load MonoCustomAttrInfo* attrInfo = mono_custom_attrs_from_method(mMethod); if (attrInfo == nullptr) return nullptr; MonoObject* foundAttr = mono_custom_attrs_get_attr(attrInfo, monoClass->_getInternalClass()); mono_custom_attrs_free(attrInfo); return foundAttr; }
void GDMonoMethod::fetch_attributes() { ERR_FAIL_COND(attributes != NULL); attributes = mono_custom_attrs_from_method(mono_method); attrs_fetched = true; }
static void add_types_from_method (MonoMethod *method) { const MonoOpcode *opcode; MonoMethodHeader *header; const unsigned char *ip, *il_code_end; gpointer val = NULL, oldkey = NULL; int i, n; guint32 token; MonoClass *klass; MonoClassField *field; MonoCustomAttrInfo* cattrs; MonoType** locals; gpointer exc_iter; MonoExceptionClause clause; if (g_hash_table_lookup_extended (method_table, method, &oldkey, &val)) return; g_hash_table_insert (method_table, method, NULL); g_assert (method->klass); if (verbose > 1) g_print ("#processing method: %s\n", mono_method_full_name (method, TRUE)); mono_class_init (method->klass); cattrs = mono_custom_attrs_from_method (method); handle_cattrs (cattrs); add_type (method->klass); add_types_from_signature (mono_method_signature (method)); for (i = 0; i < mono_method_signature (method)->param_count + 1; ++i) { cattrs = mono_custom_attrs_from_param (method, i); handle_cattrs (cattrs); } if (method->flags & METHOD_ATTRIBUTE_VIRTUAL) virtual_methods = g_list_prepend (virtual_methods, method); /* if no IL code to parse, return */ if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) return; if (method->flags & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) return; header = mono_method_get_header (method); locals = mono_method_header_get_locals (header, &n, NULL); for (i = 0; i < n; ++i) { klass = mono_class_from_mono_type (locals [i]); add_type (klass); } for (exc_iter = NULL; mono_method_header_get_clauses (header, method, &exc_iter, &clause);) { if (clause.flags == MONO_EXCEPTION_CLAUSE_NONE) add_type (clause.data.catch_class); } ip = mono_method_header_get_code (header, &n, NULL); il_code_end = ip + n; while (ip < il_code_end) { if (verbose > 2) g_print ("#%s", mono_disasm_code_one (NULL, method, ip, NULL)); if (*ip == 0xfe) { ++ip; i = *ip + 256; } else { i = *ip; } opcode = &mono_opcodes [i]; switch (opcode->argument) { case MonoInlineNone: ip++; break; case MonoInlineType: token = read32 (ip + 1); add_type (mono_class_get (method->klass->image, token)); ip += 5; break; case MonoInlineField: { token = read32 (ip + 1); field = mono_field_from_token (method->klass->image, token, &klass, NULL); add_field (field); add_type (klass); ip += 5; break; } case MonoInlineTok: case MonoInlineSig: /* FIXME */ case MonoInlineString: case MonoShortInlineR: case MonoInlineBrTarget: case MonoInlineI: ip += 5; break; case MonoInlineVar: ip += 3; break; case MonoShortInlineVar: case MonoShortInlineI: case MonoShortInlineBrTarget: ip += 2; break; case MonoInlineSwitch: ++ip; n = read32 (ip); ip += 4; ip += 4 * n; break; case MonoInlineI8: case MonoInlineR: ip += 9; break; case MonoInlineMethod: { MonoMethod *cm = mono_get_method (method->klass->image, read32 (ip + 1), NULL); add_type (cm->klass); add_types_from_method (cm); } ip += 5; break; default: g_assert_not_reached (); } } }