xref: /illumos-gate/usr/src/cmd/sgs/liblddbg/common/sections.c (revision bea83d026ee1bd1b2a2419e1d0232f107a5d7d9b)
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 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include	"msg.h"
29 #include	"_debug.h"
30 #include	"libld.h"
31 #include	"_string_table.h"
32 
33 void
34 Dbg_sec_strtab(Lm_list *lml, Os_desc *osp, Str_tbl *stp)
35 {
36 	uint_t	cnt;
37 
38 	if (DBG_NOTCLASS(DBG_C_STRTAB))
39 		return;
40 
41 	if (!osp)
42 		return;
43 
44 	Dbg_util_nl(lml, DBG_NL_STD);
45 	if (stp->st_flags & FLG_STTAB_COMPRESS)
46 		dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_COMP), osp->os_name,
47 		    EC_XWORD(stp->st_fullstrsize), EC_XWORD(stp->st_strsize));
48 	else
49 		dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_STND), osp->os_name,
50 		    EC_XWORD(stp->st_fullstrsize));
51 
52 	if ((DBG_NOTDETAIL()) ||
53 	    ((stp->st_flags & FLG_STTAB_COMPRESS) == 0))
54 		return;
55 
56 	dbg_print(lml, MSG_ORIG(MSG_STR_EMPTY));
57 	dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_HD), osp->os_name,
58 	    stp->st_hbckcnt);
59 
60 	for (cnt = 0; cnt < stp->st_hbckcnt; cnt++) {
61 		Str_hash	*strhash = stp->st_hashbcks[cnt];
62 
63 		if (strhash == 0)
64 			continue;
65 
66 		dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_BCKT), cnt);
67 
68 		while (strhash) {
69 			size_t	stroff = strhash->hi_mstr->sm_strlen -
70 			    strhash->hi_strlen;
71 
72 			if (stroff == 0) {
73 				dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_MSTR),
74 				    EC_XWORD(strhash->hi_refcnt),
75 				    strhash->hi_mstr->sm_str);
76 			} else {
77 				dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_SUFSTR),
78 				    EC_XWORD(strhash->hi_refcnt),
79 				    &strhash->hi_mstr->sm_str[stroff],
80 				    strhash->hi_mstr->sm_str);
81 			}
82 
83 			strhash = strhash->hi_next;
84 		}
85 	}
86 }
87 
88 void
89 Dbg_sec_genstr_compress(Lm_list *lml, const char *os_name,
90     Xword raw_size, Xword merge_size)
91 {
92 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
93 		return;
94 
95 	dbg_print(lml, MSG_INTL(MSG_SEC_GENSTR_COMP), os_name,
96 	    EC_XWORD(raw_size), EC_XWORD(merge_size));
97 }
98 
99 void
100 Dbg_sec_unsup_strmerge(Lm_list *lml, Is_desc *isp)
101 {
102 	const char *str;
103 
104 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
105 		return;
106 
107 	/*
108 	 * We can only merge string table sections with single byte
109 	 * (char) characters. For any other (wide) character types,
110 	 * issue a message so the user will understand why these
111 	 * sections are not being picked up.
112 	 */
113 	if ((isp->is_shdr->sh_entsize > 1) ||
114 	    (isp->is_shdr->sh_addralign > 1)) {
115 		str = (isp->is_file != NULL) ? isp->is_file->ifl_name :
116 		    MSG_INTL(MSG_STR_NULL);
117 		dbg_print(lml, MSG_INTL(MSG_SEC_STRMERGE_UNSUP),
118 		    isp->is_basename, str, EC_XWORD(isp->is_shdr->sh_addralign),
119 		    EC_XWORD(isp->is_shdr->sh_entsize));
120 	}
121 }
122 
123 void
124 Dbg_sec_in(Lm_list *lml, Is_desc *isp)
125 {
126 	const char	*str;
127 
128 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
129 		return;
130 
131 	if (isp->is_flags & FLG_IS_GNSTRMRG) {
132 		/*
133 		 * This section was generated because we have 1 or
134 		 * more SHF_MERGE|SHF_STRINGS input sections that we
135 		 * wish to merge. This new section will ultimately
136 		 * end up replacing those sections once it has been filled
137 		 * with their strings (merged and compressed) and relocations
138 		 * have been redirected.
139 		 */
140 		dbg_print(lml, MSG_INTL(MSG_SEC_INPUT_GENSTR), isp->is_name);
141 	} else {
142 		/* Standard input section */
143 		str = (isp->is_file != NULL) ? isp->is_file->ifl_name :
144 		    MSG_INTL(MSG_STR_NULL);
145 		dbg_print(lml, MSG_INTL(MSG_SEC_INPUT), isp->is_name, str);
146 	}
147 }
148 
149 void
150 Dbg_sec_added(Lm_list *lml, Os_desc *osp, Sg_desc *sgp)
151 {
152 	const char	*str;
153 
154 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
155 		return;
156 
157 	if (sgp->sg_name && *sgp->sg_name)
158 		str = sgp->sg_name;
159 	else
160 		str = MSG_INTL(MSG_STR_NULL);
161 
162 	dbg_print(lml, MSG_INTL(MSG_SEC_ADDED), osp->os_name, str);
163 }
164 
165 void
166 Dbg_sec_created(Lm_list *lml, Os_desc *osp, Sg_desc *sgp)
167 {
168 	const char	*str;
169 
170 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
171 		return;
172 
173 	if (sgp->sg_name && *sgp->sg_name)
174 		str = sgp->sg_name;
175 	else
176 		str = MSG_INTL(MSG_STR_NULL);
177 
178 	dbg_print(lml, MSG_INTL(MSG_SEC_CREATED), osp->os_name, str);
179 }
180 
181 void
182 Dbg_sec_discarded(Lm_list *lml, Is_desc *isp, Is_desc *disp)
183 {
184 	if (DBG_NOTCLASS(DBG_C_SECTIONS | DBG_C_UNUSED))
185 		return;
186 
187 	if ((isp->is_flags & FLG_IS_INSTRMRG) &&
188 	    (disp->is_flags & FLG_IS_GNSTRMRG)) {
189 		/*
190 		 * This SHF_MERGE|SHF_STRINGS input section is being
191 		 * discarded in favor of the generated merged string section.
192 		 */
193 		dbg_print(lml, MSG_INTL(MSG_SEC_STRMERGE_DISCARDED),
194 		    isp->is_basename, isp->is_file->ifl_name);
195 	} else {
196 		/* Generic section discard */
197 		dbg_print(lml, MSG_INTL(MSG_SEC_DISCARDED), isp->is_basename,
198 		    isp->is_file->ifl_name, disp->is_basename,
199 		    disp->is_file->ifl_name);
200 	}
201 }
202 
203 void
204 Dbg_sec_group(Lm_list *lml, Is_desc *isp, Group_desc *gdp)
205 {
206 	const char	*fmt;
207 
208 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
209 		return;
210 
211 	if (gdp->gd_flags & GRP_FLG_DISCARD)
212 		fmt = MSG_INTL(MSG_SEC_GRP_DISCARDED);
213 	else
214 		fmt = MSG_INTL(MSG_SEC_GRP_INPUT);
215 
216 	dbg_print(lml, fmt, isp->is_name, isp->is_file->ifl_name,
217 	    gdp->gd_gsectname, gdp->gd_symname);
218 }
219 
220 void
221 Dbg_sec_order_list(Ofl_desc *ofl, int flag)
222 {
223 	Os_desc		*osp;
224 	Is_desc		*isp1;
225 	Listnode	*lnp1, *lnp2;
226 	Lm_list		*lml = ofl->ofl_lml;
227 	const char	*str;
228 
229 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
230 		return;
231 	if (DBG_NOTDETAIL())
232 		return;
233 
234 	Dbg_util_nl(lml, DBG_NL_STD);
235 
236 	/*
237 	 * If the flag == 0, then the routine is called before sorting.
238 	 */
239 	if (flag == 0)
240 		str = MSG_INTL(MSG_ORD_SORT_BEFORE);
241 	else
242 		str = MSG_INTL(MSG_ORD_SORT_AFTER);
243 
244 	for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp1, osp)) {
245 		Sort_desc	*sort = osp->os_sort;
246 
247 		dbg_print(lml, str, osp->os_name);
248 		dbg_print(lml, MSG_INTL(MSG_ORD_HDR_1),
249 		    EC_WORD(sort->st_beforecnt), EC_WORD(sort->st_aftercnt),
250 		    EC_WORD(sort->st_ordercnt));
251 
252 		for (LIST_TRAVERSE(&osp->os_isdescs, lnp2, isp1)) {
253 			Word		link;
254 			Ifl_desc	*ifl = isp1->is_file;
255 			Is_desc		*isp2;
256 			const char	*msg;
257 
258 			if ((isp1->is_flags & FLG_IS_ORDERED) == 0) {
259 				dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_0),
260 				    isp1->is_name, isp1->is_file->ifl_name);
261 				continue;
262 			}
263 
264 			if (isp1->is_shdr->sh_flags & SHF_ORDERED) {
265 				link = isp1->is_shdr->sh_info;
266 				msg = MSG_ORIG(MSG_SH_INFO);
267 			} else {
268 				/* SHF_LINK_ORDER */
269 				link = isp1->is_shdr->sh_link;
270 				msg = MSG_ORIG(MSG_SH_LINK);
271 			}
272 
273 			if (link == SHN_BEFORE) {
274 				dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_1),
275 				    isp1->is_name, isp1->is_file->ifl_name,
276 				    msg);
277 				continue;
278 			}
279 
280 			if (link == SHN_AFTER) {
281 				dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_2),
282 				    isp1->is_name, isp1->is_file->ifl_name,
283 				    msg);
284 				continue;
285 			}
286 
287 			isp2 = ifl->ifl_isdesc[link];
288 			dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_3),
289 			    isp1->is_name, ifl->ifl_name, msg, isp2->is_name,
290 			    isp2->is_key);
291 		}
292 	}
293 	Dbg_util_nl(lml, DBG_NL_STD);
294 }
295 
296 /*
297  * Error message string table.
298  */
299 static const Msg order_errors[] = {
300 	MSG_ORD_ERR_INFORANGE,		/* MSG_INTL(MSG_ORD_ERR_INFORANGE) */
301 	MSG_ORD_ERR_ORDER,		/* MSG_INTL(MSG_ORD_ERR_ORDER) */
302 	MSG_ORD_ERR_LINKRANGE,		/* MSG_INTL(MSG_ORD_ERR_LINKRANGE) */
303 	MSG_ORD_ERR_FLAGS,		/* MSG_INTL(MSG_ORD_ERR_FLAGS) */
304 	MSG_ORD_ERR_CYCLIC,		/* MSG_INTL(MSG_ORD_ERR_CYCLIC) */
305 	MSG_ORD_ERR_LINKINV		/* MSG_INTL(MSG_ORD_ERR_LINKINV) */
306 };
307 
308 void
309 Dbg_sec_order_error(Lm_list *lml, Ifl_desc *ifl, Word ndx, int error)
310 {
311 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
312 		return;
313 	if (DBG_NOTDETAIL())
314 		return;
315 
316 	if (error == 0)
317 		return;
318 
319 	dbg_print(lml, MSG_INTL(MSG_ORD_ERR_TITLE),
320 	    ifl->ifl_isdesc[ndx]->is_name, ifl->ifl_name);
321 
322 	if (error)
323 		dbg_print(lml, MSG_INTL(order_errors[error - 1]));
324 }
325