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 51682Srie * Common Development and Distribution License (the "License"). 61682Srie * 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 */ 210Sstevel@tonic-gate 220Sstevel@tonic-gate /* 231682Srie * Copyright (c) 1988 AT&T 241682Srie * All Rights Reserved 251682Srie * 261682Srie * 27*6206Sab196087 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 280Sstevel@tonic-gate * Use is subject to license terms. 290Sstevel@tonic-gate */ 300Sstevel@tonic-gate 310Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 320Sstevel@tonic-gate 330Sstevel@tonic-gate #if !defined(_ELF64) 340Sstevel@tonic-gate #pragma weak elf_update = _elf_update 350Sstevel@tonic-gate #endif 360Sstevel@tonic-gate 370Sstevel@tonic-gate #include "syn.h" 380Sstevel@tonic-gate #include <memory.h> 390Sstevel@tonic-gate #include <malloc.h> 400Sstevel@tonic-gate #include <limits.h> 410Sstevel@tonic-gate 420Sstevel@tonic-gate #include <sgs.h> 430Sstevel@tonic-gate #include "decl.h" 440Sstevel@tonic-gate #include "msg.h" 450Sstevel@tonic-gate 460Sstevel@tonic-gate /* 470Sstevel@tonic-gate * This module is compiled twice, the second time having 480Sstevel@tonic-gate * -D_ELF64 defined. The following set of macros, along 490Sstevel@tonic-gate * with machelf.h, represent the differences between the 500Sstevel@tonic-gate * two compilations. Be careful *not* to add any class- 510Sstevel@tonic-gate * dependent code (anything that has elf32 or elf64 in the 520Sstevel@tonic-gate * name) to this code without hiding it behind a switch- 530Sstevel@tonic-gate * able macro like these. 540Sstevel@tonic-gate */ 550Sstevel@tonic-gate #if defined(_ELF64) 560Sstevel@tonic-gate 570Sstevel@tonic-gate #define FSZ_LONG ELF64_FSZ_XWORD 580Sstevel@tonic-gate #define ELFCLASS ELFCLASS64 590Sstevel@tonic-gate #define _elf_snode_init _elf64_snode_init 600Sstevel@tonic-gate #define _elfxx_cookscn _elf64_cookscn 610Sstevel@tonic-gate #define _elf_upd_lib _elf64_upd_lib 620Sstevel@tonic-gate #define elf_fsize elf64_fsize 630Sstevel@tonic-gate #define _elf_entsz _elf64_entsz 640Sstevel@tonic-gate #define _elf_msize _elf64_msize 650Sstevel@tonic-gate #define _elf_upd_usr _elf64_upd_usr 660Sstevel@tonic-gate #define wrt wrt64 670Sstevel@tonic-gate #define elf_xlatetof elf64_xlatetof 680Sstevel@tonic-gate #define _elfxx_update _elf64_update 69*6206Sab196087 #define _elfxx_swap_wrimage _elf64_swap_wrimage 700Sstevel@tonic-gate 710Sstevel@tonic-gate #else /* ELF32 */ 720Sstevel@tonic-gate 730Sstevel@tonic-gate #define FSZ_LONG ELF32_FSZ_WORD 740Sstevel@tonic-gate #define ELFCLASS ELFCLASS32 750Sstevel@tonic-gate #define _elf_snode_init _elf32_snode_init 760Sstevel@tonic-gate #define _elfxx_cookscn _elf32_cookscn 770Sstevel@tonic-gate #define _elf_upd_lib _elf32_upd_lib 780Sstevel@tonic-gate #define elf_fsize elf32_fsize 790Sstevel@tonic-gate #define _elf_entsz _elf32_entsz 800Sstevel@tonic-gate #define _elf_msize _elf32_msize 810Sstevel@tonic-gate #define _elf_upd_usr _elf32_upd_usr 820Sstevel@tonic-gate #define wrt wrt32 830Sstevel@tonic-gate #define elf_xlatetof elf32_xlatetof 840Sstevel@tonic-gate #define _elfxx_update _elf32_update 85*6206Sab196087 #define _elfxx_swap_wrimage _elf32_swap_wrimage 860Sstevel@tonic-gate 870Sstevel@tonic-gate #endif /* ELF64 */ 880Sstevel@tonic-gate 890Sstevel@tonic-gate 900Sstevel@tonic-gate /* 910Sstevel@tonic-gate * Output file update 920Sstevel@tonic-gate * These functions walk an Elf structure, update its information, 930Sstevel@tonic-gate * and optionally write the output file. Because the application 940Sstevel@tonic-gate * may control of the output file layout, two upd_... routines 950Sstevel@tonic-gate * exist. They're similar but too different to merge cleanly. 960Sstevel@tonic-gate * 970Sstevel@tonic-gate * The library defines a "dirty" bit to force parts of the file 980Sstevel@tonic-gate * to be written on update. These routines ignore the dirty bit 990Sstevel@tonic-gate * and do everything. A minimal update routine might be useful 1000Sstevel@tonic-gate * someday. 1010Sstevel@tonic-gate */ 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate static size_t 1040Sstevel@tonic-gate _elf_upd_lib(Elf * elf) 1050Sstevel@tonic-gate { 1060Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 1070Sstevel@tonic-gate Lword hi; 1080Sstevel@tonic-gate Lword hibit; 1090Sstevel@tonic-gate Elf_Scn * s; 1100Sstevel@tonic-gate register Xword sz; 1110Sstevel@tonic-gate Ehdr * eh = elf->ed_ehdr; 1120Sstevel@tonic-gate unsigned ver = eh->e_version; 1130Sstevel@tonic-gate register char *p = (char *)eh->e_ident; 1140Sstevel@tonic-gate size_t scncnt; 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate /* 1170Sstevel@tonic-gate * Ehdr and Phdr table go first 1180Sstevel@tonic-gate */ 1190Sstevel@tonic-gate p[EI_MAG0] = ELFMAG0; 1200Sstevel@tonic-gate p[EI_MAG1] = ELFMAG1; 1210Sstevel@tonic-gate p[EI_MAG2] = ELFMAG2; 1220Sstevel@tonic-gate p[EI_MAG3] = ELFMAG3; 1230Sstevel@tonic-gate p[EI_CLASS] = ELFCLASS; 1240Sstevel@tonic-gate /* LINTED */ 1250Sstevel@tonic-gate p[EI_VERSION] = (Byte)ver; 1260Sstevel@tonic-gate hi = elf_fsize(ELF_T_EHDR, 1, ver); 1270Sstevel@tonic-gate /* LINTED */ 1280Sstevel@tonic-gate eh->e_ehsize = (Half)hi; 1290Sstevel@tonic-gate if (eh->e_phnum != 0) { 1300Sstevel@tonic-gate /* LINTED */ 1310Sstevel@tonic-gate eh->e_phentsize = (Half)elf_fsize(ELF_T_PHDR, 1, ver); 1320Sstevel@tonic-gate /* LINTED */ 1330Sstevel@tonic-gate eh->e_phoff = (Off)hi; 1340Sstevel@tonic-gate hi += eh->e_phentsize * eh->e_phnum; 1350Sstevel@tonic-gate } else { 1360Sstevel@tonic-gate eh->e_phoff = 0; 1370Sstevel@tonic-gate eh->e_phentsize = 0; 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate /* 1411682Srie * Obtain the first section header. Typically, this section has NULL 1421682Srie * contents, however in the case of Extended ELF Sections this section 1431682Srie * is used to hold an alternative e_shnum, e_shstrndx and e_phnum. 1441682Srie * On initial allocation (see _elf_snode) the elements of this section 1451682Srie * would have been zeroed. The e_shnum is initialized later, after the 1461682Srie * section header count has been determined. The e_shstrndx and 1471682Srie * e_phnum may have already been initialized by the caller (for example, 1481682Srie * gelf_update_shdr() in mcs(1)). 1490Sstevel@tonic-gate */ 1500Sstevel@tonic-gate if ((s = elf->ed_hdscn) == 0) { 1510Sstevel@tonic-gate eh->e_shnum = 0; 1520Sstevel@tonic-gate scncnt = 0; 1530Sstevel@tonic-gate } else { 1541682Srie s = s->s_next; 1550Sstevel@tonic-gate scncnt = 1; 1560Sstevel@tonic-gate } 1570Sstevel@tonic-gate 1581682Srie /* 1591682Srie * Loop through sections. Compute section size before changing hi. 1601682Srie * Allow null buffers for NOBITS. 1611682Srie */ 1620Sstevel@tonic-gate hibit = 0; 1630Sstevel@tonic-gate for (; s != 0; s = s->s_next) { 1640Sstevel@tonic-gate register Dnode *d; 1650Sstevel@tonic-gate register Lword fsz, j; 1660Sstevel@tonic-gate Shdr *sh = s->s_shdr; 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate scncnt++; 1690Sstevel@tonic-gate if (sh->sh_type == SHT_NULL) { 1700Sstevel@tonic-gate *sh = _elf_snode_init.sb_shdr; 1710Sstevel@tonic-gate continue; 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate if ((s->s_myflags & SF_READY) == 0) 1750Sstevel@tonic-gate (void) _elfxx_cookscn(s); 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate sh->sh_addralign = 1; 1783621Sab196087 if ((sz = (Xword)_elf_entsz(elf, sh->sh_type, ver)) != 0) 1790Sstevel@tonic-gate /* LINTED */ 1800Sstevel@tonic-gate sh->sh_entsize = (Half)sz; 1810Sstevel@tonic-gate sz = 0; 1820Sstevel@tonic-gate for (d = s->s_hdnode; d != 0; d = d->db_next) { 1830Sstevel@tonic-gate if ((fsz = elf_fsize(d->db_data.d_type, 1840Sstevel@tonic-gate 1, ver)) == 0) 1850Sstevel@tonic-gate return (0); 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate j = _elf_msize(d->db_data.d_type, ver); 1880Sstevel@tonic-gate fsz *= (d->db_data.d_size / j); 1890Sstevel@tonic-gate d->db_osz = (size_t)fsz; 1900Sstevel@tonic-gate if ((j = d->db_data.d_align) > 1) { 1910Sstevel@tonic-gate if (j > sh->sh_addralign) 1920Sstevel@tonic-gate sh->sh_addralign = (Xword)j; 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate if (sz % j != 0) 1950Sstevel@tonic-gate sz += j - sz % j; 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate d->db_data.d_off = (off_t)sz; 1980Sstevel@tonic-gate d->db_xoff = sz; 1990Sstevel@tonic-gate sz += (Xword)fsz; 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate sh->sh_size = sz; 2030Sstevel@tonic-gate /* 2040Sstevel@tonic-gate * We want to take into account the offsets for NOBITS 2050Sstevel@tonic-gate * sections and let the "sh_offsets" point to where 2060Sstevel@tonic-gate * the section would 'conceptually' fit within 2070Sstevel@tonic-gate * the file (as required by the ABI). 2080Sstevel@tonic-gate * 2090Sstevel@tonic-gate * But - we must also make sure that the NOBITS does 2100Sstevel@tonic-gate * not take up any actual space in the file. We preserve 2110Sstevel@tonic-gate * the actual offset into the file in the 'hibit' variable. 2120Sstevel@tonic-gate * When we come to the first non-NOBITS section after a 2130Sstevel@tonic-gate * encountering a NOBITS section the hi counter is restored 2140Sstevel@tonic-gate * to its proper place in the file. 2150Sstevel@tonic-gate */ 2160Sstevel@tonic-gate if (sh->sh_type == SHT_NOBITS) { 2170Sstevel@tonic-gate if (hibit == 0) 2180Sstevel@tonic-gate hibit = hi; 2190Sstevel@tonic-gate } else { 2200Sstevel@tonic-gate if (hibit) { 2210Sstevel@tonic-gate hi = hibit; 2220Sstevel@tonic-gate hibit = 0; 2230Sstevel@tonic-gate } 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate j = sh->sh_addralign; 2260Sstevel@tonic-gate if ((fsz = hi % j) != 0) 2270Sstevel@tonic-gate hi += j - fsz; 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate /* LINTED */ 2300Sstevel@tonic-gate sh->sh_offset = (Off)hi; 2310Sstevel@tonic-gate hi += sz; 2320Sstevel@tonic-gate } 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate /* 2350Sstevel@tonic-gate * if last section was a 'NOBITS' section then we need to 2360Sstevel@tonic-gate * restore the 'hi' counter to point to the end of the last 2370Sstevel@tonic-gate * non 'NOBITS' section. 2380Sstevel@tonic-gate */ 2390Sstevel@tonic-gate if (hibit) { 2400Sstevel@tonic-gate hi = hibit; 2410Sstevel@tonic-gate hibit = 0; 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate /* 2450Sstevel@tonic-gate * Shdr table last 2460Sstevel@tonic-gate */ 2470Sstevel@tonic-gate if (scncnt != 0) { 2480Sstevel@tonic-gate if (hi % FSZ_LONG != 0) 2490Sstevel@tonic-gate hi += FSZ_LONG - hi % FSZ_LONG; 2500Sstevel@tonic-gate /* LINTED */ 2510Sstevel@tonic-gate eh->e_shoff = (Off)hi; 2520Sstevel@tonic-gate /* 2530Sstevel@tonic-gate * If we are using 'extended sections' then the 2540Sstevel@tonic-gate * e_shnum is stored in the sh_size field of the 2550Sstevel@tonic-gate * first section header. 2560Sstevel@tonic-gate * 2570Sstevel@tonic-gate * NOTE: we set e_shnum to '0' because it's specified 2580Sstevel@tonic-gate * this way in the gABI, and in the hopes that 2590Sstevel@tonic-gate * this will cause less problems to unaware 2600Sstevel@tonic-gate * tools then if we'd set it to SHN_XINDEX (0xffff). 2610Sstevel@tonic-gate */ 2620Sstevel@tonic-gate if (scncnt < SHN_LORESERVE) 2630Sstevel@tonic-gate eh->e_shnum = scncnt; 2640Sstevel@tonic-gate else { 2650Sstevel@tonic-gate Shdr *sh; 2660Sstevel@tonic-gate sh = (Shdr *)elf->ed_hdscn->s_shdr; 2670Sstevel@tonic-gate sh->sh_size = scncnt; 2680Sstevel@tonic-gate eh->e_shnum = 0; 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate /* LINTED */ 2710Sstevel@tonic-gate eh->e_shentsize = (Half)elf_fsize(ELF_T_SHDR, 1, ver); 2720Sstevel@tonic-gate hi += eh->e_shentsize * scncnt; 2730Sstevel@tonic-gate } else { 2740Sstevel@tonic-gate eh->e_shoff = 0; 2750Sstevel@tonic-gate eh->e_shentsize = 0; 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate #if !(defined(_LP64) && defined(_ELF64)) 2790Sstevel@tonic-gate if (hi > INT_MAX) { 2800Sstevel@tonic-gate _elf_seterr(EFMT_FBIG, 0); 2810Sstevel@tonic-gate return (0); 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate #endif 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate return ((size_t)hi); 2860Sstevel@tonic-gate } 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate static size_t 2910Sstevel@tonic-gate _elf_upd_usr(Elf * elf) 2920Sstevel@tonic-gate { 2930Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 2940Sstevel@tonic-gate Lword hi; 2950Sstevel@tonic-gate Elf_Scn * s; 2960Sstevel@tonic-gate register Xword sz; 2970Sstevel@tonic-gate Ehdr * eh = elf->ed_ehdr; 2980Sstevel@tonic-gate unsigned ver = eh->e_version; 2990Sstevel@tonic-gate register char *p = (char *)eh->e_ident; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate /* 3030Sstevel@tonic-gate * Ehdr and Phdr table go first 3040Sstevel@tonic-gate */ 3050Sstevel@tonic-gate p[EI_MAG0] = ELFMAG0; 3060Sstevel@tonic-gate p[EI_MAG1] = ELFMAG1; 3070Sstevel@tonic-gate p[EI_MAG2] = ELFMAG2; 3080Sstevel@tonic-gate p[EI_MAG3] = ELFMAG3; 3090Sstevel@tonic-gate p[EI_CLASS] = ELFCLASS; 3100Sstevel@tonic-gate /* LINTED */ 3110Sstevel@tonic-gate p[EI_VERSION] = (Byte)ver; 3120Sstevel@tonic-gate hi = elf_fsize(ELF_T_EHDR, 1, ver); 3130Sstevel@tonic-gate /* LINTED */ 3140Sstevel@tonic-gate eh->e_ehsize = (Half)hi; 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate /* 3170Sstevel@tonic-gate * If phnum is zero, phoff "should" be zero too, 3180Sstevel@tonic-gate * but the application is responsible for it. 3190Sstevel@tonic-gate * Allow a non-zero value here and update the 3200Sstevel@tonic-gate * hi water mark accordingly. 3210Sstevel@tonic-gate */ 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate if (eh->e_phnum != 0) 3240Sstevel@tonic-gate /* LINTED */ 3250Sstevel@tonic-gate eh->e_phentsize = (Half)elf_fsize(ELF_T_PHDR, 1, ver); 3260Sstevel@tonic-gate else 3270Sstevel@tonic-gate eh->e_phentsize = 0; 3280Sstevel@tonic-gate if ((sz = eh->e_phoff + eh->e_phentsize * eh->e_phnum) > hi) 3290Sstevel@tonic-gate hi = sz; 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate /* 3320Sstevel@tonic-gate * Loop through sections, skipping index zero. 3330Sstevel@tonic-gate * Compute section size before changing hi. 3340Sstevel@tonic-gate * Allow null buffers for NOBITS. 3350Sstevel@tonic-gate */ 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate if ((s = elf->ed_hdscn) == 0) 3380Sstevel@tonic-gate eh->e_shnum = 0; 3390Sstevel@tonic-gate else { 3400Sstevel@tonic-gate eh->e_shnum = 1; 3410Sstevel@tonic-gate *(Shdr*)s->s_shdr = _elf_snode_init.sb_shdr; 3420Sstevel@tonic-gate s = s->s_next; 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate for (; s != 0; s = s->s_next) { 3450Sstevel@tonic-gate register Dnode *d; 3460Sstevel@tonic-gate register Xword fsz, j; 3470Sstevel@tonic-gate Shdr *sh = s->s_shdr; 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate if ((s->s_myflags & SF_READY) == 0) 3500Sstevel@tonic-gate (void) _elfxx_cookscn(s); 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate ++eh->e_shnum; 3530Sstevel@tonic-gate sz = 0; 3540Sstevel@tonic-gate for (d = s->s_hdnode; d != 0; d = d->db_next) { 3550Sstevel@tonic-gate if ((fsz = (Xword)elf_fsize(d->db_data.d_type, 1, 3560Sstevel@tonic-gate ver)) == 0) 3570Sstevel@tonic-gate return (0); 3580Sstevel@tonic-gate j = (Xword)_elf_msize(d->db_data.d_type, ver); 3590Sstevel@tonic-gate fsz *= (Xword)(d->db_data.d_size / j); 3600Sstevel@tonic-gate d->db_osz = (size_t)fsz; 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate if ((sh->sh_type != SHT_NOBITS) && 363*6206Sab196087 ((j = (Xword)(d->db_data.d_off + d->db_osz)) > sz)) 3640Sstevel@tonic-gate sz = j; 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate if (sh->sh_size < sz) { 3670Sstevel@tonic-gate _elf_seterr(EFMT_SCNSZ, 0); 3680Sstevel@tonic-gate return (0); 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate if ((sh->sh_type != SHT_NOBITS) && 3710Sstevel@tonic-gate (hi < sh->sh_offset + sh->sh_size)) 3720Sstevel@tonic-gate hi = sh->sh_offset + sh->sh_size; 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate /* 3760Sstevel@tonic-gate * Shdr table last. Comment above for phnum/phoff applies here. 3770Sstevel@tonic-gate */ 3780Sstevel@tonic-gate if (eh->e_shnum != 0) 3790Sstevel@tonic-gate /* LINTED */ 3800Sstevel@tonic-gate eh->e_shentsize = (Half)elf_fsize(ELF_T_SHDR, 1, ver); 3810Sstevel@tonic-gate else 3820Sstevel@tonic-gate eh->e_shentsize = 0; 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate if ((sz = eh->e_shoff + eh->e_shentsize * eh->e_shnum) > hi) 3850Sstevel@tonic-gate hi = sz; 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate #if !(defined(_LP64) && defined(_ELF64)) 3880Sstevel@tonic-gate if (hi > INT_MAX) { 3890Sstevel@tonic-gate _elf_seterr(EFMT_FBIG, 0); 3900Sstevel@tonic-gate return (0); 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate #endif 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate return ((size_t)hi); 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate static size_t 3990Sstevel@tonic-gate wrt(Elf * elf, Xword outsz, unsigned fill, int update_cmd) 4000Sstevel@tonic-gate { 4010Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 4020Sstevel@tonic-gate Elf_Data dst, src; 4030Sstevel@tonic-gate unsigned flag; 4040Sstevel@tonic-gate Xword hi, sz; 4050Sstevel@tonic-gate char *image; 4060Sstevel@tonic-gate Elf_Scn *s; 4070Sstevel@tonic-gate Ehdr *eh = elf->ed_ehdr; 4080Sstevel@tonic-gate unsigned ver = eh->e_version; 409*6206Sab196087 unsigned encode; 4100Sstevel@tonic-gate int byte; 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate /* 413*6206Sab196087 * If this is an ELF_C_WRIMAGE write, then we encode into the 414*6206Sab196087 * byte order of the system we are running on rather than that of 415*6206Sab196087 * of the object. For ld.so.1, this is the same order, but 416*6206Sab196087 * for 'ld', it might not be in the case where we are cross 417*6206Sab196087 * linking an object for a different target. In this later case, 418*6206Sab196087 * the linker-host byte order is necessary so that the linker can 419*6206Sab196087 * manipulate the resulting image. It is expected that the linker 420*6206Sab196087 * will call elf_swap_wrimage() if necessary to convert the image 421*6206Sab196087 * to the target byte order. 422*6206Sab196087 */ 423*6206Sab196087 encode = (update_cmd == ELF_C_WRIMAGE) ? _elf_sys_encoding() : 424*6206Sab196087 eh->e_ident[EI_DATA]; 425*6206Sab196087 426*6206Sab196087 /* 4270Sstevel@tonic-gate * Two issues can cause trouble for the output file. 4280Sstevel@tonic-gate * First, begin() with ELF_C_RDWR opens a file for both 4290Sstevel@tonic-gate * read and write. On the write update(), the library 4300Sstevel@tonic-gate * has to read everything it needs before truncating 4310Sstevel@tonic-gate * the file. Second, using mmap for both read and write 4320Sstevel@tonic-gate * is too tricky. Consequently, the library disables mmap 4330Sstevel@tonic-gate * on the read side. Using mmap for the output saves swap 4340Sstevel@tonic-gate * space, because that mapping is SHARED, not PRIVATE. 4350Sstevel@tonic-gate * 4360Sstevel@tonic-gate * If the file is write-only, there can be nothing of 4370Sstevel@tonic-gate * interest to bother with. 4380Sstevel@tonic-gate * 4390Sstevel@tonic-gate * The following reads the entire file, which might be 4400Sstevel@tonic-gate * more than necessary. Better safe than sorry. 4410Sstevel@tonic-gate */ 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate if ((elf->ed_myflags & EDF_READ) && 4440Sstevel@tonic-gate (_elf_vm(elf, (size_t)0, elf->ed_fsz) != OK_YES)) 4450Sstevel@tonic-gate return (0); 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate flag = elf->ed_myflags & EDF_WRALLOC; 4480Sstevel@tonic-gate if ((image = _elf_outmap(elf->ed_fd, outsz, &flag)) == 0) 4490Sstevel@tonic-gate return (0); 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate if (flag == 0) 4520Sstevel@tonic-gate elf->ed_myflags |= EDF_IMALLOC; 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate /* 4550Sstevel@tonic-gate * If an error occurs below, a "dirty" bit may be cleared 4560Sstevel@tonic-gate * improperly. To save a second pass through the file, 4570Sstevel@tonic-gate * this code sets the dirty bit on the elf descriptor 4580Sstevel@tonic-gate * when an error happens, assuming that will "cover" any 4590Sstevel@tonic-gate * accidents. 4600Sstevel@tonic-gate */ 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate /* 4630Sstevel@tonic-gate * Hi is needed only when 'fill' is non-zero. 4640Sstevel@tonic-gate * Fill is non-zero only when the library 4650Sstevel@tonic-gate * calculates file/section/data buffer offsets. 4660Sstevel@tonic-gate * The lib guarantees they increase monotonically. 4670Sstevel@tonic-gate * That guarantees proper filling below. 4680Sstevel@tonic-gate */ 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate /* 4720Sstevel@tonic-gate * Ehdr first 4730Sstevel@tonic-gate */ 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate src.d_buf = (Elf_Void *)eh; 4760Sstevel@tonic-gate src.d_type = ELF_T_EHDR; 4770Sstevel@tonic-gate src.d_size = sizeof (Ehdr); 4780Sstevel@tonic-gate src.d_version = EV_CURRENT; 4790Sstevel@tonic-gate dst.d_buf = (Elf_Void *)image; 4800Sstevel@tonic-gate dst.d_size = eh->e_ehsize; 4810Sstevel@tonic-gate dst.d_version = ver; 4820Sstevel@tonic-gate if (elf_xlatetof(&dst, &src, encode) == 0) 4830Sstevel@tonic-gate return (0); 4840Sstevel@tonic-gate elf->ed_ehflags &= ~ELF_F_DIRTY; 4850Sstevel@tonic-gate hi = eh->e_ehsize; 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate /* 4880Sstevel@tonic-gate * Phdr table if one exists 4890Sstevel@tonic-gate */ 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate if (eh->e_phnum != 0) { 4920Sstevel@tonic-gate unsigned work; 4930Sstevel@tonic-gate /* 4940Sstevel@tonic-gate * Unlike other library data, phdr table is 4950Sstevel@tonic-gate * in the user version. Change src buffer 4960Sstevel@tonic-gate * version here, fix it after translation. 4970Sstevel@tonic-gate */ 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate src.d_buf = (Elf_Void *)elf->ed_phdr; 5000Sstevel@tonic-gate src.d_type = ELF_T_PHDR; 5010Sstevel@tonic-gate src.d_size = elf->ed_phdrsz; 5020Sstevel@tonic-gate ELFACCESSDATA(work, _elf_work) 5030Sstevel@tonic-gate src.d_version = work; 5040Sstevel@tonic-gate dst.d_buf = (Elf_Void *)(image + eh->e_phoff); 5050Sstevel@tonic-gate dst.d_size = eh->e_phnum * eh->e_phentsize; 5060Sstevel@tonic-gate hi = (Xword)(eh->e_phoff + dst.d_size); 5070Sstevel@tonic-gate if (elf_xlatetof(&dst, &src, encode) == 0) { 5080Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 5090Sstevel@tonic-gate return (0); 5100Sstevel@tonic-gate } 5110Sstevel@tonic-gate elf->ed_phflags &= ~ELF_F_DIRTY; 5120Sstevel@tonic-gate src.d_version = EV_CURRENT; 5130Sstevel@tonic-gate } 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate /* 5160Sstevel@tonic-gate * Loop through sections 5170Sstevel@tonic-gate */ 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate ELFACCESSDATA(byte, _elf_byte); 5200Sstevel@tonic-gate for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 5210Sstevel@tonic-gate register Dnode *d, *prevd; 5220Sstevel@tonic-gate Xword off = 0; 5230Sstevel@tonic-gate Shdr *sh = s->s_shdr; 5240Sstevel@tonic-gate char *start = image + sh->sh_offset; 5250Sstevel@tonic-gate char *here; 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate /* 5280Sstevel@tonic-gate * Just "clean" DIRTY flag for "empty" sections. Even if 5290Sstevel@tonic-gate * NOBITS needs padding, the next thing in the 5300Sstevel@tonic-gate * file will provide it. (And if this NOBITS is 5310Sstevel@tonic-gate * the last thing in the file, no padding needed.) 5320Sstevel@tonic-gate */ 5330Sstevel@tonic-gate if ((sh->sh_type == SHT_NOBITS) || 5340Sstevel@tonic-gate (sh->sh_type == SHT_NULL)) { 5350Sstevel@tonic-gate d = s->s_hdnode, prevd = 0; 5360Sstevel@tonic-gate for (; d != 0; prevd = d, d = d->db_next) 5370Sstevel@tonic-gate d->db_uflags &= ~ELF_F_DIRTY; 5380Sstevel@tonic-gate continue; 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate /* 5410Sstevel@tonic-gate * Clear out the memory between the end of the last 5420Sstevel@tonic-gate * section and the begining of this section. 5430Sstevel@tonic-gate */ 5440Sstevel@tonic-gate if (fill && (sh->sh_offset > hi)) { 5450Sstevel@tonic-gate sz = sh->sh_offset - hi; 5460Sstevel@tonic-gate (void) memset(start - sz, byte, sz); 5470Sstevel@tonic-gate } 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate for (d = s->s_hdnode, prevd = 0; 5510Sstevel@tonic-gate d != 0; prevd = d, d = d->db_next) { 5520Sstevel@tonic-gate d->db_uflags &= ~ELF_F_DIRTY; 5530Sstevel@tonic-gate here = start + d->db_data.d_off; 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate /* 5560Sstevel@tonic-gate * Clear out the memory between the end of the 5570Sstevel@tonic-gate * last update and the start of this data buffer. 5580Sstevel@tonic-gate */ 5590Sstevel@tonic-gate if (fill && (d->db_data.d_off > off)) { 5600Sstevel@tonic-gate sz = (Xword)(d->db_data.d_off - off); 5610Sstevel@tonic-gate (void) memset(here - sz, byte, sz); 5620Sstevel@tonic-gate } 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate if ((d->db_myflags & DBF_READY) == 0) { 5650Sstevel@tonic-gate SCNLOCK(s); 5660Sstevel@tonic-gate if (_elf_locked_getdata(s, &prevd->db_data) != 5670Sstevel@tonic-gate &d->db_data) { 5680Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 5690Sstevel@tonic-gate SCNUNLOCK(s); 5700Sstevel@tonic-gate return (0); 5710Sstevel@tonic-gate } 5720Sstevel@tonic-gate SCNUNLOCK(s); 5730Sstevel@tonic-gate } 5740Sstevel@tonic-gate dst.d_buf = (Elf_Void *)here; 5750Sstevel@tonic-gate dst.d_size = d->db_osz; 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate /* 5780Sstevel@tonic-gate * Copy the translated bits out to the destination 5790Sstevel@tonic-gate * image. 5800Sstevel@tonic-gate */ 5810Sstevel@tonic-gate if (elf_xlatetof(&dst, &d->db_data, encode) == 0) { 5820Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 5830Sstevel@tonic-gate return (0); 5840Sstevel@tonic-gate } 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate off = (Xword)(d->db_data.d_off + dst.d_size); 5870Sstevel@tonic-gate } 5880Sstevel@tonic-gate hi = sh->sh_offset + sh->sh_size; 5890Sstevel@tonic-gate } 5900Sstevel@tonic-gate 5910Sstevel@tonic-gate /* 5920Sstevel@tonic-gate * Shdr table last 5930Sstevel@tonic-gate */ 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate if (fill && (eh->e_shoff > hi)) { 5960Sstevel@tonic-gate sz = eh->e_shoff - hi; 5970Sstevel@tonic-gate (void) memset(image + hi, byte, sz); 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate src.d_type = ELF_T_SHDR; 6010Sstevel@tonic-gate src.d_size = sizeof (Shdr); 6020Sstevel@tonic-gate dst.d_buf = (Elf_Void *)(image + eh->e_shoff); 6030Sstevel@tonic-gate dst.d_size = eh->e_shentsize; 6040Sstevel@tonic-gate for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 6050Sstevel@tonic-gate assert((uintptr_t)dst.d_buf < ((uintptr_t)image + outsz)); 6060Sstevel@tonic-gate s->s_shflags &= ~ELF_F_DIRTY; 6070Sstevel@tonic-gate s->s_uflags &= ~ELF_F_DIRTY; 6080Sstevel@tonic-gate src.d_buf = s->s_shdr; 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate if (elf_xlatetof(&dst, &src, encode) == 0) { 6110Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 6120Sstevel@tonic-gate return (0); 6130Sstevel@tonic-gate } 6140Sstevel@tonic-gate 6150Sstevel@tonic-gate dst.d_buf = (char *)dst.d_buf + eh->e_shentsize; 6160Sstevel@tonic-gate } 6170Sstevel@tonic-gate /* 6180Sstevel@tonic-gate * ELF_C_WRIMAGE signifyes that we build the memory image, but 6190Sstevel@tonic-gate * that we do not actually write it to disk. This is used 6200Sstevel@tonic-gate * by ld(1) to build up a full image of an elf file and then 6210Sstevel@tonic-gate * to process the file before it's actually written out to 6220Sstevel@tonic-gate * disk. This saves ld(1) the overhead of having to write 6230Sstevel@tonic-gate * the image out to disk twice. 6240Sstevel@tonic-gate */ 6250Sstevel@tonic-gate if (update_cmd == ELF_C_WRIMAGE) { 6260Sstevel@tonic-gate elf->ed_uflags &= ~ELF_F_DIRTY; 6270Sstevel@tonic-gate elf->ed_wrimage = image; 6280Sstevel@tonic-gate elf->ed_wrimagesz = outsz; 6290Sstevel@tonic-gate return (outsz); 6300Sstevel@tonic-gate } 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate if (_elf_outsync(elf->ed_fd, image, outsz, 6330Sstevel@tonic-gate ((elf->ed_myflags & EDF_IMALLOC) ? 0 : 1)) != 0) { 6340Sstevel@tonic-gate elf->ed_uflags &= ~ELF_F_DIRTY; 6350Sstevel@tonic-gate elf->ed_myflags &= ~EDF_IMALLOC; 6360Sstevel@tonic-gate return (outsz); 6370Sstevel@tonic-gate } 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 6400Sstevel@tonic-gate return (0); 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate /* 6470Sstevel@tonic-gate * The following is a private interface between the linkers (ld & ld.so.1) 6480Sstevel@tonic-gate * and libelf: 6490Sstevel@tonic-gate * 6500Sstevel@tonic-gate * elf_update(elf, ELF_C_WRIMAGE) 6510Sstevel@tonic-gate * This will cause full image representing the elf file 6520Sstevel@tonic-gate * described by the elf pointer to be built in memory. If the 6530Sstevel@tonic-gate * elf pointer has a valid file descriptor associated with it 6540Sstevel@tonic-gate * we will attempt to build the memory image from mmap()'ed 6550Sstevel@tonic-gate * storage. If the elf descriptor does not have a valid 6560Sstevel@tonic-gate * file descriptor (opened with elf_begin(0, ELF_C_IMAGE, 0)) 6570Sstevel@tonic-gate * then the image will be allocated from dynamic memory (malloc()). 6580Sstevel@tonic-gate * 6590Sstevel@tonic-gate * elf_update() will return the size of the memory image built 6600Sstevel@tonic-gate * when sucessful. 6610Sstevel@tonic-gate * 6620Sstevel@tonic-gate * When a subsequent call to elf_update() with ELF_C_WRITE as 6630Sstevel@tonic-gate * the command is performed it will sync the image created 6640Sstevel@tonic-gate * by ELF_C_WRIMAGE to disk (if fd available) and 6650Sstevel@tonic-gate * free the memory allocated. 6660Sstevel@tonic-gate */ 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate off_t 6690Sstevel@tonic-gate _elfxx_update(Elf * elf, Elf_Cmd cmd) 6700Sstevel@tonic-gate { 6710Sstevel@tonic-gate size_t sz; 6720Sstevel@tonic-gate unsigned u; 6730Sstevel@tonic-gate Ehdr *eh = elf->ed_ehdr; 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate if (elf == 0) 6760Sstevel@tonic-gate return (-1); 6770Sstevel@tonic-gate 6780Sstevel@tonic-gate ELFWLOCK(elf) 6790Sstevel@tonic-gate switch (cmd) { 6800Sstevel@tonic-gate default: 6810Sstevel@tonic-gate _elf_seterr(EREQ_UPDATE, 0); 6820Sstevel@tonic-gate ELFUNLOCK(elf) 6830Sstevel@tonic-gate return (-1); 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate case ELF_C_WRIMAGE: 6860Sstevel@tonic-gate if ((elf->ed_myflags & EDF_WRITE) == 0) { 6870Sstevel@tonic-gate _elf_seterr(EREQ_UPDWRT, 0); 6880Sstevel@tonic-gate ELFUNLOCK(elf) 6890Sstevel@tonic-gate return (-1); 6900Sstevel@tonic-gate } 6910Sstevel@tonic-gate break; 6920Sstevel@tonic-gate case ELF_C_WRITE: 6930Sstevel@tonic-gate if ((elf->ed_myflags & EDF_WRITE) == 0) { 6940Sstevel@tonic-gate _elf_seterr(EREQ_UPDWRT, 0); 6950Sstevel@tonic-gate ELFUNLOCK(elf) 6960Sstevel@tonic-gate return (-1); 6970Sstevel@tonic-gate } 6980Sstevel@tonic-gate if (elf->ed_wrimage) { 6990Sstevel@tonic-gate if (elf->ed_myflags & EDF_WRALLOC) { 7000Sstevel@tonic-gate free(elf->ed_wrimage); 7010Sstevel@tonic-gate /* 7020Sstevel@tonic-gate * The size is still returned even 7030Sstevel@tonic-gate * though nothing is actually written 7040Sstevel@tonic-gate * out. This is just to be consistant 7050Sstevel@tonic-gate * with the rest of the interface. 7060Sstevel@tonic-gate */ 7070Sstevel@tonic-gate sz = elf->ed_wrimagesz; 7080Sstevel@tonic-gate elf->ed_wrimage = 0; 7090Sstevel@tonic-gate elf->ed_wrimagesz = 0; 7100Sstevel@tonic-gate ELFUNLOCK(elf); 7110Sstevel@tonic-gate return ((off_t)sz); 7120Sstevel@tonic-gate } 7130Sstevel@tonic-gate sz = _elf_outsync(elf->ed_fd, elf->ed_wrimage, 714*6206Sab196087 elf->ed_wrimagesz, 715*6206Sab196087 (elf->ed_myflags & EDF_IMALLOC ? 0 : 1)); 7160Sstevel@tonic-gate elf->ed_myflags &= ~EDF_IMALLOC; 7170Sstevel@tonic-gate elf->ed_wrimage = 0; 7180Sstevel@tonic-gate elf->ed_wrimagesz = 0; 7190Sstevel@tonic-gate ELFUNLOCK(elf); 7200Sstevel@tonic-gate return ((off_t)sz); 7210Sstevel@tonic-gate } 7220Sstevel@tonic-gate /* FALLTHROUGH */ 7230Sstevel@tonic-gate case ELF_C_NULL: 7240Sstevel@tonic-gate break; 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate if (eh == 0) { 7280Sstevel@tonic-gate _elf_seterr(ESEQ_EHDR, 0); 7290Sstevel@tonic-gate ELFUNLOCK(elf) 7300Sstevel@tonic-gate return (-1); 7310Sstevel@tonic-gate } 7320Sstevel@tonic-gate 7330Sstevel@tonic-gate if ((u = eh->e_version) > EV_CURRENT) { 7340Sstevel@tonic-gate _elf_seterr(EREQ_VER, 0); 7350Sstevel@tonic-gate ELFUNLOCK(elf) 7360Sstevel@tonic-gate return (-1); 7370Sstevel@tonic-gate } 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate if (u == EV_NONE) 7400Sstevel@tonic-gate eh->e_version = EV_CURRENT; 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate if ((u = eh->e_ident[EI_DATA]) == ELFDATANONE) { 7430Sstevel@tonic-gate unsigned encode; 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate ELFACCESSDATA(encode, _elf_encode) 7460Sstevel@tonic-gate if (encode == ELFDATANONE) { 7470Sstevel@tonic-gate _elf_seterr(EREQ_ENCODE, 0); 7480Sstevel@tonic-gate ELFUNLOCK(elf) 7490Sstevel@tonic-gate return (-1); 7500Sstevel@tonic-gate } 7510Sstevel@tonic-gate /* LINTED */ 7520Sstevel@tonic-gate eh->e_ident[EI_DATA] = (Byte)encode; 7530Sstevel@tonic-gate } 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate u = 1; 7560Sstevel@tonic-gate if (elf->ed_uflags & ELF_F_LAYOUT) { 7570Sstevel@tonic-gate sz = _elf_upd_usr(elf); 7580Sstevel@tonic-gate u = 0; 7590Sstevel@tonic-gate } else 7600Sstevel@tonic-gate sz = _elf_upd_lib(elf); 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate if ((sz != 0) && ((cmd == ELF_C_WRITE) || (cmd == ELF_C_WRIMAGE))) 7630Sstevel@tonic-gate sz = wrt(elf, (Xword)sz, u, cmd); 7640Sstevel@tonic-gate 7650Sstevel@tonic-gate if (sz == 0) { 7660Sstevel@tonic-gate ELFUNLOCK(elf) 7670Sstevel@tonic-gate return (-1); 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate ELFUNLOCK(elf) 7710Sstevel@tonic-gate return ((off_t)sz); 7720Sstevel@tonic-gate } 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate 775*6206Sab196087 /* 776*6206Sab196087 * When wrt() processes an ELF_C_WRIMAGE request, the resulting image 777*6206Sab196087 * gets the byte order (encoding) of the platform running the linker 778*6206Sab196087 * rather than that of the target host. This allows the linker to modify 779*6206Sab196087 * the image, prior to flushing it to the output file. This routine 780*6206Sab196087 * is used to re-translate such an image into the byte order of the 781*6206Sab196087 * target host. 782*6206Sab196087 */ 783*6206Sab196087 int 784*6206Sab196087 _elfxx_swap_wrimage(Elf * elf) 785*6206Sab196087 { 786*6206Sab196087 NOTE(ASSUMING_PROTECTED(*elf)) 787*6206Sab196087 Elf_Data dst, src; 788*6206Sab196087 Elf_Scn *s; 789*6206Sab196087 Ehdr *eh = elf->ed_ehdr; 790*6206Sab196087 Half e_phnum = eh->e_phnum; 791*6206Sab196087 unsigned ver = eh->e_version; 792*6206Sab196087 unsigned encode = eh->e_ident[EI_DATA]; 793*6206Sab196087 794*6206Sab196087 /* 795*6206Sab196087 * Ehdr first 796*6206Sab196087 */ 797*6206Sab196087 798*6206Sab196087 src.d_buf = dst.d_buf = (Elf_Void *)eh; 799*6206Sab196087 src.d_type = dst.d_type = ELF_T_EHDR; 800*6206Sab196087 src.d_size = dst.d_size = sizeof (Ehdr); 801*6206Sab196087 src.d_version = dst.d_version = ver; 802*6206Sab196087 if (elf_xlatetof(&dst, &src, encode) == 0) 803*6206Sab196087 return (1); 804*6206Sab196087 805*6206Sab196087 /* 806*6206Sab196087 * Phdr table if one exists 807*6206Sab196087 */ 808*6206Sab196087 809*6206Sab196087 if (e_phnum != 0) { 810*6206Sab196087 unsigned work; 811*6206Sab196087 /* 812*6206Sab196087 * Unlike other library data, phdr table is 813*6206Sab196087 * in the user version. 814*6206Sab196087 */ 815*6206Sab196087 816*6206Sab196087 src.d_buf = dst.d_buf = (Elf_Void *)elf->ed_phdr; 817*6206Sab196087 src.d_type = dst.d_type = ELF_T_PHDR; 818*6206Sab196087 src.d_size = dst.d_size = elf->ed_phdrsz; 819*6206Sab196087 ELFACCESSDATA(work, _elf_work) 820*6206Sab196087 src.d_version = dst.d_version = work; 821*6206Sab196087 if (elf_xlatetof(&dst, &src, encode) == 0) { 822*6206Sab196087 return (1); 823*6206Sab196087 } 824*6206Sab196087 } 825*6206Sab196087 826*6206Sab196087 /* 827*6206Sab196087 * Loop through sections 828*6206Sab196087 */ 829*6206Sab196087 830*6206Sab196087 for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 831*6206Sab196087 register Dnode *d, *prevd; 832*6206Sab196087 Shdr *sh = s->s_shdr; 833*6206Sab196087 834*6206Sab196087 if ((sh->sh_type == SHT_NOBITS) || (sh->sh_type == SHT_NULL)) 835*6206Sab196087 continue; 836*6206Sab196087 837*6206Sab196087 for (d = s->s_hdnode, prevd = 0; 838*6206Sab196087 d != 0; prevd = d, d = d->db_next) { 839*6206Sab196087 840*6206Sab196087 if ((d->db_myflags & DBF_READY) == 0) { 841*6206Sab196087 SCNLOCK(s); 842*6206Sab196087 if (_elf_locked_getdata(s, &prevd->db_data) != 843*6206Sab196087 &d->db_data) { 844*6206Sab196087 SCNUNLOCK(s); 845*6206Sab196087 return (1); 846*6206Sab196087 } 847*6206Sab196087 SCNUNLOCK(s); 848*6206Sab196087 } 849*6206Sab196087 850*6206Sab196087 dst = d->db_data; 851*6206Sab196087 if (elf_xlatetof(&dst, &d->db_data, encode) == 0) 852*6206Sab196087 return (1); 853*6206Sab196087 } 854*6206Sab196087 } 855*6206Sab196087 856*6206Sab196087 /* 857*6206Sab196087 * Shdr table 858*6206Sab196087 */ 859*6206Sab196087 860*6206Sab196087 src.d_type = dst.d_type = ELF_T_SHDR; 861*6206Sab196087 src.d_version = dst.d_version = ver; 862*6206Sab196087 for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 863*6206Sab196087 src.d_buf = dst.d_buf = s->s_shdr; 864*6206Sab196087 src.d_size = dst.d_size = sizeof (Shdr); 865*6206Sab196087 if (elf_xlatetof(&dst, &src, encode) == 0) 866*6206Sab196087 return (1); 867*6206Sab196087 } 868*6206Sab196087 869*6206Sab196087 return (0); 870*6206Sab196087 } 871*6206Sab196087 872*6206Sab196087 873*6206Sab196087 8740Sstevel@tonic-gate #ifndef _ELF64 8750Sstevel@tonic-gate /* class-independent, only needs to be compiled once */ 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate off_t 8780Sstevel@tonic-gate elf_update(Elf *elf, Elf_Cmd cmd) 8790Sstevel@tonic-gate { 8800Sstevel@tonic-gate if (elf == 0) 8810Sstevel@tonic-gate return (-1); 8820Sstevel@tonic-gate 8830Sstevel@tonic-gate if (elf->ed_class == ELFCLASS32) 8840Sstevel@tonic-gate return (_elf32_update(elf, cmd)); 8850Sstevel@tonic-gate else if (elf->ed_class == ELFCLASS64) { 8860Sstevel@tonic-gate return (_elf64_update(elf, cmd)); 8870Sstevel@tonic-gate } 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate _elf_seterr(EREQ_CLASS, 0); 8900Sstevel@tonic-gate return (-1); 8910Sstevel@tonic-gate } 8920Sstevel@tonic-gate 893*6206Sab196087 int 894*6206Sab196087 _elf_swap_wrimage(Elf *elf) 895*6206Sab196087 { 896*6206Sab196087 if (elf == 0) 897*6206Sab196087 return (0); 898*6206Sab196087 899*6206Sab196087 if (elf->ed_class == ELFCLASS32) 900*6206Sab196087 return (_elf32_swap_wrimage(elf)); 901*6206Sab196087 902*6206Sab196087 if (elf->ed_class == ELFCLASS64) 903*6206Sab196087 return (_elf64_swap_wrimage(elf)); 904*6206Sab196087 905*6206Sab196087 _elf_seterr(EREQ_CLASS, 0); 906*6206Sab196087 return (0); 907*6206Sab196087 } 908*6206Sab196087 9090Sstevel@tonic-gate /* 9100Sstevel@tonic-gate * 4106312, 4106398, This is an ad-hoc means for the 32-bit 9110Sstevel@tonic-gate * Elf64 version of libld.so.3 to get around the limitation 9120Sstevel@tonic-gate * of a 32-bit d_off field. This is only intended to be 9130Sstevel@tonic-gate * used by libld to relocate symbols in large NOBITS sections. 9140Sstevel@tonic-gate */ 9150Sstevel@tonic-gate Elf64_Off 9160Sstevel@tonic-gate _elf_getxoff(Elf_Data * d) 9170Sstevel@tonic-gate { 9180Sstevel@tonic-gate return (((Dnode *)d)->db_xoff); 9190Sstevel@tonic-gate } 9200Sstevel@tonic-gate #endif /* !_ELF64 */ 921