10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51618Srie * Common Development and Distribution License (the "License"). 61618Srie * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211618Srie 220Sstevel@tonic-gate /* 23*5892Sab196087 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate * 260Sstevel@tonic-gate * Update any dynamic entry offsets. One issue with dynamic entries is that 270Sstevel@tonic-gate * you only know whether they refer to a value or an offset if you know each 280Sstevel@tonic-gate * type. Thus we check for all types we know about, it a type is found that 290Sstevel@tonic-gate * we don't know about then return and error as we have no idea what to do. 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <libelf.h> 340Sstevel@tonic-gate #include <link.h> 350Sstevel@tonic-gate #include "libld.h" 360Sstevel@tonic-gate #include "msg.h" 370Sstevel@tonic-gate #include "rtld.h" 380Sstevel@tonic-gate #include "_librtld.h" 390Sstevel@tonic-gate 400Sstevel@tonic-gate int 411618Srie update_dynamic(Cache *cache, Cache *_cache, Rt_map *lmp, int flags, 420Sstevel@tonic-gate Addr addr, Off off, const char *file, Xword null, Xword data, Xword func, 430Sstevel@tonic-gate Xword entsize, Xword checksum) 440Sstevel@tonic-gate { 451618Srie Dyn *dyn = (Dyn *)_cache->c_data->d_buf, *posdyn = 0; 460Sstevel@tonic-gate const char *strs; 471618Srie Cache *__cache; 480Sstevel@tonic-gate 490Sstevel@tonic-gate /* 500Sstevel@tonic-gate * If we're dealing with an object that might have bound to an external 510Sstevel@tonic-gate * dependency establish our string table for possible NEEDED processing. 520Sstevel@tonic-gate */ 530Sstevel@tonic-gate if (flags & RTLD_REL_DEPENDS) { 540Sstevel@tonic-gate __cache = &cache[_cache->c_shdr->sh_link]; 550Sstevel@tonic-gate strs = (const char *)__cache->c_data->d_buf; 560Sstevel@tonic-gate } 570Sstevel@tonic-gate 580Sstevel@tonic-gate /* 590Sstevel@tonic-gate * Loop through the dynamic table updating all offsets. 600Sstevel@tonic-gate */ 610Sstevel@tonic-gate while (dyn->d_tag != DT_NULL) { 620Sstevel@tonic-gate switch ((Xword)dyn->d_tag) { 630Sstevel@tonic-gate case DT_NEEDED: 640Sstevel@tonic-gate if (posdyn) { 651618Srie Rt_map *dlmp; 660Sstevel@tonic-gate 670Sstevel@tonic-gate /* 680Sstevel@tonic-gate * Determine whether this dependency has been 690Sstevel@tonic-gate * loaded (this is the most generic way to check 700Sstevel@tonic-gate * any alias names), and if it has been bound 710Sstevel@tonic-gate * to, undo any lazy-loading position flag. 720Sstevel@tonic-gate */ 730Sstevel@tonic-gate if (dlmp = is_so_loaded(LIST(lmp), 743787Srie (strs + dyn->d_un.d_val))) { 75*5892Sab196087 Bnd_desc *bdp; 76*5892Sab196087 Aliste idx; 770Sstevel@tonic-gate 78*5892Sab196087 for (APLIST_TRAVERSE(DEPENDS(lmp), idx, 79*5892Sab196087 bdp)) { 80*5892Sab196087 if (dlmp == bdp->b_depend) { 81*5892Sab196087 posdyn->d_un.d_val &= 82*5892Sab196087 ~DF_P1_LAZYLOAD; 83*5892Sab196087 break; 840Sstevel@tonic-gate } 850Sstevel@tonic-gate } 860Sstevel@tonic-gate } 870Sstevel@tonic-gate } 880Sstevel@tonic-gate break; 890Sstevel@tonic-gate 900Sstevel@tonic-gate case DT_RELAENT: 910Sstevel@tonic-gate case DT_STRSZ: 920Sstevel@tonic-gate case DT_SYMENT: 930Sstevel@tonic-gate case DT_SONAME: 940Sstevel@tonic-gate case DT_RPATH: 950Sstevel@tonic-gate case DT_SYMBOLIC: 960Sstevel@tonic-gate case DT_RELENT: 970Sstevel@tonic-gate case DT_PLTREL: 980Sstevel@tonic-gate case DT_TEXTREL: 990Sstevel@tonic-gate case DT_VERDEFNUM: 1000Sstevel@tonic-gate case DT_VERNEEDNUM: 1010Sstevel@tonic-gate case DT_AUXILIARY: 1020Sstevel@tonic-gate case DT_USED: 1030Sstevel@tonic-gate case DT_FILTER: 1040Sstevel@tonic-gate case DT_DEPRECATED_SPARC_REGISTER: 1050Sstevel@tonic-gate case M_DT_REGISTER: 1060Sstevel@tonic-gate case DT_BIND_NOW: 1070Sstevel@tonic-gate case DT_INIT_ARRAYSZ: 1080Sstevel@tonic-gate case DT_FINI_ARRAYSZ: 1090Sstevel@tonic-gate case DT_RUNPATH: 1100Sstevel@tonic-gate case DT_FLAGS: 1110Sstevel@tonic-gate case DT_CONFIG: 1120Sstevel@tonic-gate case DT_DEPAUDIT: 1130Sstevel@tonic-gate case DT_AUDIT: 1142766Sab196087 case DT_SUNW_SYMSZ: 1150Sstevel@tonic-gate break; 1160Sstevel@tonic-gate case DT_PLTGOT: 1170Sstevel@tonic-gate case DT_HASH: 1180Sstevel@tonic-gate case DT_STRTAB: 1190Sstevel@tonic-gate case DT_SYMTAB: 1202766Sab196087 case DT_SUNW_SYMTAB: 1210Sstevel@tonic-gate case DT_INIT: 1220Sstevel@tonic-gate case DT_FINI: 1230Sstevel@tonic-gate case DT_VERSYM: 1240Sstevel@tonic-gate case DT_VERDEF: 1250Sstevel@tonic-gate case DT_VERNEED: 1260Sstevel@tonic-gate case DT_INIT_ARRAY: 1270Sstevel@tonic-gate case DT_FINI_ARRAY: 1280Sstevel@tonic-gate dyn->d_un.d_ptr += addr; 1290Sstevel@tonic-gate break; 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /* 1320Sstevel@tonic-gate * If the memory image is being used, this element would have 1330Sstevel@tonic-gate * been initialized to the runtime linkers internal link-map 1340Sstevel@tonic-gate * list. Clear it. 1350Sstevel@tonic-gate */ 1360Sstevel@tonic-gate case DT_DEBUG: 1370Sstevel@tonic-gate dyn->d_un.d_val = 0; 1380Sstevel@tonic-gate break; 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate /* 1410Sstevel@tonic-gate * The number of relocations may have been reduced if 1420Sstevel@tonic-gate * relocations have been saved in the new image. Thus we 1430Sstevel@tonic-gate * compute the new relocation size and start. 1440Sstevel@tonic-gate */ 1450Sstevel@tonic-gate case DT_RELASZ: 1460Sstevel@tonic-gate case DT_RELSZ: 1470Sstevel@tonic-gate dyn->d_un.d_val = ((data + func) * entsize); 1480Sstevel@tonic-gate break; 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate case DT_RELA: 1510Sstevel@tonic-gate case DT_REL: 1520Sstevel@tonic-gate dyn->d_un.d_ptr = (addr + off + (null * entsize)); 1530Sstevel@tonic-gate break; 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate /* 1560Sstevel@tonic-gate * If relative relocations have been processed clear the count. 1570Sstevel@tonic-gate */ 1580Sstevel@tonic-gate case DT_RELACOUNT: 1590Sstevel@tonic-gate case DT_RELCOUNT: 1600Sstevel@tonic-gate if (flags & RTLD_REL_RELATIVE) 1610Sstevel@tonic-gate dyn->d_un.d_val = 0; 1620Sstevel@tonic-gate break; 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate case DT_PLTRELSZ: 1650Sstevel@tonic-gate dyn->d_un.d_val = (func * entsize); 1660Sstevel@tonic-gate break; 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate case DT_JMPREL: 1690Sstevel@tonic-gate dyn->d_un.d_ptr = (addr + off + 170*5892Sab196087 ((null + data) * entsize)); 1710Sstevel@tonic-gate break; 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate /* 1740Sstevel@tonic-gate * Recompute the images elf checksum. 1750Sstevel@tonic-gate */ 1760Sstevel@tonic-gate case DT_CHECKSUM: 1770Sstevel@tonic-gate dyn->d_un.d_val = checksum; 1780Sstevel@tonic-gate break; 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate /* 1810Sstevel@tonic-gate * If a flag entry is available, indicate if this image has 1820Sstevel@tonic-gate * been generated via the configuration process (crle(1)). 1830Sstevel@tonic-gate * Because we only started depositing DT_FLAGS_1 entries in all 1840Sstevel@tonic-gate * objects starting with Solaris 8, set a feature flag if it 1850Sstevel@tonic-gate * is present (these got added in Solaris 7). 1860Sstevel@tonic-gate * The runtime linker may use this flag to search for a local 1870Sstevel@tonic-gate * configuration file - this is only meaningful in executables 1880Sstevel@tonic-gate * but the flag has value for identifying images regardless. 1890Sstevel@tonic-gate * 1900Sstevel@tonic-gate * If this file is acting as a filter, and dependency 1910Sstevel@tonic-gate * relocations have been processed (a filter is thought of as a 1920Sstevel@tonic-gate * dependency in terms of symbol binding), we may have bound to 1930Sstevel@tonic-gate * the filtee, and hence carried out the relocation. Indicate 1940Sstevel@tonic-gate * that the filtee must be preloaded, as the .plt won't get 1950Sstevel@tonic-gate * exercised to cause its normal loading. 1960Sstevel@tonic-gate */ 1970Sstevel@tonic-gate case DT_FLAGS_1: 1980Sstevel@tonic-gate if (flags & RTLD_CONFSET) 1990Sstevel@tonic-gate dyn->d_un.d_val |= DF_1_CONFALT; 2000Sstevel@tonic-gate if ((flags & RTLD_REL_DEPENDS) && 2010Sstevel@tonic-gate (FLAGS1(lmp)) & MSK_RT_FILTER) 2020Sstevel@tonic-gate dyn->d_un.d_val |= DF_1_LOADFLTR; 2030Sstevel@tonic-gate break; 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate case DT_FEATURE_1: 2060Sstevel@tonic-gate if (flags & RTLD_CONFSET) 2070Sstevel@tonic-gate dyn->d_un.d_val |= DTF_1_CONFEXP; 2080Sstevel@tonic-gate break; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate /* 2110Sstevel@tonic-gate * If a position flag is available save it for possible update 2120Sstevel@tonic-gate * when processing the next NEEDED tag. 2130Sstevel@tonic-gate */ 2140Sstevel@tonic-gate case DT_POSFLAG_1: 2150Sstevel@tonic-gate if (flags & RTLD_REL_DEPENDS) { 2160Sstevel@tonic-gate posdyn = dyn++; 2170Sstevel@tonic-gate continue; 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate break; 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate /* 2220Sstevel@tonic-gate * Collect the defaults. 2230Sstevel@tonic-gate */ 2240Sstevel@tonic-gate default: 2250Sstevel@tonic-gate /* 2260Sstevel@tonic-gate * If d_val is used, don't touch. 2270Sstevel@tonic-gate */ 2280Sstevel@tonic-gate if ((dyn->d_tag >= DT_VALRNGLO) && 2290Sstevel@tonic-gate (dyn->d_tag <= DT_VALRNGHI)) 2300Sstevel@tonic-gate break; 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate /* 2330Sstevel@tonic-gate * If d_ptr is used, adjust. Note, some entries that 2340Sstevel@tonic-gate * fell into this range are offsets into the dynamic 2350Sstevel@tonic-gate * string table. Although these would need modifying 2360Sstevel@tonic-gate * if the section itself were resized, there is no 2370Sstevel@tonic-gate * resizing with dldump(). Entries that correspond to 2380Sstevel@tonic-gate * offsets are picked off in the initial DT_ loop 2390Sstevel@tonic-gate * above. 2400Sstevel@tonic-gate */ 2410Sstevel@tonic-gate if ((dyn->d_tag >= DT_ADDRRNGLO) && 2420Sstevel@tonic-gate (dyn->d_tag <= DT_ADDRRNGHI)) { 2430Sstevel@tonic-gate dyn->d_un.d_ptr += addr; 2440Sstevel@tonic-gate break; 2450Sstevel@tonic-gate } 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate /* 2480Sstevel@tonic-gate * Check to see if this DT_ entry conforms 2490Sstevel@tonic-gate * to the DT_ENCODING rules. 2500Sstevel@tonic-gate */ 2510Sstevel@tonic-gate if ((dyn->d_tag >= DT_ENCODING) && 2520Sstevel@tonic-gate (dyn->d_tag <= DT_HIOS)) { 2530Sstevel@tonic-gate /* 2540Sstevel@tonic-gate * Even tag values are ADDRESS encodings 2550Sstevel@tonic-gate */ 2560Sstevel@tonic-gate if ((dyn->d_tag % 2) == 0) { 2570Sstevel@tonic-gate dyn->d_un.d_ptr += addr; 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate break; 2600Sstevel@tonic-gate } 2611618Srie eprintf(LIST(lmp), ERR_WARNING, 2621618Srie MSG_INTL(MSG_DT_UNKNOWN), file, 2630Sstevel@tonic-gate EC_XWORD(dyn->d_tag)); 2640Sstevel@tonic-gate return (1); 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate posdyn = 0; 2670Sstevel@tonic-gate dyn++; 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate return (0); 2700Sstevel@tonic-gate } 271