C++程序  |  333行  |  9.43 KB

// Copyright (C) 2013 The Android Open Source Project
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.

#ifndef _GABIXX_CXXABI_DEFINES_H
#define _GABIXX_CXXABI_DEIFNES_H

#include <cxxabi.h>
#include <stdint.h>

// Internal declarations for the implementation of <cxxabi.h> and
// related headers.

namespace __cxxabiv1 {

// Derived types of type_info below are based on 2.9.5 of C++ ABI.

class __shim_type_info : public std::type_info
{
  public:
  virtual ~__shim_type_info();
  virtual bool can_catch(const __shim_type_info* thrown_type,
                          void*& adjustedPtr) const = 0;
};

// Typeinfo for fundamental types.
class __fundamental_type_info : public __shim_type_info
{
public:
  virtual ~__fundamental_type_info();
  virtual bool can_catch(const __shim_type_info* thrown_type,
                          void*& adjustedPtr) const;
};

// Typeinfo for array types.
class __array_type_info : public __shim_type_info
{
public:
  virtual ~__array_type_info();
  virtual bool can_catch(const __shim_type_info* thrown_type,
                          void*& adjustedPtr) const;
};

// Typeinfo for function types.
class __function_type_info : public __shim_type_info
{
public:
  virtual ~__function_type_info();
  virtual bool can_catch(const __shim_type_info* thrown_type,
                          void*& adjustedPtr) const;
};

// Typeinfo for enum types.
class __enum_type_info : public __shim_type_info
{
public:
  virtual ~__enum_type_info();
  virtual bool can_catch(const __shim_type_info* thrown_type,
                          void*& adjustedPtr) const;
};


class __class_type_info;

// Used in __vmi_class_type_info
struct __base_class_type_info
{
public:
  const __class_type_info *__base_type;

  long __offset_flags;

  enum __offset_flags_masks {
    __virtual_mask = 0x1,
    __public_mask = 0x2,
    __offset_shift = 8   // lower 8 bits are flags
  };

  bool is_virtual() const {
    return (__offset_flags & __virtual_mask) != 0;
  }

  bool is_public() const {
    return (__offset_flags & __public_mask) != 0;
  }

  // FIXME: Right-shift of signed integer is implementation dependent.
  // GCC Implements it as signed (as we expect)
  long offset() const {
    return __offset_flags >> __offset_shift;
  }

  long flags() const {
    return __offset_flags & ((1 << __offset_shift) - 1);
  }
};

// Helper struct to support catch-clause match
struct __UpcastInfo {
  enum ContainedStatus {
    unknown = 0,
    has_public_contained,
    has_ambig_or_not_public
  };

  ContainedStatus status;
  const __class_type_info* base_type;
  void* adjustedPtr;
  unsigned int premier_flags;
  bool nullobj_may_conflict;

  __UpcastInfo(const __class_type_info* type);
};

// Typeinfo for classes with no bases.
class __class_type_info : public __shim_type_info
{
public:
  virtual ~__class_type_info();
  virtual bool can_catch(const __shim_type_info* thrown_type,
                          void*& adjustedPtr) const;

  enum class_type_info_code {
    CLASS_TYPE_INFO_CODE,
    SI_CLASS_TYPE_INFO_CODE,
    VMI_CLASS_TYPE_INFO_CODE
  };

  virtual class_type_info_code
    code() const { return CLASS_TYPE_INFO_CODE; }

  virtual bool walk_to(const __class_type_info* base_type,
                        void*& adjustedPtr,
                        __UpcastInfo& info) const;

protected:
  bool self_class_type_match(const __class_type_info* base_type,
                              void*& adjustedPtr,
                              __UpcastInfo& info) const;
};

// Typeinfo for classes containing only a single, public, non-virtual base at
// offset zero.
class __si_class_type_info : public __class_type_info
{
public:
  virtual ~__si_class_type_info();
  const __class_type_info *__base_type;

  virtual __class_type_info::class_type_info_code
    code() const { return SI_CLASS_TYPE_INFO_CODE; }

