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*12449SRod.Evans@Sun.COM * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate *
250Sstevel@tonic-gate * Update any dynamic entry offsets. One issue with dynamic entries is that
260Sstevel@tonic-gate * you only know whether they refer to a value or an offset if you know each
270Sstevel@tonic-gate * type. Thus we check for all types we know about, it a type is found that
280Sstevel@tonic-gate * we don't know about then return and error as we have no idea what to do.
290Sstevel@tonic-gate */
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <libelf.h>
320Sstevel@tonic-gate #include <link.h>
330Sstevel@tonic-gate #include "libld.h"
340Sstevel@tonic-gate #include "msg.h"
350Sstevel@tonic-gate #include "rtld.h"
360Sstevel@tonic-gate #include "_librtld.h"
370Sstevel@tonic-gate
380Sstevel@tonic-gate int
update_dynamic(Cache * cache,Cache * _cache,Rt_map * lmp,int flags,Addr addr,Off off,const char * file,Xword null,Xword data,Xword func,Xword entsize,Xword checksum)391618Srie update_dynamic(Cache *cache, Cache *_cache, Rt_map *lmp, int flags,
400Sstevel@tonic-gate Addr addr, Off off, const char *file, Xword null, Xword data, Xword func,
410Sstevel@tonic-gate Xword entsize, Xword checksum)
420Sstevel@tonic-gate {
431618Srie Dyn *dyn = (Dyn *)_cache->c_data->d_buf, *posdyn = 0;
440Sstevel@tonic-gate const char *strs;
451618Srie Cache *__cache;
460Sstevel@tonic-gate
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate * If we're dealing with an object that might have bound to an external
490Sstevel@tonic-gate * dependency establish our string table for possible NEEDED processing.
500Sstevel@tonic-gate */
510Sstevel@tonic-gate if (flags & RTLD_REL_DEPENDS) {
520Sstevel@tonic-gate __cache = &cache[_cache->c_shdr->sh_link];
530Sstevel@tonic-gate strs = (const char *)__cache->c_data->d_buf;
540Sstevel@tonic-gate }
550Sstevel@tonic-gate
560Sstevel@tonic-gate /*
570Sstevel@tonic-gate * Loop through the dynamic table updating all offsets.
580Sstevel@tonic-gate */
590Sstevel@tonic-gate while (dyn->d_tag != DT_NULL) {
60*12449SRod.Evans@Sun.COM Rt_map *dlmp;
61*12449SRod.Evans@Sun.COM
620Sstevel@tonic-gate switch ((Xword)dyn->d_tag) {
630Sstevel@tonic-gate case DT_NEEDED:
64*12449SRod.Evans@Sun.COM if (posdyn == 0)
65*12449SRod.Evans@Sun.COM break;
660Sstevel@tonic-gate
67*12449SRod.Evans@Sun.COM /*
68*12449SRod.Evans@Sun.COM * Determine whether this dependency has been loaded
69*12449SRod.Evans@Sun.COM * (this is the most generic way to check any alias
70*12449SRod.Evans@Sun.COM * names), and if it has been bound to, undo any
71*12449SRod.Evans@Sun.COM * lazy-loading or deferred position flag.
72*12449SRod.Evans@Sun.COM */
73*12449SRod.Evans@Sun.COM if (dlmp = is_so_loaded(LIST(lmp),
74*12449SRod.Evans@Sun.COM (strs + dyn->d_un.d_val), NULL)) {
75*12449SRod.Evans@Sun.COM Bnd_desc *bdp;
76*12449SRod.Evans@Sun.COM Aliste idx;
770Sstevel@tonic-gate
78*12449SRod.Evans@Sun.COM for (APLIST_TRAVERSE(DEPENDS(lmp), idx, bdp)) {
79*12449SRod.Evans@Sun.COM if (dlmp != bdp->b_depend)
80*12449SRod.Evans@Sun.COM continue;
81*12449SRod.Evans@Sun.COM
82*12449SRod.Evans@Sun.COM posdyn->d_un.d_val &=
83*12449SRod.Evans@Sun.COM ~(DF_P1_LAZYLOAD | DF_P1_DEFERRED);
84*12449SRod.Evans@Sun.COM break;
850Sstevel@tonic-gate }
860Sstevel@tonic-gate }
870Sstevel@tonic-gate break;
880Sstevel@tonic-gate
890Sstevel@tonic-gate case DT_RELAENT:
900Sstevel@tonic-gate case DT_STRSZ:
910Sstevel@tonic-gate case DT_SYMENT:
920Sstevel@tonic-gate case DT_SONAME:
930Sstevel@tonic-gate case DT_RPATH:
940Sstevel@tonic-gate case DT_SYMBOLIC:
950Sstevel@tonic-gate case DT_RELENT:
960Sstevel@tonic-gate case DT_PLTREL:
970Sstevel@tonic-gate case DT_TEXTREL:
980Sstevel@tonic-gate case DT_VERDEFNUM:
990Sstevel@tonic-gate case DT_VERNEEDNUM:
1000Sstevel@tonic-gate case DT_AUXILIARY:
1010Sstevel@tonic-gate case DT_USED:
1020Sstevel@tonic-gate case DT_FILTER:
1030Sstevel@tonic-gate case DT_DEPRECATED_SPARC_REGISTER:
1040Sstevel@tonic-gate case M_DT_REGISTER:
1050Sstevel@tonic-gate case DT_BIND_NOW:
1060Sstevel@tonic-gate case DT_INIT_ARRAYSZ:
1070Sstevel@tonic-gate case DT_FINI_ARRAYSZ:
1080Sstevel@tonic-gate case DT_RUNPATH:
1090Sstevel@tonic-gate case DT_FLAGS:
1100Sstevel@tonic-gate case DT_CONFIG:
1110Sstevel@tonic-gate case DT_DEPAUDIT:
1120Sstevel@tonic-gate case DT_AUDIT:
1132766Sab196087 case DT_SUNW_SYMSZ:
1140Sstevel@tonic-gate break;
1150Sstevel@tonic-gate case DT_PLTGOT:
1160Sstevel@tonic-gate case DT_HASH:
1170Sstevel@tonic-gate case DT_STRTAB:
1180Sstevel@tonic-gate case DT_SYMTAB:
1192766Sab196087 case DT_SUNW_SYMTAB:
1200Sstevel@tonic-gate case DT_INIT:
1210Sstevel@tonic-gate case DT_FINI:
1220Sstevel@tonic-gate case DT_VERSYM:
1230Sstevel@tonic-gate case DT_VERDEF:
1240Sstevel@tonic-gate case DT_VERNEED:
1250Sstevel@tonic-gate case DT_INIT_ARRAY:
1260Sstevel@tonic-gate case DT_FINI_ARRAY:
1270Sstevel@tonic-gate dyn->d_un.d_ptr += addr;
1280Sstevel@tonic-gate break;
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate /*
1310Sstevel@tonic-gate * If the memory image is being used, this element would have
1320Sstevel@tonic-gate * been initialized to the runtime linkers internal link-map
1330Sstevel@tonic-gate * list. Clear it.
1340Sstevel@tonic-gate */
1350Sstevel@tonic-gate case DT_DEBUG:
1360Sstevel@tonic-gate dyn->d_un.d_val = 0;
1370Sstevel@tonic-gate break;
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate /*
1400Sstevel@tonic-gate * The number of relocations may have been reduced if
1410Sstevel@tonic-gate * relocations have been saved in the new image. Thus we
1420Sstevel@tonic-gate * compute the new relocation size and start.
1430Sstevel@tonic-gate */
1440Sstevel@tonic-gate case DT_RELASZ:
1450Sstevel@tonic-gate case DT_RELSZ:
1460Sstevel@tonic-gate dyn->d_un.d_val = ((data + func) * entsize);
1470Sstevel@tonic-gate break;
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate case DT_RELA:
1500Sstevel@tonic-gate case DT_REL:
1510Sstevel@tonic-gate dyn->d_un.d_ptr = (addr + off + (null * entsize));
1520Sstevel@tonic-gate break;
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate /*
1550Sstevel@tonic-gate * If relative relocations have been processed clear the count.
1560Sstevel@tonic-gate */
1570Sstevel@tonic-gate case DT_RELACOUNT:
1580Sstevel@tonic-gate case DT_RELCOUNT:
1590Sstevel@tonic-gate if (flags & RTLD_REL_RELATIVE)
1600Sstevel@tonic-gate dyn->d_un.d_val = 0;
1610Sstevel@tonic-gate break;
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate case DT_PLTRELSZ:
1640Sstevel@tonic-gate dyn->d_un.d_val = (func * entsize);
1650Sstevel@tonic-gate break;
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate case DT_JMPREL:
1680Sstevel@tonic-gate dyn->d_un.d_ptr = (addr + off +
1695892Sab196087 ((null + data) * entsize));
1700Sstevel@tonic-gate break;
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate * Recompute the images elf checksum.
1740Sstevel@tonic-gate */
1750Sstevel@tonic-gate case DT_CHECKSUM:
1760Sstevel@tonic-gate dyn->d_un.d_val = checksum;
1770Sstevel@tonic-gate break;
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate /*
1800Sstevel@tonic-gate * If a flag entry is available, indicate if this image has
1810Sstevel@tonic-gate * been generated via the configuration process (crle(1)).
1820Sstevel@tonic-gate * Because we only started depositing DT_FLAGS_1 entries in all
1830Sstevel@tonic-gate * objects starting with Solaris 8, set a feature flag if it
1840Sstevel@tonic-gate * is present (these got added in Solaris 7).
1850Sstevel@tonic-gate * The runtime linker may use this flag to search for a local
1860Sstevel@tonic-gate * configuration file - this is only meaningful in executables
1870Sstevel@tonic-gate * but the flag has value for identifying images regardless.
1880Sstevel@tonic-gate *
1890Sstevel@tonic-gate * If this file is acting as a filter, and dependency
1900Sstevel@tonic-gate * relocations have been processed (a filter is thought of as a
1910Sstevel@tonic-gate * dependency in terms of symbol binding), we may have bound to
1920Sstevel@tonic-gate * the filtee, and hence carried out the relocation. Indicate
1930Sstevel@tonic-gate * that the filtee must be preloaded, as the .plt won't get
1940Sstevel@tonic-gate * exercised to cause its normal loading.
1950Sstevel@tonic-gate */
1960Sstevel@tonic-gate case DT_FLAGS_1:
1970Sstevel@tonic-gate if (flags & RTLD_CONFSET)
1980Sstevel@tonic-gate dyn->d_un.d_val |= DF_1_CONFALT;
1990Sstevel@tonic-gate if ((flags & RTLD_REL_DEPENDS) &&
2000Sstevel@tonic-gate (FLAGS1(lmp)) & MSK_RT_FILTER)
2010Sstevel@tonic-gate dyn->d_un.d_val |= DF_1_LOADFLTR;
2020Sstevel@tonic-gate break;
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate case DT_FEATURE_1:
2050Sstevel@tonic-gate if (flags & RTLD_CONFSET)
2060Sstevel@tonic-gate dyn->d_un.d_val |= DTF_1_CONFEXP;
2070Sstevel@tonic-gate break;
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate /*
2100Sstevel@tonic-gate * If a position flag is available save it for possible update
2110Sstevel@tonic-gate * when processing the next NEEDED tag.
2120Sstevel@tonic-gate */
2130Sstevel@tonic-gate case DT_POSFLAG_1:
2140Sstevel@tonic-gate if (flags & RTLD_REL_DEPENDS) {
2150Sstevel@tonic-gate posdyn = dyn++;
2160Sstevel@tonic-gate continue;
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate break;
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate * Collect the defaults.
2220Sstevel@tonic-gate */
2230Sstevel@tonic-gate default:
2240Sstevel@tonic-gate /*
2250Sstevel@tonic-gate * If d_val is used, don't touch.
2260Sstevel@tonic-gate */
2270Sstevel@tonic-gate if ((dyn->d_tag >= DT_VALRNGLO) &&
2280Sstevel@tonic-gate (dyn->d_tag <= DT_VALRNGHI))
2290Sstevel@tonic-gate break;
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate /*
2320Sstevel@tonic-gate * If d_ptr is used, adjust. Note, some entries that
2330Sstevel@tonic-gate * fell into this range are offsets into the dynamic
2340Sstevel@tonic-gate * string table. Although these would need modifying
2350Sstevel@tonic-gate * if the section itself were resized, there is no
2360Sstevel@tonic-gate * resizing with dldump(). Entries that correspond to
2370Sstevel@tonic-gate * offsets are picked off in the initial DT_ loop
2380Sstevel@tonic-gate * above.
2390Sstevel@tonic-gate */
2400Sstevel@tonic-gate if ((dyn->d_tag >= DT_ADDRRNGLO) &&
2410Sstevel@tonic-gate (dyn->d_tag <= DT_ADDRRNGHI)) {
2420Sstevel@tonic-gate dyn->d_un.d_ptr += addr;
2430Sstevel@tonic-gate break;
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate * Check to see if this DT_ entry conforms
2480Sstevel@tonic-gate * to the DT_ENCODING rules.
2490Sstevel@tonic-gate */
2500Sstevel@tonic-gate if ((dyn->d_tag >= DT_ENCODING) &&
2510Sstevel@tonic-gate (dyn->d_tag <= DT_HIOS)) {
2520Sstevel@tonic-gate /*
2530Sstevel@tonic-gate * Even tag values are ADDRESS encodings
2540Sstevel@tonic-gate */
2550Sstevel@tonic-gate if ((dyn->d_tag % 2) == 0) {
2560Sstevel@tonic-gate dyn->d_un.d_ptr += addr;
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate break;
2590Sstevel@tonic-gate }
2601618Srie eprintf(LIST(lmp), ERR_WARNING,
2611618Srie MSG_INTL(MSG_DT_UNKNOWN), file,
2620Sstevel@tonic-gate EC_XWORD(dyn->d_tag));
2630Sstevel@tonic-gate return (1);
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate posdyn = 0;
2660Sstevel@tonic-gate dyn++;
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate return (0);
2690Sstevel@tonic-gate }
270