The documentation for the Windows Debugger API mentions a debug event called RIP_EVENT. It offers little explanation of what a RIP_EVENT is, only stating that the structure "contains the error that caused the RIP debug event." In my own debugger, I have never encountered this event, so I am uncertain how to handle it.
There are precious little resources online explaining what the event is. This blog is as confused as I am:
I find very few documents about this event, only mentioned with words like system error or internal error. So I decide to print a error message and skip it. As my project is not fully tested, I have never encountered such a situation.
The Writing A Debugger CodeProject claims the event "occurs if your process being debugged dies unexpectedly." Similarly, this OALabs video states that the RIP_EVENT occurs if the process doesn't exit gracefully.
This seems to be the general consensus amongst the few resources I can find. The problem is, of all the ways I can conceive of to kill a process in unexpected fashion, none of them trigger a RIP_EVENT. Last Chance Exceptions trigger a DEBUG_EVENT, eventually followed by an EXIT_PROCESS_DEBUG_EVENT, instead. If anything, I would expect that terminating the process in Task Manager wouldn't be considered a "graceful exit," but it too triggers an EXIT_PROCESS_DEBUG_EVENT, not a RIP_EVENT. This makes me wonder if the event is even associated with process termination at all, or if that's just a confident assumption based on the name "RIP."
I'm left to speculate why I've never seen this event before and in what scenario it could potentially arise:
- Assuming a RIP_EVENT does occur when the process dies somehow, does the RIP_EVENT replace the EXIT_PROCESS_DEBUG_EVENT, or can I expect to receive both events?
- How do popular debuggers like Visual Studio or WinDbg handle the RIP_EVENT? What is the correct way to handle one? Do I even need to do anything if I receive one?
- Does the "RIP" in RIP_EVENT refer to the instruction pointer in x64? Would that imply it is exclusive to x64 and never occurs for x86? Or perhaps it is for some other CPU architecture I don't care about?
- Does it occur when connection is lost while debugging a remote process? This is another scenario I thought might cause it, but it'd be difficult for me to test.
Update: I began digging even further into this, because I wasn't satisfied with the guesses so far, and found something interesting. There is an export of USER32 called SetDebugErrorLevel. There is no official documentation for it that I can find, but if this source is to be believed, it would make a lot of sense.
The SetDebugErrorLevel function sets the minimum error level at which Windows will generate debugging events and pass them to a debugger.
dwLevel Specifies the minimum error level for debugging events. If an error is equal to or above this level, Windows generates a debugging event. This parameter must be one of the following values:
Meaning: Does not report any errors. This value is the default error level.
Meaning: Reports only ERROR level debugging events.
Meaning: Reports only MINORERROR level and ERROR level debugging events.
Meaning: Reports WARNING level, MINORERROR level, and ERROR level debugging events.
Particularly because the RIP_INFO structure contains a dwType field with these same values, I think it is likely that RIP_EVENT was intended to be thrown as a part of this mechanism. The thing is, SetDebugErrorLevel - although it exists in USER32 - does nothing. Looking at the disassembly reveals it simply returns immediately. Furthermore, these types were clearly intended to be specified in calls to SetLastErrorEx, though it too goes unused, as the documentation explains:
Currently, this function is identical to the SetLastError function. The second parameter is ignored.
...with the second, unused parameter being dwType, which was probably meant to take in the SLE_ERROR, SLE_MINORERROR, and SLE_WARNING types (with "SLE" standing for SetLastError.) From this, I infer that RIP_EVENT was probably intended to be thrown whenever SetLastErrorEx was used to set a new error level, but this feature has been abandoned. This is my best theory, but it is still only a guess, as the documentation never goes so far as to explicitly state this.