17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 23*1007fd6fSAli Bahrami * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 25ba2be530Sab #define ELF_TARGET_SPARC 26ba2be530Sab 277c478bd9Sstevel@tonic-gate #include <stdio.h> 287c478bd9Sstevel@tonic-gate #include <string.h> 297c478bd9Sstevel@tonic-gate #include <alloca.h> 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 315aefb655Srie #include <debug.h> 327c478bd9Sstevel@tonic-gate #include "msg.h" 337c478bd9Sstevel@tonic-gate #include "_libld.h" 34ba2be530Sab #include "machsym.sparc.h" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate /* 377c478bd9Sstevel@tonic-gate * Matrix of legal combinations of usage of a given register: 387c478bd9Sstevel@tonic-gate * 397c478bd9Sstevel@tonic-gate * Obj1 \ Obj2 Scratch Named 407c478bd9Sstevel@tonic-gate * Scratch OK NO 417c478bd9Sstevel@tonic-gate * Named NO * 427c478bd9Sstevel@tonic-gate * 437c478bd9Sstevel@tonic-gate * (*) OK if the symbols are identical, NO if they are not. Two symbols 447c478bd9Sstevel@tonic-gate * are identical if and only if one of the following is true: 457c478bd9Sstevel@tonic-gate * A. They are both global and have the same name. 467c478bd9Sstevel@tonic-gate * B. They are both local, have the same name, and are defined in the same 477c478bd9Sstevel@tonic-gate * object. (Note that a local symbol in one object is never identical to 487c478bd9Sstevel@tonic-gate * a local symbol in another object, even if the name is the same.) 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * Matrix of legal combinations of st_shndx for the same register symbol: 517c478bd9Sstevel@tonic-gate * 527c478bd9Sstevel@tonic-gate * Obj1 \ Obj2 UNDEF ABS 537c478bd9Sstevel@tonic-gate * UNDEF OK OK 547c478bd9Sstevel@tonic-gate * ABS OK NO 557c478bd9Sstevel@tonic-gate * 567c478bd9Sstevel@tonic-gate */ 577c478bd9Sstevel@tonic-gate int 58ba2be530Sab ld_reg_check_sparc(Sym_desc *sdp, Sym *nsym, const char *nname, Ifl_desc *ifl, 59635216b6SRod Evans Ofl_desc *ofl) 607c478bd9Sstevel@tonic-gate { 617c478bd9Sstevel@tonic-gate Sym *osym = sdp->sd_sym; 627c478bd9Sstevel@tonic-gate const char *oname = sdp->sd_name; 63de777a60Sab Conv_inv_buf_t inv_buf1, inv_buf2; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* 667c478bd9Sstevel@tonic-gate * Scratch register definitions are compatible. 677c478bd9Sstevel@tonic-gate */ 687c478bd9Sstevel@tonic-gate if ((osym->st_name == 0) && (nsym->st_name == 0)) 697c478bd9Sstevel@tonic-gate return (0); 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /* 727c478bd9Sstevel@tonic-gate * A local and a global, or another local is incompatible. 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate if ((ELF_ST_BIND(osym->st_info) == STB_LOCAL) || 757c478bd9Sstevel@tonic-gate (ELF_ST_BIND(nsym->st_info) == STB_LOCAL)) { 767c478bd9Sstevel@tonic-gate if (osym->st_value == nsym->st_value) { 77de777a60Sab 78*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, 795aefb655Srie MSG_INTL(MSG_SYM_INCOMPREG3), 80de777a60Sab conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1), 817c478bd9Sstevel@tonic-gate sdp->sd_file->ifl_name, demangle(oname), 827c478bd9Sstevel@tonic-gate ifl->ifl_name, demangle(nname)); 837c478bd9Sstevel@tonic-gate return (1); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate return (0); 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate if (osym->st_value == nsym->st_value) { 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * A scratch register and a named register are incompatible. 917c478bd9Sstevel@tonic-gate * So are two different named registers. 927c478bd9Sstevel@tonic-gate */ 937c478bd9Sstevel@tonic-gate if (((osym->st_name == 0) || (nsym->st_name == 0)) || 947c478bd9Sstevel@tonic-gate (strcmp(oname, nname) != 0)) { 95*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_INCOMPREG1), 96de777a60Sab conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1), 977c478bd9Sstevel@tonic-gate sdp->sd_file->ifl_name, demangle(oname), 987c478bd9Sstevel@tonic-gate ifl->ifl_name, demangle(nname)); 997c478bd9Sstevel@tonic-gate return (1); 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate /* 1037c478bd9Sstevel@tonic-gate * A multiply initialized symbol is also illegal. 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate if ((osym->st_shndx == SHN_ABS) && 1067c478bd9Sstevel@tonic-gate (nsym->st_shndx == SHN_ABS)) { 107*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_MULTINIREG), 108de777a60Sab conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1), 1097c478bd9Sstevel@tonic-gate demangle(nname), sdp->sd_file->ifl_name, 1107c478bd9Sstevel@tonic-gate ifl->ifl_name); 1117c478bd9Sstevel@tonic-gate return (1); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate } else if (strcmp(oname, nname) == 0) { 115*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_INCOMPREG2), 1167c478bd9Sstevel@tonic-gate demangle(sdp->sd_name), sdp->sd_file->ifl_name, 117de777a60Sab conv_sym_SPARC_value(osym->st_value, 0, &inv_buf1), 118de777a60Sab ifl->ifl_name, 119de777a60Sab conv_sym_SPARC_value(nsym->st_value, 0, &inv_buf2)); 1207c478bd9Sstevel@tonic-gate return (1); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate return (0); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate int 126ba2be530Sab ld_mach_sym_typecheck_sparc(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, 127ba2be530Sab Ofl_desc *ofl) 1287c478bd9Sstevel@tonic-gate { 129de777a60Sab Conv_inv_buf_t inv_buf1, inv_buf2; 130de777a60Sab Sym *osym = sdp->sd_sym; 131de777a60Sab Byte otype = ELF_ST_TYPE(osym->st_info); 132de777a60Sab Byte ntype = ELF_ST_TYPE(nsym->st_info); 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate if (otype != ntype) { 1357c478bd9Sstevel@tonic-gate if ((otype == STT_SPARC_REGISTER) || 1367c478bd9Sstevel@tonic-gate (ntype == STT_SPARC_REGISTER)) { 137*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_DIFFTYPE), 138*1007fd6fSAli Bahrami demangle(sdp->sd_name)); 139*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES), 1405aefb655Srie sdp->sd_file->ifl_name, conv_sym_info_type( 141de777a60Sab sdp->sd_file->ifl_ehdr->e_machine, otype, 142de777a60Sab 0, &inv_buf1), ifl->ifl_name, 1435aefb655Srie conv_sym_info_type(ifl->ifl_ehdr->e_machine, 144de777a60Sab ntype, 0, &inv_buf2)); 1457c478bd9Sstevel@tonic-gate return (1); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate } else if (otype == STT_SPARC_REGISTER) 148ba2be530Sab return (ld_reg_check_sparc(sdp, nsym, sdp->sd_name, ifl, ofl)); 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate return (0); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate static const char *registers[] = { 0, 1547c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_STO_REGISTERG1), MSG_ORIG(MSG_STO_REGISTERG2), 1557c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_STO_REGISTERG3), MSG_ORIG(MSG_STO_REGISTERG4), 1567c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_STO_REGISTERG5), MSG_ORIG(MSG_STO_REGISTERG6), 1577c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_STO_REGISTERG7) 1587c478bd9Sstevel@tonic-gate }; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate const char * 161ba2be530Sab ld_is_regsym_sparc(Ofl_desc *ofl, Ifl_desc *ifl, Sym *sym, const char *strs, 162635216b6SRod Evans int symndx, Word shndx, const char *symsecname, sd_flag_t *flags) 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate const char *name; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate /* 1677c478bd9Sstevel@tonic-gate * Only do something if this is a register symbol. 1687c478bd9Sstevel@tonic-gate */ 1697c478bd9Sstevel@tonic-gate if (ELF_ST_TYPE(sym->st_info) != STT_SPARC_REGISTER) 1707c478bd9Sstevel@tonic-gate return (0); 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * Check for bogus register number. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate if ((sym->st_value < STO_SPARC_REGISTER_G1) || 1767c478bd9Sstevel@tonic-gate (sym->st_value > STO_SPARC_REGISTER_G7)) { 177*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_BADREG), 1785aefb655Srie ifl->ifl_name, symsecname, symndx, EC_XWORD(sym->st_value)); 1797c478bd9Sstevel@tonic-gate return ((const char *)S_ERROR); 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * A register symbol can only be undefined or defined (absolute). 1847c478bd9Sstevel@tonic-gate */ 1857c478bd9Sstevel@tonic-gate if ((shndx != SHN_ABS) && (shndx != SHN_UNDEF)) { 186*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_BADREG), 1875aefb655Srie ifl->ifl_name, symsecname, symndx, EC_XWORD(sym->st_value)); 1887c478bd9Sstevel@tonic-gate return ((const char *)S_ERROR); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * Determine whether this is a scratch (unnamed) definition. 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate if (sym->st_name == 0) { 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * Check for bogus scratch register definitions. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate if ((ELF_ST_BIND(sym->st_info) != STB_GLOBAL) || 1997c478bd9Sstevel@tonic-gate (shndx != SHN_UNDEF)) { 200de777a60Sab Conv_inv_buf_t inv_buf; 201de777a60Sab 202*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_BADSCRATCH), 2037c478bd9Sstevel@tonic-gate ifl->ifl_name, symsecname, symndx, 204de777a60Sab conv_sym_SPARC_value(sym->st_value, 0, &inv_buf)); 2057c478bd9Sstevel@tonic-gate return ((const char *)S_ERROR); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Fabricate a name for this register so that this definition 2107c478bd9Sstevel@tonic-gate * can be processed through the symbol resolution engine. 2117c478bd9Sstevel@tonic-gate */ 2127c478bd9Sstevel@tonic-gate name = registers[sym->st_value]; 2137c478bd9Sstevel@tonic-gate } else 2147c478bd9Sstevel@tonic-gate name = strs + sym->st_name; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate /* 2177c478bd9Sstevel@tonic-gate * Indicate we're dealing with a register and return its name. 2187c478bd9Sstevel@tonic-gate */ 2197c478bd9Sstevel@tonic-gate *flags |= FLG_SY_REGSYM; 2207c478bd9Sstevel@tonic-gate return (name); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate Sym_desc * 224635216b6SRod Evans ld_reg_find_sparc(Sym *sym, Ofl_desc *ofl) 2257c478bd9Sstevel@tonic-gate { 226635216b6SRod Evans if (ofl->ofl_regsyms == NULL) 227635216b6SRod Evans return (NULL); 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate return (ofl->ofl_regsyms[sym->st_value]); 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate int 233635216b6SRod Evans ld_reg_enter_sparc(Sym_desc *sdp, Ofl_desc *ofl) 2347c478bd9Sstevel@tonic-gate { 235635216b6SRod Evans if (ofl->ofl_regsyms == NULL) { 236635216b6SRod Evans 2377c478bd9Sstevel@tonic-gate ofl->ofl_regsymsno = STO_SPARC_REGISTER_G7 + 1; 238635216b6SRod Evans 2397c478bd9Sstevel@tonic-gate if ((ofl->ofl_regsyms = libld_calloc(sizeof (Sym_desc *), 240635216b6SRod Evans ofl->ofl_regsymsno)) == NULL) { 2417c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 2427c478bd9Sstevel@tonic-gate return (0); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate ofl->ofl_regsyms[sdp->sd_sym->st_value] = sdp; 2477c478bd9Sstevel@tonic-gate return (1); 2487c478bd9Sstevel@tonic-gate } 249