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 #include <stdio.h>
27 #include "msg.h"
28 #include "_debug.h"
29 #include "libld.h"
30 #include "_string_table.h"
31
32 /*
33 * Format an input section descriptor name for output, in the format
34 * [ndx]name
35 * If possible, a user supplied fixed size buffer is used. Failing that,
36 * dynamic memory is allocated, which must be freed by the caller.
37 *
38 * entry:
39 * [dbg_fmt_isec_name2]: name, scnndx - Name and section index
40 * [dbg_fmt_isec_name]: isp - Input section descriptor giving name
41 * and index.
42 *
43 * buf - Caller supplied buffer
44 * alloc_mem - Address of pointer to be set to address of allocated
45 * memory, or NULL if no memory is allocated.
46 *
47 * exit:
48 * A pointer to the formatted string is returned. If the supplied buffer
49 * was sufficient, *alloc_mem is set to NULL. If memory was allocated,
50 * *alloc_mem references it. The caller must free this memory after use.
51 */
52 const char *
dbg_fmt_isec_name2(const char * name,Word scnndx,dbg_isec_name_buf_t buf,char ** alloc_mem)53 dbg_fmt_isec_name2(const char *name, Word scnndx, dbg_isec_name_buf_t buf,
54 char **alloc_mem)
55 {
56 int cnt;
57
58 /*
59 * If the section index is 0, it's not a real section.
60 * Just use the name as is.
61 */
62 if (scnndx == 0) {
63 *alloc_mem = NULL;
64 return (name);
65 }
66
67 /* Format into the fixed buffer */
68 cnt = snprintf(buf, sizeof (dbg_isec_name_buf_t),
69 MSG_ORIG(MSG_FMT_ISEC_NAME), EC_WORD(scnndx), name);
70
71 /*
72 * If the name was too long, try to allocate a dynamic buffer.
73 * Failing that, fall through and use the clipped one already
74 * formatted into buf, as that's better than nothing.
75 */
76 if ((cnt >= sizeof (dbg_isec_name_buf_t)) &&
77 ((*alloc_mem = malloc(cnt + 1)) != NULL)) {
78 (void) snprintf(*alloc_mem, cnt + 1,
79 MSG_ORIG(MSG_FMT_ISEC_NAME), EC_WORD(scnndx), name);
80 return (*alloc_mem);
81 }
82
83 /* Return the caller supplied buffer */
84 *alloc_mem = NULL;
85 return (buf);
86 }
87 const char *
dbg_fmt_isec_name(Is_desc * isp,dbg_isec_name_buf_t buf,char ** alloc_mem)88 dbg_fmt_isec_name(Is_desc *isp, dbg_isec_name_buf_t buf, char **alloc_mem)
89 {
90 return (dbg_fmt_isec_name2(isp->is_name, isp->is_scnndx, buf,
91 alloc_mem));
92 }
93
94 void
Dbg_sec_strtab(Lm_list * lml,Os_desc * osp,Str_tbl * stp)95 Dbg_sec_strtab(Lm_list *lml, Os_desc *osp, Str_tbl *stp)
96 {
97 uint_t cnt;
98
99 if (DBG_NOTCLASS(DBG_C_STRTAB))
100 return;
101
102 if (!osp)
103 return;
104
105 Dbg_util_nl(lml, DBG_NL_STD);
106 if (stp->st_flags & FLG_STTAB_COMPRESS)
107 dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_COMP), osp->os_name,
108 EC_XWORD(stp->st_fullstrsize), EC_XWORD(stp->st_strsize));
109 else
110 dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_STND), osp->os_name,
111 EC_XWORD(stp->st_fullstrsize));
112
113 if ((DBG_NOTDETAIL()) ||
114 ((stp->st_flags & FLG_STTAB_COMPRESS) == 0))
115 return;
116
117 dbg_print(lml, MSG_ORIG(MSG_STR_EMPTY));
118 dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_HD), osp->os_name,
119 stp->st_hbckcnt);
120
121 for (cnt = 0; cnt < stp->st_hbckcnt; cnt++) {
122 Str_hash *strhash = stp->st_hashbcks[cnt];
123
124 if (strhash == NULL)
125 continue;
126
127 dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_BCKT), cnt);
128
129 while (strhash) {
130 size_t stroff = strhash->hi_mstr->sm_strlen -
131 strhash->hi_strlen;
132
133 if (stroff == 0) {
134 dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_MSTR),
135 EC_XWORD(strhash->hi_refcnt),
136 strhash->hi_mstr->sm_str);
137 } else {
138 dbg_print(lml, MSG_INTL(MSG_SEC_STRTAB_SUFSTR),
139 EC_XWORD(strhash->hi_refcnt),
140 &strhash->hi_mstr->sm_str[stroff],
141 strhash->hi_mstr->sm_str);
142 }
143
144 strhash = strhash->hi_next;
145 }
146 }
147 }
148
149 void
Dbg_sec_genstr_compress(Lm_list * lml,const char * os_name,Xword raw_size,Xword merge_size)150 Dbg_sec_genstr_compress(Lm_list *lml, const char *os_name,
151 Xword raw_size, Xword merge_size)
152 {
153 if (DBG_NOTCLASS(DBG_C_SECTIONS))
154 return;
155
156 dbg_print(lml, MSG_INTL(MSG_SEC_GENSTR_COMP), os_name,
157 EC_XWORD(raw_size), EC_XWORD(merge_size));
158 }
159
160 void
Dbg_sec_unsup_strmerge(Lm_list * lml,Is_desc * isp)161 Dbg_sec_unsup_strmerge(Lm_list *lml, Is_desc *isp)
162 {
163 dbg_isec_name_buf_t buf;
164 char *alloc_mem;
165 const char *str;
166
167 if (DBG_NOTCLASS(DBG_C_SECTIONS))
168 return;
169
170 /*
171 * We can only merge string table sections with single byte
172 * (char) characters. For any other (wide) character types,
173 * issue a message so the user will understand why these
174 * sections are not being picked up.
175 */
176 if ((isp->is_shdr->sh_entsize > 1) ||
177 (isp->is_shdr->sh_addralign > 1)) {
178 str = (isp->is_file != NULL) ? isp->is_file->ifl_name :
179 MSG_INTL(MSG_STR_NULL);
180 dbg_print(lml, MSG_INTL(MSG_SEC_STRMERGE_UNSUP),
181 dbg_fmt_isec_name(isp, buf, &alloc_mem), str,
182 EC_XWORD(isp->is_shdr->sh_addralign),
183 EC_XWORD(isp->is_shdr->sh_entsize));
184 if (alloc_mem != NULL)
185 free(alloc_mem);
186 }
187 }
188
189 void
Dbg_sec_backing(Lm_list * lml)190 Dbg_sec_backing(Lm_list *lml)
191 {
192 if (DBG_NOTCLASS(DBG_C_SECTIONS))
193 return;
194
195 Dbg_util_nl(lml, DBG_NL_STD);
196 dbg_print(lml, MSG_INTL(MSG_SEC_BACKING));
197 }
198
199 void
Dbg_sec_in(Lm_list * lml,Is_desc * isp)200 Dbg_sec_in(Lm_list *lml, Is_desc *isp)
201 {
202 if (DBG_NOTCLASS(DBG_C_SECTIONS))
203 return;
204
205 if (isp->is_flags & FLG_IS_GNSTRMRG) {
206 /*
207 * This section was generated because we have 1 or
208 * more SHF_MERGE|SHF_STRINGS input sections that we
209 * wish to merge. This new section will ultimately
210 * end up replacing those sections once it has been filled
211 * with their strings (merged and compressed) and relocations
212 * have been redirected.
213 */
214 dbg_print(lml, MSG_INTL(MSG_SEC_INPUT_GENSTR), isp->is_name);
215 } else if (isp->is_file == NULL) {
216 /* Generated input section */
217 dbg_print(lml, MSG_INTL(MSG_SEC_INPUT_GEN), isp->is_name);
218 } else {
219 /* Standard input section */
220 dbg_isec_name_buf_t buf;
221 char *alloc_mem;
222
223 dbg_print(lml, MSG_INTL(MSG_SEC_INPUT),
224 dbg_fmt_isec_name(isp, buf, &alloc_mem),
225 isp->is_file->ifl_name);
226 if (alloc_mem != NULL)
227 free(alloc_mem);
228 }
229 }
230
231 void
Dbg_sec_added(Lm_list * lml,Os_desc * osp,Sg_desc * sgp)232 Dbg_sec_added(Lm_list *lml, Os_desc *osp, Sg_desc *sgp)
233 {
234 if (DBG_NOTCLASS(DBG_C_SECTIONS))
235 return;
236
237 dbg_print(lml, MSG_INTL(MSG_SEC_ADDED), osp->os_name,
238 (sgp->sg_name ? sgp->sg_name : MSG_INTL(MSG_STR_NULL)));
239 }
240
241 void
Dbg_sec_created(Lm_list * lml,Os_desc * osp,Sg_desc * sgp)242 Dbg_sec_created(Lm_list *lml, Os_desc *osp, Sg_desc *sgp)
243 {
244 if (DBG_NOTCLASS(DBG_C_SECTIONS))
245 return;
246
247 dbg_print(lml, MSG_INTL(MSG_SEC_CREATED), osp->os_name,
248 (sgp->sg_name ? sgp->sg_name : MSG_INTL(MSG_STR_NULL)));
249 }
250
251 void
Dbg_sec_discarded(Lm_list * lml,Is_desc * isp,Is_desc * disp)252 Dbg_sec_discarded(Lm_list *lml, Is_desc *isp, Is_desc *disp)
253 {
254 if (DBG_NOTCLASS(DBG_C_SECTIONS | DBG_C_UNUSED))
255 return;
256
257 if ((isp->is_flags & FLG_IS_INSTRMRG) &&
258 (disp->is_flags & FLG_IS_GNSTRMRG)) {
259 /*
260 * This SHF_MERGE|SHF_STRINGS input section is being
261 * discarded in favor of the generated merged string section.
262 */
263 dbg_isec_name_buf_t buf;
264 char *alloc_mem;
265
266 dbg_print(lml, MSG_INTL(MSG_SEC_STRMERGE_DISCARDED),
267 dbg_fmt_isec_name(isp, buf, &alloc_mem),
268 isp->is_file->ifl_name);
269 if (alloc_mem != NULL)
270 free(alloc_mem);
271 } else {
272 /* Generic section discard */
273 dbg_isec_name_buf_t buf1, buf2;
274 char *alloc_mem1, *alloc_mem2;
275
276 dbg_print(lml, MSG_INTL(MSG_SEC_DISCARDED),
277 dbg_fmt_isec_name(isp, buf1, &alloc_mem1),
278 isp->is_file->ifl_name,
279 dbg_fmt_isec_name(disp, buf2, &alloc_mem2),
280 disp->is_file->ifl_name);
281 if (alloc_mem1 != NULL)
282 free(alloc_mem1);
283 if (alloc_mem2 != NULL)
284 free(alloc_mem2);
285 }
286 }
287
288 void
Dbg_sec_group(Lm_list * lml,Is_desc * isp,Group_desc * gdp)289 Dbg_sec_group(Lm_list *lml, Is_desc *isp, Group_desc *gdp)
290 {
291 dbg_isec_name_buf_t buf;
292 char *alloc_mem;
293 const char *comdat, *isp_str;
294
295 if (DBG_NOTCLASS(DBG_C_SECTIONS))
296 return;
297
298 if (gdp->gd_data[0] & GRP_COMDAT)
299 comdat = MSG_ORIG(MSG_STR_COMDAT);
300 else
301 comdat = MSG_ORIG(MSG_STR_EMPTY);
302
303 isp_str = dbg_fmt_isec_name(isp, buf, &alloc_mem);
304
305 if (isp->is_shdr->sh_type == SHT_GROUP) {
306 dbg_print(lml, MSG_INTL(MSG_SEC_GRP_DEFINE), isp_str,
307 isp->is_file->ifl_name, comdat, gdp->gd_name);
308 } else {
309 dbg_print(lml, MSG_INTL(MSG_SEC_GRP_MEMBER), isp_str,
310 isp->is_file->ifl_name, comdat, gdp->gd_name);
311 }
312
313 if (gdp->gd_oisc) {
314 dbg_print(lml, MSG_INTL(MSG_SEC_GRP_DISCARDED), isp_str,
315 isp->is_file->ifl_name, gdp->gd_name,
316 gdp->gd_oisc->is_file->ifl_name);
317 }
318
319 if (alloc_mem != NULL)
320 free(alloc_mem);
321 }
322
323 void
Dbg_sec_order_list(Ofl_desc * ofl,int flag)324 Dbg_sec_order_list(Ofl_desc *ofl, int flag)
325 {
326 Os_desc *osp;
327 Is_desc *isp1;
328 Aliste idx1;
329 Lm_list *lml = ofl->ofl_lml;
330 const char *str;
331
332 if (DBG_NOTCLASS(DBG_C_SECTIONS))
333 return;
334 if (DBG_NOTDETAIL())
335 return;
336
337 Dbg_util_nl(lml, DBG_NL_STD);
338
339 /*
340 * If the flag == 0, then the routine is called before sorting.
341 */
342 if (flag == 0)
343 str = MSG_INTL(MSG_ORD_SORT_BEFORE);
344 else
345 str = MSG_INTL(MSG_ORD_SORT_AFTER);
346
347 for (APLIST_TRAVERSE(ofl->ofl_ordered, idx1, osp)) {
348 int os_isdescs_idx;
349 Aliste idx2;
350
351 Dbg_util_nl(lml, DBG_NL_STD);
352 dbg_print(lml, str, osp->os_name);
353 dbg_print(lml, MSG_INTL(MSG_ORD_HDR_1),
354 EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_BEFORE])),
355 EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_ORDERED])),
356 EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_DEFAULT])),
357 EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_AFTER])));
358
359 OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx2, isp1) {
360 dbg_isec_name_buf_t buf;
361 char *alloc_mem;
362 const char *isp1_str;
363 Word link;
364 Ifl_desc *ifl = isp1->is_file;
365 Is_desc *isp2;
366 const char *msg;
367
368 /*
369 * An output segment that requires ordering might have
370 * as little as two sorted input sections. For example,
371 * the crt's can provide a SHN_BEGIN and SHN_AFTER, and
372 * only these two sections must be processed. Thus, if
373 * a input section is unordered, move on. Diagnosing
374 * any unsorted section can produce way too much noise.
375 */
376 if ((isp1->is_flags & FLG_IS_ORDERED) == 0)
377 continue;
378
379 if (isp1->is_shdr->sh_flags & SHF_ORDERED) {
380 link = isp1->is_shdr->sh_info;
381 msg = MSG_ORIG(MSG_SH_INFO);
382 } else { /* SHF_LINK_ORDER */
383 link = isp1->is_shdr->sh_link;
384 msg = MSG_ORIG(MSG_SH_LINK);
385 }
386
387 isp1_str = dbg_fmt_isec_name(isp1, buf, &alloc_mem);
388
389 if (link == SHN_BEFORE) {
390 dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_1), msg,
391 isp1_str, isp1->is_file->ifl_name);
392 } else if (link == SHN_AFTER) {
393 dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_2), msg,
394 isp1_str, isp1->is_file->ifl_name);
395 } else {
396 isp2 = ifl->ifl_isdesc[link];
397 dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_3),
398 EC_WORD(isp2->is_keyident), isp1_str,
399 ifl->ifl_name, msg, isp2->is_name);
400 }
401 if (alloc_mem != NULL)
402 free(alloc_mem);
403 }
404 }
405 Dbg_util_nl(lml, DBG_NL_STD);
406 }
407
408 /*
409 * Error message string table.
410 */
411 static const Msg order_errors[] = {
412 MSG_ORD_ERR_INFORANGE, /* MSG_INTL(MSG_ORD_ERR_INFORANGE) */
413 MSG_ORD_ERR_ORDER, /* MSG_INTL(MSG_ORD_ERR_ORDER) */
414 MSG_ORD_ERR_LINKRANGE, /* MSG_INTL(MSG_ORD_ERR_LINKRANGE) */
415 MSG_ORD_ERR_FLAGS, /* MSG_INTL(MSG_ORD_ERR_FLAGS) */
416 MSG_ORD_ERR_CYCLIC, /* MSG_INTL(MSG_ORD_ERR_CYCLIC) */
417 MSG_ORD_ERR_LINKINV /* MSG_INTL(MSG_ORD_ERR_LINKINV) */
418 };
419
420 void
Dbg_sec_order_error(Lm_list * lml,Ifl_desc * ifl,Word ndx,int error)421 Dbg_sec_order_error(Lm_list *lml, Ifl_desc *ifl, Word ndx, int error)
422 {
423 dbg_isec_name_buf_t buf;
424 char *alloc_mem;
425
426 if (DBG_NOTCLASS(DBG_C_SECTIONS))
427 return;
428 if (DBG_NOTDETAIL())
429 return;
430
431 if (error == 0)
432 return;
433
434 dbg_print(lml, MSG_INTL(MSG_ORD_ERR_TITLE),
435 dbg_fmt_isec_name(ifl->ifl_isdesc[ndx], buf, &alloc_mem),
436 ifl->ifl_name);
437 if (alloc_mem != NULL)
438 free(alloc_mem);
439
440 if (error)
441 dbg_print(lml, MSG_INTL(order_errors[error - 1]));
442 }
443
444 void
Dbg_sec_redirected(Lm_list * lml,Is_desc * isp,const char * nname)445 Dbg_sec_redirected(Lm_list *lml, Is_desc *isp, const char *nname)
446 {
447 dbg_isec_name_buf_t buf;
448 char *alloc_mem;
449
450 if (DBG_NOTCLASS(DBG_C_SECTIONS))
451 return;
452
453 dbg_print(lml, MSG_INTL(MSG_SEC_REDIRECTED),
454 dbg_fmt_isec_name(isp, buf, &alloc_mem), nname);
455 if (alloc_mem != NULL)
456 free(alloc_mem);
457 }
458
459 void
Dbg_sec_gnu_comdat(Lm_list * lml,Is_desc * isp,Boolean comdat,Boolean relax)460 Dbg_sec_gnu_comdat(Lm_list *lml, Is_desc *isp, Boolean comdat, Boolean relax)
461 {
462 dbg_isec_name_buf_t buf;
463 char *alloc_mem;
464 const char *fmt;
465
466 if (DBG_NOTCLASS(DBG_C_SECTIONS))
467 return;
468
469 if (comdat && relax)
470 fmt = MSG_INTL(MSG_SEC_GNU_COMDAT_1);
471 else if (comdat)
472 fmt = MSG_INTL(MSG_SEC_GNU_COMDAT_2);
473 else
474 fmt = MSG_INTL(MSG_SEC_GNU_COMDAT_3);
475
476 dbg_print(lml, fmt, dbg_fmt_isec_name(isp, buf, &alloc_mem));
477 if (alloc_mem != NULL)
478 free(alloc_mem);
479 }
480