1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <string.h> 31*7c478bd9Sstevel@tonic-gate #include <link.h> 32*7c478bd9Sstevel@tonic-gate #include "debug.h" 33*7c478bd9Sstevel@tonic-gate #include "msg.h" 34*7c478bd9Sstevel@tonic-gate #include "_libld.h" 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate /* 38*7c478bd9Sstevel@tonic-gate * Given a group signature symbol - scan through the global list 39*7c478bd9Sstevel@tonic-gate * of GROUP sections to determine if we have a conflict/discard. 40*7c478bd9Sstevel@tonic-gate * If this is the first time we see a group signature - add it to the 41*7c478bd9Sstevel@tonic-gate * global list. 42*7c478bd9Sstevel@tonic-gate * 43*7c478bd9Sstevel@tonic-gate * Returns: 44*7c478bd9Sstevel@tonic-gate * 0 - Group kept and added to global list. 45*7c478bd9Sstevel@tonic-gate * 1 - Group should be discarded. 46*7c478bd9Sstevel@tonic-gate */ 47*7c478bd9Sstevel@tonic-gate uintptr_t 48*7c478bd9Sstevel@tonic-gate scan_global_groups(Group_desc * gdesc, Ofl_desc * ofl) 49*7c478bd9Sstevel@tonic-gate { 50*7c478bd9Sstevel@tonic-gate Group_desc * _gdesc; 51*7c478bd9Sstevel@tonic-gate Listnode * lnp; 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate /* 54*7c478bd9Sstevel@tonic-gate * Scan through global list - if we find a group of the 55*7c478bd9Sstevel@tonic-gate * same name - we return 0 saying this new group should 56*7c478bd9Sstevel@tonic-gate * be discarded (since only COMDAT's get here currently). 57*7c478bd9Sstevel@tonic-gate */ 58*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ofl->ofl_groups, lnp, _gdesc)) 59*7c478bd9Sstevel@tonic-gate if (strcmp(_gdesc->gd_symname, gdesc->gd_symname) == 0) { 60*7c478bd9Sstevel@tonic-gate gdesc->gd_flags |= GRP_FLG_DISCARD; 61*7c478bd9Sstevel@tonic-gate return (1); 62*7c478bd9Sstevel@tonic-gate } 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate if (list_appendc(&ofl->ofl_groups, gdesc) == 0) 65*7c478bd9Sstevel@tonic-gate return (S_ERROR); 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate return (0); 68*7c478bd9Sstevel@tonic-gate } 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate Group_desc * 72*7c478bd9Sstevel@tonic-gate get_group_desc(Ofl_desc *ofl, Is_desc *isp) 73*7c478bd9Sstevel@tonic-gate { 74*7c478bd9Sstevel@tonic-gate Ifl_desc *ifl = isp->is_file; 75*7c478bd9Sstevel@tonic-gate Elf *elf = ifl->ifl_elf; 76*7c478bd9Sstevel@tonic-gate uint_t scnndx = isp->is_scnndx; 77*7c478bd9Sstevel@tonic-gate Group_desc *gdesc; 78*7c478bd9Sstevel@tonic-gate Listnode *lnp; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * If this is the first section of with the SHF_GROUP flag 83*7c478bd9Sstevel@tonic-gate * set - then we havn't yet scanned for - and found our 84*7c478bd9Sstevel@tonic-gate * group sections. If thats so - do it now. 85*7c478bd9Sstevel@tonic-gate */ 86*7c478bd9Sstevel@tonic-gate if (ifl->ifl_groups.head == 0) { 87*7c478bd9Sstevel@tonic-gate Elf_Scn *scn = 0; 88*7c478bd9Sstevel@tonic-gate while (scn = elf_nextscn(elf, scn)) { 89*7c478bd9Sstevel@tonic-gate Shdr *shdr; 90*7c478bd9Sstevel@tonic-gate Shdr *_shdr; 91*7c478bd9Sstevel@tonic-gate Sym *sym; 92*7c478bd9Sstevel@tonic-gate const char *symname; 93*7c478bd9Sstevel@tonic-gate Elf_Scn *_scn; 94*7c478bd9Sstevel@tonic-gate Elf_Data *data; 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate shdr = elf_getshdr(scn); 97*7c478bd9Sstevel@tonic-gate if (shdr->sh_type != SHT_GROUP) 98*7c478bd9Sstevel@tonic-gate continue; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate /* 101*7c478bd9Sstevel@tonic-gate * Confirm that the sh_link points to a 102*7c478bd9Sstevel@tonic-gate * valid section. 103*7c478bd9Sstevel@tonic-gate */ 104*7c478bd9Sstevel@tonic-gate if ((shdr->sh_link == SHN_UNDEF) || 105*7c478bd9Sstevel@tonic-gate (shdr->sh_link >= ifl->ifl_shnum)) { 106*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_FIL_INVSHLINK), 107*7c478bd9Sstevel@tonic-gate ifl->ifl_name, elf_strptr(elf, 108*7c478bd9Sstevel@tonic-gate ifl->ifl_shstrndx, 109*7c478bd9Sstevel@tonic-gate shdr->sh_name), 110*7c478bd9Sstevel@tonic-gate EC_XWORD(shdr->sh_link)); 111*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 112*7c478bd9Sstevel@tonic-gate continue; 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate if (shdr->sh_entsize == 0) { 116*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, 117*7c478bd9Sstevel@tonic-gate MSG_INTL(MSG_FIL_INVSHENTSIZE), 118*7c478bd9Sstevel@tonic-gate ifl->ifl_name, elf_strptr(elf, 119*7c478bd9Sstevel@tonic-gate ifl->ifl_shstrndx, 120*7c478bd9Sstevel@tonic-gate shdr->sh_name), 121*7c478bd9Sstevel@tonic-gate EC_XWORD(shdr->sh_entsize)); 122*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 123*7c478bd9Sstevel@tonic-gate continue; 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* 127*7c478bd9Sstevel@tonic-gate * Get associated symbol table 128*7c478bd9Sstevel@tonic-gate */ 129*7c478bd9Sstevel@tonic-gate _scn = elf_getscn(elf, shdr->sh_link); 130*7c478bd9Sstevel@tonic-gate _shdr = elf_getshdr(_scn); 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* 133*7c478bd9Sstevel@tonic-gate * Sanity check the sh_link field (which points to 134*7c478bd9Sstevel@tonic-gate * a symbol table entry) against the size of the 135*7c478bd9Sstevel@tonic-gate * symbol table. 136*7c478bd9Sstevel@tonic-gate */ 137*7c478bd9Sstevel@tonic-gate if ((shdr->sh_info == SHN_UNDEF) || 138*7c478bd9Sstevel@tonic-gate (shdr->sh_info >= (Word)(_shdr->sh_size / 139*7c478bd9Sstevel@tonic-gate _shdr->sh_entsize))) { 140*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_FIL_INVSHINFO), 141*7c478bd9Sstevel@tonic-gate ifl->ifl_name, elf_strptr(elf, 142*7c478bd9Sstevel@tonic-gate ifl->ifl_shstrndx, 143*7c478bd9Sstevel@tonic-gate shdr->sh_name), 144*7c478bd9Sstevel@tonic-gate EC_XWORD(shdr->sh_info)); 145*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 146*7c478bd9Sstevel@tonic-gate continue; 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate data = elf_getdata(_scn, 0); 150*7c478bd9Sstevel@tonic-gate sym = data->d_buf; 151*7c478bd9Sstevel@tonic-gate sym += shdr->sh_info; 152*7c478bd9Sstevel@tonic-gate symname = elf_strptr(elf, _shdr->sh_link, sym->st_name); 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate if ((gdesc = libld_calloc(sizeof (Group_desc), 1)) == 0) 155*7c478bd9Sstevel@tonic-gate return ((Group_desc *)S_ERROR); 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate gdesc->gd_gsectname = elf_strptr(elf, 158*7c478bd9Sstevel@tonic-gate ifl->ifl_shstrndx, shdr->sh_name); 159*7c478bd9Sstevel@tonic-gate gdesc->gd_symname = symname; 160*7c478bd9Sstevel@tonic-gate gdesc->gd_sym = sym; 161*7c478bd9Sstevel@tonic-gate gdesc->gd_scn = scn; 162*7c478bd9Sstevel@tonic-gate data = elf_getdata(scn, 0); 163*7c478bd9Sstevel@tonic-gate gdesc->gd_groupdata = data->d_buf; 164*7c478bd9Sstevel@tonic-gate gdesc->gd_gdcnt = data->d_size / sizeof (Word); 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * If this group is a COMDAT group - then we 167*7c478bd9Sstevel@tonic-gate * need to find the 'signature' symbol to determine 168*7c478bd9Sstevel@tonic-gate * if this is group is to be kept or discarded. 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate if (gdesc->gd_groupdata[0] & GRP_COMDAT) { 171*7c478bd9Sstevel@tonic-gate if ((ELF_ST_BIND(sym->st_info) != STB_LOCAL) && 172*7c478bd9Sstevel@tonic-gate (sym->st_shndx != SHN_UNDEF)) { 173*7c478bd9Sstevel@tonic-gate if (scan_global_groups(gdesc, ofl) 174*7c478bd9Sstevel@tonic-gate == S_ERROR) 175*7c478bd9Sstevel@tonic-gate return ((Group_desc *)S_ERROR); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate if (list_appendc(&ifl->ifl_groups, gdesc) == 0) 179*7c478bd9Sstevel@tonic-gate return ((Group_desc *)S_ERROR); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * Now we scan through the GROUP sections associated with 185*7c478bd9Sstevel@tonic-gate * this file - to find the matching group section. 186*7c478bd9Sstevel@tonic-gate */ 187*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ifl->ifl_groups, lnp, gdesc)) { 188*7c478bd9Sstevel@tonic-gate size_t i; 189*7c478bd9Sstevel@tonic-gate Word * gdata; 190*7c478bd9Sstevel@tonic-gate if (isp->is_shdr->sh_type == SHT_GROUP) { 191*7c478bd9Sstevel@tonic-gate if ((size_t)isp->is_scnndx == 192*7c478bd9Sstevel@tonic-gate elf_ndxscn(gdesc->gd_scn)) { 193*7c478bd9Sstevel@tonic-gate isp->is_group = gdesc; 194*7c478bd9Sstevel@tonic-gate return (gdesc); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate continue; 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate gdata = gdesc->gd_groupdata; 200*7c478bd9Sstevel@tonic-gate for (i = 1; i < gdesc->gd_gdcnt; i++) { 201*7c478bd9Sstevel@tonic-gate if (gdata[i] == scnndx) { 202*7c478bd9Sstevel@tonic-gate isp->is_group = gdesc; 203*7c478bd9Sstevel@tonic-gate return (gdesc); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_ELF_NOGROUPSECT), ifl->ifl_name, 208*7c478bd9Sstevel@tonic-gate isp->is_name); 209*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 210*7c478bd9Sstevel@tonic-gate return ((Group_desc *)0); 211*7c478bd9Sstevel@tonic-gate } 212