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 * 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 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 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 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 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 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 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 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 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