1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8//  This file implements the personality and helper functions for the state
9//  table based EH used by IBM legacy compilers xlC and xlclang++ on AIX.
10//
11//===----------------------------------------------------------------------===//
12
13#include <new>
14#include <stdio.h>
15#include <sys/debug.h>
16
17#if !__has_cpp_attribute(clang::optnone)
18#error This file requires clang::optnone attribute support
19#endif
20
21/*
22  The legacy IBM xlC and xlclang++ compilers use the state table for EH
23  instead of the range table. Destructors, or addresses of the possible catch
24  sites or cleanup code are specified in the state table which is a finite
25  state machine (FSM). Each function that has a state table also has an
26  autolocal state variable. The state variable represents the current state
27  of the function for EH and is found through the traceback table of the
28  function during unwinding, which is located at the end of each function.
29  The FSM is an array of state entries. Each state entry has the following
30  fields:
31
32  * offset/address/pointer - the offset used to locate the object, or the
33    address of a global object, or the address of the next state if it is an
34    old conditional state change entry;
35  * dtor/landing pad - address of the destructor function to invoke,
36    or address of the catch block or cleanup code in the user code to branch to;
37  * element count/action flag - the number of elements or the flag for actions;
38  * element size - if the object is an array this is the size of one element
39    of the array;
40  * flags - flags used to control how fields in the entry are interpreted;
41  * next state - the state to execute next after the action for this state is
42    performed. The value of zero indicates the end of the state for this
43    function.
44
45  The following is the description of 'element count/action flag' field.
46+-----------------------------------------------------------------------------+
47| value |      description       |                  action                    |
48+-------+------------------------+--------------------------------------------+
49| > 1   |   object is an array   | calls __cxa_vec_cleanup to run dtor for    |
50|       |                        | each member of the array                   |
51+-------+------------------------+--------------------------------------------+
52| 1, 0  |   object is a scalar   | calls dtor for the object                  |
53+-------+------------------------+--------------------------------------------+
54|  -1   |      begin catch       | branches to the handler which performes    |
55|       |                        | catch-match. If there is no catch that     |
56|       |                        | matches the exception it will be rethrown  |
57+-------+------------------------+--------------------------------------------+
58|  -2   |       end catch        | ends current catch block and continues     |
59|       |                        | attempting to catch the exception          |
60+-------+------------------------+--------------------------------------------+
61|  -3   |   delete the object    | calls the delete function of the object    |
62+-------+------------------------+--------------------------------------------+
63|  -4   |      cleanup label     | branches to the user code for cleaning up  |
64+-------+------------------------+--------------------------------------------+
65*/
66
67namespace __cxxabiv1 {
68
69extern "C" {
70
71// Macros for debugging the state table parsing.
72#ifdef NDEBUG
73#  define _LIBCXXABI_TRACE_STATETAB(msg, ...)
74#  define _LIBCXXABI_TRACE_STATETAB0(msg)
75#  define _LIBCXXABI_TRACE_STATETAB1(msg)
76#  define _LIBCXXABI_TRACING_STATETAB 0
77#else
78static bool state_tab_dbg() {
79  static bool checked = false;
80  static bool log = false;
81  if (!checked) {
82    log = (getenv("LIBCXXABI_PRINT_STATTAB") != NULL);
83    checked = true;
84  }
85  return log;
86}
87
88#  define _LIBCXXABI_TRACE_STATETAB(msg, ...)                                  \
89     do {                                                                      \
90       if (state_tab_dbg())                                                    \
91         fprintf(stderr, "libcxxabi: " msg, __VA_ARGS__);                      \
92     } while (0)
93#  define _LIBCXXABI_TRACE_STATETAB0(msg)                                      \
94     do {                                                                      \
95       if (state_tab_dbg())                                                    \
96         fprintf(stderr, "libcxxabi: " msg);                                   \
97     } while (0)
98#  define _LIBCXXABI_TRACE_STATETAB1(msg)                                      \
99     do {                                                                      \
100       if (state_tab_dbg())                                                    \
101         fprintf(stderr, msg);                                                 \
102     } while (0)
103
104#  define _LIBCXXABI_TRACING_STATETAB state_tab_dbg()
105#endif // NDEBUG
106
107namespace __state_table_eh {
108
109using destruct_f = void (*)(void*);
110
111// Definition of flags for the state table entry field 'action flag'.
112enum FSMEntryCount : intptr_t { beginCatch = -1, endCatch = -2, deleteObject = -3, cleanupLabel = -4, terminate = -5 };
113
114// Definition of flags for the state table entry field 'flags'.
115enum FSMEntryFlag : int16_t {
116  indirect = 0x100,                  // Object was thrown from a function where
117                                     // the return value optimization was used.
118  oldConditionalStateChange = 0x400, // State table entry is an indirect state
119                                     // change, dereference the address in
120                                     // offset as int for the target state.
121                                     // This is deprecated. This indicates
122                                     // the address is direct. (static local).
123  conditionalStateChange = 0x800,    // State table entry is an indirect state
124                                     // change, dereference the address in
125                                     // offset as int for the target state.
126                                     // The temporary is an automatic. State
127                                     // change is used in cases such as
128                                     // (b?(T1(),foo()):(T2(),foo())),throw 42;
129                                     // which causes a conditional state change
130                                     // so that we know if T1 or T2 need to be
131                                     // destroyed.
132  thisFlag = 0x01,                   // The address of the object for the
133                                     // cleanup action is based on the
134                                     // StateVariable::thisValue.
135  vBaseFlag = 0x02,                  // The object is of a virtual base class.
136  globalObj = 0x04                   // FSMEntry::address is the address of
137                                     // a global object.
138};
139
140namespace {
141// The finite state machine to be walked.
142struct FSMEntry {
143  union {
144    // Offset of the object within its stack frame or containing object.
145    intptr_t offset;
146    // Address of a global object.
147    intptr_t address;
148    // Address of the next state if it is an old conditional state change entry.
149    intptr_t nextStatePtr;
150  };
151  union {
152    // Address of the destructor function.
153    void (*destructor)(void*, size_t);
154    // The address of the catch block or cleanup code.
155    void* landingPad;
156  };
157  union {
158    // The flag for actions (when the value is negative).
159    FSMEntryCount actionFlag;
160    // The element count (when the value is positive or zero).
161    size_t elementCount;
162  };
163  size_t elemSize;
164  FSMEntryFlag flags;
165  uint16_t nextState;
166};
167
168struct FSM {
169  uint32_t magic; // Magic number of the state table.
170  int32_t numberOfStates;
171  FSMEntry table[1]; // Actually table[numberOfStates].
172};
173
174// The state variable on the stack.
175struct StateVariable {
176  int32_t state;
177  struct FSM* table;
178  intptr_t thisValue;
179  int32_t ignoreVBasePtrs;
180};
181} // namespace
182
183// State table magic number
184enum FSMMagic : uint32_t {
185  number = 0xbeefdead,  // State table generated by xlC compiler.
186  number2 = 0xbeeedead, // State table generated by early version xlC compiler.
187  number3 = 0x1cedbeef  // State table generated by xlclang++ compiler.
188};
189
190constexpr size_t dtorArgument = 0x02; // Flag to destructor indicating to free
191                                      // virtual bases, don't delete object.
192
193static void invoke_destructor(FSMEntry* fsmEntry, void* addr) {
194  _LIBCXXABI_TRACE_STATETAB("Destruct object=%p, fsmEntry=%p\n", addr, reinterpret_cast<void*>(fsmEntry));
195  try {
196    if (fsmEntry->elementCount == 1) {
197      _LIBCXXABI_TRACE_STATETAB0("calling scalar destructor\n");
198      (*fsmEntry->destructor)(addr, dtorArgument);
199      _LIBCXXABI_TRACE_STATETAB0("returned from scalar destructor\n");
200    } else {
201      _LIBCXXABI_TRACE_STATETAB0("calling vector destructor\n");
202      __cxa_vec_cleanup(addr, reinterpret_cast<size_t>(fsmEntry->elementCount), fsmEntry->elemSize,
203                        reinterpret_cast<destruct_f>(fsmEntry->destructor));
204      _LIBCXXABI_TRACE_STATETAB0("returned from vector destructor\n");
205    }
206  } catch (...) {
207    _LIBCXXABI_TRACE_STATETAB0("Uncaught exception in destructor, terminating\n");
208    std::terminate();
209  }
210}
211
212static void invoke_delete(FSMEntry* fsmEntry, void* addr) {
213  char* objectAddress = *reinterpret_cast<char**>(addr);
214
215  _LIBCXXABI_TRACE_STATETAB("Delete object=%p, fsmEntry=%p\n", reinterpret_cast<void*>(objectAddress),
216                            reinterpret_cast<void*>(fsmEntry));
217  try {
218    _LIBCXXABI_TRACE_STATETAB0("..calling delete()\n");
219    // 'destructor' holds a function pointer to delete().
220    (*fsmEntry->destructor)(objectAddress, fsmEntry->elemSize);
221    _LIBCXXABI_TRACE_STATETAB0("..returned from delete()\n");
222  } catch (...) {
223    _LIBCXXABI_TRACE_STATETAB0("Uncaught exception in delete(), terminating\n");
224    std::terminate();
225  }
226}
227
228// Get the frame address of the current function from its traceback table
229// which is at the end of each function.
230static uintptr_t get_frame_addr(_Unwind_Context* context) {
231  int framePointerReg = 1; // default frame pointer == SP.
232  uint32_t* p = reinterpret_cast<uint32_t*>(_Unwind_GetIP(context));
233
234  // Keep looking forward until a word of 0 is found. The traceback
235  // table starts at the following word.
236  while (*p)
237    ++p;
238  tbtable* TBTable = reinterpret_cast<tbtable*>(p + 1);
239
240  p = reinterpret_cast<uint32_t*>(&TBTable->tb_ext);
241
242  // Skip field parminfo if it exists.
243  if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
244    ++p;
245
246  // Skip field tb_offset if it exists.
247  if (TBTable->tb.has_tboff)
248    ++p;
249
250  // Skip field hand_mask if it exists.
251  if (TBTable->tb.int_hndl)
252    ++p;
253
254  // Skip fields ctl_info and ctl_info_disp if they exist.
255  if (TBTable->tb.has_ctl)
256    p += 1 + *p;
257
258  // Skip fields name_len and name if exist.
259  if (TBTable->tb.name_present) {
260    const uint16_t name_len = *reinterpret_cast<uint16_t*>(p);
261    p = reinterpret_cast<uint32_t*>(reinterpret_cast<char*>(p) + name_len + sizeof(uint16_t));
262  }
263
264  if (TBTable->tb.uses_alloca)
265    framePointerReg = *reinterpret_cast<char*>(p);
266
267  return _Unwind_GetGR(context, framePointerReg);
268}
269
270// Calculate the object address from the FSM entry.
271static void* compute_addr_from_table(FSMEntry* fsmEntry, StateVariable* const state, _Unwind_Context* context) {
272  void* addr;
273  if (fsmEntry->flags & FSMEntryFlag::globalObj) {
274    addr = reinterpret_cast<void*>(fsmEntry->address);
275    _LIBCXXABI_TRACE_STATETAB("Address calculation (global obj) addr=fsmEntry->address=%p\n", addr);
276  } else if (fsmEntry->flags & FSMEntryFlag::thisFlag) {
277    addr = reinterpret_cast<void*>(state->thisValue + fsmEntry->offset);
278    _LIBCXXABI_TRACE_STATETAB("Address calculation (this obj) fsmEntry->offset=%ld : "
279                              "state->thisValue=%ld addr=(fsmEntry->offset+state->thisValue)=%p\n",
280                              fsmEntry->offset, state->thisValue, addr);
281  } else if (fsmEntry->flags & FSMEntryFlag::indirect) {
282    addr = reinterpret_cast<void*>(
283        *reinterpret_cast<char**>(get_frame_addr(context) + static_cast<uintptr_t>(fsmEntry->offset)));
284    _LIBCXXABI_TRACE_STATETAB("Address calculation (indirect obj) addr=%p, fsmEntry->offset=%ld \n",
285                              addr, fsmEntry->offset);
286  } else {
287    addr = reinterpret_cast<void*>(get_frame_addr(context) + static_cast<uintptr_t>(fsmEntry->offset));
288    _LIBCXXABI_TRACE_STATETAB("Address calculation. (local obj) addr=fsmEntry->offset=%p\n",
289                              addr);
290  }
291  return addr;
292}
293
294static void scan_state_tab(scan_results& results, _Unwind_Action actions, bool native_exception,
295                           _Unwind_Exception* unwind_exception, _Unwind_Context* context) {
296  // Initialize results to found nothing but an error.
297  results.ttypeIndex = 0;
298  results.actionRecord = 0;
299  results.languageSpecificData = 0;
300  results.landingPad = 0;
301  results.adjustedPtr = 0;
302  results.reason = _URC_FATAL_PHASE1_ERROR;
303
304  // Check for consistent actions.
305  if (actions & _UA_SEARCH_PHASE) {
306    // Do Phase 1
307    if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) {
308      // None of these flags should be set during Phase 1.
309      //   Client error
310      results.reason = _URC_FATAL_PHASE1_ERROR;
311      return;
312    }
313  } else if (actions & _UA_CLEANUP_PHASE) {
314    if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) {
315      // _UA_HANDLER_FRAME should only be set if phase 1 found a handler.
316      // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened.
317      //    Client error
318      results.reason = _URC_FATAL_PHASE2_ERROR;
319      return;
320    }
321  } else {
322    // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set.
323    //   Client error
324    results.reason = _URC_FATAL_PHASE1_ERROR;
325    return;
326  }
327
328  if (_LIBCXXABI_TRACING_STATETAB) {
329    _LIBCXXABI_TRACE_STATETAB1("\n");
330    _LIBCXXABI_TRACE_STATETAB("%s: actions=%d (", __func__, actions);
331
332    if (_UA_SEARCH_PHASE & actions)
333      _LIBCXXABI_TRACE_STATETAB1("_UA_SEARCH_PHASE ");
334    if (_UA_CLEANUP_PHASE & actions)
335      _LIBCXXABI_TRACE_STATETAB1("_UA_CLEANUP_PHASE ");
336    if (_UA_HANDLER_FRAME & actions)
337      _LIBCXXABI_TRACE_STATETAB1("_UA_HANDLER_FRAME ");
338    if (_UA_FORCE_UNWIND & actions)
339      _LIBCXXABI_TRACE_STATETAB1("_UA_FORCE_UNWIND ");
340    _LIBCXXABI_TRACE_STATETAB1(")\n");
341    _LIBCXXABI_TRACE_STATETAB("       unwind_exception=%p context=%p\n", reinterpret_cast<void*>(unwind_exception),
342                              reinterpret_cast<void*>(context));
343  }
344
345  // Start scan by getting state table address.
346  StateVariable* const state = reinterpret_cast<StateVariable* const>(_Unwind_GetLanguageSpecificData(context));
347  if (state->state <= 0) {
348    // The state is not correct - give up on this routine.
349    _LIBCXXABI_TRACE_STATETAB("state=%d and is <= 0), continue unwinding\n", state->state);
350    results.reason = _URC_CONTINUE_UNWIND;
351    return;
352  }
353  // Parse the state table.
354  FSM* const fsm = state->table;
355  FSMEntry* currFSMEntry;
356
357  if (fsm->magic != FSMMagic::number && fsm->magic != FSMMagic::number2 && fsm->magic != FSMMagic::number3) {
358    // Something is wrong with the state table we found.
359    if (_UA_SEARCH_PHASE & actions) {
360      _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table, return _URC_FATAL_PHASE1_ERROR\n");
361      results.reason = _URC_FATAL_PHASE1_ERROR;
362    } else if (_UA_CLEANUP_PHASE & actions) {
363      _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table, return _URC_FATAL_PHASE2_ERROR\n");
364      results.reason = _URC_FATAL_PHASE2_ERROR;
365    } else {
366      // We should never get here.
367      _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table + RT Internal error, return _URC_FATAL_PHASE2_ERROR\n");
368      results.reason = _URC_FATAL_PHASE2_ERROR;
369    }
370    return;
371  }
372
373  if (_LIBCXXABI_TRACING_STATETAB) {
374    // Print the state table for debugging purposes.
375    _LIBCXXABI_TRACE_STATETAB("state->state=%d, state->ignoreVBasePtrs=%d\n", state->state, state->ignoreVBasePtrs);
376    _LIBCXXABI_TRACE_STATETAB("fsm->magic=%#x, fsm->numberOfStates=%d\n", fsm->magic, fsm->numberOfStates);
377    // Print out the FSM table.
378    _LIBCXXABI_TRACE_STATETAB0("FSM table:\n");
379    _LIBCXXABI_TRACE_STATETAB("%12s %10s %8s  %10s %7s %7s %7s %7s\n", "Entry Addr", "state", "Offset", "DTR/lpad",
380                              "count", "el_size", "flags", "next");
381    for (int i = 0; i < fsm->numberOfStates; i++) {
382      currFSMEntry = &fsm->table[i];
383      _LIBCXXABI_TRACE_STATETAB("%12p (%8d) %8ld  %10p %7ld "
384                                "%7ld %#7x %7d\n",
385                                reinterpret_cast<void*>(&currFSMEntry), i + 1, currFSMEntry->offset,
386                                reinterpret_cast<void*>(currFSMEntry->destructor),
387                                currFSMEntry->elementCount, currFSMEntry->elemSize, currFSMEntry->flags,
388                                currFSMEntry->nextState);
389    }
390  }
391
392  if (_UA_SEARCH_PHASE & actions) {
393    // Start walking the state table. Use a local copy of state->state so when
394    // we return from search phase we don't change the state number.
395    int currState = state->state;
396
397    while (currState > 0) {
398      currFSMEntry = &fsm->table[currState - 1];
399      _LIBCXXABI_TRACE_STATETAB("Processing state=%d, flags=0x%hx\n", currState, currFSMEntry->flags);
400
401      if (currFSMEntry->actionFlag == FSMEntryCount::beginCatch) {
402        // Found a catch handler.
403        if (fsm->magic == FSMMagic::number) {
404          _LIBCXXABI_TRACE_STATETAB0("Found a xlC catch handler, return _URC_FATAL_PHASE1_ERROR\n");
405          // xlC catch handlers cannot be entered because they use a
406          // proprietary EH runtime that is not interoperable.
407          results.reason = _URC_FATAL_PHASE1_ERROR;
408          return;
409        }
410        // xlclang++ compiled frames use CXA-abi EH calls and any catch
411        // block will include a catch(...) block so it is safe to assume that
412        // the handler is found without checking the catch match. The
413        // catch(...) block will rethrow the exception if there isn't a
414        // match.
415        _LIBCXXABI_TRACE_STATETAB0("Found a catch handler, return _URC_HANDLER_FOUND\n");
416        results.reason = _URC_HANDLER_FOUND;
417        return;
418      }
419      if (currFSMEntry->actionFlag == FSMEntryCount::terminate) {
420        _LIBCXXABI_TRACE_STATETAB0("Found the terminate state, return _URC_HANDLER_FOUND\n");
421        results.reason = _URC_HANDLER_FOUND;
422        return;
423      }
424      if (currFSMEntry->flags & FSMEntryFlag::oldConditionalStateChange) {
425        // Deprecated conditional expression.
426        currState = *reinterpret_cast<int*>(currFSMEntry->nextStatePtr);
427        _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::oldConditionalStateChange, dereference "
428                                  "currFSMEntry->nextStatePtr(%ld), set state=%d\n",
429                                  currFSMEntry->nextStatePtr, currState);
430        continue; // We are done this iteration of the loop, since
431                  // we changed a state.
432      }
433      if (currFSMEntry->flags & FSMEntryFlag::conditionalStateChange) {
434        void* addr = compute_addr_from_table(currFSMEntry, state, context);
435        currState = *reinterpret_cast<int*>(addr);
436        _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::conditionalStateChange, dereference "
437                                  "addr(%p), set state=%d\n", addr, currState);
438        continue; // We are done this iteration of the loop, since we
439                  // changed the state.
440      }
441      // Go to the next state.
442      currState = currFSMEntry->nextState;
443    }
444    _LIBCXXABI_TRACE_STATETAB0("No catch handler found, return _URC_CONTINUE_UNWIND\n");
445    results.reason = _URC_CONTINUE_UNWIND;
446    return;
447  }
448  if (_UA_CLEANUP_PHASE & actions) {
449    // Start walking the state table.
450    while (state->state > 0) {
451      currFSMEntry = &fsm->table[state->state - 1];
452
453      if (currFSMEntry->actionFlag == FSMEntryCount::terminate) {
454        _LIBCXXABI_TRACE_STATETAB0("Reached terminate state. Call terminate.\n");
455        std::terminate();
456      }
457      // Perform action according to the currFSMEntry->actionFlag,
458      // except when flag is FSMEntryFlag::conditionalStateChange or
459      // FSMEntryFlag::oldConditionalStateChange.
460      _LIBCXXABI_TRACE_STATETAB("Processing state=%d, flags=0x%hx\n", state->state, currFSMEntry->flags);
461      if (currFSMEntry->flags & FSMEntryFlag::oldConditionalStateChange) {
462        state->state = *reinterpret_cast<int*>(currFSMEntry->nextStatePtr);
463        _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::oldConditionalStateChange, dereference "
464                                  "currFSMEntry->nextStatePtr(%ld), set state=%d\n",
465                                  currFSMEntry->nextStatePtr, state->state);
466        continue; // We are done with this iteration of the loop, since we changed a state.
467      }
468      if (currFSMEntry->flags & FSMEntryFlag::conditionalStateChange) {
469        // A conditional state table entry holds the address of a local
470        // that holds the next state.
471        void* addr = compute_addr_from_table(currFSMEntry, state, context);
472        state->state = *reinterpret_cast<int*>(addr);
473        _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::conditionalStateChange, dereference "
474                                  "addr(%p), set state=%d\n", addr, state->state);
475        continue; // We are done with this iteration of the loop, since we changed a state.
476      }
477      if (currFSMEntry->actionFlag == FSMEntryCount::beginCatch || currFSMEntry->actionFlag == FSMEntryCount::endCatch ||
478          currFSMEntry->actionFlag == FSMEntryCount::cleanupLabel) {
479
480        _LIBCXXABI_TRACE_STATETAB(
481            "FSMEntryCount::%s: handler %p/%p, return _URC_HANDLER_FOUND\n",
482            (currFSMEntry->actionFlag == FSMEntryCount::beginCatch
483                 ? "beginCatch"
484                 : (currFSMEntry->actionFlag == FSMEntryCount::endCatch ? "endCatch" : "cleanupLabel")),
485            currFSMEntry->landingPad, *reinterpret_cast<void**>(currFSMEntry->landingPad));
486
487        state->state = currFSMEntry->nextState;
488        results.landingPad = reinterpret_cast<uintptr_t>(*reinterpret_cast<void**>(currFSMEntry->landingPad));
489        results.reason = _URC_HANDLER_FOUND;
490        return;
491      }
492      if (currFSMEntry->elementCount > 0) {
493        if (currFSMEntry->flags & FSMEntryFlag::vBaseFlag && state->ignoreVBasePtrs) {
494          _LIBCXXABI_TRACE_STATETAB0("Ignoring virtual base dtor.\n");
495        } else {
496          // We need to invoke the virtual base destructor. This must be
497          // a frame from the legacy xlC compiler as the xlclang++ compiler
498          // generates inline cleanup code rather than specifying
499          // the destructor via the state table.
500          void* addr = compute_addr_from_table(currFSMEntry, state, context);
501
502          // An extra indirect to get to the object according to the object
503          // model used by the xlC compiler.
504          addr = reinterpret_cast<void*>(*reinterpret_cast<char**>(addr));
505          _LIBCXXABI_TRACE_STATETAB("Invoke dtor for object=%p\n", addr);
506          invoke_destructor(currFSMEntry, addr);
507        }
508      } else if (currFSMEntry->actionFlag == FSMEntryCount::deleteObject) {
509        void* addr = compute_addr_from_table(currFSMEntry, state, context);
510        if (currFSMEntry->flags & FSMEntryFlag::vBaseFlag) {
511          // We need to invoke the virtual base delete function. This must be
512          // a frame from the legacy xlC compiler as the xlclang++ compiler
513          // generates inline cleanup code rather than specifying
514          // the delete function via the state table.
515
516          // An extra indirect to get to the object according to the object
517          // model used by the xlC compiler.
518          addr = reinterpret_cast<void*>(*reinterpret_cast<char**>(addr));
519        }
520        _LIBCXXABI_TRACE_STATETAB("Delete object at %p\n", addr);
521        invoke_delete(currFSMEntry, addr);
522      } else {
523        _LIBCXXABI_TRACE_STATETAB("Unknown entry in FSM (count=%ld), ignored\n",
524                                  currFSMEntry->elementCount);
525      } // End of action switching.
526
527      // Go to next state.
528      state->state = currFSMEntry->nextState;
529    }
530    _LIBCXXABI_TRACE_STATETAB0("No catch handler, return _URC_CONTINUE_UNWIND\n");
531    results.reason = _URC_CONTINUE_UNWIND;
532    return;
533  }
534  _LIBCXXABI_TRACE_STATETAB0("No state table entry for this exception, call_terminate()\n");
535  // It is possible that no state table entry specify how to handle
536  // this exception. By spec, terminate it immediately.
537  call_terminate(native_exception, unwind_exception);
538}
539
540// Personality routine for EH using the state table.
541_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
542__xlcxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass,
543                       _Unwind_Exception* unwind_exception, _Unwind_Context* context) {
544  if (version != 1 || unwind_exception == 0 || context == 0)
545    return _URC_FATAL_PHASE1_ERROR;
546
547  bool native_exception = (exceptionClass & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language);
548  scan_results results;
549  scan_state_tab(results, actions, native_exception, unwind_exception, context);
550  if (actions & _UA_SEARCH_PHASE) {
551    // Phase 1 search:  All we're looking for in phase 1 is a handler that
552    //   halts unwinding
553    return results.reason;
554  }
555  if (actions & _UA_CLEANUP_PHASE) {
556    // Phase 2 cleanup:
557    if (results.reason == _URC_HANDLER_FOUND) {
558      // Store the address of unwind_exception in the stack field
559      // reserved for compilers (SP + 3 * sizeof(uintptr_t)) in the stack of
560      // the caller of the function containing the landing pad (within the link
561      // area for the call to the latter) for __xlc_exception_handle()
562      // to retrieve when it is called by the landing pad.
563      uintptr_t *currentSP = reinterpret_cast<uintptr_t*>(_Unwind_GetGR(context, 1));
564      uintptr_t *callersSP = reinterpret_cast<uintptr_t*>(currentSP[0]);
565      callersSP[3] = reinterpret_cast<uintptr_t>(unwind_exception);
566      _LIBCXXABI_TRACE_STATETAB("Handshake: set unwind_exception=%p in stack=%p\n", reinterpret_cast<void*>(unwind_exception), reinterpret_cast<void*>(callersSP));
567      // Jump to the handler.
568      _Unwind_SetIP(context, results.landingPad);
569      return _URC_INSTALL_CONTEXT;
570    }
571    // Did not find a handler. Return the results of the scan. Normally
572    // _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR.
573    return results.reason;
574  }
575  // We were called improperly: neither a phase 1 or phase 2 search.
576  return _URC_FATAL_PHASE1_ERROR;
577}
578} // namespace __state_table_eh
579
580// The following are EH helper functions for xlclang++ compiled code.
581
582// __xlc_catch_matchv2
583// Check whether the thrown object matches the catch handler's exception
584// declaration. If there is a match, the function returns true with adjusted
585// address of the thrown object. Otherwise, returns false.
586_LIBCXXABI_FUNC_VIS bool
587__xlc_catch_matchv2(_Unwind_Exception* exceptionObject, std::type_info* catchTypeInfo, void*& obj) {
588  _LIBCXXABI_TRACE_STATETAB("Entering %s, exceptionObject=%p\n", __func__, reinterpret_cast<void*>(exceptionObject));
589
590  if (!__isOurExceptionClass(exceptionObject)) {
591    _LIBCXXABI_TRACE_STATETAB0("No match, not a C++ exception\n");
592    return false;
593  }
594
595  __cxa_exception* exceptionHeader = 0;
596
597  if (__getExceptionClass(exceptionObject) == kOurDependentExceptionClass) {
598    // Walk to the __cxa_dependent_exception primary exception for the
599    // exception object and its type_info.
600    __cxa_dependent_exception* dependentExceptionHeader =
601        reinterpret_cast<__cxa_dependent_exception*>(exceptionObject + 1) - 1;
602    exceptionHeader = reinterpret_cast<__cxa_exception*>(dependentExceptionHeader->primaryException) - 1;
603    _LIBCXXABI_TRACE_STATETAB("exceptionObject 0x%p is a dependent, primary 0x%p\n",
604                              reinterpret_cast<void*>(exceptionObject),
605                              reinterpret_cast<void*>(&exceptionHeader->unwindHeader));
606    exceptionObject = &exceptionHeader->unwindHeader;
607  } else {
608    _LIBCXXABI_TRACE_STATETAB("exceptionObject %p is NOT a dependent\n", reinterpret_cast<void*>(exceptionObject));
609    exceptionHeader = reinterpret_cast<__cxa_exception*>(exceptionObject + 1) - 1;
610  }
611
612  void* thrownObject = reinterpret_cast<void*>(exceptionObject + 1);
613  std::type_info* throwTypeInfo = exceptionHeader->exceptionType;
614
615  // Get the type info for the thrown type and this catch clause and
616  // see if the catch caluse can catch that type.
617
618  __cxxabiv1::__shim_type_info* catchType = reinterpret_cast<__cxxabiv1::__shim_type_info*>(catchTypeInfo);
619  __cxxabiv1::__shim_type_info* throwType = reinterpret_cast<__cxxabiv1::__shim_type_info*>(throwTypeInfo);
620  _LIBCXXABI_TRACE_STATETAB("UnwindException=%p, thrownObject=%p, throwTypeInfo=%p(%s), catchTypeInfo=%p(%s)\n",
621                            reinterpret_cast<void*>(exceptionObject), thrownObject, reinterpret_cast<void*>(throwType),
622                            throwType->name(), reinterpret_cast<void*>(catchType), catchType->name());
623  if (catchType->can_catch(throwType, thrownObject)) {
624    exceptionHeader->adjustedPtr = thrownObject;
625    obj = thrownObject;
626    _LIBCXXABI_TRACE_STATETAB("Match found for thrownObject=%p\n", thrownObject);
627    return true;
628  }
629  _LIBCXXABI_TRACE_STATETAB0("No match\n");
630  return false;
631}
632
633// __xlc_throw_badexception
634// This function is for xlclang++. It allocates and throws a bad_exception.
635// During unwinding for this bad_exception, the previous exception which is
636// not matching the throw spec will be cleaned up. Thus having the same
637// effect as replace the top most exception (which is bad) with a bad_exception.
638_LIBCXXABI_FUNC_VIS void __xlc_throw_badexception() {
639  _LIBCXXABI_TRACE_STATETAB("Entering function: %s\n\n", __func__);
640  void* newexception = new (__cxa_allocate_exception(sizeof(std::bad_exception))) std::bad_exception;
641  __cxa_throw(newexception, const_cast<std::type_info*>(&typeid(std::bad_exception)), 0);
642}
643
644// force_a_stackframe
645// This function is called by __xlc_exception_handle() to ensure a stack frame
646// is created for __xlc_exception_handle().
647__attribute__((noinline, optnone))
648static void force_a_stackframe() {}
649
650// __xlc_exception_handle
651// This function is for xlclang++. It returns the address of the exception
652// object stored in the reserved field in the stack of the caller of the
653// function that calls __xlc_exception_handle() (within the link area for the
654// call to the latter). The address is stored by the personality routine for
655// xlclang++ compiled code. The implementation of __xlc_exception_handle()
656// assumes a stack frame is created for it. The following ensures this
657// assumption holds true: 1) a call to force_a_stackframe() is made inside
658// __xlc_exception_handle() to make it non-leaf; and 2) optimizations are
659// disabled for this function with attribute 'optnone'. Note: this function
660// may not work as expected if these are changed.
661__attribute__((optnone))
662_LIBCXXABI_FUNC_VIS uintptr_t __xlc_exception_handle() {
663  // Make a call to force_a_stackframe() so that the compiler creates a stack
664  // frame for this function.
665  force_a_stackframe();
666
667  // Get the SP of this function, i.e., __xlc_exception_handle().
668  uintptr_t *lastStack;
669  asm("mr %0, 1" : "=r"(lastStack));
670  // Get the SP of the caller of __xlc_exception_handle().
671  uintptr_t *callerStack = reinterpret_cast<uintptr_t*>(lastStack[0]);
672  // Get the SP of the caller of the caller.
673  uintptr_t *callerStack2 = reinterpret_cast<uintptr_t*>(callerStack[0]);
674  uintptr_t exceptionObject = callerStack2[3];
675  _LIBCXXABI_TRACE_STATETAB("Handshake: exceptionObject=%p from stack=%p\n", reinterpret_cast<void*>(exceptionObject), reinterpret_cast<void*>(callerStack2));
676  return exceptionObject;
677}
678
679// xlclang++ may generate calls to __Deleted_Virtual.
680_LIBCXXABI_FUNC_VIS void __Deleted_Virtual() { abort(); }
681
682// __catchThrownException is called during AIX library initialization and
683// termination to handle exceptions.  An implementation is also provided in
684// libC.a(shrcore.o).  This implementation is provided for applications that
685// link with -lc++ (the xlclang++ or ibm-clang++ link default.)
686_LIBCXXABI_FUNC_VIS int
687__catchThrownException(void (*cdfunc)(void),   // function which may fail
688                       void (*cleanup)(void*), // cleanup function
689                       void* cleanuparg,       // parameter to cleanup function
690                       int action) {           // control exception throwing and termination
691  enum Action : int { None = 0, Rethrow = 1, Terminate = 2 };
692  if (!cdfunc)
693    return 0;
694  if (action == Action::Rethrow && !cleanup) {
695    // No cleanup and rethrow is effectively no-op.
696    // Avoid the catch handler when possible to allow exceptions generated
697    // from xlC binaries to flow through.
698    (*cdfunc)();
699    return 0;
700  }
701  try {
702    (*cdfunc)();
703  } catch (...) {
704    if (action == Action::Terminate)
705      std::terminate();
706    if (cleanup)
707      (*cleanup)(cleanuparg);
708    if (action == Action::Rethrow)
709      throw;
710    assert(action == Action::None);
711    return -1; // FAILED
712  }
713  return 0;
714}
715
716}  // extern "C"
717
718}  // __cxxabiv1
719