1*8d67ca89SAndroid Build Coastguard Worker /* 2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*8d67ca89SAndroid Build Coastguard Worker * 4*8d67ca89SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*8d67ca89SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*8d67ca89SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*8d67ca89SAndroid Build Coastguard Worker * 8*8d67ca89SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*8d67ca89SAndroid Build Coastguard Worker * 10*8d67ca89SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*8d67ca89SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*8d67ca89SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*8d67ca89SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*8d67ca89SAndroid Build Coastguard Worker * limitations under the License. 15*8d67ca89SAndroid Build Coastguard Worker */ 16*8d67ca89SAndroid Build Coastguard Worker 17*8d67ca89SAndroid Build Coastguard Worker #include <dlfcn.h> 18*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h> 19*8d67ca89SAndroid Build Coastguard Worker #include <stdio.h> 20*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h> 21*8d67ca89SAndroid Build Coastguard Worker 22*8d67ca89SAndroid Build Coastguard Worker static uintptr_t g_flag = 0; 23*8d67ca89SAndroid Build Coastguard Worker init_flag()24*8d67ca89SAndroid Build Coastguard Workerstatic void __attribute__((constructor)) init_flag() { 25*8d67ca89SAndroid Build Coastguard Worker g_flag = reinterpret_cast<uintptr_t>(dlsym(RTLD_DEFAULT, "dlsym")); 26*8d67ca89SAndroid Build Coastguard Worker } 27*8d67ca89SAndroid Build Coastguard Worker 28*8d67ca89SAndroid Build Coastguard Worker static const char* is_ctor_called() __attribute__ ((ifunc("is_ctor_called_ifun"))); 29*8d67ca89SAndroid Build Coastguard Worker 30*8d67ca89SAndroid Build Coastguard Worker extern "C" const char* foo() __attribute__ ((ifunc ("foo_ifunc"))); 31*8d67ca89SAndroid Build Coastguard Worker 32*8d67ca89SAndroid Build Coastguard Worker // Static linker creates GLOBAL/IFUNC symbol and JUMP_SLOT relocation type for plt segment 33*8d67ca89SAndroid Build Coastguard Worker extern "C" const char* is_ctor_called_jump_slot() __attribute__ ((ifunc("is_ctor_called_ifun"))); 34*8d67ca89SAndroid Build Coastguard Worker is_ctor_called_irelative()35*8d67ca89SAndroid Build Coastguard Workerextern "C" const char* is_ctor_called_irelative() { 36*8d67ca89SAndroid Build Coastguard Worker // Call internal ifunc-resolved function with IRELATIVE reloc 37*8d67ca89SAndroid Build Coastguard Worker return is_ctor_called(); 38*8d67ca89SAndroid Build Coastguard Worker } 39*8d67ca89SAndroid Build Coastguard Worker return_true()40*8d67ca89SAndroid Build Coastguard Workerextern "C" const char* return_true() { 41*8d67ca89SAndroid Build Coastguard Worker return "true"; 42*8d67ca89SAndroid Build Coastguard Worker } 43*8d67ca89SAndroid Build Coastguard Worker return_false()44*8d67ca89SAndroid Build Coastguard Workerextern "C" const char* return_false() { 45*8d67ca89SAndroid Build Coastguard Worker return "false"; 46*8d67ca89SAndroid Build Coastguard Worker } 47*8d67ca89SAndroid Build Coastguard Worker f1()48*8d67ca89SAndroid Build Coastguard Workerextern "C" const char* f1() { 49*8d67ca89SAndroid Build Coastguard Worker return "unset"; 50*8d67ca89SAndroid Build Coastguard Worker } 51*8d67ca89SAndroid Build Coastguard Worker f2()52*8d67ca89SAndroid Build Coastguard Workerextern "C" const char* f2() { 53*8d67ca89SAndroid Build Coastguard Worker return "set"; 54*8d67ca89SAndroid Build Coastguard Worker } 55*8d67ca89SAndroid Build Coastguard Worker 56*8d67ca89SAndroid Build Coastguard Worker typedef const char* (*fn_ptr)(); 57*8d67ca89SAndroid Build Coastguard Worker is_ctor_called_ifun()58*8d67ca89SAndroid Build Coastguard Workerextern "C" fn_ptr is_ctor_called_ifun() { 59*8d67ca89SAndroid Build Coastguard Worker return g_flag == 0 ? return_false : return_true; 60*8d67ca89SAndroid Build Coastguard Worker } 61*8d67ca89SAndroid Build Coastguard Worker foo_ifunc()62*8d67ca89SAndroid Build Coastguard Workerextern "C" fn_ptr foo_ifunc() { 63*8d67ca89SAndroid Build Coastguard Worker char* choice = getenv("IFUNC_CHOICE"); 64*8d67ca89SAndroid Build Coastguard Worker return choice == nullptr ? f1 : f2; 65*8d67ca89SAndroid Build Coastguard Worker } 66*8d67ca89SAndroid Build Coastguard Worker foo_library()67*8d67ca89SAndroid Build Coastguard Workerextern "C" const char* foo_library() { 68*8d67ca89SAndroid Build Coastguard Worker return foo(); 69*8d67ca89SAndroid Build Coastguard Worker } 70