/* Weak Symbol Checks Copyright 1983-2020 Green Hills Software, Inc. This program is the property of Green Hills Software, Inc, its contents are proprietary information and no part of it is to be disclosed to anyone except employees of Green Hills Software, Inc., or as agreed in writing signed by the President of Green Hills Software, Inc. */ #ifndef IND_WEAK_H #define IND_WEAK_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* __ghs_weak_func_exists(fname) * * fname must be the name of an imported weak function definition or an imported * non-weak function definition. Returns true if the definition exists and * may be called or false if the imported references does not exist and should * not be called. (Non-weak references normally exist because the code will * not link otherwise.) */ #if defined(__ghs_pic) || defined(__ghs_ropi) extern void __ghs_undefined_func (void); #pragma weak __ghs_undefined_func #define __ghs_weak_func_exists(fname) ((void (*)(void))(fname) != __ghs_undefined_func) #else #define __ghs_weak_func_exists(fname) ((void *)(fname) != (void *)0) #endif /* pic/ropi */ /* __ghs_weak_var_exists(v) * * v must be the name of an imported weak variable definition or an imported * non-weak variable definition. Returns true if the definition exists and * may be accessed or false if the imported references does not exist and should * not be accessed. (Non-weak references normally exist because the code will * not link otherwise.) */ #if defined(__ghs_pid) #pragma weak __ghs_undefined_var extern void *__ghs_undefined_var; #define __ghs_weak_var_exists(v) (((void**)&(v)) != &__ghs_undefined_var) #else #define __ghs_weak_var_exists(v) (&(v) != (void *)0) #endif /* This is used in ind_crt0.c to get the address of a linker-defined text * label that is declared as an external function. Normally we can just use * the identifier name to get the address, but with indirect-function call * checks we have the address of an descriptor, and we must load the * descriptor to get the address. */ #if defined(__ghs_ifcc) #if defined(__x86_64__) /* On x64, the decriptor is runnable code. The address is at an offset * of two bytes from the beginning. */ static inline void * __get_address(unsigned long x) { if (x == 0) return 0; return *(void * __packed *)(x+2); } #define __ghs_funcadjust(x) (__get_address((unsigned long)(x))) #elif defined(__aarch64__) || defined(__ARM__) /* On ARM64, the descriptor is also runnable code. The pool entry is * at an offset of 8 or 16 from the beginning of the descriptor * depending on whether the straightline spectre mitigations are * being used. */ /* ARM doesn't currently do straightline spectre mitigation, so the * pool entry is also at an offset of 8. */ static inline void * __get_address(unsigned long x) { if (x == 0) return 0; #if defined(__ARM__) /* Strip off any Thumb bit */ x &= ~(unsigned long)1; #endif /* defined(__ARM__) */ #if defined(__ghs_straightline_spectre_mitigation) x += 16; #else x += 8; #endif /* defined(__ghs_straightline_spectre_mitigation) */ return *(void **)x; } #define __ghs_funcadjust(x) (__get_address((unsigned long)(x))) #else #error Unexpected non-descriptor case static inline void * __get_address(unsigned long x) { if (x == 0) return 0; return *(void **)x; } #define __ghs_funcadjust(x) (__get_address((unsigned long)(x))) #endif /* defined(__x86_64__) vs ... */ #else #define __ghs_funcadjust(x) (x) #endif /* FUNCADJUST */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* IND_WEAK_H */