xref: /titanic_44/usr/src/cmd/sgs/libld/common/machsym.sparc.c (revision 15d9d0b528387242011cdcc6190c9e598cfe3a07)
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 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include	<stdio.h>
29 #include	<string.h>
30 #include	<alloca.h>
31 #include	<sys/types.h>
32 #include	<debug.h>
33 #include	"msg.h"
34 #include	"_libld.h"
35 
36 /*
37  * Matrix of legal combinations of usage of a given register:
38  *
39  *	Obj1 \ Obj2      Scratch	Named
40  *	Scratch          OK		NO
41  *	Named            NO		*
42  *
43  * (*) OK if the symbols are identical, NO if they are not.  Two symbols
44  * are identical if and only if one of the following is true:
45  *   A. They are both global and have the same name.
46  *   B. They are both local, have the same name, and are defined in the same
47  *	object.  (Note that a local symbol in one object is never identical to
48  *	a local symbol in another object, even if the name is the same.)
49  *
50  * Matrix of legal combinations of st_shndx for the same register symbol:
51  *
52  *	Obj1 \ Obj2      UNDEF		ABS
53  *	UNDEF            OK		OK
54  *	ABS              OK		NO
55  *
56  */
57 int
58 ld_reg_check(Sym_desc *sdp, Sym *nsym, const char *nname, Ifl_desc *ifl,
59     Ofl_desc * ofl)
60 {
61 	Sym		*osym = sdp->sd_sym;
62 	const char	*oname = sdp->sd_name;
63 	Conv_inv_buf_t	inv_buf1, inv_buf2;
64 
65 	/*
66 	 * Scratch register definitions are compatible.
67 	 */
68 	if ((osym->st_name == 0) && (nsym->st_name == 0))
69 		return (0);
70 
71 	/*
72 	 * A local and a global, or another local is incompatible.
73 	 */
74 	if ((ELF_ST_BIND(osym->st_info) == STB_LOCAL) ||
75 	    (ELF_ST_BIND(nsym->st_info) == STB_LOCAL)) {
76 		if (osym->st_value == nsym->st_value) {
77 
78 			eprintf(ofl->ofl_lml, ERR_FATAL,
79 			    MSG_INTL(MSG_SYM_INCOMPREG3),
80 			    conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1),
81 			    sdp->sd_file->ifl_name, demangle(oname),
82 			    ifl->ifl_name, demangle(nname));
83 			ofl->ofl_flags |= FLG_OF_FATAL;
84 			return (1);
85 		}
86 		return (0);
87 	}
88 
89 	if (osym->st_value == nsym->st_value) {
90 		/*
91 		 * A scratch register and a named register are incompatible.
92 		 * So are two different named registers.
93 		 */
94 		if (((osym->st_name == 0) || (nsym->st_name == 0)) ||
95 		    (strcmp(oname, nname) != 0)) {
96 			eprintf(ofl->ofl_lml, ERR_FATAL,
97 			    MSG_INTL(MSG_SYM_INCOMPREG1),
98 			    conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1),
99 			    sdp->sd_file->ifl_name, demangle(oname),
100 			    ifl->ifl_name, demangle(nname));
101 			ofl->ofl_flags |= FLG_OF_FATAL;
102 			return (1);
103 		}
104 
105 		/*
106 		 * A multiply initialized symbol is also illegal.
107 		 */
108 		if ((osym->st_shndx == SHN_ABS) &&
109 		    (nsym->st_shndx == SHN_ABS)) {
110 			eprintf(ofl->ofl_lml, ERR_FATAL,
111 			    MSG_INTL(MSG_SYM_MULTINIREG),
112 			    conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1),
113 			    demangle(nname), sdp->sd_file->ifl_name,
114 			    ifl->ifl_name);
115 			ofl->ofl_flags |= FLG_OF_FATAL;
116 			return (1);
117 		}
118 
119 	} else if (strcmp(oname, nname) == 0) {
120 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYM_INCOMPREG2),
121 		    demangle(sdp->sd_name), sdp->sd_file->ifl_name,
122 		    conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1),
123 		    ifl->ifl_name,
124 		    conv_sym_SPARC_value(nsym->st_value, 0, &inv_buf2));
125 		ofl->ofl_flags |= FLG_OF_FATAL;
126 		return (1);
127 	}
128 	return (0);
129 }
130 
131 int
132 ld_mach_sym_typecheck(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl)
133 {
134 	Conv_inv_buf_t	inv_buf1, inv_buf2;
135 	Sym		*osym = sdp->sd_sym;
136 	Byte		otype = ELF_ST_TYPE(osym->st_info);
137 	Byte		ntype = ELF_ST_TYPE(nsym->st_info);
138 
139 	if (otype != ntype) {
140 		if ((otype == STT_SPARC_REGISTER) ||
141 		    (ntype == STT_SPARC_REGISTER)) {
142 			eprintf(ofl->ofl_lml, ERR_FATAL,
143 			    MSG_INTL(MSG_SYM_DIFFTYPE), demangle(sdp->sd_name));
144 			eprintf(ofl->ofl_lml, ERR_NONE,
145 			    MSG_INTL(MSG_SYM_FILETYPES),
146 			    sdp->sd_file->ifl_name, conv_sym_info_type(
147 			    sdp->sd_file->ifl_ehdr->e_machine, otype,
148 			    0, &inv_buf1), ifl->ifl_name,
149 			    conv_sym_info_type(ifl->ifl_ehdr->e_machine,
150 			    ntype, 0, &inv_buf2));
151 			ofl->ofl_flags |= FLG_OF_FATAL;
152 			return (1);
153 		}
154 	} else if (otype == STT_SPARC_REGISTER)
155 		return (ld_reg_check(sdp, nsym, sdp->sd_name, ifl, ofl));
156 
157 	return (0);
158 }
159 
160 static const char *registers[] = { 0,
161 	MSG_ORIG(MSG_STO_REGISTERG1),	MSG_ORIG(MSG_STO_REGISTERG2),
162 	MSG_ORIG(MSG_STO_REGISTERG3),	MSG_ORIG(MSG_STO_REGISTERG4),
163 	MSG_ORIG(MSG_STO_REGISTERG5),	MSG_ORIG(MSG_STO_REGISTERG6),
164 	MSG_ORIG(MSG_STO_REGISTERG7)
165 };
166 
167 const char *
168 ld_is_regsym(Ofl_desc *ofl, Ifl_desc *ifl, Sym *sym, const char *strs,
169     int symndx, Word shndx, const char *symsecname, Word * flags)
170 {
171 	const char	*name;
172 
173 	/*
174 	 * Only do something if this is a register symbol.
175 	 */
176 	if (ELF_ST_TYPE(sym->st_info) != STT_SPARC_REGISTER)
177 		return (0);
178 
179 	/*
180 	 * Check for bogus register number.
181 	 */
182 	if ((sym->st_value < STO_SPARC_REGISTER_G1) ||
183 	    (sym->st_value > STO_SPARC_REGISTER_G7)) {
184 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYM_BADREG),
185 		    ifl->ifl_name, symsecname, symndx, EC_XWORD(sym->st_value));
186 		return ((const char *)S_ERROR);
187 	}
188 
189 	/*
190 	 * A register symbol can only be undefined or defined (absolute).
191 	 */
192 	if ((shndx != SHN_ABS) && (shndx != SHN_UNDEF)) {
193 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYM_BADREG),
194 		    ifl->ifl_name, symsecname, symndx, EC_XWORD(sym->st_value));
195 		return ((const char *)S_ERROR);
196 	}
197 
198 	/*
199 	 * Determine whether this is a scratch (unnamed) definition.
200 	 */
201 	if (sym->st_name == 0) {
202 		/*
203 		 * Check for bogus scratch register definitions.
204 		 */
205 		if ((ELF_ST_BIND(sym->st_info) != STB_GLOBAL) ||
206 		    (shndx != SHN_UNDEF)) {
207 			Conv_inv_buf_t inv_buf;
208 
209 			eprintf(ofl->ofl_lml, ERR_FATAL,
210 			    MSG_INTL(MSG_SYM_BADSCRATCH),
211 			    ifl->ifl_name, symsecname, symndx,
212 			    conv_sym_SPARC_value(sym->st_value, 0, &inv_buf));
213 			return ((const char *)S_ERROR);
214 		}
215 
216 		/*
217 		 * Fabricate a name for this register so that this definition
218 		 * can be processed through the symbol resolution engine.
219 		 */
220 		name = registers[sym->st_value];
221 	} else
222 		name = strs + sym->st_name;
223 
224 	/*
225 	 * Indicate we're dealing with a register and return its name.
226 	 */
227 	*flags |= FLG_SY_REGSYM;
228 	return (name);
229 }
230 
231 Sym_desc *
232 ld_reg_find(Sym * sym, Ofl_desc * ofl)
233 {
234 	if (ofl->ofl_regsyms == 0)
235 		return (0);
236 
237 	return (ofl->ofl_regsyms[sym->st_value]);
238 }
239 
240 int
241 ld_reg_enter(Sym_desc * sdp, Ofl_desc * ofl)
242 {
243 	if (ofl->ofl_regsyms == 0) {
244 		ofl->ofl_regsymsno = STO_SPARC_REGISTER_G7 + 1;
245 		if ((ofl->ofl_regsyms = libld_calloc(sizeof (Sym_desc *),
246 		    ofl->ofl_regsymsno)) == 0) {
247 			ofl->ofl_flags |= FLG_OF_FATAL;
248 			return (0);
249 		}
250 	}
251 
252 	ofl->ofl_regsyms[sdp->sd_sym->st_value] = sdp;
253 	return (1);
254 }
255