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 5*5aefb655Srie * Common Development and Distribution License (the "License"). 6*5aefb655Srie * 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 */ 21*5aefb655Srie 227c478bd9Sstevel@tonic-gate /* 23*5aefb655Srie * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * Update any dynamic entry offsets. One issue with dynamic entries is that 277c478bd9Sstevel@tonic-gate * you only know whether they refer to a value or an offset if you know each 287c478bd9Sstevel@tonic-gate * type. Thus we check for all types we know about, it a type is found that 297c478bd9Sstevel@tonic-gate * we don't know about then return and error as we have no idea what to do. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <libelf.h> 347c478bd9Sstevel@tonic-gate #include <link.h> 357c478bd9Sstevel@tonic-gate #include "libld.h" 367c478bd9Sstevel@tonic-gate #include "msg.h" 377c478bd9Sstevel@tonic-gate #include "rtld.h" 387c478bd9Sstevel@tonic-gate #include "_librtld.h" 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate int 41*5aefb655Srie update_dynamic(Cache *cache, Cache *_cache, Rt_map *lmp, int flags, 427c478bd9Sstevel@tonic-gate Addr addr, Off off, const char *file, Xword null, Xword data, Xword func, 437c478bd9Sstevel@tonic-gate Xword entsize, Xword checksum) 447c478bd9Sstevel@tonic-gate { 45*5aefb655Srie Dyn *dyn = (Dyn *)_cache->c_data->d_buf, *posdyn = 0; 467c478bd9Sstevel@tonic-gate const char *strs; 47*5aefb655Srie Cache *__cache; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* 507c478bd9Sstevel@tonic-gate * If we're dealing with an object that might have bound to an external 517c478bd9Sstevel@tonic-gate * dependency establish our string table for possible NEEDED processing. 527c478bd9Sstevel@tonic-gate */ 537c478bd9Sstevel@tonic-gate if (flags & RTLD_REL_DEPENDS) { 547c478bd9Sstevel@tonic-gate __cache = &cache[_cache->c_shdr->sh_link]; 557c478bd9Sstevel@tonic-gate strs = (const char *)__cache->c_data->d_buf; 567c478bd9Sstevel@tonic-gate } 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate /* 597c478bd9Sstevel@tonic-gate * Loop through the dynamic table updating all offsets. 607c478bd9Sstevel@tonic-gate */ 617c478bd9Sstevel@tonic-gate while (dyn->d_tag != DT_NULL) { 627c478bd9Sstevel@tonic-gate switch ((Xword)dyn->d_tag) { 637c478bd9Sstevel@tonic-gate case DT_NEEDED: 647c478bd9Sstevel@tonic-gate if (posdyn) { 65*5aefb655Srie Rt_map *dlmp; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* 687c478bd9Sstevel@tonic-gate * Determine whether this dependency has been 697c478bd9Sstevel@tonic-gate * loaded (this is the most generic way to check 707c478bd9Sstevel@tonic-gate * any alias names), and if it has been bound 717c478bd9Sstevel@tonic-gate * to, undo any lazy-loading position flag. 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate if (dlmp = is_so_loaded(LIST(lmp), 747c478bd9Sstevel@tonic-gate (strs + dyn->d_un.d_val), 1)) { 757c478bd9Sstevel@tonic-gate Bnd_desc ** bdpp; 767c478bd9Sstevel@tonic-gate Aliste off; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate for (ALIST_TRAVERSE(DEPENDS(lmp), off, 797c478bd9Sstevel@tonic-gate bdpp)) { 807c478bd9Sstevel@tonic-gate if (dlmp == (*bdpp)->b_depend) { 817c478bd9Sstevel@tonic-gate posdyn->d_un.d_val &= 827c478bd9Sstevel@tonic-gate ~DF_P1_LAZYLOAD; 837c478bd9Sstevel@tonic-gate break; 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate break; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate case DT_RELAENT: 917c478bd9Sstevel@tonic-gate case DT_STRSZ: 927c478bd9Sstevel@tonic-gate case DT_SYMENT: 937c478bd9Sstevel@tonic-gate case DT_SONAME: 947c478bd9Sstevel@tonic-gate case DT_RPATH: 957c478bd9Sstevel@tonic-gate case DT_SYMBOLIC: 967c478bd9Sstevel@tonic-gate case DT_RELENT: 977c478bd9Sstevel@tonic-gate case DT_PLTREL: 987c478bd9Sstevel@tonic-gate case DT_TEXTREL: 997c478bd9Sstevel@tonic-gate case DT_VERDEFNUM: 1007c478bd9Sstevel@tonic-gate case DT_VERNEEDNUM: 1017c478bd9Sstevel@tonic-gate case DT_AUXILIARY: 1027c478bd9Sstevel@tonic-gate case DT_USED: 1037c478bd9Sstevel@tonic-gate case DT_FILTER: 1047c478bd9Sstevel@tonic-gate case DT_DEPRECATED_SPARC_REGISTER: 1057c478bd9Sstevel@tonic-gate case M_DT_REGISTER: 1067c478bd9Sstevel@tonic-gate case DT_BIND_NOW: 1077c478bd9Sstevel@tonic-gate case DT_INIT_ARRAYSZ: 1087c478bd9Sstevel@tonic-gate case DT_FINI_ARRAYSZ: 1097c478bd9Sstevel@tonic-gate case DT_RUNPATH: 1107c478bd9Sstevel@tonic-gate case DT_FLAGS: 1117c478bd9Sstevel@tonic-gate case DT_CONFIG: 1127c478bd9Sstevel@tonic-gate case DT_DEPAUDIT: 1137c478bd9Sstevel@tonic-gate case DT_AUDIT: 1147c478bd9Sstevel@tonic-gate break; 1157c478bd9Sstevel@tonic-gate case DT_PLTGOT: 1167c478bd9Sstevel@tonic-gate case DT_HASH: 1177c478bd9Sstevel@tonic-gate case DT_STRTAB: 1187c478bd9Sstevel@tonic-gate case DT_SYMTAB: 1197c478bd9Sstevel@tonic-gate case DT_INIT: 1207c478bd9Sstevel@tonic-gate case DT_FINI: 1217c478bd9Sstevel@tonic-gate case DT_VERSYM: 1227c478bd9Sstevel@tonic-gate case DT_VERDEF: 1237c478bd9Sstevel@tonic-gate case DT_VERNEED: 1247c478bd9Sstevel@tonic-gate case DT_INIT_ARRAY: 1257c478bd9Sstevel@tonic-gate case DT_FINI_ARRAY: 1267c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr += addr; 1277c478bd9Sstevel@tonic-gate break; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate /* 1307c478bd9Sstevel@tonic-gate * If the memory image is being used, this element would have 1317c478bd9Sstevel@tonic-gate * been initialized to the runtime linkers internal link-map 1327c478bd9Sstevel@tonic-gate * list. Clear it. 1337c478bd9Sstevel@tonic-gate */ 1347c478bd9Sstevel@tonic-gate case DT_DEBUG: 1357c478bd9Sstevel@tonic-gate dyn->d_un.d_val = 0; 1367c478bd9Sstevel@tonic-gate break; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * The number of relocations may have been reduced if 1407c478bd9Sstevel@tonic-gate * relocations have been saved in the new image. Thus we 1417c478bd9Sstevel@tonic-gate * compute the new relocation size and start. 1427c478bd9Sstevel@tonic-gate */ 1437c478bd9Sstevel@tonic-gate case DT_RELASZ: 1447c478bd9Sstevel@tonic-gate case DT_RELSZ: 1457c478bd9Sstevel@tonic-gate dyn->d_un.d_val = ((data + func) * entsize); 1467c478bd9Sstevel@tonic-gate break; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate case DT_RELA: 1497c478bd9Sstevel@tonic-gate case DT_REL: 1507c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = (addr + off + (null * entsize)); 1517c478bd9Sstevel@tonic-gate break; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* 1547c478bd9Sstevel@tonic-gate * If relative relocations have been processed clear the count. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate case DT_RELACOUNT: 1577c478bd9Sstevel@tonic-gate case DT_RELCOUNT: 1587c478bd9Sstevel@tonic-gate if (flags & RTLD_REL_RELATIVE) 1597c478bd9Sstevel@tonic-gate dyn->d_un.d_val = 0; 1607c478bd9Sstevel@tonic-gate break; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate case DT_PLTRELSZ: 1637c478bd9Sstevel@tonic-gate dyn->d_un.d_val = (func * entsize); 1647c478bd9Sstevel@tonic-gate break; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate case DT_JMPREL: 1677c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = (addr + off + 1687c478bd9Sstevel@tonic-gate ((null + data) * entsize)); 1697c478bd9Sstevel@tonic-gate break; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * Recompute the images elf checksum. 1737c478bd9Sstevel@tonic-gate */ 1747c478bd9Sstevel@tonic-gate case DT_CHECKSUM: 1757c478bd9Sstevel@tonic-gate dyn->d_un.d_val = checksum; 1767c478bd9Sstevel@tonic-gate break; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* 1797c478bd9Sstevel@tonic-gate * If a flag entry is available, indicate if this image has 1807c478bd9Sstevel@tonic-gate * been generated via the configuration process (crle(1)). 1817c478bd9Sstevel@tonic-gate * Because we only started depositing DT_FLAGS_1 entries in all 1827c478bd9Sstevel@tonic-gate * objects starting with Solaris 8, set a feature flag if it 1837c478bd9Sstevel@tonic-gate * is present (these got added in Solaris 7). 1847c478bd9Sstevel@tonic-gate * The runtime linker may use this flag to search for a local 1857c478bd9Sstevel@tonic-gate * configuration file - this is only meaningful in executables 1867c478bd9Sstevel@tonic-gate * but the flag has value for identifying images regardless. 1877c478bd9Sstevel@tonic-gate * 1887c478bd9Sstevel@tonic-gate * If this file is acting as a filter, and dependency 1897c478bd9Sstevel@tonic-gate * relocations have been processed (a filter is thought of as a 1907c478bd9Sstevel@tonic-gate * dependency in terms of symbol binding), we may have bound to 1917c478bd9Sstevel@tonic-gate * the filtee, and hence carried out the relocation. Indicate 1927c478bd9Sstevel@tonic-gate * that the filtee must be preloaded, as the .plt won't get 1937c478bd9Sstevel@tonic-gate * exercised to cause its normal loading. 1947c478bd9Sstevel@tonic-gate */ 1957c478bd9Sstevel@tonic-gate case DT_FLAGS_1: 1967c478bd9Sstevel@tonic-gate if (flags & RTLD_CONFSET) 1977c478bd9Sstevel@tonic-gate dyn->d_un.d_val |= DF_1_CONFALT; 1987c478bd9Sstevel@tonic-gate if ((flags & RTLD_REL_DEPENDS) && 1997c478bd9Sstevel@tonic-gate (FLAGS1(lmp)) & MSK_RT_FILTER) 2007c478bd9Sstevel@tonic-gate dyn->d_un.d_val |= DF_1_LOADFLTR; 2017c478bd9Sstevel@tonic-gate break; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate case DT_FEATURE_1: 2047c478bd9Sstevel@tonic-gate if (flags & RTLD_CONFSET) 2057c478bd9Sstevel@tonic-gate dyn->d_un.d_val |= DTF_1_CONFEXP; 2067c478bd9Sstevel@tonic-gate break; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * If a position flag is available save it for possible update 2107c478bd9Sstevel@tonic-gate * when processing the next NEEDED tag. 2117c478bd9Sstevel@tonic-gate */ 2127c478bd9Sstevel@tonic-gate case DT_POSFLAG_1: 2137c478bd9Sstevel@tonic-gate if (flags & RTLD_REL_DEPENDS) { 2147c478bd9Sstevel@tonic-gate posdyn = dyn++; 2157c478bd9Sstevel@tonic-gate continue; 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate break; 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * Collect the defaults. 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate default: 2237c478bd9Sstevel@tonic-gate /* 2247c478bd9Sstevel@tonic-gate * If d_val is used, don't touch. 2257c478bd9Sstevel@tonic-gate */ 2267c478bd9Sstevel@tonic-gate if ((dyn->d_tag >= DT_VALRNGLO) && 2277c478bd9Sstevel@tonic-gate (dyn->d_tag <= DT_VALRNGHI)) 2287c478bd9Sstevel@tonic-gate break; 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate /* 2317c478bd9Sstevel@tonic-gate * If d_ptr is used, adjust. Note, some entries that 2327c478bd9Sstevel@tonic-gate * fell into this range are offsets into the dynamic 2337c478bd9Sstevel@tonic-gate * string table. Although these would need modifying 2347c478bd9Sstevel@tonic-gate * if the section itself were resized, there is no 2357c478bd9Sstevel@tonic-gate * resizing with dldump(). Entries that correspond to 2367c478bd9Sstevel@tonic-gate * offsets are picked off in the initial DT_ loop 2377c478bd9Sstevel@tonic-gate * above. 2387c478bd9Sstevel@tonic-gate */ 2397c478bd9Sstevel@tonic-gate if ((dyn->d_tag >= DT_ADDRRNGLO) && 2407c478bd9Sstevel@tonic-gate (dyn->d_tag <= DT_ADDRRNGHI)) { 2417c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr += addr; 2427c478bd9Sstevel@tonic-gate break; 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate /* 2467c478bd9Sstevel@tonic-gate * Check to see if this DT_ entry conforms 2477c478bd9Sstevel@tonic-gate * to the DT_ENCODING rules. 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate if ((dyn->d_tag >= DT_ENCODING) && 2507c478bd9Sstevel@tonic-gate (dyn->d_tag <= DT_HIOS)) { 2517c478bd9Sstevel@tonic-gate /* 2527c478bd9Sstevel@tonic-gate * Even tag values are ADDRESS encodings 2537c478bd9Sstevel@tonic-gate */ 2547c478bd9Sstevel@tonic-gate if ((dyn->d_tag % 2) == 0) { 2557c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr += addr; 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate break; 2587c478bd9Sstevel@tonic-gate } 259*5aefb655Srie eprintf(LIST(lmp), ERR_WARNING, 260*5aefb655Srie MSG_INTL(MSG_DT_UNKNOWN), file, 2617c478bd9Sstevel@tonic-gate EC_XWORD(dyn->d_tag)); 2627c478bd9Sstevel@tonic-gate return (1); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate posdyn = 0; 2657c478bd9Sstevel@tonic-gate dyn++; 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate return (0); 2687c478bd9Sstevel@tonic-gate } 269