platform_bionic/libc/include/sys/ifunc.h
Peter Collingbourne e949195f64 Adopt GNU calling convention for ifunc resolvers.
In order for an ifunc resolver to detect the presence of certain CPU features,
access to getauxval(AT_HWCAP) or getauxval(AT_HWCAP2) may be required. In order
for getauxval() to work, it needs to access the pointer to the auxiliary vector
stored by the linker in the libc shared globals data structure. Accessing the
shared globals requires libc to call the __libc_shared_globals() function
exported by the linker. However, in order to call this function, libc must
be fully relocated, which is not guaranteed to be the case at the point when
ifunc resolvers are called.

glibc solves this problem by passing the values of getauxval(AT_HWCAP)
(and getauxval(AT_HWCAP2) on aarch64) as arguments to the ifunc resolver.
Since this seems to be not only the most straightforward way to solve the
problem but also improves our compatibility with glibc, we adopt their
calling convention.

This change is ABI compatible with old resolvers because the arguments are
passed in registers, so the old resolvers will simply ignore the new arguments.

Bug: 135772972
Change-Id: Ie65bd6e7067f0c878df3d348c815fda61dc12de2
2019-10-28 20:20:29 -07:00

71 lines
2.6 KiB
C

/*
* Copyright (C) 2019 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include <sys/cdefs.h>
/**
* @file sys/ifunc.h
* @brief Declarations used for ifunc resolvers. Currently only meaningful for arm64.
*/
__BEGIN_DECLS
#if defined(__aarch64__)
/**
* Provides information about hardware capabilities to ifunc resolvers.
*
* Starting with API level 30, ifunc resolvers on arm64 are passed two arguments. The first is a
* uint64_t whose value is equal to getauxval(AT_HWCAP) | _IFUNC_ARG_HWCAP. The second is a pointer
* to a data structure of this type. Prior to API level 30, no arguments are passed to ifunc
* resolvers. Code that wishes to be compatible with prior API levels should not accept any
* arguments in the resolver.
*/
typedef struct __ifunc_arg_t {
/** Set to sizeof(__ifunc_arg_t). */
unsigned long _size;
/** Set to getauxval(AT_HWCAP). */
unsigned long _hwcap;
/** Set to getauxval(AT_HWCAP2). */
unsigned long _hwcap2;
} __ifunc_arg_t;
/**
* If this bit is set in the first argument to an ifunc resolver, indicates that the second argument
* is a pointer to a data structure of type __ifunc_arg_t. This bit is always set on Android
* starting with API level 30.
*/
#define _IFUNC_ARG_HWCAP (1ULL << 62)
#endif
__END_DECLS