1 | /* Test case for i386 preserved registers in dynamic linker. |
2 | Copyright (C) 2015-2024 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 <dlfcn.h> |
20 | #include <stdint.h> |
21 | #include <stdio.h> |
22 | #include <stdlib.h> |
23 | #include <stddef.h> |
24 | #include <string.h> |
25 | #include <unistd.h> |
26 | #include <link.h> |
27 | #include <bits/wordsize.h> |
28 | #include <gnu/lib-names.h> |
29 | |
30 | unsigned int |
31 | la_version (unsigned int v) |
32 | { |
33 | setlinebuf (stdout); |
34 | |
35 | printf (format: "version: %u\n" , v); |
36 | |
37 | char buf[20]; |
38 | sprintf (s: buf, format: "%u" , v); |
39 | |
40 | return v; |
41 | } |
42 | |
43 | void |
44 | la_activity (uintptr_t *cookie, unsigned int flag) |
45 | { |
46 | const char *flagstr; |
47 | switch (flag) |
48 | { |
49 | case LA_ACT_CONSISTENT: |
50 | flagstr = "consistent" ; |
51 | break; |
52 | case LA_ACT_ADD: |
53 | flagstr = "add" ; |
54 | break; |
55 | case LA_ACT_DELETE: |
56 | flagstr = "delete" ; |
57 | break; |
58 | default: |
59 | printf (format: "activity: unknown activity %u\n" , flag); |
60 | return; |
61 | } |
62 | printf (format: "activity: %s\n" , flagstr); |
63 | } |
64 | |
65 | char * |
66 | la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) |
67 | { |
68 | const char *flagstr; |
69 | switch (flag) |
70 | { |
71 | case LA_SER_ORIG: |
72 | flagstr = "LA_SET_ORIG" ; |
73 | break; |
74 | case LA_SER_LIBPATH: |
75 | flagstr = "LA_SER_LIBPATH" ; |
76 | break; |
77 | case LA_SER_RUNPATH: |
78 | flagstr = "LA_SER_RUNPATH" ; |
79 | break; |
80 | case LA_SER_CONFIG: |
81 | flagstr = "LA_SER_CONFIG" ; |
82 | break; |
83 | case LA_SER_DEFAULT: |
84 | flagstr = "LA_SER_DEFAULT" ; |
85 | break; |
86 | case LA_SER_SECURE: |
87 | flagstr = "LA_SER_SECURE" ; |
88 | break; |
89 | default: |
90 | printf (format: "objsearch: %s, unknown flag %d\n" , name, flag); |
91 | return (char *) name; |
92 | } |
93 | |
94 | printf (format: "objsearch: %s, %s\n" , name, flagstr); |
95 | return (char *) name; |
96 | } |
97 | |
98 | unsigned int |
99 | la_objopen (struct link_map *l, Lmid_t lmid, uintptr_t *cookie) |
100 | { |
101 | printf (format: "objopen: %ld, %s\n" , lmid, l->l_name); |
102 | |
103 | return 3; |
104 | } |
105 | |
106 | void |
107 | la_preinit (uintptr_t *cookie) |
108 | { |
109 | printf (format: "preinit\n" ); |
110 | } |
111 | |
112 | unsigned int |
113 | la_objclose (uintptr_t *cookie) |
114 | { |
115 | printf (format: "objclose\n" ); |
116 | return 0; |
117 | } |
118 | |
119 | uintptr_t |
120 | la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, |
121 | uintptr_t *defcook, unsigned int *flags, const char *symname) |
122 | { |
123 | printf (format: "symbind32: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n" , |
124 | symname, (long int) sym->st_value, ndx, *flags); |
125 | |
126 | return sym->st_value; |
127 | } |
128 | |
129 | #include "tst-audit.h" |
130 | |
131 | ElfW(Addr) |
132 | pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, |
133 | uintptr_t *defcook, La_regs *regs, unsigned int *flags, |
134 | const char *symname, long int *framesizep) |
135 | { |
136 | printf (format: "pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n" , |
137 | symname, (long int) sym->st_value, ndx, *flags); |
138 | |
139 | if (strcmp (s1: symname, s2: "audit1_test" ) == 0 |
140 | || strcmp (s1: symname, s2: "audit2_test" ) == 0) |
141 | { |
142 | if (regs->lr_eax != 1 |
143 | || regs->lr_edx != 2 |
144 | || regs->lr_ecx != 3) |
145 | abort (); |
146 | |
147 | *framesizep = 200; |
148 | } |
149 | |
150 | return sym->st_value; |
151 | } |
152 | |
153 | unsigned int |
154 | pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, |
155 | uintptr_t *defcook, const La_regs *inregs, La_retval *outregs, |
156 | const char *symname) |
157 | { |
158 | printf (format: "pltexit: symname=%s, st_value=%#lx, ndx=%u, retval=%tu\n" , |
159 | symname, (long int) sym->st_value, ndx, |
160 | (ptrdiff_t) outregs->int_retval); |
161 | |
162 | if (strcmp (s1: symname, s2: "audit1_test" ) == 0 |
163 | || strcmp (s1: symname, s2: "audit2_test" ) == 0) |
164 | { |
165 | if (inregs->lr_eax != 1 |
166 | || inregs->lr_edx != 2 |
167 | || inregs->lr_ecx != 3) |
168 | abort (); |
169 | |
170 | if (strcmp (s1: symname, s2: "audit1_test" ) == 0) |
171 | { |
172 | long long x = ((unsigned long long) outregs->lrv_eax |
173 | | (unsigned long long) outregs->lrv_edx << 32); |
174 | |
175 | if (x != 30) |
176 | abort (); |
177 | } |
178 | else if (strcmp (s1: symname, s2: "audit2_test" ) == 0) |
179 | { |
180 | if (outregs->lrv_st0 != 30) |
181 | abort (); |
182 | } |
183 | } |
184 | |
185 | return 0; |
186 | } |
187 | |