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