How to set breakpoint in .net code

The following list provides a step-by-step description of how a breakpoint is set in managed code:

  • The debugger obtains a module object for the given function. The debugger calls theICorDebugAppDomain::GetModuleFromMetaDataInterfacemethod with the metadata interface to obtain anICorDebugModuleobject for the function’s module.
  • The debugger obtains a function object for the given function by calling theICorDebugModule::GetFunctionFromTokenmethod.
  • The debugger obtains the code object for the given function by calling theICorDebugFunction::GetILCodemethod.
  • The debugger creates a breakpoint in the managed code by calling the ICorDebugCode::CreateBreakpointmethod with a specific offset. CreateBreakpoint returns an instance ofICorDebugBreakpoint. The breakpoint is created in the active state.
  • The debugger continues execution of the process by calling theICorDebugController::Continuemethod for the current debuggee process.
  • The debugging API notifies the debugger when a thread reaches the breakpoint by calling theICorDebugManagedCallback::Breakpointcallback.
Posted in C#, Debugging | Leave a comment

How to start a new and debug .net process

The common language runtime (CLR) debugging API supports debugging in the runtime environment. The following is a step-by-step description of how a runtime process is debugged:

  • The debugger creates an instance of the ICorDebuginterface. The debugger invokes CComPtrBase::CoCreateInstance by using the CLSID CLSID_CorDebug to obtain an instance of ICorDebug.
  • The debugger initializes the debugging API by calling theICorDebug::Initializemethod.
  • The debugger registers a managed event handler. The debugger invokes theICorDebug::SetManagedHandlermethod to register an instance of theICorDebugManagedCallbackinterface as the callback for receiving notification and information about events in managed code.
  • The debugger optionally registers an unmanaged event handler. If the debugger wants to debug unmanaged code, it invokes theICorDebug::SetUnmanagedHandlermethod to register an instance ofICorDebugUnmanagedCallbackas the callback for receiving notification and information about events in unmanaged code.
  • The debugger creates the debuggee process. The debugger calls theICorDebug::CreateProcessmethod to create a process.
  • The debugging API notifies the debugger about the new debuggee process. The debugging API callsICorDebugManagedCallbackmethods, starting withICorDebugManagedCallback::CreateProcess. This may be followed by calls toICorDebugManagedCallback::LoadModule,ICorDebugManagedCallback::LoadClass,ICorDebugManagedCallback::CreateThread, and so on.
  • The debugger stops debugging. At some point, the debugger will get anICorDebugManagedCallback::ExitProcessevent, indicating that the debuggee is no longer executing. At some point after that, the debugger releases all references to any interfaces it has, and then calls theICorDebug::Terminatemethod.
Posted in C#, Debugging | Leave a comment

CLR Debugging Interfaces

ICLRDataEnumMemoryRegions Interface

Provides a method to enumerate regions of memory that are specified by callers.

ICLRDataEnumMemoryRegionsCallback Interface

Provides a callback method for EnumMemoryRegions to report to the debugger, the result of an attempt to enumerate a specified region of memory.

ICLRDataTarget Interface

Provides methods for interaction with a target CLR process.

ICLRDataTarget2 Interface

A subclass of ICLRDataTarget that is used by the data access services layer to manipulate virtual memory regions in the target process.

ICLRMetadataLocator Interface

Interface used by the data access services layer to locate metadata of assemblies in a target process.

ICorDebug Interface

Provides methods that allow developers to debug applications in the CLR environment.

ICorDebugAppDomain Interface

Provides methods for debugging application domains.

ICorDebugAppDomain2 Interface

Provides methods to work with arrays, pointers, function pointers, and ByRef types. This interface is an extension of the ICorDebugAppDomain interface.

ICorDebugAppDomainEnum Interface

Provides a method that returns a specified number of ICorDebugAppDomain values starting at the next location in the enumeration.

ICorDebugArrayValue Interface

A subclass of ICorDebugHeapValue that represents a single-dimensional or multi-dimensional array.

ICorDebugAssembly Interface

Represents an assembly.

ICorDebugAssembly2 Interface

Represents an assembly. This interface is an extension of the ICorDebugAssembly interface.

ICorDebugAssemblyEnum Interface

Implements ICorDebugEnum methods, and enumerates ICorDebugAssembly arrays.

ICorDebugBoxValue Interface

A subclass of ICorDebugHeapValue that represents a boxed value class object.

ICorDebugBreakpoint Interface

Represents a breakpoint in a function or a watch point on a value.

ICorDebugBreakpointEnum Interface

Implements ICorDebugEnum methods, and enumerates ICorDebugBreakpoint arrays.

ICorDebugChain Interface

Represents a segment of a physical or logical call stack.

ICorDebugChainEnum Interface

Implements ICorDebugEnum methods, and enumerates ICorDebugChain arrays.

ICorDebugClass Interface

Represents a type, which can be either basic or complex (that is, user-defined). If the type is generic, ICorDebugClass represents the uninstantiated generic type.

ICorDebugClass2 Interface

Represents a generic class or a class with a method parameter of type Type. This interface extends ICorDebugClass.

ICorDebugCode Interface

Represents a segment of either Microsoft intermediate language (MSIL) code or native code.

ICorDebugCode2 Interface

Provides methods that extend the capabilities of ICorDebugCode.

ICorDebugCodeEnum Interface

Implements ICorDebugEnum methods, and enumerates ICorDebugCode arrays.

ICorDebugContext Interface

Represents a context object. This interface has not been implemented yet.

ICorDebugController Interface

Represents a scope, either a Process or an AppDomain, in which code execution context can be controlled.

ICorDebugEditAndContinueErrorInfo Interface

Obsolete. Do not use this interface.

ICorDebugEditAndContinueSnapshot Interface

Obsolete. Do not use this interface.

ICorDebugEnum Interface

Serves as the abstract base interface for debugging enumerators.

ICorDebugErrorInfoEnum Interface

Obsolete. Do not use this interface.

ICorDebugEval Interface

Provides methods to enable the debugger to execute code within the context of the code being debugged.

ICorDebugEval2 Interface

Extends ICorDebugEval to provide support for generic types.

ICorDebugFrame Interface

Represents a frame on the current stack.

ICorDebugFrameEnum Interface

Implements ICorDebugEnum methods, and enumerates ICorDebugFrame arrays.

ICorDebugFunction Interface

Represents a managed function or method.

ICorDebugFunction2 Interface

Logically extends ICorDebugFunction to provide support for Just My Code step-through debugging.

ICorDebugFunctionBreakpoint Interface

Extends ICorDebugBreakpoint to support breakpoints within functions.

ICorDebugGenericValue Interface

