]> git.saurik.com Git - apple/xnu.git/blobdiff - libkern/libkern/c++/OSMetaClass.h
xnu-1228.9.59.tar.gz
[apple/xnu.git] / libkern / libkern / c++ / OSMetaClass.h
index fd4bc66b6124c12702050e3b58f818ca1701e1d2..ef527fdd7dce5896d3f678e68a20117c72829fb1 100644 (file)
@@ -48,6 +48,14 @@ class OSSerialize;
 
 #define APPLE_KEXT_VTABLE_PADDING   1
 
+#if defined(__LP64__)
+#define        APPLE_KEXT_LEGACY_ABI   0
+#elif defined(__arm__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
+#define        APPLE_KEXT_LEGACY_ABI   0
+#else
+#define        APPLE_KEXT_LEGACY_ABI   1
+#endif
+
 #if APPLE_KEXT_VTABLE_PADDING
 #define APPLE_KEXT_PAD_METHOD      virtual
 #define APPLE_KEXT_PAD_IMPL(index)  gMetaClass.reservedCalled(index)
@@ -100,13 +108,14 @@ public:
 #define OSCheckTypeInst(typeinst, inst) \
     OSMetaClassBase::checkTypeInst(inst, typeinst)
     
+typedef void (*_ptf_t)(void);
+
+#if APPLE_KEXT_LEGACY_ABI
 
 // Arcane evil code interprets a C++ pointer to function as specified in the
 // -fapple-kext ABI, i.e. the gcc-2.95 generated code.  IT DOES NOT ALLOW
 // the conversion of functions that are from MULTIPLY inherited classes.
 
-typedef void (*_ptf_t)(void);
-
 static inline _ptf_t
 _ptmf2ptf(const OSMetaClassBase *self, void (OSMetaClassBase::*func)(void))
 {
@@ -141,6 +150,43 @@ _ptmf2ptf(const OSMetaClassBase *self, void (OSMetaClassBase::*func)(void))
     }
 }
 
+#else /* !APPLE_KEXT_LEGACY_ABI */
+
+
+// Slightly less arcane and slightly less evil code to do
+// the same for kexts compiled with the standard Itanium C++
+// ABI
+
+static inline _ptf_t
+_ptmf2ptf(const OSMetaClassBase *self, void (OSMetaClassBase::*func)(void))
+{
+    union {
+       void (OSMetaClassBase::*fIn)(void);
+       uintptr_t fVTOffset;
+       _ptf_t fPFN;
+    } map;
+
+    map.fIn = func;
+
+    if (map.fVTOffset & 1) {
+       // virtual
+       union {
+           const OSMetaClassBase *fObj;
+           _ptf_t **vtablep;
+       } u;
+       u.fObj = self;
+
+       // Virtual member function so dereference vtable
+       return *(_ptf_t *)(((uintptr_t)*u.vtablep) + map.fVTOffset - 1);
+    } else {
+       // Not virtual, i.e. plain member func
+       return map.fPFN;
+    }
+}
+
+
+#endif /* !APPLE_KEXT_LEGACY_ABI */
+
 /*! @function OSMemberFunctionCast
     @abstract Convert a pointer to a member function to a c-style pointer to function.  No warnings are generated.
     @param type The type of pointer function desired.