-
Notifications
You must be signed in to change notification settings - Fork 571
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Call drreg_restore_all prior to clean calls #4128
Comments
Xref #4120 |
There is a performance tradeoff here. Many clean calls do not care about the values of most or all application registers. Some care about just one. E.g., |
Indeed, the issue here is when a user callback is triggered because we cannot make hard assumptions on its functionality, e.g. drwrap. |
The drwrap clean call interaction with drreg was in fact hit by a user of winafl: https://groups.google.com/g/dynamorio-users/c/ccXXk87SxNE |
Ideas:
|
A 4th possibility:
For the 2nd: better to make the event just "clean call here" and not "app state needed here" But we're leaning toward the first one with the label. For that: drreg has to walk backward; have drmgr provide a query to identify the New type of label and annotation inserts it too. Maybe it records New flag to dr_insert_clean_call: default to needs-all-regs for safety at But generally only 1 to 3 regs spilled: so maybe little perf advantage of Add a comment by dr_get_mcontext() about setting this new flag. Label should be before clean call inserts its stuff (b/c may pass app val Not yet figured out: How apply to drwrap: does it give users the option to get app state or not? |
Re: the drwrap questions: it looks like DRWRAP_FAST_CLEANCALLS is still using a dr_insert_clean_call (I thought it wasn't...maybe thinking of some past DrMemory optimizations) and it is just avoiding saving flags and some SIMD values: so I think it would still work w/ the label proposal. Re: drwrap providing an option: getting arg or return values does need the barrier so it seems the common case would want it; but since drwrap is commonly used and performance is an issue maybe it should provide an option to not restore app values for cases where arg or return values are not needed. |
I really like the simplicity of option 3 but it does not transcend well across other DR extensions; drwrap would need to be aware of drreg and the new wrappers (at the moment, drreg is not included in drwrap). Yeah... I would lean more towards idea 1 as it appears to be less intrusive. |
I think we need the counterpart for dr_set_mcontext() called in a clean call: we need a label requesting that drreg update the spilled app values. |
@johnfxgalea I'm updating instances of dr_insert_clean_call that call dr_{s,g}et_mcontext and there are some in drbbdup.c -- but they're generated in a cache and I'm not sure whether they need the new |
@derekbruening Thanks for informing me. There are two places where drbbdup uses clean calls. The first invokes dynamorio/ext/drbbdup/drbbdup.c Line 817 in b8f8730
This function does not use The second use of clean call insertion happens inside a cache: dynamorio/ext/drbbdup/drbbdup.c Line 1315 in b8f8730
In particular, the call targets dynamorio/ext/drbbdup/drbbdup.c Line 1208 in b8f8730
The function requires that a register, which is used as scratch at the time of the function's call, contains drbbdup information. In other words, the function assumes that this GPR register and the aflags are the only registers that do not contain original values. Prior to redirection, the function calls a helper, namely dynamorio/ext/drbbdup/drbbdup.c Line 1188 in b8f8730
|
So it sounds like these new clean call flags are not needed for drbbdup and would in fact break the current model there. |
We picked idea 1 above, but it doesn't work: drreg can't walk backward as it relies on forward time and can't move its state machine backward to the point of the label. It also has the problem of the temp move of the tool value and restore after being in the wrong place: after the label is still before the call! We'd need a 3rd label after the app-write label after the call to restore tool values if nec (and so need new drreg state too?) This problem should go away if we call drreg at the time we insert the clean call (may also need a new label there for the right "after" point): so it's unique to the label soln. The new plan is to go with idea 2 where DR has a clean call insertion event and drreg registers for it. How handle annotations?Can't call cleancall cb at annot label insert time: has to be at drmgr Move annot clean call into client that inserts in insertion phase so it Fits better w/ clean call callback and removes drreg looking for If we collapsed drmgr into core DR: I would suggest moving the clean call, What ab clean calls in other phases?
|
Adds new dr_cleancall_save_t flags which are required for proper interaction between clean calls and drreg: DR_CLEANCALL_READS_APP_CONTEXT must be set for dr_get_mcontext() to obtain the proper values, and #DR_CLEANCALL_WRITES_APP_CONTEXT must be set to ensure that dr_set_mcontext() is persistent. Adds a clean call insertion event to enable drreg to know about clean calls at the time they are inserted. dr_insert_clean_call_ex() invokes the callback and passes the flags to drreg, who then treats the clean call as an app instruction. For annotations, for now we leave drreg looking for the annotation label (possible future changes #5160 or #5161 would eliminate this special case). dr_insert_{cbr,ubr,mbr,call}_instrumentation() always set both labels. drwrap always sets both labels for pre and post callbacks. Updates uses throughout our tests and samples to use the new flags as appropriate. Adds a new dedicated test client.drwrap-drreg-test which tests both a drwrap call and a direct clean call. Fixes a missing drwrap cache invalidation on module unload that the new test uncovers. Fixes #4128
This gets more and more complicated: for control flow that can skip a clean call or not, I added DR_CLEANCALL_MULTIPATH which makes DR_CLEANCALL_READS_APP_CONTEXT invoke drreg_statelessly_restore_app_value() for flags + all GPRs. But that clobbers tool values: so I'm just documenting that and saying you have to do it manually if that's no good. And then: what about for DR_CLEANCALL_WRITES_APP_CONTEXT | DR_CLEANCALL_MULTIPATH? Go try to write a stateless version of that (again disallowing live tool values)? Or don't support that flag combo? I'm not supporting it. |
Fixes a drreg bug in drreg_spill_aflags() which set xax's ever_spilled flag to true even if it wasn't spilled because it was dead. This caused requests to get the app value of xax to return success and to move aflags out of xax and into a slot, but without restoring the app value. The fixed behavior is to fail up front if xax is dead and so leave aflags in xax. Updates the drreg tests that rely on getting the xax value moving aflags into a slot to use a live xax rather than a dead xax. This was discovered while adding PR #5164 for #4128. Issue: #4128
Fixes a drreg bug in drreg_spill_aflags() which set xax's ever_spilled flag to true even if it wasn't spilled because it was dead. This caused requests to get the app value of xax to return success and to move aflags out of xax and into a slot, but without restoring the app value. The fixed behavior is to fail up front if xax is dead and so leave aflags in xax. Updates the drreg tests that rely on getting the xax value moving aflags into a slot to use a live xax rather than a dead xax. This was discovered while adding PR #5164 for #4128. Issue: #4128
Adds new dr_cleancall_save_t flags which are required for proper interaction between clean calls and drreg: DR_CLEANCALL_READS_APP_CONTEXT must be set for dr_get_mcontext() to obtain the proper values, and #DR_CLEANCALL_WRITES_APP_CONTEXT must be set to ensure that dr_set_mcontext() is persistent. DR_CLEANCALL_MULTIPATH must be additionally set for might-skip calls. Adds a clean call insertion event to enable drreg to know about clean calls at the time they are inserted. dr_insert_clean_call_ex() invokes the callback and passes the flags to drreg, who then treats the clean call as an app instruction. For annotations, for now we leave drreg looking for the annotation label (possible future changes #5160 or #5161 would eliminate this special case). dr_insert_{cbr,ubr,mbr,call}_instrumentation() always set both labels. drwrap always sets both labels for pre and post callbacks. Updates uses throughout our tests and samples to use the new flags as appropriate. Adds drreg_statelessly_restore_all() for clean call multipath restoration. Adds a new dedicated test client.drwrap-drreg-test which tests both a drwrap call and direct clean calls. Fixes a missing drwrap cache invalidation on module unload that the new test uncovers. This likely fixes #4711 as its code was passing the same location for the where_respill as where_restore for stateless drreg restoration; the automated restore here correctly passes the post-instr location. Issue: #4128, #4711 Fixes #4128
In order for clean calls to have access to a machine context that contains original register/flag values, we need to call drreg's drreg_restore_all(). Essentially, the issue is that due to drreg's lazy restoration, registers may not have their original values upon invoking a clean call.
drreg_restore_app_values() is not appropriate as it only works on a passed operand.
The text was updated successfully, but these errors were encountered: