Home | History | Annotate | Download | only in common
      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	<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 *
     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 *
     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
     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
    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
    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
    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
    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
    232 Dbg_sec_added(Lm_list *lml, Os_desc *osp, Sg_desc *sgp)
    233 {
    234 	const char	*str;
    235 
    236 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
    237 		return;
    238 
    239 	if (sgp->sg_name && *sgp->sg_name)
    240 		str = sgp->sg_name;
    241 	else
    242 		str = MSG_INTL(MSG_STR_NULL);
    243 
    244 	dbg_print(lml, MSG_INTL(MSG_SEC_ADDED), osp->os_name, str);
    245 }
    246 
    247 void
    248 Dbg_sec_created(Lm_list *lml, Os_desc *osp, Sg_desc *sgp)
    249 {
    250 	const char	*str;
    251 
    252 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
    253 		return;
    254 
    255 	if (sgp->sg_name && *sgp->sg_name)
    256 		str = sgp->sg_name;
    257 	else
    258 		str = MSG_INTL(MSG_STR_NULL);
    259 
    260 	dbg_print(lml, MSG_INTL(MSG_SEC_CREATED), osp->os_name, str);
    261 }
    262 
    263 void
    264 Dbg_sec_discarded(Lm_list *lml, Is_desc *isp, Is_desc *disp)
    265 {
    266 	if (DBG_NOTCLASS(DBG_C_SECTIONS | DBG_C_UNUSED))
    267 		return;
    268 
    269 	if ((isp->is_flags & FLG_IS_INSTRMRG) &&
    270 	    (disp->is_flags & FLG_IS_GNSTRMRG)) {
    271 		/*
    272 		 * This SHF_MERGE|SHF_STRINGS input section is being
    273 		 * discarded in favor of the generated merged string section.
    274 		 */
    275 		dbg_isec_name_buf_t	buf;
    276 		char			*alloc_mem;
    277 
    278 		dbg_print(lml, MSG_INTL(MSG_SEC_STRMERGE_DISCARDED),
    279 		    dbg_fmt_isec_name(isp, buf, &alloc_mem),
    280 		    isp->is_file->ifl_name);
    281 		if (alloc_mem != NULL)
    282 			free(alloc_mem);
    283 	} else {
    284 		/* Generic section discard */
    285 		dbg_isec_name_buf_t	buf1, buf2;
    286 		char			*alloc_mem1, *alloc_mem2;
    287 
    288 		dbg_print(lml, MSG_INTL(MSG_SEC_DISCARDED),
    289 		    dbg_fmt_isec_name(isp, buf1, &alloc_mem1),
    290 		    isp->is_file->ifl_name,
    291 		    dbg_fmt_isec_name(disp, buf2, &alloc_mem2),
    292 		    disp->is_file->ifl_name);
    293 		if (alloc_mem1 != NULL)
    294 			free(alloc_mem1);
    295 		if (alloc_mem2 != NULL)
    296 			free(alloc_mem2);
    297 	}
    298 }
    299 
    300 void
    301 Dbg_sec_group(Lm_list *lml, Is_desc *isp, Group_desc *gdp)
    302 {
    303 	dbg_isec_name_buf_t	buf;
    304 	char			*alloc_mem;
    305 	const char		*comdat, *isp_str;
    306 
    307 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
    308 		return;
    309 
    310 	if (gdp->gd_data[0] & GRP_COMDAT)
    311 		comdat = MSG_ORIG(MSG_STR_COMDAT);
    312 	else
    313 		comdat = MSG_ORIG(MSG_STR_EMPTY);
    314 
    315 	isp_str = dbg_fmt_isec_name(isp, buf, &alloc_mem);
    316 
    317 	if (isp->is_shdr->sh_type == SHT_GROUP) {
    318 		dbg_print(lml, MSG_INTL(MSG_SEC_GRP_DEFINE), isp_str,
    319 		    isp->is_file->ifl_name, comdat, gdp->gd_name);
    320 	} else {
    321 		dbg_print(lml, MSG_INTL(MSG_SEC_GRP_MEMBER), isp_str,
    322 		    isp->is_file->ifl_name, comdat, gdp->gd_name);
    323 	}
    324 
    325 	if (gdp->gd_oisc) {
    326 		dbg_print(lml, MSG_INTL(MSG_SEC_GRP_DISCARDED), isp_str,
    327 		    isp->is_file->ifl_name, gdp->gd_name,
    328 		    gdp->gd_oisc->is_file->ifl_name);
    329 	}
    330 
    331 	if (alloc_mem != NULL)
    332 		free(alloc_mem);
    333 }
    334 
    335 void
    336 Dbg_sec_order_list(Ofl_desc *ofl, int flag)
    337 {
    338 	Os_desc		*osp;
    339 	Is_desc		*isp1;
    340 	Aliste		idx1;
    341 	Lm_list		*lml = ofl->ofl_lml;
    342 	const char	*str;
    343 
    344 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
    345 		return;
    346 	if (DBG_NOTDETAIL())
    347 		return;
    348 
    349 	Dbg_util_nl(lml, DBG_NL_STD);
    350 
    351 	/*
    352 	 * If the flag == 0, then the routine is called before sorting.
    353 	 */
    354 	if (flag == 0)
    355 		str = MSG_INTL(MSG_ORD_SORT_BEFORE);
    356 	else
    357 		str = MSG_INTL(MSG_ORD_SORT_AFTER);
    358 
    359 	for (APLIST_TRAVERSE(ofl->ofl_ordered, idx1, osp)) {
    360 		int		os_isdescs_idx;
    361 		Aliste		idx2;
    362 
    363 		Dbg_util_nl(lml, DBG_NL_STD);
    364 		dbg_print(lml, str, osp->os_name);
    365 		dbg_print(lml, MSG_INTL(MSG_ORD_HDR_1),
    366 		    EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_BEFORE])),
    367 		    EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_ORDERED])),
    368 		    EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_DEFAULT])),
    369 		    EC_WORD(aplist_nitems(osp->os_isdescs[OS_ISD_AFTER])));
    370 
    371 		OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx2, isp1) {
    372 			dbg_isec_name_buf_t	buf;
    373 			char			*alloc_mem;
    374 			const char		*isp1_str;
    375 			Word			link;
    376 			Ifl_desc		*ifl = isp1->is_file;
    377 			Is_desc			*isp2;
    378 			const char		*msg;
    379 
    380 			/*
    381 			 * An output segment that requires ordering might have
    382 			 * as little as two sorted input sections.  For example,
    383 			 * the crt's can provide a SHN_BEGIN and SHN_AFTER, and
    384 			 * only these two sections must be processed.  Thus, if
    385 			 * a input section is unordered, move on.  Diagnosing
    386 			 * any unsorted section can produce way too much noise.
    387 			 */
    388 			if ((isp1->is_flags & FLG_IS_ORDERED) == 0)
    389 				continue;
    390 
    391 			if (isp1->is_shdr->sh_flags & SHF_ORDERED) {
    392 				link = isp1->is_shdr->sh_info;
    393 				msg = MSG_ORIG(MSG_SH_INFO);
    394 			} else {	/* SHF_LINK_ORDER */
    395 				link = isp1->is_shdr->sh_link;
    396 				msg = MSG_ORIG(MSG_SH_LINK);
    397 			}
    398 
    399 			isp1_str = dbg_fmt_isec_name(isp1, buf, &alloc_mem);
    400 
    401 			if (link == SHN_BEFORE) {
    402 				dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_1), msg,
    403 				    isp1_str, isp1->is_file->ifl_name);
    404 			} else if (link == SHN_AFTER) {
    405 				dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_2), msg,
    406 				    isp1_str, isp1->is_file->ifl_name);
    407 			} else {
    408 				isp2 = ifl->ifl_isdesc[link];
    409 				dbg_print(lml, MSG_INTL(MSG_ORD_TITLE_3),
    410 				    EC_WORD(isp2->is_keyident), isp1_str,
    411 				    ifl->ifl_name, msg, isp2->is_name);
    412 			}
    413 			if (alloc_mem != NULL)
    414 				free(alloc_mem);
    415 		}
    416 	}
    417 	Dbg_util_nl(lml, DBG_NL_STD);
    418 }
    419 
    420 /*
    421  * Error message string table.
    422  */
    423 static const Msg order_errors[] = {
    424 	MSG_ORD_ERR_INFORANGE,		/* MSG_INTL(MSG_ORD_ERR_INFORANGE) */
    425 	MSG_ORD_ERR_ORDER,		/* MSG_INTL(MSG_ORD_ERR_ORDER) */
    426 	MSG_ORD_ERR_LINKRANGE,		/* MSG_INTL(MSG_ORD_ERR_LINKRANGE) */
    427 	MSG_ORD_ERR_FLAGS,		/* MSG_INTL(MSG_ORD_ERR_FLAGS) */
    428 	MSG_ORD_ERR_CYCLIC,		/* MSG_INTL(MSG_ORD_ERR_CYCLIC) */
    429 	MSG_ORD_ERR_LINKINV		/* MSG_INTL(MSG_ORD_ERR_LINKINV) */
    430 };
    431 
    432 void
    433 Dbg_sec_order_error(Lm_list *lml, Ifl_desc *ifl, Word ndx, int error)
    434 {
    435 	dbg_isec_name_buf_t	buf;
    436 	char			*alloc_mem;
    437 
    438 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
    439 		return;
    440 	if (DBG_NOTDETAIL())
    441 		return;
    442 
    443 	if (error == 0)
    444 		return;
    445 
    446 	dbg_print(lml, MSG_INTL(MSG_ORD_ERR_TITLE),
    447 	    dbg_fmt_isec_name(ifl->ifl_isdesc[ndx], buf, &alloc_mem),
    448 	    ifl->ifl_name);
    449 	if (alloc_mem != NULL)
    450 		free(alloc_mem);
    451 
    452 	if (error)
    453 		dbg_print(lml, MSG_INTL(order_errors[error - 1]));
    454 }
    455 
    456 void
    457 Dbg_sec_redirected(Lm_list *lml, Is_desc *isp, const char *nname)
    458 {
    459 	dbg_isec_name_buf_t	buf;
    460 	char			*alloc_mem;
    461 
    462 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
    463 		return;
    464 
    465 	dbg_print(lml, MSG_INTL(MSG_SEC_REDIRECTED),
    466 	    dbg_fmt_isec_name(isp, buf, &alloc_mem), nname);
    467 	if (alloc_mem != NULL)
    468 		free(alloc_mem);
    469 }
    470 
    471 void
    472 Dbg_sec_gnu_comdat(Lm_list *lml, Is_desc *isp, Boolean comdat, Boolean relax)
    473 {
    474 	dbg_isec_name_buf_t	buf;
    475 	char			*alloc_mem;
    476 	const char		*fmt;
    477 
    478 	if (DBG_NOTCLASS(DBG_C_SECTIONS))
    479 		return;
    480 
    481 	if (comdat && relax)
    482 		fmt = MSG_INTL(MSG_SEC_GNU_COMDAT_1);
    483 	else if (comdat)
    484 		fmt = MSG_INTL(MSG_SEC_GNU_COMDAT_2);
    485 	else
    486 		fmt = MSG_INTL(MSG_SEC_GNU_COMDAT_3);
    487 
    488 	dbg_print(lml, fmt, dbg_fmt_isec_name(isp, buf, &alloc_mem));
    489 	if (alloc_mem != NULL)
    490 		free(alloc_mem);
    491 }
    492