xref: /illumos-gate/usr/src/cmd/sgs/libld/common/ldentry.c (revision ed093b41a93e8563e6e1e5dae0768dda2a7bcc27)
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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
27  */
28 
29 /*
30  * Copyright (c) 2018, Joyent, Inc.
31  */
32 
33 #include	<stdio.h>
34 #include	<string.h>
35 #include	"msg.h"
36 #include	"_libld.h"
37 
38 
39 /*
40  * Print a virtual address map of input and output sections together with
41  * multiple symbol definitions (if they exist).
42  */
43 static Boolean	symbol_title = TRUE;
44 
45 static void
46 sym_muldef_title()
47 {
48 	(void) printf(MSG_INTL(MSG_ENT_MUL_FMT_TIL_0),
49 	    MSG_INTL(MSG_ENT_MUL_TIL_0));
50 	(void) printf(MSG_INTL(MSG_ENT_MUL_FMT_TIL_1),
51 	    MSG_INTL(MSG_ENT_MUL_ITM_SYM),
52 	    MSG_INTL(MSG_ENT_MUL_ITM_DEF_0),
53 	    MSG_INTL(MSG_ENT_MUL_ITM_DEF_1));
54 	symbol_title = FALSE;
55 }
56 
57 void
58 ld_map_out(Ofl_desc *ofl)
59 {
60 	Sg_desc		*sgp;
61 	Is_desc		*isp;
62 	Sym_avlnode	*sav;
63 	Aliste		idx1;
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 (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
87 		Os_desc	*osp;
88 		Aliste	idx2;
89 
90 		if (sgp->sg_phdr.p_type != PT_LOAD)
91 			continue;
92 
93 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
94 			int	os_isdescs_idx;
95 			Aliste	idx3;
96 
97 			(void) printf(MSG_INTL(MSG_ENT_MAP_ENTRY_1),
98 			    osp->os_name, EC_ADDR(osp->os_shdr->sh_addr),
99 			    EC_XWORD(osp->os_shdr->sh_size));
100 
101 			OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx3, isp) {
102 				Addr	addr;
103 
104 				/*
105 				 * Although there seems little point in printing
106 				 * discarded (empty) sections, especially as
107 				 * diagnostics under -Dsegments,details are more
108 				 * informative, continue printing them.  There
109 				 * are user scripts, fragile to say the least,
110 				 * that grep(1) through load-map output to
111 				 * discover object requirements.  These scripts
112 				 * don't grep for all input sections types (ie.
113 				 * .picdata), and have become dependent on null
114 				 * sections (ie. .text) existing in the
115 				 * load-map output.
116 				 */
117 				if (isp->is_flags & FLG_IS_DISCARD) {
118 					addr = 0;
119 				} else {
120 					addr = (Addr)
121 					    _elf_getxoff(isp->is_indata);
122 					if (!(ofl->ofl_flags & FLG_OF_RELOBJ))
123 						addr += isp->is_osdesc->
124 						    os_shdr->sh_addr;
125 				}
126 
127 				(void) printf(MSG_INTL(MSG_ENT_MAP_ENTRY_2),
128 				    isp->is_name, EC_ADDR(addr),
129 				    EC_XWORD(isp->is_shdr->sh_size),
130 				    ((isp->is_file != NULL) ?
131 				    (char *)(isp->is_file->ifl_name) :
132 				    MSG_INTL(MSG_STR_NULL)));
133 			}
134 		}
135 	}
136 
137 	if (ofl->ofl_flags & FLG_OF_RELOBJ)
138 		return;
139 
140 	/*
141 	 * Check for any multiply referenced symbols (ie. symbols that have
142 	 * been overridden from a shared library).
143 	 */
144 	for (sav = avl_first(&ofl->ofl_symavl); sav;
145 	    sav = AVL_NEXT(&ofl->ofl_symavl, sav)) {
146 		Sym_desc	*sdp = sav->sav_sdp;
147 		const char	*name = sdp->sd_name, *ducp, *adcp;
148 		APlist		*dfiles;
149 		Aliste		idx;
150 
151 		if (((dfiles = sdp->sd_aux->sa_dfiles) == NULL) ||
152 		    (aplist_nitems(dfiles) <= 1))
153 			continue;
154 
155 		/*
156 		 * Files that define a symbol are saved on the `sa_dfiles' list.
157 		 * Ignore symbols that aren't needed, and any special symbols
158 		 * that the link editor may produce (symbols of type ABS and
159 		 * COMMON are not recorded in the first place, however functions
160 		 * like _init() and _fini() commonly have multiple occurrences).
161 		 */
162 		if ((sdp->sd_ref == REF_DYN_SEEN) ||
163 		    (sdp->sd_aux->sa_symspec) ||
164 		    (strcmp(MSG_ORIG(MSG_SYM_FINI_U), name) == 0) ||
165 		    (strcmp(MSG_ORIG(MSG_SYM_INIT_U), name) == 0) ||
166 		    (strcmp(MSG_ORIG(MSG_SYM_LIBVER_U), name) == 0))
167 			continue;
168 
169 		if (symbol_title)
170 			sym_muldef_title();
171 
172 		ducp = sdp->sd_file->ifl_name;
173 		(void) printf(MSG_INTL(MSG_ENT_MUL_ENTRY_1), demangle(name),
174 		    ducp);
175 		for (APLIST_TRAVERSE(dfiles, idx, adcp)) {
176 			/*
177 			 * Ignore the referenced symbol.
178 			 */
179 			if (strcmp(adcp, ducp) != 0)
180 				(void) printf(MSG_INTL(MSG_ENT_MUL_ENTRY_2),
181 				    adcp);
182 		}
183 	}
184 }
185 
186 /*
187  * Traverse the entrance criteria list searching for those sections that haven't
188  * been met and print error message.  (only in the case of reordering)
189  */
190 void
191 ld_ent_check(Ofl_desc * ofl)
192 {
193 	Ent_desc	*enp;
194 	Aliste		ndx;
195 
196 	/*
197 	 *  Try to give as much information to the user about the specific
198 	 *  line in the mapfile.  If the line contains a file name then
199 	 *  output the filename too.  Hence we have two warning lines -
200 	 *  one for criterias where a filename is used and the other
201 	 *  for those without a filename.
202 	 */
203 	for (APLIST_TRAVERSE(ofl->ofl_ents, ndx, enp)) {
204 		/*
205 		 * No warning if any of the following hold:
206 		 * -	The segment has no entrance criteria requiring
207 		 *	input section sorting (FLG_SG_IS_ORDER not set).
208 		 * -	The entrance criteria was used to place a section.
209 		 * -	The specific entrance criteria does not require sorting
210 		 */
211 		if (((enp->ec_segment->sg_flags & FLG_SG_IS_ORDER) == 0) ||
212 		    (enp->ec_flags & FLG_EC_USED) || (enp->ec_ordndx == 0))
213 			continue;
214 
215 
216 		if (alist_nitems(enp->ec_files) > 0) {
217 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ENT_NOSEC_1),
218 			    enp->ec_segment->sg_name, enp->ec_is_name);
219 		} else {
220 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ENT_NOSEC_2),
221 			    enp->ec_segment->sg_name, enp->ec_is_name);
222 		}
223 	}
224 }
225