A subclass of ICorDebugValue that applies to all values. This interface provides Get and Set methods for the value.

ICorDebugHandleValue Interface

A subclass of ICorDebugReferenceValue that represents a reference value to which the debugger has created a handle for garbage collection.

ICorDebugHeapValue Interface

A subclass of ICorDebugValue that represents an object that has been collected by the CLR garbage collector.

ICorDebugHeapValue2 Interface

An extension of ICorDebugHeapValue that provides support for runtime handles.

ICorDebugILFrame Interface

Represents a stack frame of MSIL code.

ICorDebugILFrame2 Interface

A logical extension of ICorDebugILFrame.

ICorDebugInternalFrame Interface

Identifies frame types for the debugger.

ICorDebugManagedCallback Interface

Provides methods to process debugger callbacks.

ICorDebugManagedCallback2 Interface

Provides methods to support debugger exception handling and managed debugging assistants (MDAs). ICorDebugManagedCallback2 is a logical extension of ICorDebugManagedCallback.

ICorDebugMDA Interface

Represents a managed debugging assistant (MDA) message.

ICorDebugModule Interface

Represents a CLR module, which is either an executable or a dynamic-link library (DLL).

ICorDebugModule2 Interface

Serves as a logical extension to ICorDebugModule.

ICorDebugModule3 Interface

Creates a symbol reader for a dynamic module.

ICorDebugModuleBreakpoint Interface

Extends ICorDebugBreakpoint to provide access to specific modules.

ICorDebugModuleEnum Interface

Implements ICorDebugEnum methods, and enumerates ICorDebugModule arrays.

ICorDebugNativeFrame Interface

A specialized implementation of ICorDebugFrame used for native frames.

ICorDebugObjectEnum Interface

Implements ICorDebugEnum methods, and enumerates arrays of objects by their relative virtual addresses (RVAs).

ICorDebugObjectValue Interface

A subclass of ICorDebugValue that represents a value that contains an object.

ICorDebugObjectValue2 Interface

Extends ICorDebugObjectValue to support inheritance and overrides.

ICorDebugProcess Interface

Represents a process that is executing managed code.

ICorDebugProcess2 Interface

A logical extension of ICorDebugProcess.

ICorDebugProcessEnum Interface

Implements ICorDebugEnum methods, and enumerates ICorDebugProcess arrays.

ICorDebugRegisterSet Interface

Represents the set of registers available on the machine that is currently executing code.

ICorDebugRegisterSet2 Interface

Extends the capabilities of ICorDebugRegisterSet for hardware platforms that have more than 64 registers.

ICorDebugReferenceValue Interface

A subclass of ICorDebugValue that supports reference types.

ICorDebugRemote Interface

Provides the ability to launch or attach a managed debugger to a remote target process.

ICorDebugRemoteTarget Interface

Provides methods that allow developers to debug Silverlight-based applications in the CLR environment.

ICorDebugStepper Interface

Represents a step in code execution that is performed by a debugger, serves as an identifier between the issuance and completion of a command, and provides a way to cancel a step.

ICorDebugStepper2 Interface

Provides support for Just My Code (JMC) debugging.

ICorDebugStepperEnum Interface

Implements ICorDebugEnum methods, and enumerates ICorDebugStepper arrays.

ICorDebugStringValue Interface

A subclass of ICorDebugHeapValue that applies to string values.

ICorDebugThread Interface

Represents a thread in a process. The lifetime of an ICorDebugThread instance is the same as the lifetime of the thread it represents.

ICorDebugThread2 Interface

Serves as a logical extension to ICorDebugThread.

ICorDebugThreadEnum Interface

Implements ICorDebugEnum methods, and enumerates ICorDebugThread arrays.

ICorDebugType Interface

Represents a type, which can be either basic or complex (that is, user-defined). If the type is generic, ICorDebugType represents the instantiated generic type.

ICorDebugTypeEnum Interface

Implements ICorDebugEnum methods, and enumerates ICorDebugType arrays.

ICorDebugUnmanagedCallback Interface

Provides notification of native events that are not directly related to the CLR.

ICorDebugValue Interface

Represents a read or write value in the process being debugged.

ICorDebugValue2 Interface

Extends ICorDebugValue to provide support for ICorDebugType.

ICorDebugValueBreakpoint Interface

Extends ICorDebugBreakpoint to provide access to specific values.

ICorDebugValueEnum Interface

Implements IcorDebugEnum methods, and enumerates ICorDebugValue arrays.

ICorPublish Interface

Serves as the general interface for the publishing processes.

ICorPublishAppDomain Interface

Represents and provides information about an application domain.

ICorPublishAppDomainEnum Interface

Provides methods that traverse a collection of ICorPublishAppDomain objects that currently exist within a process.

ICorPublishEnum Interface

Serves as the abstract base for publishing enumerators.

ICorPublishProcess Interface

Provides methods that access information about a process.

ICorPublishProcessEnum Interface

Provides methods that traverse a collection of ICorPublishProcess objects.

Posted in C#, Debugging | Leave a comment

浅析IL动态调试.NET程序的三种方法

对于调试.NET程序,一般要通过IL动态调试.NET程序。这里介绍的三种方法希望能对大家有所帮助。

很久以前发过一篇“调试.Net Framework内置程序集(System.Web.dll) ”

不可避免, 都需要用到 dll=> IL => IL’ => PDB+dll 的roundtrip,很是麻烦。

今天对某物Reflector时,不想关注太多逻辑,直接查看关键代码:

方法一:Reflexil v0.8 直接添加、修改IL调用

 

修改前:

修改前

修改后:

 

 

修改后

 

 

方法二: dll=> IL => IL’ => PDB+dll . 此时可用Deblector在Reflector中直接调试。

Deblector不需要pdb的调试,我还不会。 但应该可以, 哪位可以指点指点??

具体过程请看我开头提到的上一篇。

 

 

 

方法三:DILE (Dotnet IL Editor) v0.26

此公能力超强, 结合Reflector找到关键点, 直接Add Assembly, 设置好断点,

Attach或者是Startup都可以,瞬间即可运行目标位置,调用的参数、变量一清二楚!!

调用的参数

原文标题:IL动态调试.NET 程序(without pdb files)

链接:http://www.cnblogs.com/crabo/archive/2009/10/13/DEBUG_DotNET_IN_IL_WITHOUT_PDB.html

Posted in C#, Debugging | Leave a comment

MSIL Instruction Table

原文地址:http://safari.oreilly.com/0735616485/IDABH1W

