Net Advanced Debugging No. 10: Debugging of lightweight code generation
1. Introduction
Today is the tenth article of “Net Advanced Debugging”. Speaking of advanced debugging, there is still a lot of debugging content and many skills. However, if you want to be a qualified senior debugger, you also need to master how to debug dynamically generated IL code. The advanced debugging technique we will explore today is how to debug IL code dynamically generated through Emit. Someone may ask, aren’t we writing C# code, or VB.Net code? Why do we need to dynamically generate IL code? Isn’t this work done by the compiler? Of course, this is generally the case, but when we write some high-performance frameworks, it is also common to write in IL code. Since you can also directly use IL to write code, debugging it is also indispensable. Although there are few debugging opportunities, if you have this ability, you will not panic when you encounter such a problem. As the saying goes: There is no pressure when you have more skills. body. Of course, when you watch a video or read a book for the first time, you will be very confused and don’t know how to operate it. As the old saying goes, if it doesn’t work once, then try it again. If it doesn’t work, then try it again. As the saying goes, you can read a thousand books. All over, its meaning appears by itself.
If there is no explanation, the test environment for all codes is Net Framewok 4.8. However, sometimes in order to view the source code, you may need to use Net Core projects. I will explain it in the project chapter. Okay, without further ado, let’s start our debugging work today.
I need to explain the debugging environment in case everyone is unclear. I have listed the specific circumstances.
Operating system: Windows Professional 10
Debugging tool: Windbg Preview (you can go to Microsoft Store to download)
Development Tool: Visual Studio 2022
Net version: Net Framework 4.8
CoreCLR source code: Source code download
2. Basic knowledge
1. Dynamic code debugging
Although there are not many opportunities for dynamic code debugging , but it is still necessary to master the skills of dynamic code debugging. As the saying goes, many skills do not overwhelm the body. When we encounter problems caused by writing code like this, we can also stay calm.
Today we will discuss three debugging techniques.
2. Three debugging strategies
2.1. Capture JIT’s CompileMethod method.
The compilation process of C# code is divided into two stages. The first stage is the compiler stage. At this stage, the compiler compiles the C# source code we wrote into IL code. The second stage is the compiler stage. stage, when running, JIT compiles the IL code into machine code, and our program runs. Now it is the dynamically generated IL code. There is no first stage, it is directly the second JIT compilation stage. We can try to set a breakpoint in a certain method of JIT to intercept and get the method descriptor, which is MD. , with MD, we can use the bp md command to set a breakpoint for this method, so that we can debug the dynamically generated code.
2.2. Obtain the function pointer of the delegate from the code (my test did not implement it).
This method is relatively simple, but it requires adding a line of code to the method, which is somewhat destructive. . Code: Marshal.GetFunctionPointerForDelegate(delegate instance).ToInt64().
2.3. Inject Debugger.Break() into dynamic code.
will be used to allow the program to interrupt the debugger. If we have complete control over this dynamic code, we can inject this method: Debugger.Break(), implements int 3 interrupt, and then obtains the desired data. The code is as follows: IL.Emit(OpCodes.Call,typeof(Debugger).GetMethod(“Break”)).
3. Assembly
3.1. Assembly crash
What does assembly leakage mean? That is, the memory of the program has skyrocketed, resulting in a large number of assembly assemblies.
3. Debugging Process
Without further ado, this section is about the specific debugging operations. process,It can also be said that seeing is believing. Before I start, I still want to say a few words. This section is divided into two parts. The first part is the source code part of the test. Without the code, of course there is no testing or debugging. There must be a carrier. The second part is to verify the knowledge we have learned based on specific code, which is based on seeing is believing.
1. Test source code
ccoutes
1.1、Example_10_1_1
1 namespace Example_10_1_1 2 { 3 internal span> class Program 4 { 5 private span> delegate int AddDelegate(int a, int b); 6 static span> void Main(string[] args) 7 { 8 var span> dynamicAdd = new DynamicMethod(" Add" span>, typeof(int), new Type[] { typeof(int), typeof(int) }); 9 var span> il = dynamicAdd.GetILGenerator(); 10 il.Emit (OpCodes.Ldarg_0); 11 il.Emit (OpCodes.Ldarg_1); 12 il.Emit (OpCodes.Add); 13 il.Emit (OpCodes.Ret); 14 15 var addDelegate = (AddDelegate)dynamicAdd.CreateDelegate(typeof (AddDelegate)); 16 Console.WriteLine(addDelegate(10, 20)); 17 } 18 } 19 }
View Code
1.2、Example_10_1_2
1 namespace Example_10_1_2 2 { 3 internal span> class Program 4 { 5 private span> delegate int AddDelegate(int a, int b); 6 static span> void Main(string[] args) 7 { 8 var span> dynamicAdd = new DynamicMethod(" Add" span>, typeof(int), new Type[] { typeof(int), typeof(int) }); 9 var span> il = dynamicAdd.GetILGenerator(); 10 il.Emit (OpCodes.Ldarg_0); 11 il.Emit (OpCodes.Ldarg_1); 12 il.Emit (OpCodes.Add); 13 il.Emit (OpCodes.Ret); 14 15 var addDelegate = (AddDelegate)dynamicAdd.CreateDelegate(typeof (AddDelegate)); 16 17 Console.WriteLine(" span>Function Pointer:0x{0:x16}", Marshal.GetFunctionPointerForDelegate(addDelegate).ToInt64()); 18 19 Debugger.Break(); 20 21 Console.WriteLine(addDelegate(10 , 20)) ; 22 } 23 } 24 }
View Code
1.3、Example_10_1_3
1 0x6b 26 14 010ff354 6f18b11b clr!MethodDescCallSite::CallTargetWorker+0x16a 27 15 010ff478 6f18b7fa clr!RunMain+0x1b3 28 16 010ff6e4 6f18b727 clr!Assembly::ExecuteMainMethod+0xf7 29 17 010ffbc8 6f18b8a8 clr!SystemDomain::ExecuteMainMethod+0x5ef 30 18 010ffc20 6f18b9ce clr!ExecuteEXE+0x4c 31 19 010ffc60 6f187305 clr!_CorExeMainInternal+0xdc 32 1a 010ffc9c 721bfa84 clr!_CorExeMain+0x4d 33 1b 010ffcd4 7224e81e mscoreei!_CorExeMain+0xd6 34 1c 010ffce4 72254338 MSCOREE!ShellShim__CorExeMain+0x9e 35 1d 010ffcfc 765ff989 MSCOREE!_CorExeMain_Exported+0x8 36 1e 010ffcfc 77b27084 KERNEL32!BaseThreadInitThunk+0x19 37 1f 010ffd58 77b27054 ntdll!__RtlUserThreadStart+0x2f 38 20 010ffd68 00000000 ntdll!_RtlUserThreadStart+0x1b
Or we can use the [!clrstack] command to check the call stack. This command can see it more clearly.
1 0:000> !clrstack 2 OS Thread Id: 0x3534 (0 ) 3 Child SP IP Call Site 4 010fee44 6f166b49 [ HelperMethodFrame_PROTECTOBJ: 010fee44] System.Reflection.Emit.AssemblyBuilder.nCreateDynamicAssembly(System.AppDomain, System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Threading.StackCrawlMark ByRef, System.Security.PermissionSet, System.Security.PermissionSet , System.Security.PermissionSet, Byte[], Byte[], System.Reflection.Emit.AssemblyBuilderAccess, System.Reflection.Emit.DynamicAssemblyFlags, System.Security.SecurityContextSource) 5 010fef20 6dfef391 System.Reflection.Emit.AssemblyBuilder..ctor(System.AppDomain, System.Reflection.AssemblyName , System.Reflection.Emit.AssemblyBuilderAccess, System.String, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.Security.PermissionSet, System.Threading.StackCrawlMark ByRef, System.Collections. Generic.IEnumerable`1, System.Security.SecurityContextSource) [f:\dd\ ndp\clr\src\BCL\system\reflection\emit\assemblybuilder.cs @ 424] 6 010fefa8 6dfef261 System.Reflection.Emit.AssemblyBuilder.InternalDefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection. Emit.AssemblyBuilderAccess, System.String, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.Security.PermissionSet, System.Threading.StackCrawlMark ByRef, System.Collections.Generic.IEnumerable`1, System.Security.SecurityContextSource) [f:\dd\ndp\clr\src \BCL\system\reflection\emit\assemblybuilder.cs @ 569] 7 010feffc 6e016558 System.AppDomain.InternalDefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.String, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.Security.PermissionSet, System.Threading.StackCrawlMark ByRef, System.Collections.Generic.IEnumerable`1, System.Security.SecurityContextSource) [f:\dd\ndp\clr\src\BCL\system \appdomain.cs @ 1515] 8 010ff028 6e016527 System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess) [f:\dd\ndp\clr\src\BCL\system\appdomain.cs @ 1221] 9 010ff038 6bd100bd System .Xml.Serialization.CodeGenerator.CreateAssemblyBuilder(System.AppDomain, System.String) 10 010ff04c 6bd0fa1b System .Xml.Serialization.TempAssembly.GenerateRefEmitAssembly(System.Xml.Serialization.XmlMapping[], System.Type[], System.String, System.Security.Policy.Evidence) 11 010ff0ec 6bd0f696 System .Xml.Serialization.TempAssembly..ctor(System.Xml.Serialization.XmlMapping[], System.Type[], System.String, System.String, System.Security.Policy.Evidence) 12 010ff128 6c09db2a System .Xml.Serialization.XmlSerializer.GenerateTempAssembly(System.Xml.Serialization.XmlMapping, System.Type, System.String, System.String, System.Security.Policy.Evidence) 13 010ff14c 6c09da72 System.Xml.Serialization.XmlSerializer..ctor(System.Type, System.Xml.Serialization. XmlAttributeOverrides, System.Type[], System.Xml.Serialization.XmlRootAttribute, System.String, System.String, System.Security.Policy.Evidence) 14 010ff184 6c09d8e7 System.Xml.Serialization.XmlSerializer..ctor(System.Type, System.Xml.Serialization. XmlRootAttribute) 15 010ff198 017710aa Example_10_1_4.Program.GetCustomer(Int32, System.String, System.String) [E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_10_1_4\Program.cs @ 27] 16 010ff1f4 01770ffc Example_10_1_4.Program+c__DisplayClass0_0.b__0(Int32) [E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_10_1_4\Program.cs @ 18] 17 010ff208 01770f88 System.Linq.Enumerable+WhereSelectEnumerableIterator`2[[System.Int32, mscorlib],[System.__Canon, mscorlib]].MoveNext () 18 010ff218 6dfaaa67 System.Collections.Generic.List`1[[System.__Canon, mscorlib]]..ctor(System.Collections.Generic.IEnumerable`1) [f:\dd\ndp\clr\src\BCL\system\collections\generic\list.cs @ 99] 19 010ff24c 6c77c5de System.Linq.Enumerable.ToList[[System.__Canon, mscorlib]](System.Collections .Generic.IEnumerable`1) 20 010ff260 017708f2 Example_10_1_4.Program.Main(System.String[]) [E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_10_1_4\Program.cs @ 17] 21 010ff3f8 6efdf036 [GCFrame: 010ff3f8]
We finally found the problem. The solution has already been written in the code.
IV. Summary
Finally I have finished writing. The writing process is tiring and happy at the same time. The learning process is really not that easy. Fortunately, I like this industry better, otherwise I don’t know if I can persist. Let’s talk about the old saying again. The first time I read the book “Advanced Debugging”, I was really confused. The second time it was a little better. If you don’t learn, you won’t know. Once you learn, you will be shocked. You will find that you lack a lot. Okay, let’s not talk anymore. Don’t forget your original intention and continue to work hard. I hope God will not let down those who work hard.
All countries in the world can be equalized; honors and positions can be dismissed; swordsmanship can be practiced; moderation is impossible.rgba(128, 0, 128, 1)”>1, System.Security.SecurityContextSource) [f:\dd\ndp\clr\src\BCL\system\reflection \emit\assemblybuilder.cs @ 569 ]
7 010feffc 6e016558 System.AppDomain.InternalDefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess, System.String, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.Security.PermissionSet, System.Threading.StackCrawlMark ByRef, System.Collections.Generic.IEnumerable`1, System.Security.SecurityContextSource) [f:\dd\ndp\clr\src\BCL\system \appdomain.cs @ 1515]
8 010ff028 6e016527 System.AppDomain.DefineDynamicAssembly(System.Reflection.AssemblyName, System.Reflection.Emit.AssemblyBuilderAccess) [f:\dd\ndp\clr\src\BCL\system\appdomain.cs @ 1221]
9 010ff038 6bd100bd System .Xml.Serialization.CodeGenerator.CreateAssemblyBuilder(System.AppDomain, System.String)
10 010ff04c 6bd0fa1b System .Xml.Serialization.TempAssembly.GenerateRefEmitAssembly(System.Xml.Serialization.XmlMapping[], System.Type[], System.String, System.Security.Policy.Evidence)
11 010ff0ec 6bd0f696 System .Xml.Serialization.TempAssembly..ctor(System.Xml.Serialization.XmlMapping[], System.Type[], System.String, System.String, System.Security.Policy.Evidence)
12 010ff128 6c09db2a System .Xml.Serialization.XmlSerializer.GenerateTempAssembly(System.Xml.Serialization.XmlMapping, System.Type, System.String, System.String, System.Security.Policy.Evidence)
13 010ff14c 6c09da72 System.Xml.Serialization.XmlSerializer..ctor(System.Type, System.Xml.Serialization. XmlAttributeOverrides, System.Type[], System.Xml.Serialization.XmlRootAttribute, System.String, System.String, System.Security.Policy.Evidence)
14 010ff184 6c09d8e7 System.Xml.Serialization.XmlSerializer..ctor(System.Type, System.Xml.Serialization. XmlRootAttribute)
15 010ff198 017710aa Example_10_1_4.Program.GetCustomer(Int32, System.String, System.String) [E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_10_1_4\Program.cs @ 27]
16 010ff1f4 01770ffc Example_10_1_4.Program+c__DisplayClass0_0.b__0(Int32) [E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_10_1_4\Program.cs @ 18]
17 010ff208 01770f88 System.Linq.Enumerable+WhereSelectEnumerableIterator`2[[System.Int32, mscorlib],[System.__Canon, mscorlib]].MoveNext ()
18 010ff218 6dfaaa67 System.Collections.Generic.List`1[[System.__Canon, mscorlib]]..ctor(System.Collections.Generic.IEnumerable`1) [f:\dd\ndp\clr\src\BCL\system\collections\generic\list.cs @ 99]
19 010ff24c 6c77c5de System.Linq.Enumerable.ToList[[System.__Canon, mscorlib]](System.Collections .Generic.IEnumerable`1)
20 010ff260 017708f2 Example_10_1_4.Program.Main(System.String[]) [E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test\Example_10_1_4\Program.cs @ 17]
21 010ff3f8 6efdf036 [GCFrame: 010ff3f8]
We finally found the problem. The solution has already been written in the code.
IV. Summary
Finally I have finished writing. The writing process is tiring and happy at the same time. The learning process is really not that easy. Fortunately, I like this industry better, otherwise I don’t know if I can persist. Let’s talk about the old saying again. The first time I read the book “Advanced Debugging”, I was really confused. The second time it was a little better. If you don’t learn, you won’t know. Once you learn, you will be shocked. You will find that you lack a lot. Okay, let’s not talk anymore. Don’t forget your original intention and continue to work hard. I hope God will not let down those who work hard.
All countries in the world can be equalized; honors and positions can be dismissed; swordsmanship can be practiced; moderation is impossible.gram.Main(System.String[]) [E:\Visual Studio 2022\Source\Projects\AdvancedDebug.NetFramework.Test \Example_10_1_4\Program.cs @ 17 ]
21 010ff3f8 6efdf036 [GCFrame: 010ff3f8]
We finally found the problem. The solution has already been written in the code.
IV. Summary
Finally I have finished writing. The writing process is tiring and happy at the same time. The learning process is really not that easy. Fortunately, I like this industry better, otherwise I don’t know if I can persist. Let’s talk about the old saying again. The first time I read the book “Advanced Debugging”, I was really confused. The second time it was a little better. If you don’t learn, you won’t know. Once you learn, you will be shocked. You will find that you lack a lot. Okay, let’s not talk anymore. Don’t forget your original intention and continue to work hard. I hope God will not let down those who work hard.
All countries in the world can be equalized; honors and positions can be dismissed; swordsmanship can be practiced; moderation is impossible.