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 (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <stdio.h> 32 #include <string.h> 33 #include "msg.h" 34 #include "_libld.h" 35 36 37 /* 38 * Print a virtual address map of input and output sections together with 39 * multiple symbol definitions (if they exist). 40 */ 41 static Boolean symbol_title = TRUE; 42 43 static void 44 sym_muldef_title() 45 { 46 (void) printf(MSG_INTL(MSG_ENT_MUL_FMT_TIL_0), 47 MSG_INTL(MSG_ENT_MUL_TIL_0)); 48 (void) printf(MSG_INTL(MSG_ENT_MUL_FMT_TIL_1), 49 MSG_INTL(MSG_ENT_MUL_ITM_SYM), 50 MSG_INTL(MSG_ENT_MUL_ITM_DEF_0), 51 MSG_INTL(MSG_ENT_MUL_ITM_DEF_1)); 52 symbol_title = FALSE; 53 } 54 55 void 56 ld_map_out(Ofl_desc * ofl) 57 { 58 Listnode * lnp1, * lnp2, * lnp3; 59 Sg_desc * sgp; 60 Is_desc * isp; 61 Sym_avlnode *sav; 62 63 (void) printf(MSG_INTL(MSG_ENT_MAP_FMT_TIL_1), 64 MSG_INTL(MSG_ENT_MAP_TITLE_1)); 65 if (ofl->ofl_flags & FLG_OF_RELOBJ) 66 (void) printf(MSG_INTL(MSG_ENT_MAP_FMT_TIL_2), 67 MSG_INTL(MSG_ENT_ITM_OUTPUT), 68 MSG_INTL(MSG_ENT_ITM_INPUT), 69 MSG_INTL(MSG_ENT_ITM_NEW), 70 MSG_INTL(MSG_ENT_ITM_SECTION), 71 MSG_INTL(MSG_ENT_ITM_SECTION), 72 MSG_INTL(MSG_ENT_ITM_DISPMNT), 73 MSG_INTL(MSG_ENT_ITM_SIZE)); 74 else 75 (void) printf(MSG_INTL(MSG_ENT_MAP_FMT_TIL_3), 76 MSG_INTL(MSG_ENT_ITM_OUTPUT), 77 MSG_INTL(MSG_ENT_ITM_INPUT), 78 MSG_INTL(MSG_ENT_ITM_VIRTUAL), 79 MSG_INTL(MSG_ENT_ITM_SECTION), 80 MSG_INTL(MSG_ENT_ITM_SECTION), 81 MSG_INTL(MSG_ENT_ITM_ADDRESS), 82 MSG_INTL(MSG_ENT_ITM_SIZE)); 83 84 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) { 85 Os_desc *osp; 86 Aliste idx; 87 88 if (sgp->sg_phdr.p_type != PT_LOAD) 89 continue; 90 91 for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) { 92 93 (void) printf(MSG_INTL(MSG_ENT_MAP_ENTRY_1), 94 osp->os_name, EC_ADDR(osp->os_shdr->sh_addr), 95 EC_XWORD(osp->os_shdr->sh_size)); 96 97 for (LIST_TRAVERSE(&(osp->os_isdescs), lnp3, isp)) { 98 Addr addr; 99 100 /* 101 * Although there seems little point in printing 102 * discarded (empty) sections, especially as 103 * diagnostics under -Dsegments,details are more 104 * informative, continue printing them. There 105 * are user scripts, fragile to say the least, 106 * that grep(1) through load-map output to 107 * discover object requirements. These scripts 108 * don't grep for all input sections types (ie. 109 * .picdata), and have become dependent on null 110 * sections (ie. .text) existing in the 111 * load-map output. 112 */ 113 if (isp->is_flags & FLG_IS_DISCARD) { 114 addr = 0; 115 } else { 116 addr = (Addr) 117 _elf_getxoff(isp->is_indata); 118 if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) 119 addr += isp->is_osdesc-> 120 os_shdr->sh_addr; 121 } 122 123 (void) printf(MSG_INTL(MSG_ENT_MAP_ENTRY_2), 124 isp->is_name, EC_ADDR(addr), 125 EC_XWORD(isp->is_shdr->sh_size), 126 ((isp->is_file != NULL) ? 127 (char *)(isp->is_file->ifl_name) : 128 MSG_INTL(MSG_STR_NULL))); 129 } 130 } 131 } 132 133 if (ofl->ofl_flags & FLG_OF_RELOBJ) 134 return; 135 136 /* 137 * Check for any multiply referenced symbols (ie. symbols that have 138 * been overridden from a shared library). 139 */ 140 for (sav = avl_first(&ofl->ofl_symavl); sav; 141 sav = AVL_NEXT(&ofl->ofl_symavl, sav)) { 142 Sym_desc *sdp; 143 const char *name, *ducp, *adcp; 144 List *dfiles; 145 146 sdp = sav->sav_symdesc; 147 name = sdp->sd_name; 148 dfiles = &sdp->sd_aux->sa_dfiles; 149 150 /* 151 * Files that define a symbol are saved on the 152 * `sa_dfiles' list, if the head and tail of 153 * this list differ there must have been more 154 * than one symbol definition. Ignore symbols 155 * that aren't needed, and any special symbols 156 * that the link editor may produce (symbols of 157 * type ABS and COMMON are not recorded in the 158 * first place, however functions like _init() 159 * and _fini() commonly have multiple 160 * occurrances). 161 */ 162 if ((sdp->sd_ref == REF_DYN_SEEN) || 163 (dfiles->head == dfiles->tail) || 164 (sdp->sd_aux && sdp->sd_aux->sa_symspec) || 165 (strcmp(MSG_ORIG(MSG_SYM_FINI_U), name) == 0) || 166 (strcmp(MSG_ORIG(MSG_SYM_INIT_U), name) == 0) || 167 (strcmp(MSG_ORIG(MSG_SYM_LIBVER_U), name) == 0)) 168 continue; 169 170 if (symbol_title) 171 sym_muldef_title(); 172 173 ducp = sdp->sd_file->ifl_name; 174 (void) printf(MSG_INTL(MSG_ENT_MUL_ENTRY_1), demangle(name), 175 ducp); 176 for (LIST_TRAVERSE(dfiles, lnp2, adcp)) { 177 /* 178 * Ignore the referenced symbol. 179 */ 180 if (strcmp(adcp, ducp) != 0) 181 (void) printf(MSG_INTL(MSG_ENT_MUL_ENTRY_2), 182 adcp); 183 } 184 } 185 } 186 187 /* 188 * Traverse the entrance criteria list searching for those sections that haven't 189 * been met and print error message. (only in the case of reordering) 190 */ 191 void 192 ld_ent_check(Ofl_desc * ofl) 193 { 194 Listnode * lnp; 195 Ent_desc * enp; 196 197 /* 198 * Try to give as much information to the user about the specific 199 * line in the mapfile. If the line contains a file name then 200 * output the filename too. Hence we have two warning lines - 201 * one for criterias where a filename is used and the other 202 * for those without a filename. 203 */ 204 for (LIST_TRAVERSE(&ofl->ofl_ents, lnp, enp)) { 205 if ((enp->ec_segment->sg_flags & FLG_SG_ORDER) && 206 !(enp->ec_flags & FLG_EC_USED) && enp->ec_ndx) { 207 Listnode * _lnp = enp->ec_files.head; 208 209 if ((_lnp != NULL) && (_lnp->data != NULL) && 210 (char *)(_lnp->data) != NULL) { 211 eprintf(ofl->ofl_lml, ERR_WARNING, 212 MSG_INTL(MSG_ENT_NOSEC_1), 213 enp->ec_segment->sg_name, enp->ec_name, 214 (const char *)(_lnp->data)); 215 } else { 216 eprintf(ofl->ofl_lml, ERR_WARNING, 217 MSG_INTL(MSG_ENT_NOSEC_2), 218 enp->ec_segment->sg_name, enp->ec_name); 219 } 220 } 221 } 222 } 223