1 /* ====================================================================
2 * Copyright (c) 2005 The OpenSSL Project. Rights for redistribution
3 * and usage in source and binary forms are granted according to the
13 const void *FIPS_text_start(void);
14 const void *FIPS_text_end(void);
18 #if !defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
19 # if (defined(__sun) && (defined(__sparc) || defined(__sparcv9))) || \
20 (defined(__sgi) && (defined(__mips) || defined(mips))) || \
21 (defined(__osf__) && defined(__alpha)) || \
22 (defined(__linux) && (defined(__arm) || defined(__arm__))) || \
23 (defined(__i386) || defined(__i386__)) || \
24 (defined(__x86_64) || defined(__x86_64__)) || \
25 (defined(vax) || defined(__vax__))
26 # define POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION
30 #if !defined(FIPS_REF_POINT_IS_CROSS_COMPILER_AWARE)
31 # if (defined(__ANDROID__) && (defined(__arm__) || defined(__arm) || \
32 defined(__i386__)|| defined(__i386))) || \
33 (defined(__vxworks) && (defined(__ppc__) || defined(__ppc) || \
34 defined(__mips__)|| defined(__mips))) || \
35 (defined(__linux) && ((defined(__PPC__) && !defined(__PPC64__)) || \
36 defined(__arm__) || defined(__arm))) || \
37 (defined(__APPLE__) /* verified on all MacOS X & iOS flavors */)|| \
38 (defined(_WIN32) && defined(_MSC_VER))
39 # define FIPS_REF_POINT_IS_CROSS_COMPILER_AWARE
43 #if defined(__xlC__) && __xlC__>=0x600 && (defined(_POWER) || defined(_ARCH_PPC))
44 static void *instruction_pointer_xlc(void);
45 # pragma mc_func instruction_pointer_xlc {\
46 "7c0802a6" /* mflr r0 */ \
47 "48000005" /* bl $+4 */ \
48 "7c6802a6" /* mflr r3 */ \
49 "7c0803a6" /* mtlr r0 */ }
50 # pragma reg_killed_by instruction_pointer_xlc gr0 gr3
51 # define INSTRUCTION_POINTER_IMPLEMENTED(ret) (ret=instruction_pointer_xlc());
55 # define FIPS_ref_point FIPS_text_start
56 # ifdef FIPS_REF_POINT_IS_CROSS_COMPILER_AWARE
57 # define instruction_pointer FIPS_text_startX
59 /* Some compilers put string literals into a separate segment. As we
60 * are mostly interested to hash AES tables in .rodata, we declare
61 * reference points accordingly. In case you wonder, the values are
62 * big-endian encoded variable names, just to prevent these arrays
63 * from being merged by linker. */
64 # if defined(_MSC_VER)
65 # pragma code_seg("fipstx")
67 __declspec(allocate("fipstx"))
68 const unsigned int FIPS_text_startX[]=
69 { 0x46495053, 0x5f746578, 0x745f7374, 0x61727458 };
70 # pragma const_seg("fipsro$a")
72 __declspec(allocate("fipsro$a"))
74 const unsigned int FIPS_rodata_start[]=
75 { 0x46495053, 0x5f726f64, 0x6174615f, 0x73746172 };
77 # define FIPS_ref_point FIPS_text_end
78 # ifdef FIPS_REF_POINT_IS_CROSS_COMPILER_AWARE
79 # define instruction_pointer FIPS_text_endX
81 # if defined(_MSC_VER)
82 # pragma code_seg("fipstx$z")
84 __declspec(allocate("fipstx$z"))
85 const unsigned int FIPS_text_endX[]=
86 { 0x46495053, 0x5f746578, 0x745f656e, 0x64585b5d };
87 # pragma const_seg("fipsro$z")
89 __declspec(allocate("fipsro$z"))
91 const unsigned int FIPS_rodata_end[]=
92 { 0x46495053, 0x5f726f64, 0x6174615f, 0x656e645b };
95 #if !defined(_MSC_VER) || !defined(instruction_pointer)
97 * I declare reference function as static in order to avoid certain
98 * pitfalls in -dynamic linker behaviour...
100 static void *instruction_pointer(void)
102 /* These are ABI-neutral CPU-specific snippets. ABI-neutrality means
103 * that they are designed to work under any OS running on particular
104 * CPU, which is why you don't find any #ifdef THIS_OR_THAT_OS in
106 #if defined(INSTRUCTION_POINTER_IMPLEMENTED)
107 INSTRUCTION_POINTER_IMPLEMENTED(ret);
108 #elif defined(__GNUC__) && __GNUC__>=2
109 # if defined(__alpha) || defined(__alpha__)
110 # define INSTRUCTION_POINTER_IMPLEMENTED
111 __asm __volatile ( "br %0,1f\n1:" : "=r"(ret) );
112 # elif defined(__i386) || defined(__i386__)
113 # define INSTRUCTION_POINTER_IMPLEMENTED
114 __asm __volatile ( "call 1f\n1: popl %0" : "=r"(ret) );
115 ret = (void *)((size_t)ret&~3UL); /* align for better performance */
116 # elif defined(__ia64) || defined(__ia64__)
117 # define INSTRUCTION_POINTER_IMPLEMENTED
118 __asm __volatile ( "mov %0=ip" : "=r"(ret) );
119 # elif defined(__hppa) || defined(__hppa__) || defined(__pa_risc)
120 # define INSTRUCTION_POINTER_IMPLEMENTED
121 __asm __volatile ( "blr %%r0,%0\n\tnop" : "=r"(ret) );
122 ret = (void *)((size_t)ret&~3UL); /* mask privilege level */
123 # elif defined(__mips) || defined(__mips__)
124 # define INSTRUCTION_POINTER_IMPLEMENTED
126 __asm __volatile ( "move %1,$31\n\t" /* save ra */
129 "move $31,%1" /* restore ra */
130 : "=r"(ret),"=r"(scratch) );
131 # elif defined(__ppc__) || defined(__ppc) || \
132 defined(__powerpc) || defined(__powerpc__) || \
133 defined(__POWERPC__) || defined(_POWER) || defined(__PPC__) || \
134 defined(__PPC64__) || defined(__ppc64__) || defined(__powerpc64__)
135 # define INSTRUCTION_POINTER_IMPLEMENTED
137 __asm __volatile ( "mfspr %1,8\n\t" /* save lr */
139 "mfspr %0,8\n\t" /* mflr ret */
140 "mtspr 8,%1" /* restore lr */
141 : "=r"(ret),"=r"(scratch) );
142 # elif defined(__s390__) || defined(__s390x__)
143 # define INSTRUCTION_POINTER_IMPLEMENTED
144 __asm __volatile ( "bras %0,1f\n1:" : "=r"(ret) );
145 ret = (void *)((size_t)ret&~3UL);
146 # elif defined(__sparc) || defined(__sparc__) || defined(__sparcv9)
147 # define INSTRUCTION_POINTER_IMPLEMENTED
149 __asm __volatile ( "mov %%o7,%1\n\t"
153 : "=r"(ret),"=r"(scratch) );
154 # elif defined(__x86_64) || defined(__x86_64__)
155 # define INSTRUCTION_POINTER_IMPLEMENTED
156 __asm __volatile ( "leaq 0(%%rip),%0" : "=r"(ret) );
157 ret = (void *)((size_t)ret&~3UL); /* align for better performance */
158 # elif defined(__arm) || defined(__arm__)
159 # define INSTRUCTION_POINTER_IMPLEMENTED
160 __asm __volatile ( "sub %0,pc,#8" : "=r"(ret) );
162 #elif defined(__DECC) && defined(__alpha)
163 # define INSTRUCTION_POINTER_IMPLEMENTED
164 ret = (void *)(size_t)asm("br %v0,1f\n1:");
165 #elif defined(_MSC_VER) && defined(_M_IX86)
166 # define INSTRUCTION_POINTER_IMPLEMENTED
173 ret = (void *)((size_t)scratch&~3UL);
180 * This function returns pointer to an instruction in the vicinity of
181 * its entry point, but not outside this object module. This guarantees
182 * that sequestered code is covered...
184 const void *FIPS_ref_point()
186 #if defined(FIPS_REF_POINT_IS_CROSS_COMPILER_AWARE)
187 # if defined(__thumb__) || defined(__thumb)
188 return (void *)((size_t)instruction_pointer&~1);
190 return (void *)instruction_pointer;
192 #elif defined(INSTRUCTION_POINTER_IMPLEMENTED)
193 return instruction_pointer();
194 /* Below we essentially cover vendor compilers which do not support
195 * inline assembler... */
197 struct { void *ip,*gp,*env; } *p = (void *)instruction_pointer;
199 #elif defined(_HPUX_SOURCE)
200 # if defined(__hppa) || defined(__hppa__)
201 struct { void *i[4]; } *p = (void *)FIPS_ref_point;
203 if (sizeof(p) == 8) /* 64-bit */
205 else if ((size_t)p & 2)
206 { p = (void *)((size_t)p&~3UL);
211 # elif defined(__ia64) || defined(__ia64__)
212 struct { unsigned long long ip,gp; } *p=(void *)instruction_pointer;
213 return (void *)(size_t)p->ip;
215 #elif (defined(__VMS) || defined(VMS)) && !(defined(vax) || defined(__vax__))
216 /* applies to both alpha and ia64 */
217 struct { unsigned __int64 opaque,ip; } *p=(void *)instruction_pointer;
218 return (void *)(size_t)p->ip;
219 #elif defined(__VOS__)
220 /* applies to both pa-risc and ia32 */
221 struct { void *dp,*ip,*gp; } *p = (void *)instruction_pointer;
223 #elif defined(_WIN32)
224 # if defined(_WIN64) && defined(_M_IA64)
225 struct { void *ip,*gp; } *p = (void *)FIPS_ref_point;
228 return (void *)FIPS_ref_point;
231 * In case you wonder why there is no #ifdef __linux. All Linux targets
232 * are GCC-based and therefore are covered by instruction_pointer above
233 * [well, some are covered by by the one below]...
235 #elif defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
236 return (void *)instruction_pointer;