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