  virtual bool walk_to(const __class_type_info* base_type,
                        void*& adjustedPtr,
                        __UpcastInfo& info) const;
};


// Typeinfo for classes with bases that do not satisfy the
// __si_class_type_info constraints.
class __vmi_class_type_info : public __class_type_info
{
public:
  virtual ~__vmi_class_type_info();
  unsigned int __flags;
  unsigned int __base_count;
  __base_class_type_info __base_info[1];

  enum __flags_masks {
    __non_diamond_repeat_mask = 0x1,
    __diamond_shaped_mask = 0x2,
  };

  virtual __class_type_info::class_type_info_code
    code() const { return VMI_CLASS_TYPE_INFO_CODE; }

  virtual bool walk_to(const __class_type_info* base_type,
                        void*& adjustedPtr,
                        __UpcastInfo& info) const;
};

class __pbase_type_info : public __shim_type_info
{
public:
  virtual ~__pbase_type_info();
  virtual bool can_catch(const __shim_type_info* thrown_type,
                          void*& adjustedPtr) const;
  unsigned int __flags;
  const __shim_type_info* __pointee;

  enum __masks {
    __const_mask = 0x1,
    __volatile_mask = 0x2,
    __restrict_mask = 0x4,
    __incomplete_mask = 0x8,
    __incomplete_class_mask = 0x10
  };


  virtual bool can_catch_typeinfo_wrapper(const __shim_type_info* thrown_type,
                                          void*& adjustedPtr,
                                          unsigned tracker) const;

protected:
  enum __constness_tracker_status {
    first_time_init = 0x1,
    keep_constness = 0x2,
    after_gap = 0x4         // after one non-const qualified,
                            // we cannot face const again in future
  };

private:
  bool can_catch_ptr(const __pbase_type_info *thrown_type,
                      void *&adjustedPtr,
                      unsigned tracker) const;

  // Return true if making decision done.
  virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
                                void*& adjustedPtr,
                                unsigned tracker,
                                bool& result) const = 0;
};

class __pointer_type_info : public __pbase_type_info
{
public:
  virtual ~__pointer_type_info();

private:
  virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
                                void*& adjustedPtr,
                                unsigned tracker,
                                bool& result) const;
};

class __pointer_to_member_type_info : public __pbase_type_info
{
public:
  __class_type_info* __context;

  virtual ~__pointer_to_member_type_info();

private:
  virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
                                void*& adjustedPtr,
                                unsigned tracker,
                                bool& result) const;
};

extern "C" {

// Compatible with GNU C++
const uint64_t __gxx_exception_class = 0x474E5543432B2B00LL; // GNUCC++\0

struct __cxa_exception {
  size_t referenceCount;

  std::type_info* exceptionType;
  void (*exceptionDestructor)(void*);
  std::unexpected_handler unexpectedHandler;
  std::terminate_handler terminateHandler;
  __cxa_exception* nextException;

    int handlerCount;
#ifdef __arm__
  /**
    * ARM EHABI requires the unwind library to keep track of exceptions
    * during cleanups.  These support nesting, so we need to keep a list of
    * them.
    */
  __cxa_exception* nextCleanup;
  int cleanupCount;
#endif
    int handlerSwitchValue;
    const uint8_t* actionRecord;
    const uint8_t* languageSpecificData;
    void* catchTemp;
    void* adjustedPtr;

    _Unwind_Exception unwindHeader; // must be last
};

struct __cxa_eh_globals {
  __cxa_exception* caughtExceptions;
  unsigned int uncaughtExceptions;
#ifdef __arm__
  __cxa_exception* cleanupExceptions;
#endif
};

}  // extern "C"
}  // namespace __cxxabiv1

namespace __gabixx {

// Default terminate handler.
_GABIXX_NORETURN void __default_terminate(void) _GABIXX_HIDDEN;

// Call |handler| and if it returns, call __default_terminate.
_GABIXX_NORETURN void __terminate(std::terminate_handler handler)
    _GABIXX_HIDDEN;

// Print a fatal error message to the log+stderr, then call
// std::terminate().
_GABIXX_NORETURN void __fatal_error(const char* message) _GABIXX_HIDDEN;

}  // __gabixx

#endif  // _GABIXX_CXXABI_DEFINES_H