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 * 276206Sab196087 * 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 696206Sab196087 #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 856206Sab196087 #define _elfxx_swap_wrimage _elf32_swap_wrimage 860Sstevel@tonic-gate 870Sstevel@tonic-gate #endif /* ELF64 */ 880Sstevel@tonic-gate 890Sstevel@tonic-gate 90*6223Sab196087 #if !(defined(_LP64) && defined(_ELF64)) 91*6223Sab196087 #define TEST_SIZE 92*6223Sab196087 93*6223Sab196087 /* 94*6223Sab196087 * Handle the decision of whether the current linker can handle the 95*6223Sab196087 * desired object size, and if not, which error to issue. 96*6223Sab196087 * 97*6223Sab196087 * Input is the desired size. On failure, an error has been issued 98*6223Sab196087 * and 0 is returned. On success, 1 is returned. 99*6223Sab196087 */ 100*6223Sab196087 static int 101*6223Sab196087 test_size(Lword hi) 102*6223Sab196087 { 103*6223Sab196087 #ifndef _LP64 /* 32-bit linker */ 104*6223Sab196087 /* 105*6223Sab196087 * A 32-bit libelf is limited to a 2GB output file. This limit 106*6223Sab196087 * is due to the fact that off_t is a signed value, and that 107*6223Sab196087 * libelf cannot support large file support: 108*6223Sab196087 * - ABI reasons 109*6223Sab196087 * - Memory use generally is 2x output file size anyway, 110*6223Sab196087 * so lifting the file size limit will just send 111*6223Sab196087 * you crashing into the 32-bit VM limit. 112*6223Sab196087 * If the output is an ELFCLASS64 object, or an ELFCLASS32 object 113*6223Sab196087 * under 4GB, switching to the 64-bit version of libelf will help. 114*6223Sab196087 * However, an ELFCLASS32 object must not exceed 4GB. 115*6223Sab196087 */ 116*6223Sab196087 if (hi > INT_MAX) { /* Bigger than 2GB */ 117*6223Sab196087 #ifndef _ELF64 118*6223Sab196087 /* ELFCLASS32 object is fundamentally too big? */ 119*6223Sab196087 if (hi > UINT_MAX) { 120*6223Sab196087 _elf_seterr(EFMT_FBIG_CLASS32, 0); 121*6223Sab196087 return (0); 122*6223Sab196087 } 123*6223Sab196087 #endif /* _ELF64 */ 124*6223Sab196087 125*6223Sab196087 /* Should switch to the 64-bit libelf? */ 126*6223Sab196087 _elf_seterr(EFMT_FBIG_LARGEFILE, 0); 127*6223Sab196087 return (0); 128*6223Sab196087 } 129*6223Sab196087 #endif /* !_LP64 */ 130*6223Sab196087 131*6223Sab196087 132*6223Sab196087 #if defined(_LP64) && !defined(_ELF64) /* 64-bit linker, ELFCLASS32 */ 133*6223Sab196087 /* 134*6223Sab196087 * A 64-bit linker can produce any size output 135*6223Sab196087 * file, but if the resulting file is ELFCLASS32, 136*6223Sab196087 * it must not exceed 4GB. 137*6223Sab196087 */ 138*6223Sab196087 if (hi > UINT_MAX) { 139*6223Sab196087 _elf_seterr(EFMT_FBIG_CLASS32, 0); 140*6223Sab196087 return (0); 141*6223Sab196087 } 142*6223Sab196087 #endif 143*6223Sab196087 144*6223Sab196087 return (1); 145*6223Sab196087 } 146*6223Sab196087 #endif /* TEST_SIZE */ 147*6223Sab196087 1480Sstevel@tonic-gate /* 1490Sstevel@tonic-gate * Output file update 1500Sstevel@tonic-gate * These functions walk an Elf structure, update its information, 1510Sstevel@tonic-gate * and optionally write the output file. Because the application 1520Sstevel@tonic-gate * may control of the output file layout, two upd_... routines 1530Sstevel@tonic-gate * exist. They're similar but too different to merge cleanly. 1540Sstevel@tonic-gate * 1550Sstevel@tonic-gate * The library defines a "dirty" bit to force parts of the file 1560Sstevel@tonic-gate * to be written on update. These routines ignore the dirty bit 1570Sstevel@tonic-gate * and do everything. A minimal update routine might be useful 1580Sstevel@tonic-gate * someday. 1590Sstevel@tonic-gate */ 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate static size_t 1620Sstevel@tonic-gate _elf_upd_lib(Elf * elf) 1630Sstevel@tonic-gate { 1640Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 1650Sstevel@tonic-gate Lword hi; 1660Sstevel@tonic-gate Lword hibit; 1670Sstevel@tonic-gate Elf_Scn * s; 168*6223Sab196087 register Lword sz; 1690Sstevel@tonic-gate Ehdr * eh = elf->ed_ehdr; 1700Sstevel@tonic-gate unsigned ver = eh->e_version; 1710Sstevel@tonic-gate register char *p = (char *)eh->e_ident; 1720Sstevel@tonic-gate size_t scncnt; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate /* 1750Sstevel@tonic-gate * Ehdr and Phdr table go first 1760Sstevel@tonic-gate */ 1770Sstevel@tonic-gate p[EI_MAG0] = ELFMAG0; 1780Sstevel@tonic-gate p[EI_MAG1] = ELFMAG1; 1790Sstevel@tonic-gate p[EI_MAG2] = ELFMAG2; 1800Sstevel@tonic-gate p[EI_MAG3] = ELFMAG3; 1810Sstevel@tonic-gate p[EI_CLASS] = ELFCLASS; 1820Sstevel@tonic-gate /* LINTED */ 1830Sstevel@tonic-gate p[EI_VERSION] = (Byte)ver; 1840Sstevel@tonic-gate hi = elf_fsize(ELF_T_EHDR, 1, ver); 1850Sstevel@tonic-gate /* LINTED */ 1860Sstevel@tonic-gate eh->e_ehsize = (Half)hi; 1870Sstevel@tonic-gate if (eh->e_phnum != 0) { 1880Sstevel@tonic-gate /* LINTED */ 1890Sstevel@tonic-gate eh->e_phentsize = (Half)elf_fsize(ELF_T_PHDR, 1, ver); 1900Sstevel@tonic-gate /* LINTED */ 1910Sstevel@tonic-gate eh->e_phoff = (Off)hi; 1920Sstevel@tonic-gate hi += eh->e_phentsize * eh->e_phnum; 1930Sstevel@tonic-gate } else { 1940Sstevel@tonic-gate eh->e_phoff = 0; 1950Sstevel@tonic-gate eh->e_phentsize = 0; 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate /* 1991682Srie * Obtain the first section header. Typically, this section has NULL 2001682Srie * contents, however in the case of Extended ELF Sections this section 2011682Srie * is used to hold an alternative e_shnum, e_shstrndx and e_phnum. 2021682Srie * On initial allocation (see _elf_snode) the elements of this section 2031682Srie * would have been zeroed. The e_shnum is initialized later, after the 2041682Srie * section header count has been determined. The e_shstrndx and 2051682Srie * e_phnum may have already been initialized by the caller (for example, 2061682Srie * gelf_update_shdr() in mcs(1)). 2070Sstevel@tonic-gate */ 2080Sstevel@tonic-gate if ((s = elf->ed_hdscn) == 0) { 2090Sstevel@tonic-gate eh->e_shnum = 0; 2100Sstevel@tonic-gate scncnt = 0; 2110Sstevel@tonic-gate } else { 2121682Srie s = s->s_next; 2130Sstevel@tonic-gate scncnt = 1; 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate 2161682Srie /* 2171682Srie * Loop through sections. Compute section size before changing hi. 2181682Srie * Allow null buffers for NOBITS. 2191682Srie */ 2200Sstevel@tonic-gate hibit = 0; 2210Sstevel@tonic-gate for (; s != 0; s = s->s_next) { 2220Sstevel@tonic-gate register Dnode *d; 2230Sstevel@tonic-gate register Lword fsz, j; 2240Sstevel@tonic-gate Shdr *sh = s->s_shdr; 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate scncnt++; 2270Sstevel@tonic-gate if (sh->sh_type == SHT_NULL) { 2280Sstevel@tonic-gate *sh = _elf_snode_init.sb_shdr; 2290Sstevel@tonic-gate continue; 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate if ((s->s_myflags & SF_READY) == 0) 2330Sstevel@tonic-gate (void) _elfxx_cookscn(s); 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate sh->sh_addralign = 1; 236*6223Sab196087 if ((sz = (Lword)_elf_entsz(elf, sh->sh_type, ver)) != 0) 2370Sstevel@tonic-gate /* LINTED */ 2380Sstevel@tonic-gate sh->sh_entsize = (Half)sz; 2390Sstevel@tonic-gate sz = 0; 2400Sstevel@tonic-gate for (d = s->s_hdnode; d != 0; d = d->db_next) { 2410Sstevel@tonic-gate if ((fsz = elf_fsize(d->db_data.d_type, 2420Sstevel@tonic-gate 1, ver)) == 0) 2430Sstevel@tonic-gate return (0); 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate j = _elf_msize(d->db_data.d_type, ver); 2460Sstevel@tonic-gate fsz *= (d->db_data.d_size / j); 2470Sstevel@tonic-gate d->db_osz = (size_t)fsz; 2480Sstevel@tonic-gate if ((j = d->db_data.d_align) > 1) { 2490Sstevel@tonic-gate if (j > sh->sh_addralign) 2500Sstevel@tonic-gate sh->sh_addralign = (Xword)j; 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate if (sz % j != 0) 2530Sstevel@tonic-gate sz += j - sz % j; 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate d->db_data.d_off = (off_t)sz; 2560Sstevel@tonic-gate d->db_xoff = sz; 257*6223Sab196087 sz += fsz; 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate 260*6223Sab196087 sh->sh_size = (Xword) sz; 2610Sstevel@tonic-gate /* 2620Sstevel@tonic-gate * We want to take into account the offsets for NOBITS 2630Sstevel@tonic-gate * sections and let the "sh_offsets" point to where 2640Sstevel@tonic-gate * the section would 'conceptually' fit within 2650Sstevel@tonic-gate * the file (as required by the ABI). 2660Sstevel@tonic-gate * 2670Sstevel@tonic-gate * But - we must also make sure that the NOBITS does 2680Sstevel@tonic-gate * not take up any actual space in the file. We preserve 2690Sstevel@tonic-gate * the actual offset into the file in the 'hibit' variable. 2700Sstevel@tonic-gate * When we come to the first non-NOBITS section after a 2710Sstevel@tonic-gate * encountering a NOBITS section the hi counter is restored 2720Sstevel@tonic-gate * to its proper place in the file. 2730Sstevel@tonic-gate */ 2740Sstevel@tonic-gate if (sh->sh_type == SHT_NOBITS) { 2750Sstevel@tonic-gate if (hibit == 0) 2760Sstevel@tonic-gate hibit = hi; 2770Sstevel@tonic-gate } else { 2780Sstevel@tonic-gate if (hibit) { 2790Sstevel@tonic-gate hi = hibit; 2800Sstevel@tonic-gate hibit = 0; 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate j = sh->sh_addralign; 2840Sstevel@tonic-gate if ((fsz = hi % j) != 0) 2850Sstevel@tonic-gate hi += j - fsz; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate /* LINTED */ 2880Sstevel@tonic-gate sh->sh_offset = (Off)hi; 2890Sstevel@tonic-gate hi += sz; 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* 2930Sstevel@tonic-gate * if last section was a 'NOBITS' section then we need to 2940Sstevel@tonic-gate * restore the 'hi' counter to point to the end of the last 2950Sstevel@tonic-gate * non 'NOBITS' section. 2960Sstevel@tonic-gate */ 2970Sstevel@tonic-gate if (hibit) { 2980Sstevel@tonic-gate hi = hibit; 2990Sstevel@tonic-gate hibit = 0; 3000Sstevel@tonic-gate } 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate /* 3030Sstevel@tonic-gate * Shdr table last 3040Sstevel@tonic-gate */ 3050Sstevel@tonic-gate if (scncnt != 0) { 3060Sstevel@tonic-gate if (hi % FSZ_LONG != 0) 3070Sstevel@tonic-gate hi += FSZ_LONG - hi % FSZ_LONG; 3080Sstevel@tonic-gate /* LINTED */ 3090Sstevel@tonic-gate eh->e_shoff = (Off)hi; 3100Sstevel@tonic-gate /* 3110Sstevel@tonic-gate * If we are using 'extended sections' then the 3120Sstevel@tonic-gate * e_shnum is stored in the sh_size field of the 3130Sstevel@tonic-gate * first section header. 3140Sstevel@tonic-gate * 3150Sstevel@tonic-gate * NOTE: we set e_shnum to '0' because it's specified 3160Sstevel@tonic-gate * this way in the gABI, and in the hopes that 3170Sstevel@tonic-gate * this will cause less problems to unaware 3180Sstevel@tonic-gate * tools then if we'd set it to SHN_XINDEX (0xffff). 3190Sstevel@tonic-gate */ 3200Sstevel@tonic-gate if (scncnt < SHN_LORESERVE) 3210Sstevel@tonic-gate eh->e_shnum = scncnt; 3220Sstevel@tonic-gate else { 3230Sstevel@tonic-gate Shdr *sh; 3240Sstevel@tonic-gate sh = (Shdr *)elf->ed_hdscn->s_shdr; 3250Sstevel@tonic-gate sh->sh_size = scncnt; 3260Sstevel@tonic-gate eh->e_shnum = 0; 3270Sstevel@tonic-gate } 3280Sstevel@tonic-gate /* LINTED */ 3290Sstevel@tonic-gate eh->e_shentsize = (Half)elf_fsize(ELF_T_SHDR, 1, ver); 3300Sstevel@tonic-gate hi += eh->e_shentsize * scncnt; 3310Sstevel@tonic-gate } else { 3320Sstevel@tonic-gate eh->e_shoff = 0; 3330Sstevel@tonic-gate eh->e_shentsize = 0; 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate 336*6223Sab196087 #ifdef TEST_SIZE 337*6223Sab196087 if (test_size(hi) == 0) 3380Sstevel@tonic-gate return (0); 3390Sstevel@tonic-gate #endif 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate return ((size_t)hi); 3420Sstevel@tonic-gate } 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate static size_t 3470Sstevel@tonic-gate _elf_upd_usr(Elf * elf) 3480Sstevel@tonic-gate { 3490Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 3500Sstevel@tonic-gate Lword hi; 3510Sstevel@tonic-gate Elf_Scn * s; 352*6223Sab196087 register Lword sz; 3530Sstevel@tonic-gate Ehdr * eh = elf->ed_ehdr; 3540Sstevel@tonic-gate unsigned ver = eh->e_version; 3550Sstevel@tonic-gate register char *p = (char *)eh->e_ident; 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate /* 3590Sstevel@tonic-gate * Ehdr and Phdr table go first 3600Sstevel@tonic-gate */ 3610Sstevel@tonic-gate p[EI_MAG0] = ELFMAG0; 3620Sstevel@tonic-gate p[EI_MAG1] = ELFMAG1; 3630Sstevel@tonic-gate p[EI_MAG2] = ELFMAG2; 3640Sstevel@tonic-gate p[EI_MAG3] = ELFMAG3; 3650Sstevel@tonic-gate p[EI_CLASS] = ELFCLASS; 3660Sstevel@tonic-gate /* LINTED */ 3670Sstevel@tonic-gate p[EI_VERSION] = (Byte)ver; 3680Sstevel@tonic-gate hi = elf_fsize(ELF_T_EHDR, 1, ver); 3690Sstevel@tonic-gate /* LINTED */ 3700Sstevel@tonic-gate eh->e_ehsize = (Half)hi; 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate /* 3730Sstevel@tonic-gate * If phnum is zero, phoff "should" be zero too, 3740Sstevel@tonic-gate * but the application is responsible for it. 3750Sstevel@tonic-gate * Allow a non-zero value here and update the 3760Sstevel@tonic-gate * hi water mark accordingly. 3770Sstevel@tonic-gate */ 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate if (eh->e_phnum != 0) 3800Sstevel@tonic-gate /* LINTED */ 3810Sstevel@tonic-gate eh->e_phentsize = (Half)elf_fsize(ELF_T_PHDR, 1, ver); 3820Sstevel@tonic-gate else 3830Sstevel@tonic-gate eh->e_phentsize = 0; 3840Sstevel@tonic-gate if ((sz = eh->e_phoff + eh->e_phentsize * eh->e_phnum) > hi) 3850Sstevel@tonic-gate hi = sz; 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate /* 3880Sstevel@tonic-gate * Loop through sections, skipping index zero. 3890Sstevel@tonic-gate * Compute section size before changing hi. 3900Sstevel@tonic-gate * Allow null buffers for NOBITS. 3910Sstevel@tonic-gate */ 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate if ((s = elf->ed_hdscn) == 0) 3940Sstevel@tonic-gate eh->e_shnum = 0; 3950Sstevel@tonic-gate else { 3960Sstevel@tonic-gate eh->e_shnum = 1; 3970Sstevel@tonic-gate *(Shdr*)s->s_shdr = _elf_snode_init.sb_shdr; 3980Sstevel@tonic-gate s = s->s_next; 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate for (; s != 0; s = s->s_next) { 4010Sstevel@tonic-gate register Dnode *d; 402*6223Sab196087 register Lword fsz, j; 4030Sstevel@tonic-gate Shdr *sh = s->s_shdr; 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate if ((s->s_myflags & SF_READY) == 0) 4060Sstevel@tonic-gate (void) _elfxx_cookscn(s); 4070Sstevel@tonic-gate 4080Sstevel@tonic-gate ++eh->e_shnum; 4090Sstevel@tonic-gate sz = 0; 4100Sstevel@tonic-gate for (d = s->s_hdnode; d != 0; d = d->db_next) { 411*6223Sab196087 if ((fsz = elf_fsize(d->db_data.d_type, 1, 4120Sstevel@tonic-gate ver)) == 0) 4130Sstevel@tonic-gate return (0); 414*6223Sab196087 j = _elf_msize(d->db_data.d_type, ver); 415*6223Sab196087 fsz *= (d->db_data.d_size / j); 4160Sstevel@tonic-gate d->db_osz = (size_t)fsz; 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate if ((sh->sh_type != SHT_NOBITS) && 419*6223Sab196087 ((j = (d->db_data.d_off + d->db_osz)) > sz)) 4200Sstevel@tonic-gate sz = j; 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate if (sh->sh_size < sz) { 4230Sstevel@tonic-gate _elf_seterr(EFMT_SCNSZ, 0); 4240Sstevel@tonic-gate return (0); 4250Sstevel@tonic-gate } 4260Sstevel@tonic-gate if ((sh->sh_type != SHT_NOBITS) && 4270Sstevel@tonic-gate (hi < sh->sh_offset + sh->sh_size)) 4280Sstevel@tonic-gate hi = sh->sh_offset + sh->sh_size; 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* 4320Sstevel@tonic-gate * Shdr table last. Comment above for phnum/phoff applies here. 4330Sstevel@tonic-gate */ 4340Sstevel@tonic-gate if (eh->e_shnum != 0) 4350Sstevel@tonic-gate /* LINTED */ 4360Sstevel@tonic-gate eh->e_shentsize = (Half)elf_fsize(ELF_T_SHDR, 1, ver); 4370Sstevel@tonic-gate else 4380Sstevel@tonic-gate eh->e_shentsize = 0; 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate if ((sz = eh->e_shoff + eh->e_shentsize * eh->e_shnum) > hi) 4410Sstevel@tonic-gate hi = sz; 4420Sstevel@tonic-gate 443*6223Sab196087 #ifdef TEST_SIZE 444*6223Sab196087 if (test_size(hi) == 0) 4450Sstevel@tonic-gate return (0); 4460Sstevel@tonic-gate #endif 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate return ((size_t)hi); 4490Sstevel@tonic-gate } 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate static size_t 4530Sstevel@tonic-gate wrt(Elf * elf, Xword outsz, unsigned fill, int update_cmd) 4540Sstevel@tonic-gate { 4550Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 4560Sstevel@tonic-gate Elf_Data dst, src; 4570Sstevel@tonic-gate unsigned flag; 4580Sstevel@tonic-gate Xword hi, sz; 4590Sstevel@tonic-gate char *image; 4600Sstevel@tonic-gate Elf_Scn *s; 4610Sstevel@tonic-gate Ehdr *eh = elf->ed_ehdr; 4620Sstevel@tonic-gate unsigned ver = eh->e_version; 4636206Sab196087 unsigned encode; 4640Sstevel@tonic-gate int byte; 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate /* 4676206Sab196087 * If this is an ELF_C_WRIMAGE write, then we encode into the 4686206Sab196087 * byte order of the system we are running on rather than that of 4696206Sab196087 * of the object. For ld.so.1, this is the same order, but 4706206Sab196087 * for 'ld', it might not be in the case where we are cross 4716206Sab196087 * linking an object for a different target. In this later case, 4726206Sab196087 * the linker-host byte order is necessary so that the linker can 4736206Sab196087 * manipulate the resulting image. It is expected that the linker 4746206Sab196087 * will call elf_swap_wrimage() if necessary to convert the image 4756206Sab196087 * to the target byte order. 4766206Sab196087 */ 4776206Sab196087 encode = (update_cmd == ELF_C_WRIMAGE) ? _elf_sys_encoding() : 4786206Sab196087 eh->e_ident[EI_DATA]; 4796206Sab196087 4806206Sab196087 /* 4810Sstevel@tonic-gate * Two issues can cause trouble for the output file. 4820Sstevel@tonic-gate * First, begin() with ELF_C_RDWR opens a file for both 4830Sstevel@tonic-gate * read and write. On the write update(), the library 4840Sstevel@tonic-gate * has to read everything it needs before truncating 4850Sstevel@tonic-gate * the file. Second, using mmap for both read and write 4860Sstevel@tonic-gate * is too tricky. Consequently, the library disables mmap 4870Sstevel@tonic-gate * on the read side. Using mmap for the output saves swap 4880Sstevel@tonic-gate * space, because that mapping is SHARED, not PRIVATE. 4890Sstevel@tonic-gate * 4900Sstevel@tonic-gate * If the file is write-only, there can be nothing of 4910Sstevel@tonic-gate * interest to bother with. 4920Sstevel@tonic-gate * 4930Sstevel@tonic-gate * The following reads the entire file, which might be 4940Sstevel@tonic-gate * more than necessary. Better safe than sorry. 4950Sstevel@tonic-gate */ 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate if ((elf->ed_myflags & EDF_READ) && 4980Sstevel@tonic-gate (_elf_vm(elf, (size_t)0, elf->ed_fsz) != OK_YES)) 4990Sstevel@tonic-gate return (0); 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate flag = elf->ed_myflags & EDF_WRALLOC; 5020Sstevel@tonic-gate if ((image = _elf_outmap(elf->ed_fd, outsz, &flag)) == 0) 5030Sstevel@tonic-gate return (0); 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate if (flag == 0) 5060Sstevel@tonic-gate elf->ed_myflags |= EDF_IMALLOC; 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate /* 5090Sstevel@tonic-gate * If an error occurs below, a "dirty" bit may be cleared 5100Sstevel@tonic-gate * improperly. To save a second pass through the file, 5110Sstevel@tonic-gate * this code sets the dirty bit on the elf descriptor 5120Sstevel@tonic-gate * when an error happens, assuming that will "cover" any 5130Sstevel@tonic-gate * accidents. 5140Sstevel@tonic-gate */ 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate /* 5170Sstevel@tonic-gate * Hi is needed only when 'fill' is non-zero. 5180Sstevel@tonic-gate * Fill is non-zero only when the library 5190Sstevel@tonic-gate * calculates file/section/data buffer offsets. 5200Sstevel@tonic-gate * The lib guarantees they increase monotonically. 5210Sstevel@tonic-gate * That guarantees proper filling below. 5220Sstevel@tonic-gate */ 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate /* 5260Sstevel@tonic-gate * Ehdr first 5270Sstevel@tonic-gate */ 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate src.d_buf = (Elf_Void *)eh; 5300Sstevel@tonic-gate src.d_type = ELF_T_EHDR; 5310Sstevel@tonic-gate src.d_size = sizeof (Ehdr); 5320Sstevel@tonic-gate src.d_version = EV_CURRENT; 5330Sstevel@tonic-gate dst.d_buf = (Elf_Void *)image; 5340Sstevel@tonic-gate dst.d_size = eh->e_ehsize; 5350Sstevel@tonic-gate dst.d_version = ver; 5360Sstevel@tonic-gate if (elf_xlatetof(&dst, &src, encode) == 0) 5370Sstevel@tonic-gate return (0); 5380Sstevel@tonic-gate elf->ed_ehflags &= ~ELF_F_DIRTY; 5390Sstevel@tonic-gate hi = eh->e_ehsize; 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate /* 5420Sstevel@tonic-gate * Phdr table if one exists 5430Sstevel@tonic-gate */ 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate if (eh->e_phnum != 0) { 5460Sstevel@tonic-gate unsigned work; 5470Sstevel@tonic-gate /* 5480Sstevel@tonic-gate * Unlike other library data, phdr table is 5490Sstevel@tonic-gate * in the user version. Change src buffer 5500Sstevel@tonic-gate * version here, fix it after translation. 5510Sstevel@tonic-gate */ 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate src.d_buf = (Elf_Void *)elf->ed_phdr; 5540Sstevel@tonic-gate src.d_type = ELF_T_PHDR; 5550Sstevel@tonic-gate src.d_size = elf->ed_phdrsz; 5560Sstevel@tonic-gate ELFACCESSDATA(work, _elf_work) 5570Sstevel@tonic-gate src.d_version = work; 5580Sstevel@tonic-gate dst.d_buf = (Elf_Void *)(image + eh->e_phoff); 5590Sstevel@tonic-gate dst.d_size = eh->e_phnum * eh->e_phentsize; 5600Sstevel@tonic-gate hi = (Xword)(eh->e_phoff + dst.d_size); 5610Sstevel@tonic-gate if (elf_xlatetof(&dst, &src, encode) == 0) { 5620Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 5630Sstevel@tonic-gate return (0); 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate elf->ed_phflags &= ~ELF_F_DIRTY; 5660Sstevel@tonic-gate src.d_version = EV_CURRENT; 5670Sstevel@tonic-gate } 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate /* 5700Sstevel@tonic-gate * Loop through sections 5710Sstevel@tonic-gate */ 5720Sstevel@tonic-gate 5730Sstevel@tonic-gate ELFACCESSDATA(byte, _elf_byte); 5740Sstevel@tonic-gate for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 5750Sstevel@tonic-gate register Dnode *d, *prevd; 5760Sstevel@tonic-gate Xword off = 0; 5770Sstevel@tonic-gate Shdr *sh = s->s_shdr; 5780Sstevel@tonic-gate char *start = image + sh->sh_offset; 5790Sstevel@tonic-gate char *here; 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate /* 5820Sstevel@tonic-gate * Just "clean" DIRTY flag for "empty" sections. Even if 5830Sstevel@tonic-gate * NOBITS needs padding, the next thing in the 5840Sstevel@tonic-gate * file will provide it. (And if this NOBITS is 5850Sstevel@tonic-gate * the last thing in the file, no padding needed.) 5860Sstevel@tonic-gate */ 5870Sstevel@tonic-gate if ((sh->sh_type == SHT_NOBITS) || 5880Sstevel@tonic-gate (sh->sh_type == SHT_NULL)) { 5890Sstevel@tonic-gate d = s->s_hdnode, prevd = 0; 5900Sstevel@tonic-gate for (; d != 0; prevd = d, d = d->db_next) 5910Sstevel@tonic-gate d->db_uflags &= ~ELF_F_DIRTY; 5920Sstevel@tonic-gate continue; 5930Sstevel@tonic-gate } 5940Sstevel@tonic-gate /* 5950Sstevel@tonic-gate * Clear out the memory between the end of the last 5960Sstevel@tonic-gate * section and the begining of this section. 5970Sstevel@tonic-gate */ 5980Sstevel@tonic-gate if (fill && (sh->sh_offset > hi)) { 5990Sstevel@tonic-gate sz = sh->sh_offset - hi; 6000Sstevel@tonic-gate (void) memset(start - sz, byte, sz); 6010Sstevel@tonic-gate } 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate for (d = s->s_hdnode, prevd = 0; 6050Sstevel@tonic-gate d != 0; prevd = d, d = d->db_next) { 6060Sstevel@tonic-gate d->db_uflags &= ~ELF_F_DIRTY; 6070Sstevel@tonic-gate here = start + d->db_data.d_off; 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate /* 6100Sstevel@tonic-gate * Clear out the memory between the end of the 6110Sstevel@tonic-gate * last update and the start of this data buffer. 6120Sstevel@tonic-gate */ 6130Sstevel@tonic-gate if (fill && (d->db_data.d_off > off)) { 6140Sstevel@tonic-gate sz = (Xword)(d->db_data.d_off - off); 6150Sstevel@tonic-gate (void) memset(here - sz, byte, sz); 6160Sstevel@tonic-gate } 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate if ((d->db_myflags & DBF_READY) == 0) { 6190Sstevel@tonic-gate SCNLOCK(s); 6200Sstevel@tonic-gate if (_elf_locked_getdata(s, &prevd->db_data) != 6210Sstevel@tonic-gate &d->db_data) { 6220Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 6230Sstevel@tonic-gate SCNUNLOCK(s); 6240Sstevel@tonic-gate return (0); 6250Sstevel@tonic-gate } 6260Sstevel@tonic-gate SCNUNLOCK(s); 6270Sstevel@tonic-gate } 6280Sstevel@tonic-gate dst.d_buf = (Elf_Void *)here; 6290Sstevel@tonic-gate dst.d_size = d->db_osz; 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate /* 6320Sstevel@tonic-gate * Copy the translated bits out to the destination 6330Sstevel@tonic-gate * image. 6340Sstevel@tonic-gate */ 6350Sstevel@tonic-gate if (elf_xlatetof(&dst, &d->db_data, encode) == 0) { 6360Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 6370Sstevel@tonic-gate return (0); 6380Sstevel@tonic-gate } 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate off = (Xword)(d->db_data.d_off + dst.d_size); 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate hi = sh->sh_offset + sh->sh_size; 6430Sstevel@tonic-gate } 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate /* 6460Sstevel@tonic-gate * Shdr table last 6470Sstevel@tonic-gate */ 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate if (fill && (eh->e_shoff > hi)) { 6500Sstevel@tonic-gate sz = eh->e_shoff - hi; 6510Sstevel@tonic-gate (void) memset(image + hi, byte, sz); 6520Sstevel@tonic-gate } 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate src.d_type = ELF_T_SHDR; 6550Sstevel@tonic-gate src.d_size = sizeof (Shdr); 6560Sstevel@tonic-gate dst.d_buf = (Elf_Void *)(image + eh->e_shoff); 6570Sstevel@tonic-gate dst.d_size = eh->e_shentsize; 6580Sstevel@tonic-gate for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 6590Sstevel@tonic-gate assert((uintptr_t)dst.d_buf < ((uintptr_t)image + outsz)); 6600Sstevel@tonic-gate s->s_shflags &= ~ELF_F_DIRTY; 6610Sstevel@tonic-gate s->s_uflags &= ~ELF_F_DIRTY; 6620Sstevel@tonic-gate src.d_buf = s->s_shdr; 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate if (elf_xlatetof(&dst, &src, encode) == 0) { 6650Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 6660Sstevel@tonic-gate return (0); 6670Sstevel@tonic-gate } 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate dst.d_buf = (char *)dst.d_buf + eh->e_shentsize; 6700Sstevel@tonic-gate } 6710Sstevel@tonic-gate /* 6720Sstevel@tonic-gate * ELF_C_WRIMAGE signifyes that we build the memory image, but 6730Sstevel@tonic-gate * that we do not actually write it to disk. This is used 6740Sstevel@tonic-gate * by ld(1) to build up a full image of an elf file and then 6750Sstevel@tonic-gate * to process the file before it's actually written out to 6760Sstevel@tonic-gate * disk. This saves ld(1) the overhead of having to write 6770Sstevel@tonic-gate * the image out to disk twice. 6780Sstevel@tonic-gate */ 6790Sstevel@tonic-gate if (update_cmd == ELF_C_WRIMAGE) { 6800Sstevel@tonic-gate elf->ed_uflags &= ~ELF_F_DIRTY; 6810Sstevel@tonic-gate elf->ed_wrimage = image; 6820Sstevel@tonic-gate elf->ed_wrimagesz = outsz; 6830Sstevel@tonic-gate return (outsz); 6840Sstevel@tonic-gate } 6850Sstevel@tonic-gate 6860Sstevel@tonic-gate if (_elf_outsync(elf->ed_fd, image, outsz, 6870Sstevel@tonic-gate ((elf->ed_myflags & EDF_IMALLOC) ? 0 : 1)) != 0) { 6880Sstevel@tonic-gate elf->ed_uflags &= ~ELF_F_DIRTY; 6890Sstevel@tonic-gate elf->ed_myflags &= ~EDF_IMALLOC; 6900Sstevel@tonic-gate return (outsz); 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 6940Sstevel@tonic-gate return (0); 6950Sstevel@tonic-gate } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate 7000Sstevel@tonic-gate /* 7010Sstevel@tonic-gate * The following is a private interface between the linkers (ld & ld.so.1) 7020Sstevel@tonic-gate * and libelf: 7030Sstevel@tonic-gate * 7040Sstevel@tonic-gate * elf_update(elf, ELF_C_WRIMAGE) 7050Sstevel@tonic-gate * This will cause full image representing the elf file 7060Sstevel@tonic-gate * described by the elf pointer to be built in memory. If the 7070Sstevel@tonic-gate * elf pointer has a valid file descriptor associated with it 7080Sstevel@tonic-gate * we will attempt to build the memory image from mmap()'ed 7090Sstevel@tonic-gate * storage. If the elf descriptor does not have a valid 7100Sstevel@tonic-gate * file descriptor (opened with elf_begin(0, ELF_C_IMAGE, 0)) 7110Sstevel@tonic-gate * then the image will be allocated from dynamic memory (malloc()). 7120Sstevel@tonic-gate * 7130Sstevel@tonic-gate * elf_update() will return the size of the memory image built 7140Sstevel@tonic-gate * when sucessful. 7150Sstevel@tonic-gate * 7160Sstevel@tonic-gate * When a subsequent call to elf_update() with ELF_C_WRITE as 7170Sstevel@tonic-gate * the command is performed it will sync the image created 7180Sstevel@tonic-gate * by ELF_C_WRIMAGE to disk (if fd available) and 7190Sstevel@tonic-gate * free the memory allocated. 7200Sstevel@tonic-gate */ 7210Sstevel@tonic-gate 7220Sstevel@tonic-gate off_t 7230Sstevel@tonic-gate _elfxx_update(Elf * elf, Elf_Cmd cmd) 7240Sstevel@tonic-gate { 7250Sstevel@tonic-gate size_t sz; 7260Sstevel@tonic-gate unsigned u; 7270Sstevel@tonic-gate Ehdr *eh = elf->ed_ehdr; 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate if (elf == 0) 7300Sstevel@tonic-gate return (-1); 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate ELFWLOCK(elf) 7330Sstevel@tonic-gate switch (cmd) { 7340Sstevel@tonic-gate default: 7350Sstevel@tonic-gate _elf_seterr(EREQ_UPDATE, 0); 7360Sstevel@tonic-gate ELFUNLOCK(elf) 7370Sstevel@tonic-gate return (-1); 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate case ELF_C_WRIMAGE: 7400Sstevel@tonic-gate if ((elf->ed_myflags & EDF_WRITE) == 0) { 7410Sstevel@tonic-gate _elf_seterr(EREQ_UPDWRT, 0); 7420Sstevel@tonic-gate ELFUNLOCK(elf) 7430Sstevel@tonic-gate return (-1); 7440Sstevel@tonic-gate } 7450Sstevel@tonic-gate break; 7460Sstevel@tonic-gate case ELF_C_WRITE: 7470Sstevel@tonic-gate if ((elf->ed_myflags & EDF_WRITE) == 0) { 7480Sstevel@tonic-gate _elf_seterr(EREQ_UPDWRT, 0); 7490Sstevel@tonic-gate ELFUNLOCK(elf) 7500Sstevel@tonic-gate return (-1); 7510Sstevel@tonic-gate } 7520Sstevel@tonic-gate if (elf->ed_wrimage) { 7530Sstevel@tonic-gate if (elf->ed_myflags & EDF_WRALLOC) { 7540Sstevel@tonic-gate free(elf->ed_wrimage); 7550Sstevel@tonic-gate /* 7560Sstevel@tonic-gate * The size is still returned even 7570Sstevel@tonic-gate * though nothing is actually written 7580Sstevel@tonic-gate * out. This is just to be consistant 7590Sstevel@tonic-gate * with the rest of the interface. 7600Sstevel@tonic-gate */ 7610Sstevel@tonic-gate sz = elf->ed_wrimagesz; 7620Sstevel@tonic-gate elf->ed_wrimage = 0; 7630Sstevel@tonic-gate elf->ed_wrimagesz = 0; 7640Sstevel@tonic-gate ELFUNLOCK(elf); 7650Sstevel@tonic-gate return ((off_t)sz); 7660Sstevel@tonic-gate } 7670Sstevel@tonic-gate sz = _elf_outsync(elf->ed_fd, elf->ed_wrimage, 7686206Sab196087 elf->ed_wrimagesz, 7696206Sab196087 (elf->ed_myflags & EDF_IMALLOC ? 0 : 1)); 7700Sstevel@tonic-gate elf->ed_myflags &= ~EDF_IMALLOC; 7710Sstevel@tonic-gate elf->ed_wrimage = 0; 7720Sstevel@tonic-gate elf->ed_wrimagesz = 0; 7730Sstevel@tonic-gate ELFUNLOCK(elf); 7740Sstevel@tonic-gate return ((off_t)sz); 7750Sstevel@tonic-gate } 7760Sstevel@tonic-gate /* FALLTHROUGH */ 7770Sstevel@tonic-gate case ELF_C_NULL: 7780Sstevel@tonic-gate break; 7790Sstevel@tonic-gate } 7800Sstevel@tonic-gate 7810Sstevel@tonic-gate if (eh == 0) { 7820Sstevel@tonic-gate _elf_seterr(ESEQ_EHDR, 0); 7830Sstevel@tonic-gate ELFUNLOCK(elf) 7840Sstevel@tonic-gate return (-1); 7850Sstevel@tonic-gate } 7860Sstevel@tonic-gate 7870Sstevel@tonic-gate if ((u = eh->e_version) > EV_CURRENT) { 7880Sstevel@tonic-gate _elf_seterr(EREQ_VER, 0); 7890Sstevel@tonic-gate ELFUNLOCK(elf) 7900Sstevel@tonic-gate return (-1); 7910Sstevel@tonic-gate } 7920Sstevel@tonic-gate 7930Sstevel@tonic-gate if (u == EV_NONE) 7940Sstevel@tonic-gate eh->e_version = EV_CURRENT; 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate if ((u = eh->e_ident[EI_DATA]) == ELFDATANONE) { 7970Sstevel@tonic-gate unsigned encode; 7980Sstevel@tonic-gate 7990Sstevel@tonic-gate ELFACCESSDATA(encode, _elf_encode) 8000Sstevel@tonic-gate if (encode == ELFDATANONE) { 8010Sstevel@tonic-gate _elf_seterr(EREQ_ENCODE, 0); 8020Sstevel@tonic-gate ELFUNLOCK(elf) 8030Sstevel@tonic-gate return (-1); 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate /* LINTED */ 8060Sstevel@tonic-gate eh->e_ident[EI_DATA] = (Byte)encode; 8070Sstevel@tonic-gate } 8080Sstevel@tonic-gate 8090Sstevel@tonic-gate u = 1; 8100Sstevel@tonic-gate if (elf->ed_uflags & ELF_F_LAYOUT) { 8110Sstevel@tonic-gate sz = _elf_upd_usr(elf); 8120Sstevel@tonic-gate u = 0; 8130Sstevel@tonic-gate } else 8140Sstevel@tonic-gate sz = _elf_upd_lib(elf); 8150Sstevel@tonic-gate 8160Sstevel@tonic-gate if ((sz != 0) && ((cmd == ELF_C_WRITE) || (cmd == ELF_C_WRIMAGE))) 8170Sstevel@tonic-gate sz = wrt(elf, (Xword)sz, u, cmd); 8180Sstevel@tonic-gate 8190Sstevel@tonic-gate if (sz == 0) { 8200Sstevel@tonic-gate ELFUNLOCK(elf) 8210Sstevel@tonic-gate return (-1); 8220Sstevel@tonic-gate } 8230Sstevel@tonic-gate 8240Sstevel@tonic-gate ELFUNLOCK(elf) 8250Sstevel@tonic-gate return ((off_t)sz); 8260Sstevel@tonic-gate } 8270Sstevel@tonic-gate 8280Sstevel@tonic-gate 8296206Sab196087 /* 8306206Sab196087 * When wrt() processes an ELF_C_WRIMAGE request, the resulting image 8316206Sab196087 * gets the byte order (encoding) of the platform running the linker 8326206Sab196087 * rather than that of the target host. This allows the linker to modify 8336206Sab196087 * the image, prior to flushing it to the output file. This routine 8346206Sab196087 * is used to re-translate such an image into the byte order of the 8356206Sab196087 * target host. 8366206Sab196087 */ 8376206Sab196087 int 8386206Sab196087 _elfxx_swap_wrimage(Elf * elf) 8396206Sab196087 { 8406206Sab196087 NOTE(ASSUMING_PROTECTED(*elf)) 8416206Sab196087 Elf_Data dst, src; 8426206Sab196087 Elf_Scn *s; 8436206Sab196087 Ehdr *eh = elf->ed_ehdr; 8446206Sab196087 Half e_phnum = eh->e_phnum; 8456206Sab196087 unsigned ver = eh->e_version; 8466206Sab196087 unsigned encode = eh->e_ident[EI_DATA]; 8476206Sab196087 8486206Sab196087 /* 8496206Sab196087 * Ehdr first 8506206Sab196087 */ 8516206Sab196087 8526206Sab196087 src.d_buf = dst.d_buf = (Elf_Void *)eh; 8536206Sab196087 src.d_type = dst.d_type = ELF_T_EHDR; 8546206Sab196087 src.d_size = dst.d_size = sizeof (Ehdr); 8556206Sab196087 src.d_version = dst.d_version = ver; 8566206Sab196087 if (elf_xlatetof(&dst, &src, encode) == 0) 8576206Sab196087 return (1); 8586206Sab196087 8596206Sab196087 /* 8606206Sab196087 * Phdr table if one exists 8616206Sab196087 */ 8626206Sab196087 8636206Sab196087 if (e_phnum != 0) { 8646206Sab196087 unsigned work; 8656206Sab196087 /* 8666206Sab196087 * Unlike other library data, phdr table is 8676206Sab196087 * in the user version. 8686206Sab196087 */ 8696206Sab196087 8706206Sab196087 src.d_buf = dst.d_buf = (Elf_Void *)elf->ed_phdr; 8716206Sab196087 src.d_type = dst.d_type = ELF_T_PHDR; 8726206Sab196087 src.d_size = dst.d_size = elf->ed_phdrsz; 8736206Sab196087 ELFACCESSDATA(work, _elf_work) 8746206Sab196087 src.d_version = dst.d_version = work; 8756206Sab196087 if (elf_xlatetof(&dst, &src, encode) == 0) { 8766206Sab196087 return (1); 8776206Sab196087 } 8786206Sab196087 } 8796206Sab196087 8806206Sab196087 /* 8816206Sab196087 * Loop through sections 8826206Sab196087 */ 8836206Sab196087 8846206Sab196087 for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 8856206Sab196087 register Dnode *d, *prevd; 8866206Sab196087 Shdr *sh = s->s_shdr; 8876206Sab196087 8886206Sab196087 if ((sh->sh_type == SHT_NOBITS) || (sh->sh_type == SHT_NULL)) 8896206Sab196087 continue; 8906206Sab196087 8916206Sab196087 for (d = s->s_hdnode, prevd = 0; 8926206Sab196087 d != 0; prevd = d, d = d->db_next) { 8936206Sab196087 8946206Sab196087 if ((d->db_myflags & DBF_READY) == 0) { 8956206Sab196087 SCNLOCK(s); 8966206Sab196087 if (_elf_locked_getdata(s, &prevd->db_data) != 8976206Sab196087 &d->db_data) { 8986206Sab196087 SCNUNLOCK(s); 8996206Sab196087 return (1); 9006206Sab196087 } 9016206Sab196087 SCNUNLOCK(s); 9026206Sab196087 } 9036206Sab196087 9046206Sab196087 dst = d->db_data; 9056206Sab196087 if (elf_xlatetof(&dst, &d->db_data, encode) == 0) 9066206Sab196087 return (1); 9076206Sab196087 } 9086206Sab196087 } 9096206Sab196087 9106206Sab196087 /* 9116206Sab196087 * Shdr table 9126206Sab196087 */ 9136206Sab196087 9146206Sab196087 src.d_type = dst.d_type = ELF_T_SHDR; 9156206Sab196087 src.d_version = dst.d_version = ver; 9166206Sab196087 for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 9176206Sab196087 src.d_buf = dst.d_buf = s->s_shdr; 9186206Sab196087 src.d_size = dst.d_size = sizeof (Shdr); 9196206Sab196087 if (elf_xlatetof(&dst, &src, encode) == 0) 9206206Sab196087 return (1); 9216206Sab196087 } 9226206Sab196087 9236206Sab196087 return (0); 9246206Sab196087 } 9256206Sab196087 9266206Sab196087 9276206Sab196087 9280Sstevel@tonic-gate #ifndef _ELF64 9290Sstevel@tonic-gate /* class-independent, only needs to be compiled once */ 9300Sstevel@tonic-gate 9310Sstevel@tonic-gate off_t 9320Sstevel@tonic-gate elf_update(Elf *elf, Elf_Cmd cmd) 9330Sstevel@tonic-gate { 9340Sstevel@tonic-gate if (elf == 0) 9350Sstevel@tonic-gate return (-1); 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate if (elf->ed_class == ELFCLASS32) 9380Sstevel@tonic-gate return (_elf32_update(elf, cmd)); 9390Sstevel@tonic-gate else if (elf->ed_class == ELFCLASS64) { 9400Sstevel@tonic-gate return (_elf64_update(elf, cmd)); 9410Sstevel@tonic-gate } 9420Sstevel@tonic-gate 9430Sstevel@tonic-gate _elf_seterr(EREQ_CLASS, 0); 9440Sstevel@tonic-gate return (-1); 9450Sstevel@tonic-gate } 9460Sstevel@tonic-gate 9476206Sab196087 int 9486206Sab196087 _elf_swap_wrimage(Elf *elf) 9496206Sab196087 { 9506206Sab196087 if (elf == 0) 9516206Sab196087 return (0); 9526206Sab196087 9536206Sab196087 if (elf->ed_class == ELFCLASS32) 9546206Sab196087 return (_elf32_swap_wrimage(elf)); 9556206Sab196087 9566206Sab196087 if (elf->ed_class == ELFCLASS64) 9576206Sab196087 return (_elf64_swap_wrimage(elf)); 9586206Sab196087 9596206Sab196087 _elf_seterr(EREQ_CLASS, 0); 9606206Sab196087 return (0); 9616206Sab196087 } 9626206Sab196087 9630Sstevel@tonic-gate /* 9640Sstevel@tonic-gate * 4106312, 4106398, This is an ad-hoc means for the 32-bit 9650Sstevel@tonic-gate * Elf64 version of libld.so.3 to get around the limitation 9660Sstevel@tonic-gate * of a 32-bit d_off field. This is only intended to be 9670Sstevel@tonic-gate * used by libld to relocate symbols in large NOBITS sections. 9680Sstevel@tonic-gate */ 9690Sstevel@tonic-gate Elf64_Off 9700Sstevel@tonic-gate _elf_getxoff(Elf_Data * d) 9710Sstevel@tonic-gate { 9720Sstevel@tonic-gate return (((Dnode *)d)->db_xoff); 9730Sstevel@tonic-gate } 9740Sstevel@tonic-gate #endif /* !_ELF64 */ 975