2008-09-16 10:12:23 +00:00
|
|
|
/* ====================================================================
|
|
|
|
* Copyright (c) 2005 The OpenSSL Project. Rights for redistribution
|
|
|
|
* and usage in source and binary forms are granted according to the
|
|
|
|
* OpenSSL license.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#if defined(__DECC)
|
|
|
|
# include <c_asm.h>
|
|
|
|
# pragma __nostandard
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "e_os.h"
|
|
|
|
|
|
|
|
#if !defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
|
2015-01-22 02:47:42 +00:00
|
|
|
# if (defined(__sun) && (defined(__sparc) || defined(__sparcv9))) || \
|
|
|
|
(defined(__sgi) && (defined(__mips) || defined(mips))) || \
|
|
|
|
(defined(__osf__) && defined(__alpha)) || \
|
|
|
|
(defined(__linux) && (defined(__arm) || defined(__arm__))) || \
|
|
|
|
(defined(__i386) || defined(__i386__)) || \
|
|
|
|
(defined(__x86_64) || defined(__x86_64__)) || \
|
|
|
|
defined(__ANDROID__) || \
|
|
|
|
(defined(vax) || defined(__vax__))
|
2008-09-16 10:12:23 +00:00
|
|
|
# define POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__xlC__) && __xlC__>=0x600 && (defined(_POWER) || defined(_ARCH_PPC))
|
|
|
|
static void *instruction_pointer_xlc(void);
|
|
|
|
# pragma mc_func instruction_pointer_xlc {\
|
2015-01-22 02:47:42 +00:00
|
|
|
"7c0802a6" /* mflr r0 */ \
|
|
|
|
"48000005" /* bl $+4 */ \
|
|
|
|
"7c6802a6" /* mflr r3 */ \
|
|
|
|
"7c0803a6" /* mtlr r0 */ }
|
2008-09-16 10:12:23 +00:00
|
|
|
# pragma reg_killed_by instruction_pointer_xlc gr0 gr3
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED(ret) (ret=instruction_pointer_xlc());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef FIPS_START
|
2015-01-22 02:47:42 +00:00
|
|
|
# define FIPS_ref_point FIPS_text_start
|
|
|
|
/*
|
|
|
|
* Some compilers put string literals into a separate segment. As we are
|
|
|
|
* mostly interested to hash AES tables in .rodata, we declare reference
|
|
|
|
* points accordingly. In case you wonder, the values are big-endian encoded
|
|
|
|
* variable names, just to prevent these arrays from being merged by linker.
|
|
|
|
*/
|
|
|
|
const unsigned int FIPS_rodata_start[] =
|
|
|
|
{ 0x46495053, 0x5f726f64, 0x6174615f, 0x73746172 };
|
2008-09-16 10:12:23 +00:00
|
|
|
#else
|
2015-01-22 02:47:42 +00:00
|
|
|
# define FIPS_ref_point FIPS_text_end
|
|
|
|
const unsigned int FIPS_rodata_end[] =
|
|
|
|
{ 0x46495053, 0x5f726f64, 0x6174615f, 0x656e645b };
|
2008-09-16 10:12:23 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* I declare reference function as static in order to avoid certain
|
|
|
|
* pitfalls in -dynamic linker behaviour...
|
|
|
|
*/
|
|
|
|
static void *instruction_pointer(void)
|
2015-01-22 02:47:42 +00:00
|
|
|
{
|
|
|
|
void *ret = NULL;
|
|
|
|
/*
|
|
|
|
* These are ABI-neutral CPU-specific snippets. ABI-neutrality means that
|
|
|
|
* they are designed to work under any OS running on particular CPU,
|
|
|
|
* which is why you don't find any #ifdef THIS_OR_THAT_OS in this
|
|
|
|
* function.
|
|
|
|
*/
|
|
|
|
#if defined(INSTRUCTION_POINTER_IMPLEMENTED)
|
2008-09-16 10:12:23 +00:00
|
|
|
INSTRUCTION_POINTER_IMPLEMENTED(ret);
|
2015-01-22 02:47:42 +00:00
|
|
|
#elif defined(__GNUC__) && __GNUC__>=2
|
|
|
|
# if defined(__alpha) || defined(__alpha__)
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
|
|
|
__asm __volatile("br %0,1f\n1:":"=r"(ret));
|
|
|
|
# elif defined(__i386) || defined(__i386__)
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
|
|
|
__asm __volatile("call 1f\n1: popl %0":"=r"(ret));
|
|
|
|
ret = (void *)((size_t)ret & ~3UL); /* align for better performance */
|
|
|
|
# elif defined(__ia64) || defined(__ia64__)
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
|
|
|
__asm __volatile("mov %0=ip":"=r"(ret));
|
|
|
|
# elif defined(__hppa) || defined(__hppa__) || defined(__pa_risc)
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
|
|
|
__asm __volatile("blr %%r0,%0\n\tnop":"=r"(ret));
|
|
|
|
ret = (void *)((size_t)ret & ~3UL); /* mask privilege level */
|
|
|
|
# elif defined(__mips) || defined(__mips__)
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
2008-09-16 10:12:23 +00:00
|
|
|
void *scratch;
|
2015-01-22 02:47:42 +00:00
|
|
|
__asm __volatile("move %1,$31\n\t" /* save ra */
|
|
|
|
"bal .+8; nop\n\t" "move %0,$31\n\t"
|
|
|
|
/* restore ra */
|
|
|
|
"move $31,%1":"=r"(ret), "=r"(scratch));
|
|
|
|
# elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \
|
|
|
|
defined(__POWERPC__) || defined(_POWER) || defined(__PPC__) || \
|
|
|
|
defined(__PPC64__) || defined(__powerpc64__)
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
2008-09-16 10:12:23 +00:00
|
|
|
void *scratch;
|
2015-01-22 02:47:42 +00:00
|
|
|
__asm __volatile("mfspr %1,8\n\t" /* save lr */
|
|
|
|
"bl $+4\n\t" "mfspr %0,8\n\t" /* mflr ret */
|
|
|
|
"mtspr 8,%1" /* restore lr */
|
|
|
|
:"=r"(ret), "=r"(scratch));
|
|
|
|
# elif defined(__s390__) || defined(__s390x__)
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
|
|
|
__asm __volatile("bras %0,1f\n1:":"=r"(ret));
|
|
|
|
ret = (void *)((size_t)ret & ~3UL);
|
|
|
|
# elif defined(__sparc) || defined(__sparc__) || defined(__sparcv9)
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
2008-09-16 10:12:23 +00:00
|
|
|
void *scratch;
|
2015-01-22 02:47:42 +00:00
|
|
|
__asm __volatile("mov %%o7,%1\n\t"
|
|
|
|
"call .+8; nop\n\t"
|
|
|
|
"mov %%o7,%0\n\t"
|
|
|
|
"mov %1,%%o7":"=r"(ret), "=r"(scratch));
|
|
|
|
# elif defined(__x86_64) || defined(__x86_64__)
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
|
|
|
__asm __volatile("leaq 0(%%rip),%0":"=r"(ret));
|
|
|
|
ret = (void *)((size_t)ret & ~3UL); /* align for better performance */
|
2008-09-16 10:12:23 +00:00
|
|
|
# endif
|
2015-01-22 02:47:42 +00:00
|
|
|
#elif defined(__DECC) && defined(__alpha)
|
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
2008-09-16 10:12:23 +00:00
|
|
|
ret = (void *)(size_t)asm("br %v0,1f\n1:");
|
|
|
|
#elif defined(_MSC_VER) && defined(_M_IX86)
|
2015-01-22 02:47:42 +00:00
|
|
|
# define INSTRUCTION_POINTER_IMPLEMENTED
|
2008-09-16 10:12:23 +00:00
|
|
|
void *scratch;
|
|
|
|
_asm {
|
2015-01-22 02:47:42 +00:00
|
|
|
call self
|
|
|
|
self:pop eax
|
|
|
|
mov scratch, eax} ret = (void *)((size_t)scratch & ~3UL);
|
2008-09-16 10:12:23 +00:00
|
|
|
#endif
|
2015-01-22 02:47:42 +00:00
|
|
|
return ret;
|
2008-09-16 10:12:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function returns pointer to an instruction in the vicinity of
|
|
|
|
* its entry point, but not outside this object module. This guarantees
|
|
|
|
* that sequestered code is covered...
|
|
|
|
*/
|
|
|
|
void *FIPS_ref_point()
|
|
|
|
{
|
2015-01-22 02:47:42 +00:00
|
|
|
#if defined(INSTRUCTION_POINTER_IMPLEMENTED)
|
2008-09-16 10:12:23 +00:00
|
|
|
return instruction_pointer();
|
2015-01-22 02:47:42 +00:00
|
|
|
/*
|
|
|
|
* Below we essentially cover vendor compilers which do not support
|
|
|
|
* inline assembler...
|
|
|
|
*/
|
|
|
|
#elif defined(_AIX)
|
|
|
|
struct {
|
|
|
|
void *ip, *gp, *env;
|
|
|
|
} *p = (void *)instruction_pointer;
|
2008-09-16 10:12:23 +00:00
|
|
|
return p->ip;
|
2015-01-22 02:47:42 +00:00
|
|
|
#elif defined(_HPUX_SOURCE)
|
|
|
|
# if defined(__hppa) || defined(__hppa__)
|
|
|
|
struct {
|
|
|
|
void *i[4];
|
|
|
|
} *p = (void *)FIPS_ref_point;
|
2008-09-16 10:12:23 +00:00
|
|
|
|
2015-01-22 02:47:42 +00:00
|
|
|
if (sizeof(p) == 8) /* 64-bit */
|
|
|
|
return p->i[2];
|
|
|
|
else if ((size_t)p & 2) {
|
|
|
|
p = (void *)((size_t)p & ~3UL);
|
|
|
|
return p->i[0];
|
|
|
|
} else
|
|
|
|
return (void *)p;
|
|
|
|
# elif defined(__ia64) || defined(__ia64__)
|
|
|
|
struct {
|
|
|
|
unsigned long long ip, gp;
|
|
|
|
} *p = (void *)instruction_pointer;
|
2008-09-16 10:12:23 +00:00
|
|
|
return (void *)(size_t)p->ip;
|
|
|
|
# endif
|
2015-01-22 02:47:42 +00:00
|
|
|
#elif (defined(__VMS) || defined(VMS)) && !(defined(vax) || defined(__vax__))
|
2008-09-16 10:12:23 +00:00
|
|
|
/* applies to both alpha and ia64 */
|
2015-01-22 02:47:42 +00:00
|
|
|
struct {
|
|
|
|
unsigned __int64 opaque, ip;
|
|
|
|
} *p = (void *)instruction_pointer;
|
2008-09-16 10:12:23 +00:00
|
|
|
return (void *)(size_t)p->ip;
|
2015-01-22 02:47:42 +00:00
|
|
|
#elif defined(__VOS__)
|
2008-09-16 10:12:23 +00:00
|
|
|
/* applies to both pa-risc and ia32 */
|
2015-01-22 02:47:42 +00:00
|
|
|
struct {
|
|
|
|
void *dp, *ip, *gp;
|
|
|
|
} *p = (void *)instruction_pointer;
|
2008-09-16 10:12:23 +00:00
|
|
|
return p->ip;
|
2015-01-22 02:47:42 +00:00
|
|
|
#elif defined(_WIN32)
|
|
|
|
# if defined(_WIN64) && defined(_M_IA64)
|
|
|
|
struct {
|
|
|
|
void *ip, *gp;
|
|
|
|
} *p = (void *)FIPS_ref_point;
|
2008-09-16 10:12:23 +00:00
|
|
|
return p->ip;
|
|
|
|
# else
|
|
|
|
return (void *)FIPS_ref_point;
|
|
|
|
# endif
|
2015-01-22 02:47:42 +00:00
|
|
|
/*
|
|
|
|
* In case you wonder why there is no #ifdef __linux. All Linux targets
|
|
|
|
* are GCC-based and therefore are covered by instruction_pointer above
|
|
|
|
* [well, some are covered by by the one below]...
|
|
|
|
*/
|
|
|
|
#elif defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION)
|
2008-09-16 10:12:23 +00:00
|
|
|
return (void *)instruction_pointer;
|
|
|
|
#else
|
|
|
|
return NULL;
|
|
|
|
#endif
|
|
|
|
}
|