DynamoRIO / dynamorio

Dynamic Instrumentation Tool Platform
Other
2.66k stars 562 forks source link

preserve cs changes from far ctis and iret #823

Open derekbruening opened 9 years ago

derekbruening commented 9 years ago

From bruen...@google.com on June 21, 2012 15:23:39

this was PR 271317

For 64-bit DR in WOW64 ( issue #49 ) we need to handle application cs changes. Splitting out from that case.

For common/decode we fail to reproduce the bad-segment fault of a native lretw (66 cb), and my current SEH64 setup fails to recover from a fault on only the target of a retw: so for now that test uses a retw. Once we have faithful cs preservation we can re-enable lretw.

On x64 "push cs" is an invalid instr; for now I'm pushing 0x33. This case covers fixing that as well.

*\ TODO far cti must exit code cache to update dcontext_t.x86_mode

or can we use last_fragment (but be wary of empty_fragment)? are we planning on requiring exits to update ibl tls slots?

ifdef X64

set_x86_mode(dcontext, TEST(FRAG_32_BIT, targetf->flags));

endif

Note that if we don't require a cache exit on mode switches we need to change the call to get_reset_exit_stub() to first see what mode of fragment the thread is suspended inside.

Original issue: http://code.google.com/p/dynamorio/issues/detail?id=823

derekbruening commented 9 years ago

From bruen...@google.com on June 21, 2012 13:10:46

*\ TODO currently not switching modes on far cti

0x0000000074c1271b 41 ff 2e ljmp (% r14 ) end_pc = 0x0000000074c1271e

exit_branch_type=0x12 bb->exit_target=0x0000000021353a40 make_writable: pc 0x00000000154c3000-0x00000000154ed000, currently r--- committed make_unwritable: pc 0x00000000154c3000-0x00000000154ed000, currently rw-- committed make_writable: pc 0x00000000154c3000-0x00000000154ed000, currently r--- committed make_unwritable: pc 0x00000000154c3000-0x00000000154ed000, currently rw-- committed SYSLOG_WARNING: Encountered a far indirect jump emit_fragment: bb use ibl <0x0000000021353a40> exit_branch_type=0x12 target=0x0000000021353a40 l->flags=0x9012 Fragment 2963, tag 0x0000000074c126ce, flags 0x1000030, shared, size 94: [wow64cpu.dll~CpuSimulate+0x11e,~TurboDispatchJumpAddressStart-0x77] Entry into F2963(0x0000000074c126ce).0x000000002152d7a0 (shared)

Exit from sourceless ibl: bb jmp* [](target 0x0000000077649e69 not in cache) fragment_add_ibl_target tag 0x0000000077649e69, branch 2, F0

dispatch: target = 0x0000000077649e69

interp: start_pc = 0x0000000077649e69 new shared vm area: 0x0000000077620000-0x00000000776f6000 ---- module ntdll.dll 0x0000000077649e69 8b ff mov %edi -> %edi 0x0000000077649e6b 55 push %rbp %rsp -> %rsp 0xfffffff8(%rsp) 0x0000000077649e6c 8b ec mov %esp -> %ebp 0x0000000077649e6e ff 75 0c push 0x0c(%rbp) %rsp -> %rsp 0xfffffff8(%rsp) 0x0000000077649e71 ff 75 08 push 0x08(%rbp) %rsp -> %rsp 0xfffffff8(%rsp) 0x0000000077649e74 e8 fd 00 00 00 call $0x0000000077649f76 %rsp -> %rsp 0xfffffff8(%rsp) NOT following direct call from 0x0000000077649e74 to 0x0000000077649f76 end_pc = 0x0000000077649e79

derekbruening commented 9 years ago

From bruen...@google.com on June 21, 2012 13:16:33

Owner: ya...@google.com

derekbruening commented 9 years ago

From bruen...@google.com on June 22, 2012 15:46:05

to really be general, would have to stick selector somewhere and do far cti either on way to ibl or at end of special "far ibl". but for the issue #751 prototype, if we do the set_x86_mode(), then next fragment will be 32-bit, and will use the special fcache_enter that does a mode switch. so forget general far cti handling: not worth it for prototype. just need to have the post-exit code figure out whether a mode switch or not and call set_x86_mode(). need some code sequence to communicate address of full far opnd to DR. special mangling. or could get app addr of the instr and decode from DR and emulate to get opnd. need to record next app pc as well either in the standard way or as part of the new segment communication.

derekbruening commented 9 years ago

From bruen...@google.com on June 23, 2012 07:07:41

may actually be simpler to do more in-cache and forget about dispatch figuring out what's going on:

proposal: mangle far indirect cti to:

spill xcx movzx selector -> xcx lea xcx -32_bit_cs -> xcx jecxz to_32 64: (punting on handling cs o/w) mov target -> xcx jmp 64-bit ibl to-32: dcontext -> ecx mov $1 -> x86_mode_offs(ecx) mov target -> ecx far ind jmp through const mem that targets 32-bit ibl

if ind branch memref uses xcx, need to spill another reg

handles unlinking nicely: just need 2nd const mem for unlink ibl. for 32 to 64, can do far direct jmp

update state xl8 to handle movzx of selector failing

derekbruening commented 9 years ago

From bruen...@google.com on June 27, 2012 08:15:28

/* issue #823: handle far cti transitions. For now only handling known cs values

Owner: bruen...@google.com

derekbruening commented 9 years ago

From bruen...@google.com on June 27, 2012 08:18:01

*\ TODO far direct cti handling

can statically see whether it's a cs we expect

unfortunately selector is last so would mess up exit cti patching

how about:

spill eax dcontext -> eax mov $0 -> x86_mode_offs(eax) restore eax jmp 33:next next: regular exit cti jmp to app target

problem: stub size now depends not only on FRAG_ flags but link flags too! =>

=> going with treating as indirect and using far_ibl