1# REQUIRES: x86_64-linux 2# RUN: rm -rf %t && mkdir -p %t 3# RUN: split-file %s %t 4# RUN: llvm-mc -triple=x86_64-unknown-linux-gnu -filetype=obj -o %t/test_runner.o %t/test_runner.s 5# RUN: llvm-mc -triple=x86_64-unknown-linux-gnu -filetype=obj -o %t/func_defs.o %t/func_defs.s 6# RUN: llvm-rtdyld -triple=x86_64-unknown-linux-gnu -verify -check=%s %t/test_runner.o %t/func_defs.o 7# RUN: llvm-rtdyld -triple=x86_64-unknown-linux-gnu -execute %t/test_runner.o %t/func_defs.o 8 9#--- test_runner.s 10 11# The _main function of this file contains calls to the two external functions 12# "indirect_func" and "normal_func" that are not yet defined. They are called via 13# the PLT to simulate how a compiler would emit a call to an external function. 14# Eventually, indirect_func will resolve to a STT_GNU_IFUNC and normal_func to a 15# regular function. We include calls to both types of functions in this test to 16# test that both types of functions are executed correctly when their types are 17# not known initially. 18# It also contains a call to a locally defined indirect function. As RuntimeDyld 19# treats local functions a bit differently than external functions, we also test 20# that. 21# Verify that the functions return the excpeted value. If the external indirect 22# function call fails, this returns the error code 1. If the external normal 23# function call fails, it's the error code 2. If the call to the locally 24# defined indirect function fails, return the error code 3. 25 26local_real_func: 27 mov $0x56, %eax 28 ret 29 30local_indirect_func_resolver: 31 lea local_real_func(%rip), %rax 32 ret 33 34 .type local_indirect_func, @gnu_indirect_function 35 .set local_indirect_func, local_indirect_func_resolver 36 37 .global _main 38_main: 39 call indirect_func@plt 40 cmp $0x12, %eax 41 je 1f 42 mov $1, %eax 43 ret 441: 45 46 call normal_func@plt 47 cmp $0x34, %eax 48 je 1f 49 mov $2, %eax 50 ret 511: 52 53 call local_indirect_func@plt 54 cmp $0x56, %eax 55 je 1f 56 mov $3, %eax 57 ret 581: 59 60 xor %eax, %eax 61 ret 62 63# Test that the indirect functions have the same addresses in both calls. 64# rtdyld-check: decode_operand(test_indirect_func_address_1, 4) + next_pc(test_indirect_func_address_1) = decode_operand(test_indirect_func_address_2, 4) + next_pc(test_indirect_func_address_2) 65test_indirect_func_address_1: 66 lea indirect_func(%rip), %rax 67 68test_indirect_func_address_2: 69 lea indirect_func(%rip), %rax 70 71# rtdyld-check: decode_operand(test_local_indirect_func_address_1, 4) + next_pc(test_indirect_func_address_1) = decode_operand(test_local_indirect_func_address_2, 4) + next_pc(test_indirect_func_address_2) 72test_local_indirect_func_address_1: 73 lea local_indirect_func(%rip), %rax 74 75test_local_indirect_func_address_2: 76 lea local_indirect_func(%rip), %rax 77 78#--- func_defs.s 79 80# This file contains the external functions that are called above. The type of 81# the indirect function is set to @gnu_indirect_function and its value is set 82# to the value of ifunc_resolver. This is what gcc emits when using 83# __attribute__((ifunc("ifunc_resolver"))) in C. The resolver function just 84# returns the address of the real function "real_func". 85# To test that everyting works correctly, the indirect function returns 0x12 86# and the direct function returns 0x23. This is verified in the _main function 87# above. 88 89real_func: 90 mov $0x12, %eax 91 ret 92 93ifunc_resolver: 94 lea real_func(%rip), %rax 95 ret 96 97 .global indirect_func 98 .type indirect_func, @gnu_indirect_function 99 .set indirect_func, ifunc_resolver 100 101 .global normal_func 102normal_func: 103 mov $0x34, %eax 104 ret 105 106# Test that the address of the indirect function is equal even when it is 107# defined in another object file. 108# rtdyld-check: decode_operand(test_indirect_func_address_1, 4) + next_pc(test_indirect_func_address_1) = decode_operand(test_indirect_func_address_3, 4) + next_pc(test_indirect_func_address_3) 109test_indirect_func_address_3: 110 lea indirect_func(%rip), %rax 111