Pat,
You can affect the functional part of the application, as you can from any Pintool. E.g. use PIN_ExecuteAt to redirect control flow, or PIN_SafeCopy to modify memory contents. Sniper's Pin front-end is located in the sources in sniper/pin/* so that's where you could add this code.
Two tings to keep in mind:
- Instructions are sent from the functional side to the timing side in basic block chunks. You can only change control flow at the end of a basic block, else the timing model will get confused. (There may be some code left to do it per-instruction, at some performance cost, but allowing you jump out of the middle of basic blocks. If that's what you need I can look up where this code is.)
- There is a queue (up to several basic blocks) between the functional and timing parts. The branch predictor is ran immediately when the branch is functionally executed, and you can use its prediction to affect control flow (the (mis)prediction itself is queued together with the instruction, and will affect timing later). But other events such as ROB stalls are only known much later so you cannot use that information in the pintool.
Regards,
Wim