Re: [DynInst_API:] Incorrect offset calculation for jmp targets


Date: Fri, 05 Sep 2014 11:05:22 -0500
From: Bill Williams <bill@xxxxxxxxxxx>
Subject: Re: [DynInst_API:] Incorrect offset calculation for jmp targets
On 09/04/2014 11:50 AM, Mohamed Elsabagh wrote:
I am using Dyninst to insert a call at the entry point of each local
function in a program. This used to work fine with versions prior to
8.2. However, with Dyninst 8.2, it seems that some jump targets were
shifted yet their corresponding jump sites were not updated. Dyninst 8.2
also insert an additional jmp that consumes more bytes than available.
Please see below.

Before instrumentation (works):
   99fa40: 48 8b 15 69 d6 87 00  mov    0x87d669(%rip),%rdx
   99fa47: 31 c0                 xor    %eax,%eax
   99fa49: 48 85 d2              test   %rdx,%rdx
   99fa4c: 74 1e                 je     99fa6c <sinh@plt+0x59b85c>
   99fa4e: 48 83 ec 08           sub    $0x8,%rsp
   99fa52: be 01 00 00 00        mov    $0x1,%esi
   99fa57: bf a0 76 68 01        mov    $0x16876a0,%edi
   99fa5c: ff d2                 callq  *%rdx
   99fa5e: 85 c0                 test   %eax,%eax
   99fa60: 0f 95 c0              setne  %al
   99fa63: 48 83 c4 08           add    $0x8,%rsp
   99fa67: 0f b6 c0              movzbl %al,%eax
   99fa6a: f7 d8                 neg    %eax
->*99fa6c: *f3**c3**repz**retq
*99fa6e*: 66 90                 xchg   %ax,%ax
->*99fa70*: 48 8b 15 39 d6 87 00  mov    0x87d639(%rip),%rdx

And there are two jump sites at:
   58c89d: e9 ce 31 41 00        jmpq *99fa70*
   ...
   58c8bd: e9 ae 31 41 00        jmpq *99fa70*
*
*
-------------------------------------------------------------------------

After instrumentation using Dyninst 8.1 (works):

   99fa40: e9 7c 04 05 01        jmpq   19efec1 <targ99fa40_dyninst>
   99fa45: 87 00                 xchg   %eax,(%rax)
   99fa47: 31 c0                 xor    %eax,%eax
   99fa49: 48 85 d2              test   %rdx,%rdx
   99fa4c: 74 1e                 je     99fa6c <targ99fa40+0x2c>
   99fa4e: e9 7d 05 05 01        jmpq   19effd0 <targ99fa40_dyninst+0x10f>
   99fa53: 01 00                 add    %eax,(%rax)
   99fa55: 00 00                 add    %al,(%rax)
   99fa57: bf a0 76 68 01        mov    $0x16876a0,%edi
   99fa5c: ff d2                 callq  *%rdx
   99fa5e: e9 7d 05 05 01        jmpq   19effe0 <targ99fa40_dyninst+0x11f>
   99fa63: 48 83 c4 08           add    $0x8,%rsp
   99fa67: 0f b6 c0              movzbl %al,%eax
   99fa6a: f7 d8                 neg    %eax
->*99fa6c*: f3 c3                 repz retq
*99fa6e*: 66 90                 xchg   %ax,%ax
->*99fa70*: 48 8b 15 39 d6 87 00  mov    0x87d639(%rip),%rdx

And the two aforementioned jump sites are intact.

-------------------------------------------------------------------------

After instrumentation with Dyninst 8.2 (crashes at 99fa70):
   99fa40: e9 51 16 05 01        jmpq   19f1096 <targ99fa40_dyninst>
   99fa45: 87 00                 xchg   %eax,(%rax)
   99fa47: 31 c0                 xor    %eax,%eax
   99fa49: 48 85 d2              test   %rdx,%rdx
   99fa4c: 74 1e                 je     99fa6c <targ99fa40+0x2c>
   99fa4e: e9 2e 17 05 01        jmpq   19f1181 <targ99fa40_dyninst+0xeb>
   99fa53: 01 00                 add    %eax,(%rax)
   99fa55: 00 00                 add    %al,(%rax)
   99fa57: bf a0 76 68 01        mov    $0x16876a0,%edi
   99fa5c: ff d2                 callq  *%rdx
   99fa5e: e9 2e 17 05 01        jmpq   19f1191 <targ99fa40_dyninst+0xfb>
   99fa63: 48 83 c4 08           add    $0x8,%rsp
   99fa67: 0f b6 c0              movzbl %al,%eax
   99fa6a: f7 d8                 neg    %eax
->*99fa6c*: e9 2e 17 05 01        jmpq   19f119f <targ99fa40_dyninst+0x109>
->*99fa71*: 8b 15 39 d6 87 00     mov    0x87d639(%rip),%edx

But the two jump sites are still pointing at 99fa70:
   19c70f1: e9 7a 89 fd fe        jmpq *99fa70*
   ...
   19c71b6: e9 b5 88 fd fe        jmpq *99fa70*
*
*
The instrumented process instantly crashes at 99fa70 once any of the two
jumps are taken. The program executes correctly if I manually patch the
jump sites to point at the correct target 99fa71.

Also, as you can notice, Dyninst 8.2 has inserted an *additional* jmp at
99fa6c that consumed 5 bytes, while the original block had a space for
only 4 bytes. Dyninst 8.1 did not insert that jmp and 99fa6c ... 99fa70
were left intact.

Is this a known issue? Is there a workaround?

Mo--

In the course of doing some optimization work (avoiding unnecessary trap-based instrumentation) we introduced the possibility of bugs of this type, though I thought we'd gotten them all before the release. If you can send me either mutator/mutatee code, or a log of your mutator running with DYNINST_DEBUG_SPRINGBOARD=1 in your environment, I should be able to diagnose this and get you a patch (and get the patched 8.2 posted soon).

Sorry for the inconvenience.

Thank you,
Mo


_______________________________________________
Dyninst-api mailing list
Dyninst-api@xxxxxxxxxxx
https://lists.cs.wisc.edu/mailman/listinfo/dyninst-api



--
--bw

Bill Williams
Paradyn Project
bill@xxxxxxxxxxx
[← Prev in Thread] Current Thread [Next in Thread→]