1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include	"msg.h"
28 #include	"_debug.h"
29 #include	"libld.h"
30 
31 void
Dbg_dl_iphdr_enter(Rt_map * clmp,u_longlong_t cnt_map,u_longlong_t cnt_unmap)32 Dbg_dl_iphdr_enter(Rt_map *clmp, u_longlong_t cnt_map, u_longlong_t cnt_unmap)
33 {
34 	Lm_list	*lml = LIST(clmp);
35 
36 	if (DBG_NOTCLASS(DBG_C_DL))
37 		return;
38 
39 	Dbg_util_nl(lml, DBG_NL_STD);
40 	dbg_print(lml, MSG_INTL(MSG_DL_IPHDR_ENTER), NAME(clmp));
41 	dbg_print(lml, MSG_INTL(MSG_DL_IPHDR_MAPCNT), cnt_map, cnt_unmap);
42 }
43 
44 void
Dbg_dl_iphdr_callback(Lm_list * lml,struct dl_phdr_info * info)45 Dbg_dl_iphdr_callback(Lm_list *lml, struct dl_phdr_info *info)
46 {
47 	if (DBG_NOTCLASS(DBG_C_DL))
48 		return;
49 
50 	dbg_print(lml, MSG_INTL(MSG_DL_IPHDR_CALLBACK));
51 	dbg_print(lml, MSG_INTL(MSG_DL_IPHDR_NAME), info->dlpi_name);
52 	dbg_print(lml, MSG_INTL(MSG_DL_IPHDR_ADDR), EC_ADDR(info->dlpi_addr));
53 	dbg_print(lml, MSG_INTL(MSG_DL_IPHDR_PHDR),
54 	    EC_ADDR(CAST_PTRINT(Addr, info->dlpi_phdr)),
55 	    EC_WORD(info->dlpi_phnum));
56 }
57 
58 void
Dbg_dl_iphdr_mapchange(Lm_list * lml,u_longlong_t cnt_map,u_longlong_t cnt_unmap)59 Dbg_dl_iphdr_mapchange(Lm_list *lml, u_longlong_t cnt_map,
60     u_longlong_t cnt_unmap)
61 {
62 	if (DBG_NOTCLASS(DBG_C_DL))
63 		return;
64 
65 	dbg_print(lml, MSG_INTL(MSG_DL_IPHDR_MAPCNG));
66 	dbg_print(lml, MSG_INTL(MSG_DL_IPHDR_MAPCNT), cnt_map, cnt_unmap);
67 }
68 
69 void
Dbg_dl_iphdr_unmap_ret(Lm_list * lml)70 Dbg_dl_iphdr_unmap_ret(Lm_list *lml)
71 {
72 	if (DBG_NOTCLASS(DBG_C_DL))
73 		return;
74 
75 	dbg_print(lml, MSG_INTL(MSG_DL_IPHDR_UNMAP));
76 }
77 
78 void
Dbg_dl_dlopen(Rt_map * clmp,const char * name,int * in_nfavl,int mode)79 Dbg_dl_dlopen(Rt_map *clmp, const char *name, int *in_nfavl, int mode)
80 {
81 	Conv_dl_mode_buf_t	dl_mode_buf;
82 	Lm_list			*lml = LIST(clmp);
83 	const char		*retry;
84 
85 	if (DBG_NOTCLASS(DBG_C_FILES | DBG_C_DL))
86 		return;
87 
88 	/*
89 	 * The core functionality of dlopen() can be called twice.  The first
90 	 * attempt can be affected by path names that exist in the "not-found"
91 	 * AVL tree.  Should a "not-found" path name be found, a second attempt
92 	 * is made to locate the required file (in_nfavl is NULL).  This fall-
93 	 * back provides for file system changes while a process executes.
94 	 */
95 	if (in_nfavl)
96 		retry = MSG_ORIG(MSG_STR_EMPTY);
97 	else
98 		retry = MSG_INTL(MSG_STR_RETRY);
99 
100 	Dbg_util_nl(lml, DBG_NL_STD);
101 	dbg_print(lml, MSG_INTL(MSG_DL_DLOPEN), name, NAME(clmp), retry,
102 	    conv_dl_mode(mode, 0, &dl_mode_buf));
103 }
104 
105 void
Dbg_dl_dlclose(Rt_map * clmp,const char * name,int flag)106 Dbg_dl_dlclose(Rt_map *clmp, const char *name, int flag)
107 {
108 	const char	*str;
109 	Lm_list		*lml = LIST(clmp);
110 
111 	if (DBG_NOTCLASS(DBG_C_FILES | DBG_C_DL))
112 		return;
113 
114 	if (flag == DBG_DLCLOSE_IGNORE)
115 		str = MSG_INTL(MSG_STR_IGNORE);
116 	else
117 		str = MSG_ORIG(MSG_STR_EMPTY);
118 
119 	Dbg_util_nl(lml, DBG_NL_STD);
120 	dbg_print(lml, MSG_INTL(MSG_DL_DLCLOSE), name, NAME(clmp), str);
121 }
122 
123 void
Dbg_dl_dldump(Rt_map * clmp,const char * ipath,const char * opath,int flags)124 Dbg_dl_dldump(Rt_map *clmp, const char *ipath, const char *opath, int flags)
125 {
126 	Conv_dl_flag_buf_t	dl_flag_buf;
127 	Lm_list			*lml = LIST(clmp);
128 
129 	if (DBG_NOTCLASS(DBG_C_FILES | DBG_C_DL))
130 		return;
131 
132 	Dbg_util_nl(lml, DBG_NL_STD);
133 	dbg_print(lml, MSG_INTL(MSG_DL_DLDUMP), ipath, NAME(clmp),
134 	    opath ? opath : MSG_INTL(MSG_STR_NULL),
135 	    conv_dl_flag(flags, 0, &dl_flag_buf));
136 }
137 
138 void
Dbg_dl_dlerror(Rt_map * clmp,const char * str)139 Dbg_dl_dlerror(Rt_map *clmp, const char *str)
140 {
141 	Lm_list	*lml = LIST(clmp);
142 
143 	if (DBG_NOTCLASS(DBG_C_DL))
144 		return;
145 
146 	Dbg_util_nl(lml, DBG_NL_STD);
147 	dbg_print(lml, MSG_INTL(MSG_DL_DLERROR), NAME(clmp),
148 	    str ? str : MSG_INTL(MSG_STR_NULL));
149 }
150 
151 void
Dbg_dl_dladdr(Rt_map * clmp,void * addr)152 Dbg_dl_dladdr(Rt_map *clmp, void *addr)
153 {
154 	Lm_list	*lml = LIST(clmp);
155 
156 	if (DBG_NOTCLASS(DBG_C_DL))
157 		return;
158 
159 	Dbg_util_nl(lml, DBG_NL_STD);
160 	dbg_print(lml, MSG_INTL(MSG_DL_DLADDR), NAME(clmp), EC_NATPTR(addr));
161 }
162 
163 void
Dbg_dl_dlsym(Rt_map * clmp,const char * sym,int * in_nfavl,const char * next,int type)164 Dbg_dl_dlsym(Rt_map *clmp, const char *sym, int *in_nfavl, const char *next,
165     int type)
166 {
167 	const char	*str, *retry, *from = NAME(clmp);
168 	Lm_list		*lml = LIST(clmp);
169 
170 	static const Msg	dlsym_msg[DBG_DLSYM_NUM] = {
171 		MSG_STR_EMPTY,		/* MSG_ORIG(MSG_STR_EMPTY) */
172 		MSG_DLSYM_NEXT,		/* MSG_ORIG(MSG_DLSYM_NEXT) */
173 		MSG_DLSYM_DEFAULT,	/* MSG_ORIG(MSG_DLSYM_DEFAULT) */
174 		MSG_DLSYM_SELF,		/* MSG_ORIG(MSG_DLSYM_SELF) */
175 		MSG_DLSYM_PROBE,	/* MSG_ORIG(MSG_DLSYM_PROBE) */
176 		MSG_DLSYM_SINGLETON	/* MSG_ORIG(MSG_DLSYM_SINGLETON) */
177 	};
178 #if	DBG_DLSYM_NUM != (DBG_DLSYM_SINGLETON + 1)
179 #error	DBG_DLSYM_NUM has grown
180 #endif
181 	if (DBG_NOTCLASS(DBG_C_SYMBOLS | DBG_C_DL))
182 		return;
183 
184 	/*
185 	 * The core functionality of dlsym() can be called twice.  The first
186 	 * attempt can be affected by path names that exist in the "not-found"
187 	 * AVL tree.  Should a "not-found" path name be found, a second attempt
188 	 * is made to locate the required file (in_nfavl is NULL).  This fall-
189 	 * back provides for file system changes while a process executes.
190 	 */
191 	if (in_nfavl)
192 		retry = MSG_ORIG(MSG_STR_EMPTY);
193 	else
194 		retry = MSG_INTL(MSG_STR_RETRY);
195 
196 	if (type >= DBG_DLSYM_NUM)
197 		type = 0;
198 	str = MSG_ORIG(dlsym_msg[type]);
199 
200 	Dbg_util_nl(lml, DBG_NL_STD);
201 	if (next == 0)
202 		dbg_print(lml, MSG_INTL(MSG_DLSYM_1), Dbg_demangle_name(sym),
203 		    from, retry, str);
204 	else
205 		dbg_print(lml, MSG_INTL(MSG_DLSYM_2), Dbg_demangle_name(sym),
206 		    from, next, retry, str);
207 }
208 
209 void
Dbg_dl_dlinfo(Rt_map * clmp,const char * name,int request,void * addr)210 Dbg_dl_dlinfo(Rt_map *clmp, const char *name, int request, void *addr)
211 {
212 	Lm_list	*lml = LIST(clmp);
213 
214 	if (DBG_NOTCLASS(DBG_C_DL))
215 		return;
216 
217 	Dbg_util_nl(lml, DBG_NL_STD);
218 	dbg_print(lml, MSG_INTL(MSG_DL_DLINFO), NAME(clmp), name,
219 	    conv_dl_info(request), EC_NATPTR(addr));
220 }
221