4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/types.h>
27 #include <sys/param.h>
37 static Elist
*bindto_list
= NULL
;
38 static Elist
*bindfrom_list
= NULL
;
40 static uint_t pidout
= 0;
42 static FILE *outfile
= stderr
;
43 static uint_t indent
= 1;
44 static uint_t indent_level
= 1;
45 static uint_t trussall
= 0;
46 static uint_t noexit
= 0;
50 * It's not possible to gather the return code on routines
51 * which actually have a dependence on the 'stack frame structure'.
52 * Below is a list of known symbols which have this dependency,
53 * truss.so will disable the la_pltexit() entry point for these
54 * routines, which will remove the requirement for the extra
55 * stackframe that the link_auditing interface creates.
57 * NOTE: this list *must* be mainted in alphabetical order.
58 * if this list ever became to long a faster search mechanism
59 * should be considered.
61 static char *spec_sym
[] = {
89 la_version(uint_t version
)
93 if (version
> LAV_CURRENT
)
94 (void) fprintf(stderr
, "truss.so: unexpected version: %d\n",
97 build_env_list(&bindto_list
, (const char *)"TRUSS_BINDTO");
98 build_env_list(&bindfrom_list
, (const char *)"TRUSS_BINDFROM");
100 if (checkenv((const char *)"TRUSS_PID")) {
104 char *str
= "LD_AUDIT=";
106 * This disables truss output in subsequent fork()/exec
112 if (checkenv((const char *)"TRUSS_NOEXIT")) {
117 if (checkenv((const char *)"TRUSS_NOINDENT"))
120 if (checkenv((const char *)"TRUSS_ALL"))
123 if (str
= checkenv((const char *)"TRUSS_OUTPUT")) {
125 char fname
[MAXPATHLEN
];
128 (void) snprintf(fname
, MAXPATHLEN
, "%s.%d", str
,
131 (void) strncpy(fname
, str
, MAXPATHLEN
);
133 if (fp
= fopen(fname
, (const char *)"w")) {
136 (void) fprintf(stderr
,
137 "truss.so: unable to open file=`%s': %s\n",
138 fname
, strerror(errno
));
142 * Initalize iset to the full set of signals to be masked durring
145 (void) sigfillset(&iset
);
147 return (LAV_CURRENT
);
152 la_objopen(Link_map
*lmp
, Lmid_t lmid
, uintptr_t *cookie
)
156 static int first
= 1;
158 if ((bindto_list
== NULL
) || (trussall
))
159 flags
= LA_FLG_BINDTO
;
160 else if (check_list(bindto_list
, lmp
->l_name
))
161 flags
= LA_FLG_BINDTO
;
165 if (((bindfrom_list
== NULL
) && first
) || trussall
||
166 (check_list(bindfrom_list
, lmp
->l_name
)))
167 flags
|= LA_FLG_BINDFROM
;
172 if ((basename
= strrchr(lmp
->l_name
, '/')) != NULL
)
175 basename
= lmp
->l_name
;
176 *cookie
= (uintptr_t)basename
;
185 la_symbind64(Elf64_Sym
*symp
, uint_t symndx
, uintptr_t *refcook
,
186 uintptr_t *defcook
, uint_t
*sb_flags
, const char *sym_name
)
189 la_symbind32(Elf32_Sym
*symp
, uint_t symndx
, uintptr_t *refcook
,
190 uintptr_t *defcook
, uint_t
*sb_flags
)
194 const char *sym_name
= (const char *)symp
->st_name
;
199 *sb_flags
|= LA_SYMB_NOPLTEXIT
;
202 * Check to see if this symbol is one of the 'special' symbols.
203 * If so we disable PLTEXIT calls for that symbol.
205 if ((*sb_flags
& LA_SYMB_NOPLTEXIT
) == 0) {
209 for (ndx
= 0; str
= spec_sym
[ndx
]; ndx
++) {
211 cmpval
= strcmp(sym_name
, str
);
215 *sb_flags
|= LA_SYMB_NOPLTEXIT
;
220 return (symp
->st_value
);
224 #if defined(__sparcv9)
226 la_sparcv9_pltenter(Elf64_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
227 uintptr_t *defcookie
, La_sparcv9_regs
*regset
, uint_t
*sb_flags
,
228 const char *sym_name
)
229 #elif defined(__sparc)
231 la_sparcv8_pltenter(Elf32_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
232 uintptr_t *defcookie
, La_sparcv8_regs
*regset
, uint_t
*sb_flags
)
233 #elif defined(__amd64)
235 la_amd64_pltenter(Elf64_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
236 uintptr_t *defcookie
, La_amd64_regs
*regset
, uint_t
*sb_flags
,
237 const char *sym_name
)
238 #elif defined(__i386)
240 la_i86_pltenter(Elf32_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
241 uintptr_t *defcookie
, La_i86_regs
*regset
, uint_t
*sb_flags
)
245 char *defname
= (char *)(*defcookie
);
246 char *refname
= (char *)(*refcookie
);
248 const char *sym_name
= (const char *)symp
->st_name
;
252 (void) sigprocmask(SIG_BLOCK
, &iset
, &oset
);
255 (void) fprintf(outfile
, "%5d:", (int)getpid());
257 if ((*sb_flags
& LA_SYMB_NOPLTEXIT
) == 0)
262 (void) fprintf(outfile
, "%-15s -> %15s:%-*s%s(0x%lx, 0x%lx, 0x%lx)\n",
263 refname
, defname
, indent_level
, istr
, sym_name
,
264 (long)GETARG0(regset
), (long)GETARG1(regset
),
265 (long)GETARG2(regset
));
267 (void) fflush(outfile
);
268 if (indent
&& ((*sb_flags
& LA_SYMB_NOPLTEXIT
) == 0))
270 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);
271 return (symp
->st_value
);
278 la_pltexit64(Elf64_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
279 uintptr_t *defcookie
, uintptr_t retval
, const char *sym_name
)
282 la_pltexit(Elf32_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
283 uintptr_t *defcookie
, uintptr_t retval
)
286 char *defname
= (char *)(*defcookie
);
287 char *refname
= (char *)(*refcookie
);
290 const char *sym_name
= (const char *)symp
->st_name
;
293 (void) sigprocmask(SIG_BLOCK
, &iset
, &oset
);
296 (void) fprintf(outfile
, "%5d:", (int)pid
);
299 (void) fprintf(outfile
, "%-15s -> %15s:%*s%s - 0x%lx\n", refname
,
300 defname
, indent_level
, "", sym_name
, (ulong_t
)retval
);
301 (void) fflush(outfile
);
302 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);