dr_insert_clean_call after instr?

118 views
Skip to first unread message

Jordan Conrad

unread,
Jan 18, 2022, 10:15:25 PM1/18/22
to DynamoRIO Users
Hi I'm wondering how to insert a clean call when instr_get_next(instr) == NULL. Note that instr is always a call instruction

I want the basic block to go from looking like this

mov rcx, [rsi+8]
call (some function)
**end of bb

To this

mov rcx, [rsi+8]
call 1st instrumentation
call (some function)
call 2nd instrumentation
**end of bb

I've tried a few different approaches like inserting a meta instruction onto the end of the instruction list and adding a clean call to that. However, when I did that it behaved like this

mov rcx, [rsi+8]
call 1st instrumentation
call 2nd instrumentation
call (some function)
**end of bb

It's also worth noting that a decoding the next basic block isn't the solution for this. Any help would be greatly appreciated 

sharma...@google.com

unread,
Jan 19, 2022, 6:18:56 PM1/19/22
to DynamoRIO Users
Does passing where=NULL to the dr_insert_clean_call call work? I think it should append the instrs to end of the instrlist (similar to instrlist_meta_preinsert).

Abhinav

Jordan Conrad

unread,
Jan 19, 2022, 7:46:09 PM1/19/22
to DynamoRIO Users
Sadly no. It seems to insert the clean call before the instruction rather than after, even with instr_get_next(). It behaves just like this

mov rcx, [rsi+8]
call 1st instrumentation
call 2nd instrumentation
call (some function)
**end of bb

sharma...@google.com

unread,
Jan 20, 2022, 7:11:58 PM1/20/22
to DynamoRIO Users
Hi,
If this is the case, then it seems like a bug to me. Can you create an issue at https://github.com/DynamoRIO/dynamorio/issues with a small client and the basic block before and after instrumentation?

Abhinav

sharma...@google.com

unread,
Jan 21, 2022, 10:52:16 AM1/21/22
to DynamoRIO Users
I later found (thanks Derek for pointing me to the documentation) that adding instructions after a call instruction in a basic block is actually not supported. See https://dynamorio.org/dr__events_8h.html#acbfe1ece2c520d409ffd59076507a710, "An application direct call must be the final instruction in the block" and the following 2 points also. But DR should fail with a clear message if it finds such illegal instrumentation, and not silently put the instructions somewhere else. Thanks for creating https://github.com/DynamoRIO/dynamorio/issues/5290; I'll update the scope of that issue to finding why there was no clear message in this case.

As far as your use case is concerned, I wonder if drwrap (https://dynamorio.org/page_drwrap.html) can help. You can register pre- and post-function callbacks using drwrap_wrap (https://dynamorio.org/group__drwrap.html#ga4c004987daae07af15f2146c2d7d4b09). Does this work for you?

Abhinav

Jordan Conrad

unread,
Jan 21, 2022, 7:00:33 PM1/21/22
to DynamoRIO Users
Ok thanks. Glad to understand what's going on now

As for a solution, drwrap seemed like a good idea. However after many attempts I was unable to get it to work. The wraps behaved very strangely  and was unreliable for some reason. Normally when I use it to loop a function there are no problems.  It seemed as though using the DRWRAP_REPLACE_RETADDR would be a great solution, but it didn't work like I expected.

I decided to go for a more hacky solution to see if it would work. 
Since this is impossible:

mov rcx, [rsi+8]
call 1st instrumentation <-- meta
call (some function)
call 2nd instrumentation <-- meta

I thought perhaps this could work:
mov rcx, [rsi+8]
call 1st instrumentation <-- meta
call (some function) <-- meta
call 2nd instrumentation <-- meta
JMP (skip below call)
call (some function)

Oddly enough the program functions correctly but none of the instructions inside (some function) are ever hit in the basic block event. I'm guessing that this has something to do with the fact that the new call is inserted as a meta instruction (with instrlist_meta_preinsert()). Is there a way to make it so that the instructions after the new call are recognized as app instructions? If not are there perhaps any other ways to make this work?

Thanks for the assistance

Jordan Conrad

unread,
Jan 21, 2022, 8:14:39 PM1/21/22
to DynamoRIO Users
Along with my most recent tests I have also tried overriding the return address on the stack and redirecting execution out of a clean call. Is there a way to set the return address to return to my instrumentation out of an application instruction. So it would look something like this

pop rdx
ret (<--Address on stack points to my instrumentation)
(reaches my instrumentation)

On Friday, January 21, 2022 at 10:52:16 AM UTC-5 sharma...@google.com wrote:

Jordan Conrad

unread,
Jan 22, 2022, 12:12:24 PM1/22/22
to DynamoRIO Users
Found a solution that's kind of hacky but it works. I insert a cleancall before the call that pushes the a return address (set as the address of the cleancall instruction), then redirect execution to the target. Once the function returns, the cleancall is executed for a second time. With a combination of tracking the call instruction and stack addresses it can be determined whether the execution of the cleancall is that of a call or a return, even in recursive calls. If it is determined the execution is a return then just redirect execution  to where the return address would have pointed to.

During call
call 1st instrumentation -> Override return address and redirect execution -> (somefunction)
call (some function)
**end of bb

During return 
↓ <-call 1st instrumentation <- Skip below call instruction  <- (somefunction)
↓call (some function)  (never executed)
->test rax, rax
**end of bb

Derek Bruening

unread,
Jan 22, 2022, 4:01:56 PM1/22/22
to dynamor...@googlegroups.com
If your goal is to take some action after an app callee returns, you cannot do that by inserting instrumentation after the call instruction.  The call turns into just a jump to the callee: the app callee does *not* return to that point.  It will return to a completely separate block after executing blocks for the content of the callee.  The best way to take action at the return point is to use drwrap.  If you are hitting some problems with drwrap, please investigate and bring up the details as that is something to be fixed.

If your goal is take some action at the entry point of the callee, simply wait for the next block which will be the entry point.  Or use drwrap, which does that for you.

--
You received this message because you are subscribed to the Google Groups "DynamoRIO Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dynamorio-use...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dynamorio-users/2f85a8cf-3725-40fb-8655-a6dd4a6897afn%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages