xref: /titanic_44/usr/src/cmd/sgs/libld/common/ldentry.c (revision 0a1ad920531b37f01f4aa8084737026621c76bdb)
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 2009 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 #include	<stdio.h>
31 #include	<string.h>
32 #include	"msg.h"
33 #include	"_libld.h"
34 
35 
36 /*
37  * Print a virtual address map of input and output sections together with
38  * multiple symbol definitions (if they exist).
39  */
40 static Boolean	symbol_title = TRUE;
41 
42 static void
43 sym_muldef_title()
44 {
45 	(void) printf(MSG_INTL(MSG_ENT_MUL_FMT_TIL_0),
46 	    MSG_INTL(MSG_ENT_MUL_TIL_0));
47 	(void) printf(MSG_INTL(MSG_ENT_MUL_FMT_TIL_1),
48 	    MSG_INTL(MSG_ENT_MUL_ITM_SYM),
49 	    MSG_INTL(MSG_ENT_MUL_ITM_DEF_0),
50 	    MSG_INTL(MSG_ENT_MUL_ITM_DEF_1));
51 	symbol_title = FALSE;
52 }
53 
54 void
55 ld_map_out(Ofl_desc *ofl)
56 {
57 	Sg_desc		*sgp;
58 	Is_desc		*isp;
59 	Sym_avlnode	*sav;
60 	Aliste		idx1;
61 
62 	(void) printf(MSG_INTL(MSG_ENT_MAP_FMT_TIL_1),
63 	    MSG_INTL(MSG_ENT_MAP_TITLE_1));
64 	if (ofl->ofl_flags & FLG_OF_RELOBJ)
65 		(void) printf(MSG_INTL(MSG_ENT_MAP_FMT_TIL_2),
66 		    MSG_INTL(MSG_ENT_ITM_OUTPUT),
67 		    MSG_INTL(MSG_ENT_ITM_INPUT),
68 		    MSG_INTL(MSG_ENT_ITM_NEW),
69 		    MSG_INTL(MSG_ENT_ITM_SECTION),
70 		    MSG_INTL(MSG_ENT_ITM_SECTION),
71 		    MSG_INTL(MSG_ENT_ITM_DISPMNT),
72 		    MSG_INTL(MSG_ENT_ITM_SIZE));
73 	else
74 		(void) printf(MSG_INTL(MSG_ENT_MAP_FMT_TIL_3),
75 		    MSG_INTL(MSG_ENT_ITM_OUTPUT),
76 		    MSG_INTL(MSG_ENT_ITM_INPUT),
77 		    MSG_INTL(MSG_ENT_ITM_VIRTUAL),
78 		    MSG_INTL(MSG_ENT_ITM_SECTION),
79 		    MSG_INTL(MSG_ENT_ITM_SECTION),
80 		    MSG_INTL(MSG_ENT_ITM_ADDRESS),
81 		    MSG_INTL(MSG_ENT_ITM_SIZE));
82 
83 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
84 		Os_desc	*osp;
85 		Aliste	idx2;
86 
87 		if (sgp->sg_phdr.p_type != PT_LOAD)
88 			continue;
89 
90 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
91 			Aliste	idx3;
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 (APLIST_TRAVERSE(osp->os_isdescs, idx3, 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 = sav->sav_symdesc;
143 		const char	*name = sdp->sd_name, *ducp, *adcp;
144 		APlist		*dfiles;
145 		Aliste		idx;
146 
147 		if (((dfiles = sdp->sd_aux->sa_dfiles) == NULL) ||
148 		    (aplist_nitems(dfiles) == 1))
149 			continue;
150 
151 		/*
152 		 * Files that define a symbol are saved on the `sa_dfiles' list.
153 		 * Ignore symbols that aren't needed, and any special symbols
154 		 * that the link editor may produce (symbols of type ABS and
155 		 * COMMON are not recorded in the first place, however functions
156 		 * like _init() and _fini() commonly have multiple occurrences).
157 		 */
158 		if ((sdp->sd_ref == REF_DYN_SEEN) ||
159 		    (sdp->sd_aux && sdp->sd_aux->sa_symspec) ||
160 		    (strcmp(MSG_ORIG(MSG_SYM_FINI_U), name) == 0) ||
161 		    (strcmp(MSG_ORIG(MSG_SYM_INIT_U), name) == 0) ||
162 		    (strcmp(MSG_ORIG(MSG_SYM_LIBVER_U), name) == 0))
163 			continue;
164 
165 		if (symbol_title)
166 			sym_muldef_title();
167 
168 		ducp = sdp->sd_file->ifl_name;
169 		(void) printf(MSG_INTL(MSG_ENT_MUL_ENTRY_1), demangle(name),
170 		    ducp);
171 		for (APLIST_TRAVERSE(dfiles, idx, adcp)) {
172 			/*
173 			 * Ignore the referenced symbol.
174 			 */
175 			if (strcmp(adcp, ducp) != 0)
176 				(void) printf(MSG_INTL(MSG_ENT_MUL_ENTRY_2),
177 				    adcp);
178 		}
179 	}
180 }
181 
182 /*
183  * Traverse the entrance criteria list searching for those sections that haven't
184  * been met and print error message.  (only in the case of reordering)
185  */
186 void
187 ld_ent_check(Ofl_desc * ofl)
188 {
189 	Ent_desc	*enp;
190 	Aliste		ndx;
191 
192 	/*
193 	 *  Try to give as much information to the user about the specific
194 	 *  line in the mapfile.  If the line contains a file name then
195 	 *  output the filename too.  Hence we have two warning lines -
196 	 *  one for criterias where a filename is used and the other
197 	 *  for those without a filename.
198 	 */
199 	for (ALIST_TRAVERSE(ofl->ofl_ents, ndx, enp)) {
200 		const char	*file;
201 
202 		if (((enp->ec_segment->sg_flags & FLG_SG_ORDER) == 0) ||
203 		    (enp->ec_flags & FLG_EC_USED) || (enp->ec_ordndx == 0))
204 			continue;
205 
206 
207 		if (enp->ec_files &&
208 		    ((file = enp->ec_files->apl_data[0]) != NULL)) {
209 			eprintf(ofl->ofl_lml, ERR_WARNING,
210 			    MSG_INTL(MSG_ENT_NOSEC_1), enp->ec_segment->sg_name,
211 			    enp->ec_name, file);
212 		} else {
213 			eprintf(ofl->ofl_lml, ERR_WARNING,
214 			    MSG_INTL(MSG_ENT_NOSEC_2), enp->ec_segment->sg_name,
215 			    enp->ec_name);
216 		}
217 	}
218 }
219