#ifndef CODEDEFENDER_H
#define CODEDEFENDER_H
#if defined(__cplusplus)
#define EXTERN_C extern "C"
#else
#define EXTERN_C extern
#endif
#if defined(_MSC_VER)
#define CODEDEFENDER_NOINLINE __declspec(noinline)
#elif defined(__GNUC__) || defined(__clang__)
#define CODEDEFENDER_NOINLINE __attribute__((noinline))
#else
#define CODEDEFENDER_NOINLINE
#endif
#if defined(_MSC_VER)
#define CODEDEFENDER_SECTION EXTERN_C __declspec(allocate(".cdmacro"))
#pragma section(".cdmacro", read)
#define CODEDEFENDER_STRINGIFY2(x) #x
#define CODEDEFENDER_STRINGIFY(x) CODEDEFENDER_STRINGIFY2(x)
#define CODEDEFENDER_PRAGMA_LINKER_INCLUDE(symbol) \
__pragma(comment(linker, "/INCLUDE:" #symbol))
#define CODEDEFENDER_SYMBOL_NAME(fn) \
"_" \
" __cdmacro_entry_" #fn
#define CODEDEFENDER(Profile, ReturnTy, Func, Params) \
CODEDEFENDER_NOINLINE ReturnTy Func Params; \
__pragma(pack(push, 1)) __declspec(align(1)) CODEDEFENDER_SECTION struct { \
void* pFunc; \
char str[sizeof(Profile)]; \
} __cdmacro_entry_##Func = {(void*)Func, Profile}; \
__pragma(pack(pop)) CODEDEFENDER_PRAGMA_LINKER_INCLUDE(__cdmacro_entry_##Func)
#elif defined(__GNUC__) || defined(__clang__)
#define CODEDEFENDER_SECTION __attribute__((section(".cdmacro"), used))
#define CODEDEFENDER(Profile, ReturnTy, Func, Params) \
CODEDEFENDER_NOINLINE ReturnTy Func Params; \
CODEDEFENDER_SECTION const struct { \
void* pFunc; \
char str[sizeof(Profile)]; \
} __cdmacro_entry_##Func = {(void*)Func, Profile}; \
CODEDEFENDER_PRAGMA_LINKER_INCLUDE(__cdmacro_entry_##Func)
#endif
#endif