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