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 */ 21c174926fSrie 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T 247c478bd9Sstevel@tonic-gate * All Rights Reserved 257c478bd9Sstevel@tonic-gate * 26bf994817SAli Bahrami * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * set-up for relocations 317c478bd9Sstevel@tonic-gate */ 32ba2be530Sab196087 33ba2be530Sab196087 #define ELF_TARGET_AMD64 34ba2be530Sab196087 #define ELF_TARGET_SPARC 35ba2be530Sab196087 367c478bd9Sstevel@tonic-gate #include <string.h> 377c478bd9Sstevel@tonic-gate #include <stdio.h> 387c478bd9Sstevel@tonic-gate #include <alloca.h> 395aefb655Srie #include <debug.h> 407c478bd9Sstevel@tonic-gate #include "msg.h" 417c478bd9Sstevel@tonic-gate #include "_libld.h" 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* 44ba2be530Sab196087 * Set up the relocation table flag test macros so that they use the 45ba2be530Sab196087 * relocation table for the current target machine. 46ba2be530Sab196087 */ 47ba2be530Sab196087 #define IS_PLT(X) RELTAB_IS_PLT(X, ld_targ.t_mr.mr_reloc_table) 48ba2be530Sab196087 #define IS_GOT_RELATIVE(X) \ 49ba2be530Sab196087 RELTAB_IS_GOT_RELATIVE(X, ld_targ.t_mr.mr_reloc_table) 50ba2be530Sab196087 #define IS_GOT_PC(X) RELTAB_IS_GOT_PC(X, ld_targ.t_mr.mr_reloc_table) 51ba2be530Sab196087 #define IS_GOTPCREL(X) RELTAB_IS_GOTPCREL(X, ld_targ.t_mr.mr_reloc_table) 52ba2be530Sab196087 #define IS_GOT_BASED(X) RELTAB_IS_GOT_BASED(X, ld_targ.t_mr.mr_reloc_table) 53ba2be530Sab196087 #define IS_GOT_OPINS(X) RELTAB_IS_GOT_OPINS(X, ld_targ.t_mr.mr_reloc_table) 54ba2be530Sab196087 #define IS_GOT_REQUIRED(X) \ 55ba2be530Sab196087 RELTAB_IS_GOT_REQUIRED(X, ld_targ.t_mr.mr_reloc_table) 56ba2be530Sab196087 #define IS_PC_RELATIVE(X) RELTAB_IS_PC_RELATIVE(X, ld_targ.t_mr.mr_reloc_table) 57ba2be530Sab196087 #define IS_ADD_RELATIVE(X) \ 58ba2be530Sab196087 RELTAB_IS_ADD_RELATIVE(X, ld_targ.t_mr.mr_reloc_table) 59ba2be530Sab196087 #define IS_REGISTER(X) RELTAB_IS_REGISTER(X, ld_targ.t_mr.mr_reloc_table) 60ba2be530Sab196087 #define IS_NOTSUP(X) RELTAB_IS_NOTSUP(X, ld_targ.t_mr.mr_reloc_table) 61ba2be530Sab196087 #define IS_SEG_RELATIVE(X) \ 62ba2be530Sab196087 RELTAB_IS_SEG_RELATIVE(X, ld_targ.t_mr.mr_reloc_table) 63ba2be530Sab196087 #define IS_EXTOFFSET(X) RELTAB_IS_EXTOFFSET(X, ld_targ.t_mr.mr_reloc_table) 64ba2be530Sab196087 #define IS_SEC_RELATIVE(X) \ 65ba2be530Sab196087 RELTAB_IS_SEC_RELATIVE(X, ld_targ.t_mr.mr_reloc_table) 66ba2be530Sab196087 #define IS_TLS_INS(X) RELTAB_IS_TLS_INS(X, ld_targ.t_mr.mr_reloc_table) 67ba2be530Sab196087 #define IS_TLS_GD(X) RELTAB_IS_TLS_GD(X, ld_targ.t_mr.mr_reloc_table) 68ba2be530Sab196087 #define IS_TLS_LD(X) RELTAB_IS_TLS_LD(X, ld_targ.t_mr.mr_reloc_table) 69ba2be530Sab196087 #define IS_TLS_IE(X) RELTAB_IS_TLS_IE(X, ld_targ.t_mr.mr_reloc_table) 70ba2be530Sab196087 #define IS_TLS_LE(X) RELTAB_IS_TLS_LE(X, ld_targ.t_mr.mr_reloc_table) 71ba2be530Sab196087 #define IS_LOCALBND(X) RELTAB_IS_LOCALBND(X, ld_targ.t_mr.mr_reloc_table) 72ba2be530Sab196087 #define IS_SIZE(X) RELTAB_IS_SIZE(X, ld_targ.t_mr.mr_reloc_table) 73ba2be530Sab196087 74ba2be530Sab196087 /* 757c478bd9Sstevel@tonic-gate * Structure to hold copy relocation items. 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate typedef struct copy_rel { 7857ef7aa9SRod Evans Sym_desc *c_sdp; /* symbol descriptor to be copied */ 7957ef7aa9SRod Evans Addr c_val; /* original symbol value */ 807c478bd9Sstevel@tonic-gate } Copy_rel; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate /* 837c478bd9Sstevel@tonic-gate * For each copy relocation symbol, determine if the symbol is: 847c478bd9Sstevel@tonic-gate * 1) to be *disp* relocated at runtime 857c478bd9Sstevel@tonic-gate * 2) a reference symbol for *disp* relocation 867c478bd9Sstevel@tonic-gate * 3) possibly *disp* relocated at ld time. 877c478bd9Sstevel@tonic-gate * 887c478bd9Sstevel@tonic-gate * The first and the second are serious errors. 897c478bd9Sstevel@tonic-gate */ 907c478bd9Sstevel@tonic-gate static void 9157ef7aa9SRod Evans is_disp_copied(Ofl_desc *ofl, Copy_rel *crp) 927c478bd9Sstevel@tonic-gate { 9357ef7aa9SRod Evans Ifl_desc *ifl = crp->c_sdp->sd_file; 9457ef7aa9SRod Evans Sym_desc *sdp = crp->c_sdp; 9557ef7aa9SRod Evans Addr symaddr = crp->c_val; 967c478bd9Sstevel@tonic-gate Is_desc *irel; 9757ef7aa9SRod Evans Aliste idx; 98de777a60Sab196087 Conv_inv_buf_t inv_buf; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* 1017c478bd9Sstevel@tonic-gate * This symbol may not be *disp* relocated at run time, but could 1027c478bd9Sstevel@tonic-gate * already have been *disp* relocated when the shared object was 1037c478bd9Sstevel@tonic-gate * created. Warn the user. 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate if ((ifl->ifl_flags & FLG_IF_DISPDONE) && 1067c478bd9Sstevel@tonic-gate (ofl->ofl_flags & FLG_OF_VERBOSE)) 107*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_DISPREL2), 108ba2be530Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, 109ba2be530Sab196087 ld_targ.t_m.m_r_copy, 0, &inv_buf), 110ba2be530Sab196087 ifl->ifl_name, demangle(sdp->sd_name)); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate if ((ifl->ifl_flags & FLG_IF_DISPPEND) == 0) 1137c478bd9Sstevel@tonic-gate return; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Traverse the input relocation sections. 1177c478bd9Sstevel@tonic-gate */ 11857ef7aa9SRod Evans for (APLIST_TRAVERSE(ifl->ifl_relsect, idx, irel)) { 1197c478bd9Sstevel@tonic-gate Sym_desc *rsdp; 1207c478bd9Sstevel@tonic-gate Is_desc *trel; 1217c478bd9Sstevel@tonic-gate Rel *rend, *reloc; 1227c478bd9Sstevel@tonic-gate Xword rsize, entsize; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate trel = ifl->ifl_isdesc[irel->is_shdr->sh_info]; 1257c478bd9Sstevel@tonic-gate rsize = irel->is_shdr->sh_size; 1267c478bd9Sstevel@tonic-gate entsize = irel->is_shdr->sh_entsize; 1277c478bd9Sstevel@tonic-gate reloc = (Rel *)irel->is_indata->d_buf; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate /* 1307c478bd9Sstevel@tonic-gate * Decide entry size 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate if ((entsize == 0) || (entsize > rsize)) { 1337c478bd9Sstevel@tonic-gate if (irel->is_shdr->sh_type == SHT_RELA) 1347c478bd9Sstevel@tonic-gate entsize = sizeof (Rela); 1357c478bd9Sstevel@tonic-gate else 1367c478bd9Sstevel@tonic-gate entsize = sizeof (Rel); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* 1407c478bd9Sstevel@tonic-gate * Traverse the relocation entries. 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate for (rend = (Rel *)((uintptr_t)reloc + (uintptr_t)rsize); 1437c478bd9Sstevel@tonic-gate reloc < rend; 144b3fbe5e6Sseizo reloc = (Rel *)((uintptr_t)reloc + (uintptr_t)entsize)) { 1457c478bd9Sstevel@tonic-gate const char *str; 1467c478bd9Sstevel@tonic-gate Word rstndx; 1477c478bd9Sstevel@tonic-gate 148ba2be530Sab196087 if (IS_PC_RELATIVE(ELF_R_TYPE(reloc->r_info, 149ba2be530Sab196087 ld_targ.t_m.m_mach)) == 0) 1507c478bd9Sstevel@tonic-gate continue; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* 153635216b6SRod Evans * Determine if symbol is referenced from a relocation. 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate rstndx = (Word) ELF_R_SYM(reloc->r_info); 1567c478bd9Sstevel@tonic-gate rsdp = ifl->ifl_oldndx[rstndx]; 1577c478bd9Sstevel@tonic-gate if (rsdp == sdp) { 1587c478bd9Sstevel@tonic-gate if ((str = demangle(rsdp->sd_name)) != 1597c478bd9Sstevel@tonic-gate rsdp->sd_name) { 1607c478bd9Sstevel@tonic-gate char *_str = alloca(strlen(str) + 1); 1617c478bd9Sstevel@tonic-gate (void) strcpy(_str, str); 1627c478bd9Sstevel@tonic-gate str = (const char *)_str; 1637c478bd9Sstevel@tonic-gate } 164*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 165*1007fd6fSAli Bahrami MSG_INTL(MSG_REL_DISPREL1), 1665aefb655Srie conv_reloc_type(ifl->ifl_ehdr->e_machine, 167ba2be530Sab196087 (uint_t)ELF_R_TYPE(reloc->r_info, 168ba2be530Sab196087 ld_targ.t_m.m_mach), 169de777a60Sab196087 0, &inv_buf), ifl->ifl_name, str, 1707c478bd9Sstevel@tonic-gate MSG_INTL(MSG_STR_UNKNOWN), 1717c478bd9Sstevel@tonic-gate EC_XWORD(reloc->r_offset), 1727c478bd9Sstevel@tonic-gate demangle(sdp->sd_name)); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 176635216b6SRod Evans * Determine whether the relocation entry is relocating 1777c478bd9Sstevel@tonic-gate * this symbol. 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate if ((sdp->sd_isc != trel) || 1807c478bd9Sstevel@tonic-gate (reloc->r_offset < symaddr) || 1817c478bd9Sstevel@tonic-gate (reloc->r_offset >= 1827c478bd9Sstevel@tonic-gate (symaddr + sdp->sd_sym->st_size))) 1837c478bd9Sstevel@tonic-gate continue; 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate /* 1867c478bd9Sstevel@tonic-gate * This symbol is truely *disp* relocated, so should 1877c478bd9Sstevel@tonic-gate * really be fixed by user. 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate if ((str = demangle(sdp->sd_name)) != sdp->sd_name) { 1907c478bd9Sstevel@tonic-gate char *_str = alloca(strlen(str) + 1); 1917c478bd9Sstevel@tonic-gate (void) strcpy(_str, str); 1927c478bd9Sstevel@tonic-gate str = (const char *)_str; 1937c478bd9Sstevel@tonic-gate } 194*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_DISPREL1), 1955aefb655Srie conv_reloc_type(ifl->ifl_ehdr->e_machine, 196ba2be530Sab196087 (uint_t)ELF_R_TYPE(reloc->r_info, 197ba2be530Sab196087 ld_targ.t_m.m_mach), 0, &inv_buf), 198c13de8f6Sab196087 ifl->ifl_name, demangle(rsdp->sd_name), str, 1997c478bd9Sstevel@tonic-gate EC_XWORD(reloc->r_offset), str); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * The number of symbols provided by some objects can be very large. Use a 2067c478bd9Sstevel@tonic-gate * binary search to match the associated value to a symbol table entry. 2077c478bd9Sstevel@tonic-gate */ 2087c478bd9Sstevel@tonic-gate static int 2097c478bd9Sstevel@tonic-gate disp_bsearch(const void *key, const void *array) 2107c478bd9Sstevel@tonic-gate { 2117c478bd9Sstevel@tonic-gate Addr kvalue, avalue; 2127c478bd9Sstevel@tonic-gate Ssv_desc *ssvp = (Ssv_desc *)array; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate kvalue = *((Addr *)key); 2157c478bd9Sstevel@tonic-gate avalue = ssvp->ssv_value; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (avalue > kvalue) 2187c478bd9Sstevel@tonic-gate return (-1); 2197c478bd9Sstevel@tonic-gate if ((avalue < kvalue) && 2207c478bd9Sstevel@tonic-gate ((avalue + ssvp->ssv_sdp->sd_sym->st_size) <= kvalue)) 2217c478bd9Sstevel@tonic-gate return (1); 2227c478bd9Sstevel@tonic-gate return (0); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * Given a sorted list of symbols, look for a symbol in which the relocation 2277c478bd9Sstevel@tonic-gate * offset falls between the [sym.st_value - sym.st_value + sym.st_size]. Since 2287c478bd9Sstevel@tonic-gate * the symbol list is maintained in sorted order, we can bail once the 2297c478bd9Sstevel@tonic-gate * relocation offset becomes less than the symbol values. The symbol is 2307c478bd9Sstevel@tonic-gate * returned for use in error diagnostics. 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate static Sym_desc * 2337c478bd9Sstevel@tonic-gate disp_scansyms(Ifl_desc * ifl, Rel_desc *rld, Boolean rlocal, int inspect, 2347c478bd9Sstevel@tonic-gate Ofl_desc *ofl) 2357c478bd9Sstevel@tonic-gate { 2367c478bd9Sstevel@tonic-gate Sym_desc *tsdp, *rsdp; 2377c478bd9Sstevel@tonic-gate Sym *rsym, *tsym; 2387c478bd9Sstevel@tonic-gate Ssv_desc *ssvp; 2397c478bd9Sstevel@tonic-gate uchar_t rtype, ttype; 2407c478bd9Sstevel@tonic-gate Addr value; 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * Sorted symbol values have been uniquified by adding their associated 2447c478bd9Sstevel@tonic-gate * section offset. Uniquify the relocation offset by adding its 2457c478bd9Sstevel@tonic-gate * associated section offset, and search for the symbol. 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate value = rld->rel_roffset; 2487c478bd9Sstevel@tonic-gate if (rld->rel_isdesc->is_shdr) 2497c478bd9Sstevel@tonic-gate value += rld->rel_isdesc->is_shdr->sh_offset; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate if ((ssvp = bsearch((void *)&value, (void *)ifl->ifl_sortsyms, 2527c478bd9Sstevel@tonic-gate ifl->ifl_sortcnt, sizeof (Ssv_desc), &disp_bsearch)) != 0) 2537c478bd9Sstevel@tonic-gate tsdp = ssvp->ssv_sdp; 2547c478bd9Sstevel@tonic-gate else 2557c478bd9Sstevel@tonic-gate tsdp = 0; 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate if (inspect) 2587c478bd9Sstevel@tonic-gate return (tsdp); 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate /* 2617c478bd9Sstevel@tonic-gate * Determine the relocation reference symbol and its type. 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate rsdp = rld->rel_sym; 2647c478bd9Sstevel@tonic-gate rsym = rsdp->sd_sym; 2657c478bd9Sstevel@tonic-gate rtype = ELF_ST_TYPE(rsym->st_info); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * If there is no target symbol to match the relocation offset, then the 2697c478bd9Sstevel@tonic-gate * offset is effectively local data. If the relocation symbol is global 2707c478bd9Sstevel@tonic-gate * data we have a potential for this displacement relocation to be 2717c478bd9Sstevel@tonic-gate * invalidated should the global symbol be copied. 2727c478bd9Sstevel@tonic-gate */ 2737c478bd9Sstevel@tonic-gate if (tsdp == 0) { 2747c478bd9Sstevel@tonic-gate if ((rlocal == TRUE) || 2757c478bd9Sstevel@tonic-gate ((rtype != STT_OBJECT) && (rtype != STT_SECTION))) 2767c478bd9Sstevel@tonic-gate return (tsdp); 2777c478bd9Sstevel@tonic-gate } else { 2787c478bd9Sstevel@tonic-gate /* 2797c478bd9Sstevel@tonic-gate * If both symbols are local, no copy relocations can occur to 28060758829Srie * either symbol. Note, this test is very similar to the test 28160758829Srie * used in ld_sym_adjust_vis(). 2827c478bd9Sstevel@tonic-gate */ 28308278a5eSRod Evans if ((rlocal == TRUE) && (SYM_IS_HIDDEN(tsdp) || 28460758829Srie (ELF_ST_BIND(tsdp->sd_sym->st_info) != STB_GLOBAL) || 28544bac77bSrie ((ofl->ofl_flags & (FLG_OF_AUTOLCL | FLG_OF_AUTOELM)) && 286635216b6SRod Evans ((tsdp->sd_flags & MSK_SY_NOAUTO) == 0)))) 2877c478bd9Sstevel@tonic-gate return (tsdp); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * Determine the relocation target symbols type. 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate tsym = tsdp->sd_sym; 2937c478bd9Sstevel@tonic-gate ttype = ELF_ST_TYPE(tsym->st_info); 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate /* 296141040e8Srie * If the reference symbol is local, and the target isn't a 297141040e8Srie * data element, then no copy relocations can occur to either 298141040e8Srie * symbol. Note, this catches pc-relative relocations against 299141040e8Srie * the _GLOBAL_OFFSET_TABLE_, which is effectively treated as 300141040e8Srie * a local symbol. 301141040e8Srie */ 302141040e8Srie if ((rlocal == TRUE) && (ttype != STT_OBJECT) && 303141040e8Srie (ttype != STT_SECTION)) 304141040e8Srie return (tsdp); 305141040e8Srie 306141040e8Srie /* 307141040e8Srie * Finally, one of the symbols must reference a data element. 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate if ((rtype != STT_OBJECT) && (rtype != STT_SECTION) && 3107c478bd9Sstevel@tonic-gate (ttype != STT_OBJECT) && (ttype != STT_SECTION)) 3117c478bd9Sstevel@tonic-gate return (tsdp); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * We have two global symbols, at least one of which is a data item. 3167c478bd9Sstevel@tonic-gate * The last case where a displacement relocation can be ignored, is 3177c478bd9Sstevel@tonic-gate * if the reference symbol is included in the target symbol. 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate value = rsym->st_value; 320cce0e03bSab196087 if ((rld->rel_flags & FLG_REL_RELA) == FLG_REL_RELA) 3217c478bd9Sstevel@tonic-gate value += rld->rel_raddend; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate if ((rld->rel_roffset >= value) && 3247c478bd9Sstevel@tonic-gate (rld->rel_roffset < (value + rsym->st_size))) 3257c478bd9Sstevel@tonic-gate return (tsdp); 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate /* 3287c478bd9Sstevel@tonic-gate * We have a displacement relocation that could be compromised by a 3297c478bd9Sstevel@tonic-gate * copy relocation of one of the associated data items. 3307c478bd9Sstevel@tonic-gate */ 3317c478bd9Sstevel@tonic-gate rld->rel_flags |= FLG_REL_DISP; 3327c478bd9Sstevel@tonic-gate return (tsdp); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate void 3365aefb655Srie ld_disp_errmsg(const char *msg, Rel_desc *rsp, Ofl_desc *ofl) 3377c478bd9Sstevel@tonic-gate { 3387c478bd9Sstevel@tonic-gate Sym_desc *sdp; 3397c478bd9Sstevel@tonic-gate const char *str; 3407c478bd9Sstevel@tonic-gate Ifl_desc *ifl = rsp->rel_isdesc->is_file; 341de777a60Sab196087 Conv_inv_buf_t inv_buf; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if ((sdp = disp_scansyms(ifl, rsp, 0, 1, ofl)) != 0) 3447c478bd9Sstevel@tonic-gate str = demangle(sdp->sd_name); 3457c478bd9Sstevel@tonic-gate else 3467c478bd9Sstevel@tonic-gate str = MSG_INTL(MSG_STR_UNKNOWN); 3477c478bd9Sstevel@tonic-gate 348*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, msg, 349de777a60Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, rsp->rel_rtype, 350bf994817SAli Bahrami 0, &inv_buf), ifl->ifl_name, ld_reloc_sym_name(rsp), str, 351de777a60Sab196087 EC_OFF(rsp->rel_roffset)); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate /* 3557c478bd9Sstevel@tonic-gate * qsort(3C) comparison routine used for the disp_sortsyms(). 3567c478bd9Sstevel@tonic-gate */ 3577c478bd9Sstevel@tonic-gate static int 3587c478bd9Sstevel@tonic-gate disp_qsort(const void * s1, const void * s2) 3597c478bd9Sstevel@tonic-gate { 3607c478bd9Sstevel@tonic-gate Ssv_desc *ssvp1 = ((Ssv_desc *)s1); 3617c478bd9Sstevel@tonic-gate Ssv_desc *ssvp2 = ((Ssv_desc *)s2); 3627c478bd9Sstevel@tonic-gate Addr val1 = ssvp1->ssv_value; 3637c478bd9Sstevel@tonic-gate Addr val2 = ssvp2->ssv_value; 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate if (val1 > val2) 3667c478bd9Sstevel@tonic-gate return (1); 3677c478bd9Sstevel@tonic-gate if (val1 < val2) 3687c478bd9Sstevel@tonic-gate return (-1); 3697c478bd9Sstevel@tonic-gate return (0); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate /* 3737c478bd9Sstevel@tonic-gate * Determine whether a displacement relocation is between a local and global 3747c478bd9Sstevel@tonic-gate * symbol pair. One symbol is used to perform the relocation, and the other 3757c478bd9Sstevel@tonic-gate * is the destination offset of the relocation. 3767c478bd9Sstevel@tonic-gate */ 3777c478bd9Sstevel@tonic-gate static uintptr_t 3787c478bd9Sstevel@tonic-gate disp_inspect(Ofl_desc *ofl, Rel_desc *rld, Boolean rlocal) 3797c478bd9Sstevel@tonic-gate { 3807c478bd9Sstevel@tonic-gate Is_desc *isp = rld->rel_isdesc; 3817c478bd9Sstevel@tonic-gate Ifl_desc *ifl = rld->rel_isdesc->is_file; 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * If the input files symbols haven't been sorted yet, do so. 3857c478bd9Sstevel@tonic-gate */ 3867c478bd9Sstevel@tonic-gate if (ifl->ifl_sortsyms == 0) { 3877c478bd9Sstevel@tonic-gate Word ondx, nndx; 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate if ((ifl->ifl_sortsyms = libld_malloc((ifl->ifl_symscnt + 1) * 3907c478bd9Sstevel@tonic-gate sizeof (Ssv_desc))) == 0) 3917c478bd9Sstevel@tonic-gate return (S_ERROR); 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate for (ondx = 0, nndx = 0; ondx < ifl->ifl_symscnt; ondx++) { 3947c478bd9Sstevel@tonic-gate Sym_desc *sdp; 3957c478bd9Sstevel@tonic-gate Addr value; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * As symbol resolution has already occurred, various 3997c478bd9Sstevel@tonic-gate * symbols from this object may have been satisfied 4007c478bd9Sstevel@tonic-gate * from other objects. Only select symbols from this 4017c478bd9Sstevel@tonic-gate * object. For the displacement test, we only really 4027c478bd9Sstevel@tonic-gate * need to observe data definitions, however, later as 4037c478bd9Sstevel@tonic-gate * part of providing warning disgnostics, relating the 4047c478bd9Sstevel@tonic-gate * relocation offset to a symbol is desirable. Thus, 4057c478bd9Sstevel@tonic-gate * collect all symbols that define a memory area. 4067c478bd9Sstevel@tonic-gate */ 4077c478bd9Sstevel@tonic-gate if (((sdp = ifl->ifl_oldndx[ondx]) == 0) || 4080bc07c75Srie (sdp->sd_sym->st_shndx == SHN_UNDEF) || 4090bc07c75Srie (sdp->sd_sym->st_shndx >= SHN_LORESERVE) || 4107c478bd9Sstevel@tonic-gate (sdp->sd_ref != REF_REL_NEED) || 4117c478bd9Sstevel@tonic-gate (sdp->sd_file != ifl) || 4127c478bd9Sstevel@tonic-gate (sdp->sd_sym->st_size == 0)) 4137c478bd9Sstevel@tonic-gate continue; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate /* 4167c478bd9Sstevel@tonic-gate * As a further optimization for later checking, mark 4177c478bd9Sstevel@tonic-gate * this section if this a global data definition. 4187c478bd9Sstevel@tonic-gate */ 4197c478bd9Sstevel@tonic-gate if (sdp->sd_isc && (ondx >= ifl->ifl_locscnt)) 4207c478bd9Sstevel@tonic-gate sdp->sd_isc->is_flags |= FLG_IS_GDATADEF; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate /* 4237c478bd9Sstevel@tonic-gate * Capture the symbol. Within relocatable objects, a 4247c478bd9Sstevel@tonic-gate * symbols value is its offset within its associated 4257c478bd9Sstevel@tonic-gate * section. Add the section offset to this value to 4267c478bd9Sstevel@tonic-gate * uniquify the symbol. 4277c478bd9Sstevel@tonic-gate */ 4287c478bd9Sstevel@tonic-gate value = sdp->sd_sym->st_value; 4297c478bd9Sstevel@tonic-gate if (sdp->sd_isc && sdp->sd_isc->is_shdr) 4307c478bd9Sstevel@tonic-gate value += sdp->sd_isc->is_shdr->sh_offset; 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate ifl->ifl_sortsyms[nndx].ssv_value = value; 4337c478bd9Sstevel@tonic-gate ifl->ifl_sortsyms[nndx].ssv_sdp = sdp; 4347c478bd9Sstevel@tonic-gate nndx++; 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * Sort the list based on the symbols value (address). 4397c478bd9Sstevel@tonic-gate */ 4407c478bd9Sstevel@tonic-gate if ((ifl->ifl_sortcnt = nndx) != 0) 4417c478bd9Sstevel@tonic-gate qsort(ifl->ifl_sortsyms, nndx, sizeof (Ssv_desc), 4427c478bd9Sstevel@tonic-gate &disp_qsort); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate /* 4467c478bd9Sstevel@tonic-gate * If the reference symbol is local, and the section being relocated 4477c478bd9Sstevel@tonic-gate * contains no global definitions, neither can be the target of a copy 4487c478bd9Sstevel@tonic-gate * relocation. 4497c478bd9Sstevel@tonic-gate */ 4507c478bd9Sstevel@tonic-gate if ((rlocal == FALSE) && ((isp->is_flags & FLG_IS_GDATADEF) == 0)) 4517c478bd9Sstevel@tonic-gate return (1); 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /* 4547c478bd9Sstevel@tonic-gate * Otherwise determine whether this relocation symbol and its offset 4557c478bd9Sstevel@tonic-gate * could be candidates for a copy relocation. 4567c478bd9Sstevel@tonic-gate */ 4577c478bd9Sstevel@tonic-gate if (ifl->ifl_sortcnt) 4587c478bd9Sstevel@tonic-gate (void) disp_scansyms(ifl, rld, rlocal, 0, ofl); 4597c478bd9Sstevel@tonic-gate return (1); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 462141040e8Srie /* 463bf994817SAli Bahrami * Return a Rel_cachebuf with an available Rel_desc entry from the 464bf994817SAli Bahrami * specified cache, allocating a cache buffer if necessary. 465bf994817SAli Bahrami * 466bf994817SAli Bahrami * entry: 467bf994817SAli Bahrami * ofl - Output file descriptor 468bf994817SAli Bahrami * rcp - Relocation cache to allocate the descriptor from. 469bf994817SAli Bahrami * One of &ofl->ofl_actrels or &ofl->ofl_outrels. 470bf994817SAli Bahrami * 471bf994817SAli Bahrami * exit: 472bf994817SAli Bahrami * Returns the allocated descriptor, or NULL if the allocation fails. 47357ef7aa9SRod Evans */ 474bf994817SAli Bahrami static Rel_cachebuf * 475bf994817SAli Bahrami ld_add_rel_cache(Ofl_desc *ofl, Rel_cache *rcp) 47657ef7aa9SRod Evans { 477bf994817SAli Bahrami Rel_cachebuf *rcbp; 478bf994817SAli Bahrami size_t nelts, size, alloc_cnt; 47957ef7aa9SRod Evans 48057ef7aa9SRod Evans /* 48157ef7aa9SRod Evans * If there is space available in the present cache bucket, return the 48257ef7aa9SRod Evans * next free entry. 48357ef7aa9SRod Evans */ 484bf994817SAli Bahrami alloc_cnt = aplist_nitems(rcp->rc_list); 485bf994817SAli Bahrami if (rcp->rc_list && 486bf994817SAli Bahrami ((rcbp = rcp->rc_list->apl_data[alloc_cnt - 1]) != NULL) && 487bf994817SAli Bahrami (rcbp->rc_free < rcbp->rc_end)) 488bf994817SAli Bahrami return (rcbp); 48957ef7aa9SRod Evans 49057ef7aa9SRod Evans /* 491bf994817SAli Bahrami * Allocate a new bucket. As we cannot know the number of relocations 492bf994817SAli Bahrami * we'll have in the active and output cache until after the link is 493bf994817SAli Bahrami * complete, the size of the bucket is a heuristic. 494bf994817SAli Bahrami * 495bf994817SAli Bahrami * In general, if the output object is an executable, or a sharable 496bf994817SAli Bahrami * object, then the size of the active relocation list will be nearly 497bf994817SAli Bahrami * the same as the number of input relocations, and the output 498bf994817SAli Bahrami * relocation list will be very short. If the output object is a 499bf994817SAli Bahrami * relocatable object, then the reverse is true. Therefore, the initial 500bf994817SAli Bahrami * allocation for the appropriate list is sized to fit all the input 501bf994817SAli Bahrami * allocations in a single shot. 502bf994817SAli Bahrami * 503bf994817SAli Bahrami * All other allocations are done in units of REL_CACHEBUF_ALLOC, 504bf994817SAli Bahrami * which is chosen to be large enough to cover most common cases, 505bf994817SAli Bahrami * but small enough that not using it fully is inconsequential. 506bf994817SAli Bahrami * 507bf994817SAli Bahrami * In an ideal scenario, this results in one allocation on each list. 50857ef7aa9SRod Evans */ 509bf994817SAli Bahrami nelts = REL_CACHEBUF_ALLOC; 510bf994817SAli Bahrami if ((alloc_cnt == 0) && (ofl->ofl_relocincnt > REL_CACHEBUF_ALLOC)) { 511bf994817SAli Bahrami Boolean is_rel = (ofl->ofl_flags & FLG_OF_RELOBJ) != 0; 51257ef7aa9SRod Evans 513bf994817SAli Bahrami if (((rcp == &ofl->ofl_actrels) && !is_rel) || 514bf994817SAli Bahrami ((rcp == &ofl->ofl_outrels) && is_rel)) 515bf994817SAli Bahrami nelts = ofl->ofl_relocincnt; 516bf994817SAli Bahrami } 51757ef7aa9SRod Evans 518bf994817SAli Bahrami /* 519bf994817SAli Bahrami * Compute the total number of bytes to allocate. The first element 520bf994817SAli Bahrami * of the array is built into the Rel_cachebuf header, so we subtract 521bf994817SAli Bahrami * one from nelts. 522bf994817SAli Bahrami */ 523bf994817SAli Bahrami size = sizeof (Rel_cachebuf) + ((nelts - 1) * sizeof (Rel_desc)); 52457ef7aa9SRod Evans 525bf994817SAli Bahrami if (((rcbp = libld_malloc(size)) == NULL) || 526bf994817SAli Bahrami (aplist_append(&rcp->rc_list, rcbp, AL_CNT_OFL_RELS) == NULL)) 527bf994817SAli Bahrami return (NULL); 52857ef7aa9SRod Evans 529bf994817SAli Bahrami rcbp->rc_free = rcbp->rc_arr; 530bf994817SAli Bahrami rcbp->rc_end = rcbp->rc_arr + nelts; 531bf994817SAli Bahrami 532bf994817SAli Bahrami return (rcbp); 533bf994817SAli Bahrami } 534bf994817SAli Bahrami 535bf994817SAli Bahrami /* 536bf994817SAli Bahrami * Allocate a Rel_aux descriptor and attach it to the given Rel_desc, 537bf994817SAli Bahrami * allocating an auxiliary cache buffer if necessary. 538bf994817SAli Bahrami * 539bf994817SAli Bahrami * entry: 540bf994817SAli Bahrami * ofl - Output file descriptor 541bf994817SAli Bahrami * rdp - Rel_desc descriptor that requires an auxiliary block 542bf994817SAli Bahrami * 543bf994817SAli Bahrami * exit: 544bf994817SAli Bahrami * Returns TRUE on success, and FALSE if the allocation fails. 545bf994817SAli Bahrami * On success, the caller is responsible for initializing the 546bf994817SAli Bahrami * auxiliary block properly. 547bf994817SAli Bahrami */ 548bf994817SAli Bahrami static Boolean 549bf994817SAli Bahrami ld_add_rel_aux(Ofl_desc *ofl, Rel_desc *rdesc) 550bf994817SAli Bahrami { 551bf994817SAli Bahrami Rel_aux_cachebuf *racp = NULL; 552bf994817SAli Bahrami size_t size; 553bf994817SAli Bahrami 554bf994817SAli Bahrami /* 555bf994817SAli Bahrami * If there is space available in the present cache bucket, use it. 556bf994817SAli Bahrami * Otherwise, allocate a new bucket. 557bf994817SAli Bahrami */ 558bf994817SAli Bahrami if (ofl->ofl_relaux) { 559bf994817SAli Bahrami racp = ofl->ofl_relaux->apl_data[ 560bf994817SAli Bahrami ofl->ofl_relaux->apl_nitems - 1]; 561bf994817SAli Bahrami 562bf994817SAli Bahrami if (racp && (racp->rac_free >= racp->rac_end)) 563bf994817SAli Bahrami racp = NULL; 564bf994817SAli Bahrami } 565bf994817SAli Bahrami if (racp == NULL) { 566bf994817SAli Bahrami /* 567bf994817SAli Bahrami * Compute the total number of bytes to allocate. The first 568bf994817SAli Bahrami * element of the array is built into the Rel_aux_cachebuf 569bf994817SAli Bahrami * header, so we subtract one from the number of elements. 570bf994817SAli Bahrami */ 571bf994817SAli Bahrami size = sizeof (Rel_aux_cachebuf) + 572bf994817SAli Bahrami ((RELAUX_CACHEBUF_ALLOC - 1) * sizeof (Rel_aux)); 573bf994817SAli Bahrami if (((racp = libld_malloc(size)) == NULL) || 574bf994817SAli Bahrami (aplist_append(&ofl->ofl_relaux, racp, AL_CNT_OFL_RELS) == 575bf994817SAli Bahrami NULL)) 576bf994817SAli Bahrami return (FALSE); 577bf994817SAli Bahrami 578bf994817SAli Bahrami racp->rac_free = racp->rac_arr; 579bf994817SAli Bahrami racp->rac_end = racp->rac_arr + RELAUX_CACHEBUF_ALLOC; 580bf994817SAli Bahrami } 581bf994817SAli Bahrami 582bf994817SAli Bahrami /* Take an auxiliary descriptor from the cache and add it to rdesc */ 583bf994817SAli Bahrami rdesc->rel_aux = racp->rac_free++; 584bf994817SAli Bahrami 585bf994817SAli Bahrami return (TRUE); 586bf994817SAli Bahrami } 587bf994817SAli Bahrami 588bf994817SAli Bahrami /* 589bf994817SAli Bahrami * Enter a copy of the given Rel_desc relocation descriptor, and 590bf994817SAli Bahrami * any associated auxiliary Rel_aux it may reference, into the 591bf994817SAli Bahrami * specified relocation cache. 592bf994817SAli Bahrami * 593bf994817SAli Bahrami * entry: 594bf994817SAli Bahrami * ofl - Output file descriptor 595bf994817SAli Bahrami * rcp - Relocation descriptor cache to recieve relocation 596bf994817SAli Bahrami * rdesc - Rel_desc image to be inserted 597bf994817SAli Bahrami * flags - Flags to add to rdest->rel_flags in the inserted descriptor 598bf994817SAli Bahrami * 599bf994817SAli Bahrami * exit: 600bf994817SAli Bahrami * Returns the pointer to the inserted descriptor on success. 601bf994817SAli Bahrami * Returns NULL if an allocation error occurs. 602bf994817SAli Bahrami */ 603bf994817SAli Bahrami Rel_desc * 604bf994817SAli Bahrami ld_reloc_enter(Ofl_desc *ofl, Rel_cache *rcp, Rel_desc *rdesc, Word flags) 605bf994817SAli Bahrami { 606bf994817SAli Bahrami Rel_desc *arsp; 607bf994817SAli Bahrami Rel_aux *auxp; 608bf994817SAli Bahrami Rel_cachebuf *rcbp; 609bf994817SAli Bahrami 610bf994817SAli Bahrami 611bf994817SAli Bahrami /* 612bf994817SAli Bahrami * If no relocation cache structures are available, allocate a new 613bf994817SAli Bahrami * one and link it to the buffer list. 614bf994817SAli Bahrami */ 615bf994817SAli Bahrami rcbp = ld_add_rel_cache(ofl, rcp); 616bf994817SAli Bahrami if (rcbp == NULL) 617bf994817SAli Bahrami return (NULL); 618bf994817SAli Bahrami arsp = rcbp->rc_free; 619bf994817SAli Bahrami 620bf994817SAli Bahrami /* 621bf994817SAli Bahrami * If there is an auxiliary block on the original, allocate 622bf994817SAli Bahrami * one for the clone. Save the pointer, because the struct copy 623bf994817SAli Bahrami * below will crush it. 624bf994817SAli Bahrami */ 625bf994817SAli Bahrami if (rdesc->rel_aux != NULL) { 626bf994817SAli Bahrami if (!ld_add_rel_aux(ofl, arsp)) 627bf994817SAli Bahrami return (NULL); 628bf994817SAli Bahrami auxp = arsp->rel_aux; 629bf994817SAli Bahrami } 630bf994817SAli Bahrami 631bf994817SAli Bahrami /* Copy contents of the original into the clone */ 632bf994817SAli Bahrami *arsp = *rdesc; 633bf994817SAli Bahrami 634bf994817SAli Bahrami /* 635bf994817SAli Bahrami * If there is an auxiliary block, restore the clone's pointer to 636bf994817SAli Bahrami * it, and copy the auxiliary contents. 637bf994817SAli Bahrami */ 638bf994817SAli Bahrami if (rdesc->rel_aux != NULL) { 639bf994817SAli Bahrami arsp->rel_aux = auxp; 640bf994817SAli Bahrami *auxp = *rdesc->rel_aux; 641bf994817SAli Bahrami } 642bf994817SAli Bahrami arsp->rel_flags |= flags; 643bf994817SAli Bahrami 644bf994817SAli Bahrami rcbp->rc_free++; 645bf994817SAli Bahrami rcp->rc_cnt++; 646bf994817SAli Bahrami 647bf994817SAli Bahrami return (arsp); 648bf994817SAli Bahrami } 649bf994817SAli Bahrami 650bf994817SAli Bahrami /* 651bf994817SAli Bahrami * Initialize a relocation descriptor auxiliary block to default 652bf994817SAli Bahrami * values. 653bf994817SAli Bahrami * 654bf994817SAli Bahrami * entry: 655bf994817SAli Bahrami * rdesc - Relocation descriptor, with a non-NULL rel_aux field 656bf994817SAli Bahrami * pointing at the auxiliary block to be initialized. 657bf994817SAli Bahrami * 658bf994817SAli Bahrami * exit: 659bf994817SAli Bahrami * Each field in rdesc->rel_aux has been set to its default value 660bf994817SAli Bahrami */ 661bf994817SAli Bahrami static void 662bf994817SAli Bahrami ld_init_rel_aux(Rel_desc *rdesc) 663bf994817SAli Bahrami { 664bf994817SAli Bahrami Rel_aux *rap = rdesc->rel_aux; 665bf994817SAli Bahrami 666bf994817SAli Bahrami /* 667bf994817SAli Bahrami * The default output section is the one the input section 668bf994817SAli Bahrami * is assigned to, assuming that there is an input section. 669bf994817SAli Bahrami * Failing that, NULL is the only possibility, and we expect 670bf994817SAli Bahrami * that the caller will assign an explicit value. 671bf994817SAli Bahrami */ 672bf994817SAli Bahrami rap->ra_osdesc = (rdesc->rel_isdesc == NULL) ? NULL : 673bf994817SAli Bahrami rdesc->rel_isdesc->is_osdesc; 674bf994817SAli Bahrami 675bf994817SAli Bahrami /* The ra_usym defaults to the value in rel_sym */ 676bf994817SAli Bahrami rap->ra_usym = rdesc->rel_sym; 677bf994817SAli Bahrami 678bf994817SAli Bahrami /* Remaining fields are zeroed */ 679bf994817SAli Bahrami rap->ra_move = NULL; 680bf994817SAli Bahrami rap->ra_typedata = 0; 681bf994817SAli Bahrami } 682bf994817SAli Bahrami 683bf994817SAli Bahrami /* 684bf994817SAli Bahrami * The ld_reloc_set_aux_XXX() functions are used to set the value of an 685bf994817SAli Bahrami * auxiliary relocation item on a relocation descriptor that exists in 686bf994817SAli Bahrami * the active or output relocation cache. These descriptors are created 687bf994817SAli Bahrami * via a call to ld_reloc_enter(). 688bf994817SAli Bahrami * 689bf994817SAli Bahrami * These functions preserve the illusion that every relocation descriptor 690bf994817SAli Bahrami * has a non-NULL auxiliary block into which values can be set, while 691bf994817SAli Bahrami * only creating an auxiliary block if one is actually necessary, preventing 692bf994817SAli Bahrami * the large memory allocations that would otherwise occur. They operate 693bf994817SAli Bahrami * as follows: 694bf994817SAli Bahrami * 695bf994817SAli Bahrami * - If an auxiliary block already exists, set the desired value and 696bf994817SAli Bahrami * and return TRUE. 697bf994817SAli Bahrami * 698bf994817SAli Bahrami * - If no auxiliary block exists, but the desired value is the default 699bf994817SAli Bahrami * value for the specified item, then no auxiliary block is needed, 700bf994817SAli Bahrami * and TRUE is returned. 701bf994817SAli Bahrami * 702bf994817SAli Bahrami * - If no auxiliary block exists, and the desired value is not the 703bf994817SAli Bahrami * default for the specified item, allocate an auxiliary block for 704bf994817SAli Bahrami * the descriptor, initialize its contents to default values for all 705bf994817SAli Bahrami * items, set the specified value, and return TRUE. 706bf994817SAli Bahrami * 707bf994817SAli Bahrami * - If an auxiliary block needs to be added, but the allocation fails, 708bf994817SAli Bahrami * an error is issued, and FALSE is returned. 709bf994817SAli Bahrami * 710bf994817SAli Bahrami * Note that we only provide an ld_reloc_set_aux_XXX() function for those 711bf994817SAli Bahrami * auxiliary items that libld actually modifies in Rel_desc descriptors 712bf994817SAli Bahrami * in the active or output caches. If another one is needed, add it here. 713bf994817SAli Bahrami * 714bf994817SAli Bahrami * The PROCESS_NULL_REL_AUX macro is used to provide a single implementation 715bf994817SAli Bahrami * for the logic that determines if an auxiliary block is needed or not, 716bf994817SAli Bahrami * and handles the details of allocating and initializing it. It accepts 717bf994817SAli Bahrami * one argument, _isdefault_predicate, which should be a call to the 718bf994817SAli Bahrami * RELAUX_ISDEFAULT_xxx() macro appropriate for the auxiliary item 719bf994817SAli Bahrami */ 720bf994817SAli Bahrami 721bf994817SAli Bahrami #define PROCESS_NULL_REL_AUX(_isdefault_predicate) \ 722bf994817SAli Bahrami if (rdesc->rel_aux == NULL) { \ 723bf994817SAli Bahrami /* If requested value is the default, no need for aux block */ \ 724bf994817SAli Bahrami if (_isdefault_predicate) \ 725bf994817SAli Bahrami return (TRUE); \ 726bf994817SAli Bahrami /* Allocate and attach an auxiliary block */ \ 727bf994817SAli Bahrami if (!ld_add_rel_aux(ofl, rdesc)) \ 728bf994817SAli Bahrami return (FALSE); \ 729bf994817SAli Bahrami /* Initialize the auxiliary block with default values */ \ 730bf994817SAli Bahrami ld_init_rel_aux(rdesc); \ 731bf994817SAli Bahrami } 732bf994817SAli Bahrami 733bf994817SAli Bahrami Boolean 734bf994817SAli Bahrami ld_reloc_set_aux_osdesc(Ofl_desc *ofl, Rel_desc *rdesc, Os_desc *osp) 735bf994817SAli Bahrami { 736bf994817SAli Bahrami PROCESS_NULL_REL_AUX(RELAUX_ISDEFAULT_OSDESC(rdesc, osp)) 737bf994817SAli Bahrami rdesc->rel_aux->ra_osdesc = osp; 738bf994817SAli Bahrami return (TRUE); 739bf994817SAli Bahrami } 740bf994817SAli Bahrami 741bf994817SAli Bahrami Boolean 742bf994817SAli Bahrami ld_reloc_set_aux_usym(Ofl_desc *ofl, Rel_desc *rdesc, Sym_desc *sdp) 743bf994817SAli Bahrami { 744bf994817SAli Bahrami PROCESS_NULL_REL_AUX(RELAUX_ISDEFAULT_USYM(rdesc, sdp)) 745bf994817SAli Bahrami rdesc->rel_aux->ra_usym = sdp; 746bf994817SAli Bahrami return (TRUE); 747bf994817SAli Bahrami } 748bf994817SAli Bahrami 749bf994817SAli Bahrami #undef PROCESS_NULL_REL_AUX 750bf994817SAli Bahrami 751bf994817SAli Bahrami /* 752bf994817SAli Bahrami * Return a descriptive name for the symbol associated with the 753bf994817SAli Bahrami * given relocation descriptor. This will be the actual symbol 754bf994817SAli Bahrami * name if one exists, or a suitable alternative otherwise. 755bf994817SAli Bahrami * 756bf994817SAli Bahrami * entry: 757bf994817SAli Bahrami * rsp - Relocation descriptor 758bf994817SAli Bahrami */ 759bf994817SAli Bahrami const char * 760bf994817SAli Bahrami ld_reloc_sym_name(Rel_desc *rsp) 761bf994817SAli Bahrami { 762bf994817SAli Bahrami Sym_desc *sdp = rsp->rel_sym; 763bf994817SAli Bahrami 764bf994817SAli Bahrami if (sdp != NULL) { 765bf994817SAli Bahrami /* If the symbol has a valid name use it */ 766bf994817SAli Bahrami if (sdp->sd_name && *sdp->sd_name) 767bf994817SAli Bahrami return (demangle(sdp->sd_name)); 768bf994817SAli Bahrami 769bf994817SAli Bahrami /* 770bf994817SAli Bahrami * If the symbol is STT_SECTION, and the corresponding 771bf994817SAli Bahrami * section symbol has the specially prepared string intended 772bf994817SAli Bahrami * for this use, use that string. The string is of the form 773bf994817SAli Bahrami * secname (section) 774bf994817SAli Bahrami */ 775bf994817SAli Bahrami if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) && 776bf994817SAli Bahrami (sdp->sd_isc != NULL) && (sdp->sd_isc->is_sym_name != NULL)) 777bf994817SAli Bahrami return (demangle(sdp->sd_isc->is_sym_name)); 778bf994817SAli Bahrami } else { 779bf994817SAli Bahrami /* 780bf994817SAli Bahrami * Use an empty name for a register relocation with 781bf994817SAli Bahrami * no symbol. 782bf994817SAli Bahrami */ 783bf994817SAli Bahrami if (IS_REGISTER(rsp->rel_rtype)) 784bf994817SAli Bahrami return (MSG_ORIG(MSG_STR_EMPTY)); 785bf994817SAli Bahrami } 786bf994817SAli Bahrami 787bf994817SAli Bahrami /* If all else fails, report it as <unknown> */ 788bf994817SAli Bahrami return (MSG_INTL(MSG_STR_UNKNOWN)); 78957ef7aa9SRod Evans } 79057ef7aa9SRod Evans 79157ef7aa9SRod Evans /* 792141040e8Srie * Add an active relocation record. 793141040e8Srie */ 794141040e8Srie uintptr_t 7955aefb655Srie ld_add_actrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl) 796141040e8Srie { 797141040e8Srie Rel_desc *arsp; 798141040e8Srie 799bf994817SAli Bahrami if ((arsp = ld_reloc_enter(ofl, &ofl->ofl_actrels, rsp, flags)) == NULL) 800141040e8Srie return (S_ERROR); 801141040e8Srie 802141040e8Srie /* 803141040e8Srie * Any GOT relocation reference requires the creation of a .got table. 804141040e8Srie * Most references to a .got require a .got entry, which is accounted 805141040e8Srie * for with the ofl_gotcnt counter. However, some references are 806141040e8Srie * relative to the .got table, but require no .got entry. This test 807141040e8Srie * insures a .got is created regardless of the type of reference. 808141040e8Srie */ 809141040e8Srie if (IS_GOT_REQUIRED(arsp->rel_rtype)) 810141040e8Srie ofl->ofl_flags |= FLG_OF_BLDGOT; 811141040e8Srie 812141040e8Srie /* 813141040e8Srie * If this is a displacement relocation generate a warning. 814141040e8Srie */ 815141040e8Srie if (arsp->rel_flags & FLG_REL_DISP) { 816141040e8Srie ofl->ofl_dtflags_1 |= DF_1_DISPRELDNE; 817141040e8Srie 818141040e8Srie if (ofl->ofl_flags & FLG_OF_VERBOSE) 8195aefb655Srie ld_disp_errmsg(MSG_INTL(MSG_REL_DISPREL3), arsp, ofl); 820141040e8Srie } 821141040e8Srie 8225aefb655Srie DBG_CALL(Dbg_reloc_ars_entry(ofl->ofl_lml, ELF_DBG_LD, 823ba2be530Sab196087 arsp->rel_isdesc->is_shdr->sh_type, ld_targ.t_m.m_mach, arsp)); 824141040e8Srie return (1); 825141040e8Srie } 826141040e8Srie 827f3324781Sab196087 /* 828f3324781Sab196087 * In the platform specific machrel.XXX.c files, we sometimes write 829ba2be530Sab196087 * a value directly into the got/plt. These function can be used when 830f3324781Sab196087 * the running linker has the opposite byte order of the object being 831f3324781Sab196087 * produced. 832f3324781Sab196087 */ 833ba2be530Sab196087 Word 834ba2be530Sab196087 ld_bswap_Word(Word v) 835f3324781Sab196087 { 836ba2be530Sab196087 return (BSWAP_WORD(v)); 837ba2be530Sab196087 } 838ba2be530Sab196087 839ba2be530Sab196087 840ba2be530Sab196087 Xword 841ba2be530Sab196087 ld_bswap_Xword(Xword v) 842ba2be530Sab196087 { 843ba2be530Sab196087 return (BSWAP_XWORD(v)); 844f3324781Sab196087 } 845f3324781Sab196087 846f3324781Sab196087 8477c478bd9Sstevel@tonic-gate uintptr_t 8485aefb655Srie ld_reloc_GOT_relative(Boolean local, Rel_desc *rsp, Ofl_desc *ofl) 8497c478bd9Sstevel@tonic-gate { 85057ef7aa9SRod Evans Sym_desc *sdp = rsp->rel_sym; 8511d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags; 8527c478bd9Sstevel@tonic-gate Gotndx *gnp; 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate /* 8557c478bd9Sstevel@tonic-gate * If this is the first time we've seen this symbol in a GOT 8567c478bd9Sstevel@tonic-gate * relocation we need to assign it a GOT token. Once we've got 8577c478bd9Sstevel@tonic-gate * all of the GOT's assigned we can assign the actual indexes. 8587c478bd9Sstevel@tonic-gate */ 85957ef7aa9SRod Evans if ((gnp = (*ld_targ.t_mr.mr_find_got_ndx)(sdp->sd_GOTndxs, 860ba2be530Sab196087 GOT_REF_GENERIC, ofl, rsp)) == 0) { 8617c478bd9Sstevel@tonic-gate Word rtype = rsp->rel_rtype; 8627c478bd9Sstevel@tonic-gate 86357ef7aa9SRod Evans if ((*ld_targ.t_mr.mr_assign_got_ndx)(&(sdp->sd_GOTndxs), NULL, 864ba2be530Sab196087 GOT_REF_GENERIC, ofl, rsp, sdp) == S_ERROR) 8657c478bd9Sstevel@tonic-gate return (S_ERROR); 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate /* 868c1d50c4dSAli Bahrami * Initialize the GOT table entry. 8697c478bd9Sstevel@tonic-gate * 870c1d50c4dSAli Bahrami * For global symbols, we clear the GOT table entry and create 871c1d50c4dSAli Bahrami * a GLOB_DAT relocation against the symbol. 8727c478bd9Sstevel@tonic-gate * 873c1d50c4dSAli Bahrami * For local symbols, we enter the symbol value into a GOT 874c1d50c4dSAli Bahrami * table entry and create a relative relocation if all of 875c1d50c4dSAli Bahrami * the following hold: 876c1d50c4dSAli Bahrami * 877c1d50c4dSAli Bahrami * - Output is a shared object 878c1d50c4dSAli Bahrami * - Symbol is not ABS 879c1d50c4dSAli Bahrami * - Relocation is not against one of the special sections 880c1d50c4dSAli Bahrami * (COMMON, ...) 881c1d50c4dSAli Bahrami * - This is not one of the generated symbols we have 882c1d50c4dSAli Bahrami * to update after the output object has been fully 883c1d50c4dSAli Bahrami * laid out (_START_, _END_, ...) 884c1d50c4dSAli Bahrami * 885c1d50c4dSAli Bahrami * Local symbols that don't meet the above requirements 886c1d50c4dSAli Bahrami * are processed as is. 8877c478bd9Sstevel@tonic-gate */ 8887c478bd9Sstevel@tonic-gate if (local == TRUE) { 889c1d50c4dSAli Bahrami if ((flags & FLG_OF_SHAROBJ) && 890c1d50c4dSAli Bahrami (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) || 891c1d50c4dSAli Bahrami ((sdp->sd_sym->st_shndx != SHN_ABS)) || 892c1d50c4dSAli Bahrami (sdp->sd_aux && sdp->sd_aux->sa_symspec))) { 8935aefb655Srie if (ld_add_actrel((FLG_REL_GOT | FLG_REL_GOTCL), 8947c478bd9Sstevel@tonic-gate rsp, ofl) == S_ERROR) 8957c478bd9Sstevel@tonic-gate return (S_ERROR); 8967c478bd9Sstevel@tonic-gate 897c1d50c4dSAli Bahrami rsp->rel_rtype = ld_targ.t_m.m_r_relative; 898c1d50c4dSAli Bahrami 899ba2be530Sab196087 if ((*ld_targ.t_mr.mr_add_outrel) 900c1d50c4dSAli Bahrami ((FLG_REL_GOT | FLG_REL_ADVAL), 901c1d50c4dSAli Bahrami rsp, ofl) == S_ERROR) 9027c478bd9Sstevel@tonic-gate return (S_ERROR); 903c1d50c4dSAli Bahrami 9047c478bd9Sstevel@tonic-gate rsp->rel_rtype = rtype; 9057c478bd9Sstevel@tonic-gate } else { 9065aefb655Srie if (ld_add_actrel(FLG_REL_GOT, rsp, 9077c478bd9Sstevel@tonic-gate ofl) == S_ERROR) 9087c478bd9Sstevel@tonic-gate return (S_ERROR); 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate } else { 911ba2be530Sab196087 rsp->rel_rtype = ld_targ.t_m.m_r_glob_dat; 912ba2be530Sab196087 if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_GOT, 913ba2be530Sab196087 rsp, ofl) == S_ERROR) 9147c478bd9Sstevel@tonic-gate return (S_ERROR); 9157c478bd9Sstevel@tonic-gate rsp->rel_rtype = rtype; 9167c478bd9Sstevel@tonic-gate } 9177c478bd9Sstevel@tonic-gate } else { 918ba2be530Sab196087 if ((*ld_targ.t_mr.mr_assign_got_ndx)(&(sdp->sd_GOTndxs), gnp, 919ba2be530Sab196087 GOT_REF_GENERIC, ofl, rsp, sdp) == S_ERROR) 9207c478bd9Sstevel@tonic-gate return (S_ERROR); 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate /* 9247c478bd9Sstevel@tonic-gate * Perform relocation to GOT table entry. 9257c478bd9Sstevel@tonic-gate */ 9265aefb655Srie return (ld_add_actrel(NULL, rsp, ofl)); 9277c478bd9Sstevel@tonic-gate } 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate /* 9307c478bd9Sstevel@tonic-gate * Perform relocations for PLT's 9317c478bd9Sstevel@tonic-gate */ 9327c478bd9Sstevel@tonic-gate uintptr_t 9335aefb655Srie ld_reloc_plt(Rel_desc *rsp, Ofl_desc *ofl) 9347c478bd9Sstevel@tonic-gate { 9357c478bd9Sstevel@tonic-gate Sym_desc *sdp = rsp->rel_sym; 9367c478bd9Sstevel@tonic-gate 937ba2be530Sab196087 switch (ld_targ.t_m.m_mach) { 938ba2be530Sab196087 case EM_AMD64: 9397c478bd9Sstevel@tonic-gate /* 940ba2be530Sab196087 * AMD64 TLS code sequences do not use a unique TLS 941ba2be530Sab196087 * relocation to reference the __tls_get_addr() function call. 9427c478bd9Sstevel@tonic-gate */ 9437c478bd9Sstevel@tonic-gate if ((ofl->ofl_flags & FLG_OF_EXEC) && 944ba2be530Sab196087 (strcmp(sdp->sd_name, MSG_ORIG(MSG_SYM_TLSGETADDR_U)) == 945ba2be530Sab196087 0)) 9465aefb655Srie return (ld_add_actrel(FLG_REL_TLSFIX, rsp, ofl)); 947ba2be530Sab196087 break; 948ba2be530Sab196087 949ba2be530Sab196087 case EM_386: 9507c478bd9Sstevel@tonic-gate /* 951ba2be530Sab196087 * GNUC IA32 TLS code sequences do not use a unique TLS 952ba2be530Sab196087 * relocation to reference the ___tls_get_addr() function call. 9537c478bd9Sstevel@tonic-gate */ 9547c478bd9Sstevel@tonic-gate if ((ofl->ofl_flags & FLG_OF_EXEC) && 955ba2be530Sab196087 (strcmp(sdp->sd_name, MSG_ORIG(MSG_SYM_TLSGETADDR_UU)) == 956ba2be530Sab196087 0)) 9575aefb655Srie return (ld_add_actrel(FLG_REL_TLSFIX, rsp, ofl)); 958ba2be530Sab196087 break; 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate /* 9627c478bd9Sstevel@tonic-gate * if (not PLT yet assigned) 9637c478bd9Sstevel@tonic-gate * then 9647c478bd9Sstevel@tonic-gate * assign PLT index to symbol 9657c478bd9Sstevel@tonic-gate * build output JMP_SLOT relocation 9667c478bd9Sstevel@tonic-gate * fi 9677c478bd9Sstevel@tonic-gate */ 9687c478bd9Sstevel@tonic-gate if (sdp->sd_aux->sa_PLTndx == 0) { 9697c478bd9Sstevel@tonic-gate Word ortype = rsp->rel_rtype; 9707c478bd9Sstevel@tonic-gate 971ba2be530Sab196087 (*ld_targ.t_mr.mr_assign_plt_ndx)(sdp, ofl); 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate /* 974f441771bSRod Evans * If this symbol is binding to a lazy loadable, or deferred 975f441771bSRod Evans * dependency, then identify the symbol. 9767c478bd9Sstevel@tonic-gate */ 977f441771bSRod Evans if (sdp->sd_file) { 978f441771bSRod Evans if (sdp->sd_file->ifl_flags & FLG_IF_LAZYLD) 9797c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_LAZYLD; 980f441771bSRod Evans if (sdp->sd_file->ifl_flags & FLG_IF_DEFERRED) 981f441771bSRod Evans sdp->sd_flags |= FLG_SY_DEFERRED; 982f441771bSRod Evans } 9837c478bd9Sstevel@tonic-gate 984ba2be530Sab196087 rsp->rel_rtype = ld_targ.t_m.m_r_jmp_slot; 985ba2be530Sab196087 if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_PLT, rsp, ofl) == 986ba2be530Sab196087 S_ERROR) 9877c478bd9Sstevel@tonic-gate return (S_ERROR); 9887c478bd9Sstevel@tonic-gate rsp->rel_rtype = ortype; 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate /* 9927c478bd9Sstevel@tonic-gate * Perform relocation to PLT table entry. 9937c478bd9Sstevel@tonic-gate */ 9947c478bd9Sstevel@tonic-gate if ((ofl->ofl_flags & FLG_OF_SHAROBJ) && 9957c478bd9Sstevel@tonic-gate IS_ADD_RELATIVE(rsp->rel_rtype)) { 9967c478bd9Sstevel@tonic-gate Word ortype = rsp->rel_rtype; 9977c478bd9Sstevel@tonic-gate 998ba2be530Sab196087 rsp->rel_rtype = ld_targ.t_m.m_r_relative; 999ba2be530Sab196087 if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_ADVAL, rsp, ofl) == 1000ba2be530Sab196087 S_ERROR) 10017c478bd9Sstevel@tonic-gate return (S_ERROR); 10027c478bd9Sstevel@tonic-gate rsp->rel_rtype = ortype; 10037c478bd9Sstevel@tonic-gate return (1); 10047c478bd9Sstevel@tonic-gate } else 10055aefb655Srie return (ld_add_actrel(NULL, rsp, ofl)); 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate /* 100902938ba2SRod Evans * Round up to the next power of 2. Used to ensure section alignments that can 101002938ba2SRod Evans * be used for copy relocation symbol alignments are sane values. 101102938ba2SRod Evans */ 101202938ba2SRod Evans static Word 101302938ba2SRod Evans nlpo2(Word val) 101402938ba2SRod Evans { 101502938ba2SRod Evans val--; 101602938ba2SRod Evans val |= (val >> 1); 101702938ba2SRod Evans val |= (val >> 2); 101802938ba2SRod Evans val |= (val >> 4); 101902938ba2SRod Evans val |= (val >> 8); 102002938ba2SRod Evans val |= (val >> 16); 102102938ba2SRod Evans return (++val); 102202938ba2SRod Evans } 102302938ba2SRod Evans 102402938ba2SRod Evans /* 10257c478bd9Sstevel@tonic-gate * process GLOBAL undefined and ref_dyn_need symbols. 10267c478bd9Sstevel@tonic-gate */ 10275aefb655Srie static uintptr_t 10287c478bd9Sstevel@tonic-gate reloc_exec(Rel_desc *rsp, Ofl_desc *ofl) 10297c478bd9Sstevel@tonic-gate { 10307c478bd9Sstevel@tonic-gate Sym_desc *_sdp, *sdp = rsp->rel_sym; 10317c478bd9Sstevel@tonic-gate Sym_aux *sap = sdp->sd_aux; 10327c478bd9Sstevel@tonic-gate Sym *sym = sdp->sd_sym; 10337c478bd9Sstevel@tonic-gate Addr stval; 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate /* 10367c478bd9Sstevel@tonic-gate * Reference is to a function so simply create a plt entry for it. 10377c478bd9Sstevel@tonic-gate */ 10387c478bd9Sstevel@tonic-gate if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) 10395aefb655Srie return (ld_reloc_plt(rsp, ofl)); 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate /* 10427c478bd9Sstevel@tonic-gate * Catch absolutes - these may cause a text relocation. 10437c478bd9Sstevel@tonic-gate */ 10440bc07c75Srie if ((sdp->sd_flags & FLG_SY_SPECSEC) && (sym->st_shndx == SHN_ABS)) { 10457c478bd9Sstevel@tonic-gate if ((ofl->ofl_flags1 & FLG_OF1_ABSEXEC) == 0) 1046ba2be530Sab196087 return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl)); 10475aefb655Srie 10487c478bd9Sstevel@tonic-gate /* 10495aefb655Srie * If -zabsexec is set then promote the ABSOLUTE symbol to 10505aefb655Srie * current the current object and perform the relocation now. 10517c478bd9Sstevel@tonic-gate */ 10527c478bd9Sstevel@tonic-gate sdp->sd_ref = REF_REL_NEED; 10535aefb655Srie return (ld_add_actrel(NULL, rsp, ofl)); 10547c478bd9Sstevel@tonic-gate } 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate /* 10577c478bd9Sstevel@tonic-gate * If the relocation is against a writable section simply compute the 10587c478bd9Sstevel@tonic-gate * necessary output relocation. As an optimization, if the symbol has 10597c478bd9Sstevel@tonic-gate * already been transformed into a copy relocation then we can perform 10607c478bd9Sstevel@tonic-gate * the relocation directly (copy relocations should only be generated 10617c478bd9Sstevel@tonic-gate * for references from the text segment and these relocations are 10627c478bd9Sstevel@tonic-gate * normally carried out before we get to the data segment relocations). 10637c478bd9Sstevel@tonic-gate */ 10647c478bd9Sstevel@tonic-gate if ((ELF_ST_TYPE(sym->st_info) == STT_OBJECT) && 1065bf994817SAli Bahrami (RELAUX_GET_OSDESC(rsp)->os_shdr->sh_flags & SHF_WRITE)) { 10667c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_MVTOCOMM) 10675aefb655Srie return (ld_add_actrel(NULL, rsp, ofl)); 10687c478bd9Sstevel@tonic-gate else 1069ba2be530Sab196087 return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl)); 10707c478bd9Sstevel@tonic-gate } 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate /* 10735aefb655Srie * If the reference isn't to an object (normally because a .type 107402938ba2SRod Evans * directive wasn't defined in some assembler source), then apply 10755aefb655Srie * a generic relocation (this has a tendency to result in text 10765aefb655Srie * relocations). 10777c478bd9Sstevel@tonic-gate */ 10787c478bd9Sstevel@tonic-gate if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) { 1079de777a60Sab196087 Conv_inv_buf_t inv_buf; 1080de777a60Sab196087 1081*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_UNEXPSYM), 10825aefb655Srie conv_sym_info_type(sdp->sd_file->ifl_ehdr->e_machine, 1083de777a60Sab196087 ELF_ST_TYPE(sym->st_info), 0, &inv_buf), 10847c478bd9Sstevel@tonic-gate rsp->rel_isdesc->is_file->ifl_name, 1085bf994817SAli Bahrami ld_reloc_sym_name(rsp), sdp->sd_file->ifl_name); 1086ba2be530Sab196087 return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl)); 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate /* 10907c478bd9Sstevel@tonic-gate * Prepare for generating a copy relocation. 10917c478bd9Sstevel@tonic-gate * 109202938ba2SRod Evans * If this symbol is one of an alias pair, we need to ensure both 10937c478bd9Sstevel@tonic-gate * symbols become part of the output (the strong symbol will be used to 10947c478bd9Sstevel@tonic-gate * maintain the symbols state). And, if we did raise the precedence of 10957c478bd9Sstevel@tonic-gate * a symbol we need to check and see if this is a weak symbol. If it is 10967c478bd9Sstevel@tonic-gate * we want to use it's strong counter part. 10977c478bd9Sstevel@tonic-gate * 10987c478bd9Sstevel@tonic-gate * The results of this logic should be: 1099bf994817SAli Bahrami * ra_usym: assigned to strong 11007c478bd9Sstevel@tonic-gate * rel_sym: assigned to symbol to perform 11017c478bd9Sstevel@tonic-gate * copy_reloc against (weak or strong). 11027c478bd9Sstevel@tonic-gate */ 11037c478bd9Sstevel@tonic-gate if (sap->sa_linkndx) { 11047c478bd9Sstevel@tonic-gate _sdp = sdp->sd_file->ifl_oldndx[sap->sa_linkndx]; 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate if (_sdp->sd_ref < sdp->sd_ref) { 11077c478bd9Sstevel@tonic-gate _sdp->sd_ref = sdp->sd_ref; 11087c478bd9Sstevel@tonic-gate _sdp->sd_flags |= FLG_SY_REFRSD; 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate /* 11117c478bd9Sstevel@tonic-gate * As we're going to replicate a symbol from a shared 11127c478bd9Sstevel@tonic-gate * object, retain its correct binding status. 11137c478bd9Sstevel@tonic-gate */ 11147c478bd9Sstevel@tonic-gate if (ELF_ST_BIND(_sdp->sd_sym->st_info) == STB_GLOBAL) 11157c478bd9Sstevel@tonic-gate _sdp->sd_flags |= FLG_SY_GLOBREF; 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate } else if (_sdp->sd_ref > sdp->sd_ref) { 11187c478bd9Sstevel@tonic-gate sdp->sd_ref = _sdp->sd_ref; 11197c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_REFRSD; 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate /* 11227c478bd9Sstevel@tonic-gate * As we're going to replicate a symbol from a shared 11237c478bd9Sstevel@tonic-gate * object, retain its correct binding status. 11247c478bd9Sstevel@tonic-gate */ 11257c478bd9Sstevel@tonic-gate if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL) 11267c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_GLOBREF; 11277c478bd9Sstevel@tonic-gate } 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate /* 11307c478bd9Sstevel@tonic-gate * If this is a weak symbol then we want to move the strong 11317c478bd9Sstevel@tonic-gate * symbol into local .bss. If there is a copy_reloc to be 11327c478bd9Sstevel@tonic-gate * performed, that should still occur against the WEAK symbol. 11337c478bd9Sstevel@tonic-gate */ 1134bf994817SAli Bahrami if (((ELF_ST_BIND(sdp->sd_sym->st_info) == STB_WEAK) || 1135bf994817SAli Bahrami (sdp->sd_flags & FLG_SY_WEAKDEF)) && 1136bf994817SAli Bahrami !ld_reloc_set_aux_usym(ofl, rsp, _sdp)) 1137bf994817SAli Bahrami return (S_ERROR); 11387c478bd9Sstevel@tonic-gate } else 11397c478bd9Sstevel@tonic-gate _sdp = 0; 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate /* 11427c478bd9Sstevel@tonic-gate * If the reference is to an object then allocate space for the object 11437c478bd9Sstevel@tonic-gate * within the executables .bss. Relocations will now be performed from 11447c478bd9Sstevel@tonic-gate * this new location. If the original shared objects data is 11457c478bd9Sstevel@tonic-gate * initialized, then generate a copy relocation that will copy the data 11467c478bd9Sstevel@tonic-gate * to the executables .bss at runtime. 11477c478bd9Sstevel@tonic-gate */ 1148bf994817SAli Bahrami if (!(RELAUX_GET_USYM(rsp)->sd_flags & FLG_SY_MVTOCOMM)) { 114902938ba2SRod Evans Word rtype = rsp->rel_rtype, w2align; 115057ef7aa9SRod Evans Copy_rel cr; 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate /* 115302938ba2SRod Evans * Diagnose the original copy reference, as this symbol 115402938ba2SRod Evans * information will be overridden with the new destination. 115502938ba2SRod Evans */ 115602938ba2SRod Evans DBG_CALL(Dbg_syms_copy_reloc(ofl, sdp, 0)); 115702938ba2SRod Evans 115802938ba2SRod Evans /* 11597c478bd9Sstevel@tonic-gate * Indicate that the symbol(s) against which we're relocating 11607c478bd9Sstevel@tonic-gate * have been moved to the executables common. Also, insure that 11617c478bd9Sstevel@tonic-gate * the symbol(s) remain marked as global, as the shared object 11627c478bd9Sstevel@tonic-gate * from which they are copied must be able to relocate to the 11637c478bd9Sstevel@tonic-gate * new common location within the executable. 11647c478bd9Sstevel@tonic-gate * 11657c478bd9Sstevel@tonic-gate * Note that even though a new symbol has been generated in the 11667c478bd9Sstevel@tonic-gate * output files' .bss, the symbol must remain REF_DYN_NEED and 11677c478bd9Sstevel@tonic-gate * not be promoted to REF_REL_NEED. sym_validate() still needs 11687c478bd9Sstevel@tonic-gate * to carry out a number of checks against the symbols binding 11697c478bd9Sstevel@tonic-gate * that are triggered by the REF_DYN_NEED state. 11707c478bd9Sstevel@tonic-gate */ 1171635216b6SRod Evans sdp->sd_flags |= 1172635216b6SRod Evans (FLG_SY_MVTOCOMM | FLG_SY_DEFAULT | FLG_SY_EXPDEF); 1173635216b6SRod Evans sdp->sd_flags &= ~MSK_SY_LOCAL; 11747c478bd9Sstevel@tonic-gate sdp->sd_sym->st_other &= ~MSK_SYM_VISIBILITY; 11757c478bd9Sstevel@tonic-gate if (_sdp) { 1176635216b6SRod Evans _sdp->sd_flags |= (FLG_SY_MVTOCOMM | 1177635216b6SRod Evans FLG_SY_DEFAULT | FLG_SY_EXPDEF); 1178635216b6SRod Evans _sdp->sd_flags &= ~MSK_SY_LOCAL; 11797c478bd9Sstevel@tonic-gate _sdp->sd_sym->st_other &= ~MSK_SYM_VISIBILITY; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate /* 11827c478bd9Sstevel@tonic-gate * Make sure the symbol has a reference in case of any 11837c478bd9Sstevel@tonic-gate * error diagnostics against it (perhaps this belongs 11847c478bd9Sstevel@tonic-gate * to a version that isn't allowable for this build). 11857c478bd9Sstevel@tonic-gate * The resulting diagnostic (see sym_undef_entry()) 11867c478bd9Sstevel@tonic-gate * might seem a little bogus, as the symbol hasn't 11877c478bd9Sstevel@tonic-gate * really been referenced by this file, but has been 11887c478bd9Sstevel@tonic-gate * promoted as a consequence of its alias reference. 11897c478bd9Sstevel@tonic-gate */ 11907c478bd9Sstevel@tonic-gate if (!(_sdp->sd_aux->sa_rfile)) 11917c478bd9Sstevel@tonic-gate _sdp->sd_aux->sa_rfile = sdp->sd_aux->sa_rfile; 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate /* 119502938ba2SRod Evans * Assign the symbol to the bss. 11967c478bd9Sstevel@tonic-gate */ 1197bf994817SAli Bahrami _sdp = RELAUX_GET_USYM(rsp); 11987c478bd9Sstevel@tonic-gate stval = _sdp->sd_sym->st_value; 11995aefb655Srie if (ld_sym_copy(_sdp) == S_ERROR) 12007c478bd9Sstevel@tonic-gate return (S_ERROR); 12017c478bd9Sstevel@tonic-gate _sdp->sd_shndx = _sdp->sd_sym->st_shndx = SHN_COMMON; 12027c478bd9Sstevel@tonic-gate _sdp->sd_flags |= FLG_SY_SPECSEC; 120302938ba2SRod Evans 120402938ba2SRod Evans /* 120502938ba2SRod Evans * Ensure the symbol has sufficient alignment. The symbol 120602938ba2SRod Evans * definition has no alignment information that can be used, 120702938ba2SRod Evans * hence we use a heuristic. Historically, twice the native 120802938ba2SRod Evans * word alignment was sufficient for any data type, however, 120902938ba2SRod Evans * the developer may have requested larger alignments (pragma 121002938ba2SRod Evans * align). The most conservative approach is to use a power 121102938ba2SRod Evans * of two alignment, determined from the alignment of the 121202938ba2SRod Evans * section containing the symbol definition. Note that this 121302938ba2SRod Evans * can result in some bloat to the .bss as the not every item 121402938ba2SRod Evans * of copied data might need the section alignment. 121502938ba2SRod Evans * 121602938ba2SRod Evans * COMMON symbols carry their alignment requirements in the 121702938ba2SRod Evans * symbols st_value field. This alignment is applied to the 121802938ba2SRod Evans * symbol when it is eventually transformed into .bss. 121902938ba2SRod Evans */ 122002938ba2SRod Evans w2align = ld_targ.t_m.m_word_align * 2; 122102938ba2SRod Evans if (_sdp->sd_sym->st_size < w2align) 122202938ba2SRod Evans _sdp->sd_sym->st_value = ld_targ.t_m.m_word_align; 122302938ba2SRod Evans else { 122402938ba2SRod Evans Shdr *shdr; 122502938ba2SRod Evans Word isalign; 122602938ba2SRod Evans 122702938ba2SRod Evans if (_sdp->sd_isc && 122802938ba2SRod Evans ((shdr = _sdp->sd_isc->is_shdr) != NULL) && 122902938ba2SRod Evans ((isalign = shdr->sh_addralign) != 0)) 123002938ba2SRod Evans _sdp->sd_sym->st_value = nlpo2(isalign); 123102938ba2SRod Evans else 123202938ba2SRod Evans _sdp->sd_sym->st_value = w2align; 123302938ba2SRod Evans } 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate /* 123657ef7aa9SRod Evans * Whether or not the symbol references initialized data we 123757ef7aa9SRod Evans * generate a copy relocation - this differs from the past 123857ef7aa9SRod Evans * where we would not create the COPY_RELOC if we were binding 123957ef7aa9SRod Evans * against .bss. This is done for *two* reasons. 12407c478bd9Sstevel@tonic-gate * 124157ef7aa9SRod Evans * - If the symbol in the shared object changes to a 124257ef7aa9SRod Evans * initialized data - we need the COPY to pick it up. 124357ef7aa9SRod Evans * - Without the COPY RELOC we can't tell that the symbol 124457ef7aa9SRod Evans * from the COPY'd object has been moved and all bindings 124557ef7aa9SRod Evans * to it should bind here. 124657ef7aa9SRod Evans * 124757ef7aa9SRod Evans * Keep this symbol in the copy relocation list to check the 124857ef7aa9SRod Evans * validity later. 12497c478bd9Sstevel@tonic-gate */ 125057ef7aa9SRod Evans cr.c_sdp = _sdp; 125157ef7aa9SRod Evans cr.c_val = stval; 125257ef7aa9SRod Evans if (alist_append(&ofl->ofl_copyrels, &cr, sizeof (Copy_rel), 125357ef7aa9SRod Evans AL_CNT_OFL_COPYRELS) == NULL) 12547c478bd9Sstevel@tonic-gate return (S_ERROR); 12557c478bd9Sstevel@tonic-gate 1256ba2be530Sab196087 rsp->rel_rtype = ld_targ.t_m.m_r_copy; 1257ba2be530Sab196087 if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_BSS, rsp, ofl) == 1258ba2be530Sab196087 S_ERROR) 12597c478bd9Sstevel@tonic-gate return (S_ERROR); 12607c478bd9Sstevel@tonic-gate rsp->rel_rtype = rtype; 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate /* 126302938ba2SRod Evans * If this symbol is a protected symbol, warn the user. A 126402938ba2SRod Evans * potential issue exists as the copy relocated symbol within 126502938ba2SRod Evans * the executable can be visible to others, whereas the shared 126602938ba2SRod Evans * object that defined the original copy data symbol is pre- 126702938ba2SRod Evans * bound to reference it's own definition. Any modification 126802938ba2SRod Evans * of the symbols data could lead to inconsistencies for the 126902938ba2SRod Evans * various users. 12707c478bd9Sstevel@tonic-gate */ 1271de777a60Sab196087 if (_sdp->sd_flags & FLG_SY_PROT) { 1272de777a60Sab196087 Conv_inv_buf_t inv_buf; 1273de777a60Sab196087 1274*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_COPY), 12755aefb655Srie conv_reloc_type(_sdp->sd_file->ifl_ehdr->e_machine, 1276ba2be530Sab196087 ld_targ.t_m.m_r_copy, 0, &inv_buf), 1277ba2be530Sab196087 _sdp->sd_file->ifl_name, _sdp->sd_name); 1278de777a60Sab196087 } 127902938ba2SRod Evans DBG_CALL(Dbg_syms_copy_reloc(ofl, _sdp, 128002938ba2SRod Evans _sdp->sd_sym->st_value)); 12817c478bd9Sstevel@tonic-gate } 12825aefb655Srie return (ld_add_actrel(NULL, rsp, ofl)); 12837c478bd9Sstevel@tonic-gate } 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate /* 12867c478bd9Sstevel@tonic-gate * All relocations should have been handled by the other routines. This 12875aefb655Srie * routine is here as a catch all, if we do enter it we've goofed - but 1288635216b6SRod Evans * we'll try and do the best we can. 12897c478bd9Sstevel@tonic-gate */ 12905aefb655Srie static uintptr_t 12917c478bd9Sstevel@tonic-gate reloc_generic(Rel_desc *rsp, Ofl_desc *ofl) 12927c478bd9Sstevel@tonic-gate { 12935aefb655Srie Ifl_desc *ifl = rsp->rel_isdesc->is_file; 1294de777a60Sab196087 Conv_inv_buf_t inv_buf; 12957c478bd9Sstevel@tonic-gate 1296*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_UNEXPREL), 1297de777a60Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, rsp->rel_rtype, 1298bf994817SAli Bahrami 0, &inv_buf), ifl->ifl_name, ld_reloc_sym_name(rsp)); 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate /* 13017c478bd9Sstevel@tonic-gate * If building a shared object then put the relocation off 13027c478bd9Sstevel@tonic-gate * until runtime. 13037c478bd9Sstevel@tonic-gate */ 13045aefb655Srie if (ofl->ofl_flags & FLG_OF_SHAROBJ) 1305ba2be530Sab196087 return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl)); 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate /* 13087c478bd9Sstevel@tonic-gate * Otherwise process relocation now. 13097c478bd9Sstevel@tonic-gate */ 13105aefb655Srie return (ld_add_actrel(NULL, rsp, ofl)); 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate 1313141040e8Srie /* 1314141040e8Srie * Process relocations when building a relocatable object. Typically, there 1315141040e8Srie * aren't many relocations that can be caught at this point, most are simply 1316141040e8Srie * passed through to the output relocatable object. 1317141040e8Srie */ 1318141040e8Srie static uintptr_t 1319141040e8Srie reloc_relobj(Boolean local, Rel_desc *rsp, Ofl_desc *ofl) 1320141040e8Srie { 1321141040e8Srie Word rtype = rsp->rel_rtype; 1322141040e8Srie Sym_desc *sdp = rsp->rel_sym; 1323141040e8Srie Is_desc *isp = rsp->rel_isdesc; 1324141040e8Srie Word oflags = NULL; 1325141040e8Srie 1326141040e8Srie /* 1327141040e8Srie * Determine if we can do any relocations at this point. We can if: 1328141040e8Srie * 1329141040e8Srie * this is local_symbol and a non-GOT relocation, and 1330141040e8Srie * the relocation is pc-relative, and 1331141040e8Srie * the relocation is against a symbol in same section 1332141040e8Srie */ 1333ba2be530Sab196087 if (local && !IS_GOT_RELATIVE(rtype) && 1334ba2be530Sab196087 !IS_GOT_BASED(rtype) && !IS_GOT_PC(rtype) && 1335ba2be530Sab196087 IS_PC_RELATIVE(rtype) && 1336141040e8Srie ((sdp->sd_isc) && (sdp->sd_isc->is_osdesc == isp->is_osdesc))) 13375aefb655Srie return (ld_add_actrel(NULL, rsp, ofl)); 1338141040e8Srie 1339141040e8Srie /* 1340141040e8Srie * If -zredlocsym is in effect, translate all local symbol relocations 134160758829Srie * to be against section symbols, since section symbols are the only 134260758829Srie * local symbols which will be added to the .symtab. 1343141040e8Srie */ 134444bac77bSrie if (local && (((ofl->ofl_flags & FLG_OF_REDLSYM) && 1345141040e8Srie (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL)) || 1346635216b6SRod Evans ((sdp->sd_flags & FLG_SY_ELIM) && 1347141040e8Srie (ofl->ofl_flags & FLG_OF_PROCRED)))) { 1348141040e8Srie /* 1349141040e8Srie * But if this is PIC code, don't allow it for now. 1350141040e8Srie */ 1351141040e8Srie if (IS_GOT_RELATIVE(rsp->rel_rtype)) { 1352141040e8Srie Ifl_desc *ifl = rsp->rel_isdesc->is_file; 1353de777a60Sab196087 Conv_inv_buf_t inv_buf; 1354141040e8Srie 1355*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_PICREDLOC), 1356bf994817SAli Bahrami ld_reloc_sym_name(rsp), ifl->ifl_name, 13575aefb655Srie conv_reloc_type(ifl->ifl_ehdr->e_machine, 1358de777a60Sab196087 rsp->rel_rtype, 0, &inv_buf)); 1359141040e8Srie return (S_ERROR); 1360141040e8Srie } 1361141040e8Srie 1362141040e8Srie /* 1363141040e8Srie * Indicate that this relocation should be processed the same 1364ba2be530Sab196087 * as a section symbol. For RELA, indicate that the addend 1365ba2be530Sab196087 * also needs to be applied to this relocation. 1366141040e8Srie */ 1367ba2be530Sab196087 if ((rsp->rel_flags & FLG_REL_RELA) == FLG_REL_RELA) 1368141040e8Srie oflags = FLG_REL_SCNNDX | FLG_REL_ADVAL; 1369ba2be530Sab196087 else 1370ba2be530Sab196087 oflags = FLG_REL_SCNNDX; 1371141040e8Srie } 1372141040e8Srie 1373ba2be530Sab196087 if ((rsp->rel_flags & FLG_REL_RELA) == 0) { 1374141040e8Srie /* 1375ba2be530Sab196087 * Intel (Rel) relocations do not contain an addend. Any 1376ba2be530Sab196087 * addend is contained within the file at the location 1377ba2be530Sab196087 * identified by the relocation offset. Therefore, if we're 1378ba2be530Sab196087 * processing a section symbol, or a -zredlocsym relocation 1379ba2be530Sab196087 * (that basically transforms a local symbol reference into 1380ba2be530Sab196087 * a section reference), perform an active relocation to 1381141040e8Srie * propagate any addend. 1382141040e8Srie */ 1383141040e8Srie if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) || 1384141040e8Srie (oflags == FLG_REL_SCNNDX)) 13855aefb655Srie if (ld_add_actrel(NULL, rsp, ofl) == S_ERROR) 1386141040e8Srie return (S_ERROR); 1387ba2be530Sab196087 } 1388ba2be530Sab196087 return ((*ld_targ.t_mr.mr_add_outrel)(oflags, rsp, ofl)); 1389141040e8Srie } 13907c478bd9Sstevel@tonic-gate 1391d326b23bSrie /* 1392d326b23bSrie * Perform any generic TLS validations before passing control to machine 1393d326b23bSrie * specific routines. At this point we know we are dealing with an executable 1394d326b23bSrie * or shared object - relocatable objects have already been processed. 1395d326b23bSrie */ 1396d326b23bSrie static uintptr_t 1397d326b23bSrie reloc_TLS(Boolean local, Rel_desc *rsp, Ofl_desc *ofl) 1398d326b23bSrie { 13991d9df23bSab196087 Word rtype = rsp->rel_rtype; 14001d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags; 1401d326b23bSrie Ifl_desc *ifl = rsp->rel_isdesc->is_file; 1402d326b23bSrie Half mach = ifl->ifl_ehdr->e_machine; 1403d326b23bSrie Sym_desc *sdp = rsp->rel_sym; 1404d326b23bSrie unsigned char type; 1405de777a60Sab196087 Conv_inv_buf_t inv_buf1, inv_buf2; 1406d326b23bSrie 1407d326b23bSrie /* 1408d326b23bSrie * All TLS relocations are illegal in a static executable. 1409d326b23bSrie */ 1410635216b6SRod Evans if (OFL_IS_STATIC_EXEC(ofl)) { 1411*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_TLSSTAT), 1412de777a60Sab196087 conv_reloc_type(mach, rtype, 0, &inv_buf1), ifl->ifl_name, 1413bf994817SAli Bahrami ld_reloc_sym_name(rsp)); 1414d326b23bSrie return (S_ERROR); 1415d326b23bSrie } 1416d326b23bSrie 1417d326b23bSrie /* 1418d326b23bSrie * Any TLS relocation must be against a STT_TLS symbol, all others 1419d326b23bSrie * are illegal. 1420d326b23bSrie */ 1421d326b23bSrie if ((type = ELF_ST_TYPE(sdp->sd_sym->st_info)) != STT_TLS) { 1422*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_TLSBADSYM), 1423de777a60Sab196087 conv_reloc_type(mach, rtype, 0, &inv_buf1), ifl->ifl_name, 1424bf994817SAli Bahrami ld_reloc_sym_name(rsp), 1425de777a60Sab196087 conv_sym_info_type(mach, type, 0, &inv_buf2)); 1426d326b23bSrie return (S_ERROR); 1427d326b23bSrie } 1428d326b23bSrie 1429d326b23bSrie /* 1430d326b23bSrie * A dynamic executable can not use the LD or LE reference models to 1431d326b23bSrie * reference an external symbol. A shared object can not use the LD 1432d326b23bSrie * reference model to reference an external symbol. 1433d326b23bSrie */ 1434d326b23bSrie if (!local && (IS_TLS_LD(rtype) || 1435d326b23bSrie ((flags & FLG_OF_EXEC) && IS_TLS_LE(rtype)))) { 1436*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_TLSBND), 1437de777a60Sab196087 conv_reloc_type(mach, rtype, 0, &inv_buf1), ifl->ifl_name, 1438bf994817SAli Bahrami ld_reloc_sym_name(rsp), sdp->sd_file->ifl_name); 1439d326b23bSrie return (S_ERROR); 1440d326b23bSrie } 1441d326b23bSrie 1442d326b23bSrie /* 1443d326b23bSrie * The TLS LE model is only allowed for dynamic executables. The TLS IE 1444d326b23bSrie * model is allowed for shared objects, but this model has restrictions. 1445d326b23bSrie * This model can only be used freely in dependencies that are loaded 1446d326b23bSrie * immediately as part of process initialization. However, during the 1447d326b23bSrie * initial runtime handshake with libc that establishes the thread 1448d326b23bSrie * pointer, a small backup TLS reservation is created. This area can 1449d326b23bSrie * be used by objects that are loaded after threads are initialized. 1450d326b23bSrie * However, this area is limited in size and may have already been 1451d326b23bSrie * used. This area is intended for specialized applications, and does 1452d326b23bSrie * not provide the degree of flexibility dynamic TLS can offer. Under 1453d326b23bSrie * -z verbose indicate this restriction to the user. 1454d326b23bSrie */ 1455d326b23bSrie if ((flags & FLG_OF_EXEC) == 0) { 1456d326b23bSrie if (IS_TLS_LE(rtype)) { 1457*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_TLSLE), 1458de777a60Sab196087 conv_reloc_type(mach, rtype, 0, &inv_buf1), 1459bf994817SAli Bahrami ifl->ifl_name, ld_reloc_sym_name(rsp)); 1460d326b23bSrie return (S_ERROR); 1461d326b23bSrie 1462ba2be530Sab196087 } else if ((IS_TLS_IE(rtype)) && 1463ba2be530Sab196087 (flags & FLG_OF_VERBOSE)) { 1464*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_TLSIE), 1465de777a60Sab196087 conv_reloc_type(mach, rtype, 0, &inv_buf1), 1466bf994817SAli Bahrami ifl->ifl_name, ld_reloc_sym_name(rsp)); 1467d326b23bSrie } 1468d326b23bSrie } 1469d326b23bSrie 1470ba2be530Sab196087 return ((*ld_targ.t_mr.mr_reloc_TLS)(local, rsp, ofl)); 1471d326b23bSrie } 1472d326b23bSrie 14737c478bd9Sstevel@tonic-gate uintptr_t 14745aefb655Srie ld_process_sym_reloc(Ofl_desc *ofl, Rel_desc *reld, Rel *reloc, Is_desc *isp, 1475e23c41c9SAli Bahrami const char *isname, Word isscnndx) 14767c478bd9Sstevel@tonic-gate { 14777c478bd9Sstevel@tonic-gate Word rtype = reld->rel_rtype; 14781d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags; 14797c478bd9Sstevel@tonic-gate Sym_desc *sdp = reld->rel_sym; 14807c478bd9Sstevel@tonic-gate Sym_aux *sap; 14817c478bd9Sstevel@tonic-gate Boolean local; 1482de777a60Sab196087 Conv_inv_buf_t inv_buf; 14837c478bd9Sstevel@tonic-gate 1484ba2be530Sab196087 DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, ld_targ.t_m.m_mach, 1485e23c41c9SAli Bahrami ld_targ.t_m.m_rel_sht_type, (void *)reloc, isname, isscnndx, 1486bf994817SAli Bahrami ld_reloc_sym_name(reld))); 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate /* 14897c478bd9Sstevel@tonic-gate * Indicate this symbol is being used for relocation and therefore must 14907c478bd9Sstevel@tonic-gate * have its output address updated accordingly (refer to update_osym()). 14917c478bd9Sstevel@tonic-gate */ 14927c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_UPREQD; 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate /* 14957c478bd9Sstevel@tonic-gate * Indicate the section this symbol is defined in has been referenced, 14967c478bd9Sstevel@tonic-gate * therefor it *is not* a candidate for elimination. 14977c478bd9Sstevel@tonic-gate */ 14987c478bd9Sstevel@tonic-gate if (sdp->sd_isc) { 14997c478bd9Sstevel@tonic-gate sdp->sd_isc->is_flags |= FLG_IS_SECTREF; 15007c478bd9Sstevel@tonic-gate sdp->sd_isc->is_file->ifl_flags |= FLG_IF_FILEREF; 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate 1503bf994817SAli Bahrami if (!ld_reloc_set_aux_usym(ofl, reld, sdp)) 1504bf994817SAli Bahrami return (S_ERROR); 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate /* 15077c478bd9Sstevel@tonic-gate * Determine if this symbol is actually an alias to another symbol. If 1508bf994817SAli Bahrami * so, and the alias is not REF_DYN_SEEN, set ra_usym to point to the 15097c478bd9Sstevel@tonic-gate * weak symbols strong counter-part. The one exception is if the 15107c478bd9Sstevel@tonic-gate * FLG_SY_MVTOCOMM flag is set on the weak symbol. If this is the case, 15117c478bd9Sstevel@tonic-gate * the strong is only here because of its promotion, and the weak symbol 15127c478bd9Sstevel@tonic-gate * should still be used for the relocation reference (see reloc_exec()). 15137c478bd9Sstevel@tonic-gate */ 15147c478bd9Sstevel@tonic-gate sap = sdp->sd_aux; 15157c478bd9Sstevel@tonic-gate if (sap && sap->sa_linkndx && 15167c478bd9Sstevel@tonic-gate ((ELF_ST_BIND(sdp->sd_sym->st_info) == STB_WEAK) || 15177c478bd9Sstevel@tonic-gate (sdp->sd_flags & FLG_SY_WEAKDEF)) && 15187c478bd9Sstevel@tonic-gate (!(sdp->sd_flags & FLG_SY_MVTOCOMM))) { 15197c478bd9Sstevel@tonic-gate Sym_desc *_sdp; 15207c478bd9Sstevel@tonic-gate 15217c478bd9Sstevel@tonic-gate _sdp = sdp->sd_file->ifl_oldndx[sap->sa_linkndx]; 1522bf994817SAli Bahrami if ((_sdp->sd_ref != REF_DYN_SEEN) && 1523bf994817SAli Bahrami !ld_reloc_set_aux_usym(ofl, reld, _sdp)) 1524bf994817SAli Bahrami return (S_ERROR); 15257c478bd9Sstevel@tonic-gate } 15267c478bd9Sstevel@tonic-gate 15277c478bd9Sstevel@tonic-gate /* 15287c478bd9Sstevel@tonic-gate * Determine whether this symbol should be bound locally or not. 15299a411307Srie * Symbols are bound locally if one of the following is true: 15307c478bd9Sstevel@tonic-gate * 1531635216b6SRod Evans * - the symbol is of type STB_LOCAL. 15327c478bd9Sstevel@tonic-gate * 1533635216b6SRod Evans * - the output image is not a relocatable object and the relocation 15349a411307Srie * is relative to the .got. 15357c478bd9Sstevel@tonic-gate * 1536635216b6SRod Evans * - the section being relocated is of type SHT_SUNW_dof. These 15379a411307Srie * sections must be bound to the functions in the containing 15389a411307Srie * object and can not be interposed upon. 15397c478bd9Sstevel@tonic-gate * 1540635216b6SRod Evans * - the symbol has been reduced (scoped to a local or symbolic) and 15419a411307Srie * reductions are being processed. 15427c478bd9Sstevel@tonic-gate * 1543635216b6SRod Evans * - the -Bsymbolic flag is in use when building a shared object, 15449a411307Srie * and the symbol hasn't explicitly been defined as nodirect. 15457c478bd9Sstevel@tonic-gate * 1546635216b6SRod Evans * - an executable (fixed address) is being created, and the symbol 15479a411307Srie * is defined in the executable. 15487c478bd9Sstevel@tonic-gate * 1549635216b6SRod Evans * - the relocation is against a segment which will not be loaded 15509a411307Srie * into memory. In this case, the relocation must be resolved 15519a411307Srie * now, as ld.so.1 can not process relocations against unmapped 15529a411307Srie * segments. 15537c478bd9Sstevel@tonic-gate */ 15547c478bd9Sstevel@tonic-gate local = FALSE; 15557c478bd9Sstevel@tonic-gate if (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL) { 15567c478bd9Sstevel@tonic-gate local = TRUE; 15577c478bd9Sstevel@tonic-gate } else if (!(reld->rel_flags & FLG_REL_LOAD)) { 15587c478bd9Sstevel@tonic-gate local = TRUE; 15590bc07c75Srie } else if (sdp->sd_sym->st_shndx != SHN_UNDEF) { 15607c478bd9Sstevel@tonic-gate if (reld->rel_isdesc && 15617c478bd9Sstevel@tonic-gate reld->rel_isdesc->is_shdr->sh_type == SHT_SUNW_dof) { 15627c478bd9Sstevel@tonic-gate local = TRUE; 15637c478bd9Sstevel@tonic-gate } else if (!(flags & FLG_OF_RELOBJ) && 1564635216b6SRod Evans (IS_LOCALBND(rtype) || IS_SEG_RELATIVE(rtype))) { 15657c478bd9Sstevel@tonic-gate local = TRUE; 156608278a5eSRod Evans } else if ((sdp->sd_ref == REF_REL_NEED) && 156708278a5eSRod Evans ((sdp->sd_flags & FLG_SY_CAP) == 0)) { 15689a411307Srie /* 15699a411307Srie * Global symbols may have been individually reduced in 15709a411307Srie * scope. If the whole object is to be self contained, 15719a411307Srie * such as when generating an executable or a symbolic 15729a411307Srie * shared object, make sure all relocation symbol 15739a411307Srie * references (sections too) are treated locally. Note, 15749a411307Srie * explicit no-direct symbols should not be bound to 15759a411307Srie * locally. 15769a411307Srie */ 1577635216b6SRod Evans if ((sdp->sd_flags & 1578635216b6SRod Evans (FLG_SY_HIDDEN | FLG_SY_PROTECT))) 15797c478bd9Sstevel@tonic-gate local = TRUE; 15809a411307Srie else if ((flags & FLG_OF_EXEC) || 15819a411307Srie ((flags & FLG_OF_SYMBOLIC) && 1582635216b6SRod Evans ((sdp->sd_flags & FLG_SY_NDIR) == 0))) { 15837c478bd9Sstevel@tonic-gate local = TRUE; 15847c478bd9Sstevel@tonic-gate } 15857c478bd9Sstevel@tonic-gate } 1586635216b6SRod Evans } 15877c478bd9Sstevel@tonic-gate 15887c478bd9Sstevel@tonic-gate /* 15897c478bd9Sstevel@tonic-gate * If this is a PC_RELATIVE relocation, the relocation could be 15907c478bd9Sstevel@tonic-gate * compromised if the relocated address is later used as a copy 15917c478bd9Sstevel@tonic-gate * relocated symbol (PSARC 1999/636, bugid 4187211). Scan the input 15927c478bd9Sstevel@tonic-gate * files symbol table to cross reference this relocation offset. 15937c478bd9Sstevel@tonic-gate */ 1594ba2be530Sab196087 if ((ofl->ofl_flags & FLG_OF_SHAROBJ) && 1595ba2be530Sab196087 IS_PC_RELATIVE(rtype) && 1596ba2be530Sab196087 (IS_GOT_PC(rtype) == 0) && 1597ba2be530Sab196087 (IS_PLT(rtype) == 0)) { 15987c478bd9Sstevel@tonic-gate if (disp_inspect(ofl, reld, local) == S_ERROR) 15997c478bd9Sstevel@tonic-gate return (S_ERROR); 16007c478bd9Sstevel@tonic-gate } 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate /* 16037c478bd9Sstevel@tonic-gate * GOT based relocations must bind to the object being built - since 16047c478bd9Sstevel@tonic-gate * they are relevant to the current GOT. If not building a relocatable 16057c478bd9Sstevel@tonic-gate * object - give a appropriate error message. 16067c478bd9Sstevel@tonic-gate */ 1607ba2be530Sab196087 if (!local && !(flags & FLG_OF_RELOBJ) && 1608ba2be530Sab196087 IS_GOT_BASED(rtype)) { 16095aefb655Srie Ifl_desc *ifl = reld->rel_isdesc->is_file; 16105aefb655Srie 1611*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_BADGOTBASED), 1612de777a60Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype, 1613de777a60Sab196087 0, &inv_buf), ifl->ifl_name, demangle(sdp->sd_name)); 16147c478bd9Sstevel@tonic-gate return (S_ERROR); 16157c478bd9Sstevel@tonic-gate } 16167c478bd9Sstevel@tonic-gate 16177c478bd9Sstevel@tonic-gate /* 16187c478bd9Sstevel@tonic-gate * TLS symbols can only have TLS relocations. 16197c478bd9Sstevel@tonic-gate */ 1620d326b23bSrie if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_TLS) && 1621d326b23bSrie (IS_TLS_INS(rtype) == 0)) { 16227c478bd9Sstevel@tonic-gate /* 16237c478bd9Sstevel@tonic-gate * The above test is relaxed if the target section is 16247c478bd9Sstevel@tonic-gate * non-allocable. 16257c478bd9Sstevel@tonic-gate */ 1626bf994817SAli Bahrami if (RELAUX_GET_OSDESC(reld)->os_shdr->sh_flags & SHF_ALLOC) { 16275aefb655Srie Ifl_desc *ifl = reld->rel_isdesc->is_file; 16285aefb655Srie 1629*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_BADTLS), 1630c13de8f6Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, 1631de777a60Sab196087 rtype, 0, &inv_buf), ifl->ifl_name, 1632de777a60Sab196087 demangle(sdp->sd_name)); 16337c478bd9Sstevel@tonic-gate return (S_ERROR); 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate } 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate /* 16387c478bd9Sstevel@tonic-gate * Select the relocation to perform. 16397c478bd9Sstevel@tonic-gate */ 1640ba2be530Sab196087 if (IS_REGISTER(rtype)) { 1641ba2be530Sab196087 if (ld_targ.t_mr.mr_reloc_register == NULL) { 1642*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_NOREG)); 1643ba2be530Sab196087 return (S_ERROR); 1644ba2be530Sab196087 } 1645ba2be530Sab196087 return ((*ld_targ.t_mr.mr_reloc_register)(reld, isp, ofl)); 1646ba2be530Sab196087 } 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate if (flags & FLG_OF_RELOBJ) 16497c478bd9Sstevel@tonic-gate return (reloc_relobj(local, reld, ofl)); 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate if (IS_TLS_INS(rtype)) 1652d326b23bSrie return (reloc_TLS(local, reld, ofl)); 16537c478bd9Sstevel@tonic-gate 1654ba2be530Sab196087 if (IS_GOT_OPINS(rtype)) { 1655ba2be530Sab196087 if (ld_targ.t_mr.mr_reloc_GOTOP == NULL) { 1656ba2be530Sab196087 assert(0); 1657ba2be530Sab196087 return (S_ERROR); 1658ba2be530Sab196087 } 1659ba2be530Sab196087 return ((*ld_targ.t_mr.mr_reloc_GOTOP)(local, reld, ofl)); 1660ba2be530Sab196087 } 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate if (IS_GOT_RELATIVE(rtype)) 16635aefb655Srie return (ld_reloc_GOT_relative(local, reld, ofl)); 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate if (local) 1666ba2be530Sab196087 return ((*ld_targ.t_mr.mr_reloc_local)(reld, ofl)); 16677c478bd9Sstevel@tonic-gate 166808278a5eSRod Evans if ((IS_PLT(rtype) || ((sdp->sd_flags & FLG_SY_CAP) && 166908278a5eSRod Evans (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_FUNC))) && 167008278a5eSRod Evans ((flags & FLG_OF_BFLAG) == 0)) 16715aefb655Srie return (ld_reloc_plt(reld, ofl)); 16727c478bd9Sstevel@tonic-gate 16737c478bd9Sstevel@tonic-gate if ((sdp->sd_ref == REF_REL_NEED) || 16747c478bd9Sstevel@tonic-gate (flags & FLG_OF_BFLAG) || (flags & FLG_OF_SHAROBJ) || 16757c478bd9Sstevel@tonic-gate (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_NOTYPE)) 1676ba2be530Sab196087 return ((*ld_targ.t_mr.mr_add_outrel)(NULL, reld, ofl)); 16777c478bd9Sstevel@tonic-gate 16787c478bd9Sstevel@tonic-gate if (sdp->sd_ref == REF_DYN_NEED) 16797c478bd9Sstevel@tonic-gate return (reloc_exec(reld, ofl)); 16807c478bd9Sstevel@tonic-gate 16817c478bd9Sstevel@tonic-gate /* 16827c478bd9Sstevel@tonic-gate * IS_NOT_REL(rtype) 16837c478bd9Sstevel@tonic-gate */ 16847c478bd9Sstevel@tonic-gate return (reloc_generic(reld, ofl)); 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate /* 16880e233487SRod Evans * Given a relocation that references a local symbol from a discarded COMDAT 16890e233487SRod Evans * section, replace the symbol with the corresponding symbol from the section 16900e233487SRod Evans * that was kept. 1691d2ef9fe9Sab196087 * 1692d2ef9fe9Sab196087 * entry: 1693d2ef9fe9Sab196087 * reld - Relocation 16946b3ba5bdSAli Bahrami * sdp - Symbol to be replaced. Must be a local symbol (STB_LOCAL). 169540e53e87SAli Bahrami * reject - Address of variable to receive rejection code 169640e53e87SAli Bahrami * if no replacement symbol is found. 1697d2ef9fe9Sab196087 * 1698d2ef9fe9Sab196087 * exit: 1699d2ef9fe9Sab196087 * Returns address of replacement symbol descriptor if one was 17006b3ba5bdSAli Bahrami * found, and NULL otherwise. The result is also cached in 17016b3ba5bdSAli Bahrami * ofl->ofl_sr_cache as an optimization to speed following calls 17026b3ba5bdSAli Bahrami * for the same value of sdp. 1703d2ef9fe9Sab196087 * 170440e53e87SAli Bahrami * On success (non-NULL result), *reject is set to RLXREL_REJ_NONE. 170540e53e87SAli Bahrami * On failure (NULL result), *reject is filled in with a code 170640e53e87SAli Bahrami * describing the underlying reason. 170740e53e87SAli Bahrami * 1708d2ef9fe9Sab196087 * note: 17090e233487SRod Evans * The word "COMDAT" is used to refer to actual COMDAT sections, COMDAT 17100e233487SRod Evans * groups tied together with an SHF_GROUP section, and .gnu.linkonce 17110e233487SRod Evans * sections which provide a simplified COMDAT requirement. COMDAT 17120e233487SRod Evans * sections are identified with the FLG_IS_COMDAT section flag. 1713d2ef9fe9Sab196087 * 1714d2ef9fe9Sab196087 * In principle, this sort of sloppy relocation remapping is 1715d2ef9fe9Sab196087 * a questionable practice. All self-referential sections should 1716d2ef9fe9Sab196087 * be in a common SHF_GROUP so that they are all kept or removed 1717d2ef9fe9Sab196087 * together. The problem is that there is no way to ensure that the 1718d2ef9fe9Sab196087 * two sections are similar enough that the replacement section will 1719d2ef9fe9Sab196087 * really supply the correct information. However, we see a couple of 1720d2ef9fe9Sab196087 * situations where it is useful to do this: (1) Older Sun C compilers 1721d2ef9fe9Sab196087 * generated DWARF sections that would refer to one of the COMDAT 17226b3ba5bdSAli Bahrami * sections, and (2) gcc, when its GNU linkonce COMDAT feature is enabled. 1723d2ef9fe9Sab196087 * It turns out that the GNU ld does these sloppy remappings. 1724d2ef9fe9Sab196087 * 1725d2ef9fe9Sab196087 * The GNU ld takes an approach that hard wires special section 1726d2ef9fe9Sab196087 * names and treats them specially. We avoid that practice and 1727d2ef9fe9Sab196087 * try to get the necessary work done relying only on the ELF 1728d2ef9fe9Sab196087 * attributes of the sections and symbols involved. This means 1729d2ef9fe9Sab196087 * that our heuristic is somewhat different than theirs, but the 1730d2ef9fe9Sab196087 * end result is close enough to solve the same problem. 1731d2ef9fe9Sab196087 * 17326b3ba5bdSAli Bahrami * gcc is in the process of converting to SHF_GROUP. This will 17336b3ba5bdSAli Bahrami * eventually phase out the need for sloppy relocations, and 17340e233487SRod Evans * then this logic won't be needed. In the meantime, relaxed relocation 17350e233487SRod Evans * processing allows us to interoperate. 1736d2ef9fe9Sab196087 */ 1737d2ef9fe9Sab196087 static Sym_desc * 173840e53e87SAli Bahrami sloppy_comdat_reloc(Ofl_desc *ofl, Rel_desc *reld, Sym_desc *sdp, 173940e53e87SAli Bahrami Rlxrel_rej *reject) 1740d2ef9fe9Sab196087 { 1741d2ef9fe9Sab196087 Is_desc *rep_isp; 17426b3ba5bdSAli Bahrami Sym *sym, *rep_sym; 17436b3ba5bdSAli Bahrami Is_desc *isp; 17446b3ba5bdSAli Bahrami Ifl_desc *ifl; 1745de777a60Sab196087 Conv_inv_buf_t inv_buf; 17466b3ba5bdSAli Bahrami Word scnndx, symscnt; 17476b3ba5bdSAli Bahrami Sym_desc **oldndx, *rep_sdp; 174840e53e87SAli Bahrami const char *is_name; 174940e53e87SAli Bahrami 175040e53e87SAli Bahrami 175140e53e87SAli Bahrami /* 175240e53e87SAli Bahrami * Sloppy relocations are never applied to .eh_frame or 175340e53e87SAli Bahrami * .gcc_except_table sections. The entries in these sections 175440e53e87SAli Bahrami * for discarded sections are better left uninitialized. 175540e53e87SAli Bahrami * 175640e53e87SAli Bahrami * We match these sections by name, because on most platforms they 175740e53e87SAli Bahrami * are SHT_PROGBITS, and cannot be identified otherwise. On amd64 175840e53e87SAli Bahrami * architectures, .eh_frame is SHT_AMD64_UNWIND, but that is ambiguous 175940e53e87SAli Bahrami * (.eh_frame_hdr is also SHT_AMD64_UNWIND), so we still match it by 176040e53e87SAli Bahrami * name. 176140e53e87SAli Bahrami */ 176240e53e87SAli Bahrami is_name = reld->rel_isdesc->is_name; 176340e53e87SAli Bahrami if (((is_name[1] == 'e') && 176440e53e87SAli Bahrami (strcmp(is_name, MSG_ORIG(MSG_SCN_EHFRAME)) == 0)) || 176540e53e87SAli Bahrami ((is_name[1] == 'g') && 176640e53e87SAli Bahrami (strcmp(is_name, MSG_ORIG(MSG_SCN_GCC_X_TBL)) == 0))) { 176740e53e87SAli Bahrami *reject = RLXREL_REJ_TARGET; 176840e53e87SAli Bahrami return (NULL); 176940e53e87SAli Bahrami } 1770d2ef9fe9Sab196087 1771d2ef9fe9Sab196087 /* 17726b3ba5bdSAli Bahrami * If we looked up the same symbol on the previous call, we can 17736b3ba5bdSAli Bahrami * return the cached value. 17746b3ba5bdSAli Bahrami */ 177540e53e87SAli Bahrami if (sdp == ofl->ofl_sr_cache.sr_osdp) { 177640e53e87SAli Bahrami *reject = ofl->ofl_sr_cache.sr_rej; 17776b3ba5bdSAli Bahrami return (ofl->ofl_sr_cache.sr_rsdp); 177840e53e87SAli Bahrami } 17796b3ba5bdSAli Bahrami 17806b3ba5bdSAli Bahrami ofl->ofl_sr_cache.sr_osdp = sdp; 17816b3ba5bdSAli Bahrami sym = sdp->sd_sym; 17826b3ba5bdSAli Bahrami isp = sdp->sd_isc; 17836b3ba5bdSAli Bahrami ifl = sdp->sd_file; 17846b3ba5bdSAli Bahrami 17856b3ba5bdSAli Bahrami /* 17866b3ba5bdSAli Bahrami * When a COMDAT section is discarded in favor of another COMDAT 17876b3ba5bdSAli Bahrami * section, the replacement is recorded in its section descriptor 17886b3ba5bdSAli Bahrami * (is_comdatkeep). We must validate the replacement before using 17896b3ba5bdSAli Bahrami * it. The replacement section must: 1790d2ef9fe9Sab196087 * - Not have been discarded 1791ca4eed8bSAli Bahrami * - Have the same size (*) 17920e233487SRod Evans * - Have the same section type 1793d2ef9fe9Sab196087 * - Have the same SHF_GROUP flag setting (either on or off) 1794d2ef9fe9Sab196087 * - Must be a COMDAT section of one form or the other. 1795ca4eed8bSAli Bahrami * 1796ca4eed8bSAli Bahrami * (*) One might imagine that the replacement section could be 1797ca4eed8bSAli Bahrami * larger than the original, rather than the exact size. However, 1798ca4eed8bSAli Bahrami * we have verified that this is the same policy used by the GNU 1799ca4eed8bSAli Bahrami * ld. If the sections are not the same size, the chance of them 1800ca4eed8bSAli Bahrami * being interchangeable drops significantly. 1801d2ef9fe9Sab196087 */ 18026b3ba5bdSAli Bahrami if (((rep_isp = isp->is_comdatkeep) == NULL) || 18036b3ba5bdSAli Bahrami ((rep_isp->is_flags & FLG_IS_DISCARD) != 0) || 18046b3ba5bdSAli Bahrami ((rep_isp->is_flags & FLG_IS_COMDAT) == 0) || 18056b3ba5bdSAli Bahrami (isp->is_indata->d_size != rep_isp->is_indata->d_size) || 18066b3ba5bdSAli Bahrami (isp->is_shdr->sh_type != rep_isp->is_shdr->sh_type) || 18076b3ba5bdSAli Bahrami ((isp->is_shdr->sh_flags & SHF_GROUP) != 180840e53e87SAli Bahrami (rep_isp->is_shdr->sh_flags & SHF_GROUP))) { 180940e53e87SAli Bahrami *reject = ofl->ofl_sr_cache.sr_rej = RLXREL_REJ_SECTION; 18106b3ba5bdSAli Bahrami return (ofl->ofl_sr_cache.sr_rsdp = NULL); 181140e53e87SAli Bahrami } 1812d2ef9fe9Sab196087 1813d2ef9fe9Sab196087 /* 1814d2ef9fe9Sab196087 * We found the kept COMDAT section. Now, look at all of the 1815d2ef9fe9Sab196087 * symbols from the input file that contains it to find the 1816d2ef9fe9Sab196087 * symbol that corresponds to the one we started with: 1817d2ef9fe9Sab196087 * - Hasn't been discarded 1818d2ef9fe9Sab196087 * - Has section index of kept section 1819d2ef9fe9Sab196087 * - If one symbol has a name, the other must have 1820d2ef9fe9Sab196087 * the same name. The st_name field of a symbol 1821d2ef9fe9Sab196087 * is 0 if there is no name, and is a string 1822d2ef9fe9Sab196087 * table offset otherwise. The string table 1823d2ef9fe9Sab196087 * offsets may well not agree --- it is the 1824d2ef9fe9Sab196087 * actual string that matters. 1825d2ef9fe9Sab196087 * - Type and binding attributes match (st_info) 1826d2ef9fe9Sab196087 * - Values match (st_value) 1827d2ef9fe9Sab196087 * - Sizes match (st_size) 1828d2ef9fe9Sab196087 * - Visibility matches (st_other) 1829d2ef9fe9Sab196087 */ 18306b3ba5bdSAli Bahrami scnndx = rep_isp->is_scnndx; 18316b3ba5bdSAli Bahrami oldndx = rep_isp->is_file->ifl_oldndx; 18326b3ba5bdSAli Bahrami symscnt = rep_isp->is_file->ifl_symscnt; 1833d2ef9fe9Sab196087 while (symscnt--) { 1834d2ef9fe9Sab196087 rep_sdp = *oldndx++; 18356b3ba5bdSAli Bahrami if ((rep_sdp == NULL) || (rep_sdp->sd_flags & FLG_SY_ISDISC) || 18366b3ba5bdSAli Bahrami ((rep_sym = rep_sdp->sd_sym)->st_shndx != scnndx) || 18376b3ba5bdSAli Bahrami ((sym->st_name == 0) != (rep_sym->st_name == 0)) || 18386b3ba5bdSAli Bahrami ((sym->st_name != 0) && 18396b3ba5bdSAli Bahrami (strcmp(sdp->sd_name, rep_sdp->sd_name) != 0)) || 18406b3ba5bdSAli Bahrami (sym->st_info != rep_sym->st_info) || 18416b3ba5bdSAli Bahrami (sym->st_value != rep_sym->st_value) || 18426b3ba5bdSAli Bahrami (sym->st_size != rep_sym->st_size) || 18436b3ba5bdSAli Bahrami (sym->st_other != rep_sym->st_other)) 18446b3ba5bdSAli Bahrami continue; 18456b3ba5bdSAli Bahrami 1846d2ef9fe9Sab196087 1847d2ef9fe9Sab196087 if (ofl->ofl_flags & FLG_OF_VERBOSE) { 1848d2ef9fe9Sab196087 if (sym->st_name != 0) { 1849*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 1850d2ef9fe9Sab196087 MSG_INTL(MSG_REL_SLOPCDATNAM), 1851d2ef9fe9Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, 1852de777a60Sab196087 reld->rel_rtype, 0, &inv_buf), 18534a8d0ea7SAli Bahrami ifl->ifl_name, 18544a8d0ea7SAli Bahrami EC_WORD(reld->rel_isdesc->is_scnndx), 18554a8d0ea7SAli Bahrami reld->rel_isdesc->is_name, 18564a8d0ea7SAli Bahrami rep_sdp->sd_name, 18574a8d0ea7SAli Bahrami EC_WORD(isp->is_scnndx), isp->is_name, 1858d2ef9fe9Sab196087 rep_sdp->sd_file->ifl_name); 1859d2ef9fe9Sab196087 } else { 1860*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 1861d2ef9fe9Sab196087 MSG_INTL(MSG_REL_SLOPCDATNONAM), 18626b3ba5bdSAli Bahrami conv_reloc_type(ifl->ifl_ehdr->e_machine, 1863de777a60Sab196087 reld->rel_rtype, 0, &inv_buf), 18644a8d0ea7SAli Bahrami ifl->ifl_name, 18654a8d0ea7SAli Bahrami EC_WORD(reld->rel_isdesc->is_scnndx), 18664a8d0ea7SAli Bahrami reld->rel_isdesc->is_name, 18674a8d0ea7SAli Bahrami EC_WORD(isp->is_scnndx), isp->is_name, 18684a8d0ea7SAli Bahrami rep_sdp->sd_file->ifl_name); 1869d2ef9fe9Sab196087 } 1870d2ef9fe9Sab196087 } 1871e23c41c9SAli Bahrami DBG_CALL(Dbg_reloc_sloppycomdat(ofl->ofl_lml, rep_sdp)); 187240e53e87SAli Bahrami *reject = ofl->ofl_sr_cache.sr_rej = RLXREL_REJ_NONE; 18736b3ba5bdSAli Bahrami return (ofl->ofl_sr_cache.sr_rsdp = rep_sdp); 1874d2ef9fe9Sab196087 } 1875d2ef9fe9Sab196087 1876d2ef9fe9Sab196087 /* If didn't return above, we didn't find it */ 187740e53e87SAli Bahrami *reject = ofl->ofl_sr_cache.sr_rej = RLXREL_REJ_SYMBOL; 18786b3ba5bdSAli Bahrami return (ofl->ofl_sr_cache.sr_rsdp = NULL); 1879d2ef9fe9Sab196087 } 1880d2ef9fe9Sab196087 1881cce0e03bSab196087 /* 18827c478bd9Sstevel@tonic-gate * Generate relocation descriptor and dispatch 18837c478bd9Sstevel@tonic-gate */ 18847c478bd9Sstevel@tonic-gate static uintptr_t 18857c478bd9Sstevel@tonic-gate process_reld(Ofl_desc *ofl, Is_desc *isp, Rel_desc *reld, Word rsndx, 18867c478bd9Sstevel@tonic-gate Rel *reloc) 18877c478bd9Sstevel@tonic-gate { 18887c478bd9Sstevel@tonic-gate Ifl_desc *ifl = isp->is_file; 18897c478bd9Sstevel@tonic-gate Word rtype = reld->rel_rtype; 18907c478bd9Sstevel@tonic-gate Sym_desc *sdp; 1891de777a60Sab196087 Conv_inv_buf_t inv_buf; 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate /* 18947c478bd9Sstevel@tonic-gate * Make sure the relocation is in the valid range. 18957c478bd9Sstevel@tonic-gate */ 1896ba2be530Sab196087 if (rtype >= ld_targ.t_m.m_r_num) { 1897*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_INVALRELT), 18984a8d0ea7SAli Bahrami ifl->ifl_name, EC_WORD(isp->is_scnndx), isp->is_name, 18994a8d0ea7SAli Bahrami rtype); 19007c478bd9Sstevel@tonic-gate return (S_ERROR); 19017c478bd9Sstevel@tonic-gate } 19027c478bd9Sstevel@tonic-gate 1903c174926fSrie ofl->ofl_entrelscnt++; 1904c174926fSrie 19057c478bd9Sstevel@tonic-gate /* 19067c478bd9Sstevel@tonic-gate * Special case: a register symbol associated with symbol index 0 is 19077c478bd9Sstevel@tonic-gate * initialized (i.e., relocated) to a constant from the r_addend field 19087c478bd9Sstevel@tonic-gate * rather than from a symbol value. 19097c478bd9Sstevel@tonic-gate */ 19107c478bd9Sstevel@tonic-gate if (IS_REGISTER(rtype) && (rsndx == 0)) { 1911bf994817SAli Bahrami reld->rel_sym = NULL; 1912ba2be530Sab196087 DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, 1913ba2be530Sab196087 ld_targ.t_m.m_mach, isp->is_shdr->sh_type, 1914e23c41c9SAli Bahrami (void *)reloc, isp->is_name, isp->is_scnndx, 1915bf994817SAli Bahrami ld_reloc_sym_name(reld))); 1916ba2be530Sab196087 if (ld_targ.t_mr.mr_reloc_register == NULL) { 1917*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_NOREG)); 1918ba2be530Sab196087 return (S_ERROR); 1919ba2be530Sab196087 } 1920ba2be530Sab196087 return ((*ld_targ.t_mr.mr_reloc_register)(reld, isp, ofl)); 19217c478bd9Sstevel@tonic-gate } 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate /* 1924bf994817SAli Bahrami * If this is a STT_SECTION symbol, make sure the associated 1925bf994817SAli Bahrami * section has a descriptive non-NULL is_sym_name field that can 1926bf994817SAli Bahrami * be accessed by ld_reloc_sym_name() to satisfy debugging output 1927bf994817SAli Bahrami * and errors. 1928bf994817SAli Bahrami * 1929bf994817SAli Bahrami * In principle, we could add this string to every input section 1930bf994817SAli Bahrami * as it is created, but we defer it until we see a relocation 1931bf994817SAli Bahrami * symbol that might need it. Not every section will have such 1932bf994817SAli Bahrami * a relocation, so we create fewer of them this way. 19337c478bd9Sstevel@tonic-gate */ 1934bf994817SAli Bahrami sdp = reld->rel_sym = ifl->ifl_oldndx[rsndx]; 1935bf994817SAli Bahrami if ((sdp != NULL) && 1936cce0e03bSab196087 (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) && 1937bf994817SAli Bahrami (sdp->sd_isc != NULL) && (sdp->sd_isc->is_name != NULL) && 1938bf994817SAli Bahrami (sdp->sd_isc->is_sym_name == NULL) && 1939bf994817SAli Bahrami (ld_stt_section_sym_name(sdp->sd_isc) == NULL)) 1940cce0e03bSab196087 return (S_ERROR); 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate /* 19437c478bd9Sstevel@tonic-gate * If for some reason we have a null relocation record issue a 19447c478bd9Sstevel@tonic-gate * warning and continue (the compiler folks can get into this 19457c478bd9Sstevel@tonic-gate * state some time). Normal users should never see this error. 19467c478bd9Sstevel@tonic-gate */ 1947ba2be530Sab196087 if (rtype == ld_targ.t_m.m_r_none) { 1948ba2be530Sab196087 DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, 1949ba2be530Sab196087 ld_targ.t_m.m_mach, ld_targ.t_m.m_rel_sht_type, 1950e23c41c9SAli Bahrami (void *)reloc, isp->is_name, isp->is_scnndx, 1951bf994817SAli Bahrami ld_reloc_sym_name(reld))); 1952*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_NULL), 19534a8d0ea7SAli Bahrami ifl->ifl_name, EC_WORD(isp->is_scnndx), isp->is_name); 19547c478bd9Sstevel@tonic-gate return (1); 19557c478bd9Sstevel@tonic-gate } 19567c478bd9Sstevel@tonic-gate 1957ba2be530Sab196087 if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && 1958ba2be530Sab196087 IS_NOTSUP(rtype)) { 1959*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_NOTSUP), 1960de777a60Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype, 19614a8d0ea7SAli Bahrami 0, &inv_buf), ifl->ifl_name, EC_WORD(isp->is_scnndx), 19624a8d0ea7SAli Bahrami isp->is_name); 19637c478bd9Sstevel@tonic-gate return (S_ERROR); 19647c478bd9Sstevel@tonic-gate } 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate /* 19677c478bd9Sstevel@tonic-gate * If we are here, we know that the relocation requires reference 19687c478bd9Sstevel@tonic-gate * symbol. If no symbol is assigned, this is a fatal error. 19697c478bd9Sstevel@tonic-gate */ 19707c478bd9Sstevel@tonic-gate if (sdp == NULL) { 1971*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_NOSYMBOL), 1972de777a60Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype, 19734a8d0ea7SAli Bahrami 0, &inv_buf), ifl->ifl_name, EC_WORD(isp->is_scnndx), 19744a8d0ea7SAli Bahrami isp->is_name, EC_XWORD(reloc->r_offset)); 19757c478bd9Sstevel@tonic-gate return (S_ERROR); 19767c478bd9Sstevel@tonic-gate } 19777c478bd9Sstevel@tonic-gate 1978635216b6SRod Evans if (sdp->sd_flags & FLG_SY_IGNORE) 19797c478bd9Sstevel@tonic-gate return (1); 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate /* 19827c478bd9Sstevel@tonic-gate * If this symbol is part of a DISCARDED section attempt to find another 19837c478bd9Sstevel@tonic-gate * definition. 19847c478bd9Sstevel@tonic-gate */ 19857c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_ISDISC) { 1986d2ef9fe9Sab196087 Sym_desc *nsdp = NULL; 198740e53e87SAli Bahrami Rlxrel_rej reject; 19887c478bd9Sstevel@tonic-gate 1989d2ef9fe9Sab196087 if (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL) { 1990d2ef9fe9Sab196087 /* 19910e233487SRod Evans * If "-z relaxreloc", and the input section is COMDAT 19920e233487SRod Evans * that has been assigned to an output section, then 19930e233487SRod Evans * determine if this is a reference to a discarded 19940e233487SRod Evans * COMDAT section that can be replaced with a COMDAT 19950e233487SRod Evans * that has been kept. 1996d2ef9fe9Sab196087 */ 19970e233487SRod Evans if ((ofl->ofl_flags1 & FLG_OF1_RLXREL) && 19980e233487SRod Evans sdp->sd_isc->is_osdesc && 19990e233487SRod Evans (sdp->sd_isc->is_flags & FLG_IS_COMDAT) && 20000e233487SRod Evans ((nsdp = sloppy_comdat_reloc(ofl, reld, 200140e53e87SAli Bahrami sdp, &reject)) == NULL)) { 2002ca4eed8bSAli Bahrami Shdr *is_shdr = reld->rel_isdesc->is_shdr; 2003ca4eed8bSAli Bahrami 2004ca4eed8bSAli Bahrami /* 2005ca4eed8bSAli Bahrami * A matching symbol was not found. We will 2006635216b6SRod Evans * ignore this relocation. Determine whether 2007635216b6SRod Evans * or not to issue a warning. 2008ca4eed8bSAli Bahrami * Warnings are always issued under -z verbose, 2009ca4eed8bSAli Bahrami * but otherwise, we will follow the lead of 2010ca4eed8bSAli Bahrami * the GNU ld and suppress them for certain 2011ca4eed8bSAli Bahrami * cases: 2012635216b6SRod Evans * 2013ca4eed8bSAli Bahrami * - It is a non-allocable debug section. 2014ca4eed8bSAli Bahrami * The GNU ld tests for these by name, 2015ca4eed8bSAli Bahrami * but we are willing to extend it to 2016ca4eed8bSAli Bahrami * any non-allocable section. 201740e53e87SAli Bahrami * - The target section is excluded from 201840e53e87SAli Bahrami * sloppy relocations by policy. 2019ca4eed8bSAli Bahrami */ 202040e53e87SAli Bahrami if (((ofl->ofl_flags & FLG_OF_VERBOSE) != 0) || 202140e53e87SAli Bahrami ((is_shdr->sh_flags & SHF_ALLOC) && 202240e53e87SAli Bahrami (reject != RLXREL_REJ_TARGET))) 2023*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 20240e233487SRod Evans MSG_INTL(MSG_REL_SLOPCDATNOSYM), 202540e53e87SAli Bahrami conv_reloc_type( 202640e53e87SAli Bahrami ifl->ifl_ehdr->e_machine, 20270e233487SRod Evans reld->rel_rtype, 0, &inv_buf), 20284a8d0ea7SAli Bahrami ifl->ifl_name, 20294a8d0ea7SAli Bahrami EC_WORD(isp->is_scnndx), 20304a8d0ea7SAli Bahrami isp->is_name, 2031bf994817SAli Bahrami ld_reloc_sym_name(reld), 20324a8d0ea7SAli Bahrami EC_WORD(sdp->sd_isc->is_scnndx), 20330e233487SRod Evans sdp->sd_isc->is_name); 20340e233487SRod Evans return (1); 2035d2ef9fe9Sab196087 } 2036bf994817SAli Bahrami } else if ((sdp != NULL) && sdp->sd_name && *sdp->sd_name) 2037635216b6SRod Evans nsdp = ld_sym_find(sdp->sd_name, SYM_NOHASH, NULL, ofl); 20380e233487SRod Evans 20390e233487SRod Evans if (nsdp == NULL) { 2040*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_SYMDISC), 20410e233487SRod Evans conv_reloc_type(ifl->ifl_ehdr->e_machine, 20420e233487SRod Evans reld->rel_rtype, 0, &inv_buf), ifl->ifl_name, 20434a8d0ea7SAli Bahrami EC_WORD(isp->is_scnndx), isp->is_name, 2044bf994817SAli Bahrami ld_reloc_sym_name(reld), 20454a8d0ea7SAli Bahrami EC_WORD(sdp->sd_isc->is_scnndx), 20460e233487SRod Evans sdp->sd_isc->is_name); 20477c478bd9Sstevel@tonic-gate return (S_ERROR); 20487c478bd9Sstevel@tonic-gate } 20497c478bd9Sstevel@tonic-gate ifl->ifl_oldndx[rsndx] = sdp = nsdp; 2050bf994817SAli Bahrami if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) && 2051bf994817SAli Bahrami (sdp->sd_isc != NULL) && (sdp->sd_isc->is_name != NULL) && 2052bf994817SAli Bahrami (sdp->sd_isc->is_sym_name == NULL) && 2053bf994817SAli Bahrami (ld_stt_section_sym_name(sdp->sd_isc) == NULL)) 2054bf994817SAli Bahrami return (S_ERROR); 20557c478bd9Sstevel@tonic-gate } 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate /* 20587c478bd9Sstevel@tonic-gate * If this is a global symbol, determine whether its visibility needs 20597c478bd9Sstevel@tonic-gate * adjusting. 20607c478bd9Sstevel@tonic-gate */ 20617c478bd9Sstevel@tonic-gate if (sdp->sd_aux && ((sdp->sd_flags & FLG_SY_VISIBLE) == 0)) 20625aefb655Srie ld_sym_adjust_vis(sdp, ofl); 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate /* 20657c478bd9Sstevel@tonic-gate * Ignore any relocation against a section that will not be in the 20667c478bd9Sstevel@tonic-gate * output file (has been stripped). 20677c478bd9Sstevel@tonic-gate */ 20687c478bd9Sstevel@tonic-gate if ((sdp->sd_isc == 0) && 20697c478bd9Sstevel@tonic-gate (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION)) 20707c478bd9Sstevel@tonic-gate return (1); 20717c478bd9Sstevel@tonic-gate 20727c478bd9Sstevel@tonic-gate /* 2073c1c6f601Srie * If the input section exists, but the section has not been associated 2074c1c6f601Srie * to an output section, then this is a little suspicious. 2075c1c6f601Srie */ 2076c1c6f601Srie if (sdp->sd_isc && (sdp->sd_isc->is_osdesc == 0) && 2077c1c6f601Srie (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION)) { 2078*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_RELINVSEC), 2079de777a60Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype, 20804a8d0ea7SAli Bahrami 0, &inv_buf), ifl->ifl_name, EC_WORD(isp->is_scnndx), 20814a8d0ea7SAli Bahrami isp->is_name, EC_WORD(sdp->sd_isc->is_scnndx), 2082de777a60Sab196087 sdp->sd_isc->is_name); 2083c1c6f601Srie return (1); 2084c1c6f601Srie } 2085c1c6f601Srie 2086c1c6f601Srie /* 20877c478bd9Sstevel@tonic-gate * If the symbol for this relocation is invalid (which should have 20887c478bd9Sstevel@tonic-gate * generated a message during symbol processing), or the relocation 20897c478bd9Sstevel@tonic-gate * record's symbol reference is in any other way invalid, then it's 20907c478bd9Sstevel@tonic-gate * about time we gave up. 20917c478bd9Sstevel@tonic-gate */ 20927c478bd9Sstevel@tonic-gate if ((sdp->sd_flags & FLG_SY_INVALID) || (rsndx == 0) || 20937c478bd9Sstevel@tonic-gate (rsndx >= ifl->ifl_symscnt)) { 2094*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_UNKNWSYM), 2095de777a60Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype, 20964a8d0ea7SAli Bahrami 0, &inv_buf), ifl->ifl_name, EC_WORD(isp->is_scnndx), 2097bf994817SAli Bahrami isp->is_name, ld_reloc_sym_name(reld), 20984a8d0ea7SAli Bahrami EC_XWORD(reloc->r_offset), EC_WORD(rsndx)); 20997c478bd9Sstevel@tonic-gate return (S_ERROR); 21007c478bd9Sstevel@tonic-gate } 21017c478bd9Sstevel@tonic-gate 21022926dd2eSrie /* 21032926dd2eSrie * Size relocations against section symbols are presently unsupported. 21042926dd2eSrie * There is a question as to whether the input section size, or output 21052926dd2eSrie * section size would be used. Until an explicit requirement is 21062926dd2eSrie * established for either case, we'll punt. 21072926dd2eSrie */ 21082926dd2eSrie if (IS_SIZE(rtype) && 21092926dd2eSrie (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION)) { 2110*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSIZE), 2111de777a60Sab196087 conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype, 21124a8d0ea7SAli Bahrami 0, &inv_buf), ifl->ifl_name, EC_WORD(isp->is_scnndx), 21134a8d0ea7SAli Bahrami isp->is_name); 21142926dd2eSrie return (S_ERROR); 21152926dd2eSrie } 21162926dd2eSrie 21177c478bd9Sstevel@tonic-gate reld->rel_sym = sdp; 2118bf994817SAli Bahrami if (reld->rel_aux) 2119bf994817SAli Bahrami reld->rel_aux->ra_usym = sdp; 2120e23c41c9SAli Bahrami return (ld_process_sym_reloc(ofl, reld, reloc, isp, isp->is_name, 2121e23c41c9SAli Bahrami isp->is_scnndx)); 21227c478bd9Sstevel@tonic-gate } 21237c478bd9Sstevel@tonic-gate 21247c478bd9Sstevel@tonic-gate static uintptr_t 21257c478bd9Sstevel@tonic-gate reloc_section(Ofl_desc *ofl, Is_desc *isect, Is_desc *rsect, Os_desc *osect) 21267c478bd9Sstevel@tonic-gate { 21277c478bd9Sstevel@tonic-gate Rel *rend; /* end of relocation section data */ 21287c478bd9Sstevel@tonic-gate Rel *reloc; /* current relocation entry */ 21297c478bd9Sstevel@tonic-gate Xword rsize; /* size of relocation section data */ 21307c478bd9Sstevel@tonic-gate Xword entsize; /* size of relocation entry */ 21317c478bd9Sstevel@tonic-gate Rel_desc reld; /* relocation descriptor */ 2132bf994817SAli Bahrami Rel_aux rel_aux; 21337c478bd9Sstevel@tonic-gate Shdr * shdr; 21347c478bd9Sstevel@tonic-gate Word flags = 0; 213502ca3e02Srie uintptr_t ret = 1; 21367c478bd9Sstevel@tonic-gate 21377c478bd9Sstevel@tonic-gate shdr = rsect->is_shdr; 21387c478bd9Sstevel@tonic-gate rsize = shdr->sh_size; 21397c478bd9Sstevel@tonic-gate reloc = (Rel *)rsect->is_indata->d_buf; 21407c478bd9Sstevel@tonic-gate 21417c478bd9Sstevel@tonic-gate /* 21427c478bd9Sstevel@tonic-gate * Decide entry size. 21437c478bd9Sstevel@tonic-gate */ 21447c478bd9Sstevel@tonic-gate if (((entsize = shdr->sh_entsize) == 0) || (entsize > rsize)) { 21457c478bd9Sstevel@tonic-gate if (shdr->sh_type == SHT_RELA) 21467c478bd9Sstevel@tonic-gate entsize = sizeof (Rela); 21477c478bd9Sstevel@tonic-gate else 21487c478bd9Sstevel@tonic-gate entsize = sizeof (Rel); 21497c478bd9Sstevel@tonic-gate } 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate /* 21527c478bd9Sstevel@tonic-gate * Build up the basic information in for the Rel_desc structure. 21537c478bd9Sstevel@tonic-gate */ 21547c478bd9Sstevel@tonic-gate reld.rel_isdesc = isect; 2155bf994817SAli Bahrami reld.rel_aux = &rel_aux; 2156bf994817SAli Bahrami ld_init_rel_aux(&reld); 2157bf994817SAli Bahrami rel_aux.ra_osdesc = osect; 21587c478bd9Sstevel@tonic-gate 21597c478bd9Sstevel@tonic-gate if ((ofl->ofl_flags & FLG_OF_RELOBJ) || 21607c478bd9Sstevel@tonic-gate (osect && (osect->os_sgdesc->sg_phdr.p_type == PT_LOAD))) 21617c478bd9Sstevel@tonic-gate flags |= FLG_REL_LOAD; 21627c478bd9Sstevel@tonic-gate 21637c478bd9Sstevel@tonic-gate if (shdr->sh_info == 0) 21647c478bd9Sstevel@tonic-gate flags |= FLG_REL_NOINFO; 21657c478bd9Sstevel@tonic-gate 21665aefb655Srie DBG_CALL(Dbg_reloc_proc(ofl->ofl_lml, osect, isect, rsect)); 21677c478bd9Sstevel@tonic-gate 21687c478bd9Sstevel@tonic-gate for (rend = (Rel *)((uintptr_t)reloc + (uintptr_t)rsize); 21697c478bd9Sstevel@tonic-gate reloc < rend; 2170b3fbe5e6Sseizo reloc = (Rel *)((uintptr_t)reloc + (uintptr_t)entsize)) { 21717c478bd9Sstevel@tonic-gate Word rsndx; 21727c478bd9Sstevel@tonic-gate 21737c478bd9Sstevel@tonic-gate /* 21747c478bd9Sstevel@tonic-gate * Initialize the relocation record information and process 21757c478bd9Sstevel@tonic-gate * the individual relocation. Reinitialize the flags to 21767c478bd9Sstevel@tonic-gate * insure we don't carry any state over from the previous 21777c478bd9Sstevel@tonic-gate * relocation records processing. 21787c478bd9Sstevel@tonic-gate */ 21797c478bd9Sstevel@tonic-gate reld.rel_flags = flags; 2180bf994817SAli Bahrami rsndx = (*ld_targ.t_mr.mr_init_rel)(&reld, 2181bf994817SAli Bahrami &rel_aux.ra_typedata, (void *)reloc); 2182bf994817SAli Bahrami 2183bf994817SAli Bahrami /* 2184bf994817SAli Bahrami * Determine whether or not to pass an auxiliary block 2185bf994817SAli Bahrami * in with this Rel_desc. It is not needed if both the 2186bf994817SAli Bahrami * osdesc and typedata fields have default values. 2187bf994817SAli Bahrami */ 2188bf994817SAli Bahrami reld.rel_aux = 2189bf994817SAli Bahrami (RELAUX_ISDEFAULT_OSDESC(&reld, rel_aux.ra_osdesc) && 2190bf994817SAli Bahrami RELAUX_ISDEFAULT_TYPEDATA(&reld, rel_aux.ra_typedata)) ? 2191bf994817SAli Bahrami NULL : &rel_aux; 21927c478bd9Sstevel@tonic-gate 21937c478bd9Sstevel@tonic-gate if (process_reld(ofl, rsect, &reld, rsndx, reloc) == S_ERROR) 219402ca3e02Srie ret = S_ERROR; 21957c478bd9Sstevel@tonic-gate } 219602ca3e02Srie return (ret); 21977c478bd9Sstevel@tonic-gate } 21987c478bd9Sstevel@tonic-gate 21995aefb655Srie static uintptr_t 22007c478bd9Sstevel@tonic-gate reloc_segments(int wr_flag, Ofl_desc *ofl) 22017c478bd9Sstevel@tonic-gate { 220257ef7aa9SRod Evans Aliste idx1; 22037c478bd9Sstevel@tonic-gate Sg_desc *sgp; 22047c478bd9Sstevel@tonic-gate Is_desc *isp; 22057c478bd9Sstevel@tonic-gate 220657ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 2207cce0e03bSab196087 Os_desc *osp; 220857ef7aa9SRod Evans Aliste idx2; 22097c478bd9Sstevel@tonic-gate 22107c478bd9Sstevel@tonic-gate if ((sgp->sg_phdr.p_flags & PF_W) != wr_flag) 22117c478bd9Sstevel@tonic-gate continue; 22127c478bd9Sstevel@tonic-gate 221357ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 22147c478bd9Sstevel@tonic-gate Is_desc *risp; 221557ef7aa9SRod Evans Aliste idx3; 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gate osp->os_szoutrels = 0; 221857ef7aa9SRod Evans for (APLIST_TRAVERSE(osp->os_relisdescs, idx3, risp)) { 22197c478bd9Sstevel@tonic-gate Word indx; 22207c478bd9Sstevel@tonic-gate 22217c478bd9Sstevel@tonic-gate /* 22227c478bd9Sstevel@tonic-gate * Determine the input section that this 22237c478bd9Sstevel@tonic-gate * relocation information refers to. 22247c478bd9Sstevel@tonic-gate */ 22257c478bd9Sstevel@tonic-gate indx = risp->is_shdr->sh_info; 22267c478bd9Sstevel@tonic-gate isp = risp->is_file->ifl_isdesc[indx]; 22277c478bd9Sstevel@tonic-gate 22287c478bd9Sstevel@tonic-gate /* 22297c478bd9Sstevel@tonic-gate * Do not process relocations against sections 22307c478bd9Sstevel@tonic-gate * which are being discarded (COMDAT) 22317c478bd9Sstevel@tonic-gate */ 22327c478bd9Sstevel@tonic-gate if (isp->is_flags & FLG_IS_DISCARD) 22337c478bd9Sstevel@tonic-gate continue; 22347c478bd9Sstevel@tonic-gate 22357c478bd9Sstevel@tonic-gate if (reloc_section(ofl, isp, risp, osp) == 22367c478bd9Sstevel@tonic-gate S_ERROR) 22377c478bd9Sstevel@tonic-gate return (S_ERROR); 22387c478bd9Sstevel@tonic-gate } 22397c478bd9Sstevel@tonic-gate 22407c478bd9Sstevel@tonic-gate /* 22417c478bd9Sstevel@tonic-gate * Check for relocations against non-writable 22427c478bd9Sstevel@tonic-gate * allocatable sections. 22437c478bd9Sstevel@tonic-gate */ 22446b3ba5bdSAli Bahrami if (osp->os_szoutrels && 22457c478bd9Sstevel@tonic-gate (sgp->sg_phdr.p_type == PT_LOAD) && 22467c478bd9Sstevel@tonic-gate ((sgp->sg_phdr.p_flags & PF_W) == 0)) { 22477c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_TEXTREL; 22487c478bd9Sstevel@tonic-gate ofl->ofl_dtflags |= DF_TEXTREL; 22497c478bd9Sstevel@tonic-gate } 22507c478bd9Sstevel@tonic-gate } 22517c478bd9Sstevel@tonic-gate } 22527c478bd9Sstevel@tonic-gate 22537c478bd9Sstevel@tonic-gate return (1); 22547c478bd9Sstevel@tonic-gate } 22557c478bd9Sstevel@tonic-gate 22567c478bd9Sstevel@tonic-gate /* 22577c478bd9Sstevel@tonic-gate * Move Section related function 22587c478bd9Sstevel@tonic-gate * Get move entry 22597c478bd9Sstevel@tonic-gate */ 22607c478bd9Sstevel@tonic-gate static Move * 22617c478bd9Sstevel@tonic-gate get_move_entry(Is_desc *rsect, Xword roffset) 22627c478bd9Sstevel@tonic-gate { 22637c478bd9Sstevel@tonic-gate Ifl_desc *ifile = rsect->is_file; 22647c478bd9Sstevel@tonic-gate Shdr *rshdr = rsect->is_shdr; 22657c478bd9Sstevel@tonic-gate Is_desc *misp; 22667c478bd9Sstevel@tonic-gate Shdr *mshdr; 22677c478bd9Sstevel@tonic-gate Xword midx; 226857ef7aa9SRod Evans Move *mvp; 22697c478bd9Sstevel@tonic-gate 22707c478bd9Sstevel@tonic-gate /* 22717c478bd9Sstevel@tonic-gate * Set info for the target move section 22727c478bd9Sstevel@tonic-gate */ 22737c478bd9Sstevel@tonic-gate misp = ifile->ifl_isdesc[rshdr->sh_info]; 227457ef7aa9SRod Evans mshdr = misp->is_shdr; 22757c478bd9Sstevel@tonic-gate 22767c478bd9Sstevel@tonic-gate if (mshdr->sh_entsize == 0) 227757ef7aa9SRod Evans return (NULL); 22787c478bd9Sstevel@tonic-gate 22797c478bd9Sstevel@tonic-gate /* 228057ef7aa9SRod Evans * If this is an invalid entry, return NULL. 22817c478bd9Sstevel@tonic-gate */ 228257ef7aa9SRod Evans midx = roffset / mshdr->sh_entsize; 22837c478bd9Sstevel@tonic-gate if ((midx * mshdr->sh_entsize) >= mshdr->sh_size) 228457ef7aa9SRod Evans return (NULL); 228557ef7aa9SRod Evans 228657ef7aa9SRod Evans mvp = (Move *)misp->is_indata->d_buf; 228757ef7aa9SRod Evans mvp += midx; 228857ef7aa9SRod Evans return (mvp); 22897c478bd9Sstevel@tonic-gate } 22907c478bd9Sstevel@tonic-gate 22917c478bd9Sstevel@tonic-gate /* 22927c478bd9Sstevel@tonic-gate * Relocation against Move Table. 22937c478bd9Sstevel@tonic-gate */ 22947c478bd9Sstevel@tonic-gate static uintptr_t 22957c478bd9Sstevel@tonic-gate process_movereloc(Ofl_desc *ofl, Is_desc *rsect) 22967c478bd9Sstevel@tonic-gate { 22977c478bd9Sstevel@tonic-gate Ifl_desc *file = rsect->is_file; 22987c478bd9Sstevel@tonic-gate Rel *rend, *reloc; 22997c478bd9Sstevel@tonic-gate Xword rsize, entsize; 23007c478bd9Sstevel@tonic-gate Rel_desc reld; 2301bf994817SAli Bahrami Rel_aux rel_aux; 23027c478bd9Sstevel@tonic-gate 23037c478bd9Sstevel@tonic-gate rsize = rsect->is_shdr->sh_size; 23047c478bd9Sstevel@tonic-gate reloc = (Rel *)rsect->is_indata->d_buf; 23057c478bd9Sstevel@tonic-gate 23067c478bd9Sstevel@tonic-gate /* 230757ef7aa9SRod Evans * Decide entry size. 23087c478bd9Sstevel@tonic-gate */ 23097c478bd9Sstevel@tonic-gate entsize = rsect->is_shdr->sh_entsize; 23107c478bd9Sstevel@tonic-gate if ((entsize == 0) || 23117c478bd9Sstevel@tonic-gate (entsize > rsect->is_shdr->sh_size)) { 23127c478bd9Sstevel@tonic-gate if (rsect->is_shdr->sh_type == SHT_RELA) 23137c478bd9Sstevel@tonic-gate entsize = sizeof (Rela); 23147c478bd9Sstevel@tonic-gate else 23157c478bd9Sstevel@tonic-gate entsize = sizeof (Rel); 23167c478bd9Sstevel@tonic-gate } 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate /* 2319bf994817SAli Bahrami * The requirement for move data ensures that we have to supply a 2320bf994817SAli Bahrami * Rel_aux auxiliary block. 2321bf994817SAli Bahrami */ 2322bf994817SAli Bahrami reld.rel_aux = &rel_aux; 2323bf994817SAli Bahrami ld_init_rel_aux(&reld); 2324bf994817SAli Bahrami 2325bf994817SAli Bahrami /* 23267c478bd9Sstevel@tonic-gate * Go through the relocation entries. 23277c478bd9Sstevel@tonic-gate */ 23287c478bd9Sstevel@tonic-gate for (rend = (Rel *)((uintptr_t)reloc + (uintptr_t)rsize); 23297c478bd9Sstevel@tonic-gate reloc < rend; 2330b3fbe5e6Sseizo reloc = (Rel *)((uintptr_t)reloc + (uintptr_t)entsize)) { 23317c478bd9Sstevel@tonic-gate Sym_desc *psdp; 233257ef7aa9SRod Evans Move *mvp; 23337c478bd9Sstevel@tonic-gate Word rsndx; 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate /* 23367c478bd9Sstevel@tonic-gate * Initialize the relocation record information. 23377c478bd9Sstevel@tonic-gate */ 23387c478bd9Sstevel@tonic-gate reld.rel_flags = FLG_REL_LOAD; 2339bf994817SAli Bahrami rsndx = (*ld_targ.t_mr.mr_init_rel)(&reld, 2340bf994817SAli Bahrami &rel_aux.ra_typedata, (void *)reloc); 23417c478bd9Sstevel@tonic-gate 234257ef7aa9SRod Evans if (((mvp = get_move_entry(rsect, reloc->r_offset)) == NULL) || 2343bf994817SAli Bahrami ((rel_aux.ra_move = 2344bf994817SAli Bahrami libld_malloc(sizeof (Mv_reloc))) == NULL)) 23457c478bd9Sstevel@tonic-gate return (S_ERROR); 23467c478bd9Sstevel@tonic-gate 234757ef7aa9SRod Evans psdp = file->ifl_oldndx[ELF_M_SYM(mvp->m_info)]; 2348bf994817SAli Bahrami rel_aux.ra_move->mr_move = mvp; 2349bf994817SAli Bahrami rel_aux.ra_move->mr_sym = psdp; 23507c478bd9Sstevel@tonic-gate 23517c478bd9Sstevel@tonic-gate if (psdp->sd_flags & FLG_SY_PAREXPN) { 235257ef7aa9SRod Evans int _num, num = mvp->m_repeat; 23537c478bd9Sstevel@tonic-gate 2354bf994817SAli Bahrami rel_aux.ra_osdesc = ofl->ofl_isparexpn->is_osdesc; 235535450702SAli Bahrami reld.rel_isdesc = ofl->ofl_isparexpn; 235657ef7aa9SRod Evans reld.rel_roffset = mvp->m_poffset; 23577c478bd9Sstevel@tonic-gate 235857ef7aa9SRod Evans for (_num = 0; _num < num; _num++) { 23597c478bd9Sstevel@tonic-gate reld.rel_roffset += 23607c478bd9Sstevel@tonic-gate /* LINTED */ 236157ef7aa9SRod Evans (_num * ELF_M_SIZE(mvp->m_info)); 236260758829Srie 23637c478bd9Sstevel@tonic-gate /* 23647c478bd9Sstevel@tonic-gate * Generate Reld 23657c478bd9Sstevel@tonic-gate */ 23667c478bd9Sstevel@tonic-gate if (process_reld(ofl, 23677c478bd9Sstevel@tonic-gate rsect, &reld, rsndx, reloc) == S_ERROR) 23687c478bd9Sstevel@tonic-gate return (S_ERROR); 23697c478bd9Sstevel@tonic-gate } 23707c478bd9Sstevel@tonic-gate } else { 23717c478bd9Sstevel@tonic-gate /* 23727c478bd9Sstevel@tonic-gate * Generate Reld 23737c478bd9Sstevel@tonic-gate */ 23747c478bd9Sstevel@tonic-gate reld.rel_flags |= FLG_REL_MOVETAB; 2375bf994817SAli Bahrami rel_aux.ra_osdesc = ofl->ofl_osmove; 23761dd9d86fSAli Bahrami reld.rel_isdesc = ld_os_first_isdesc(ofl->ofl_osmove); 237760758829Srie 23787c478bd9Sstevel@tonic-gate if (process_reld(ofl, 23797c478bd9Sstevel@tonic-gate rsect, &reld, rsndx, reloc) == S_ERROR) 23807c478bd9Sstevel@tonic-gate return (S_ERROR); 23817c478bd9Sstevel@tonic-gate } 23827c478bd9Sstevel@tonic-gate } 23837c478bd9Sstevel@tonic-gate return (1); 23847c478bd9Sstevel@tonic-gate } 23857c478bd9Sstevel@tonic-gate 23867c478bd9Sstevel@tonic-gate /* 23877c478bd9Sstevel@tonic-gate * This function is similar to reloc_init(). 23887c478bd9Sstevel@tonic-gate * 238957ef7aa9SRod Evans * This function is called when the SHT_SUNW_move table is expanded and there 239057ef7aa9SRod Evans * are relocations against the SHT_SUNW_move section. 23917c478bd9Sstevel@tonic-gate */ 23927c478bd9Sstevel@tonic-gate static uintptr_t 23937c478bd9Sstevel@tonic-gate reloc_movesections(Ofl_desc *ofl) 23947c478bd9Sstevel@tonic-gate { 239557ef7aa9SRod Evans Aliste idx; 23967c478bd9Sstevel@tonic-gate Is_desc *risp; 239702ca3e02Srie uintptr_t ret = 1; 23987c478bd9Sstevel@tonic-gate 23997c478bd9Sstevel@tonic-gate /* 24007c478bd9Sstevel@tonic-gate * Generate/Expand relocation entries 24017c478bd9Sstevel@tonic-gate */ 240257ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_ismoverel, idx, risp)) { 24037c478bd9Sstevel@tonic-gate if (process_movereloc(ofl, risp) == S_ERROR) 240402ca3e02Srie ret = S_ERROR; 24057c478bd9Sstevel@tonic-gate } 24067c478bd9Sstevel@tonic-gate 240702ca3e02Srie return (ret); 24087c478bd9Sstevel@tonic-gate } 24097c478bd9Sstevel@tonic-gate 24107c478bd9Sstevel@tonic-gate /* 24117c478bd9Sstevel@tonic-gate * Count the number of output relocation entries, global offset table entries, 24127c478bd9Sstevel@tonic-gate * and procedure linkage table entries. This function searches the segment and 24137c478bd9Sstevel@tonic-gate * outsect lists and passes each input reloc section to process_reloc(). 24147c478bd9Sstevel@tonic-gate * It allocates space for any output relocations needed. And builds up 24157c478bd9Sstevel@tonic-gate * the relocation structures for later processing. 24167c478bd9Sstevel@tonic-gate */ 24177c478bd9Sstevel@tonic-gate uintptr_t 24185aefb655Srie ld_reloc_init(Ofl_desc *ofl) 24197c478bd9Sstevel@tonic-gate { 242057ef7aa9SRod Evans Aliste idx; 24217c478bd9Sstevel@tonic-gate Is_desc *isp; 24229a411307Srie Sym_desc *sdp; 24237c478bd9Sstevel@tonic-gate 24242017c965SRod Evans DBG_CALL(Dbg_basic_collect(ofl->ofl_lml)); 24252017c965SRod Evans 24267c478bd9Sstevel@tonic-gate /* 24277c478bd9Sstevel@tonic-gate * At this point we have finished processing all input symbols. Make 24287c478bd9Sstevel@tonic-gate * sure we add any absolute (internal) symbols before continuing with 24297c478bd9Sstevel@tonic-gate * any relocation processing. 24307c478bd9Sstevel@tonic-gate */ 24315aefb655Srie if (ld_sym_spec(ofl) == S_ERROR) 24327c478bd9Sstevel@tonic-gate return (S_ERROR); 24337c478bd9Sstevel@tonic-gate 2434ba2be530Sab196087 ofl->ofl_gotcnt = ld_targ.t_m.m_got_xnumber; 24357c478bd9Sstevel@tonic-gate 24367c478bd9Sstevel@tonic-gate /* 2437635216b6SRod Evans * Process all of the relocations against NON-writable segments 2438635216b6SRod Evans * followed by relocations against the writable segments. 24397c478bd9Sstevel@tonic-gate * 24407c478bd9Sstevel@tonic-gate * This separation is so that when the writable segments are processed 24417c478bd9Sstevel@tonic-gate * we know whether or not a COPYRELOC will be produced for any symbols. 24427c478bd9Sstevel@tonic-gate * If relocations aren't processed in this order, a COPYRELOC and a 24437c478bd9Sstevel@tonic-gate * regular relocation can be produced against the same symbol. The 24447c478bd9Sstevel@tonic-gate * regular relocation would be redundant. 24457c478bd9Sstevel@tonic-gate */ 24467c478bd9Sstevel@tonic-gate if (reloc_segments(0, ofl) == S_ERROR) 24477c478bd9Sstevel@tonic-gate return (S_ERROR); 24487c478bd9Sstevel@tonic-gate 24497c478bd9Sstevel@tonic-gate if (reloc_segments(PF_W, ofl) == S_ERROR) 24507c478bd9Sstevel@tonic-gate return (S_ERROR); 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate /* 24537c478bd9Sstevel@tonic-gate * Process any extra relocations. These are relocation sections that 24547c478bd9Sstevel@tonic-gate * have a NULL sh_info. 24557c478bd9Sstevel@tonic-gate */ 245657ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_extrarels, idx, isp)) { 24577c478bd9Sstevel@tonic-gate if (reloc_section(ofl, NULL, isp, NULL) == S_ERROR) 24587c478bd9Sstevel@tonic-gate return (S_ERROR); 24597c478bd9Sstevel@tonic-gate } 24607c478bd9Sstevel@tonic-gate 24617c478bd9Sstevel@tonic-gate /* 24627c478bd9Sstevel@tonic-gate * If there were relocation against move table, 24637c478bd9Sstevel@tonic-gate * process the relocation sections. 24647c478bd9Sstevel@tonic-gate */ 24657c478bd9Sstevel@tonic-gate if (reloc_movesections(ofl) == S_ERROR) 24667c478bd9Sstevel@tonic-gate return (S_ERROR); 24677c478bd9Sstevel@tonic-gate 24687c478bd9Sstevel@tonic-gate /* 24697c478bd9Sstevel@tonic-gate * Now all the relocations are pre-processed, 24707c478bd9Sstevel@tonic-gate * check the validity of copy relocations. 24717c478bd9Sstevel@tonic-gate */ 247257ef7aa9SRod Evans if (ofl->ofl_copyrels) { 247357ef7aa9SRod Evans Copy_rel *crp; 24747c478bd9Sstevel@tonic-gate 247557ef7aa9SRod Evans for (ALIST_TRAVERSE(ofl->ofl_copyrels, idx, crp)) { 24767c478bd9Sstevel@tonic-gate /* 24777c478bd9Sstevel@tonic-gate * If there were no displacement relocation 24787c478bd9Sstevel@tonic-gate * in this file, don't worry about it. 24797c478bd9Sstevel@tonic-gate */ 248057ef7aa9SRod Evans if (crp->c_sdp->sd_file->ifl_flags & 24817c478bd9Sstevel@tonic-gate (FLG_IF_DISPPEND | FLG_IF_DISPDONE)) 248257ef7aa9SRod Evans is_disp_copied(ofl, crp); 24837c478bd9Sstevel@tonic-gate } 24847c478bd9Sstevel@tonic-gate } 24857c478bd9Sstevel@tonic-gate 24867c478bd9Sstevel@tonic-gate /* 2487141040e8Srie * GOT sections are created for dynamic executables and shared objects 2488141040e8Srie * if the FLG_OF_BLDGOT is set, or explicit reference has been made to 2489141040e8Srie * a GOT symbol. 24907c478bd9Sstevel@tonic-gate */ 2491141040e8Srie if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && 2492141040e8Srie ((ofl->ofl_flags & FLG_OF_BLDGOT) || 24939a411307Srie ((((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_GOFTBL), 2494635216b6SRod Evans SYM_NOHASH, NULL, ofl)) != NULL) || 24959a411307Srie ((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_GOFTBL_U), 2496635216b6SRod Evans SYM_NOHASH, NULL, ofl)) != NULL)) && 2497635216b6SRod Evans (sdp->sd_ref != REF_DYN_SEEN)))) { 24985aefb655Srie if (ld_make_got(ofl) == S_ERROR) 24997c478bd9Sstevel@tonic-gate return (S_ERROR); 25007c478bd9Sstevel@tonic-gate 2501ba2be530Sab196087 /* Allocate the GOT if required by target */ 2502ba2be530Sab196087 if ((ld_targ.t_mr.mr_allocate_got != NULL) && 2503ba2be530Sab196087 ((*ld_targ.t_mr.mr_allocate_got)(ofl) == S_ERROR)) 25047c478bd9Sstevel@tonic-gate return (S_ERROR); 25057c478bd9Sstevel@tonic-gate } 25067c478bd9Sstevel@tonic-gate 25077c478bd9Sstevel@tonic-gate return (1); 25087c478bd9Sstevel@tonic-gate } 25097c478bd9Sstevel@tonic-gate 25107c478bd9Sstevel@tonic-gate /* 25117c478bd9Sstevel@tonic-gate * Simple comparison routine to be used by qsort() for 25127c478bd9Sstevel@tonic-gate * the sorting of the output relocation list. 25137c478bd9Sstevel@tonic-gate * 25147c478bd9Sstevel@tonic-gate * The reloc_compare() routine results in a relocation 25157c478bd9Sstevel@tonic-gate * table which is located on: 25167c478bd9Sstevel@tonic-gate * 25177c478bd9Sstevel@tonic-gate * file referenced (NEEDED NDX) 25187c478bd9Sstevel@tonic-gate * referenced symbol 25197c478bd9Sstevel@tonic-gate * relocation offset 25207c478bd9Sstevel@tonic-gate * 25217c478bd9Sstevel@tonic-gate * This provides the most efficient traversal of the relocation 25227c478bd9Sstevel@tonic-gate * table at run-time. 25237c478bd9Sstevel@tonic-gate */ 25245aefb655Srie static int 25257c478bd9Sstevel@tonic-gate reloc_compare(Reloc_list *i, Reloc_list *j) 25267c478bd9Sstevel@tonic-gate { 25277c478bd9Sstevel@tonic-gate 25287c478bd9Sstevel@tonic-gate /* 25297c478bd9Sstevel@tonic-gate * first - sort on neededndx 25307c478bd9Sstevel@tonic-gate */ 25317c478bd9Sstevel@tonic-gate if (i->rl_key1 > j->rl_key1) 25327c478bd9Sstevel@tonic-gate return (1); 25337c478bd9Sstevel@tonic-gate if (i->rl_key1 < j->rl_key1) 25347c478bd9Sstevel@tonic-gate return (-1); 25357c478bd9Sstevel@tonic-gate 25367c478bd9Sstevel@tonic-gate /* 25377c478bd9Sstevel@tonic-gate * Then sort on symbol 25387c478bd9Sstevel@tonic-gate */ 25397c478bd9Sstevel@tonic-gate if ((uintptr_t)i->rl_key2 > (uintptr_t)j->rl_key2) 25407c478bd9Sstevel@tonic-gate return (1); 25417c478bd9Sstevel@tonic-gate if ((uintptr_t)i->rl_key2 < (uintptr_t)j->rl_key2) 25427c478bd9Sstevel@tonic-gate return (-1); 25437c478bd9Sstevel@tonic-gate 25447c478bd9Sstevel@tonic-gate /* 25457c478bd9Sstevel@tonic-gate * i->key2 == j->key2 25467c478bd9Sstevel@tonic-gate * 25477c478bd9Sstevel@tonic-gate * At this point we fall back to key2 (offsets) to 25487c478bd9Sstevel@tonic-gate * sort the output relocations. Ideally this will 25497c478bd9Sstevel@tonic-gate * make for the most efficient processing of these 25507c478bd9Sstevel@tonic-gate * relocations at run-time. 25517c478bd9Sstevel@tonic-gate */ 25527c478bd9Sstevel@tonic-gate if (i->rl_key3 > j->rl_key3) 25537c478bd9Sstevel@tonic-gate return (1); 25547c478bd9Sstevel@tonic-gate if (i->rl_key3 < j->rl_key3) 25557c478bd9Sstevel@tonic-gate return (-1); 25567c478bd9Sstevel@tonic-gate return (0); 25577c478bd9Sstevel@tonic-gate } 25587c478bd9Sstevel@tonic-gate 25595aefb655Srie static uintptr_t 25607c478bd9Sstevel@tonic-gate do_sorted_outrelocs(Ofl_desc *ofl) 25617c478bd9Sstevel@tonic-gate { 25627c478bd9Sstevel@tonic-gate Rel_desc *orsp; 2563bf994817SAli Bahrami Rel_cachebuf *rcbp; 256457ef7aa9SRod Evans Aliste idx; 25657c478bd9Sstevel@tonic-gate Reloc_list *sorted_list; 25667c478bd9Sstevel@tonic-gate Word index = 0; 25677c478bd9Sstevel@tonic-gate int debug = 0; 25687c478bd9Sstevel@tonic-gate uintptr_t error = 1; 2569*1007fd6fSAli Bahrami Boolean remain_seen = FALSE; 25707c478bd9Sstevel@tonic-gate 25717c478bd9Sstevel@tonic-gate if ((sorted_list = libld_malloc((size_t)(sizeof (Reloc_list) * 25727c478bd9Sstevel@tonic-gate ofl->ofl_reloccnt))) == NULL) 25737c478bd9Sstevel@tonic-gate return (S_ERROR); 25747c478bd9Sstevel@tonic-gate 25757c478bd9Sstevel@tonic-gate /* 25767c478bd9Sstevel@tonic-gate * All but the PLT output relocations are sorted in the output file 25777c478bd9Sstevel@tonic-gate * based upon their sym_desc. By doing this multiple relocations 25787c478bd9Sstevel@tonic-gate * against the same symbol are grouped together, thus when the object 25797c478bd9Sstevel@tonic-gate * is later relocated by ld.so.1 it will take advantage of the symbol 25807c478bd9Sstevel@tonic-gate * cache that ld.so.1 has. This can significantly reduce the runtime 25817c478bd9Sstevel@tonic-gate * relocation cost of a dynamic object. 25827c478bd9Sstevel@tonic-gate * 25837c478bd9Sstevel@tonic-gate * PLT relocations are not sorted because the order of the PLT 25847c478bd9Sstevel@tonic-gate * relocations is used by ld.so.1 to determine what symbol a PLT 25857c478bd9Sstevel@tonic-gate * relocation is against. 25867c478bd9Sstevel@tonic-gate */ 2587bf994817SAli Bahrami REL_CACHE_TRAVERSE(&ofl->ofl_outrels, idx, rcbp, orsp) { 25887c478bd9Sstevel@tonic-gate if (debug == 0) { 25895aefb655Srie DBG_CALL(Dbg_reloc_dooutrel(ofl->ofl_lml, 2590ba2be530Sab196087 ld_targ.t_m.m_rel_sht_type)); 25917c478bd9Sstevel@tonic-gate debug = 1; 25927c478bd9Sstevel@tonic-gate } 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate /* 25957c478bd9Sstevel@tonic-gate * If it's a PLT relocation we output it now in the 25967c478bd9Sstevel@tonic-gate * order that it was originally processed. 25977c478bd9Sstevel@tonic-gate */ 25987c478bd9Sstevel@tonic-gate if (orsp->rel_flags & FLG_REL_PLT) { 2599*1007fd6fSAli Bahrami if ((*ld_targ.t_mr.mr_perform_outreloc) 2600*1007fd6fSAli Bahrami (orsp, ofl, &remain_seen) == S_ERROR) 26017c478bd9Sstevel@tonic-gate error = S_ERROR; 26027c478bd9Sstevel@tonic-gate continue; 26037c478bd9Sstevel@tonic-gate } 26047c478bd9Sstevel@tonic-gate 2605ba2be530Sab196087 if ((orsp->rel_rtype == ld_targ.t_m.m_r_relative) || 2606ba2be530Sab196087 (orsp->rel_rtype == ld_targ.t_m.m_r_register)) { 26077c478bd9Sstevel@tonic-gate sorted_list[index].rl_key1 = 0; 26087c478bd9Sstevel@tonic-gate sorted_list[index].rl_key2 = 26097c478bd9Sstevel@tonic-gate /* LINTED */ 26107c478bd9Sstevel@tonic-gate (Sym_desc *)(uintptr_t)orsp->rel_rtype; 26117c478bd9Sstevel@tonic-gate } else { 26127c478bd9Sstevel@tonic-gate sorted_list[index].rl_key1 = 26137c478bd9Sstevel@tonic-gate orsp->rel_sym->sd_file->ifl_neededndx; 2614bf994817SAli Bahrami sorted_list[index].rl_key2 = orsp->rel_sym; 26157c478bd9Sstevel@tonic-gate } 26167c478bd9Sstevel@tonic-gate 2617bf994817SAli Bahrami if (orsp->rel_flags & FLG_REL_GOT) { 26187c478bd9Sstevel@tonic-gate sorted_list[index].rl_key3 = 2619bf994817SAli Bahrami (*ld_targ.t_mr.mr_calc_got_offset)(orsp, ofl); 2620bf994817SAli Bahrami } else { 2621bf994817SAli Bahrami if (orsp->rel_rtype == ld_targ.t_m.m_r_register) { 26227c478bd9Sstevel@tonic-gate sorted_list[index].rl_key3 = 0; 2623bf994817SAli Bahrami } else { 2624bf994817SAli Bahrami sorted_list[index].rl_key3 = orsp->rel_roffset + 26257c478bd9Sstevel@tonic-gate (Xword)_elf_getxoff(orsp-> 2626de777a60Sab196087 rel_isdesc->is_indata) + 26277c478bd9Sstevel@tonic-gate orsp->rel_isdesc->is_osdesc-> 26287c478bd9Sstevel@tonic-gate os_shdr->sh_addr; 26297c478bd9Sstevel@tonic-gate } 26307c478bd9Sstevel@tonic-gate } 26317c478bd9Sstevel@tonic-gate 26327c478bd9Sstevel@tonic-gate sorted_list[index++].rl_rsp = orsp; 26337c478bd9Sstevel@tonic-gate } 26347c478bd9Sstevel@tonic-gate 26357c478bd9Sstevel@tonic-gate qsort(sorted_list, (size_t)ofl->ofl_reloccnt, sizeof (Reloc_list), 26367c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))reloc_compare); 26377c478bd9Sstevel@tonic-gate 26387c478bd9Sstevel@tonic-gate /* 26397c478bd9Sstevel@tonic-gate * All output relocations have now been sorted, go through 26407c478bd9Sstevel@tonic-gate * and process each relocation. 26417c478bd9Sstevel@tonic-gate */ 26427c478bd9Sstevel@tonic-gate for (index = 0; index < ofl->ofl_reloccnt; index++) { 2643ba2be530Sab196087 if ((*ld_targ.t_mr.mr_perform_outreloc) 2644*1007fd6fSAli Bahrami (sorted_list[index].rl_rsp, ofl, &remain_seen) == S_ERROR) 26457c478bd9Sstevel@tonic-gate error = S_ERROR; 26467c478bd9Sstevel@tonic-gate } 26477c478bd9Sstevel@tonic-gate 2648*1007fd6fSAli Bahrami /* Guidance: Use -z text when building shared objects */ 2649*1007fd6fSAli Bahrami if (remain_seen && OFL_GUIDANCE(ofl, FLG_OFG_NO_TEXT)) 2650*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_GUIDANCE, MSG_INTL(MSG_GUIDE_TEXT)); 2651*1007fd6fSAli Bahrami 26527c478bd9Sstevel@tonic-gate return (error); 26537c478bd9Sstevel@tonic-gate } 26547c478bd9Sstevel@tonic-gate 26557c478bd9Sstevel@tonic-gate /* 26567c478bd9Sstevel@tonic-gate * Process relocations. Finds every input relocation section for each output 2657cce0e03bSab196087 * section and invokes reloc_section() to relocate that section. 26587c478bd9Sstevel@tonic-gate */ 26597c478bd9Sstevel@tonic-gate uintptr_t 26605aefb655Srie ld_reloc_process(Ofl_desc *ofl) 26617c478bd9Sstevel@tonic-gate { 26627c478bd9Sstevel@tonic-gate Sg_desc *sgp; 2663d326b23bSrie Os_desc *osp; 26641d9df23bSab196087 Word ndx = 0; 26651d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags; 26667c478bd9Sstevel@tonic-gate Shdr *shdr; 26677c478bd9Sstevel@tonic-gate 26682017c965SRod Evans DBG_CALL(Dbg_basic_relocate(ofl->ofl_lml)); 26692017c965SRod Evans 26707c478bd9Sstevel@tonic-gate /* 26717c478bd9Sstevel@tonic-gate * Determine the index of the symbol table that will be referenced by 26727c478bd9Sstevel@tonic-gate * the relocation entries. 26737c478bd9Sstevel@tonic-gate */ 2674635216b6SRod Evans if (OFL_ALLOW_DYNSYM(ofl)) 26757c478bd9Sstevel@tonic-gate /* LINTED */ 26767c478bd9Sstevel@tonic-gate ndx = (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn); 26777c478bd9Sstevel@tonic-gate else if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ)) 26787c478bd9Sstevel@tonic-gate /* LINTED */ 26797c478bd9Sstevel@tonic-gate ndx = (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn); 26807c478bd9Sstevel@tonic-gate 26817c478bd9Sstevel@tonic-gate /* 26827c478bd9Sstevel@tonic-gate * Re-initialize counters. These are used to provide relocation 26837c478bd9Sstevel@tonic-gate * offsets within the output buffers. 26847c478bd9Sstevel@tonic-gate */ 26857c478bd9Sstevel@tonic-gate ofl->ofl_relocpltsz = 0; 26867c478bd9Sstevel@tonic-gate ofl->ofl_relocgotsz = 0; 26877c478bd9Sstevel@tonic-gate ofl->ofl_relocbsssz = 0; 26887c478bd9Sstevel@tonic-gate 26897c478bd9Sstevel@tonic-gate /* 26907c478bd9Sstevel@tonic-gate * Now that the output file is created and symbol update has occurred, 26917c478bd9Sstevel@tonic-gate * process the relocations collected in process_reloc(). 26927c478bd9Sstevel@tonic-gate */ 26937c478bd9Sstevel@tonic-gate if (do_sorted_outrelocs(ofl) == S_ERROR) 26947c478bd9Sstevel@tonic-gate return (S_ERROR); 26957c478bd9Sstevel@tonic-gate 2696ba2be530Sab196087 if ((*ld_targ.t_mr.mr_do_activerelocs)(ofl) == S_ERROR) 26977c478bd9Sstevel@tonic-gate return (S_ERROR); 26987c478bd9Sstevel@tonic-gate 26991d9df23bSab196087 if ((flags & FLG_OF_COMREL) == 0) { 270057ef7aa9SRod Evans Aliste idx1; 270157ef7aa9SRod Evans 27027c478bd9Sstevel@tonic-gate /* 2703635216b6SRod Evans * Process the relocation sections. For each relocation 2704635216b6SRod Evans * section generated for the output image update its shdr 2705635216b6SRod Evans * information to reflect the symbol table it needs (sh_link) 2706635216b6SRod Evans * and the section to which the relocation must be applied 2707635216b6SRod Evans * (sh_info). 27087c478bd9Sstevel@tonic-gate */ 270957ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 2710cce0e03bSab196087 Os_desc *osp; 271157ef7aa9SRod Evans Aliste idx2; 27127c478bd9Sstevel@tonic-gate 271357ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 27147c478bd9Sstevel@tonic-gate if (osp->os_relosdesc == 0) 27157c478bd9Sstevel@tonic-gate continue; 27167c478bd9Sstevel@tonic-gate 27177c478bd9Sstevel@tonic-gate shdr = osp->os_relosdesc->os_shdr; 27187c478bd9Sstevel@tonic-gate shdr->sh_link = ndx; 27197c478bd9Sstevel@tonic-gate /* LINTED */ 27207c478bd9Sstevel@tonic-gate shdr->sh_info = (Word)elf_ndxscn(osp->os_scn); 27217c478bd9Sstevel@tonic-gate } 27227c478bd9Sstevel@tonic-gate } 27237c478bd9Sstevel@tonic-gate 27247c478bd9Sstevel@tonic-gate /* 27257c478bd9Sstevel@tonic-gate * Since the .rel[a] section is not tied to any specific 2726d326b23bSrie * section, we'd not have found it above. 27277c478bd9Sstevel@tonic-gate */ 2728d326b23bSrie if ((osp = ofl->ofl_osrel) != NULL) { 2729d326b23bSrie shdr = osp->os_shdr; 27307c478bd9Sstevel@tonic-gate shdr->sh_link = ndx; 27317c478bd9Sstevel@tonic-gate shdr->sh_info = 0; 27327c478bd9Sstevel@tonic-gate } 27337c478bd9Sstevel@tonic-gate } else { 27347c478bd9Sstevel@tonic-gate /* 27357c478bd9Sstevel@tonic-gate * We only have two relocation sections here, (PLT's, 27367c478bd9Sstevel@tonic-gate * coalesced) so just hit them directly instead of stepping 27377c478bd9Sstevel@tonic-gate * over the output sections. 27387c478bd9Sstevel@tonic-gate */ 2739d326b23bSrie if ((osp = ofl->ofl_osrelhead) != NULL) { 2740d326b23bSrie shdr = osp->os_shdr; 27417c478bd9Sstevel@tonic-gate shdr->sh_link = ndx; 27427c478bd9Sstevel@tonic-gate shdr->sh_info = 0; 27437c478bd9Sstevel@tonic-gate } 2744d326b23bSrie if (((osp = ofl->ofl_osplt) != NULL) && osp->os_relosdesc) { 2745d326b23bSrie shdr = osp->os_relosdesc->os_shdr; 27467c478bd9Sstevel@tonic-gate shdr->sh_link = ndx; 27477c478bd9Sstevel@tonic-gate /* LINTED */ 2748d326b23bSrie shdr->sh_info = (Word)elf_ndxscn(osp->os_scn); 27497c478bd9Sstevel@tonic-gate } 27507c478bd9Sstevel@tonic-gate } 27517c478bd9Sstevel@tonic-gate 27527c478bd9Sstevel@tonic-gate /* 27537c478bd9Sstevel@tonic-gate * If the -z text option was given, and we have output relocations 27547c478bd9Sstevel@tonic-gate * against a non-writable, allocatable section, issue a diagnostic and 27557c478bd9Sstevel@tonic-gate * return (the actual entries that caused this error would have been 27567c478bd9Sstevel@tonic-gate * output during the relocating section phase). 27577c478bd9Sstevel@tonic-gate */ 27587c478bd9Sstevel@tonic-gate if ((flags & (FLG_OF_PURETXT | FLG_OF_TEXTREL)) == 27597c478bd9Sstevel@tonic-gate (FLG_OF_PURETXT | FLG_OF_TEXTREL)) { 2760*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_REMAIN_3)); 27617c478bd9Sstevel@tonic-gate return (S_ERROR); 27627c478bd9Sstevel@tonic-gate } 27637c478bd9Sstevel@tonic-gate 27647c478bd9Sstevel@tonic-gate /* 27657c478bd9Sstevel@tonic-gate * Finally, initialize the first got entry with the address of the 27667c478bd9Sstevel@tonic-gate * .dynamic section (_DYNAMIC). 27677c478bd9Sstevel@tonic-gate */ 27687c478bd9Sstevel@tonic-gate if (flags & FLG_OF_DYNAMIC) { 2769ba2be530Sab196087 if ((*ld_targ.t_mr.mr_fillin_gotplt)(ofl) == S_ERROR) 27707c478bd9Sstevel@tonic-gate return (S_ERROR); 27717c478bd9Sstevel@tonic-gate } 27727c478bd9Sstevel@tonic-gate 2773d326b23bSrie /* 2774d326b23bSrie * Now that any GOT information has been written, display the debugging 2775d326b23bSrie * information if required. 2776d326b23bSrie */ 2777d326b23bSrie if ((osp = ofl->ofl_osgot) != NULL) 2778ba2be530Sab196087 DBG_CALL(Dbg_got_display(ofl, osp->os_shdr->sh_addr, 1, 2779ba2be530Sab196087 ld_targ.t_m.m_got_xnumber, ld_targ.t_m.m_got_entsize)); 2780d326b23bSrie 27817c478bd9Sstevel@tonic-gate return (1); 27827c478bd9Sstevel@tonic-gate } 27837c478bd9Sstevel@tonic-gate 27847c478bd9Sstevel@tonic-gate /* 27857c478bd9Sstevel@tonic-gate * If the -z text option was given, and we have output relocations against a 27867c478bd9Sstevel@tonic-gate * non-writable, allocatable section, issue a diagnostic. Print offending 27877c478bd9Sstevel@tonic-gate * symbols in tabular form similar to the way undefined symbols are presented. 27887c478bd9Sstevel@tonic-gate * Called from reloc_count(). The actual fatal error condition is triggered on 27897c478bd9Sstevel@tonic-gate * in reloc_process() above. 27907c478bd9Sstevel@tonic-gate * 27917c478bd9Sstevel@tonic-gate * Note. For historic reasons -ztext is not a default option (however all OS 27927c478bd9Sstevel@tonic-gate * shared object builds use this option). It can be argued that this option 27937c478bd9Sstevel@tonic-gate * should also be default when generating an a.out (see 1163979). However, if 27947c478bd9Sstevel@tonic-gate * an a.out contains text relocations it is either because the user is creating 27957c478bd9Sstevel@tonic-gate * something pretty weird (they've used the -b or -znodefs options), or because 27967c478bd9Sstevel@tonic-gate * the library against which they're building wasn't constructed correctly (ie. 27977c478bd9Sstevel@tonic-gate * a function has a NOTYPE type, in which case the a.out won't generate an 27987c478bd9Sstevel@tonic-gate * associated plt). In the latter case the builder of the a.out can't do 27997c478bd9Sstevel@tonic-gate * anything to fix the error - thus we've chosen not to give the user an error, 28007c478bd9Sstevel@tonic-gate * or warning, for this case. 28017c478bd9Sstevel@tonic-gate */ 28027c478bd9Sstevel@tonic-gate void 2803*1007fd6fSAli Bahrami ld_reloc_remain_entry(Rel_desc *orsp, Os_desc *osp, Ofl_desc *ofl, 2804*1007fd6fSAli Bahrami Boolean *remain_seen) 28057c478bd9Sstevel@tonic-gate { 28067c478bd9Sstevel@tonic-gate 28077c478bd9Sstevel@tonic-gate /* 28087c478bd9Sstevel@tonic-gate * -ztextoff 28097c478bd9Sstevel@tonic-gate */ 28107c478bd9Sstevel@tonic-gate if (ofl->ofl_flags1 & FLG_OF1_TEXTOFF) 28117c478bd9Sstevel@tonic-gate return; 28127c478bd9Sstevel@tonic-gate 28137c478bd9Sstevel@tonic-gate /* 28147c478bd9Sstevel@tonic-gate * Only give relocation errors against loadable read-only segments. 28157c478bd9Sstevel@tonic-gate */ 2816ba2be530Sab196087 if ((orsp->rel_rtype == ld_targ.t_m.m_r_register) || (!osp) || 28177c478bd9Sstevel@tonic-gate (osp->os_sgdesc->sg_phdr.p_type != PT_LOAD) || 28187c478bd9Sstevel@tonic-gate (osp->os_sgdesc->sg_phdr.p_flags & PF_W)) 28197c478bd9Sstevel@tonic-gate return; 28207c478bd9Sstevel@tonic-gate 28217c478bd9Sstevel@tonic-gate /* 28227c478bd9Sstevel@tonic-gate * If we are in -ztextwarn mode, it's a silent error if a relocation is 28237c478bd9Sstevel@tonic-gate * due to a 'WEAK REFERENCE'. This is because if the symbol is not 28247c478bd9Sstevel@tonic-gate * provided at run-time we will not perform a text-relocation. 28257c478bd9Sstevel@tonic-gate */ 28267c478bd9Sstevel@tonic-gate if (((ofl->ofl_flags & FLG_OF_PURETXT) == 0) && 28277c478bd9Sstevel@tonic-gate (ELF_ST_BIND(orsp->rel_sym->sd_sym->st_info) == STB_WEAK) && 28280bc07c75Srie (orsp->rel_sym->sd_sym->st_shndx == SHN_UNDEF)) 28297c478bd9Sstevel@tonic-gate return; 28307c478bd9Sstevel@tonic-gate 2831*1007fd6fSAli Bahrami if (*remain_seen == FALSE) { 28327c478bd9Sstevel@tonic-gate /* 28337c478bd9Sstevel@tonic-gate * If building with '-ztext' then emit a fatal error. If 28347c478bd9Sstevel@tonic-gate * building a executable then only emit a 'warning'. 28357c478bd9Sstevel@tonic-gate */ 2836*1007fd6fSAli Bahrami const char *str1 = (ofl->ofl_flags & FLG_OF_PURETXT) ? 2837*1007fd6fSAli Bahrami MSG_INTL(MSG_REL_RMN_ITM_11) : MSG_INTL(MSG_REL_RMN_ITM_13); 2838*1007fd6fSAli Bahrami 2839*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_REL_REMAIN_FMT_1), str1, 2840*1007fd6fSAli Bahrami MSG_INTL(MSG_REL_RMN_ITM_31), MSG_INTL(MSG_REL_RMN_ITM_12), 2841*1007fd6fSAli Bahrami MSG_INTL(MSG_REL_RMN_ITM_2), MSG_INTL(MSG_REL_RMN_ITM_32)); 2842*1007fd6fSAli Bahrami 2843*1007fd6fSAli Bahrami *remain_seen = TRUE; 28447c478bd9Sstevel@tonic-gate } 28457c478bd9Sstevel@tonic-gate 2846*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_REL_REMAIN_2), 2847bf994817SAli Bahrami ld_reloc_sym_name(orsp), EC_OFF(orsp->rel_roffset), 28485aefb655Srie orsp->rel_isdesc->is_file->ifl_name); 28497c478bd9Sstevel@tonic-gate } 28507c478bd9Sstevel@tonic-gate 28517c478bd9Sstevel@tonic-gate /* 2852d326b23bSrie * Generic encapsulation for generating a TLS got index. 28537c478bd9Sstevel@tonic-gate */ 2854d326b23bSrie uintptr_t 2855d326b23bSrie ld_assign_got_TLS(Boolean local, Rel_desc *rsp, Ofl_desc *ofl, Sym_desc *sdp, 2856d326b23bSrie Gotndx *gnp, Gotref gref, Word rflag, Word ortype, Word rtype1, Word rtype2) 2857d326b23bSrie { 2858d326b23bSrie Word rflags; 2859d326b23bSrie 2860ba2be530Sab196087 if ((*ld_targ.t_mr.mr_assign_got_ndx)(&(sdp->sd_GOTndxs), gnp, 2861ba2be530Sab196087 gref, ofl, rsp, sdp) == S_ERROR) 2862d326b23bSrie return (S_ERROR); 2863d326b23bSrie 2864d326b23bSrie rflags = FLG_REL_GOT | rflag; 2865d326b23bSrie if (local) 2866d326b23bSrie rflags |= FLG_REL_SCNNDX; 2867d326b23bSrie rsp->rel_rtype = rtype1; 2868d326b23bSrie 2869ba2be530Sab196087 if ((*ld_targ.t_mr.mr_add_outrel)(rflags, rsp, ofl) == S_ERROR) 2870d326b23bSrie return (S_ERROR); 2871d326b23bSrie 2872d326b23bSrie if (local && (gref == GOT_REF_TLSIE)) { 2873d326b23bSrie /* 2874d326b23bSrie * If this is a local LE TLS symbol, then the symbol won't be 2875d326b23bSrie * available at runtime. The value of the local symbol will 2876d326b23bSrie * be placed in the associated got entry, and the got 2877d326b23bSrie * relocation is reassigned to a section symbol. 2878d326b23bSrie */ 2879d326b23bSrie if (ld_add_actrel(rflags, rsp, ofl) == S_ERROR) 2880d326b23bSrie return (S_ERROR); 2881d326b23bSrie } 2882d326b23bSrie 2883d326b23bSrie if (rtype2) { 2884d326b23bSrie rflags = FLG_REL_GOT | rflag; 2885d326b23bSrie rsp->rel_rtype = rtype2; 2886d326b23bSrie 2887d326b23bSrie if (local) { 2888d326b23bSrie if (ld_add_actrel(rflags, rsp, ofl) == S_ERROR) 2889d326b23bSrie return (S_ERROR); 2890d326b23bSrie } else { 2891ba2be530Sab196087 if ((*ld_targ.t_mr.mr_add_outrel)(rflags, rsp, ofl) == 2892ba2be530Sab196087 S_ERROR) 2893d326b23bSrie return (S_ERROR); 2894d326b23bSrie } 2895d326b23bSrie } 2896d326b23bSrie 2897d326b23bSrie rsp->rel_rtype = ortype; 2898d326b23bSrie 2899d326b23bSrie return (1); 2900d326b23bSrie } 29017c478bd9Sstevel@tonic-gate 29027c478bd9Sstevel@tonic-gate /* 29037c478bd9Sstevel@tonic-gate * Move Section related function 29047c478bd9Sstevel@tonic-gate */ 290557ef7aa9SRod Evans static void 290657ef7aa9SRod Evans newroffset_for_move(Sym_desc *sdp, Move *mvp, Xword offset1, Xword *offset2) 29077c478bd9Sstevel@tonic-gate { 290857ef7aa9SRod Evans Mv_desc *mdp; 290957ef7aa9SRod Evans Aliste idx; 29107c478bd9Sstevel@tonic-gate 29117c478bd9Sstevel@tonic-gate /* 291257ef7aa9SRod Evans * Search for matching move entry. 29137c478bd9Sstevel@tonic-gate */ 291457ef7aa9SRod Evans for (ALIST_TRAVERSE(sdp->sd_move, idx, mdp)) { 291557ef7aa9SRod Evans if (mdp->md_move == mvp) { 29167c478bd9Sstevel@tonic-gate /* 29177c478bd9Sstevel@tonic-gate * Update r_offset 29187c478bd9Sstevel@tonic-gate */ 291957ef7aa9SRod Evans *offset2 = (Xword)((mdp->md_oidx - 1) * sizeof (Move) + 29207c478bd9Sstevel@tonic-gate offset1 % sizeof (Move)); 292157ef7aa9SRod Evans return; 292257ef7aa9SRod Evans } 292357ef7aa9SRod Evans } 29247c478bd9Sstevel@tonic-gate } 29257c478bd9Sstevel@tonic-gate 29267c478bd9Sstevel@tonic-gate void 29275aefb655Srie ld_adj_movereloc(Ofl_desc *ofl, Rel_desc *arsp) 29287c478bd9Sstevel@tonic-gate { 2929bf994817SAli Bahrami Move *move = arsp->rel_aux->ra_move->mr_move; 2930bf994817SAli Bahrami Sym_desc *psdp = arsp->rel_aux->ra_move->mr_sym; 29317c478bd9Sstevel@tonic-gate Xword newoffset; 29327c478bd9Sstevel@tonic-gate 29337c478bd9Sstevel@tonic-gate if (arsp->rel_flags & FLG_REL_MOVETAB) { 29347c478bd9Sstevel@tonic-gate /* 29357c478bd9Sstevel@tonic-gate * We are relocating the move table itself. 29367c478bd9Sstevel@tonic-gate */ 293757ef7aa9SRod Evans newroffset_for_move(psdp, move, arsp->rel_roffset, 29387c478bd9Sstevel@tonic-gate &newoffset); 29395aefb655Srie DBG_CALL(Dbg_move_adjmovereloc(ofl->ofl_lml, arsp->rel_roffset, 29405aefb655Srie newoffset, psdp->sd_name)); 29417c478bd9Sstevel@tonic-gate arsp->rel_roffset = newoffset; 29427c478bd9Sstevel@tonic-gate } else { 29437c478bd9Sstevel@tonic-gate /* 29447c478bd9Sstevel@tonic-gate * We are expanding the partial symbol. So we are generating 29457c478bd9Sstevel@tonic-gate * the relocation entry relocating the expanded partial symbol. 29467c478bd9Sstevel@tonic-gate */ 29475aefb655Srie arsp->rel_roffset += psdp->sd_sym->st_value - 294835450702SAli Bahrami ofl->ofl_isparexpn->is_osdesc->os_shdr->sh_addr; 29495aefb655Srie DBG_CALL(Dbg_move_adjexpandreloc(ofl->ofl_lml, 29505aefb655Srie arsp->rel_roffset, psdp->sd_name)); 29517c478bd9Sstevel@tonic-gate } 29527c478bd9Sstevel@tonic-gate } 29537c478bd9Sstevel@tonic-gate 29547c478bd9Sstevel@tonic-gate /* 29557c478bd9Sstevel@tonic-gate * Partially Initialized Symbol Handling routines 2956635216b6SRod Evans * For RELA architecture, the second argument is reld->rel_raddend. For REL 2957635216b6SRod Evans * architecure, the second argument is the value stored at the relocation 2958635216b6SRod Evans * target address. 29597c478bd9Sstevel@tonic-gate */ 29607c478bd9Sstevel@tonic-gate Sym_desc * 29615aefb655Srie ld_am_I_partial(Rel_desc *reld, Xword val) 29627c478bd9Sstevel@tonic-gate { 29637c478bd9Sstevel@tonic-gate Ifl_desc *ifile = reld->rel_sym->sd_isc->is_file; 29647c478bd9Sstevel@tonic-gate int nlocs = ifile->ifl_locscnt, i; 29657c478bd9Sstevel@tonic-gate 29667c478bd9Sstevel@tonic-gate for (i = 1; i < nlocs; i++) { 29677c478bd9Sstevel@tonic-gate Sym *osym; 29687c478bd9Sstevel@tonic-gate Sym_desc *symd = ifile->ifl_oldndx[i]; 29697c478bd9Sstevel@tonic-gate 29707c478bd9Sstevel@tonic-gate if ((osym = symd->sd_osym) == 0) 29717c478bd9Sstevel@tonic-gate continue; 29727c478bd9Sstevel@tonic-gate if ((symd->sd_flags & FLG_SY_PAREXPN) == 0) 29737c478bd9Sstevel@tonic-gate continue; 29747c478bd9Sstevel@tonic-gate if ((osym->st_value <= val) && 29757c478bd9Sstevel@tonic-gate (osym->st_value + osym->st_size > val)) 29767c478bd9Sstevel@tonic-gate return (symd); 29777c478bd9Sstevel@tonic-gate } 297857ef7aa9SRod Evans return (NULL); 29797c478bd9Sstevel@tonic-gate } 29807c478bd9Sstevel@tonic-gate 2981ba2be530Sab196087 /* 2982ba2be530Sab196087 * Return True (1) if the code processing the given relocation 2983ba2be530Sab196087 * needs to perform byte swapping when accessing the section data. 2984ba2be530Sab196087 */ 2985ba2be530Sab196087 int 2986ba2be530Sab196087 ld_swap_reloc_data(Ofl_desc *ofl, Rel_desc *rsp) 2987ba2be530Sab196087 { 2988ba2be530Sab196087 /* 2989ba2be530Sab196087 * In a cross-link situation where the linker host and target 2990ba2be530Sab196087 * have opposite byte orders, it can be necessary to swap bytes 2991ba2be530Sab196087 * when doing relocation processing. This is indicated by the 2992ba2be530Sab196087 * presence of the FLG_OF1_ENCDIFF flag bit. However, swapping 2993ba2be530Sab196087 * is only needed for the section types that libelf doesn't 2994ba2be530Sab196087 * automatically xlate. 2995ba2be530Sab196087 */ 2996ba2be530Sab196087 if ((ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0) { 2997bf994817SAli Bahrami switch (RELAUX_GET_OSDESC(rsp)->os_shdr->sh_type) { 2998ba2be530Sab196087 case SHT_PROGBITS: 2999ba2be530Sab196087 return (1); 3000ba2be530Sab196087 3001ba2be530Sab196087 case SHT_SPARC_GOTDATA: 3002ba2be530Sab196087 if (ld_targ.t_m.m_mach == 3003ba2be530Sab196087 LD_TARG_BYCLASS(EM_SPARC, EM_SPARCV9)) 3004ba2be530Sab196087 return (1); 3005ba2be530Sab196087 break; 3006ba2be530Sab196087 3007ba2be530Sab196087 case SHT_AMD64_UNWIND: 3008ba2be530Sab196087 if (ld_targ.t_m.m_mach == EM_AMD64) 3009ba2be530Sab196087 return (1); 3010ba2be530Sab196087 break; 3011ba2be530Sab196087 } 3012ba2be530Sab196087 } 3013ba2be530Sab196087 3014ba2be530Sab196087 /* 3015ba2be530Sab196087 * If FLG_OF1_ENCDIFF isn't set, or the section isn't 3016ba2be530Sab196087 * progbits (or similar), then no swapping is needed. 3017ba2be530Sab196087 */ 3018ba2be530Sab196087 return (0); 3019ba2be530Sab196087 } 3020ba2be530Sab196087 3021ba2be530Sab196087 3022ba2be530Sab196087 3023cce0e03bSab196087 /* 3024cce0e03bSab196087 * Obtain the current value at the given relocation target. 3025cce0e03bSab196087 * 3026cce0e03bSab196087 * entry: 3027cce0e03bSab196087 * ofl - Output file descriptor 3028cce0e03bSab196087 * rsp - Relocation record 3029cce0e03bSab196087 * data - Pointer to relocation target 3030cce0e03bSab196087 * value - Address of variable to recieve value 3031cce0e03bSab196087 * 3032cce0e03bSab196087 * exit: 3033cce0e03bSab196087 * The value of the data at the relocation target has 3034cce0e03bSab196087 * been stored in value. 3035cce0e03bSab196087 */ 3036cce0e03bSab196087 int 3037cce0e03bSab196087 ld_reloc_targval_get(Ofl_desc *ofl, Rel_desc *rsp, uchar_t *data, Xword *value) 3038cce0e03bSab196087 { 3039cce0e03bSab196087 const Rel_entry *rep; 3040cce0e03bSab196087 3041ba2be530Sab196087 rep = &ld_targ.t_mr.mr_reloc_table[rsp->rel_rtype]; 3042cce0e03bSab196087 3043cce0e03bSab196087 switch (rep->re_fsize) { 3044cce0e03bSab196087 case 1: 3045cce0e03bSab196087 /* LINTED */ 3046cce0e03bSab196087 *value = (Xword) *((uchar_t *)data); 3047cce0e03bSab196087 break; 3048cce0e03bSab196087 case 2: 3049ba2be530Sab196087 { 3050ba2be530Sab196087 Half v; 3051ba2be530Sab196087 uchar_t *v_bytes = (uchar_t *)&v; 3052ba2be530Sab196087 3053ba2be530Sab196087 if (OFL_SWAP_RELOC_DATA(ofl, rsp)) { 3054ba2be530Sab196087 UL_ASSIGN_BSWAP_HALF(v_bytes, data); 3055ba2be530Sab196087 } else { 3056ba2be530Sab196087 UL_ASSIGN_HALF(v_bytes, data); 3057ba2be530Sab196087 } 3058ba2be530Sab196087 *value = (Xword) v; 3059ba2be530Sab196087 } 3060cce0e03bSab196087 break; 3061cce0e03bSab196087 case 4: 3062ba2be530Sab196087 { 3063ba2be530Sab196087 Word v; 3064ba2be530Sab196087 uchar_t *v_bytes = (uchar_t *)&v; 3065ba2be530Sab196087 3066ba2be530Sab196087 if (OFL_SWAP_RELOC_DATA(ofl, rsp)) { 3067ba2be530Sab196087 UL_ASSIGN_BSWAP_WORD(v_bytes, data); 3068ba2be530Sab196087 } else { 3069ba2be530Sab196087 UL_ASSIGN_WORD(v_bytes, data); 3070ba2be530Sab196087 } 3071ba2be530Sab196087 *value = (Xword) v; 3072ba2be530Sab196087 } 3073cce0e03bSab196087 break; 3074cce0e03bSab196087 default: 3075ba2be530Sab196087 { 3076ba2be530Sab196087 Conv_inv_buf_t inv_buf; 3077*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), 3078ba2be530Sab196087 conv_reloc_type(ld_targ.t_m.m_mach, rsp->rel_rtype, 3079ba2be530Sab196087 0, &inv_buf), rsp->rel_isdesc->is_file->ifl_name, 3080bf994817SAli Bahrami ld_reloc_sym_name(rsp), (int)rep->re_fsize); 3081ba2be530Sab196087 } 3082cce0e03bSab196087 return (0); 3083cce0e03bSab196087 } 3084cce0e03bSab196087 return (1); 3085cce0e03bSab196087 } 3086cce0e03bSab196087 3087cce0e03bSab196087 3088cce0e03bSab196087 /* 3089cce0e03bSab196087 * Set the value at the given relocation target. 3090cce0e03bSab196087 * 3091cce0e03bSab196087 * entry: 3092cce0e03bSab196087 * ofl - Output file descriptor 3093cce0e03bSab196087 * rsp - Relocation record 3094cce0e03bSab196087 * data - Pointer to relocation target 3095cce0e03bSab196087 * value - Address of variable to recieve value 3096cce0e03bSab196087 * 3097cce0e03bSab196087 * exit: 3098cce0e03bSab196087 * The value of the data at the relocation target has 3099cce0e03bSab196087 * been stored in value. 3100cce0e03bSab196087 */ 3101cce0e03bSab196087 int 3102cce0e03bSab196087 ld_reloc_targval_set(Ofl_desc *ofl, Rel_desc *rsp, uchar_t *data, Xword value) 3103cce0e03bSab196087 { 3104cce0e03bSab196087 const Rel_entry *rep; 3105cce0e03bSab196087 3106ba2be530Sab196087 rep = &ld_targ.t_mr.mr_reloc_table[rsp->rel_rtype]; 3107cce0e03bSab196087 3108cce0e03bSab196087 switch (rep->re_fsize) { 3109cce0e03bSab196087 case 1: 3110cce0e03bSab196087 /* LINTED */ 3111cce0e03bSab196087 *((uchar_t *)data) = (uchar_t)value; 3112cce0e03bSab196087 break; 3113cce0e03bSab196087 case 2: 3114ba2be530Sab196087 { 3115ba2be530Sab196087 Half v = (Half)value; 3116ba2be530Sab196087 uchar_t *v_bytes = (uchar_t *)&v; 3117ba2be530Sab196087 3118ba2be530Sab196087 if (OFL_SWAP_RELOC_DATA(ofl, rsp)) { 3119ba2be530Sab196087 UL_ASSIGN_BSWAP_HALF(data, v_bytes); 3120ba2be530Sab196087 } else { 3121ba2be530Sab196087 UL_ASSIGN_HALF(data, v_bytes); 3122ba2be530Sab196087 } 3123ba2be530Sab196087 } 3124cce0e03bSab196087 break; 3125cce0e03bSab196087 case 4: 3126ba2be530Sab196087 { 3127ba2be530Sab196087 Word v = (Word)value; 3128ba2be530Sab196087 uchar_t *v_bytes = (uchar_t *)&v; 3129ba2be530Sab196087 3130ba2be530Sab196087 if (OFL_SWAP_RELOC_DATA(ofl, rsp)) { 3131ba2be530Sab196087 UL_ASSIGN_BSWAP_WORD(data, v_bytes); 3132ba2be530Sab196087 } else { 3133ba2be530Sab196087 UL_ASSIGN_WORD(data, v_bytes); 3134ba2be530Sab196087 } 3135ba2be530Sab196087 } 3136cce0e03bSab196087 break; 3137cce0e03bSab196087 default: 3138ba2be530Sab196087 { 3139ba2be530Sab196087 Conv_inv_buf_t inv_buf; 3140*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), 3141ba2be530Sab196087 conv_reloc_type(ld_targ.t_m.m_mach, rsp->rel_rtype, 3142ba2be530Sab196087 0, &inv_buf), rsp->rel_isdesc->is_file->ifl_name, 3143bf994817SAli Bahrami ld_reloc_sym_name(rsp), (int)rep->re_fsize); 3144ba2be530Sab196087 } 3145cce0e03bSab196087 return (0); 3146cce0e03bSab196087 } 3147cce0e03bSab196087 return (1); 3148cce0e03bSab196087 } 3149cce0e03bSab196087 3150cce0e03bSab196087 31517c478bd9Sstevel@tonic-gate /* 31527c478bd9Sstevel@tonic-gate * Because of the combinations of 32-bit lib providing 64-bit support, and 31537c478bd9Sstevel@tonic-gate * visa-versa, the use of krtld's dorelocs can result in differing message 31547c478bd9Sstevel@tonic-gate * requirements that make msg.c/msg.h creation and chkmsg "interesting". 31557c478bd9Sstevel@tonic-gate * Thus the actual message files contain a couple of entries to satisfy 31567c478bd9Sstevel@tonic-gate * each architectures build. Here we add dummy calls to quieten chkmsg. 31577c478bd9Sstevel@tonic-gate * 31587c478bd9Sstevel@tonic-gate * chkmsg: MSG_INTL(MSG_REL_NOFIT) 31597c478bd9Sstevel@tonic-gate * chkmsg: MSG_INTL(MSG_REL_NONALIGN) 31607c478bd9Sstevel@tonic-gate */ 3161