Throughout this text, I’ve often employed the ILDASM utility to illustrate the Microsoft intermediate language (MSIL) that the C# compiler generates. I used ILDASM to give you a more complete understanding of the lower-level workings of the C# compiler. Although I briefly explain what each MSIL instruction does in the context of the chapter in which the instruction is used, I thought it would be nice to have a central listing of all the instructions. In the following table, I list each MSIL instruction, its opcode, the parameters that are passed to the instruction, and the resulting stack transition.

Here are a few notes that should help you when reading the table:

  • Because pushing means to place something on the stack, I use the phrase pushing a value rather than the more verbose pushing the value onto the stack.
  • Because popping is widely understood to mean taking something off the stack, I use the phrase popping the value instead of the more verbose popping the value off the stack.
  • When I use the word indirect, I’m referring to retrieving a value through its address. Therefore, the phrase pushes (indirect) value should be understood to mean pushes the value pointed at by an address onto the stack.
  • The term native int represents a 32-bit integer on all 32-bit versions of Microsoft Windows.
  • The letter F represents the native floating point.
  • The state transition column is intended to illustrate a before-and-after picture of the stack. For example, the stack transition: “…, value1, value2-> …, result” indicates that before the instruction is executed, the stack must contain two values (value1,value2), and that after the instruction is executed, these values will be replaced with one value (result). Note that the ellipsis character simply indicates unknown values on the stack that have nothing to do with this instruction.

 

Table A-1. MSIL Instructions

Instruction (Opcode) Description Stack Transition
add (0×58) Adds two values, pushing result …,val1,val2->…,result
add.ovf (0xD6) Adds integer values, pushing result; throws exception on overflow …,val1,val2->…,result
add.ovf.un (0xD7) Adds unsigned integer values, pushing result; throws exception on overflow …,val1,val2->…,result
and (0x5F) Bitwise AND of two integral values, pushing an integral value …val1,val2->…,result
arglist (0xFE 0×00) Pushes argument list handle for current method …->…,argListHandle
beq int32 (0x3B) Branches to specified offset if two top stack values are equal …,value,value->…
beq.s int8 (0x2E) Branches to specified offset if two top stack values are equal …,value,value->…
bge int32 (0x3C) Branches to specified offset if value1 is greater than or equal to value2 …,value1,value2->…
bge.s int8 (0x2F) Branches to specified offset if value1 is greater than or equal to value2 …,value1,value2->…
bge.un int32 (0×41) Branches to specified offset if value1 is greater than or equal to value2 (unsigned or unordered) …,value1,value2->…
bge.un.s int8 (0×34) Branches to specified offset if value1 is greater than or equal to value2 (unsigned or unordered) …,value1,value2->…
bgt int32 (0x3D) Branches to specified offset if value1 is greater than value2 …,value1,value2->…
bgt.s int8 (0×30) Branches to specified offset if value1 is greater than value2 …,value1,value2->…
bgt.un int32 (0×42) Branches to specified offset if value1 is greater than value2 (unsigned or unordered) …,value1,value2->…
bgt.un.s int8 (0×35) Branches to specified offset if value1 is greater than value2 (unsigned or unordered) …,value1,value2->…
ble int32 (0x3E) Branches to specified offset if value1 is less than or equal to value2 …,value1,value2->…
ble.s int8 (0×31) Branches to specified offset if value1 is less than or equal to value2 …,value1,value2->…
ble.un int32 (0×43) Branches to specified offset if value1 is less than or equal to value2 (unsigned or unordered) …,value1,value2->…
ble.un.s int8 (0×36) Branches to specified offset if value1 is less than or equal to value2 (unsigned or unordered) …,value1,value2->…
blt.un int32 (0×44) Branches to specified offset if value1 is less than value2 (unsigned or unordered) …,value1,value2->…
blt.un.s int8 (0×37) Branches to specified offset if value1 is less than value2 (unsigned or unordered) …,value1,value2->…
bne.un.s int8 (0×33) Branches to specified offset if value1 isn’t equal to value2 (unsigned or unordered) …,value1,value2->…
blt int32 (0x3F) Branches to specified offset if value1 is less than value2 …,value1,value2->…
blt.s int8 (0×32) Branches to specified offset if value1 is less than value2 …,value1,value2->…
bne.un int32 (0×40) Branches to specified offset if value1 isn’t equal to value2 (unsigned or unordered) …,value1,value2->…
box type (0x8C) Converts value type to object reference …,valType->…,obj
br int32 (0×38) Unconditional branch to specified offset …->…
br.s int8 (0x2B) Branches to specified offset …->…
Break (0×01) Informs the debugger that a breakpoint has been reached …->…
brfalse int32 (0×39) Branches to specified offset if value on stack is false …,value->…
brfalse.s int8 (0x2C) Branches to specified offset if value on stack is false …,value->…
brtrue int32 (0x3A) Branches to specified offset if value on stack is true …,value->…
brtrue.s int8 (0x2D) Branches to specified offset if value on stack is true …,value->…
call method (0×28) Calls a method …->…
calli signature (0×29) Calls method indicated by address on stack; stack also contains 1…n arguments …,arg1,arg2,argN, method->retVal

(retVal is not always pushed onto the stack as a result of the calli signature instruction.)

callvirt method (0x6F) Calls virtual method of obj …,obj,arg1… argn->…,retVal

(Not always pushed onto the stack for the callvirt method instruction.)

