1 | /* Test that lazy binding does not clobber r0. |
2 | Copyright (C) 2018-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <assert.h> |
20 | #include <dlfcn.h> |
21 | #include <stdio.h> |
22 | #include <stdlib.h> |
23 | #include <unistd.h> |
24 | |
25 | #if defined (__s390x__) |
26 | static const unsigned long magic_value = 0x0011223344556677UL; |
27 | #else |
28 | static const unsigned long magic_value = 0x00112233; |
29 | #endif |
30 | |
31 | unsigned long r0x2_trampoline (unsigned long); |
32 | |
33 | /* Invoke r0x2, which doubles the value in r0. If we get |
34 | value * 2 back, this means nothing clobbers r0, particularly, |
35 | _dl_runtime_resolve and _dl_runtime_profile. */ |
36 | asm (" .type r0x2_trampoline, @function\n" |
37 | "r0x2_trampoline:\n" |
38 | #if defined (__s390x__) |
39 | " lgr %r0,%r2\n" |
40 | " stg %r14,112(%r15)\n" |
41 | " aghi %r15,-160\n" |
42 | " brasl %r14,r0x2@plt\n" |
43 | " aghi %r15,160\n" |
44 | " lg %r14,112(%r15)\n" |
45 | " lgr %r2,%r0\n" |
46 | " br %r14\n" |
47 | #elif defined (__zarch__) |
48 | " lr %r0,%r2\n" |
49 | " st %r14,56(%r15)\n" |
50 | " ahi %r15,-96\n" |
51 | " brasl %r14,r0x2@plt\n" |
52 | " ahi %r15,96\n" |
53 | " l %r14,56(%r15)\n" |
54 | " lr %r2,%r0\n" |
55 | " br %r14\n" |
56 | #else |
57 | " lr %r0,%r2\n" |
58 | " st %r14,56(%r15)\n" |
59 | " ahi %r15,-96\n" |
60 | " balr %r14,0\n" |
61 | " l %r14,1f-.(%r14)\n" |
62 | " basr %r14,%r14\n" |
63 | " ahi %r15,96\n" |
64 | " l %r14,56(%r15)\n" |
65 | " lr %r2,%r0\n" |
66 | " br %r14\n" |
67 | "1: .long r0x2\n" |
68 | #endif |
69 | ); |
70 | |
71 | static int |
72 | do_test (void) |
73 | { |
74 | int i; |
75 | unsigned long r0; |
76 | const char *run; |
77 | |
78 | for (i = 0; i < 2; i++) |
79 | { |
80 | run = (i == 0) ? "lazy" : "non-lazy" ; |
81 | r0 = magic_value; |
82 | printf (format: "-> %s r0 = 0x%lx\n" , run, r0); |
83 | r0 = r0x2_trampoline (r0); |
84 | printf (format: "<- %s r0 * 2 = 0x%lx\n" , run, r0); |
85 | if (r0 != magic_value * 2) |
86 | return EXIT_FAILURE; |
87 | } |
88 | return EXIT_SUCCESS; |
89 | } |
90 | |
91 | #include <support/test-driver.c> |
92 | |