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.
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.
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]
23 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
29 #include <sys/elf_SPARC.h>
38 * Matrix of legal combinations of usage of a given register:
40 * Obj1\Obj2 Scratch Named
44 * * OK if the symbols are identical, NO if they are not. Two symbols
45 * are identical if and only if one of the following is true:
46 * A. They are both global and have the same name.
47 * B. They are both local, have the same name, and are defined in
48 * the same object. (Note that a local symbol in one object is
49 * never identical to a local symbol in another object, even if the
52 * Matrix of legal combinations of st_shndx for the same register symbol:
60 * Test the compatiblity of two register symbols, 0 pass, >0 fail
63 check_regsyms(Sym
*sym1
, const char *name1
, Sym
*sym2
, const char *name2
)
65 if ((sym1
->st_name
== 0) && (sym2
->st_name
== 0))
66 return (0); /* scratches are always compatible */
68 if ((ELF_ST_BIND(sym1
->st_info
) == STB_LOCAL
) ||
69 (ELF_ST_BIND(sym2
->st_info
) == STB_LOCAL
)) {
70 if (sym1
->st_value
== sym2
->st_value
)
71 return (1); /* local symbol incompat */
72 return (0); /* no other prob from locals */
75 if (sym1
->st_value
== sym2
->st_value
) {
76 /* NOTE this just avoids strcmp */
77 if ((sym1
->st_name
== 0) || (sym2
->st_name
== 0))
78 return (2); /* can't match scratch to named */
80 if (strcmp(name1
, name2
) != 0)
81 return (4); /* diff name, same register value */
83 if ((sym1
->st_shndx
== SHN_ABS
) && (sym2
->st_shndx
== SHN_ABS
))
84 return (3); /* multiply defined */
85 } else if (strcmp(name1
, name2
) == 0)
86 return (5); /* same name, diff register value */
92 elf_regsyms(Rt_map
*lmp
)
100 * Scan through the .dynamic section of this object looking for all
101 * DT_REGISTER entries. For each DT_REGISTER entry found identify the
102 * register symbol it identifies and confirm that it doesn't conflict
103 * with any other register symbols.
105 for (dyn
= DYN(lmp
), dip
= DYNINFO(lmp
);
106 !(dip
->di_flags
& FLG_DI_IGNORE
); dyn
++, dip
++) {
109 if ((dip
->di_flags
& FLG_DI_REGISTER
) == 0)
113 * Get the local symbol table entry.
115 rsymndx
= dyn
->d_un
.d_val
;
116 symdef
= (Sym
*)((unsigned long)SYMTAB(lmp
) +
117 (rsymndx
* SYMENT(lmp
)));
119 for (rp
= reglist
; rp
; rp
= rp
->rl_next
) {
120 Conv_inv_buf_t inv_buf
;
121 const char *str
, *sym1
, *sym2
;
123 if (rp
->rl_sym
== symdef
) {
125 * Same symbol definition - everything is a-ok.
130 sym1
= (STRTAB(rp
->rl_lmp
) + rp
->rl_sym
->st_name
);
131 sym2
= (STRTAB(lmp
) + symdef
->st_name
);
133 if (check_regsyms(rp
->rl_sym
, sym1
, symdef
, sym2
) == 0)
136 if ((str
= demangle(sym1
)) != sym1
) {
137 char *_str
= alloca(strlen(str
) + 1);
138 (void) strcpy(_str
, str
);
139 sym1
= (const char *)_str
;
141 sym2
= demangle(sym2
);
143 if (LIST(lmp
)->lm_flags
& LML_FLG_TRC_WARN
) {
144 (void) printf(MSG_INTL(MSG_LDD_REG_SYMCONF
),
145 conv_sym_SPARC_value(symdef
->st_value
,
146 0, &inv_buf
), NAME(rp
->rl_lmp
),
147 sym1
, NAME(lmp
), sym2
);
149 eprintf(LIST(lmp
), ERR_FATAL
,
150 MSG_INTL(MSG_REG_SYMCONF
),
151 conv_sym_SPARC_value(symdef
->st_value
,
152 0, &inv_buf
), NAME(rp
->rl_lmp
),
153 sym1
, NAME(lmp
), sym2
);
157 if ((rp
= calloc(sizeof (Reglist
), 1)) == NULL
)
161 rp
->rl_next
= reglist
;