xref: /illumos-gate/usr/src/cmd/sgs/libld/common/machsym.sparc.c (revision bcd524b5c10222cf2a1ef37ac7ea8bf1baa3a2ee)
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 2006 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 
64 	/*
65 	 * Scratch register definitions are compatible.
66 	 */
67 	if ((osym->st_name == 0) && (nsym->st_name == 0))
68 		return (0);
69 
70 	/*
71 	 * A local and a global, or another local is incompatible.
72 	 */
73 	if ((ELF_ST_BIND(osym->st_info) == STB_LOCAL) ||
74 	    (ELF_ST_BIND(nsym->st_info) == STB_LOCAL)) {
75 		if (osym->st_value == nsym->st_value) {
76 			eprintf(ofl->ofl_lml, ERR_FATAL,
77 			    MSG_INTL(MSG_SYM_INCOMPREG3),
78 			    conv_sym_SPARC_value(osym->st_value, 0),
79 			    sdp->sd_file->ifl_name, demangle(oname),
80 			    ifl->ifl_name, demangle(nname));
81 			ofl->ofl_flags |= FLG_OF_FATAL;
82 			return (1);
83 		}
84 		return (0);
85 	}
86 
87 	if (osym->st_value == nsym->st_value) {
88 		/*
89 		 * A scratch register and a named register are incompatible.
90 		 * So are two different named registers.
91 		 */
92 		if (((osym->st_name == 0) || (nsym->st_name == 0)) ||
93 		    (strcmp(oname, nname) != 0)) {
94 			eprintf(ofl->ofl_lml, ERR_FATAL,
95 			    MSG_INTL(MSG_SYM_INCOMPREG1),
96 			    conv_sym_SPARC_value(osym->st_value, 0),
97 			    sdp->sd_file->ifl_name, demangle(oname),
98 			    ifl->ifl_name, demangle(nname));
99 			ofl->ofl_flags |= FLG_OF_FATAL;
100 			return (1);
101 		}
102 
103 		/*
104 		 * A multiply initialized symbol is also illegal.
105 		 */
106 		if ((osym->st_shndx == SHN_ABS) &&
107 		    (nsym->st_shndx == SHN_ABS)) {
108 			eprintf(ofl->ofl_lml, ERR_FATAL,
109 			    MSG_INTL(MSG_SYM_MULTINIREG),
110 			    conv_sym_SPARC_value(osym->st_value, 0),
111 			    demangle(nname), sdp->sd_file->ifl_name,
112 			    ifl->ifl_name);
113 			ofl->ofl_flags |= FLG_OF_FATAL;
114 			return (1);
115 		}
116 
117 	} else if (strcmp(oname, nname) == 0) {
118 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYM_INCOMPREG2),
119 		    demangle(sdp->sd_name), sdp->sd_file->ifl_name,
120 		    conv_sym_SPARC_value(osym->st_value, 0), ifl->ifl_name,
121 		    conv_sym_SPARC_value(nsym->st_value, 0));
122 		ofl->ofl_flags |= FLG_OF_FATAL;
123 		return (1);
124 	}
125 	return (0);
126 }
127 
128 int
129 ld_mach_sym_typecheck(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl)
130 {
131 	Sym	*osym = sdp->sd_sym;
132 	Byte	otype = ELF_ST_TYPE(osym->st_info);
133 	Byte	ntype = ELF_ST_TYPE(nsym->st_info);
134 
135 	if (otype != ntype) {
136 		if ((otype == STT_SPARC_REGISTER) ||
137 		    (ntype == STT_SPARC_REGISTER)) {
138 			eprintf(ofl->ofl_lml, ERR_FATAL,
139 			    MSG_INTL(MSG_SYM_DIFFTYPE), demangle(sdp->sd_name));
140 			eprintf(ofl->ofl_lml, ERR_NONE,
141 			    MSG_INTL(MSG_SYM_FILETYPES),
142 			    sdp->sd_file->ifl_name, conv_sym_info_type(
143 			    sdp->sd_file->ifl_ehdr->e_machine, otype, 0),
144 			    ifl->ifl_name,
145 			    conv_sym_info_type(ifl->ifl_ehdr->e_machine,
146 			    ntype, 0));
147 			ofl->ofl_flags |= FLG_OF_FATAL;
148 			return (1);
149 		}
150 	} else if (otype == STT_SPARC_REGISTER)
151 		return (ld_reg_check(sdp, nsym, sdp->sd_name, ifl, ofl));
152 
153 	return (0);
154 }
155 
156 static const char *registers[] = { 0,
157 	MSG_ORIG(MSG_STO_REGISTERG1),	MSG_ORIG(MSG_STO_REGISTERG2),
158 	MSG_ORIG(MSG_STO_REGISTERG3),	MSG_ORIG(MSG_STO_REGISTERG4),
159 	MSG_ORIG(MSG_STO_REGISTERG5),	MSG_ORIG(MSG_STO_REGISTERG6),
160 	MSG_ORIG(MSG_STO_REGISTERG7)
161 };
162 
163 const char *
164 ld_is_regsym(Ofl_desc *ofl, Ifl_desc *ifl, Sym *sym, const char *strs,
165     int symndx, Word shndx, const char *symsecname, Word * flags)
166 {
167 	const char	*name;
168 
169 	/*
170 	 * Only do something if this is a register symbol.
171 	 */
172 	if (ELF_ST_TYPE(sym->st_info) != STT_SPARC_REGISTER)
173 		return (0);
174 
175 	/*
176 	 * Check for bogus register number.
177 	 */
178 	if ((sym->st_value < STO_SPARC_REGISTER_G1) ||
179 	    (sym->st_value > STO_SPARC_REGISTER_G7)) {
180 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYM_BADREG),
181 		    ifl->ifl_name, symsecname, symndx, EC_XWORD(sym->st_value));
182 		return ((const char *)S_ERROR);
183 	}
184 
185 	/*
186 	 * A register symbol can only be undefined or defined (absolute).
187 	 */
188 	if ((shndx != SHN_ABS) && (shndx != SHN_UNDEF)) {
189 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYM_BADREG),
190 		    ifl->ifl_name, symsecname, symndx, EC_XWORD(sym->st_value));
191 		return ((const char *)S_ERROR);
192 	}
193 
194 	/*
195 	 * Determine whether this is a scratch (unnamed) definition.
196 	 */
197 	if (sym->st_name == 0) {
198 		/*
199 		 * Check for bogus scratch register definitions.
200 		 */
201 		if ((ELF_ST_BIND(sym->st_info) != STB_GLOBAL) ||
202 		    (shndx != SHN_UNDEF)) {
203 			eprintf(ofl->ofl_lml, ERR_FATAL,
204 			    MSG_INTL(MSG_SYM_BADSCRATCH),
205 			    ifl->ifl_name, symsecname, symndx,
206 			    conv_sym_SPARC_value(sym->st_value, 0));
207 			return ((const char *)S_ERROR);
208 		}
209 
210 		/*
211 		 * Fabricate a name for this register so that this definition
212 		 * can be processed through the symbol resolution engine.
213 		 */
214 		name = registers[sym->st_value];
215 	} else
216 		name = strs + sym->st_name;
217 
218 	/*
219 	 * Indicate we're dealing with a register and return its name.
220 	 */
221 	*flags |= FLG_SY_REGSYM;
222 	return (name);
223 }
224 
225 Sym_desc *
226 ld_reg_find(Sym * sym, Ofl_desc * ofl)
227 {
228 	if (ofl->ofl_regsyms == 0)
229 		return (0);
230 
231 	return (ofl->ofl_regsyms[sym->st_value]);
232 }
233 
234 int
235 ld_reg_enter(Sym_desc * sdp, Ofl_desc * ofl)
236 {
237 	if (ofl->ofl_regsyms == 0) {
238 		ofl->ofl_regsymsno = STO_SPARC_REGISTER_G7 + 1;
239 		if ((ofl->ofl_regsyms = libld_calloc(sizeof (Sym_desc *),
240 		    ofl->ofl_regsymsno)) == 0) {
241 			ofl->ofl_flags |= FLG_OF_FATAL;
242 			return (0);
243 		}
244 	}
245 
246 	ofl->ofl_regsyms[sdp->sd_sym->st_value] = sdp;
247 	return (1);
248 }
249