DebugService.cs 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using ILRuntime.CLR.Method;
  8. using ILRuntime.Runtime.Intepreter;
  9. using ILRuntime.Runtime.Stack;
  10. using ILRuntime.CLR.Utils;
  11. using ILRuntime.Runtime.Intepreter.RegisterVM;
  12. namespace ILRuntime.Runtime.Debugger
  13. {
  14. public class DebugService
  15. {
  16. BreakPointContext curBreakpoint;
  17. DebuggerServer server;
  18. Runtime.Enviorment.AppDomain domain;
  19. Dictionary<int, LinkedList<BreakpointInfo>> activeBreakpoints = new Dictionary<int, LinkedList<BreakpointInfo>>();
  20. Dictionary<int, BreakpointInfo> breakpointMapping = new Dictionary<int, BreakpointInfo>();
  21. Queue<KeyValuePair<int, VariableReference>> pendingReferences = new Queue<KeyValuePair<int, VariableReference>>();
  22. Queue<KeyValuePair<int, VariableReference>> pendingEnuming = new Queue<KeyValuePair<int, VariableReference>>();
  23. Queue<KeyValuePair<int, KeyValuePair<VariableReference, VariableReference>>> pendingIndexing = new Queue<KeyValuePair<int, KeyValuePair<VariableReference, VariableReference>>>();
  24. AutoResetEvent evt = new AutoResetEvent(false);
  25. public Action<string> OnBreakPoint;
  26. public Action<string> OnILRuntimeException;
  27. public Enviorment.AppDomain AppDomain { get { return domain; } }
  28. public AutoResetEvent BlockEvent { get { return evt; } }
  29. public bool IsDebuggerAttached
  30. {
  31. get
  32. {
  33. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  34. return (server != null && server.IsAttached);
  35. #else
  36. return false;
  37. #endif
  38. }
  39. }
  40. public DebugService(Runtime.Enviorment.AppDomain domain)
  41. {
  42. this.domain = domain;
  43. }
  44. /// <summary>
  45. /// Start Debugger Server
  46. /// </summary>
  47. /// <param name="port">Port to listen on</param>
  48. public void StartDebugService(int port)
  49. {
  50. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  51. server = new Debugger.DebuggerServer(this);
  52. server.Port = port;
  53. server.Start();
  54. #endif
  55. }
  56. /// <summary>
  57. /// Stop Debugger Server
  58. /// </summary>
  59. public void StopDebugService()
  60. {
  61. #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
  62. if (server != null)
  63. server.Stop();
  64. server = null;
  65. #endif
  66. }
  67. /// <summary>
  68. /// 中断运行
  69. /// </summary>
  70. /// <param name="intpreter"></param>
  71. /// <param name="ex"></param>
  72. /// <returns>如果挂的有调试器则返回true</returns>
  73. internal bool Break(ILIntepreter intpreter, Exception ex = null)
  74. {
  75. BreakPointContext ctx = new BreakPointContext();
  76. ctx.Interpreter = intpreter;
  77. ctx.Exception = ex;
  78. curBreakpoint = ctx;
  79. if (OnBreakPoint != null)
  80. {
  81. OnBreakPoint(ctx.DumpContext());
  82. return true;
  83. }
  84. return false;
  85. }
  86. string GetInstructionDocument(Mono.Cecil.Cil.Instruction ins, Mono.Cecil.MethodDefinition md)
  87. {
  88. if (ins != null)
  89. {
  90. var seq = FindSequencePoint(ins, md.DebugInformation.GetSequencePointMapping());
  91. if (seq != null)
  92. {
  93. string path = seq.Document.Url.Replace("\\", "/");
  94. return string.Format("(at {0}:{1})", path, seq.StartLine);
  95. }
  96. }
  97. return null;
  98. }
  99. public string GetStackTrace(ILIntepreter intepreper)
  100. {
  101. StringBuilder sb = new StringBuilder();
  102. ILRuntime.CLR.Method.ILMethod m;
  103. StackFrame[] frames = intepreper.Stack.Frames.ToArray();
  104. Mono.Cecil.Cil.Instruction ins = null;
  105. RegisterVMSymbol vmSymbol;
  106. if (frames[0].Address != null)
  107. {
  108. if (frames[0].IsRegister)
  109. {
  110. frames[0].Method.RegisterVMSymbols.TryGetValue(frames[0].Address.Value, out vmSymbol);
  111. ins = vmSymbol.Instruction;
  112. sb.AppendLine(string.Format("{0}(JIT_{1:0000}:{2})", ins, frames[0].Address.Value, frames[0].Method.BodyRegister[frames[0].Address.Value]));
  113. }
  114. else
  115. {
  116. ins = frames[0].Method.Definition.Body.Instructions[frames[0].Address.Value];
  117. sb.AppendLine(ins.ToString());
  118. }
  119. }
  120. for (int i = 0; i < frames.Length; i++)
  121. {
  122. var f = frames[i];
  123. m = f.Method;
  124. string document = "";
  125. if (f.IsRegister)
  126. {
  127. if (f.Address != null)
  128. {
  129. if (f.Method.RegisterVMSymbols.TryGetValue(f.Address.Value, out vmSymbol))
  130. {
  131. RegisterVMSymbolLink link = null;
  132. do
  133. {
  134. if (link != null)
  135. vmSymbol = link.Value;
  136. ins = vmSymbol.Instruction;
  137. var md = vmSymbol.Method.Definition;
  138. document = GetInstructionDocument(ins, md);
  139. sb.AppendFormat("at {0} {1}\r\n", vmSymbol.Method, document);
  140. link = vmSymbol.ParentSymbol;
  141. }
  142. while (link != null);
  143. }
  144. else
  145. sb.AppendFormat("at {0} {1}\r\n", m, document);
  146. }
  147. else
  148. sb.AppendFormat("at {0} {1}\r\n", m, document);
  149. }
  150. else
  151. {
  152. if (f.Address != null)
  153. {
  154. ins = m.Definition.Body.Instructions[f.Address.Value];
  155. var md = m.Definition;
  156. document = GetInstructionDocument(ins, md);
  157. }
  158. sb.AppendFormat("at {0} {1}\r\n", m, document);
  159. }
  160. }
  161. return sb.ToString();
  162. }
  163. public unsafe string GetThisInfo(ILIntepreter intepreter)
  164. {
  165. var topFrame = intepreter.Stack.Frames.Peek();
  166. var arg = Minus(topFrame.LocalVarPointer, topFrame.Method.ParameterCount);
  167. if (topFrame.Method.HasThis)
  168. arg--;
  169. if (arg->ObjectType == ObjectTypes.StackObjectReference)
  170. {
  171. var addr = *(long*)&arg->Value;
  172. arg = (StackObject*)addr;
  173. }
  174. ILTypeInstance instance = arg->ObjectType != ObjectTypes.Null ? intepreter.Stack.ManagedStack[arg->Value] as ILTypeInstance : null;
  175. if (instance == null)
  176. return "null";
  177. var fields = instance.Type.TypeDefinition.Fields;
  178. int idx = 0;
  179. StringBuilder sb = new StringBuilder();
  180. for (int i = 0; i < fields.Count; i++)
  181. {
  182. try
  183. {
  184. var f = fields[i];
  185. if (f.IsStatic)
  186. continue;
  187. var field = instance.Fields[idx];
  188. var v = StackObject.ToObject(&field, intepreter.AppDomain, instance.ManagedObjects);
  189. if (v == null)
  190. v = "null";
  191. string name = f.Name;
  192. sb.AppendFormat("{0} {1} = {2}", f.FieldType.Name, name, v);
  193. if ((idx % 3 == 0 && idx != 0) || idx == instance.Fields.Length - 1)
  194. sb.AppendLine();
  195. else
  196. sb.Append(", ");
  197. idx++;
  198. }
  199. catch
  200. {
  201. }
  202. }
  203. return sb.ToString();
  204. }
  205. public unsafe string GetLocalVariableInfo(ILIntepreter intepreter)
  206. {
  207. StackFrame topFrame = intepreter.Stack.Frames.Peek();
  208. var m = topFrame.Method;
  209. StringBuilder sb = new StringBuilder();
  210. for (int i = 0; i < m.LocalVariableCount; i++)
  211. {
  212. try
  213. {
  214. var lv = m.Definition.Body.Variables[i];
  215. var val = Add(topFrame.LocalVarPointer, i);
  216. var v = StackObject.ToObject(val, intepreter.AppDomain, intepreter.Stack.ManagedStack);
  217. if (v == null)
  218. v = "null";
  219. string vName = null;
  220. m.Definition.DebugInformation.TryGetName(lv, out vName);
  221. string name = string.IsNullOrEmpty(vName) ? "v" + lv.Index : vName;
  222. sb.AppendFormat("{0} {1} = {2}", lv.VariableType.Name, name, v);
  223. if ((i % 3 == 0 && i != 0) || i == m.LocalVariableCount - 1)
  224. sb.AppendLine();
  225. else
  226. sb.Append(", ");
  227. }
  228. catch
  229. {
  230. }
  231. }
  232. return sb.ToString();
  233. }
  234. internal static Mono.Cecil.Cil.SequencePoint FindSequencePoint(Mono.Cecil.Cil.Instruction ins, IDictionary<Mono.Cecil.Cil.Instruction, Mono.Cecil.Cil.SequencePoint> seqMapping)
  235. {
  236. Mono.Cecil.Cil.Instruction cur = ins;
  237. Mono.Cecil.Cil.SequencePoint sp;
  238. while (!seqMapping.TryGetValue(cur, out sp) && cur.Previous != null)
  239. cur = cur.Previous;
  240. return sp;
  241. }
  242. unsafe StackObject* Add(StackObject* a, int b)
  243. {
  244. return (StackObject*)((long)a + sizeof(StackObject) * b);
  245. }
  246. unsafe StackObject* Minus(StackObject* a, int b)
  247. {
  248. return (StackObject*)((long)a - sizeof(StackObject) * b);
  249. }
  250. internal void NotifyModuleLoaded(string moduleName)
  251. {
  252. if (server != null && server.IsAttached)
  253. server.NotifyModuleLoaded(moduleName);
  254. }
  255. internal void SetBreakPoint(int methodHash, int bpHash, int startLine)
  256. {
  257. lock (activeBreakpoints)
  258. {
  259. LinkedList<BreakpointInfo> lst;
  260. if(!activeBreakpoints.TryGetValue(methodHash, out lst))
  261. {
  262. lst = new LinkedList<Debugger.BreakpointInfo>();
  263. activeBreakpoints[methodHash] = lst;
  264. }
  265. BreakpointInfo bpInfo = new BreakpointInfo();
  266. bpInfo.BreakpointHashCode = bpHash;
  267. bpInfo.MethodHashCode = methodHash;
  268. bpInfo.StartLine = startLine;
  269. lst.AddLast(bpInfo);
  270. breakpointMapping[bpHash] = bpInfo;
  271. }
  272. }
  273. internal void DeleteBreakpoint(int bpHash)
  274. {
  275. lock (activeBreakpoints)
  276. {
  277. BreakpointInfo bpInfo;
  278. if (breakpointMapping.TryGetValue(bpHash, out bpInfo))
  279. {
  280. LinkedList<BreakpointInfo> lst;
  281. if(activeBreakpoints.TryGetValue(bpInfo.MethodHashCode, out lst))
  282. {
  283. lst.Remove(bpInfo);
  284. }
  285. breakpointMapping.Remove(bpHash);
  286. }
  287. }
  288. }
  289. internal void ExecuteThread(int threadHash)
  290. {
  291. lock (AppDomain.FreeIntepreters)
  292. {
  293. foreach(var i in AppDomain.Intepreters)
  294. {
  295. //We should resume all threads on execute
  296. i.Value.ClearDebugState();
  297. i.Value.Resume();
  298. }
  299. }
  300. }
  301. internal unsafe void StepThread(int threadHash, StepTypes type)
  302. {
  303. lock (AppDomain.FreeIntepreters)
  304. {
  305. ILIntepreter intp;
  306. if(AppDomain.Intepreters.TryGetValue(threadHash, out intp))
  307. {
  308. intp.ClearDebugState();
  309. intp.CurrentStepType = type;
  310. intp.LastStepInstructionIndex = intp.Stack.Frames.Count > 0 ? intp.Stack.Frames.Peek().Address.Value : 0;
  311. intp.LastStepFrameBase = intp.Stack.Frames.Count > 0 ? ResolveCurrentFrameBasePointer(intp) : (StackObject*)0;
  312. intp.Resume();
  313. }
  314. }
  315. }
  316. unsafe StackObject* ResolveCurrentFrameBasePointer(ILIntepreter intp,ILMethod method = null, int ip = -1)
  317. {
  318. StackObject* basePointer = intp.Stack.Frames.Peek().BasePointer;
  319. if (method == null)
  320. method = intp.Stack.Frames.Peek().Method;
  321. if (ip < 0)
  322. ip = intp.Stack.Frames.Peek().Address.Value;
  323. if (intp.Stack.Frames.Peek().IsRegister)
  324. {
  325. basePointer = intp.Stack.Frames.Peek().LocalVarPointer;
  326. RegisterVMSymbol vmSymbol;
  327. if (method.RegisterVMSymbols.TryGetValue(ip, out vmSymbol))
  328. {
  329. var paramCnt = method.HasThis ? method.ParameterCount + 1 : method.ParameterCount;
  330. var frameBase = basePointer - paramCnt;
  331. int registerCnt = vmSymbol.Method.StackRegisterCount + vmSymbol.Method.LocalVariableCount;
  332. if (method.HasThis)
  333. frameBase--;
  334. var curParamCnt = vmSymbol.Method.HasThis ? vmSymbol.Method.ParameterCount + 1 : vmSymbol.Method.ParameterCount;
  335. if (vmSymbol.ParentSymbol != null)
  336. {
  337. basePointer = frameBase + vmSymbol.ParentSymbol.BaseRegisterIndex;
  338. }
  339. else
  340. {
  341. registerCnt -= vmSymbol.Method.StackRegisterCount;
  342. basePointer = frameBase ;
  343. }
  344. basePointer = basePointer + curParamCnt + registerCnt;
  345. }
  346. }
  347. return basePointer;
  348. }
  349. unsafe internal void CheckShouldBreak(ILMethod method, ILIntepreter intp, int ip)
  350. {
  351. if (server != null && server.IsAttached)
  352. {
  353. RegisterVMSymbol vmSymbol;
  354. Mono.Cecil.Cil.Instruction ins = null;
  355. Mono.Cecil.MethodDefinition md = null;
  356. ILMethod m = method;
  357. if (intp.Stack.Frames.Peek().IsRegister)
  358. {
  359. if (!method.IsRegisterVMSymbolFixed)
  360. method.FixRegisterVMSymbol();
  361. if(method.RegisterVMSymbols.TryGetValue(ip, out vmSymbol))
  362. {
  363. ins = vmSymbol.Instruction;
  364. m = vmSymbol.Method;
  365. md = vmSymbol.Method.Definition;
  366. }
  367. }
  368. else
  369. {
  370. md = method.Definition;
  371. ins = md.Body.Instructions[ip];
  372. }
  373. StackObject* basePointer = ResolveCurrentFrameBasePointer(intp, method, ip);
  374. int methodHash = m.GetHashCode();
  375. BreakpointInfo[] lst = null;
  376. lock (activeBreakpoints)
  377. {
  378. LinkedList<BreakpointInfo> bps;
  379. if (activeBreakpoints.TryGetValue(methodHash, out bps))
  380. lst = bps.ToArray();
  381. }
  382. if (ins == null)
  383. return;
  384. if (lst != null)
  385. {
  386. var sp = md.DebugInformation.GetSequencePoint(ins);
  387. if (sp != null)
  388. {
  389. foreach (var i in lst)
  390. {
  391. if ((i.StartLine + 1) == sp.StartLine)
  392. {
  393. DoBreak(intp, i.BreakpointHashCode, false);
  394. return;
  395. }
  396. }
  397. }
  398. }
  399. if (intp.CurrentStepType != StepTypes.None)
  400. {
  401. var sp = md.DebugInformation.GetSequencePoint(ins);
  402. if (sp != null && IsSequenceValid(sp))
  403. {
  404. switch (intp.CurrentStepType)
  405. {
  406. case StepTypes.Into:
  407. DoBreak(intp, 0, true);
  408. break;
  409. case StepTypes.Over:
  410. if (basePointer <= intp.LastStepFrameBase && ip != intp.LastStepInstructionIndex)
  411. {
  412. DoBreak(intp, 0, true);
  413. }
  414. break;
  415. case StepTypes.Out:
  416. {
  417. if (intp.Stack.Frames.Count > 0 && basePointer < intp.LastStepFrameBase)
  418. {
  419. DoBreak(intp, 0, true);
  420. }
  421. }
  422. break;
  423. }
  424. }
  425. }
  426. }
  427. }
  428. bool IsSequenceValid(Mono.Cecil.Cil.SequencePoint sp)
  429. {
  430. return sp.StartLine != sp.EndLine || sp.StartColumn != sp.EndColumn;
  431. }
  432. void DoBreak(ILIntepreter intp, int bpHash, bool isStep)
  433. {
  434. var arr = AppDomain.Intepreters.ToArray();
  435. KeyValuePair<int, StackFrameInfo[]>[] frames = new KeyValuePair<int, StackFrameInfo[]>[arr.Length];
  436. frames[0] = new KeyValuePair<int, StackFrameInfo[]>(intp.GetHashCode(), GetStackFrameInfo(intp));
  437. int idx = 1;
  438. foreach (var j in arr)
  439. {
  440. if (j.Value != intp)
  441. {
  442. j.Value.ShouldBreak = true;
  443. try
  444. {
  445. frames[idx++] = new KeyValuePair<int, Debugger.StackFrameInfo[]>(j.Value.GetHashCode(), GetStackFrameInfo(j.Value));
  446. }
  447. catch
  448. {
  449. frames[idx++] = new KeyValuePair<int, Debugger.StackFrameInfo[]>(j.Value.GetHashCode(), new StackFrameInfo[0]);
  450. }
  451. }
  452. }
  453. if (!isStep)
  454. server.SendSCBreakpointHit(intp.GetHashCode(), bpHash, frames);
  455. else
  456. server.SendSCStepComplete(intp.GetHashCode(), frames);
  457. //Breakpoint hit
  458. intp.Break();
  459. }
  460. unsafe void InitializeStackFrameInfo(ILIntepreter intp, StackFrame f, List<StackFrameInfo> frameInfos)
  461. {
  462. Mono.Cecil.Cil.Instruction ins = null;
  463. var m = f.Method;
  464. int argCnt = m.HasThis ? m.ParameterCount + 1 : m.ParameterCount;
  465. StackObject* frameBasePointer = Minus(f.LocalVarPointer, argCnt);
  466. if (f.Address != null)
  467. {
  468. if (f.IsRegister)
  469. {
  470. RegisterVMSymbol vmSymbol;
  471. if(m.RegisterVMSymbols.TryGetValue(f.Address.Value, out vmSymbol))
  472. {
  473. RegisterVMSymbolLink link = null;
  474. StackObject* basePointer;
  475. do
  476. {
  477. if (link != null)
  478. {
  479. vmSymbol = link.Value;
  480. }
  481. ins = vmSymbol.Instruction;
  482. m = vmSymbol.Method;
  483. if(vmSymbol.ParentSymbol!=null)
  484. {
  485. basePointer = Add(frameBasePointer, vmSymbol.ParentSymbol.BaseRegisterIndex);
  486. }
  487. else
  488. {
  489. basePointer = frameBasePointer;
  490. }
  491. var info = CreateStackFrameInfo(m, ins);
  492. AddStackFrameInfoVariables(intp, info, m, basePointer);
  493. frameInfos.Add(info);
  494. link = vmSymbol.ParentSymbol;
  495. }
  496. while (link != null);
  497. }
  498. else
  499. {
  500. var info = CreateStackFrameInfo(m, null);
  501. AddStackFrameInfoVariables(intp, info, m, frameBasePointer);
  502. frameInfos.Add(info);
  503. }
  504. }
  505. else
  506. {
  507. ins = m.Definition.Body.Instructions[f.Address.Value];
  508. var info = CreateStackFrameInfo(m, ins);
  509. AddStackFrameInfoVariables(intp, info, m, frameBasePointer);
  510. frameInfos.Add(info);
  511. }
  512. }
  513. else
  514. {
  515. var info = CreateStackFrameInfo(m, null);
  516. AddStackFrameInfoVariables(intp, info, m, frameBasePointer);
  517. frameInfos.Add(info);
  518. }
  519. }
  520. StackFrameInfo CreateStackFrameInfo(ILMethod m, Mono.Cecil.Cil.Instruction ins)
  521. {
  522. Mono.Cecil.MethodDefinition md = m.Definition;
  523. StackFrameInfo info = new StackFrameInfo();
  524. info.MethodName = m.ToString();
  525. if (ins != null)
  526. {
  527. var seq = FindSequencePoint(ins, md.DebugInformation.GetSequencePointMapping());
  528. if (seq != null)
  529. {
  530. info.DocumentName = seq.Document.Url;
  531. info.StartLine = seq.StartLine - 1;
  532. info.StartColumn = seq.StartColumn - 1;
  533. info.EndLine = seq.EndLine - 1;
  534. info.EndColumn = seq.EndColumn - 1;
  535. }
  536. }
  537. return info;
  538. }
  539. unsafe void AddStackFrameInfoVariables(ILIntepreter intp, StackFrameInfo info, ILMethod m, StackObject* basePointer)
  540. {
  541. int argumentCount = m.ParameterCount;
  542. if (m.HasThis)
  543. argumentCount++;
  544. info.LocalVariables = new VariableInfo[argumentCount + m.LocalVariableCount];
  545. for (int i = 0; i < argumentCount; i++)
  546. {
  547. int argIdx = m.HasThis ? i - 1 : i;
  548. var arg = basePointer;
  549. string name = null;
  550. object v = null;
  551. string typeName = null;
  552. var val = Add(arg, i);
  553. v = StackObject.ToObject(val, intp.AppDomain, intp.Stack.ManagedStack);
  554. if (argIdx >= 0)
  555. {
  556. var lv = m.Definition.Parameters[argIdx];
  557. name = string.IsNullOrEmpty(lv.Name) ? "arg" + lv.Index : lv.Name;
  558. typeName = lv.ParameterType.FullName;
  559. }
  560. else
  561. {
  562. name = "this";
  563. typeName = m.DeclearingType.FullName;
  564. }
  565. VariableInfo vinfo = VariableInfo.FromObject(v);
  566. vinfo.Address = (long)val;
  567. vinfo.Name = name;
  568. vinfo.TypeName = typeName;
  569. vinfo.Expandable = GetValueExpandable(val, intp.Stack.ManagedStack);
  570. info.LocalVariables[i] = vinfo;
  571. }
  572. for (int i = argumentCount; i < info.LocalVariables.Length; i++)
  573. {
  574. var locIdx = i - argumentCount;
  575. var lv = m.Definition.Body.Variables[locIdx];
  576. var val = Add(basePointer, argumentCount + locIdx);
  577. var v = StackObject.ToObject(val, intp.AppDomain, intp.Stack.ManagedStack);
  578. var type = intp.AppDomain.GetType(lv.VariableType, m.DeclearingType, m);
  579. string vName = null;
  580. m.Definition.DebugInformation.TryGetName(lv, out vName);
  581. string name = string.IsNullOrEmpty(vName) ? "v" + lv.Index : vName;
  582. VariableInfo vinfo = VariableInfo.FromObject(v);
  583. vinfo.Address = (long)val;
  584. vinfo.Name = name;
  585. vinfo.TypeName = lv.VariableType.FullName;
  586. vinfo.Expandable = GetValueExpandable(val, intp.Stack.ManagedStack);
  587. info.LocalVariables[i] = vinfo;
  588. }
  589. }
  590. unsafe StackFrameInfo[] GetStackFrameInfo(ILIntepreter intp)
  591. {
  592. StackFrame[] frames = intp.Stack.Frames.ToArray();
  593. List<StackFrameInfo> frameInfos = new List<StackFrameInfo>();
  594. for (int j = 0; j < frames.Length; j++)
  595. {
  596. InitializeStackFrameInfo(intp, frames[j], frameInfos);
  597. }
  598. return frameInfos.ToArray();
  599. }
  600. internal unsafe VariableInfo[] EnumChildren(int threadHashCode, VariableReference parent)
  601. {
  602. ILIntepreter intepreter;
  603. if (AppDomain.Intepreters.TryGetValue(threadHashCode, out intepreter))
  604. {
  605. #if DEBUG && !NO_PROFILER
  606. if (domain.IsNotUnityMainThread())
  607. {
  608. lock (pendingEnuming)
  609. {
  610. pendingEnuming.Enqueue(new KeyValuePair<int, VariableReference>(threadHashCode, parent));
  611. }
  612. return null;
  613. }
  614. #endif
  615. object obj;
  616. var info = ResolveVariable(threadHashCode, parent, out obj);
  617. if (obj != null)
  618. {
  619. if(obj is Array)
  620. {
  621. return EnumArray((Array)obj, intepreter);
  622. }
  623. else if(obj is IList)
  624. {
  625. return EnumList((IList)obj, intepreter);
  626. }
  627. else if(obj is IDictionary)
  628. {
  629. return EnumDictionary((IDictionary)obj, intepreter);
  630. }
  631. else if(obj is ILTypeInstance)
  632. {
  633. return EnumILTypeInstance((ILTypeInstance)obj, intepreter);
  634. }
  635. else if(obj is ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType)
  636. {
  637. return EnumILTypeInstance(((Enviorment.CrossBindingAdaptorType)obj).ILInstance, intepreter);
  638. }
  639. else
  640. {
  641. return EnumCLRObject(obj, intepreter);
  642. }
  643. }
  644. else
  645. return new VariableInfo[] { VariableInfo.NullReferenceExeption };
  646. }
  647. else
  648. return new VariableInfo[] { VariableInfo.NullReferenceExeption };
  649. }
  650. VariableInfo[] EnumArray(Array arr, ILIntepreter intepreter)
  651. {
  652. VariableInfo[] res = new VariableInfo[arr.Length];
  653. for(int i = 0; i < arr.Length; i++)
  654. {
  655. try
  656. {
  657. var obj = arr.GetValue(i);
  658. VariableInfo info = VariableInfo.FromObject(obj, true);
  659. info.Name = string.Format("[{0}]", i);
  660. info.Offset = i;
  661. info.Type = VariableTypes.IndexAccess;
  662. res[i] = info;
  663. }
  664. catch(Exception ex)
  665. {
  666. var info = VariableInfo.GetException(ex);
  667. info.Name = string.Format("[{0}]", i);
  668. res[i] = info;
  669. }
  670. }
  671. return res;
  672. }
  673. VariableInfo[] EnumList(IList lst, ILIntepreter intepreter)
  674. {
  675. VariableInfo[] res = new VariableInfo[lst.Count];
  676. for (int i = 0; i < lst.Count; i++)
  677. {
  678. try
  679. {
  680. var obj = lst[i];
  681. VariableInfo info = VariableInfo.FromObject(obj, true);
  682. info.Name = string.Format("[{0}]", i);
  683. info.Offset = i;
  684. info.Type = VariableTypes.IndexAccess;
  685. res[i] = info;
  686. }
  687. catch (Exception ex)
  688. {
  689. var info = VariableInfo.GetException(ex);
  690. info.Name = string.Format("[{0}]", i);
  691. res[i] = info;
  692. }
  693. }
  694. return res;
  695. }
  696. VariableInfo[] EnumDictionary(IDictionary lst, ILIntepreter intepreter)
  697. {
  698. VariableInfo[] res = new VariableInfo[lst.Count];
  699. var keys = GetArray(lst.Keys);
  700. var values = GetArray(lst.Values);
  701. for (int i = 0; i < lst.Count; i++)
  702. {
  703. try
  704. {
  705. var obj = values[i];
  706. VariableInfo info = VariableInfo.FromObject(obj, true);
  707. info.Name = string.Format("[{0}]", i);
  708. info.Type = VariableTypes.IndexAccess;
  709. info.Offset = i;
  710. info.Value = string.Format("{0},{1}", SafeToString(keys[i]), SafeToString(values[i]));
  711. info.Expandable = true;
  712. res[i] = info;
  713. }
  714. catch (Exception ex)
  715. {
  716. var info = VariableInfo.GetException(ex);
  717. info.Name = string.Format("[{0}]", i);
  718. res[i] = info;
  719. }
  720. }
  721. return res;
  722. }
  723. string SafeToString(object obj)
  724. {
  725. if (obj != null)
  726. return obj.ToString();
  727. else
  728. return "null";
  729. }
  730. object[] GetArray(ICollection lst)
  731. {
  732. object[] res = new object[lst.Count];
  733. int idx = 0;
  734. foreach(var i in lst)
  735. {
  736. res[idx++] = i;
  737. }
  738. return res;
  739. }
  740. VariableInfo[] EnumILTypeInstance(ILTypeInstance obj, ILIntepreter intepreter)
  741. {
  742. return EnumObject(obj, obj.Type.ReflectionType);
  743. }
  744. VariableInfo[] EnumCLRObject(object obj, ILIntepreter intepreter)
  745. {
  746. return EnumObject(obj, obj.GetType());
  747. }
  748. VariableInfo[] EnumObject(object obj, Type t)
  749. {
  750. List<VariableInfo> lst = new List<VariableInfo>();
  751. foreach (var i in t.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance))
  752. {
  753. try
  754. {
  755. if (i.GetCustomAttributes(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false).Length > 0)
  756. continue;
  757. var val = i.GetValue(obj);
  758. VariableInfo info = VariableInfo.FromObject(val);
  759. info.Type = VariableTypes.FieldReference;
  760. info.TypeName = i.FieldType.FullName;
  761. info.Name = i.Name;
  762. info.Expandable = !i.FieldType.IsPrimitive && val != null;
  763. info.IsPrivate = i.IsPrivate;
  764. info.IsProtected = i.IsFamily;
  765. lst.Add(info);
  766. }
  767. catch (Exception ex)
  768. {
  769. var info = VariableInfo.GetException(ex);
  770. info.Name = i.Name;
  771. lst.Add(info);
  772. }
  773. }
  774. foreach (var i in t.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance))
  775. {
  776. try
  777. {
  778. if (i.GetIndexParameters().Length > 0)
  779. continue;
  780. if (i.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0)
  781. continue;
  782. var val = i.GetValue(obj, null);
  783. VariableInfo info = VariableInfo.FromObject(val);
  784. info.Type = VariableTypes.PropertyReference;
  785. info.TypeName = i.PropertyType.FullName;
  786. info.Name = i.Name;
  787. info.Expandable = !i.PropertyType.IsPrimitive && val != null;
  788. info.IsPrivate = i.GetGetMethod(true).IsPrivate;
  789. info.IsProtected = i.GetGetMethod(true).IsFamily;
  790. lst.Add(info);
  791. }
  792. catch (Exception ex)
  793. {
  794. var info = VariableInfo.GetException(ex);
  795. info.Name = i.Name;
  796. lst.Add(info);
  797. }
  798. }
  799. return lst.ToArray();
  800. }
  801. internal unsafe VariableInfo ResolveIndexAccess(int threadHashCode, VariableReference body, VariableReference idx, out object res)
  802. {
  803. ILIntepreter intepreter;
  804. res = null;
  805. if (AppDomain.Intepreters.TryGetValue(threadHashCode, out intepreter))
  806. {
  807. #if DEBUG && !NO_PROFILER
  808. if (domain.IsNotUnityMainThread())
  809. {
  810. lock (pendingIndexing)
  811. {
  812. pendingIndexing.Enqueue(new KeyValuePair<int, KeyValuePair<VariableReference, VariableReference>>(threadHashCode, new KeyValuePair<VariableReference, VariableReference>(body, idx)));
  813. }
  814. res = null;
  815. return new VariableInfo() { Type = VariableTypes.Pending };
  816. }
  817. #endif
  818. object obj;
  819. var info = ResolveVariable(threadHashCode, body, out obj);
  820. if (obj != null)
  821. {
  822. object idxObj;
  823. info = ResolveVariable(threadHashCode, idx, out idxObj);
  824. if(obj is Array)
  825. {
  826. res = ((Array)obj).GetValue((int)idxObj);
  827. info = VariableInfo.FromObject(res);
  828. info.Type = VariableTypes.IndexAccess;
  829. info.TypeName = obj.GetType().GetElementType().FullName;
  830. info.Expandable = res != null && !obj.GetType().GetElementType().IsPrimitive;
  831. return info;
  832. }
  833. else
  834. {
  835. if(obj is ILTypeInstance)
  836. {
  837. var m = ((ILTypeInstance)obj).Type.GetMethod("get_Item");
  838. if (m != null)
  839. {
  840. res = intepreter.AppDomain.Invoke(m, obj, idxObj);
  841. info = VariableInfo.FromObject(res);
  842. info.Type = VariableTypes.IndexAccess;
  843. info.TypeName = m.ReturnType.FullName;
  844. info.Expandable = res != null && !m.ReturnType.IsPrimitive;
  845. return info;
  846. }
  847. else
  848. return VariableInfo.NullReferenceExeption;
  849. }
  850. else
  851. {
  852. if(obj is ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType)
  853. {
  854. throw new NotImplementedException();
  855. }
  856. else
  857. {
  858. if(obj is IDictionary && idxObj is int)
  859. {
  860. IDictionary dic = (IDictionary)obj;
  861. var keys = GetArray(dic.Keys);
  862. if (keys[0].GetType() != typeof(int))
  863. {
  864. int index = (int)idxObj;
  865. var values = GetArray(dic.Values);
  866. var t = typeof(KeyValuePair<,>).MakeGenericType(keys[index].GetType(), values[index].GetType());
  867. var ctor = t.GetConstructor(new Type[] { keys[index].GetType(), values[index].GetType() });
  868. res = ctor.Invoke(new object[] { keys[index], values[index] });
  869. info = VariableInfo.FromObject(res);
  870. info.Type = VariableTypes.IndexAccess;
  871. info.Offset = index;
  872. info.TypeName = t.FullName;
  873. info.Expandable = true;
  874. return info;
  875. }
  876. }
  877. var pi = obj.GetType().GetProperty("Item");
  878. if (pi != null)
  879. {
  880. res = pi.GetValue(obj, new object[] { idxObj });
  881. info = VariableInfo.FromObject(res);
  882. info.Type = VariableTypes.IndexAccess;
  883. info.TypeName = pi.PropertyType.FullName;
  884. info.Expandable = res != null && !pi.PropertyType.IsPrimitive;
  885. return info;
  886. }
  887. else
  888. return VariableInfo.NullReferenceExeption;
  889. }
  890. }
  891. }
  892. }
  893. else
  894. return VariableInfo.NullReferenceExeption;
  895. }
  896. else
  897. return VariableInfo.NullReferenceExeption;
  898. }
  899. internal void ResolvePendingRequests()
  900. {
  901. lock (pendingReferences)
  902. {
  903. while (pendingReferences.Count > 0)
  904. {
  905. VariableInfo info;
  906. var r = pendingReferences.Dequeue();
  907. try
  908. {
  909. object res;
  910. info = ResolveVariable(r.Key, r.Value, out res);
  911. }
  912. catch (Exception ex)
  913. {
  914. info = VariableInfo.GetException(ex);
  915. }
  916. server.SendSCResolveVariableResult(info);
  917. }
  918. }
  919. lock (pendingEnuming)
  920. {
  921. while (pendingEnuming.Count > 0)
  922. {
  923. VariableInfo[] info;
  924. var r = pendingEnuming.Dequeue();
  925. try
  926. {
  927. info = EnumChildren(r.Key, r.Value);
  928. }
  929. catch (Exception ex)
  930. {
  931. info = new VariableInfo[] { VariableInfo.GetException(ex) };
  932. }
  933. server.SendSCEnumChildrenResult(info);
  934. }
  935. }
  936. lock (pendingIndexing)
  937. {
  938. while (pendingIndexing.Count > 0)
  939. {
  940. VariableInfo info;
  941. var r = pendingIndexing.Dequeue();
  942. try
  943. {
  944. object res;
  945. info = ResolveIndexAccess(r.Key, r.Value.Key, r.Value.Value, out res);
  946. }
  947. catch (Exception ex)
  948. {
  949. info = VariableInfo.GetException(ex);
  950. }
  951. server.SendSCResolveVariableResult(info);
  952. }
  953. }
  954. }
  955. internal unsafe VariableInfo ResolveVariable(int threadHashCode, VariableReference variable, out object res)
  956. {
  957. ILIntepreter intepreter;
  958. res = null;
  959. if (AppDomain.Intepreters.TryGetValue(threadHashCode, out intepreter))
  960. {
  961. if (variable != null)
  962. {
  963. #if DEBUG && !NO_PROFILER
  964. if (domain.IsNotUnityMainThread())
  965. {
  966. lock (pendingReferences)
  967. {
  968. pendingReferences.Enqueue(new KeyValuePair<int, VariableReference>(threadHashCode, variable));
  969. }
  970. res = null;
  971. return new VariableInfo() { Type = VariableTypes.Pending };
  972. }
  973. #endif
  974. switch (variable.Type)
  975. {
  976. case VariableTypes.Normal:
  977. {
  978. StackObject* ptr = (StackObject*)variable.Address;
  979. object obj = StackObject.ToObject(ptr, AppDomain, intepreter.Stack.ManagedStack);
  980. if (obj != null)
  981. {
  982. //return ResolveMember(obj, name, out res);
  983. res = obj;
  984. return null;
  985. }
  986. else
  987. {
  988. return VariableInfo.Null;
  989. }
  990. }
  991. case VariableTypes.FieldReference:
  992. case VariableTypes.PropertyReference:
  993. {
  994. object obj;
  995. if (variable.Parent != null)
  996. {
  997. var info = ResolveVariable(threadHashCode, variable.Parent, out obj);
  998. if (obj != null)
  999. {
  1000. return ResolveMember(obj, variable.Name, out res);
  1001. }
  1002. else
  1003. {
  1004. return VariableInfo.NullReferenceExeption;
  1005. }
  1006. }
  1007. else
  1008. {
  1009. var frame = intepreter.Stack.Frames.Peek();
  1010. var m = frame.Method;
  1011. if (m.HasThis)
  1012. {
  1013. var addr = Minus(frame.LocalVarPointer, m.ParameterCount + 1);
  1014. var v = StackObject.ToObject(addr, intepreter.AppDomain, intepreter.Stack.ManagedStack);
  1015. var result = ResolveMember(v, variable.Name, out res);
  1016. if (result.Type == VariableTypes.NotFound)
  1017. {
  1018. ILTypeInstance ins = v as ILTypeInstance;
  1019. if (ins != null)
  1020. {
  1021. var ilType = ins.Type.ReflectionType;
  1022. var fields = ilType.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  1023. foreach (var f in fields)
  1024. {
  1025. if (f.Name.Contains("_this"))
  1026. {
  1027. result = ResolveMember(f.GetValue(v), variable.Name, out res);
  1028. if (result.Type != VariableTypes.NotFound)
  1029. return result;
  1030. }
  1031. }
  1032. }
  1033. }
  1034. return result;
  1035. }
  1036. else
  1037. {
  1038. return VariableInfo.GetCannotFind(variable.Name);
  1039. }
  1040. }
  1041. }
  1042. case VariableTypes.IndexAccess:
  1043. {
  1044. return ResolveIndexAccess(threadHashCode, variable.Parent, variable.Parameters[0], out res);
  1045. }
  1046. case VariableTypes.Integer:
  1047. {
  1048. res = variable.Offset;
  1049. return VariableInfo.GetInteger(variable.Offset);
  1050. }
  1051. case VariableTypes.String:
  1052. {
  1053. res = variable.Name;
  1054. return VariableInfo.GetString(variable.Name);
  1055. }
  1056. case VariableTypes.Boolean:
  1057. {
  1058. if(variable.Offset == 1)
  1059. {
  1060. res = true;
  1061. return VariableInfo.True;
  1062. }
  1063. else
  1064. {
  1065. res = false;
  1066. return VariableInfo.False;
  1067. }
  1068. }
  1069. case VariableTypes.Null:
  1070. {
  1071. res = null;
  1072. return VariableInfo.Null;
  1073. }
  1074. default:
  1075. throw new NotImplementedException();
  1076. }
  1077. }
  1078. else
  1079. {
  1080. return VariableInfo.NullReferenceExeption;
  1081. }
  1082. }
  1083. else
  1084. return VariableInfo.NullReferenceExeption;
  1085. }
  1086. VariableInfo ResolveMember(object obj, string name, out object res)
  1087. {
  1088. res = null;
  1089. Type type = null;
  1090. if (obj is ILTypeInstance)
  1091. {
  1092. type = ((ILTypeInstance)obj).Type.ReflectionType;
  1093. }
  1094. else if (obj is Enviorment.CrossBindingAdaptorType)
  1095. type = ((Enviorment.CrossBindingAdaptorType)obj).ILInstance.Type.ReflectionType;
  1096. else
  1097. type = obj.GetType();
  1098. var fi = type.GetField(name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  1099. if (fi != null)
  1100. {
  1101. res = fi.GetValue(obj);
  1102. VariableInfo info = VariableInfo.FromObject(res);
  1103. info.Address = 0;
  1104. info.Name = name;
  1105. info.Type = VariableTypes.FieldReference;
  1106. info.TypeName = fi.FieldType.FullName;
  1107. info.IsPrivate = fi.IsPrivate;
  1108. info.IsProtected = fi.IsFamily;
  1109. info.Expandable = res != null && !fi.FieldType.IsPrimitive;
  1110. return info;
  1111. }
  1112. else
  1113. {
  1114. var fields = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  1115. string match = string.Format("<{0}>", name);
  1116. foreach (var f in fields)
  1117. {
  1118. if (f.Name.Contains(match))
  1119. {
  1120. res = f.GetValue(obj);
  1121. VariableInfo info = VariableInfo.FromObject(res);
  1122. info.Address = 0;
  1123. info.Name = name;
  1124. info.Type = VariableTypes.FieldReference;
  1125. info.TypeName = f.FieldType.FullName;
  1126. info.IsPrivate = f.IsPrivate;
  1127. info.IsProtected = f.IsFamily;
  1128. info.Expandable = res != null && !f.FieldType.IsPrimitive;
  1129. return info;
  1130. }
  1131. }
  1132. }
  1133. var pi = type.GetProperty(name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
  1134. if (pi != null)
  1135. {
  1136. res = pi.GetValue(obj, null);
  1137. VariableInfo info = VariableInfo.FromObject(res);
  1138. info.Address = 0;
  1139. info.Name = name;
  1140. info.Type = VariableTypes.PropertyReference;
  1141. info.TypeName = pi.PropertyType.FullName;
  1142. info.IsPrivate = pi.GetGetMethod(true).IsPrivate;
  1143. info.IsProtected = pi.GetGetMethod(true).IsFamily;
  1144. info.Expandable = res != null && !pi.PropertyType.IsPrimitive;
  1145. return info;
  1146. }
  1147. return VariableInfo.GetCannotFind(name);
  1148. }
  1149. unsafe bool GetValueExpandable(StackObject* esp, IList<object> mStack)
  1150. {
  1151. if (esp->ObjectType < ObjectTypes.Object)
  1152. return false;
  1153. else
  1154. {
  1155. var obj = mStack[esp->Value];
  1156. if (obj == null)
  1157. return false;
  1158. if (obj is ILTypeInstance)
  1159. return true;
  1160. else if (obj.GetType().IsPrimitive)
  1161. return false;
  1162. else
  1163. return true;
  1164. }
  1165. }
  1166. internal void ThreadStarted(ILIntepreter intp)
  1167. {
  1168. if (server != null && server.IsAttached)
  1169. {
  1170. server.SendSCThreadStarted(intp.GetHashCode());
  1171. }
  1172. }
  1173. internal void ThreadEnded(ILIntepreter intp)
  1174. {
  1175. if (server != null && server.IsAttached)
  1176. {
  1177. server.SendSCThreadEnded(intp.GetHashCode());
  1178. }
  1179. }
  1180. internal void Detach()
  1181. {
  1182. activeBreakpoints.Clear();
  1183. breakpointMapping.Clear();
  1184. pendingEnuming.Clear();
  1185. pendingReferences.Clear();
  1186. pendingIndexing.Clear();
  1187. foreach (var j in AppDomain.Intepreters)
  1188. {
  1189. j.Value.ClearDebugState();
  1190. j.Value.Resume();
  1191. }
  1192. }
  1193. internal unsafe void DumpStack(StackObject* esp, RuntimeStack stack)
  1194. {
  1195. var start = stack.StackBase;
  1196. var end = esp + 10;
  1197. var frames = stack.Frames;
  1198. var mStack = stack.ManagedStack;
  1199. var valuePointerEnd = stack.ValueTypeStackPointer;
  1200. StringBuilder final = new StringBuilder();
  1201. HashSet<long> leakVObj = new HashSet<long>();
  1202. for (var i = stack.ValueTypeStackBase; i > stack.ValueTypeStackPointer;)
  1203. {
  1204. leakVObj.Add((long)i);
  1205. i = Minus(i, i->ValueLow + 1);
  1206. }
  1207. for (var i = start; i <= end; i++)
  1208. {
  1209. StringBuilder sb = new StringBuilder();
  1210. ILMethod localMethod = null, baseMethod = null;
  1211. bool isLocal = false;
  1212. bool isBase = false;
  1213. int localIdx = 0;
  1214. if (i == esp)
  1215. sb.Append("->");
  1216. foreach (var j in frames)
  1217. {
  1218. if (i >= j.LocalVarPointer && i < j.BasePointer)
  1219. {
  1220. isLocal = true;
  1221. localIdx = (int)(i - j.LocalVarPointer);
  1222. localMethod = j.Method;
  1223. }
  1224. else if (i == j.BasePointer)
  1225. {
  1226. isBase = true;
  1227. baseMethod = j.Method;
  1228. }
  1229. }
  1230. sb.Append(string.Format("(0x{0:X8}) Type:{1} ", (long)i, i->ObjectType));
  1231. try
  1232. {
  1233. GetStackObjectText(sb, i, mStack, valuePointerEnd);
  1234. }
  1235. catch
  1236. {
  1237. sb.Append(" Cannot Fetch Object Info");
  1238. }
  1239. if (i < esp)
  1240. {
  1241. if (i->ObjectType == ObjectTypes.ValueTypeObjectReference)
  1242. VisitValueTypeReference(ILIntepreter.ResolveReference(i), leakVObj);
  1243. }
  1244. if (isLocal)
  1245. {
  1246. sb.Append(string.Format("|Loc:{0}", localIdx));
  1247. if (localIdx == 0)
  1248. {
  1249. sb.Append(" Method:");
  1250. sb.Append(localMethod.ToString());
  1251. }
  1252. }
  1253. if (isBase)
  1254. {
  1255. sb.Append("|Base");
  1256. sb.Append(" Method:");
  1257. sb.Append(baseMethod.ToString());
  1258. }
  1259. final.AppendLine(sb.ToString());
  1260. }
  1261. for (var i = stack.ValueTypeStackBase; i > stack.ValueTypeStackPointer;)
  1262. {
  1263. var vt = domain.GetTypeByIndex(i->Value);
  1264. var cnt = i->ValueLow;
  1265. bool leak = leakVObj.Contains((long)i);
  1266. final.AppendLine("----------------------------------------------");
  1267. final.AppendLine(string.Format("{2}(0x{0:X8}){1}", (long)i, vt, leak ? "*" : ""));
  1268. for (int j = 0; j < cnt; j++)
  1269. {
  1270. StringBuilder sb = new StringBuilder();
  1271. var ptr = Minus(i, j + 1);
  1272. sb.Append(string.Format("(0x{0:X8}) Type:{1} ", (long)ptr, ptr->ObjectType));
  1273. GetStackObjectText(sb, ptr, mStack, valuePointerEnd);
  1274. final.AppendLine(sb.ToString());
  1275. }
  1276. i = Minus(i, i->ValueLow + 1);
  1277. }
  1278. final.AppendLine("Managed Objects:");
  1279. for (int i = 0; i < mStack.Count; i++)
  1280. {
  1281. final.AppendLine(string.Format("({0}){1}", i, mStack[i]));
  1282. }
  1283. #if !UNITY_5 && !UNITY_2017_1_OR_NEWER && !UNITY_4
  1284. System.Diagnostics.Debug.Print(final.ToString());
  1285. #else
  1286. UnityEngine.Debug.LogWarning(final.ToString());
  1287. #endif
  1288. }
  1289. unsafe void GetStackObjectText(StringBuilder sb, StackObject* esp, IList<object> mStack, StackObject* valueTypeEnd)
  1290. {
  1291. string text = "null";
  1292. switch (esp->ObjectType)
  1293. {
  1294. case ObjectTypes.StackObjectReference:
  1295. {
  1296. sb.Append(string.Format("Value:0x{0:X8}", (long)ILIntepreter.ResolveReference(esp)));
  1297. }
  1298. break;
  1299. case ObjectTypes.ValueTypeObjectReference:
  1300. {
  1301. object obj = null;
  1302. var dst = ILIntepreter.ResolveReference(esp);
  1303. try
  1304. {
  1305. if (dst > valueTypeEnd)
  1306. obj = StackObject.ToObject(esp, domain, mStack);
  1307. if (obj != null)
  1308. text = obj.ToString();
  1309. }
  1310. catch
  1311. {
  1312. text = "Invalid Object";
  1313. }
  1314. text += string.Format("({0})", domain.GetTypeByIndex(dst->Value));
  1315. }
  1316. sb.Append(string.Format("Value:0x{0:X8} Text:{1} ", (long)ILIntepreter.ResolveReference(esp), text));
  1317. break;
  1318. default:
  1319. {
  1320. if (esp->ObjectType >= ObjectTypes.Null && esp->ObjectType <= ObjectTypes.ArrayReference)
  1321. {
  1322. if (esp->ObjectType < ObjectTypes.Object || esp->Value < mStack.Count)
  1323. {
  1324. var obj = StackObject.ToObject(esp, domain, mStack);
  1325. if (obj != null)
  1326. text = obj.ToString();
  1327. }
  1328. }
  1329. sb.Append(string.Format("Value:{0} ValueLow:{1} Text:{2} ", esp->Value, esp->ValueLow, text));
  1330. }
  1331. break;
  1332. }
  1333. }
  1334. unsafe void VisitValueTypeReference(StackObject* esp, HashSet<long> leak)
  1335. {
  1336. leak.Remove((long)esp);
  1337. for (int i = 0; i < esp->ValueLow; i++)
  1338. {
  1339. var ptr = Minus(esp, i + 1);
  1340. if (ptr->ObjectType == ObjectTypes.ValueTypeObjectReference)
  1341. {
  1342. VisitValueTypeReference(ILIntepreter.ResolveReference(ptr), leak);
  1343. }
  1344. }
  1345. }
  1346. }
  1347. }