1/* ==================================================================== 2 * Copyright (c) 2005 The OpenSSL Project. Rights for redistribution 3 * and usage in source and binary forms are granted according to the 4 * OpenSSL license. 5 */ 6 7#include <stdio.h> 8#if defined(__DECC) 9# include <c_asm.h> 10# pragma __nostandard 11#endif 12 13#include "e_os.h" 14 15#if !defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION) 16# if (defined(__sun) && (defined(__sparc) || defined(__sparcv9))) || \ 17 (defined(__sgi) && (defined(__mips) || defined(mips))) || \ 18 (defined(__osf__) && defined(__alpha)) || \ 19 (defined(__linux) && (defined(__arm) || defined(__arm__))) || \ 20 (defined(__i386) || defined(__i386__)) || \ 21 (defined(__x86_64) || defined(__x86_64__)) || \ 22 defined(__ANDROID__) || \ 23 (defined(vax) || defined(__vax__)) 24# define POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION 25# endif 26#endif 27 28#if defined(__xlC__) && __xlC__>=0x600 && (defined(_POWER) || defined(_ARCH_PPC)) 29static void *instruction_pointer_xlc(void); 30# pragma mc_func instruction_pointer_xlc {\ 31 "7c0802a6" /* mflr r0 */ \ 32 "48000005" /* bl $+4 */ \ 33 "7c6802a6" /* mflr r3 */ \ 34 "7c0803a6" /* mtlr r0 */ } 35# pragma reg_killed_by instruction_pointer_xlc gr0 gr3 36# define INSTRUCTION_POINTER_IMPLEMENTED(ret) (ret=instruction_pointer_xlc()); 37#endif 38 39#ifdef FIPS_START 40#define FIPS_ref_point FIPS_text_start 41/* Some compilers put string literals into a separate segment. As we 42 * are mostly interested to hash AES tables in .rodata, we declare 43 * reference points accordingly. In case you wonder, the values are 44 * big-endian encoded variable names, just to prevent these arrays 45 * from being merged by linker. */ 46const unsigned int FIPS_rodata_start[]= 47 { 0x46495053, 0x5f726f64, 0x6174615f, 0x73746172 }; 48#else 49#define FIPS_ref_point FIPS_text_end 50const unsigned int FIPS_rodata_end[]= 51 { 0x46495053, 0x5f726f64, 0x6174615f, 0x656e645b }; 52#endif 53 54/* 55 * I declare reference function as static in order to avoid certain 56 * pitfalls in -dynamic linker behaviour... 57 */ 58static void *instruction_pointer(void) 59{ void *ret=NULL; 60/* These are ABI-neutral CPU-specific snippets. ABI-neutrality means 61 * that they are designed to work under any OS running on particular 62 * CPU, which is why you don't find any #ifdef THIS_OR_THAT_OS in 63 * this function. */ 64#if defined(INSTRUCTION_POINTER_IMPLEMENTED) 65 INSTRUCTION_POINTER_IMPLEMENTED(ret); 66#elif defined(__GNUC__) && __GNUC__>=2 67# if defined(__alpha) || defined(__alpha__) 68# define INSTRUCTION_POINTER_IMPLEMENTED 69 __asm __volatile ( "br %0,1f\n1:" : "=r"(ret) ); 70# elif defined(__i386) || defined(__i386__) 71# define INSTRUCTION_POINTER_IMPLEMENTED 72 __asm __volatile ( "call 1f\n1: popl %0" : "=r"(ret) ); 73 ret = (void *)((size_t)ret&~3UL); /* align for better performance */ 74# elif defined(__ia64) || defined(__ia64__) 75# define INSTRUCTION_POINTER_IMPLEMENTED 76 __asm __volatile ( "mov %0=ip" : "=r"(ret) ); 77# elif defined(__hppa) || defined(__hppa__) || defined(__pa_risc) 78# define INSTRUCTION_POINTER_IMPLEMENTED 79 __asm __volatile ( "blr %%r0,%0\n\tnop" : "=r"(ret) ); 80 ret = (void *)((size_t)ret&~3UL); /* mask privilege level */ 81# elif defined(__mips) || defined(__mips__) 82# define INSTRUCTION_POINTER_IMPLEMENTED 83 void *scratch; 84 __asm __volatile ( "move %1,$31\n\t" /* save ra */ 85 "bal .+8; nop\n\t" 86 "move %0,$31\n\t" 87 "move $31,%1" /* restore ra */ 88 : "=r"(ret),"=r"(scratch) ); 89# elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \ 90 defined(__POWERPC__) || defined(_POWER) || defined(__PPC__) || \ 91 defined(__PPC64__) || defined(__powerpc64__) 92# define INSTRUCTION_POINTER_IMPLEMENTED 93 void *scratch; 94 __asm __volatile ( "mfspr %1,8\n\t" /* save lr */ 95 "bl $+4\n\t" 96 "mfspr %0,8\n\t" /* mflr ret */ 97 "mtspr 8,%1" /* restore lr */ 98 : "=r"(ret),"=r"(scratch) ); 99# elif defined(__s390__) || defined(__s390x__) 100# define INSTRUCTION_POINTER_IMPLEMENTED 101 __asm __volatile ( "bras %0,1f\n1:" : "=r"(ret) ); 102 ret = (void *)((size_t)ret&~3UL); 103# elif defined(__sparc) || defined(__sparc__) || defined(__sparcv9) 104# define INSTRUCTION_POINTER_IMPLEMENTED 105 void *scratch; 106 __asm __volatile ( "mov %%o7,%1\n\t" 107 "call .+8; nop\n\t" 108 "mov %%o7,%0\n\t" 109 "mov %1,%%o7" 110 : "=r"(ret),"=r"(scratch) ); 111# elif defined(__x86_64) || defined(__x86_64__) 112# define INSTRUCTION_POINTER_IMPLEMENTED 113 __asm __volatile ( "leaq 0(%%rip),%0" : "=r"(ret) ); 114 ret = (void *)((size_t)ret&~3UL); /* align for better performance */ 115# endif 116#elif defined(__DECC) && defined(__alpha) 117# define INSTRUCTION_POINTER_IMPLEMENTED 118 ret = (void *)(size_t)asm("br %v0,1f\n1:"); 119#elif defined(_MSC_VER) && defined(_M_IX86) 120# define INSTRUCTION_POINTER_IMPLEMENTED 121 void *scratch; 122 _asm { 123 call self 124 self: pop eax 125 mov scratch,eax 126 } 127 ret = (void *)((size_t)scratch&~3UL); 128#endif 129 return ret; 130} 131 132/* 133 * This function returns pointer to an instruction in the vicinity of 134 * its entry point, but not outside this object module. This guarantees 135 * that sequestered code is covered... 136 */ 137void *FIPS_ref_point() 138{ 139#if defined(INSTRUCTION_POINTER_IMPLEMENTED) 140 return instruction_pointer(); 141/* Below we essentially cover vendor compilers which do not support 142 * inline assembler... */ 143#elif defined(_AIX) 144 struct { void *ip,*gp,*env; } *p = (void *)instruction_pointer; 145 return p->ip; 146#elif defined(_HPUX_SOURCE) 147# if defined(__hppa) || defined(__hppa__) 148 struct { void *i[4]; } *p = (void *)FIPS_ref_point; 149 150 if (sizeof(p) == 8) /* 64-bit */ 151 return p->i[2]; 152 else if ((size_t)p & 2) 153 { p = (void *)((size_t)p&~3UL); 154 return p->i[0]; 155 } 156 else 157 return (void *)p; 158# elif defined(__ia64) || defined(__ia64__) 159 struct { unsigned long long ip,gp; } *p=(void *)instruction_pointer; 160 return (void *)(size_t)p->ip; 161# endif 162#elif (defined(__VMS) || defined(VMS)) && !(defined(vax) || defined(__vax__)) 163 /* applies to both alpha and ia64 */ 164 struct { unsigned __int64 opaque,ip; } *p=(void *)instruction_pointer; 165 return (void *)(size_t)p->ip; 166#elif defined(__VOS__) 167 /* applies to both pa-risc and ia32 */ 168 struct { void *dp,*ip,*gp; } *p = (void *)instruction_pointer; 169 return p->ip; 170#elif defined(_WIN32) 171# if defined(_WIN64) && defined(_M_IA64) 172 struct { void *ip,*gp; } *p = (void *)FIPS_ref_point; 173 return p->ip; 174# else 175 return (void *)FIPS_ref_point; 176# endif 177/* 178 * In case you wonder why there is no #ifdef __linux. All Linux targets 179 * are GCC-based and therefore are covered by instruction_pointer above 180 * [well, some are covered by by the one below]... 181 */ 182#elif defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION) 183 return (void *)instruction_pointer; 184#else 185 return NULL; 186#endif 187} 188