castclass type (0×74) Casts obj to class …,obj->…,obj2
ceq (0xFE 0×01) Compares equality of two values on stack; pushes 1 if equal; otherwise, pushes 0 …,val1,val2->…,result
cgt (0xFE 0×02) Compares to see whether val1 is greater than val2; pushes 1 if true and 0 if false …,val1,val2->…,result
cgt.un (0xFE 0×03) Compares to see whether val1 is greater than val2 (unsigned or unordered); pushes 1 if true and 0 if false …,val1,val2->…,result
ckfinite (0xC3) Checks for a finite real number; exception thrown if not a number (NaN) or (+/-)infinity; otherwise, value is left on stack …,value->…,value
clt (0xFE 0×04) Compares to see whether val1 is less than val2; pushes 1 if true and 0 if false …,val1,val2->…,result
clt.un (0xFE 0×05) Compares to see whether val1 is less than val2 (unsigned or unordered); pushes 1 if true and 0 if false …,val1,val2->…,result
conv.i (0xD3) Converts value to native int, pushing resulting native int …,value->…,result
conv.i1 (0×67) Converts value to int8, pushing int32 …,value->…,result
conv.i2 (0×68) Converts value to int16, pushing int32 …,value->…,result
conv.i4 (0×69) Converts value to int32, pushing int32 …,value->…,result
conv.i8 (0x6A) Converts value to int64, pushing int64 …,value->…,result
conv.ovf.i (0xD4) Converts value to native int, pushing resulting native int; throws exception on overflow …,value->…,result
conv.ovf.i.un (0x8A) Converts unsigned value to native int, pushing resulting native int; throws exception on overflow …,value->…,result
conv.ovf.i1 (0xB3) Converts value to int8, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.i1.un (0×82) Converts value to uint8, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.i2 (0xB5) Converts value to int16, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.i2.un (0×83) Converts value to uint16, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.i4 (0xB7) Converts value to int32, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.i4.un (0×84) Converts value to uint32, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.i8 (0xB9) Converts value to int64, pushing resulting int64; throws exception on overflow …,value->…,result
conv.ovf.i8.un (0×85) Converts value to uint64, pushing resulting int64; throws exception on overflow …,value->…,result
conv.ovf.u (0xD5) Converts value to native unsigned int, pushing resulting native unsigned int; throws exception on overflow …,value->…,result
conv.ovf.u.un (0x8B) Converts unsigned value to native unsigned int, pushing resulting native int; throws exception on overflow …,value->…,result
conv.ovf.u2 (0xB6) Converts value to uint16, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.u2.un (0×87) Converts unsigned value to uint16, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.u4 (0xB8) Converts value to uint32, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.u4.un (0×88) Converts unsigned value to uint32, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.u8 (0xBA) Converts value to uint16, pushing resulting int64; throws exception on overflow …,value->…,result
conv.ovf.u8.un (0×89) Converts unsigned value to uint64, pushing resulting int64; throws exception on overflow …,value->…,result
conv.ovf.u1 (0xB4) Converts value to uint8, pushing resulting int32; throws exception on overflow …,value->…,result
conv.ovf.u1.un (0×86) Converts unsigned value to uint8, pushing resulting int32; throws exception on overflow …,value->…,result
conv.r.un (0×76) Converts unsigned integer to floating point, pushing F …,value->…,result
conv.r4 (0x6B) Converts value to float32, pushing F …,value->…,result
conv.r8 (0x6C) Converts value to float64, pushing F …,value->…,result
conv.u (0xE0) Converts value to native unsigned int, pushing native int …,value->…,result
conv.u1 (0xD2) Converts value to uint8, pushing resulting int32 …,value->…,result
conv.u2 (0xD1) Converts value to uint16, pushing resulting int32 …,value->…,result
conv.u4 (0x6D) Converts value to uint32, pushing int32 …,value->…,result
conv.u8 (0x6E) Converts value to uint32, pushing int32 …,value->…,result
cpblk (0xFE 0×17) Copies size bytes from srcAddr to destAddr in memory …,destAddr,srcAddr, size->…
cpobj type (0×70) Copies a value type …,destAddr, srcAddr->…
div (0x5B) Divides value1 by value2, pushing result …,val1,val2->…,result
div.un (0x5C) Divides (unsigned) integer values, pushing result …,val1,val2->…,result
dup (0×25) Duplicates the value at top of stack …,value-> …,value,value
endfilter (0xFE 0×11) Returns from the filter clause of an SEH exception …,value->…
endfinally (0xDC) Returns from a finally clause …->…
jmp method (0×27) Transfers control to the specified method …->…
initblk (0xFE 0×18) Initializes a block of size memory starting at addr with value …,addr,value,size->…
initobj classToken (0xFE 0×15) Initializes a value type …,valueObjAddr->…
isinst type (0×75) Tests whether an object is an instance of a type or interface, pushing resulting cast if successful or null on failure.

(A null is defined by the CLI as zero (having a bit pattern of all bits zero).)

