1 /* Test case for i386 preserved registers in dynamic linker.
2    Copyright (C) 2015-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 <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
la_version(unsigned int v)31 la_version (unsigned int v)
32 {
33   setlinebuf (stdout);
34 
35   printf ("version: %u\n", v);
36 
37   char buf[20];
38   sprintf (buf, "%u", v);
39 
40   return v;
41 }
42 
43 void
la_activity(uintptr_t * cookie,unsigned int flag)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 ("activity: unknown activity %u\n", flag);
60       return;
61     }
62   printf ("activity: %s\n", flagstr);
63 }
64 
65 char *
la_objsearch(const char * name,uintptr_t * cookie,unsigned int flag)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 ("objsearch: %s, unknown flag %d\n", name, flag);
91       return (char *) name;
92     }
93 
94   printf ("objsearch: %s, %s\n", name, flagstr);
95   return (char *) name;
96 }
97 
98 unsigned int
la_objopen(struct link_map * l,Lmid_t lmid,uintptr_t * cookie)99 la_objopen (struct link_map *l, Lmid_t lmid, uintptr_t *cookie)
100 {
101   printf ("objopen: %ld, %s\n", lmid, l->l_name);
102 
103   return 3;
104 }
105 
106 void
la_preinit(uintptr_t * cookie)107 la_preinit (uintptr_t *cookie)
108 {
109   printf ("preinit\n");
110 }
111 
112 unsigned int
la_objclose(uintptr_t * cookie)113 la_objclose  (uintptr_t *cookie)
114 {
115   printf ("objclose\n");
116   return 0;
117 }
118 
119 uintptr_t
la_symbind32(Elf32_Sym * sym,unsigned int ndx,uintptr_t * refcook,uintptr_t * defcook,unsigned int * flags,const char * symname)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 ("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)
pltenter(ElfW (Sym)* sym,unsigned int ndx,uintptr_t * refcook,uintptr_t * defcook,La_regs * regs,unsigned int * flags,const char * symname,long int * framesizep)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 ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
137 	  symname, (long int) sym->st_value, ndx, *flags);
138 
139   if (strcmp (symname, "audit1_test") == 0
140       || strcmp (symname, "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
pltexit(ElfW (Sym)* sym,unsigned int ndx,uintptr_t * refcook,uintptr_t * defcook,const La_regs * inregs,La_retval * outregs,const char * symname)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 ("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 (symname, "audit1_test") == 0
163       || strcmp (symname, "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 (symname, "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 (symname, "audit2_test") == 0)
179 	{
180 	  if (outregs->lrv_st0 != 30)
181 	    abort ();
182 	}
183     }
184 
185   return 0;
186 }
187