il2cpp-api-debugger.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. #if defined(RUNTIME_IL2CPP) && !defined(IL2CPP_MONO_DEBUGGER_DISABLED)
  2. // This file implements an extension to the IL2CPP embedding API that the debugger code requires.
  3. // It should not include any Mono headers.
  4. #include "il2cpp-config.h"
  5. #include "il2cpp-class-internals.h"
  6. #include "il2cpp-mono-api.h"
  7. #include "il2cpp-api-debugger.h"
  8. #include "gc/GarbageCollector.h"
  9. #include "gc/WriteBarrier.h"
  10. #include "metadata/CustomAttributeDataReader.h"
  11. #include "metadata/FieldLayout.h"
  12. #include "metadata/GenericMetadata.h"
  13. #include "vm/Array.h"
  14. #include "vm/Assembly.h"
  15. #include "vm/AssemblyName.h"
  16. #include "vm/Class.h"
  17. #include "vm/ClassInlines.h"
  18. #include "vm/Field.h"
  19. #include "vm/GenericClass.h"
  20. #include "vm/GenericContainer.h"
  21. #include "vm/GlobalMetadata.h"
  22. #include "vm/Image.h"
  23. #include "vm/MetadataCache.h"
  24. #include "vm/Object.h"
  25. #include "vm/Property.h"
  26. #include "vm/Reflection.h"
  27. #include "vm-utils/Debugger.h"
  28. #include <algorithm>
  29. struct Il2CppMonoError
  30. {
  31. unsigned short error_code;
  32. unsigned short flags;
  33. void *hidden_1[12];
  34. };
  35. static void error_init(MonoError* error)
  36. {
  37. auto il2CppError = (Il2CppMonoError*)error;
  38. il2CppError->error_code = 0;
  39. il2CppError->flags = 0;
  40. }
  41. extern "C" {
  42. void* il2cpp_domain_get_agent_info(MonoAppDomain* domain)
  43. {
  44. return ((Il2CppDomain*)domain)->agent_info;
  45. }
  46. void il2cpp_domain_set_agent_info(MonoAppDomain* domain, void* agentInfo)
  47. {
  48. il2cpp::gc::WriteBarrier::GenericStore(&((Il2CppDomain*)domain)->agent_info, agentInfo);
  49. }
  50. const char* il2cpp_domain_get_friendly_name(MonoAppDomain* domain)
  51. {
  52. return ((Il2CppDomain*)domain)->friendly_name;
  53. }
  54. void il2cpp_start_debugger_thread()
  55. {
  56. #if IL2CPP_MONO_DEBUGGER
  57. il2cpp::utils::Debugger::StartDebuggerThread();
  58. #endif
  59. }
  60. const char* il2cpp_domain_get_name(MonoDomain* domain)
  61. {
  62. return ((Il2CppDomain*)domain)->friendly_name;
  63. }
  64. Il2CppSequencePoint* il2cpp_get_method_sequence_points(MonoMethod* method, void* *iter)
  65. {
  66. #if IL2CPP_MONO_DEBUGGER
  67. if (method == NULL)
  68. return il2cpp::utils::Debugger::GetAllSequencePoints(iter);
  69. else
  70. return (Il2CppSequencePoint*)il2cpp::utils::Debugger::GetSequencePoints((const MethodInfo*)method, iter);
  71. #else
  72. return NULL;
  73. #endif
  74. }
  75. Il2CppCatchPoint* il2cpp_get_method_catch_points(MonoMethod* method, void* *iter)
  76. {
  77. #if IL2CPP_MONO_DEBUGGER
  78. return (Il2CppCatchPoint*)il2cpp::utils::Debugger::GetCatchPoints((const MethodInfo*)method, iter);
  79. #else
  80. return NULL;
  81. #endif
  82. }
  83. Il2CppSequencePoint* il2cpp_get_seq_point_from_catch_point(Il2CppCatchPoint *cp)
  84. {
  85. #if IL2CPP_MONO_DEBUGGER
  86. return (Il2CppSequencePoint*)il2cpp::utils::Debugger::GetSequencePoint(NULL, cp);
  87. #else
  88. return NULL;
  89. #endif
  90. }
  91. int32_t il2cpp_mono_methods_match(MonoMethod* left, MonoMethod* right)
  92. {
  93. MethodInfo* leftMethod = (MethodInfo*)left;
  94. MethodInfo* rightMethod = (MethodInfo*)right;
  95. if (rightMethod == leftMethod)
  96. return 1;
  97. if (rightMethod == NULL || leftMethod == NULL)
  98. return 0;
  99. if (leftMethod->methodMetadataHandle == rightMethod->methodMetadataHandle)
  100. return 1;
  101. return 0;
  102. }
  103. MonoClass* il2cpp_defaults_object_class()
  104. {
  105. return (MonoClass*)il2cpp_defaults.object_class;
  106. }
  107. const char* il2cpp_image_name(MonoImage *monoImage)
  108. {
  109. Il2CppImage *image = (Il2CppImage*)monoImage;
  110. return image->name;
  111. }
  112. uint8_t* il2cpp_field_get_address(MonoObject *obj, MonoClassField *monoField)
  113. {
  114. FieldInfo *field = (FieldInfo*)monoField;
  115. return (uint8_t*)obj + field->offset;
  116. }
  117. MonoClass* il2cpp_defaults_exception_class()
  118. {
  119. return (MonoClass*)il2cpp_defaults.exception_class;
  120. }
  121. MonoImage* il2cpp_defaults_corlib_image()
  122. {
  123. return (MonoImage*)il2cpp_defaults.corlib;
  124. }
  125. MonoClass* il2cpp_defaults_runtimetype_class()
  126. {
  127. return (MonoClass*)il2cpp_defaults.runtimetype_class;
  128. }
  129. bool il2cpp_method_is_string_ctor(const MonoMethod * method)
  130. {
  131. MethodInfo* methodInfo = (MethodInfo*)method;
  132. return methodInfo->klass == il2cpp_defaults.string_class && !strcmp(methodInfo->name, ".ctor");
  133. }
  134. MonoClass* il2cpp_defaults_void_class()
  135. {
  136. return (MonoClass*)il2cpp_defaults.void_class;
  137. }
  138. MonoMethod* il2cpp_get_interface_method(MonoClass* klass, MonoClass* itf, int slot)
  139. {
  140. const VirtualInvokeData* data = il2cpp::vm::ClassInlines::GetInterfaceInvokeDataFromVTable((Il2CppClass*)klass, (Il2CppClass*)itf, slot);
  141. if (!data)
  142. return NULL;
  143. return (MonoMethod*)data->method;
  144. }
  145. struct TypeIterState
  146. {
  147. il2cpp::vm::AssemblyVector* assemblies;
  148. il2cpp::vm::AssemblyVector::iterator assembly;
  149. Il2CppImage* image;
  150. il2cpp::vm::TypeVector types;
  151. il2cpp::vm::TypeVector::iterator type;
  152. };
  153. MonoClass* il2cpp_iterate_loaded_classes(void* *iter)
  154. {
  155. if (!iter)
  156. return NULL;
  157. if (!*iter)
  158. {
  159. TypeIterState *state = new TypeIterState();
  160. state->assemblies = il2cpp::vm::Assembly::GetAllAssemblies();
  161. state->assembly = state->assemblies->begin();
  162. state->image = il2cpp::vm::Assembly::GetImage(*state->assembly);
  163. il2cpp::vm::Image::GetTypes(state->image, false, &state->types);
  164. state->type = state->types.begin();
  165. *iter = state;
  166. return (MonoClass*)*state->type;
  167. }
  168. TypeIterState *state = (TypeIterState*)*iter;
  169. state->type++;
  170. if (state->type == state->types.end())
  171. {
  172. state->assembly++;
  173. if (state->assembly == state->assemblies->end())
  174. {
  175. delete state;
  176. *iter = NULL;
  177. return NULL;
  178. }
  179. state->image = il2cpp::vm::Assembly::GetImage(*state->assembly);
  180. il2cpp::vm::Image::GetTypes(state->image, false, &state->types);
  181. state->type = state->types.begin();
  182. }
  183. return (MonoClass*)*state->type;
  184. }
  185. const char** il2cpp_get_source_files_for_type(MonoClass *klass, int *count)
  186. {
  187. #if IL2CPP_MONO_DEBUGGER
  188. return il2cpp::utils::Debugger::GetTypeSourceFiles((Il2CppClass*)klass, *count);
  189. #else
  190. return NULL;
  191. #endif
  192. }
  193. MonoMethod* il2cpp_method_get_generic_definition(MonoMethodInflated *imethod)
  194. {
  195. MethodInfo *method = (MethodInfo*)imethod;
  196. if (!method->is_inflated || method->is_generic)
  197. return NULL;
  198. return (MonoMethod*)((MethodInfo*)imethod)->genericMethod->methodDefinition;
  199. }
  200. MonoGenericInst* il2cpp_method_get_generic_class_inst(MonoMethodInflated *imethod)
  201. {
  202. MethodInfo *method = (MethodInfo*)imethod;
  203. if (!method->is_inflated || method->is_generic)
  204. return NULL;
  205. return (MonoGenericInst*)method->genericMethod->context.class_inst;
  206. }
  207. MonoClass* il2cpp_generic_class_get_container_class(MonoGenericClass *gclass)
  208. {
  209. return (MonoClass*)il2cpp::vm::GenericClass::GetTypeDefinition((Il2CppGenericClass*)gclass);
  210. }
  211. Il2CppSequencePoint* il2cpp_get_sequence_point(MonoImage* image, int id)
  212. {
  213. #if IL2CPP_MONO_DEBUGGER
  214. return il2cpp::utils::Debugger::GetSequencePoint((const Il2CppImage*)image, id);
  215. #else
  216. return NULL;
  217. #endif
  218. }
  219. char* il2cpp_assembly_get_full_name(MonoAssembly *assembly)
  220. {
  221. std::string s = il2cpp::vm::AssemblyName::AssemblyNameToString(((Il2CppAssembly*)assembly)->aname);
  222. return il2cpp::utils::StringUtils::StringDuplicate(s.c_str());
  223. }
  224. const MonoMethod* il2cpp_get_seq_point_method(Il2CppSequencePoint *seqPoint)
  225. {
  226. #if IL2CPP_MONO_DEBUGGER
  227. return (const MonoMethod*)il2cpp::utils::Debugger::GetSequencePointMethod(NULL, seqPoint);
  228. #else
  229. return NULL;
  230. #endif
  231. }
  232. const MonoClass* il2cpp_get_class_from_index(int index)
  233. {
  234. if (index < 0)
  235. return NULL;
  236. return (const MonoClass*)il2cpp::vm::MetadataCache::GetTypeInfoFromTypeIndex(NULL, index);
  237. }
  238. const MonoType* il2cpp_type_inflate(MonoType* type, const MonoGenericContext* context)
  239. {
  240. return (MonoType*)il2cpp::metadata::GenericMetadata::InflateIfNeeded((Il2CppType*)type, (const Il2CppGenericContext*)context, true);
  241. }
  242. void il2cpp_debugger_get_method_execution_context_and_header_info(const MonoMethod* method, uint32_t* executionContextInfoCount, const Il2CppMethodExecutionContextInfo **executionContextInfo, const Il2CppMethodHeaderInfo **headerInfo, const Il2CppMethodScope **scopes)
  243. {
  244. #if IL2CPP_MONO_DEBUGGER
  245. il2cpp::utils::Debugger::GetMethodExecutionContextInfo((const MethodInfo*)method, executionContextInfoCount, executionContextInfo, headerInfo, scopes);
  246. #endif
  247. }
  248. Il2CppThreadUnwindState* il2cpp_debugger_get_thread_context()
  249. {
  250. #if IL2CPP_MONO_DEBUGGER
  251. return il2cpp::utils::Debugger::GetThreadStatePointer();
  252. #else
  253. return NULL;
  254. #endif
  255. }
  256. Il2CppSequencePointSourceFile* il2cpp_debug_get_source_file(MonoImage* image, int index)
  257. {
  258. return ((Il2CppImage*)image)->codeGenModule->debuggerMetadata->sequencePointSourceFiles + index;
  259. }
  260. MonoMethod* il2cpp_get_generic_method_definition(MonoMethod* method)
  261. {
  262. return (MonoMethod*)((MethodInfo*)method)->genericMethod->methodDefinition;
  263. }
  264. bool il2cpp_class_is_initialized(MonoClass* klass)
  265. {
  266. return ((Il2CppClass*)klass)->initialized_and_no_error;
  267. }
  268. int il2cpp_generic_inst_get_argc(MonoGenericInst* inst)
  269. {
  270. return ((Il2CppGenericInst*)inst)->type_argc;
  271. }
  272. MonoType* il2cpp_generic_inst_get_argv(MonoGenericInst* inst, int index)
  273. {
  274. return (MonoType*)((Il2CppGenericInst*)inst)->type_argv[index];
  275. }
  276. MonoObject* il2cpp_assembly_get_object(MonoDomain* domain, MonoAssembly* assembly, MonoError* error)
  277. {
  278. return (MonoObject*)il2cpp::vm::Reflection::GetAssemblyObject((const Il2CppAssembly *)assembly);
  279. }
  280. const MonoType* il2cpp_get_type_from_index(int index)
  281. {
  282. return (const MonoType*)il2cpp::vm::MetadataCache::GetIl2CppTypeFromIndex(NULL, index);
  283. }
  284. void il2cpp_thread_info_safe_suspend_and_run(size_t /*Really MonoNativeThreadId*/ id, int32_t interrupt_kernel, MonoSuspendThreadCallback callback, void* user_data)
  285. {
  286. callback(NULL, user_data);
  287. }
  288. MonoGenericParam* il2cpp_generic_container_get_param(MonoGenericContainer *gc, int i)
  289. {
  290. return (MonoGenericParam*)il2cpp::vm::GenericContainer::GetGenericParameter((Il2CppMetadataGenericContainerHandle)gc, i);
  291. }
  292. void il2cpp_field_static_get_value_checked(MonoVTable* vt, MonoClassField* field, void* value, MonoError* error)
  293. {
  294. error_init(error);
  295. il2cpp::vm::Field::StaticGetValue((FieldInfo*)field, value);
  296. }
  297. void il2cpp_field_static_get_value_for_thread(MonoInternalThread* thread, MonoVTable* vt, MonoClassField* field, void* value, MonoError* error)
  298. {
  299. error_init(error);
  300. il2cpp::vm::Field::StaticGetValueForThread((FieldInfo*)field, value, (Il2CppInternalThread*)thread);
  301. }
  302. static bool IsFixedBufferAttribute(const MethodInfo* ctor)
  303. {
  304. const Il2CppClass* klass = ctor->klass;
  305. return strcmp(klass->name, "FixedBufferAttribute") == 0 &&
  306. strcmp(klass->namespaze, "System.Runtime.CompilerServices") == 0;
  307. }
  308. static bool IsInt32Type(Il2CppClass* klass)
  309. {
  310. return klass == il2cpp_defaults.int32_class;
  311. }
  312. struct FixedBufferAttributeConstructorVisitor : public il2cpp::metadata::CustomAttributeReaderVisitor
  313. {
  314. FixedBufferAttributeConstructorVisitor() : FixedArraySize(1) {}
  315. int32_t FixedArraySize;
  316. virtual void VisitCtor(const MethodInfo* ctor, il2cpp::metadata::CustomAttributeArgument args[], uint32_t argumentCount)
  317. {
  318. if (argumentCount == 2 && IsInt32Type(args[1].klass))
  319. FixedArraySize = *(int32_t*)&args[1].data;
  320. }
  321. };
  322. int32_t il2cpp_field_get_fixed_array_size(MonoClassField* field)
  323. {
  324. FieldInfo* il2cppField = (FieldInfo*)field;
  325. Il2CppMetadataCustomAttributeHandle attributeHandle = il2cpp::vm::MetadataCache::GetCustomAttributeTypeToken(il2cppField->parent->image, il2cppField->token);
  326. if (attributeHandle == NULL)
  327. return 1;
  328. auto reader = il2cpp::vm::GlobalMetadata::GetCustomAttributeDataReader(attributeHandle);
  329. Il2CppException* exc = NULL;
  330. il2cpp::metadata::CustomAttributeDataIterator iter = reader.GetDataIterator(IsFixedBufferAttribute);
  331. FixedBufferAttributeConstructorVisitor visitor;
  332. // Assume there is only one fixed buffer attribute - we will use the first one.
  333. if (reader.VisitCustomAttributeData(&iter, &visitor, &exc))
  334. {
  335. if (exc == NULL)
  336. return visitor.FixedArraySize;
  337. }
  338. return 1;
  339. }
  340. class DebuggerCustomAttributeVisitor : public il2cpp::metadata::CustomAttributeReaderVisitor
  341. {
  342. public:
  343. DebuggerCustomAttributeVisitor(Il2CppCustomAttributeDataList* attrs) : m_propertyIndexOffset(0), m_currentAttributeIndex(-1), m_attrs(attrs) {}
  344. virtual void MoveNext(const MethodInfo* ctor)
  345. {
  346. ++m_currentAttributeIndex;
  347. m_propertyIndexOffset = 0;
  348. IL2CPP_ASSERT(m_currentAttributeIndex < m_attrs->numberOfAttributes);
  349. m_attributeData = m_attrs->attributeData + m_currentAttributeIndex;
  350. }
  351. virtual void VisitArgumentSizes(uint32_t argumentCount, uint32_t fieldCount, uint32_t propertyCount)
  352. {
  353. m_attributeData->typedArgs = argumentCount == 0 ? nullptr : il2cpp::vm::Array::New(il2cpp_defaults.object_class, argumentCount);
  354. il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)&m_attributeData->typedArgs);
  355. int32_t numberOfNamedArguments = fieldCount + propertyCount;
  356. m_attributeData->namedArgs = numberOfNamedArguments == 0 ? nullptr : il2cpp::vm::Array::New(il2cpp_defaults.object_class, numberOfNamedArguments);
  357. il2cpp::gc::GarbageCollector::SetWriteBarrier((void**)&m_attributeData->namedArgs);
  358. m_propertyIndexOffset = fieldCount;
  359. m_attributeData->argInfo = numberOfNamedArguments == 0 ? nullptr : (Il2CppCattrNamedArg*)IL2CPP_CALLOC(numberOfNamedArguments, sizeof(Il2CppCattrNamedArg));
  360. }
  361. virtual void VisitArgument(const il2cpp::metadata::CustomAttributeArgument& argument, uint32_t index)
  362. {
  363. AddArgumentValueToArray(m_attributeData->typedArgs, argument, index);
  364. }
  365. virtual void VisitCtor(const MethodInfo* ctor, il2cpp::metadata::CustomAttributeArgument args[], uint32_t argumentCount)
  366. {
  367. m_attributeData->ctor = ctor;
  368. }
  369. virtual void VisitField(const il2cpp::metadata::CustomAttributeFieldArgument& field, uint32_t index)
  370. {
  371. AddArgumentValueToArray(m_attributeData->namedArgs, field.arg, index);
  372. m_attributeData->argInfo[index].type = field.field->type;
  373. m_attributeData->argInfo[index].field = field.field;
  374. }
  375. virtual void VisitProperty(const il2cpp::metadata::CustomAttributePropertyArgument& prop, uint32_t index)
  376. {
  377. AddArgumentValueToArray(m_attributeData->namedArgs, prop.arg, index + m_propertyIndexOffset);
  378. m_attributeData->argInfo[index + m_propertyIndexOffset].type = il2cpp::vm::Property::GetType(prop.prop);
  379. m_attributeData->argInfo[index + m_propertyIndexOffset].prop = prop.prop;
  380. }
  381. private:
  382. int32_t m_propertyIndexOffset;
  383. int32_t m_currentAttributeIndex;
  384. Il2CppCustomAttributeData* m_attributeData;
  385. Il2CppCustomAttributeDataList* m_attrs;
  386. static void AddArgumentValueToArray(Il2CppArray* array, const il2cpp::metadata::CustomAttributeArgument arg, uint32_t index)
  387. {
  388. Il2CppObject* argumentValue = il2cpp::vm::Class::IsValuetype(arg.klass) ? il2cpp::vm::Object::Box(arg.klass, (void*)&arg.data) : reinterpret_cast<Il2CppObject*>(arg.data.obj);
  389. il2cpp_array_setref(array, index, argumentValue);
  390. }
  391. };
  392. static void free_custom_attribute_data(Il2CppCustomAttributeData* attr)
  393. {
  394. if (attr->argInfo != NULL)
  395. IL2CPP_FREE(attr->argInfo);
  396. }
  397. static Il2CppCustomAttributeDataList EmptyDataList = { 0 };
  398. void il2cpp_free_custom_attribute_data_list(Il2CppCustomAttributeDataList* attrs)
  399. {
  400. if (attrs == &EmptyDataList)
  401. return;
  402. for (int32_t i = 0; i < attrs->numberOfAttributes; ++i)
  403. free_custom_attribute_data(attrs->attributeData + i);
  404. il2cpp::gc::GarbageCollector::FreeFixed(attrs);
  405. }
  406. const Il2CppCustomAttributeDataList* il2cpp_get_custom_attribute_data_list(MonoClass* attr_klass, MonoCustomAttrInfo* cinfo, MonoImage* image)
  407. {
  408. // Get a reader to access the attribute data.
  409. auto reader = il2cpp::vm::GlobalMetadata::GetCustomAttributeDataReader((Il2CppMetadataCustomAttributeHandle)cinfo);
  410. auto filter = [attr_klass](const MethodInfo* ctor)
  411. {
  412. return attr_klass == NULL || il2cpp::vm::Class::HasParent(ctor->klass, (Il2CppClass*)attr_klass);
  413. };
  414. uint32_t count = reader.GetCount(filter);
  415. if (count == 0)
  416. return &EmptyDataList;
  417. // Allocate a structure to hold the data for all attributes.
  418. Il2CppCustomAttributeDataList* attrs = (Il2CppCustomAttributeDataList*)il2cpp::gc::GarbageCollector::AllocateFixed(sizeof(Il2CppCustomAttributeDataList) + (count * sizeof(Il2CppCustomAttributeData)), NULL);
  419. attrs->numberOfAttributes = count;
  420. uint32_t createdAttributes = 0;
  421. il2cpp::metadata::CustomAttributeDataIterator iter = reader.GetDataIterator(filter);
  422. Il2CppException* exc = NULL;
  423. DebuggerCustomAttributeVisitor visitor(attrs);
  424. while (reader.VisitCustomAttributeData(&iter, &visitor, &exc))
  425. {
  426. createdAttributes++;
  427. }
  428. // If an error occurred, we don't have a great way to communicate what it is. Just return NULL and let the client handle
  429. // it in a general way.
  430. if (exc != NULL)
  431. {
  432. // Reset the number of created attributes, so we only free that many
  433. attrs->numberOfAttributes = createdAttributes;
  434. il2cpp_free_custom_attribute_data_list(attrs);
  435. return NULL;
  436. }
  437. return attrs;
  438. }
  439. MonoType* il2cpp_class_get_byval_arg(MonoClass* klass)
  440. {
  441. return (MonoType*)&((Il2CppClass*)klass)->byval_arg;
  442. }
  443. }
  444. #endif // RUNTIME_IL2CPP