…,obj->…,result
ldarg uint32 (0xFE 0×09) Pushes argument at specified index …->…,value
ldarg.0 (0×02) Pushes the first argument of a method …->…,value
ldarg.1 (0×03) Pushes the second argument of a method …->…,value
ldarg.2 (0×04) Pushes the third argument of a method …->…,value
ldarg.3 (0×05) Pushes the fourth argument of a method …->…,value
ldarg.s uint8 (0x0E) Pushes specified argument …->…,value
ldarga uint32 (0xFE 0x0A) Pushes address of argument at specified index …->…,address
ldarga.s uint8 (0x0F) Pushes address of specified argument …->…,value
ldc.i4.m1 (0×15) Pushes the literal value, -1 …->…,-1
ldc.i4 int32 (0×20) Pushes specified 32-bit value …-> …,value
ldc.i4.0 (0×16) Pushes the literal value, 0 …->…,0
ldc.i4.1 (0×17) Pushes the literal value, 1 …->…,1
ldc.i4.2 (0×18) Pushes the literal value, 2 …->…,2
ldc.i4.3 (0×19) Pushes the literal value, 3 …>…,3
ldc.i4.4 (0x1A) Pushes the literal value, 4 …->…,4
ldc.i4.5 (0x1B) Pushes the literal value, 5 …->…,5
ldc.i4.6 (0x1C) Pushes the literal value, 6 …->…,6
ldc.i4.7 (0x1D) Pushes the literal value, 7 …->…,7
ldc.i4.8 (0x1E) Pushes the literal value, 8 …->…,8
ldc.i4.s int8 (0x1F) Pushes specified 8-bit value as 32-bit …->…,value
ldc.i8 int64 (0×21) Pushes specified 64-bit value …->…,value
ldc.r4 float32 (0×22) Pushes specified 32-bit floating point …->…,value
ldc.r8 float64 (0×23) Pushes specified 64-bit floating point …->…,value
ldelem.i (0×97) Pushes array element (native int) as native int …array,index->…, value
ldelem.i1 (0×90) Pushes array element (int8) as int32 …array,index->…, value
ldelem.i2 (0×92) Pushes array element (int16) as int32 …array,index->…, value
ldelem.i4 (0×94) Pushes array element (int32) as int32 …array,index->…, value
ldelem.i8 (0×96) Pushes array element (int64) as int64 …array,index->…, value
ldelem.r4 (0×98) Pushes array element (float32) as F …array,index->…, value
ldelem.r8 (0×99) Pushes array element (float64) as F …array,index->…, value
ldelem.ref (0x9A) Pushes array element (object) as object …array,index->…, value
ldelem.u1 (0×91) Pushes array element (uint8) as int32 …array,index-> …,value
ldelem.u2 (0×93) Pushes array element (uint16) as int32 …array,index-> …,value
ldelem.u4 (0×95) Pushes array element (uint32) as int32 …array,index-> …,value
ldelema type (0x8F) Pushes the address of an array element …,array,index-> …,addr
ldfld field (0x7B) Pushes field of an object …,obj->…,value
ldflda field (0x7C) Pushes field address of an object …,obj->…,addr
ldftn method (0xFE 0×06) Pushes the method pointer referenced by method …->…,ftn
ldind.i (0x4D) Pushes (indirect) value of type native int as native int …,addr->…,value
ldind.i1 (0×46) Pushes (indirect) value of type int8 as int32 …,addr->…,value
ldind.i2 (0×48) Pushes (indirect) value of type int16 as int32 …,addr->…,value
ldind.i4 (0x4A) Pushes (indirect) value of type int32 as int32 …,addr->…,value
ldind.i8 (0x4C) Pushes (indirect) value of type int64 as int64 …,addr->…,value
ldind.u1 (0×47) Pushes (indirect) value of type uint8 as int32 …,addr->…,value
ldind.u2 (0×49) Pushes (indirect) value of type uint16 as int32 …,addr->…,value
ldind.u4 (0x4B) Pushes (indirect) value of type uint32 as int32 …,addr->…,value
ldind.r4 (0x4E) Pushes (indirect) value of type float32 as F …,addr->…,value
ldind.r8 (0x4F) Pushes (indirect) value of type float64 as F …,addr->…,value
ldind.ref (0×50) Pushes (indirect) object ref as o …,addr->…,value
ldlen (0x8E) Pushes the length of an array …,array->…,length
ldloc uint32 (0xFE 0x0C) Pushes local variable at specified index …->…,value
ldloc.0 (0×06) Pushes the first local variable …->…,value
ldloc.1 (0×07) Pushes the second local variable …->…,value
ldloc.2 (0×08) Pushes the third local variable …->…,value
ldloc.3 (0×09) Pushes the fourth local variable …->…,value
ldloc.s uint8 (0×11) Pushes the specified local variable …->…,value
ldloca uint32 (0xFE 0x0D) Pushes address of local variable at specified index …->…,address
ldloca.s uint8 (0×12) Pushes address of specified local variable …->…,value
ldnull (0×14) Pushes null reference …->…,null
ldobj type (0×71) Pushes value …,addrValueObj-> …,valueObj
ldsfld field (0x7E) Pushes static field of an object …->…,value
ldsflda field (0x7F) Pushes static field address of an object …->…,value
ldstr type (0×72) Pushes a literal string …,->..,string
ldtoken token (0xD0) Loads the common language runtime representation of a metadata token …->…,runtimeHandle
ldvirtftn method (0xFE 0×07) Pushes the method pointer referenced by method …,obj->…,ftn
leave int32 (0xDD) Branches out of a protected block of code (try, filter, catch) to target (int32 offset) …->…
leave.s int8 (0xDE) Branches out of a protected block of code (try, filter, catch) to target (int8 offset) …->…
localloc (0xFE 0x0F) Allocates size (native unsigned int) bytes from the local dynamic memory pool and pushes address …,size->…,address
mkrefany type (0xC6) Pushes a typed reference on the stack …,ptr->…,typedRef
mul (0x5A) Multiplies two values, pushing result …,val1,val2->…,result
mul.ovf (0xD8) Multiplies signed integer values, pushing result; throws exception on overflow …,val1,val2->…,result
mul.ovf.un (0xD9) Multiplies unsigned signed integer values, pushing result; throws exception on overflow …,val1,val2->…,result
neg (0×65) Negates the value on the stack …,value->…,result
newarr elementType (0x8D) Creates a one-dimensional array of elementType …,numberOfElements->…,array
newobj method (0×73) Creates a new object (calling its ctor) …,arg1…argn->…,obj
not (0×66) Computes bitwise complement of value on stack, pushing result …,value->…,result
nop (0×00) Null operation used only to fill in space if bytecodes are patched …->…
or (0×60) Bitwise OR of two integral values, pushing an integral value …val1,val2->…,result
pop (0×26) Pops top element of stack …,value->…
refanytype (0xFE 0x1D) Pushes the type token out of typed reference …,typedRef->…,type
refanyval type (0xC2) Loads the address out of a typed reference …,typedRef->…,addr
rem (0x5D) Computes remainder of dividing value1 by value2 …,val1,val2->…,result
rem.un (0x5E) Computes remainder of dividing value1 by value2 (both unsigned) …,val1,val2->…,result
ret (0x2A) Returns control from current method to caller …,retVal->

(Not always pushed onto the stack for the ret instruction.)

…,retVal

(Not always pushed onto the stack for the ret instruction.)

rethrow (0xFE 0x1A) Only valid within a catch block; this instruction rethrows the current exception back up the call stack …->…
shl (0×62) Shift-left operation in which signed integer value and number of decimal places to shift are on stack …,value,shiftAmount-> …,result
shr (0×63) Shift-right operation in which signed integer value and number of decimal places to shift are on stack …,value,shiftAmount-> …,result
shr.un (0×64) Shift-right operation in which unsigned integer value and number of decimal places to shift are on stack …,value,shiftAmount-> …,result
sizeof valueType (0xFE 0x1C) Pushes the size (in bytes) of the specified valueType …->…,size
starg uint32 (0xFE 0x0B) Stores a value to argument at specified index …,value->…
starg.s uint8 (0×10) Pops value to specified method argument …,value ->…
stelem.i (0x9B) Overwrites array element at index with value on the stack …,array,index,value-> …
stelem.i1 (0x9C) Overwrites array element at index with int8 value on the stack …,array,index,value-> …
stelem.i2 (0x9D) Overwrites array element at index with int16 value on the stack …,array,index,value-> …
stelem.i4 (0x9E) Overwrites array element at index with int32 value on the stack …,array,index,value-> …
stelem.i8 (0x9F) Overwrites array element at index with int64 value on the stack …,array,index,value-> …
stelem.r4 (0xA0) Overwrites array element at index with float32 value on the stack …,array,index,value-> …
stelem.r8 (0xA1) Overwrites array element at index with float64 value on the stack …,array,index,value-> …
stelem.ref (0xA2) Overwrites array element at index with reference value on the stack …array,index,value-> …
stfld field (0x7D) Stores into a field of an object …,obj,value->…
stind.ref (0×51) Stores object reference value into addr …,addr,value->…
stind.i (0xDF) Stores native int value into addr …,addr,value->…
stind.i1 (0×52) Stores int8 value at addr …,addr,value->…
stind.i2 (0×53) Stores int16 value at addr …,addr,value->…
stind.i4 (0×54) Stores int32 value at addr …,addr,value->…
stind.i8 (0×55) Stores int64 value at addr …,addr,value->…
stind.r4 (0×56) Stores float32 value at addr …,addr,value->…
stind.r8 (0×57) Stores float64 value at addr …,addr,value->…
stloc uint32 (0xFE 0x0E) Pops value to local variable at specified index …,value->…
stloc.0 (0x0A) Pops value to first local variable …,value ->…
stloc.1 (0x0B) Pops value to second local variable …,value ->…
stloc.2 (0x0C) Pops value to third local variable …,value ->…
stloc.3 (0x0D) Pops value to fourth local variable …,value ->…
stloc.s uint8 (0×13) Pops value to specified local variable ..,value ->…
stobj type (0×81) Copies valObj into addr …,addr,valObj->…
stsfld field (0×80) Stores a static field …,value->…
sub (0×59) Subtracts value2 from value1, pushing result …,val1,val2->…,result
sub.ovf (0xDA) Subtracts integer values, pushing result; throws exception on overflow …,val1,val2->…,result
sub.ovf.un (0xDB) Subtracts unsigned integer values, pushing result; throws exception on overflow …,val1,val2->…,result
switch uint32 (N) + N(int32) (0×45) Implements a jump table in which first argument (uint32) is number of targets (specified as offsets); remaining arguments (int32) are the target offsets …,value->…
tail (0xFE 0×14) This prefix indicates termination of current method via subsequent call, calli, or callvirt instructions …->…
throw (0x7A) Throws an exception of type o …,object->…
unaligned uint8 (0xFE 0×12) Specifies that addr shouldn’t be aligned …,addr->…,addr
unbox type (0×79) Converts boxed value type to raw form …,obj->…, valueTypePtr
volatile (0xFE 0×13) This prefix specifies that the pointer reference (on the stack) is volatile …,addr->…,addr
xor (0×61) Bitwise exclusive OR of two integral values, pushing an integral value …val1,val2->…,result
Posted in Assembly, C# | Leave a comment

