malloc: Additional checks for unsorted bin integrity I.
[glibc.git] / elf / sotruss-lib.c
blobf0a7e55599d767142b17f47487d6939595500700
1 /* Trace calls through PLTs and show caller, callee, and parameters.
2 Copyright (C) 2011-2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
20 #include <error.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/param.h>
27 #include <sys/uio.h>
29 #include <ldsodefs.h>
32 extern const char *__progname;
33 extern const char *__progname_full;
36 /* List of objects to trace calls from. */
37 static const char *fromlist;
38 /* List of objects to trace calls to. */
39 static const char *tolist;
41 /* If non-zero, also trace returns of the calls. */
42 static int do_exit;
43 /* If non-zero print PID for each line. */
44 static int print_pid;
46 /* The output stream to use. */
47 static FILE *out_file;
50 static int
51 match_pid (pid_t pid, const char *which)
53 if (which == NULL || which[0] == '\0')
55 print_pid = 1;
56 return 1;
59 char *endp;
60 unsigned long n = strtoul (which, &endp, 0);
61 return *endp == '\0' && n == pid;
65 static void
66 init (void)
68 fromlist = getenv ("SOTRUSS_FROMLIST");
69 if (fromlist != NULL && fromlist[0] == '\0')
70 fromlist = NULL;
71 tolist = getenv ("SOTRUSS_TOLIST");
72 if (tolist != NULL && tolist[0] == '\0')
73 tolist = NULL;
74 do_exit = (getenv ("SOTRUSS_EXIT") ?: "")[0] != '\0';
76 /* Determine whether this process is supposed to be traced and if
77 yes, whether we should print into a file. */
78 const char *which_process = getenv ("SOTRUSS_WHICH");
79 pid_t pid = getpid ();
80 int out_fd = -1;
81 if (match_pid (pid, which_process))
83 const char *out_filename = getenv ("SOTRUSS_OUTNAME");
85 if (out_filename != NULL && out_filename[0] != 0)
87 size_t out_filename_len = strlen (out_filename) + 13;
88 char fullname[out_filename_len];
89 char *endp = stpcpy (fullname, out_filename);
90 if (which_process == NULL || which_process[0] == '\0')
91 snprintf (endp, 13, ".%ld", (long int) pid);
93 out_fd = open (fullname, O_RDWR | O_CREAT | O_TRUNC, 0666);
94 if (out_fd != -1)
95 print_pid = 0;
99 /* If we do not write into a file write to stderr. Duplicate the
100 descriptor so that we can keep printing in case the program
101 closes stderr. Try first to allocate a descriptor with a value
102 usually not used as to minimize interference with the
103 program. */
104 if (out_fd == -1)
106 out_fd = fcntl (STDERR_FILENO, F_DUPFD, 1000);
107 if (out_fd == -1)
108 out_fd = dup (STDERR_FILENO);
111 if (out_fd != -1)
113 /* Convert file descriptor into a stream. */
114 out_file = fdopen (out_fd, "w");
115 if (out_file != NULL)
116 setlinebuf (out_file);
121 /* Audit interface verification. We also initialize everything if
122 everything checks out OK. */
123 unsigned int
124 la_version (unsigned int v)
126 if (v != LAV_CURRENT)
127 error (1, 0, "cannot handle interface version %u", v);
129 init ();
131 return v;
135 /* Check whether a file name is on the colon-separated list of file
136 names. */
137 static unsigned int
138 match_file (const char *list, const char *name, size_t name_len,
139 unsigned int mask)
141 if (list[0] == '\0')
142 return 0;
144 const char *cp = list;
145 while (1)
147 if (strncmp (cp, name, name_len) == 0
148 && (cp[name_len] == ':' || cp[name_len] == '\0'))
149 return mask;
151 cp = strchr (cp, ':');
152 if (cp == NULL)
153 return 0;
154 ++cp;
159 unsigned int
160 la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
162 if (out_file == NULL)
163 return 0;
165 const char *full_name = map->l_name ?: "";
166 if (full_name[0] == '\0')
167 full_name = __progname_full;
168 size_t full_name_len = strlen (full_name);
169 const char *base_name = basename (full_name);
170 if (base_name[0] == '\0')
171 base_name = __progname;
172 size_t base_name_len = strlen (base_name);
174 int result = 0;
175 const char *print_name = NULL;
176 for (struct libname_list *l = map->l_libname; l != NULL; l = l->next)
178 if (print_name == NULL || (print_name[0] == '/' && l->name[0] != '/'))
179 print_name = l->name;
181 if (fromlist != NULL)
182 result |= match_file (fromlist, l->name, strlen (l->name),
183 LA_FLG_BINDFROM);
185 if (tolist != NULL)
186 result |= match_file (tolist, l->name, strlen (l->name),LA_FLG_BINDTO);
189 if (print_name == NULL)
190 print_name = base_name;
191 if (print_name[0] == '\0')
192 print_name = __progname;
194 /* We cannot easily get to the object name in the PLT handling
195 functions. Use the cookie to get the string pointer passed back
196 to us. */
197 *cookie = (uintptr_t) print_name;
199 /* The object name has to be on the list of objects to trace calls
200 from or that list must be empty. In the latter case we trace
201 only calls from the main binary. */
202 if (fromlist == NULL)
203 result |= map->l_name[0] == '\0' ? LA_FLG_BINDFROM : 0;
204 else
205 result |= (match_file (fromlist, full_name, full_name_len,
206 LA_FLG_BINDFROM)
207 | match_file (fromlist, base_name, base_name_len,
208 LA_FLG_BINDFROM));
210 /* The object name has to be on the list of objects to trace calls
211 to or that list must be empty. In the latter case we trace
212 calls toall objects. */
213 if (tolist == NULL)
214 result |= LA_FLG_BINDTO;
215 else
216 result |= (match_file (tolist, full_name, full_name_len, LA_FLG_BINDTO)
217 | match_file (tolist, base_name, base_name_len, LA_FLG_BINDTO));
219 return result;
223 #if __ELF_NATIVE_CLASS == 32
224 # define la_symbind la_symbind32
225 typedef Elf32_Sym Elf_Sym;
226 #else
227 # define la_symbind la_symbind64
228 typedef Elf64_Sym Elf_Sym;
229 #endif
231 uintptr_t
232 la_symbind (Elf_Sym *sym, unsigned int ndx, uintptr_t *refcook,
233 uintptr_t *defcook, unsigned int *flags, const char *symname)
235 if (!do_exit)
236 *flags = LA_SYMB_NOPLTEXIT;
238 return sym->st_value;
242 static void
243 print_enter (uintptr_t *refcook, uintptr_t *defcook, const char *symname,
244 unsigned long int reg1, unsigned long int reg2,
245 unsigned long int reg3, unsigned int flags)
247 char buf[3 * sizeof (pid_t) + 3];
248 buf[0] = '\0';
249 if (print_pid)
250 snprintf (buf, sizeof (buf), "%5ld: ", (long int) getpid ());
252 fprintf (out_file, "%s%15s -> %-15s:%s%s(0x%lx, 0x%lx, 0x%lx)\n",
253 buf, (char *) *refcook, (char *) *defcook,
254 (flags & LA_SYMB_NOPLTEXIT) ? "*" : " ", symname, reg1, reg2, reg3);
258 #ifdef __i386__
259 Elf32_Addr
260 la_i86_gnu_pltenter (Elf32_Sym *sym __attribute__ ((unused)),
261 unsigned int ndx __attribute__ ((unused)),
262 uintptr_t *refcook, uintptr_t *defcook,
263 La_i86_regs *regs, unsigned int *flags,
264 const char *symname, long int *framesizep)
266 unsigned long int *sp = (unsigned long int *) regs->lr_esp;
268 print_enter (refcook, defcook, symname, sp[1], sp[2], sp[3], *flags);
270 /* No need to copy anything, we will not need the parameters in any case. */
271 *framesizep = 0;
273 return sym->st_value;
275 #elif defined __x86_64__
276 Elf64_Addr
277 la_x86_64_gnu_pltenter (Elf64_Sym *sym __attribute__ ((unused)),
278 unsigned int ndx __attribute__ ((unused)),
279 uintptr_t *refcook, uintptr_t *defcook,
280 La_x86_64_regs *regs, unsigned int *flags,
281 const char *symname, long int *framesizep)
283 print_enter (refcook, defcook, symname,
284 regs->lr_rdi, regs->lr_rsi, regs->lr_rdx, *flags);
286 /* No need to copy anything, we will not need the parameters in any case. */
287 *framesizep = 0;
289 return sym->st_value;
291 #elif defined __sparc__ && !defined __arch64__
292 Elf32_Addr
293 la_sparc32_gnu_pltenter (Elf32_Sym *sym __attribute__ ((unused)),
294 unsigned int ndx __attribute__ ((unused)),
295 uintptr_t *refcook, uintptr_t *defcook,
296 La_sparc32_regs *regs, unsigned int *flags,
297 const char *symname, long int *framesizep)
299 print_enter (refcook, defcook, symname,
300 regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2],
301 *flags);
303 /* No need to copy anything, we will not need the parameters in any case. */
304 *framesizep = 0;
306 return sym->st_value;
308 #elif defined __sparc__ && defined __arch64__
309 Elf64_Addr
310 la_sparc64_gnu_pltenter (Elf64_Sym *sym __attribute__ ((unused)),
311 unsigned int ndx __attribute__ ((unused)),
312 uintptr_t *refcook, uintptr_t *defcook,
313 La_sparc64_regs *regs, unsigned int *flags,
314 const char *symname, long int *framesizep)
316 print_enter (refcook, defcook, symname,
317 regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2],
318 *flags);
320 /* No need to copy anything, we will not need the parameters in any case. */
321 *framesizep = 0;
323 return sym->st_value;
325 #elif !defined HAVE_ARCH_PLTENTER
326 # warning "pltenter for architecture not supported"
327 #endif
330 static void
331 print_exit (uintptr_t *refcook, uintptr_t *defcook, const char *symname,
332 unsigned long int reg)
334 char buf[3 * sizeof (pid_t) + 3];
335 buf[0] = '\0';
336 if (print_pid)
337 snprintf (buf, sizeof (buf), "%5ld: ", (long int) getpid ());
339 fprintf (out_file, "%s%15s -> %-15s:%s%s - 0x%lx\n",
340 buf, (char *) *refcook, (char *) *defcook, " ", symname, reg);
344 #ifdef __i386__
345 unsigned int
346 la_i86_gnu_pltexit (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
347 uintptr_t *defcook, const struct La_i86_regs *inregs,
348 struct La_i86_retval *outregs, const char *symname)
350 print_exit (refcook, defcook, symname, outregs->lrv_eax);
352 return 0;
354 #elif defined __x86_64__
355 unsigned int
356 la_x86_64_gnu_pltexit (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
357 uintptr_t *defcook, const struct La_x86_64_regs *inregs,
358 struct La_x86_64_retval *outregs, const char *symname)
360 print_exit (refcook, defcook, symname, outregs->lrv_rax);
362 return 0;
364 #elif defined __sparc__ && !defined __arch64__
365 unsigned int
366 la_sparc32_gnu_pltexit (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
367 uintptr_t *defcook, const struct La_sparc32_regs *inregs,
368 struct La_sparc32_retval *outregs, const char *symname)
370 print_exit (refcook, defcook, symname, outregs->lrv_reg[0]);
372 return 0;
374 #elif defined __sparc__ && defined __arch64__
375 unsigned int
376 la_sparc64_gnu_pltexit (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
377 uintptr_t *defcook, const struct La_sparc64_regs *inregs,
378 struct La_sparc64_retval *outregs, const char *symname)
380 print_exit (refcook, defcook, symname, outregs->lrv_reg[0]);
382 return 0;
384 #elif !defined HAVE_ARCH_PLTEXIT
385 # warning "pltexit for architecture not supported"
386 #endif