2

I'm looking at UnwindMapEntry. Here is it's declaration:

//
// UnwindMapEntry - Description of each state transition for unwinding
//  the stack (i.e. calling destructors).
//
// The unwind map is an array, indexed by current state.  Each entry specifies
// the state to go to during unwind, and the action required to get there.
// Note that states are represented by a signed integer, and that the 'blank'
// state is -1 so that the array remains 0-based (because by definition there
// is never any unwind action to be performed from state -1).  It is also
// assumed that state indices will be dense, i.e. that there will be no gaps of
// unused state indices in a function.
//

typedef const struct _s_UnwindMapEntry {
    __ehstate_t toState;                    // State this action takes us to
#if _EH_RELATIVE_FUNCINFO
    int         action;                     // Image relative offset of funclet
#else
    void        (__cdecl * action)(void);   // Funclet to call to effect state change
#endif
} UnwindMapEntry;

Sorry if it's obvious for you but what does toState means? It is not clear for me by reading the description above.

Also there is this structure for a tryblockmaprntry which is also involved somehow:

//
// HandlerMapEntry - associates a handler list (sequence of catches) with a
//  range of eh-states.
//
typedef const struct _s_TryBlockMapEntry {
    __ehstate_t     tryLow;             // Lowest state index of try
    __ehstate_t     tryHigh;            // Highest state index of try
    __ehstate_t     catchHigh;          // Highest state index of any associated catch
    //....

What's catchHigh - is it always tryHigh + 1?

OK It seems the catchHigh is continuing the state inside the catch block - because you can have exception there too. But still I don't see it's purpose - like when this field makes any difference.

4

the __ehstate_t type is defined as int. toState is the index of the next handler in the array that needs to be unwind.

Action is the operation that needs to be done in order to reach the next state (the value of toState). This happens until toState reaches -1, which is the "blank" state that ends the unwinding process.

The state is incremented by one every time you enter a try block or otherwise create an object that must be destructed in the unwinding process if an exception is thrown before the program called its destructor.

Example:

Say there is a function int F1(){}

At the beginning of the function, the state for the current scope is -1 as there are no actions to take if an exception occurs.

Somewhere after the beginning of F1 an object of type ClassA is created. This calls the constructor ClassA::ClassA(). At this point if an exception is thrown, there is a ClassA object that needs to be deleted before the catch block is called. The initialization of the object incremented the state to 0.

Now comes a try block - the state is now 1. Should an exception be thrown here, the handler will have to leave the try block (state->0) and call ClassA::~ClassA() on the object that was created before (state->-1). If the execution reaches the end of the try block an no exception occurred, the state is decremented (state->0 again).

tryLow is the target outmost state that a handler must get to before it calls the catch block. In our example, when entering the try block (state = 1), the tryLow value will be -1. The handler will have to get to state -1, that is, leaving the try block and calling ClassA::~ClassA() and only then call the catch block.

For reverse engineering purposes, there is a great post at OpenRCE:

http://www.openrce.org/articles/full_view/21

5
  • Can you elaborate with an example algorithm of how it's done. Also if possible to include tryLow, tryLow and catchHigh. In the meantime I'll be continuing to try to understand this myself by looking into the msvct crt sources. – rec Apr 24 '20 at 11:20
  • Edited my answer. – Yotamz Apr 24 '20 at 15:18
  • Also there is sometime a filler of UnwindMapEntry <-1, 0> - any ideas what that is for? – rec Apr 24 '20 at 18:43
  • @rec: that's for empty transitions in the state machine (nothing to destruct). – Igor Skochinsky Apr 24 '20 at 19:28
  • I guess this is a representation of the relevant UnwindMapEntry with a toState (-1) and an action function pointer (NULL). – Yotamz Apr 24 '20 at 19:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.