| 211 | | It may be unnecessary. I think it is included for compatibility with MSVC |
|---|
| 212 | | exceptions? |
|---|
| | 212 | // Walk the exception handler chain |
|---|
| | 213 | void printHandlerChain() |
|---|
| | 214 | { |
|---|
| | 215 | DEstablisherFrame *head; |
|---|
| | 216 | asm |
|---|
| | 217 | { |
|---|
| | 218 | mov EAX, FS:[0]; |
|---|
| | 219 | mov head, EAX; |
|---|
| | 220 | } |
|---|
| | 221 | while (head && head != cast(DEstablisherFrame *)~0) |
|---|
| | 222 | { |
|---|
| | 223 | printf("%p %p ", head, head.handler); |
|---|
| | 224 | if (head.handler == &unwindCollisionExceptionHandler) |
|---|
| | 225 | printf("UnwindCollisionHandler\n"); |
|---|
| | 226 | else if (head.handler == &_except_handler3) |
|---|
| | 227 | printf("excepthandler3\n"); |
|---|
| | 228 | else |
|---|
| | 229 | { |
|---|
| | 230 | ubyte *hnd = cast(ubyte *)head.handler; |
|---|
| | 231 | if (hnd[0] == 0xB8 && hnd[5]==0xE9) // mov EAX, xxx; jmp yyy; |
|---|
| | 232 | { |
|---|
| | 233 | int adr = *cast(int *)(hnd+6); |
|---|
| | 234 | printf("thunk: frametable=%x adr=%x ", *cast(int *)(hnd+1), hnd + adr+10); |
|---|
| | 235 | if (cast(void *)(hnd + adr + 10) == &_d_framehandler) |
|---|
| | 236 | printf("dframehandler\n"); |
|---|
| | 237 | else printf("\n"); |
|---|
| | 238 | } else printf("(unknown)\n"); |
|---|
| | 239 | } |
|---|
| | 240 | head = head.prev; |
|---|
| | 241 | } |
|---|
| | 242 | } |
|---|
| 213 | 243 | |
|---|
| 214 | 244 | Documentation of Windows SEH is hard to find. Here is a brief explanation: |
|---|
| 215 | 245 | |
|---|
| 216 | 246 | When an exception is raised, the OS calls each handler in the FS:[0] list in |
|---|
| 217 | 247 | turn, looking for a catch block. It continues moving down the list, as long as |
|---|
| 218 | 248 | each handler indicates that it has not caught the exception. When a handler is |
|---|
| 219 | 249 | ready to catch the exception, it calls the OS function RtlUnwind. |
|---|
| 220 | 250 | This calls each function in the FS:[0] list again, this time indicating that it |
|---|
| 221 | 251 | is a 'unwind' call. All of the intervening finally blocks are run at this time. |
|---|
| 222 | 252 | The complicated case is a CollidedException, which happens when a finally block |
|---|