1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate * 26*0Sstevel@tonic-gate * Update any dynamic entry offsets. One issue with dynamic entries is that 27*0Sstevel@tonic-gate * you only know whether they refer to a value or an offset if you know each 28*0Sstevel@tonic-gate * type. Thus we check for all types we know about, it a type is found that 29*0Sstevel@tonic-gate * we don't know about then return and error as we have no idea what to do. 30*0Sstevel@tonic-gate */ 31*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <libelf.h> 34*0Sstevel@tonic-gate #include <link.h> 35*0Sstevel@tonic-gate #include "libld.h" 36*0Sstevel@tonic-gate #include "msg.h" 37*0Sstevel@tonic-gate #include "rtld.h" 38*0Sstevel@tonic-gate #include "_librtld.h" 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate int 41*0Sstevel@tonic-gate update_dynamic(Cache * cache, Cache * _cache, Rt_map * lmp, int flags, 42*0Sstevel@tonic-gate Addr addr, Off off, const char *file, Xword null, Xword data, Xword func, 43*0Sstevel@tonic-gate Xword entsize, Xword checksum) 44*0Sstevel@tonic-gate { 45*0Sstevel@tonic-gate Dyn * dyn = (Dyn *)_cache->c_data->d_buf, * posdyn = 0; 46*0Sstevel@tonic-gate const char *strs; 47*0Sstevel@tonic-gate Cache * __cache; 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate /* 50*0Sstevel@tonic-gate * If we're dealing with an object that might have bound to an external 51*0Sstevel@tonic-gate * dependency establish our string table for possible NEEDED processing. 52*0Sstevel@tonic-gate */ 53*0Sstevel@tonic-gate if (flags & RTLD_REL_DEPENDS) { 54*0Sstevel@tonic-gate __cache = &cache[_cache->c_shdr->sh_link]; 55*0Sstevel@tonic-gate strs = (const char *)__cache->c_data->d_buf; 56*0Sstevel@tonic-gate } 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* 59*0Sstevel@tonic-gate * Loop through the dynamic table updating all offsets. 60*0Sstevel@tonic-gate */ 61*0Sstevel@tonic-gate while (dyn->d_tag != DT_NULL) { 62*0Sstevel@tonic-gate switch ((Xword)dyn->d_tag) { 63*0Sstevel@tonic-gate case DT_NEEDED: 64*0Sstevel@tonic-gate if (posdyn) { 65*0Sstevel@tonic-gate Rt_map * dlmp; 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate /* 68*0Sstevel@tonic-gate * Determine whether this dependency has been 69*0Sstevel@tonic-gate * loaded (this is the most generic way to check 70*0Sstevel@tonic-gate * any alias names), and if it has been bound 71*0Sstevel@tonic-gate * to, undo any lazy-loading position flag. 72*0Sstevel@tonic-gate */ 73*0Sstevel@tonic-gate if (dlmp = is_so_loaded(LIST(lmp), 74*0Sstevel@tonic-gate (strs + dyn->d_un.d_val), 1)) { 75*0Sstevel@tonic-gate Bnd_desc ** bdpp; 76*0Sstevel@tonic-gate Aliste off; 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate for (ALIST_TRAVERSE(DEPENDS(lmp), off, 79*0Sstevel@tonic-gate bdpp)) { 80*0Sstevel@tonic-gate if (dlmp == (*bdpp)->b_depend) { 81*0Sstevel@tonic-gate posdyn->d_un.d_val &= 82*0Sstevel@tonic-gate ~DF_P1_LAZYLOAD; 83*0Sstevel@tonic-gate break; 84*0Sstevel@tonic-gate } 85*0Sstevel@tonic-gate } 86*0Sstevel@tonic-gate } 87*0Sstevel@tonic-gate } 88*0Sstevel@tonic-gate break; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate case DT_RELAENT: 91*0Sstevel@tonic-gate case DT_STRSZ: 92*0Sstevel@tonic-gate case DT_SYMENT: 93*0Sstevel@tonic-gate case DT_SONAME: 94*0Sstevel@tonic-gate case DT_RPATH: 95*0Sstevel@tonic-gate case DT_SYMBOLIC: 96*0Sstevel@tonic-gate case DT_RELENT: 97*0Sstevel@tonic-gate case DT_PLTREL: 98*0Sstevel@tonic-gate case DT_TEXTREL: 99*0Sstevel@tonic-gate case DT_VERDEFNUM: 100*0Sstevel@tonic-gate case DT_VERNEEDNUM: 101*0Sstevel@tonic-gate case DT_AUXILIARY: 102*0Sstevel@tonic-gate case DT_USED: 103*0Sstevel@tonic-gate case DT_FILTER: 104*0Sstevel@tonic-gate case DT_DEPRECATED_SPARC_REGISTER: 105*0Sstevel@tonic-gate case M_DT_REGISTER: 106*0Sstevel@tonic-gate case DT_BIND_NOW: 107*0Sstevel@tonic-gate case DT_INIT_ARRAYSZ: 108*0Sstevel@tonic-gate case DT_FINI_ARRAYSZ: 109*0Sstevel@tonic-gate case DT_RUNPATH: 110*0Sstevel@tonic-gate case DT_FLAGS: 111*0Sstevel@tonic-gate case DT_CONFIG: 112*0Sstevel@tonic-gate case DT_DEPAUDIT: 113*0Sstevel@tonic-gate case DT_AUDIT: 114*0Sstevel@tonic-gate break; 115*0Sstevel@tonic-gate case DT_PLTGOT: 116*0Sstevel@tonic-gate case DT_HASH: 117*0Sstevel@tonic-gate case DT_STRTAB: 118*0Sstevel@tonic-gate case DT_SYMTAB: 119*0Sstevel@tonic-gate case DT_INIT: 120*0Sstevel@tonic-gate case DT_FINI: 121*0Sstevel@tonic-gate case DT_VERSYM: 122*0Sstevel@tonic-gate case DT_VERDEF: 123*0Sstevel@tonic-gate case DT_VERNEED: 124*0Sstevel@tonic-gate case DT_INIT_ARRAY: 125*0Sstevel@tonic-gate case DT_FINI_ARRAY: 126*0Sstevel@tonic-gate dyn->d_un.d_ptr += addr; 127*0Sstevel@tonic-gate break; 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate /* 130*0Sstevel@tonic-gate * If the memory image is being used, this element would have 131*0Sstevel@tonic-gate * been initialized to the runtime linkers internal link-map 132*0Sstevel@tonic-gate * list. Clear it. 133*0Sstevel@tonic-gate */ 134*0Sstevel@tonic-gate case DT_DEBUG: 135*0Sstevel@tonic-gate dyn->d_un.d_val = 0; 136*0Sstevel@tonic-gate break; 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate /* 139*0Sstevel@tonic-gate * The number of relocations may have been reduced if 140*0Sstevel@tonic-gate * relocations have been saved in the new image. Thus we 141*0Sstevel@tonic-gate * compute the new relocation size and start. 142*0Sstevel@tonic-gate */ 143*0Sstevel@tonic-gate case DT_RELASZ: 144*0Sstevel@tonic-gate case DT_RELSZ: 145*0Sstevel@tonic-gate dyn->d_un.d_val = ((data + func) * entsize); 146*0Sstevel@tonic-gate break; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate case DT_RELA: 149*0Sstevel@tonic-gate case DT_REL: 150*0Sstevel@tonic-gate dyn->d_un.d_ptr = (addr + off + (null * entsize)); 151*0Sstevel@tonic-gate break; 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate /* 154*0Sstevel@tonic-gate * If relative relocations have been processed clear the count. 155*0Sstevel@tonic-gate */ 156*0Sstevel@tonic-gate case DT_RELACOUNT: 157*0Sstevel@tonic-gate case DT_RELCOUNT: 158*0Sstevel@tonic-gate if (flags & RTLD_REL_RELATIVE) 159*0Sstevel@tonic-gate dyn->d_un.d_val = 0; 160*0Sstevel@tonic-gate break; 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate case DT_PLTRELSZ: 163*0Sstevel@tonic-gate dyn->d_un.d_val = (func * entsize); 164*0Sstevel@tonic-gate break; 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate case DT_JMPREL: 167*0Sstevel@tonic-gate dyn->d_un.d_ptr = (addr + off + 168*0Sstevel@tonic-gate ((null + data) * entsize)); 169*0Sstevel@tonic-gate break; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate /* 172*0Sstevel@tonic-gate * Recompute the images elf checksum. 173*0Sstevel@tonic-gate */ 174*0Sstevel@tonic-gate case DT_CHECKSUM: 175*0Sstevel@tonic-gate dyn->d_un.d_val = checksum; 176*0Sstevel@tonic-gate break; 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate /* 179*0Sstevel@tonic-gate * If a flag entry is available, indicate if this image has 180*0Sstevel@tonic-gate * been generated via the configuration process (crle(1)). 181*0Sstevel@tonic-gate * Because we only started depositing DT_FLAGS_1 entries in all 182*0Sstevel@tonic-gate * objects starting with Solaris 8, set a feature flag if it 183*0Sstevel@tonic-gate * is present (these got added in Solaris 7). 184*0Sstevel@tonic-gate * The runtime linker may use this flag to search for a local 185*0Sstevel@tonic-gate * configuration file - this is only meaningful in executables 186*0Sstevel@tonic-gate * but the flag has value for identifying images regardless. 187*0Sstevel@tonic-gate * 188*0Sstevel@tonic-gate * If this file is acting as a filter, and dependency 189*0Sstevel@tonic-gate * relocations have been processed (a filter is thought of as a 190*0Sstevel@tonic-gate * dependency in terms of symbol binding), we may have bound to 191*0Sstevel@tonic-gate * the filtee, and hence carried out the relocation. Indicate 192*0Sstevel@tonic-gate * that the filtee must be preloaded, as the .plt won't get 193*0Sstevel@tonic-gate * exercised to cause its normal loading. 194*0Sstevel@tonic-gate */ 195*0Sstevel@tonic-gate case DT_FLAGS_1: 196*0Sstevel@tonic-gate if (flags & RTLD_CONFSET) 197*0Sstevel@tonic-gate dyn->d_un.d_val |= DF_1_CONFALT; 198*0Sstevel@tonic-gate if ((flags & RTLD_REL_DEPENDS) && 199*0Sstevel@tonic-gate (FLAGS1(lmp)) & MSK_RT_FILTER) 200*0Sstevel@tonic-gate dyn->d_un.d_val |= DF_1_LOADFLTR; 201*0Sstevel@tonic-gate break; 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate case DT_FEATURE_1: 204*0Sstevel@tonic-gate if (flags & RTLD_CONFSET) 205*0Sstevel@tonic-gate dyn->d_un.d_val |= DTF_1_CONFEXP; 206*0Sstevel@tonic-gate break; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate /* 209*0Sstevel@tonic-gate * If a position flag is available save it for possible update 210*0Sstevel@tonic-gate * when processing the next NEEDED tag. 211*0Sstevel@tonic-gate */ 212*0Sstevel@tonic-gate case DT_POSFLAG_1: 213*0Sstevel@tonic-gate if (flags & RTLD_REL_DEPENDS) { 214*0Sstevel@tonic-gate posdyn = dyn++; 215*0Sstevel@tonic-gate continue; 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate break; 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate /* 220*0Sstevel@tonic-gate * Collect the defaults. 221*0Sstevel@tonic-gate */ 222*0Sstevel@tonic-gate default: 223*0Sstevel@tonic-gate /* 224*0Sstevel@tonic-gate * If d_val is used, don't touch. 225*0Sstevel@tonic-gate */ 226*0Sstevel@tonic-gate if ((dyn->d_tag >= DT_VALRNGLO) && 227*0Sstevel@tonic-gate (dyn->d_tag <= DT_VALRNGHI)) 228*0Sstevel@tonic-gate break; 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate /* 231*0Sstevel@tonic-gate * If d_ptr is used, adjust. Note, some entries that 232*0Sstevel@tonic-gate * fell into this range are offsets into the dynamic 233*0Sstevel@tonic-gate * string table. Although these would need modifying 234*0Sstevel@tonic-gate * if the section itself were resized, there is no 235*0Sstevel@tonic-gate * resizing with dldump(). Entries that correspond to 236*0Sstevel@tonic-gate * offsets are picked off in the initial DT_ loop 237*0Sstevel@tonic-gate * above. 238*0Sstevel@tonic-gate */ 239*0Sstevel@tonic-gate if ((dyn->d_tag >= DT_ADDRRNGLO) && 240*0Sstevel@tonic-gate (dyn->d_tag <= DT_ADDRRNGHI)) { 241*0Sstevel@tonic-gate dyn->d_un.d_ptr += addr; 242*0Sstevel@tonic-gate break; 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate /* 246*0Sstevel@tonic-gate * Check to see if this DT_ entry conforms 247*0Sstevel@tonic-gate * to the DT_ENCODING rules. 248*0Sstevel@tonic-gate */ 249*0Sstevel@tonic-gate if ((dyn->d_tag >= DT_ENCODING) && 250*0Sstevel@tonic-gate (dyn->d_tag <= DT_HIOS)) { 251*0Sstevel@tonic-gate /* 252*0Sstevel@tonic-gate * Even tag values are ADDRESS encodings 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate if ((dyn->d_tag % 2) == 0) { 255*0Sstevel@tonic-gate dyn->d_un.d_ptr += addr; 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate break; 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate eprintf(ERR_WARNING, MSG_INTL(MSG_DT_UNKNOWN), file, 260*0Sstevel@tonic-gate EC_XWORD(dyn->d_tag)); 261*0Sstevel@tonic-gate return (1); 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate posdyn = 0; 264*0Sstevel@tonic-gate dyn++; 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate return (0); 267*0Sstevel@tonic-gate } 268