When a Time Travel Debugging trace has been captured It can be vary useful to find where in the execution of an application specific strings are generated such as error messages etc. For example if an error message string is generated with sprintf, this point in execution in often much closer to when actual error occurred vs when it is displayed to user or written to a log file.
The first parameter of sprintf is pointer to a buffer that will take the generated text. So when we hit the function we must record that in a temporary variable, then we set a one time breakpoint on the return address, go to that position and dump out the string in the buffer location.
Also the sprintf function can be called from more DLLs then just the C runtime library, so we use a wildcard for modules, and a wildcard at the end to handle the secure variants i.e sprintf_s.
In 32-bit process:
bm *!sprintf* "!position;r @$t0 = poi(@esp+4);bp /1 @$ra \".printf \\\"%ma\\\\r\\\\n\\\",@$t0;g\";g"
In 64-bit process:
bm *!sprintf* "!position;r @$t0 = poi(@RCX);bp /1 @$ra \".printf \\\"%ma\\\\r\\\\n\\\",@$t0;g\";g"
This can be tweaked for any of the *printf* style APIs. If logging a unicode variation of the API change %ma to %mu
This will give you output like below:
Before going to the time travel position locations clear the breakpoints:
bc *
This can also be used for live debugging by removing !position command