xref: /titanic_41/usr/src/cmd/sgs/libld/common/ldentry.c (revision fd9cb95cbb2f626355a60efb9d02c5f0a33c10e6)
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