<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Mono Runtime Notes</title>
	<atom:link href="https://monoruntime.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://monoruntime.wordpress.com</link>
	<description>Mono Runtime Notes</description>
	<lastBuildDate>Mon, 11 May 2009 00:14:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='monoruntime.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>https://s0.wp.com/i/buttonw-com.png</url>
		<title>Mono Runtime Notes</title>
		<link>https://monoruntime.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="https://monoruntime.wordpress.com/osd.xml" title="Mono Runtime Notes" />
	<atom:link rel='hub' href='https://monoruntime.wordpress.com/?pushpress=hub'/>
	<item>
		<title>Exception Handling</title>
		<link>https://monoruntime.wordpress.com/2009/05/10/exception-handling/</link>
		<pubDate>Sun, 10 May 2009 15:59:43 +0000</pubDate>
		<dc:creator><![CDATA[kjambunathan]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[eh]]></category>
		<category><![CDATA[exception]]></category>
		<category><![CDATA[exception-handling]]></category>
		<category><![CDATA[MonoContext]]></category>
		<category><![CDATA[rethrow]]></category>
		<category><![CDATA[throw]]></category>
		<category><![CDATA[try-catch-finally]]></category>
		<category><![CDATA[undeniable-exception]]></category>
		<category><![CDATA[unhandled-exception]]></category>

		<guid isPermaLink="false">http://monoruntime.wordpress.com/?p=108</guid>
		<description><![CDATA[ExceptionHandling Table of Contents 1 Introduction 2 Example Assembly 3 Compile, Disassemble and Execute the Assembly 4 MonoContext struct 5 Code Generation for &#8216;throw&#8217; 6 Throwing Exceptions from Managed Code 7 Fault Recovery and Restoring Context 8 Code Generation for Try-Catch-Finally blocks 9 Exception Handler Internals 9.1 Handler Identification Pass 9.2 Handler Invocation Pass 10 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h1 class="title">ExceptionHandling</h1>
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#sec-1">1 Introduction </a></li>
<li><a href="#sec-2">2 Example Assembly </a></li>
<li><a href="#sec-3">3 Compile, Disassemble and Execute the Assembly </a></li>
<li><a href="#sec-4">4 MonoContext struct </a></li>
<li><a href="#sec-5">5 Code Generation for &#8216;throw&#8217; </a></li>
<li><a href="#sec-6">6 Throwing Exceptions from Managed Code </a></li>
<li><a href="#sec-7">7 Fault Recovery and Restoring Context </a></li>
<li><a href="#sec-8">8 Code Generation for Try-Catch-Finally blocks </a></li>
<li><a href="#sec-9">9 Exception Handler Internals </a>
<ul>
<li><a href="#sec-9.1">9.1 Handler Identification Pass </a></li>
<li><a href="#sec-9.2">9.2 Handler Invocation Pass </a></li>
</ul>
</li>
<li><a href="#sec-10">10 Call Filter </a></li>
<li><a href="#sec-11">11 References </a></li>
</ul>
</div>
</div>
<div id="outline-container-1" class="outline-2">
<h2>1 Introduction </h2>
<div id="text-1">
<p>
<b>(This an Initial Draft)</b>
</p>
<p>
In this article, I attempt to explore how Exception Handling (EH for<br />
convenience) is implemented in the Mono Runtime. This I do by<br />
considering a simple example assembly. As is customary, the<br />
exploration would be limited to only those aspects of Exception<br />
Handling that kicks in for the example under consideration.
</p>
<p>
Specifically we will be examining &#8211;
</p>
<ol>
<li>
Native code generation for</p>
<ol>
<li>
try-catch and try-finally blocks SEH blocks <sup><a class="footref" name="fnr.1" href="#fn.1">1</a></sup>
</li>
<li>
throw CIL instruction</p>
</li>
</ol>
</li>
<li>
Exception Handling</p>
<ol>
<li>
Fault Handler Identification
</li>
<li>
Fault Handling and Recovery</p>
</li>
</ol>
</li>
</ol>
</div>
</div>
<div id="outline-container-2" class="outline-2">
<h2>2 Example Assembly </h2>
<div id="text-2">
<p>
Consider the example down below.
</p>
<p>
The method Test.ThrowException () unconditionally throws an<br />
exception.
</p>
<p>
The method Test.Main () invokes ThrowException () within a protected<br />
block. The protected block has a catch handler that swallows the<br />
thrown exception and a finally handler that waits on user input<br />
before exiting.
</p>
<p>
The property Test.Path and enum Test.MARKER are defined more for<br />
convenience. The specific convenience they offer is &#8211;
</p>
<ol>
<li>
The enum values of Test.Marker are &#8216;magical&#8217;. These magical<br />
values would help us easily identify try, catch, finally blocks<br />
in the generated native code.</p>
</li>
<li>
The property Test.Path traces and logs the control flow.
</li>
<li>
Last but not the least, they help us have non-empty<br />
try-catch-finally blocks.</p>
<pre class="example">
  // file ExceptionHandling.cs

  using System;

  class Test
  {
      enum MARKER
      {
          TRY_CATCH_FINALLY_BEGIN = 0x1111,
          TRY_BEGIN = 0x2222,
          TRY_END = 0x3333,
          CATCH_BEGIN = 0x4444,
          CATCH_END = 0x5555,
          FINALLY_BEGIN = 0x6666,
          FINALLY_END = 0x7777,
          TRY_CATCH_FINALLY_END = 0x8888
      }

      private static MARKER Path {
          set {
              Console.WriteLine (value);
          }
      }

      private static void ThrowException ()
      {
          throw new Exception ("");
      }

      static void Main() {
          Path = MARKER.TRY_CATCH_FINALLY_BEGIN;

          try {
              Path = MARKER.TRY_BEGIN;

              ThrowException ();

              Path = MARKER.TRY_END;
          }
          catch (Exception e) {
              Path = MARKER.CATCH_BEGIN;

              Path = MARKER.CATCH_END;
          }

          finally {
              Path = MARKER.FINALLY_BEGIN;
              Path = MARKER.FINALLY_END;

              Console.ReadLine ();
         }

         Path = MARKER.TRY_CATCH_FINALLY_END;
      }
  }
</pre>
</li>
</ol>
</div>
</div>
<div id="outline-container-3" class="outline-2">
<h2>3 Compile, Disassemble and Execute the Assembly </h2>
<div id="text-3">
<pre class="example">
  $ mcs ExceptionHandling.cs

  ExceptionHandling.cs(43): warning CS0162: Unreachable code detected
  ExceptionHandling.cs(38): warning CS0168: The variable `e' is declared
  but never used
</pre>
<p>
The dump down below shows the disassembly of methods &#8211;<br />
ThrowException () and Main () in the generated CIL executable.
</p>
<p>
Pay specific attention to the highlighted portions.
</p>
<pre class="example">

  $ ildasm ExceptionHandling.exe

  // Disassembly of Test.ThrowException () and Test.Main ()

   .method private static hidebysig void ThrowException() cil managed
   {
       // Start of method header: 2104
       .maxstack  8
   ?L2105:
       ldsfld     class System.String [mscorlib]System.String::Empty
       newobj     instance void [mscorlib]System.Exception::.ctor(class System.String)
       throw
   }
   .method private static hidebysig void Main() cil managed
   {
       // Start of method header: 2110
       .entrypoint
       .maxstack  7
       .locals    init (class [mscorlib]System.Exception)
   ?L211c:
       ldc.i4     4369
       call       void Test::set_Path(valuetype Test/MARKER)

                                                              --------------------+
   ?L2126:                                                    -------+            |
       ldc.i4     8738                                               |            |
       call       void Test::set_Path(valuetype Test/MARKER)         |            |
       call       void Test::ThrowException()                        |            |
       ldc.i4     13107                                              | SEHBlock1  |
       call       void Test::set_Path(valuetype Test/MARKER)         | Try-Catch  |
       leave      ?L2179                                             |  Block     |
                                                              -------+            |
                                                                     |            |
   ?L2144:                                                           |            |
       stloc.0                                                       |            |
       ldc.i4     17476                                              |            |
       call       void Test::set_Path(valuetype Test/MARKER)         |            | SEHBlock2
       ldc.i4     21845                                              |            |
       call       void Test::set_Path(valuetype Test/MARKER)         |            | Try-Finally
       leave      ?L2179                                      -------+            |  Block
                                                                                  |
                                                              --------------------+
                                                                                  |
   ?L215e:                                                                        |
       ldc.i4     26214                                                           |
       call       void Test::set_Path(valuetype Test/MARKER)                      |
       ldc.i4     30583                                                           |
       call       void Test::set_Path(valuetype Test/MARKER)                      |
       call       class System.String [mscorlib]System.Console: ReadLine()        |
       pop                                                                        |
       endfinally                                                                 |
                                                             ----------------------

   ?L2179:
       ldc.i4     34952
       call       void Test::set_Path(valuetype Test/MARKER)
       ret
       .try ?L2126 to ?L2144 catch [mscorlib]System.Exception handler ?L2144 to ?L215e
       .try ?L2126 to ?L215e finally handler ?L215e to ?L2179
   }

</pre>
<pre class="example">
  $ mono ExceptionHandling.exe

  TRY_CATCH_FINALLY_BEGIN
  TRY_BEGIN
  CATCH_BEGIN
  CATCH_END
  FINALLY_BEGIN
  FINALLY_END

  TRY_CATCH_FINALLY_END
</pre>
</div>
</div>
<div id="outline-container-4" class="outline-2">
<h2>4 MonoContext struct </h2>
<div id="text-4">
<p>
Before we proceed ahead let&#8217;s see what a MonoContext structure is.
</p>
<pre class="example">

  typedef struct {
      guint32 eax;
      guint32 ebx;
      guint32 ecx;
      guint32 edx;
      guint32 ebp;
      guint32 esp;
      guint32 esi;
      guint32 edi;
      guint32 eip;
  } MonoContext;

</pre>
<p>
There is nothing surprising in the definition here. It merely<br />
represents the machine state at a given point in time.
</p>
</div>
</div>
<div id="outline-container-5" class="outline-2">
<h2>5 Code Generation for &#8216;throw&#8217; </h2>
<div id="text-5">
<p>
Let&#8217;s now examine the native code generated by the JIT compiler for<br />
ThrowException ().
</p>
<p>
In <b>mono_method_to_ir ()</b>, <b>CEE_THROW</b> is mapped in to <b>OP_THROW</b> and<br />
<b>OP_NOT_REACHED</b> intermediate sequence.
</p>
<p>
In <b>mono_arch_output_basic_block ()</b>, <b>OP_THROW</b> is translated into a push<br />
of the exception object and a native call to<br />
<b>mono_arch_throw_exception ()</b>.
</p>
<pre class="example">
  Native code for ThrowException ()

  @ 0xb797b010 - @ 0xb797b038:
  push   ebp
  mov    ebp,esp
  sub    esp,0x8
  mov    eax,0x28fe0
  sub    esp,0x8
  push   0x2bcd0
  push   0x200002d
  call   0x80b6cb0     // mono_create_corlib_exception_1 ()
  add    esp,0x10
                                                      ----+
  push   eax           // push exception object           |  'throw'
  call   0xb7bbccf8    // mono_arch_throw_exception ()    |
                                                      ----+
  leave
  ret
</pre>
</div>
</div>
<div id="outline-container-6" class="outline-2">
<h2>6 Throwing Exceptions from Managed Code </h2>
<div id="text-6">
<p>
In the previous section we saw that a &#8216;throw&#8217; in CIL is mapped to a<br />
native method <b>mono_arch_throw_exception ()</b>.
</p>
<p>
<b>mono_arch_throw_exception ()</b> is an icall and maps to following code<br />
sequence.
</p>
<p>
The routine merely saves the context information on to the stack and<br />
invokes <b>throw_exception ()</b>. Note that the EIP of the dumped context<br />
is within the scope of the function that threw the exception.
</p>
<p>
It is the <b>throw_exception ()</b> that kicks off the exception handling<br />
path.
</p>
<pre class="example">
  Native code for mono_arch_throw_exception ()

  @ 0xb7bbccf8 - 0xb7bbcd0:
  push   esp
  push   DWORD PTR [esp+4]     // point of throw
  push   DWORD PTR [esp+12]    // exception object
  push   ebp
  push   edi
  push   esi
  push   ebx
  push   edx
  push   ecx
  push   eax
  call   0x8107e00     // throw_exception ()
  int3
</pre>
<pre class="example">

 // Snippet code from throw_exception ()

static void
throw_exception (unsigned long eax, unsigned long ecx, unsigned long edx,
                     unsigned long ebx, unsigned long esi, unsigned long edi,
                 unsigned long ebp, MonoObject *exc, unsigned long eip,
                 unsigned long esp, gboolean rethrow)
{
    static void (*restore_context) (MonoContext *);
    MonoContext ctx;

    /* Pop argument and return address */
    ctx.esp = esp + (2 * sizeof (gpointer));
    ctx.eip = eip;
    ctx.ebp = ebp;
    ctx.edi = edi;
    ctx.esi = esi;
    ctx.ebx = ebx;
    ctx.edx = edx;
    ctx.ecx = ecx;
    ctx.eax = eax;

    if (mono_object_isinst (exc, mono_defaults.exception_class)) {
        MonoException *mono_ex = (MonoException*)exc;
        if (!rethrow)
            mono_ex-&gt;stack_trace = NULL;
    }

    /* adjust eip so that it point into the call instruction */
    ctx.eip -= 1;

    mono_handle_exception (&amp;ctx, exc, (gpointer)eip, FALSE);

    restore_context = mono_arch_get_restore_context ();:
    restore_context (&amp;ctx);     // mono_arch_get_restore_context ()


    g_assert_not_reached ();
}
</pre>
<p>
<b>throw_exception ()</b> essentially does the following &#8211;
</p>
<ol>
<li>
Marshals a MonoContext struct that is representative of the<br />
machine state at the point of exception. It then kicks off<br />
exception handling via <b>mono_handle_exception ()</b>.</p>
<p>
Shortly we will examine handling of exceptions in detail. For now<br />
it is sufficient to remark that the context struct is both an<br />
&#8216;in&#8217; and an &#8216;out&#8217; param of <b>mono_handle_exception ()</b>. In essence<br />
the exception handling mechanism examines the current machine<br />
state and also advises a machine state for resumption of normal<br />
control.
</p>
</li>
<li>
Restores the execution context to that advised by the EH<br />
mechanism and transfers control to the new EIP address.</p>
</li>
</ol>
</div>
</div>
<div id="outline-container-7" class="outline-2">
<h2>7 Fault Recovery and Restoring Context </h2>
<div id="text-7">
<pre class="example">
  Native code for mono_arch_get_restore_context ()

  @0xb7bbcc38 - @0xb7bbcc50:
  0xb7bbcc38:  mov    eax,DWORD PTR [esp+4]    // eax = ctx
  0xb7bbcc3c:  mov    edx,DWORD PTR [eax+32]   // edx = ctx-&gt;eip
  0xb7bbcc3f:  mov    ebx,DWORD PTR [eax+4]    // ebx = ctx-&gt;ebx
  0xb7bbcc42:  mov    edi,DWORD PTR [eax+28]   // edi = ctx-&gt;edi
  0xb7bbcc45:  mov    esi,DWORD PTR [eax+24]   // esi = ctx-&gt;esi
  0xb7bbcc48:  mov    esp,DWORD PTR [eax+20]   // esp = ctx-&gt;esp
  0xb7bbcc4b:  mov    ebp,DWORD PTR [eax+16]   // ebp = ctx-&gt;ebp
  0xb7bbcc4e:  jmp    edx                      // jump to ctx-&gt;eip
</pre>
<p>
Note that the registers eax and edx aren&#8217;t restored.
</p>
</div>
</div>
<div id="outline-container-8" class="outline-2">
<h2>8 Code Generation for Try-Catch-Finally blocks </h2>
<div id="text-8">
<p>
Before we proceed to look at specifics of exception handling<br />
mechanism, let&#8217;s look at the native code generated for<br />
Try-Catch-Finally block in Main ().
</p>
<p>
In <b>method_to_ir ()</b>, a &#8216;leave&#8217; instruction is translated in to zero<br />
or more <b>OP_CALL_HANDLER</b> followed by an <b>OP_BR</b>. <b>OP_CALL_HANDLER</b><br />
arranges for a call to into the &#8216;finally&#8217; block while <b>OP_BR</b> arranges<br />
for control to flow out of the current SEHBlock.
</p>
<p>
In case of &#8216;leave&#8217; instruction that occur within a catch handler,<br />
prior to arranging for calling of &#8216;finally&#8217; handlers as described<br />
above the following special case handling for ThreadAbortException<br />
is done &#8211; If the running thread has a ThreadAbortException pending,<br />
it is rethrown immediately <sup><a class="footref" name="fnr.2" href="#fn.2">2</a></sup>.
</p>
<p>
Furthermore, catch (and filter handlers) require an exception object<br />
be passed in the event of an exception. These are passed via<br />
specially allocated variables on the method stack.
</p>
<pre class="example">
  Native code for Main ()

  @0xb796e280 - @0xb796e35d:

  0xb796e280:  push   ebp
  0xb796e281:  mov    ebp,esp
  0xb796e283:  sub    esp,0x28
  0xb796e286:  mov    DWORD PTR [ebp-24],0x0

  0xb796e28d:  sub    esp,0xc
  0xb796e290:  push   0x1111
  0xb796e295:  call   0xb796e388
  0xb796e29a:  add    esp,0x10

  0xb796e29d:  sub    esp,0xc                               &lt;------+
  0xb796e2a0:  push   0x2222                                       |
  0xb796e2a5:  call   0xb796e388                                   |
  0xb796e2aa:  add    esp,0x10                                     |
                                                                   |
  0xb796e2ad:  call   0xb797b010  // ThrowException ()             |
                                                                   |
                                                                   |  C# try block
  0xb796e2b2:  sub    esp,0xc                                      |
  0xb796e2b5:  push   0x3333                                       |
  0xb796e2ba:  call   0xb796e360                                   |
  0xb796e2bf:  add    esp,0x10                                     |
                                                                   |
                                                                   |
  0xb796e2c2:  sub    esp,0xc                                      |
  0xb796e2c5:  call   0xb796e31f  // call finally block            |
  0xb796e2ca:  add    esp,0xc                                      |
  0xb796e2cd:  jmp    0xb796e34b                            &lt;------+


                                                            &lt;------+
  0xb796e2d2:  mov    eax,DWORD PTR [ebp-20]   // eax = exception  |
  0xb796e2d5:  mov    eax,DWORD PTR [ebp-20]                       |
  0xb796e2d8:  mov    DWORD PTR [ebp-24],eax                       |
                                                                    |
  0xb796e2db:  sub    esp,0xc                                      |
  0xb796e2de:  push   0x4444                                       |
  0xb796e2e3:  call   0xb796e388                                   |
  0xb796e2e8:  add    esp,0x10                                     |
                                                                   |
  0xb796e2eb:  sub    esp,0xc                                      |  C# catch block
  0xb796e2ee:  push   0x5555                                       |
  0xb796e2f3:  call   0xb796e388                                   |
  0xb796e2f8:  add    esp,0x10                                     |
                                                                   |
  0xb796e2fb:  call   0xb797b038  // __icall_wrapper_mono_thread_ge|_undeniable_exception
  0xb796e300:  mov    DWORD PTR [ebp-28],eax                       |
  0xb796e303:  cmp    DWORD PTR [ebp-28],0x0                       |
  0xb796e307:  je     0xb796e312                                   |
  0xb796e309:  mov    eax,DWORD PTR [ebp-28]                       |
  0xb796e30c:  push   eax                                          |
  0xb796e30d:  call   0xb7bbccf8  // get_throw_exception ()        |
  0xb796e312:  sub    esp,0xc                                      |
  0xb796e315:  call   0xb796e31f  // call finally block            |
  0xb796e31a:  add    esp,0xc                                      |
  0xb796e31d:  jmp    0xb796e34b                            &lt;------+

                                                            &lt;------+
  0xb796e31f:  mov    DWORD PTR [ebp-4],esp                        |
                                                                   |
  0xb796e322:  sub    esp,0xc                                      |
  0xb796e325:  push   0x6666                                       |
  0xb796e32a:  call   0xb796e388                                   |
  0xb796e32f:  add    esp,0x10                                     |
                                                                   | finally block
  0xb796e332:  sub    esp,0xc                                      |
  0xb796e335:  push   0x7777                                       |
  0xb796e33a:  call   0xb796e388                                   |
  0xb796e33f:  add    esp,0x10                                     |
                                                                   |
  0xb796e342:  call   0xb797b098  // Console.ReadLine              |
  0xb796e347:  mov    esp,DWORD PTR [ebp-4]                        |
  0xb796e34a:  ret                                         &lt;-------+


                                                          &lt;--------+
  0xb796e34b:  sub    esp,0xc                                      |
  0xb796e34e:  push   0x8888                                       | Block 'following' the try block
  0xb796e353:  call   0xb796e360                                   |
  0xb796e358:  add    esp,0x10                            &lt;--------+


  0xb796e35b:  leave
  0xb796e35c:  ret
</pre>
</div>
</div>
<div id="outline-container-9" class="outline-2">
<h2>9 Exception Handler Internals </h2>
<div id="text-9">
<p>
Exception Handling is done in following passes &#8211;
</p>
<ol>
<li>
Handler Identification Pass &#8211; In this pass, the runtime walks the<br />
stack and tries to identify a block that is willing to handle the<br />
exception.</p>
</li>
<li>
Handler Invocation Pass &#8211; In this pass the runtime invokes fault<br />
and finally handlers on all blocks that intervene between the<br />
point at which the exception is thrown and the point at which the<br />
exception is handled. Subsequently it transfers control to the<br />
handler identified in part 1.</p>
</li>
</ol>
<p>For the sake of completion, the pseudocode for Handler<br />
Identification and Handler Invocation Passes is given below.
</p>
<p>
Before one proceeds to examine the pseudo code, it needs to be borne<br />
in mind that the entries in a Method&#8217;s Exception Handler Table are<br />
stored in such as way that a nested protected block always occurs<br />
before any of it&#8217;s parent protected block.
</p>
<p>
The following specifics may be noted in the pseudo-code
</p>
<ol>
<li>
Stack is merely walked.</p>
</li>
</ol>
<p>In the Handler Identification Pass,
</p>
<ol>
<li>
The exception object is passed to the filtering code by storing<br />
it in a pre-defined location on the current stack frame.</p>
</li>
<li>
The stack walk is terminated as soon as a catch or a filter<br />
handler that is willing to handle the exception is identified.</p>
</li>
<li>
Failure to locate a handler causes a FALSE to be returned.</p>
</li>
</ol>
<p>In the Handler Invocation Pass,
</p>
<ol>
<li>
The intervening finally and fault handlers are called via an<br />
architecture specific stub &#8211;  <b>mono_arch_get_call_filter ()</b></p>
</li>
<li>
Once the matching filter or catch handler is identified, the EIP<br />
in ctx is adjusted to point to the handler address using the macro</p>
<p>
<b>MONO_CONTEXT_SET_IP (ctx, ei-&gt;handler_start)</b>
</p>
<p>
The exception object is passed to the catch handler by storing it<br />
in a pre-defined location on the current stack frame
</p>
<p>
As was earlier mentioned, it is the responsibility of<br />
<b>throw_exception ()</b> to actually resume exception at the handler.
</p>
</li>
</ol>
</div>
<div id="outline-container-9.1" class="outline-3">
<h3>9.1 Handler Identification Pass </h3>
<div id="text-9.1">
<pre class="example">

    // Handler Identification Pass
    // test_only == FALSE for Handler Invocation Pass


    mono_handle_internal_excpetion (MonoContext *ctx, gpointer obj,
       gpointer original_ip, gboolean test_only, gint32 * out_filter_idx)

    MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id)
    MonoLMF *lmf = mono_get_lmf ()

    *out_filter_idx = -1
    filter_idx = 0
    initial_ctx = *ctx

    MonoJitInfo rji = {0}

   call_filter = mono_arch_get_call_filter ();


    while (1)
        MonoContext new_ctx;
        guint32 free_stack;

        ji = mono_find_jit_info (domain, jit_tls, &amp;rji, &amp;rji, ctx,
                &amp;new_ctx, NULL, &amp;lmf, NULL, NULL)

        assert (ji)
                                                                  -----------+
        if (ji == -1)                                                        | Handler not found
            return FALSE                                          -----------+

        if !(ji-&gt;code_start &lt;= MONO_CONTEXT_GET_IP (ctx)
               &lt;= ji-&gt;code_start + ji-&gt;code_size)

            // skip native frame
            *ctx = new_ctx
            continue;

        ++ frame_count

        if (!ji-&gt;num_clauses)
            // not within a protected block
            *ctx = new_ctx
            continue;

        foreach MonoJitExceptionInfo *ei in &amp;ji-&gt;clauses
            filtered = FALSE
            if (!(ei-&gt;try_start &lt;= IP &lt;= ei-&gt;try_end))
                continue;

            MonoClass *catch_class = get_exception_class (ei, ji, ctx)
                                                                  -----------+
            if (ei-&gt;flags == MONO_EXCEPTION_CLAUSE_NONE | FILTER) o          | Pass Exception Object
                (*MONO_CONTEXT_GET_BP (ctx) + ei-&gt;exvar_offset) = obj        |
                                                                  -----------+
            if (ei-&gt;flags == MONO_EXCEPTION_CLAUSE_FILTER)
                filtered = call_filter (ctx, ei-&gt;data.filter)

                if (filtered &amp;&amp; out_filter_idx)
                    *out_filter_idx = filter_idx;
                ++ filter_idx;
                                                                 ------------+
            if (ei-&gt;flags == MONO_EXCEPTION_CLAUSE_NONE &amp;&amp;                   | Handler Identified
                mono_object_isinst (obj, catch_class)) || filtered           |
                return TRUE;                                     ------------+

            continue;

        *ctx = new_ctx;
        continue;

</pre>
</div>
</div>
<div id="outline-container-9.2" class="outline-3">
<h3>9.2 Handler Invocation Pass </h3>
<div id="text-9.2">
<pre class="example">
    // Handler Invocation Pass
    // test_only == FALSE for Handler Invocation Pass

    mono_handle_internal_excpetion (MonoContext *ctx, gpointer obj,
       gpointer original_ip, gboolean test_only, gint32 * out_filter_idx)


   MonoJitInfo rji;
   MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id)
   MonoLMF *lmf = mono_get_lmf ();


   MonoContext ctx_cp = *ctx                                     ------------+
   if (!mono_handle_exception_internal (&amp;ctx_cp, obj,                        |
               original_ip, TRUE, &amp;first_filter_idx)                         | Unhandled Exception
       mono_unhandled_exception (obj)                            ------------+

   if (out_filter_idx)
       *out_filter_idx = -1

   filter_idx = 0
   initial_ctx = *ctx
   rji = {0}

   while (1)
       MonoContext new_ctx;
       guint32 free_stack;

       ji = mono_find_jit_info (domain, jit_tls, &amp;rji, &amp;rji, ctx, &amp;new_ctx,
               NULL, &amp;lmf, NULL, NULL)

       assert (ji) // Exception inside fucntion with unwind info


       if ji == -1
           *ctx = new_ctx
           *(mono_get_lmf_addr ()) = lmf
           jit_tls-&gt;abort_func (obj)
           g_assert_not_reached ();


       if ! (ji-&gt;code_start &lt;= MONO_CONTEXT_GET_IP (ctx) &lt;= ji-&gt;code_start + ji-&gt;code_size)

           // exception in native code. We got back to managed code using LMF
           *ctx = new_ctx
           conitnue;

       ++ frame_count

       if (!ji-&gt;num_clauses)
           *ctx = new_ctx
           continue;

       foreach MonoJitExceptionInfo *ei in ji-&gt;clauses [i]
           filtered = FALSE

           if ! (ei-&gt;try_start &lt;= MONO_CONTEXT_GET_IP (ctx) &lt;= ei-&gt;try_end)
               continue;

           MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx)
                                                                 ------------+
           if (ei-&gt;flags == MONO_EXCEPTION_CLAUSE_NONE | FILTER)             | Pass Exception Object
               *(MONO_CONTEXT_GET_BP (ctx) + ei-&gt;exvar_offset) = obj         |
                                                                 ------------+
           if (ei-&gt;flags == MONO_EXCEPTION_CLAUSE_FILTER)
               filtered = (filter_idx == first_filter_idx)
               filter_idx ++

           if (ei-&gt;flags == MONO_EXCEPTION_CLAUSE_NONE &amp;&amp;
               mono_object_isinst (obj, catch_class) || filtered)
                                                                  ------------+
               MONO_CONTEXT_SET_IP (ctx, ei-&gt;handler_start)                   | Update EIP for Fault Recovery
               *(mono_get_lmf_addr ()) = lmf                                  |
                                                                  ------------+

                                                                  ------------+
           if (ei-&gt;flags == MONO_EXCEPTION_CLAUSE_FAULT)                      |
               call_filter (ctx, ei-&gt;handler_start)                           |
                                                                              | Call fault and finally handlers
           if (ei-&gt;flags == MONO_EXCEPTION_CLAUSE_FINALLY)                    |
               call_filter (ctx, ei-&gt;handler_start)                           |
                                                                  ------------+
           continue;
       *ctx = new_ctx
       continue;
</pre>
</div>
</div>
</div>
<div id="outline-container-10" class="outline-2">
<h2>10 Call Filter </h2>
<div id="text-10">
<pre class="example">
  // Native code for mono_arch_get_call_filter ()
  // @ 0xb7bbccb8 - 0xb7bbcd7c

  push   ebp
  mov    ebp,esp
  push   ebx
  push   edi
  push   esi
  mov    eax,DWORD PTR [ebp+8]     // eax = ctx
  mov    ecx,DWORD PTR [ebp+12]    // ecx = exception handler
  push   ebp                       // save ebp
  mov    ebp,DWORD PTR [eax+16]    // ebp = ctx-&gt;ebp
  mov    ebx,DWORD PTR [eax+4]     // ebx = ctx-&gt;ebx
  mov    esi,DWORD PTR [eax+24]    // esi = ctx-&gt;esi
  mov    edi,DWORD PTR [eax+28]    // edi = ctx-&gt;edi
  mov    edx,esp
  and    esp,0xfffffff0            // align esp
  sub    esp,0x8
  push   edx                       // save original esp
  call   ecx                       // call handler
  pop    esp                       // restore esp
  pop    ebp                       // restore ebp
  pop    esi                       // restore esi
  pop    edi                       // restore edi
  pop    ebx                       // restore ebx
  leave
  ret
</pre>
</div>
</div>
<div id="outline-container-11" class="outline-2">
<h2>11 References </h2>
<div id="text-11">
<p><a href="http://www.mono-project.com/Mono:Runtime:Documentation:ExceptionHandling">Exception Handling in Mono Runtime</a>
</p>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="footnotes-text">
<p class="footnote"><sup><a class="footnum" name="fn.1" href="#fnr.1">1</a></sup> <a href="https://monoruntime.wordpress.com/2009/04/17/marshalling-in-runtime/">Marshalling In Runtime</a> talks of use of filter blocks with Runtime<br />
Invoke Wrappers
</p>
<p class="footnote"><sup><a class="footnum" name="fn.2" href="#fnr.2">2</a></sup> <a href="http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx">Undeniable Exception Propagation</a>
</p>
</div>
</div>
<div id="postamble">
<p class="author"> Author: Jambunathan K. Consult <a href="https://monoruntime.wordpress.com/about/">About page</a> for<br />
 my Inbox information.</p>
<p class="date"> Date: 2009-05-10 21:16:46 IST</p>
<p>HTML generated by org-mode 6.17c in emacs 21</p>
</div>
]]></content:encoded>
		
		<media:content url="http://0.gravatar.com/avatar/6f3696c2b1298455c3643afd255ad03d?s=96&#38;d=https%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">kjambunathan</media:title>
		</media:content>
	</item>
	</channel>
</rss>
