xref: /titanic_44/usr/src/cmd/sgs/libld/common/machsym.sparc.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
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) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 #define	ELF_TARGET_SPARC
26 
27 #include	<stdio.h>
28 #include	<string.h>
29 #include	<alloca.h>
30 #include	<sys/types.h>
31 #include	<debug.h>
32 #include	"msg.h"
33 #include	"_libld.h"
34 #include	"machsym.sparc.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
ld_reg_check_sparc(Sym_desc * sdp,Sym * nsym,const char * nname,Ifl_desc * ifl,Ofl_desc * ofl)58 ld_reg_check_sparc(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 			ld_eprintf(ofl, 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 			return (1);
84 		}
85 		return (0);
86 	}
87 
88 	if (osym->st_value == nsym->st_value) {
89 		/*
90 		 * A scratch register and a named register are incompatible.
91 		 * So are two different named registers.
92 		 */
93 		if (((osym->st_name == 0) || (nsym->st_name == 0)) ||
94 		    (strcmp(oname, nname) != 0)) {
95 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_INCOMPREG1),
96 			    conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1),
97 			    sdp->sd_file->ifl_name, demangle(oname),
98 			    ifl->ifl_name, demangle(nname));
99 			return (1);
100 		}
101 
102 		/*
103 		 * A multiply initialized symbol is also illegal.
104 		 */
105 		if ((osym->st_shndx == SHN_ABS) &&
106 		    (nsym->st_shndx == SHN_ABS)) {
107 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_MULTINIREG),
108 			    conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1),
109 			    demangle(nname), sdp->sd_file->ifl_name,
110 			    ifl->ifl_name);
111 			return (1);
112 		}
113 
114 	} else if (strcmp(oname, nname) == 0) {
115 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_INCOMPREG2),
116 		    demangle(sdp->sd_name), sdp->sd_file->ifl_name,
117 		    conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1),
118 		    ifl->ifl_name,
119 		    conv_sym_SPARC_value(nsym->st_value, 0, &inv_buf2));
120 		return (1);
121 	}
122 	return (0);
123 }
124 
125 int
ld_mach_sym_typecheck_sparc(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl)126 ld_mach_sym_typecheck_sparc(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl,
127     Ofl_desc *ofl)
128 {
129 	Conv_inv_buf_t	inv_buf1, inv_buf2;
130 	Sym		*osym = sdp->sd_sym;
131 	Byte		otype = ELF_ST_TYPE(osym->st_info);
132 	Byte		ntype = ELF_ST_TYPE(nsym->st_info);
133 
134 	if (otype != ntype) {
135 		if ((otype == STT_SPARC_REGISTER) ||
136 		    (ntype == STT_SPARC_REGISTER)) {
137 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_DIFFTYPE),
138 			    demangle(sdp->sd_name));
139 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
140 			    sdp->sd_file->ifl_name, conv_sym_info_type(
141 			    sdp->sd_file->ifl_ehdr->e_machine, otype,
142 			    0, &inv_buf1), ifl->ifl_name,
143 			    conv_sym_info_type(ifl->ifl_ehdr->e_machine,
144 			    ntype, 0, &inv_buf2));
145 			return (1);
146 		}
147 	} else if (otype == STT_SPARC_REGISTER)
148 		return (ld_reg_check_sparc(sdp, nsym, sdp->sd_name, ifl, ofl));
149 
150 	return (0);
151 }
152 
153 static const char *registers[] = { 0,
154 	MSG_ORIG(MSG_STO_REGISTERG1),	MSG_ORIG(MSG_STO_REGISTERG2),
155 	MSG_ORIG(MSG_STO_REGISTERG3),	MSG_ORIG(MSG_STO_REGISTERG4),
156 	MSG_ORIG(MSG_STO_REGISTERG5),	MSG_ORIG(MSG_STO_REGISTERG6),
157 	MSG_ORIG(MSG_STO_REGISTERG7)
158 };
159 
160 const char *
ld_is_regsym_sparc(Ofl_desc * ofl,Ifl_desc * ifl,Sym * sym,const char * strs,int symndx,Word shndx,const char * symsecname,sd_flag_t * flags)161 ld_is_regsym_sparc(Ofl_desc *ofl, Ifl_desc *ifl, Sym *sym, const char *strs,
162     int symndx, Word shndx, const char *symsecname, sd_flag_t *flags)
163 {
164 	const char	*name;
165 
166 	/*
167 	 * Only do something if this is a register symbol.
168 	 */
169 	if (ELF_ST_TYPE(sym->st_info) != STT_SPARC_REGISTER)
170 		return (0);
171 
172 	/*
173 	 * Check for bogus register number.
174 	 */
175 	if ((sym->st_value < STO_SPARC_REGISTER_G1) ||
176 	    (sym->st_value > STO_SPARC_REGISTER_G7)) {
177 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_BADREG),
178 		    ifl->ifl_name, symsecname, symndx, EC_XWORD(sym->st_value));
179 		return ((const char *)S_ERROR);
180 	}
181 
182 	/*
183 	 * A register symbol can only be undefined or defined (absolute).
184 	 */
185 	if ((shndx != SHN_ABS) && (shndx != SHN_UNDEF)) {
186 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_BADREG),
187 		    ifl->ifl_name, symsecname, symndx, EC_XWORD(sym->st_value));
188 		return ((const char *)S_ERROR);
189 	}
190 
191 	/*
192 	 * Determine whether this is a scratch (unnamed) definition.
193 	 */
194 	if (sym->st_name == 0) {
195 		/*
196 		 * Check for bogus scratch register definitions.
197 		 */
198 		if ((ELF_ST_BIND(sym->st_info) != STB_GLOBAL) ||
199 		    (shndx != SHN_UNDEF)) {
200 			Conv_inv_buf_t inv_buf;
201 
202 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_BADSCRATCH),
203 			    ifl->ifl_name, symsecname, symndx,
204 			    conv_sym_SPARC_value(sym->st_value, 0, &inv_buf));
205 			return ((const char *)S_ERROR);
206 		}
207 
208 		/*
209 		 * Fabricate a name for this register so that this definition
210 		 * can be processed through the symbol resolution engine.
211 		 */
212 		name = registers[sym->st_value];
213 	} else
214 		name = strs + sym->st_name;
215 
216 	/*
217 	 * Indicate we're dealing with a register and return its name.
218 	 */
219 	*flags |= FLG_SY_REGSYM;
220 	return (name);
221 }
222 
223 Sym_desc *
ld_reg_find_sparc(Sym * sym,Ofl_desc * ofl)224 ld_reg_find_sparc(Sym *sym, Ofl_desc *ofl)
225 {
226 	if (ofl->ofl_regsyms == NULL)
227 		return (NULL);
228 
229 	return (ofl->ofl_regsyms[sym->st_value]);
230 }
231 
232 int
ld_reg_enter_sparc(Sym_desc * sdp,Ofl_desc * ofl)233 ld_reg_enter_sparc(Sym_desc *sdp, Ofl_desc *ofl)
234 {
235 	if (ofl->ofl_regsyms == NULL) {
236 
237 		ofl->ofl_regsymsno = STO_SPARC_REGISTER_G7 + 1;
238 
239 		if ((ofl->ofl_regsyms = libld_calloc(sizeof (Sym_desc *),
240 		    ofl->ofl_regsymsno)) == NULL) {
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