MSIL 教程(一)

介绍

微软中间语言 (MSIL) 是一种语言,是许多编译器(C#,VB.NET等)的输出. ILDasm (中间语言反汇编器)程序和.Net Framework SDK(FrameworkSDK\Bin\ildasm.exe)打包在一起,让用户以人可阅读的格式查看MSIL代码。通过该工具,我们可以打开任何.net可执行文件(exe或dll)并查看其MSIL代码。

ILAsm 程序(中间语言编译器)从MSIL语言生成可执行文件。我们可以在WINNT \ Microsoft.NET \Framework \vn.nn.nn目录中找到这个程序。

许多Visual C++程序员开始.net开发是因为他们对.NET框架的底层发生了一些什么感兴趣。学习MSIL给了用户理解某些对C#程序员或VB.NET程序员来说是透明的东西的机会。通晓MSIL给.NET程序员更多的能力。我们从不需要直接用MSIL编写程序,但是在某些情况下是非常有用的,我们可以用ILDasm打开程序的MSIL代码,查看它到底做了一些什么。

一个Doc格式的MSIL参考对.NET开发人员来说比较有用,它也许可以在Framework SDK目录下找到:

  • FrameworkSDK\Tool Developers Guide\docs\Partition II Metadata.doc (元数据定义和术语). 在这个文件中,我发现了所有MSIL指令的说明,例如.entrypoint.locals等.
  • FrameworkSDK\Tool Developers Guide\docs\Partition III CIL.doc (CIL命令集)包含了一个MSIL命令的完整列表。

在工作中,我也用到了一个MSDN的ILDAsm教程,一篇2001年5月由John Robbins发表在MSDN杂志的优秀的文章: ”ILDASM is Your New Best Friend”。

我想学习一门语言最好的途径就是用它写一些程序,所以我决定写一些小的MSIL程序。实际上,我们有写这些代码——是C#编译器生成的,我只是做一了一些小的更改,并加了许多注释以描述MSIL是如何工作的。

通过阅读附在本文的例子可以帮助.NET程序员理解中间语言,帮助其在需要的时候更易读懂MSIL代码。


一般信息

在MSIL中,所有的操作都在栈上完成。当调用一个函数的时候,其参数和局部变量都被分配到栈上。函数的代码从该栈开始,把一些值压入栈,对这些值进行一些操作,从栈上取出值。

执行MSIL名利和函数由3个步骤完成:

1.      把命令操作数和函数参数压入栈。

2.      执行命令或者调用函数。命令或函数从栈中取出他们的操作数(参数)并把他们压入结果栈 (返回值)。

3.      从栈中读取结果值。

步骤1~3是可选的,例如,void函数不会压入一个结果值到栈。

栈包含值类型对象和引用类型对象的引用。引用类型对象本身保存在堆中。

用来把一个值压入栈中的MSIL命令是ld… (装载),用来从栈中取出值的命令是st… (存储),因为值都存在变量中。我们可以把入栈操作叫做装载,出栈操作叫做存储。


示例项目

本文附上的代码中包含了许多用MSIL写的控制台程序. 如果需要编译他们,请确定ILAsm程序可以通过PATH访问。每个项目都是一个Visual Studio解决方案,IL源文件可以用VS的文本编辑器打开,Build命令运行ILAsm 程序在项目所在目录生成exe文件,run命令执行该文件。在每个程序的末尾,我加了几行代码,他们可以用C#来写:

    Console.WriteLine(“Press Enter to continue”);

    Console.Read();

这样,当从Windows Explorer运行的时候,就可以看到程序的输出。

下面是所含项目的列表:

1.      打印字符串—打印字符传到控制台。

2.      赋值—给一个int变量赋值并把它打印到控制台。

3.      运算—从控制台读取2个数字,惊醒+,-和乘的操作,并显示结果。

4.      数组— 分配一个int类型的数组,给他的元素赋值,打印其元素和数组的长度。

5.      比较— 输入2个数字并打印出最小的那个。

6.      数组2— 用循环填充数组元素并打印某些元素。

7.      不安全代码— 使用unsafe指针访问数组元素。

8.      PInvoke— 调用Win32 API。

9.      — 和类一起工作。

10.   异常— 异常处理。

我假设你以在这所说的顺序阅读这些项目。在下面的项目描述中,我用程序来解释每一条MSIL命令,并给出一些代码片段。


打印字符串

PrintString 就是MSIL版的 Hello, World

在代码中用到的MSIL指令如下:

l          .entrypoint— 定义程序的入口点(该函数在程序启动的时候由.NET 运行库调用)

l          .maxstack— 定义函数代码所用堆栈的最大深度。C#编译器可以对每个函数设置准确的值, 在例子中,我把他设为8。

用到的MSIL命令如下:

  • ldstr string—把一个字符串常量装入堆栈。
  • call function(parameters)—调用静态函数。函数的参数必须在函数调用前装入堆栈。
  • pop— 取出栈顶的值。当我们不需要把值存入变量时使用。
  • ret— 从一个函数中返回。

调用静态函数很简单。我们把函数的参数压入堆栈,调用函数,然后从堆栈中读取函数的返回值(如果是非void函数)。Console.WriteLine 就是一个这样的函数。

下面是代码:

.assembly PrintString {}

/*

    Console.WriteLine(“Hello, World)”

*/

.method static public void main() il managed

{

    .entrypoint             // 该函数是程序的入口

    .maxstack 8

    // *****************************************************

    // Console.WriteLine(“Hello, World)”;

    // *****************************************************

    ldstr “Hello, World”        // 把字符串压入堆栈

    // 调用静态的System.Console.Writeline函数

    // (函数移除栈顶的字符串)

    call   void [mscorlib]System.Console::WriteLine

                                 (class System.String)

    // *****************************************************

    ldstr “Press Enter to continue”

    call   void [mscorlib]System.Console::WriteLine

                                 (class System.String)

    // 调用 System.Console.Read 函数

    call int32 [mscorlib]System.Console::Read()

    // pop 指令移除栈顶元素

    // (移除由Read()函数返回的数字

    pop

    // *****************************************************

    ret

}


赋值

该程序给一个变量赋与int值并把它打印到控制台窗口。

命令:

  • ldc.i4.n—把一个 32位的常量(n从0到8)装入堆栈
  • stloc.n— 把一个从堆栈中返回的值存入第n(n从0到8)个局部变量

代码:

.assembly XequalN {}

// int x;

// x = 7;

// Console.WriteLine(x);

.method static public void main() il managed

{

    .entrypoint

    .maxstack 8

    .locals init ([0] int32 x)  // 分配一个局部变量

    // *****************************************************

    // x = 7;

    // *****************************************************

    ldc.i4.7                    // 把常量装入堆栈

    stloc.0                     // 把堆栈中的值存入第0个变量

    // *****************************************************

    // Console.WriteLine(x);

    // *****************************************************

    ldloc.0                     // 把第0个变量转入堆栈

    call void [mscorlib]System.Console::WriteLine(int32)

    ret

}


数据运算

本程序从控制台读取2个数字,对它们进行简单的运算,然后显示结果。

命令:

  • add—2个值相加。命令的参数必须在调用前装入堆栈,该函数从堆栈中移除参数并把运算后的结果压入堆栈。
  • sub— 2个值相减。
  • mul— 2个值相乘。

代码片段:

.assembly Operations {}

/*

// 程序的C#代码:

            int x, y, z;

            string s;

            Console.WriteLine(“Enter x:”);

            s = Console.ReadLine();

            x = Int32.Parse(s);

            Console.WriteLine(“Enter y:”);

            s = Console.ReadLine();

            y = Int32.Parse(s);

            z = x + y;

            Console.Write(“x + y = “);

            Console.Write(z);

            Console.WriteLine(“”);

            z = x – y;

            Console.Write(“x – y = “);

            Console.Write(z);

            Console.WriteLine(“”);

            z = x * y;

            Console.Write(“x * y = “);

            Console.Write(z);

            Console.WriteLine(“”);

*/

.method static public void main() il managed

{

    .entrypoint

    .maxstack 8

    .locals init ([0] int32 x,

           [1] int32 y,

           [2] int32 z,

           [3] string s)

    // *****************************************************

    // Console.WriteLine(“Enter x:”);

    // *****************************************************

    ldstr      ”Enter x:”       // 把字符装入堆栈

call       void [mscorlib]System.Console::WriteLine(string)

    // *****************************************************

    // s = Console.ReadLine();

    // *****************************************************

    call       string [mscorlib]System.Console::ReadLine()

    stloc.3                     // 把值存入第3个变量

    // *****************************************************

    // x = Int32.Parse(s);

    // *****************************************************

    ldloc.3                     // 把第3个变量装入堆栈

    // 调用 System.Int32::Parse(string)函数

    // 把字符串从堆栈中移除并把解析的结果——int值压入堆栈

    call       int32 [mscorlib]System.Int32::Parse(string)

    stloc.0                     // 把值存入第0个变量

    // *****************************************************

    // 和变量y的一些运算

    // *****************************************************

    ldstr      ”Enter y:”

               // 装入字符串

    call       void [mscorlib]System.Console::WriteLine(string)

               // 调用

    call       string [mscorlib]System.Console::ReadLine()

               // 调用

    stloc.3

               //把值存入第3个变量

    ldloc.3

               //把第3个变量装入堆栈

    call       int32 [mscorlib]System.Int32::Parse(string)

               // 调用

    stloc.1

               //把值存入第1个变量

    // *****************************************************

    // z = x + y;

    // *****************************************************

    ldloc.0             //把第0个变量装入堆栈

    ldloc.1             //把第1个变量装入堆栈

    // 把这2个值从堆栈中移除,把结果压入堆栈

add

    stloc.2             //把值存入第2个变量

    // *****************************************************

    // Console.Write(“x + y = “);

    // *****************************************************

    ldstr      ”x + y = “          // load string onto stack

    call       void [mscorlib]System.Console::Write(string)

    // *****************************************************

    // Console.Write(z);

    // *****************************************************

    ldloc.2                    //把第2个变量装入堆栈

    call       void [mscorlib]System.Console::Write(int32)

    // *****************************************************

    // Console.WriteLine(“”);

    // *****************************************************

    ldstr      ”"                  //装入字符串

    call       void [mscorlib]System.Console::WriteLine(string)

    //相减和相乘运算过程与上面相同

    ret

}

 

Posted in Assembly, C# | Leave a comment

clr!MethodDesc::DoPrestub is compiling IL code into Native code

0:000> u 526b2041 L 20
clr!PreStubWorker:
526b2041 6a3c push 3Ch
526b2043 b87c8ebd52 mov eax,offset clr! ?? ::FNODOBFM::`string’+0x3e00f (52bd8e7c)
526b2048 e8bcf7fdff call clr!_EH_prolog3_catch (52691809)
526b204d ff1508126952 call dword ptr [clr!_imp__GetLastError (52691208)]
526b2053 8945dc mov dword ptr [ebp-24h],eax
526b2056 ff1550a2c752 call dword ptr [clr!GetThread (52c7a250)]
526b205c 8bf0 mov esi,eax
526b205e 8b460c mov eax,dword ptr [esi+0Ch]
526b2061 8945e4 mov dword ptr [ebp-1Ch],eax
526b2064 8365fc00 and dword ptr [ebp-4],0
526b2068 8975e8 mov dword ptr [ebp-18h],esi
526b206b e893f7fdff call clr!IsStackProbingEnabled (52691803)
526b2070 85c0 test eax,eax
526b2072 0f8580633000 jne clr!PreStubWorker+0×33 (529b83f8)
526b2078 8d4dd0 lea ecx,[ebp-30h]
526b207b e84bf7fdff call clr!SOIntolerantTransitionHandler::SOIntolerantTransitionHandler (5
26917cb)
526b2080 c645fc01 mov byte ptr [ebp-4],1
526b2084 8b0d98a9c752 mov ecx,dword ptr [clr!Microsoft_Windows_DotNETRuntimePrivateHandle (52
c7a998)]
526b208a 894db8 mov dword ptr [ebp-48h],ecx
526b208d 8b159ca9c752 mov edx,dword ptr [clr!Microsoft_Windows_DotNETRuntimePrivateHandle+0x4
(52c7a99c)]
526b2093 8955bc mov dword ptr [ebp-44h],edx
526b2096 b850216b52 mov eax,offset clr!PrestubWorker_V1 (526b2150)
526b209b 8945c0 mov dword ptr [ebp-40h],eax
526b209e bf60216b52 mov edi,offset clr!PrestubWorkerEnd_V1 (526b2160)
526b20a3 897dc8 mov dword ptr [ebp-38h],edi
526b20a6 be3c796c52 mov esi,offset clr!StartupId (526c793c)
526b20ab 8975c4 mov dword ptr [ebp-3Ch],esi
526b20ae 8975cc mov dword ptr [ebp-34h],esi
526b20b1 56 push esi
526b20b2 50 push eax
526b20b3 52 push edx
526b20b4 51 push ecx
526b20b5 e85a580100 call clr!ETWTraceStartup::StartupTraceEvent (526c7914)
526b20ba c645fc02 mov byte ptr [ebp-4],2
526b20be 8b5d08 mov ebx,dword ptr [ebp+8]
526b20c1 8b03 mov eax,dword ptr [ebx]
526b20c3 8bcb mov ecx,ebx
526b20c5 ff5014 call dword ptr [eax+14h]
526b20c8 894508 mov dword ptr [ebp+8],eax
526b20cb 833d78a2c75200 cmp dword ptr [clr!g_IBCLogger (52c7a278)],0
526b20d2 0f8556633000 jne clr!PreStubWorker+0xbc (529b842e)
526b20d8 6a06 push 6
526b20da 8b4d08 mov ecx,dword ptr [ebp+8]
526b20dd e825ccfeff call clr!MethodDesc::CheckRestore (5269ed07)
526b20e2 8b4d08 mov ecx,dword ptr [ebp+8]
526b20e5 e886000000 call clr!MethodDesc::IsIntrospectionOnly (526b2170)
526b20ea 85c0 test eax,eax
526b20ec 0f8547633000 jne clr!PreStubWorker+0xd8 (529b8439)
526b20f2 8365ec00 and dword ptr [ebp-14h],0
526b20f6 8b4d08 mov ecx,dword ptr [ebp+8]
526b20f9 e880d6feff call clr!MethodDesc::IsVtableMethod (5269f77e)
526b20fe 85c0 test eax,eax
526b2100 0f8533020000 jne clr!PreStubWorker+0×100 (526b2339)
526b2106 ff75ec push dword ptr [ebp-14h]
526b2109 8b4d08 mov ecx,dword ptr [ebp+8]
526b210c e834fdffff call clr!MethodDesc::DoPrestub (526b1e45) ///////////// This line is compiling IL code into Native code

/////////////////start
526b2111 8945d8 mov dword ptr [ebp-28h],eax
526b2114 c645fc01 mov byte ptr [ebp-4],1
526b2118 56 push esi
526b2119 57 push edi
526b211a ff75bc push dword ptr [ebp-44h]
526b211d ff75b8 push dword ptr [ebp-48h]
526b2120 e8ef570100 call clr!ETWTraceStartup::StartupTraceEvent (526c7914)
526b2125 8365d000 and dword ptr [ebp-30h],0
526b2129 c645fc00 mov byte ptr [ebp-4],0
526b212d 8d4dd0 lea ecx,[ebp-30h]
526b2130 e8bcf6fdff call clr!SOIntolerantTransitionHandler::~SOIntolerantTransitionHandler (
526917f1)
526b2135 834dfcff or dword ptr [ebp-4],0FFFFFFFFh
526b2139 ff75dc push dword ptr [ebp-24h]
526b213c ff150c126952 call dword ptr [clr!_imp__SetLastError (5269120c)]
526b2142 8b45d8 mov eax,dword ptr [ebp-28h]

//////////// end

526b2145 e8f2f5fdff call clr!_EH_epilog3 (5269173c)
526b214a c20400 ret 4
526b214d 90 nop
526b214e 90 nop
526b214f 90 nop
clr!PrestubWorker_V1:
526b2150 5e pop esi
526b2151 0001 add byte ptr [ecx],al

 
0:000> k
ChildEBP RetAddr
0046e208 5001576f clrjit!Compiler::gtNewOperNode+0×2
0046e8f8 50012d28 clrjit!Compiler::impImportBlockCode+0x59b3
0046e974 50012e58 clrjit!Compiler::impImportBlock+0xf1
0046e98c 50012ea2 clrjit!Compiler::impImport+0xe8
0046e998 50012ed3 clrjit!Compiler::fgImport+0×22
0046e9a8 500132a2 clrjit!Compiler::compCompile+0×37
0046e9e4 50013396 clrjit!Compiler::compCompileHelper+0x2df
0046ea54 500134c9 clrjit!Compiler::compCompile+0x1ac
0046eb30 50015e4b clrjit!jitNativeCode+0x14e
0046eb54 5272a761 clrjit!CILJit::compileMethod+0×27
0046ebbc 5272a7ed clr!invokeCompileMethodHelper+0×65
0046ec04 5272a833 clr!invokeCompileMethod+0×31
0046ec6c 5272a608 clr!CallCompileMethodWithSEHWrapper+0x2e
0046f028 52793c03 clr!UnsafeJitFunction+0x3f9
0046f108 52793db0 clr!MethodDesc::MakeJitWorker+0×284
0046f178 526b2111 clr!MethodDesc::DoPrestub+0x45d
0046f1dc 00a00882 clr!PreStubWorker+0x12c
WARNING: Frame IP not in any known module. Following frames may be wrong.
0046f234 526921bb 0xa00882
0046f23c 5269e001 clr!CallDescrWorker+0×33
0046f254 00000000 clr!SigParser::GetElemType+0×28

 

Posted in Assembly, C# | Leave a comment