Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Describing dynamically generated code with RtlAddFunctionTable on Windows x64

My application (written in Delphi, but that doesn't really matter) generates chunks of code dynamically (it contains a built-in compiler). In order to let exceptions on Windows x64 work correctly, I need to describe the generated functions via RtlAddFunctionTable. So far so good, I've changed the code generator to only use the official prolog and epilog forms, and I've encoded them by setting up a RUNTIME_FUNCTION containing UNWIND_INFO etc.

However, a (deliberate) access violation within the generated code still leads to immediate termination of the application, so apparently something is wrong. Using windbg, I see the following (where 0x4c5006f is the exception address):

0:000> .fnent 0x4c5006f 
Debugger function entry 00000000`05436910 for:

BeginAddress      = 00000000`00000000 
EndAddress        = 00000000`00000097
UnwindInfoAddress = 00000000`000000a0

However, it doesn't print the unwind info below this. I can see it from a memory window:

00000000`04c50000 53 56 57 55 41 54 41 55 41 56 41 57 48 83 ec 08  SVWUATAUAVAWH...
00000000`04c50010 49 89 ce 9b db e3 9b d9 3c 24 41 d9 ae e4 00 00  I.......<$A.....
00000000`04c50020 00 0f ae 5c 24 04 4c 89 f0 0f ae 90 e0 00 00 00  ...\$.L.........
00000000`04c50030 4d 8b be 28 01 00 00 4c 89 fd 49 8b 4f 08 48 85  M..(...L..I.O.H.
00000000`04c50040 c9 0f 84 1d 00 00 00 83 69 f0 01 0f 8f 13 00 00  ........i.......
00000000`04c50050 00 48 89 ca 4c 89 f1 48 83 ec 20 e8 70 41 ba fb  .H..L..H.. .pA..
00000000`04c50060 48 83 c4 20 48 33 c9 49 89 4f 08 49 8b 4f 08 48  H.. H3.I.O.I.O.H
00000000`04c50070 3b 09 ba 03 00 00 00 89 51 08 0f ae 54 24 04 9b  ;.......Q...T$..
00000000`04c50080 db e2 9b d9 2c 24 48 83 c4 08 41 5f 41 5e 41 5d  ....,$H...A_A^A]
00000000`04c50090 41 5c 5d 5f 5e 5b c3 90 90 90 90 90 90 90 90 90  A\]_^[..........
00000000`04c500a0 01 10 09 00 10 02 0c f0 0a e0 08 d0 06 c0 04 50  ...............P
00000000`04c500b0 03 70 02 60 01 30 00 00 00 00 00 00 00 00 00 00

At offset 4c500a0, you see the unwind info (01 10 09 00), then the nine entries corresponding to the following prolog:

  push  rbx
  push  rsi
  push  rdi
  push  rbp
  push  r12
  push  r13
  push  r14
  push  r15
  sub   rsp, $8

I'm passing 0x4c50000 as the base address to RtlAddFunctionTable. Why is windbg not printing the unwind info? Am I misunderstanding how the offsets work?

Compare with a regular Delphi function:

0:000> .fnent 0x79caa9
Debugger function entry 00000000`05436910 for:

BeginAddress      = 00000000`0039ca70
EndAddress        = 00000000`0039caaf
UnwindInfoAddress = 00000000`005304d8

Unwind info at 00000000`009304d8, a bytes
  version 1, flags 0, prolog 8, codes 3
  frame reg 5, frame offs 0
  00: offs 8, unwind op 3, op info 0    UWOP_SET_FPREG
  01: offs 5, unwind op 2, op info 5    UWOP_ALLOC_SMALL
  02: offs 1, unwind op 0, op info 5    UWOP_PUSH_NONVOL

Has anyone managed to get this to work in their own code and can point me into the right direction? Thanks!

like image 374
Frederik Slijkerman Avatar asked Jan 08 '14 14:01

Frederik Slijkerman


1 Answers

It turns out that a variety of my own bugs caused this to fail. I've discovered and fixed them and now unwinding works correctly. Specifically there were some cases where RtlDeleteFunctionTable was not called before RtlAddFunctionTable when the code was changed. Also it is important not to touch RSP in the function body: this makes complete sense but isn't really spelled out in the MSDN documentation.

like image 149
Frederik Slijkerman Avatar answered Oct 12 '22 22:10

Frederik Slijkerman