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 /* 236206Sab196087 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 27*6812Sraf /* 28*6812Sraf * Copyright (c) 1988 AT&T 29*6812Sraf * All Rights Reserved 30*6812Sraf */ 31*6812Sraf 320Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include <memory.h> 350Sstevel@tonic-gate #include <malloc.h> 360Sstevel@tonic-gate #include <limits.h> 370Sstevel@tonic-gate 380Sstevel@tonic-gate #include <sgs.h> 390Sstevel@tonic-gate #include "decl.h" 400Sstevel@tonic-gate #include "msg.h" 410Sstevel@tonic-gate 420Sstevel@tonic-gate /* 430Sstevel@tonic-gate * This module is compiled twice, the second time having 440Sstevel@tonic-gate * -D_ELF64 defined. The following set of macros, along 450Sstevel@tonic-gate * with machelf.h, represent the differences between the 460Sstevel@tonic-gate * two compilations. Be careful *not* to add any class- 470Sstevel@tonic-gate * dependent code (anything that has elf32 or elf64 in the 480Sstevel@tonic-gate * name) to this code without hiding it behind a switch- 490Sstevel@tonic-gate * able macro like these. 500Sstevel@tonic-gate */ 510Sstevel@tonic-gate #if defined(_ELF64) 520Sstevel@tonic-gate 530Sstevel@tonic-gate #define FSZ_LONG ELF64_FSZ_XWORD 540Sstevel@tonic-gate #define ELFCLASS ELFCLASS64 550Sstevel@tonic-gate #define _elf_snode_init _elf64_snode_init 560Sstevel@tonic-gate #define _elfxx_cookscn _elf64_cookscn 570Sstevel@tonic-gate #define _elf_upd_lib _elf64_upd_lib 580Sstevel@tonic-gate #define elf_fsize elf64_fsize 590Sstevel@tonic-gate #define _elf_entsz _elf64_entsz 600Sstevel@tonic-gate #define _elf_msize _elf64_msize 610Sstevel@tonic-gate #define _elf_upd_usr _elf64_upd_usr 620Sstevel@tonic-gate #define wrt wrt64 630Sstevel@tonic-gate #define elf_xlatetof elf64_xlatetof 640Sstevel@tonic-gate #define _elfxx_update _elf64_update 656206Sab196087 #define _elfxx_swap_wrimage _elf64_swap_wrimage 660Sstevel@tonic-gate 670Sstevel@tonic-gate #else /* ELF32 */ 680Sstevel@tonic-gate 690Sstevel@tonic-gate #define FSZ_LONG ELF32_FSZ_WORD 700Sstevel@tonic-gate #define ELFCLASS ELFCLASS32 710Sstevel@tonic-gate #define _elf_snode_init _elf32_snode_init 720Sstevel@tonic-gate #define _elfxx_cookscn _elf32_cookscn 730Sstevel@tonic-gate #define _elf_upd_lib _elf32_upd_lib 740Sstevel@tonic-gate #define elf_fsize elf32_fsize 750Sstevel@tonic-gate #define _elf_entsz _elf32_entsz 760Sstevel@tonic-gate #define _elf_msize _elf32_msize 770Sstevel@tonic-gate #define _elf_upd_usr _elf32_upd_usr 780Sstevel@tonic-gate #define wrt wrt32 790Sstevel@tonic-gate #define elf_xlatetof elf32_xlatetof 800Sstevel@tonic-gate #define _elfxx_update _elf32_update 816206Sab196087 #define _elfxx_swap_wrimage _elf32_swap_wrimage 820Sstevel@tonic-gate 830Sstevel@tonic-gate #endif /* ELF64 */ 840Sstevel@tonic-gate 850Sstevel@tonic-gate 866223Sab196087 #if !(defined(_LP64) && defined(_ELF64)) 876223Sab196087 #define TEST_SIZE 886223Sab196087 896223Sab196087 /* 906223Sab196087 * Handle the decision of whether the current linker can handle the 916223Sab196087 * desired object size, and if not, which error to issue. 926223Sab196087 * 936223Sab196087 * Input is the desired size. On failure, an error has been issued 946223Sab196087 * and 0 is returned. On success, 1 is returned. 956223Sab196087 */ 966223Sab196087 static int 976223Sab196087 test_size(Lword hi) 986223Sab196087 { 996223Sab196087 #ifndef _LP64 /* 32-bit linker */ 1006223Sab196087 /* 1016223Sab196087 * A 32-bit libelf is limited to a 2GB output file. This limit 1026223Sab196087 * is due to the fact that off_t is a signed value, and that 1036223Sab196087 * libelf cannot support large file support: 1046223Sab196087 * - ABI reasons 1056223Sab196087 * - Memory use generally is 2x output file size anyway, 1066223Sab196087 * so lifting the file size limit will just send 1076223Sab196087 * you crashing into the 32-bit VM limit. 1086223Sab196087 * If the output is an ELFCLASS64 object, or an ELFCLASS32 object 1096223Sab196087 * under 4GB, switching to the 64-bit version of libelf will help. 1106223Sab196087 * However, an ELFCLASS32 object must not exceed 4GB. 1116223Sab196087 */ 1126223Sab196087 if (hi > INT_MAX) { /* Bigger than 2GB */ 1136223Sab196087 #ifndef _ELF64 1146223Sab196087 /* ELFCLASS32 object is fundamentally too big? */ 1156223Sab196087 if (hi > UINT_MAX) { 1166223Sab196087 _elf_seterr(EFMT_FBIG_CLASS32, 0); 1176223Sab196087 return (0); 1186223Sab196087 } 1196223Sab196087 #endif /* _ELF64 */ 1206223Sab196087 1216223Sab196087 /* Should switch to the 64-bit libelf? */ 1226223Sab196087 _elf_seterr(EFMT_FBIG_LARGEFILE, 0); 1236223Sab196087 return (0); 1246223Sab196087 } 1256223Sab196087 #endif /* !_LP64 */ 1266223Sab196087 1276223Sab196087 1286223Sab196087 #if defined(_LP64) && !defined(_ELF64) /* 64-bit linker, ELFCLASS32 */ 1296223Sab196087 /* 1306223Sab196087 * A 64-bit linker can produce any size output 1316223Sab196087 * file, but if the resulting file is ELFCLASS32, 1326223Sab196087 * it must not exceed 4GB. 1336223Sab196087 */ 1346223Sab196087 if (hi > UINT_MAX) { 1356223Sab196087 _elf_seterr(EFMT_FBIG_CLASS32, 0); 1366223Sab196087 return (0); 1376223Sab196087 } 1386223Sab196087 #endif 1396223Sab196087 1406223Sab196087 return (1); 1416223Sab196087 } 1426223Sab196087 #endif /* TEST_SIZE */ 1436223Sab196087 1440Sstevel@tonic-gate /* 1450Sstevel@tonic-gate * Output file update 1460Sstevel@tonic-gate * These functions walk an Elf structure, update its information, 1470Sstevel@tonic-gate * and optionally write the output file. Because the application 1480Sstevel@tonic-gate * may control of the output file layout, two upd_... routines 1490Sstevel@tonic-gate * exist. They're similar but too different to merge cleanly. 1500Sstevel@tonic-gate * 1510Sstevel@tonic-gate * The library defines a "dirty" bit to force parts of the file 1520Sstevel@tonic-gate * to be written on update. These routines ignore the dirty bit 1530Sstevel@tonic-gate * and do everything. A minimal update routine might be useful 1540Sstevel@tonic-gate * someday. 1550Sstevel@tonic-gate */ 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate static size_t 1580Sstevel@tonic-gate _elf_upd_lib(Elf * elf) 1590Sstevel@tonic-gate { 1600Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 1610Sstevel@tonic-gate Lword hi; 1620Sstevel@tonic-gate Lword hibit; 1630Sstevel@tonic-gate Elf_Scn * s; 1646223Sab196087 register Lword sz; 1650Sstevel@tonic-gate Ehdr * eh = elf->ed_ehdr; 1660Sstevel@tonic-gate unsigned ver = eh->e_version; 1670Sstevel@tonic-gate register char *p = (char *)eh->e_ident; 1680Sstevel@tonic-gate size_t scncnt; 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate /* 1710Sstevel@tonic-gate * Ehdr and Phdr table go first 1720Sstevel@tonic-gate */ 1730Sstevel@tonic-gate p[EI_MAG0] = ELFMAG0; 1740Sstevel@tonic-gate p[EI_MAG1] = ELFMAG1; 1750Sstevel@tonic-gate p[EI_MAG2] = ELFMAG2; 1760Sstevel@tonic-gate p[EI_MAG3] = ELFMAG3; 1770Sstevel@tonic-gate p[EI_CLASS] = ELFCLASS; 1780Sstevel@tonic-gate /* LINTED */ 1790Sstevel@tonic-gate p[EI_VERSION] = (Byte)ver; 1800Sstevel@tonic-gate hi = elf_fsize(ELF_T_EHDR, 1, ver); 1810Sstevel@tonic-gate /* LINTED */ 1820Sstevel@tonic-gate eh->e_ehsize = (Half)hi; 1830Sstevel@tonic-gate if (eh->e_phnum != 0) { 1840Sstevel@tonic-gate /* LINTED */ 1850Sstevel@tonic-gate eh->e_phentsize = (Half)elf_fsize(ELF_T_PHDR, 1, ver); 1860Sstevel@tonic-gate /* LINTED */ 1870Sstevel@tonic-gate eh->e_phoff = (Off)hi; 1880Sstevel@tonic-gate hi += eh->e_phentsize * eh->e_phnum; 1890Sstevel@tonic-gate } else { 1900Sstevel@tonic-gate eh->e_phoff = 0; 1910Sstevel@tonic-gate eh->e_phentsize = 0; 1920Sstevel@tonic-gate } 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate /* 1951682Srie * Obtain the first section header. Typically, this section has NULL 1961682Srie * contents, however in the case of Extended ELF Sections this section 1971682Srie * is used to hold an alternative e_shnum, e_shstrndx and e_phnum. 1981682Srie * On initial allocation (see _elf_snode) the elements of this section 1991682Srie * would have been zeroed. The e_shnum is initialized later, after the 2001682Srie * section header count has been determined. The e_shstrndx and 2011682Srie * e_phnum may have already been initialized by the caller (for example, 2021682Srie * gelf_update_shdr() in mcs(1)). 2030Sstevel@tonic-gate */ 2040Sstevel@tonic-gate if ((s = elf->ed_hdscn) == 0) { 2050Sstevel@tonic-gate eh->e_shnum = 0; 2060Sstevel@tonic-gate scncnt = 0; 2070Sstevel@tonic-gate } else { 2081682Srie s = s->s_next; 2090Sstevel@tonic-gate scncnt = 1; 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2121682Srie /* 2131682Srie * Loop through sections. Compute section size before changing hi. 2141682Srie * Allow null buffers for NOBITS. 2151682Srie */ 2160Sstevel@tonic-gate hibit = 0; 2170Sstevel@tonic-gate for (; s != 0; s = s->s_next) { 2180Sstevel@tonic-gate register Dnode *d; 2190Sstevel@tonic-gate register Lword fsz, j; 2200Sstevel@tonic-gate Shdr *sh = s->s_shdr; 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate scncnt++; 2230Sstevel@tonic-gate if (sh->sh_type == SHT_NULL) { 2240Sstevel@tonic-gate *sh = _elf_snode_init.sb_shdr; 2250Sstevel@tonic-gate continue; 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate if ((s->s_myflags & SF_READY) == 0) 2290Sstevel@tonic-gate (void) _elfxx_cookscn(s); 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate sh->sh_addralign = 1; 2326223Sab196087 if ((sz = (Lword)_elf_entsz(elf, sh->sh_type, ver)) != 0) 2330Sstevel@tonic-gate /* LINTED */ 2340Sstevel@tonic-gate sh->sh_entsize = (Half)sz; 2350Sstevel@tonic-gate sz = 0; 2360Sstevel@tonic-gate for (d = s->s_hdnode; d != 0; d = d->db_next) { 2370Sstevel@tonic-gate if ((fsz = elf_fsize(d->db_data.d_type, 2380Sstevel@tonic-gate 1, ver)) == 0) 2390Sstevel@tonic-gate return (0); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate j = _elf_msize(d->db_data.d_type, ver); 2420Sstevel@tonic-gate fsz *= (d->db_data.d_size / j); 2430Sstevel@tonic-gate d->db_osz = (size_t)fsz; 2440Sstevel@tonic-gate if ((j = d->db_data.d_align) > 1) { 2450Sstevel@tonic-gate if (j > sh->sh_addralign) 2460Sstevel@tonic-gate sh->sh_addralign = (Xword)j; 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate if (sz % j != 0) 2490Sstevel@tonic-gate sz += j - sz % j; 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate d->db_data.d_off = (off_t)sz; 2520Sstevel@tonic-gate d->db_xoff = sz; 2536223Sab196087 sz += fsz; 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate 2566223Sab196087 sh->sh_size = (Xword) sz; 2570Sstevel@tonic-gate /* 2580Sstevel@tonic-gate * We want to take into account the offsets for NOBITS 2590Sstevel@tonic-gate * sections and let the "sh_offsets" point to where 2600Sstevel@tonic-gate * the section would 'conceptually' fit within 2610Sstevel@tonic-gate * the file (as required by the ABI). 2620Sstevel@tonic-gate * 2630Sstevel@tonic-gate * But - we must also make sure that the NOBITS does 2640Sstevel@tonic-gate * not take up any actual space in the file. We preserve 2650Sstevel@tonic-gate * the actual offset into the file in the 'hibit' variable. 2660Sstevel@tonic-gate * When we come to the first non-NOBITS section after a 2670Sstevel@tonic-gate * encountering a NOBITS section the hi counter is restored 2680Sstevel@tonic-gate * to its proper place in the file. 2690Sstevel@tonic-gate */ 2700Sstevel@tonic-gate if (sh->sh_type == SHT_NOBITS) { 2710Sstevel@tonic-gate if (hibit == 0) 2720Sstevel@tonic-gate hibit = hi; 2730Sstevel@tonic-gate } else { 2740Sstevel@tonic-gate if (hibit) { 2750Sstevel@tonic-gate hi = hibit; 2760Sstevel@tonic-gate hibit = 0; 2770Sstevel@tonic-gate } 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate j = sh->sh_addralign; 2800Sstevel@tonic-gate if ((fsz = hi % j) != 0) 2810Sstevel@tonic-gate hi += j - fsz; 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate /* LINTED */ 2840Sstevel@tonic-gate sh->sh_offset = (Off)hi; 2850Sstevel@tonic-gate hi += sz; 2860Sstevel@tonic-gate } 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate /* 2890Sstevel@tonic-gate * if last section was a 'NOBITS' section then we need to 2900Sstevel@tonic-gate * restore the 'hi' counter to point to the end of the last 2910Sstevel@tonic-gate * non 'NOBITS' section. 2920Sstevel@tonic-gate */ 2930Sstevel@tonic-gate if (hibit) { 2940Sstevel@tonic-gate hi = hibit; 2950Sstevel@tonic-gate hibit = 0; 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* 2990Sstevel@tonic-gate * Shdr table last 3000Sstevel@tonic-gate */ 3010Sstevel@tonic-gate if (scncnt != 0) { 3020Sstevel@tonic-gate if (hi % FSZ_LONG != 0) 3030Sstevel@tonic-gate hi += FSZ_LONG - hi % FSZ_LONG; 3040Sstevel@tonic-gate /* LINTED */ 3050Sstevel@tonic-gate eh->e_shoff = (Off)hi; 3060Sstevel@tonic-gate /* 3070Sstevel@tonic-gate * If we are using 'extended sections' then the 3080Sstevel@tonic-gate * e_shnum is stored in the sh_size field of the 3090Sstevel@tonic-gate * first section header. 3100Sstevel@tonic-gate * 3110Sstevel@tonic-gate * NOTE: we set e_shnum to '0' because it's specified 3120Sstevel@tonic-gate * this way in the gABI, and in the hopes that 3130Sstevel@tonic-gate * this will cause less problems to unaware 3140Sstevel@tonic-gate * tools then if we'd set it to SHN_XINDEX (0xffff). 3150Sstevel@tonic-gate */ 3160Sstevel@tonic-gate if (scncnt < SHN_LORESERVE) 3170Sstevel@tonic-gate eh->e_shnum = scncnt; 3180Sstevel@tonic-gate else { 3190Sstevel@tonic-gate Shdr *sh; 3200Sstevel@tonic-gate sh = (Shdr *)elf->ed_hdscn->s_shdr; 3210Sstevel@tonic-gate sh->sh_size = scncnt; 3220Sstevel@tonic-gate eh->e_shnum = 0; 3230Sstevel@tonic-gate } 3240Sstevel@tonic-gate /* LINTED */ 3250Sstevel@tonic-gate eh->e_shentsize = (Half)elf_fsize(ELF_T_SHDR, 1, ver); 3260Sstevel@tonic-gate hi += eh->e_shentsize * scncnt; 3270Sstevel@tonic-gate } else { 3280Sstevel@tonic-gate eh->e_shoff = 0; 3290Sstevel@tonic-gate eh->e_shentsize = 0; 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate 3326223Sab196087 #ifdef TEST_SIZE 3336223Sab196087 if (test_size(hi) == 0) 3340Sstevel@tonic-gate return (0); 3350Sstevel@tonic-gate #endif 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate return ((size_t)hi); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate static size_t 3430Sstevel@tonic-gate _elf_upd_usr(Elf * elf) 3440Sstevel@tonic-gate { 3450Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 3460Sstevel@tonic-gate Lword hi; 3470Sstevel@tonic-gate Elf_Scn * s; 3486223Sab196087 register Lword sz; 3490Sstevel@tonic-gate Ehdr * eh = elf->ed_ehdr; 3500Sstevel@tonic-gate unsigned ver = eh->e_version; 3510Sstevel@tonic-gate register char *p = (char *)eh->e_ident; 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate /* 3550Sstevel@tonic-gate * Ehdr and Phdr table go first 3560Sstevel@tonic-gate */ 3570Sstevel@tonic-gate p[EI_MAG0] = ELFMAG0; 3580Sstevel@tonic-gate p[EI_MAG1] = ELFMAG1; 3590Sstevel@tonic-gate p[EI_MAG2] = ELFMAG2; 3600Sstevel@tonic-gate p[EI_MAG3] = ELFMAG3; 3610Sstevel@tonic-gate p[EI_CLASS] = ELFCLASS; 3620Sstevel@tonic-gate /* LINTED */ 3630Sstevel@tonic-gate p[EI_VERSION] = (Byte)ver; 3640Sstevel@tonic-gate hi = elf_fsize(ELF_T_EHDR, 1, ver); 3650Sstevel@tonic-gate /* LINTED */ 3660Sstevel@tonic-gate eh->e_ehsize = (Half)hi; 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate /* 3690Sstevel@tonic-gate * If phnum is zero, phoff "should" be zero too, 3700Sstevel@tonic-gate * but the application is responsible for it. 3710Sstevel@tonic-gate * Allow a non-zero value here and update the 3720Sstevel@tonic-gate * hi water mark accordingly. 3730Sstevel@tonic-gate */ 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate if (eh->e_phnum != 0) 3760Sstevel@tonic-gate /* LINTED */ 3770Sstevel@tonic-gate eh->e_phentsize = (Half)elf_fsize(ELF_T_PHDR, 1, ver); 3780Sstevel@tonic-gate else 3790Sstevel@tonic-gate eh->e_phentsize = 0; 3800Sstevel@tonic-gate if ((sz = eh->e_phoff + eh->e_phentsize * eh->e_phnum) > hi) 3810Sstevel@tonic-gate hi = sz; 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate /* 3840Sstevel@tonic-gate * Loop through sections, skipping index zero. 3850Sstevel@tonic-gate * Compute section size before changing hi. 3860Sstevel@tonic-gate * Allow null buffers for NOBITS. 3870Sstevel@tonic-gate */ 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate if ((s = elf->ed_hdscn) == 0) 3900Sstevel@tonic-gate eh->e_shnum = 0; 3910Sstevel@tonic-gate else { 3920Sstevel@tonic-gate eh->e_shnum = 1; 3930Sstevel@tonic-gate *(Shdr*)s->s_shdr = _elf_snode_init.sb_shdr; 3940Sstevel@tonic-gate s = s->s_next; 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate for (; s != 0; s = s->s_next) { 3970Sstevel@tonic-gate register Dnode *d; 3986223Sab196087 register Lword fsz, j; 3990Sstevel@tonic-gate Shdr *sh = s->s_shdr; 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate if ((s->s_myflags & SF_READY) == 0) 4020Sstevel@tonic-gate (void) _elfxx_cookscn(s); 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate ++eh->e_shnum; 4050Sstevel@tonic-gate sz = 0; 4060Sstevel@tonic-gate for (d = s->s_hdnode; d != 0; d = d->db_next) { 4076223Sab196087 if ((fsz = elf_fsize(d->db_data.d_type, 1, 4080Sstevel@tonic-gate ver)) == 0) 4090Sstevel@tonic-gate return (0); 4106223Sab196087 j = _elf_msize(d->db_data.d_type, ver); 4116223Sab196087 fsz *= (d->db_data.d_size / j); 4120Sstevel@tonic-gate d->db_osz = (size_t)fsz; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate if ((sh->sh_type != SHT_NOBITS) && 4156223Sab196087 ((j = (d->db_data.d_off + d->db_osz)) > sz)) 4160Sstevel@tonic-gate sz = j; 4170Sstevel@tonic-gate } 4180Sstevel@tonic-gate if (sh->sh_size < sz) { 4190Sstevel@tonic-gate _elf_seterr(EFMT_SCNSZ, 0); 4200Sstevel@tonic-gate return (0); 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate if ((sh->sh_type != SHT_NOBITS) && 4230Sstevel@tonic-gate (hi < sh->sh_offset + sh->sh_size)) 4240Sstevel@tonic-gate hi = sh->sh_offset + sh->sh_size; 4250Sstevel@tonic-gate } 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate /* 4280Sstevel@tonic-gate * Shdr table last. Comment above for phnum/phoff applies here. 4290Sstevel@tonic-gate */ 4300Sstevel@tonic-gate if (eh->e_shnum != 0) 4310Sstevel@tonic-gate /* LINTED */ 4320Sstevel@tonic-gate eh->e_shentsize = (Half)elf_fsize(ELF_T_SHDR, 1, ver); 4330Sstevel@tonic-gate else 4340Sstevel@tonic-gate eh->e_shentsize = 0; 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate if ((sz = eh->e_shoff + eh->e_shentsize * eh->e_shnum) > hi) 4370Sstevel@tonic-gate hi = sz; 4380Sstevel@tonic-gate 4396223Sab196087 #ifdef TEST_SIZE 4406223Sab196087 if (test_size(hi) == 0) 4410Sstevel@tonic-gate return (0); 4420Sstevel@tonic-gate #endif 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate return ((size_t)hi); 4450Sstevel@tonic-gate } 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate static size_t 4490Sstevel@tonic-gate wrt(Elf * elf, Xword outsz, unsigned fill, int update_cmd) 4500Sstevel@tonic-gate { 4510Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 4520Sstevel@tonic-gate Elf_Data dst, src; 4530Sstevel@tonic-gate unsigned flag; 4540Sstevel@tonic-gate Xword hi, sz; 4550Sstevel@tonic-gate char *image; 4560Sstevel@tonic-gate Elf_Scn *s; 4570Sstevel@tonic-gate Ehdr *eh = elf->ed_ehdr; 4580Sstevel@tonic-gate unsigned ver = eh->e_version; 4596206Sab196087 unsigned encode; 4600Sstevel@tonic-gate int byte; 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate /* 4636206Sab196087 * If this is an ELF_C_WRIMAGE write, then we encode into the 4646206Sab196087 * byte order of the system we are running on rather than that of 4656206Sab196087 * of the object. For ld.so.1, this is the same order, but 4666206Sab196087 * for 'ld', it might not be in the case where we are cross 4676206Sab196087 * linking an object for a different target. In this later case, 4686206Sab196087 * the linker-host byte order is necessary so that the linker can 4696206Sab196087 * manipulate the resulting image. It is expected that the linker 4706206Sab196087 * will call elf_swap_wrimage() if necessary to convert the image 4716206Sab196087 * to the target byte order. 4726206Sab196087 */ 4736206Sab196087 encode = (update_cmd == ELF_C_WRIMAGE) ? _elf_sys_encoding() : 4746206Sab196087 eh->e_ident[EI_DATA]; 4756206Sab196087 4766206Sab196087 /* 4770Sstevel@tonic-gate * Two issues can cause trouble for the output file. 4780Sstevel@tonic-gate * First, begin() with ELF_C_RDWR opens a file for both 4790Sstevel@tonic-gate * read and write. On the write update(), the library 4800Sstevel@tonic-gate * has to read everything it needs before truncating 4810Sstevel@tonic-gate * the file. Second, using mmap for both read and write 4820Sstevel@tonic-gate * is too tricky. Consequently, the library disables mmap 4830Sstevel@tonic-gate * on the read side. Using mmap for the output saves swap 4840Sstevel@tonic-gate * space, because that mapping is SHARED, not PRIVATE. 4850Sstevel@tonic-gate * 4860Sstevel@tonic-gate * If the file is write-only, there can be nothing of 4870Sstevel@tonic-gate * interest to bother with. 4880Sstevel@tonic-gate * 4890Sstevel@tonic-gate * The following reads the entire file, which might be 4900Sstevel@tonic-gate * more than necessary. Better safe than sorry. 4910Sstevel@tonic-gate */ 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate if ((elf->ed_myflags & EDF_READ) && 4940Sstevel@tonic-gate (_elf_vm(elf, (size_t)0, elf->ed_fsz) != OK_YES)) 4950Sstevel@tonic-gate return (0); 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate flag = elf->ed_myflags & EDF_WRALLOC; 4980Sstevel@tonic-gate if ((image = _elf_outmap(elf->ed_fd, outsz, &flag)) == 0) 4990Sstevel@tonic-gate return (0); 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate if (flag == 0) 5020Sstevel@tonic-gate elf->ed_myflags |= EDF_IMALLOC; 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate /* 5050Sstevel@tonic-gate * If an error occurs below, a "dirty" bit may be cleared 5060Sstevel@tonic-gate * improperly. To save a second pass through the file, 5070Sstevel@tonic-gate * this code sets the dirty bit on the elf descriptor 5080Sstevel@tonic-gate * when an error happens, assuming that will "cover" any 5090Sstevel@tonic-gate * accidents. 5100Sstevel@tonic-gate */ 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate /* 5130Sstevel@tonic-gate * Hi is needed only when 'fill' is non-zero. 5140Sstevel@tonic-gate * Fill is non-zero only when the library 5150Sstevel@tonic-gate * calculates file/section/data buffer offsets. 5160Sstevel@tonic-gate * The lib guarantees they increase monotonically. 5170Sstevel@tonic-gate * That guarantees proper filling below. 5180Sstevel@tonic-gate */ 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate /* 5220Sstevel@tonic-gate * Ehdr first 5230Sstevel@tonic-gate */ 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate src.d_buf = (Elf_Void *)eh; 5260Sstevel@tonic-gate src.d_type = ELF_T_EHDR; 5270Sstevel@tonic-gate src.d_size = sizeof (Ehdr); 5280Sstevel@tonic-gate src.d_version = EV_CURRENT; 5290Sstevel@tonic-gate dst.d_buf = (Elf_Void *)image; 5300Sstevel@tonic-gate dst.d_size = eh->e_ehsize; 5310Sstevel@tonic-gate dst.d_version = ver; 5320Sstevel@tonic-gate if (elf_xlatetof(&dst, &src, encode) == 0) 5330Sstevel@tonic-gate return (0); 5340Sstevel@tonic-gate elf->ed_ehflags &= ~ELF_F_DIRTY; 5350Sstevel@tonic-gate hi = eh->e_ehsize; 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate /* 5380Sstevel@tonic-gate * Phdr table if one exists 5390Sstevel@tonic-gate */ 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate if (eh->e_phnum != 0) { 5420Sstevel@tonic-gate unsigned work; 5430Sstevel@tonic-gate /* 5440Sstevel@tonic-gate * Unlike other library data, phdr table is 5450Sstevel@tonic-gate * in the user version. Change src buffer 5460Sstevel@tonic-gate * version here, fix it after translation. 5470Sstevel@tonic-gate */ 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate src.d_buf = (Elf_Void *)elf->ed_phdr; 5500Sstevel@tonic-gate src.d_type = ELF_T_PHDR; 5510Sstevel@tonic-gate src.d_size = elf->ed_phdrsz; 5520Sstevel@tonic-gate ELFACCESSDATA(work, _elf_work) 5530Sstevel@tonic-gate src.d_version = work; 5540Sstevel@tonic-gate dst.d_buf = (Elf_Void *)(image + eh->e_phoff); 5550Sstevel@tonic-gate dst.d_size = eh->e_phnum * eh->e_phentsize; 5560Sstevel@tonic-gate hi = (Xword)(eh->e_phoff + dst.d_size); 5570Sstevel@tonic-gate if (elf_xlatetof(&dst, &src, encode) == 0) { 5580Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 5590Sstevel@tonic-gate return (0); 5600Sstevel@tonic-gate } 5610Sstevel@tonic-gate elf->ed_phflags &= ~ELF_F_DIRTY; 5620Sstevel@tonic-gate src.d_version = EV_CURRENT; 5630Sstevel@tonic-gate } 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate /* 5660Sstevel@tonic-gate * Loop through sections 5670Sstevel@tonic-gate */ 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate ELFACCESSDATA(byte, _elf_byte); 5700Sstevel@tonic-gate for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 5710Sstevel@tonic-gate register Dnode *d, *prevd; 5720Sstevel@tonic-gate Xword off = 0; 5730Sstevel@tonic-gate Shdr *sh = s->s_shdr; 5740Sstevel@tonic-gate char *start = image + sh->sh_offset; 5750Sstevel@tonic-gate char *here; 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate /* 5780Sstevel@tonic-gate * Just "clean" DIRTY flag for "empty" sections. Even if 5790Sstevel@tonic-gate * NOBITS needs padding, the next thing in the 5800Sstevel@tonic-gate * file will provide it. (And if this NOBITS is 5810Sstevel@tonic-gate * the last thing in the file, no padding needed.) 5820Sstevel@tonic-gate */ 5830Sstevel@tonic-gate if ((sh->sh_type == SHT_NOBITS) || 5840Sstevel@tonic-gate (sh->sh_type == SHT_NULL)) { 5850Sstevel@tonic-gate d = s->s_hdnode, prevd = 0; 5860Sstevel@tonic-gate for (; d != 0; prevd = d, d = d->db_next) 5870Sstevel@tonic-gate d->db_uflags &= ~ELF_F_DIRTY; 5880Sstevel@tonic-gate continue; 5890Sstevel@tonic-gate } 5900Sstevel@tonic-gate /* 5910Sstevel@tonic-gate * Clear out the memory between the end of the last 5920Sstevel@tonic-gate * section and the begining of this section. 5930Sstevel@tonic-gate */ 5940Sstevel@tonic-gate if (fill && (sh->sh_offset > hi)) { 5950Sstevel@tonic-gate sz = sh->sh_offset - hi; 5960Sstevel@tonic-gate (void) memset(start - sz, byte, sz); 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate for (d = s->s_hdnode, prevd = 0; 6010Sstevel@tonic-gate d != 0; prevd = d, d = d->db_next) { 6020Sstevel@tonic-gate d->db_uflags &= ~ELF_F_DIRTY; 6030Sstevel@tonic-gate here = start + d->db_data.d_off; 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate /* 6060Sstevel@tonic-gate * Clear out the memory between the end of the 6070Sstevel@tonic-gate * last update and the start of this data buffer. 6080Sstevel@tonic-gate */ 6090Sstevel@tonic-gate if (fill && (d->db_data.d_off > off)) { 6100Sstevel@tonic-gate sz = (Xword)(d->db_data.d_off - off); 6110Sstevel@tonic-gate (void) memset(here - sz, byte, sz); 6120Sstevel@tonic-gate } 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate if ((d->db_myflags & DBF_READY) == 0) { 6150Sstevel@tonic-gate SCNLOCK(s); 6160Sstevel@tonic-gate if (_elf_locked_getdata(s, &prevd->db_data) != 6170Sstevel@tonic-gate &d->db_data) { 6180Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 6190Sstevel@tonic-gate SCNUNLOCK(s); 6200Sstevel@tonic-gate return (0); 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate SCNUNLOCK(s); 6230Sstevel@tonic-gate } 6240Sstevel@tonic-gate dst.d_buf = (Elf_Void *)here; 6250Sstevel@tonic-gate dst.d_size = d->db_osz; 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate /* 6280Sstevel@tonic-gate * Copy the translated bits out to the destination 6290Sstevel@tonic-gate * image. 6300Sstevel@tonic-gate */ 6310Sstevel@tonic-gate if (elf_xlatetof(&dst, &d->db_data, encode) == 0) { 6320Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 6330Sstevel@tonic-gate return (0); 6340Sstevel@tonic-gate } 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate off = (Xword)(d->db_data.d_off + dst.d_size); 6370Sstevel@tonic-gate } 6380Sstevel@tonic-gate hi = sh->sh_offset + sh->sh_size; 6390Sstevel@tonic-gate } 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate /* 6420Sstevel@tonic-gate * Shdr table last 6430Sstevel@tonic-gate */ 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate if (fill && (eh->e_shoff > hi)) { 6460Sstevel@tonic-gate sz = eh->e_shoff - hi; 6470Sstevel@tonic-gate (void) memset(image + hi, byte, sz); 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate src.d_type = ELF_T_SHDR; 6510Sstevel@tonic-gate src.d_size = sizeof (Shdr); 6520Sstevel@tonic-gate dst.d_buf = (Elf_Void *)(image + eh->e_shoff); 6530Sstevel@tonic-gate dst.d_size = eh->e_shentsize; 6540Sstevel@tonic-gate for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 6550Sstevel@tonic-gate assert((uintptr_t)dst.d_buf < ((uintptr_t)image + outsz)); 6560Sstevel@tonic-gate s->s_shflags &= ~ELF_F_DIRTY; 6570Sstevel@tonic-gate s->s_uflags &= ~ELF_F_DIRTY; 6580Sstevel@tonic-gate src.d_buf = s->s_shdr; 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate if (elf_xlatetof(&dst, &src, encode) == 0) { 6610Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 6620Sstevel@tonic-gate return (0); 6630Sstevel@tonic-gate } 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate dst.d_buf = (char *)dst.d_buf + eh->e_shentsize; 6660Sstevel@tonic-gate } 6670Sstevel@tonic-gate /* 6680Sstevel@tonic-gate * ELF_C_WRIMAGE signifyes that we build the memory image, but 6690Sstevel@tonic-gate * that we do not actually write it to disk. This is used 6700Sstevel@tonic-gate * by ld(1) to build up a full image of an elf file and then 6710Sstevel@tonic-gate * to process the file before it's actually written out to 6720Sstevel@tonic-gate * disk. This saves ld(1) the overhead of having to write 6730Sstevel@tonic-gate * the image out to disk twice. 6740Sstevel@tonic-gate */ 6750Sstevel@tonic-gate if (update_cmd == ELF_C_WRIMAGE) { 6760Sstevel@tonic-gate elf->ed_uflags &= ~ELF_F_DIRTY; 6770Sstevel@tonic-gate elf->ed_wrimage = image; 6780Sstevel@tonic-gate elf->ed_wrimagesz = outsz; 6790Sstevel@tonic-gate return (outsz); 6800Sstevel@tonic-gate } 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate if (_elf_outsync(elf->ed_fd, image, outsz, 6830Sstevel@tonic-gate ((elf->ed_myflags & EDF_IMALLOC) ? 0 : 1)) != 0) { 6840Sstevel@tonic-gate elf->ed_uflags &= ~ELF_F_DIRTY; 6850Sstevel@tonic-gate elf->ed_myflags &= ~EDF_IMALLOC; 6860Sstevel@tonic-gate return (outsz); 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate elf->ed_uflags |= ELF_F_DIRTY; 6900Sstevel@tonic-gate return (0); 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate /* 6970Sstevel@tonic-gate * The following is a private interface between the linkers (ld & ld.so.1) 6980Sstevel@tonic-gate * and libelf: 6990Sstevel@tonic-gate * 7000Sstevel@tonic-gate * elf_update(elf, ELF_C_WRIMAGE) 7010Sstevel@tonic-gate * This will cause full image representing the elf file 7020Sstevel@tonic-gate * described by the elf pointer to be built in memory. If the 7030Sstevel@tonic-gate * elf pointer has a valid file descriptor associated with it 7040Sstevel@tonic-gate * we will attempt to build the memory image from mmap()'ed 7050Sstevel@tonic-gate * storage. If the elf descriptor does not have a valid 7060Sstevel@tonic-gate * file descriptor (opened with elf_begin(0, ELF_C_IMAGE, 0)) 7070Sstevel@tonic-gate * then the image will be allocated from dynamic memory (malloc()). 7080Sstevel@tonic-gate * 7090Sstevel@tonic-gate * elf_update() will return the size of the memory image built 7100Sstevel@tonic-gate * when sucessful. 7110Sstevel@tonic-gate * 7120Sstevel@tonic-gate * When a subsequent call to elf_update() with ELF_C_WRITE as 7130Sstevel@tonic-gate * the command is performed it will sync the image created 7140Sstevel@tonic-gate * by ELF_C_WRIMAGE to disk (if fd available) and 7150Sstevel@tonic-gate * free the memory allocated. 7160Sstevel@tonic-gate */ 7170Sstevel@tonic-gate 7180Sstevel@tonic-gate off_t 7190Sstevel@tonic-gate _elfxx_update(Elf * elf, Elf_Cmd cmd) 7200Sstevel@tonic-gate { 7210Sstevel@tonic-gate size_t sz; 7220Sstevel@tonic-gate unsigned u; 7230Sstevel@tonic-gate Ehdr *eh = elf->ed_ehdr; 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate if (elf == 0) 7260Sstevel@tonic-gate return (-1); 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate ELFWLOCK(elf) 7290Sstevel@tonic-gate switch (cmd) { 7300Sstevel@tonic-gate default: 7310Sstevel@tonic-gate _elf_seterr(EREQ_UPDATE, 0); 7320Sstevel@tonic-gate ELFUNLOCK(elf) 7330Sstevel@tonic-gate return (-1); 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate case ELF_C_WRIMAGE: 7360Sstevel@tonic-gate if ((elf->ed_myflags & EDF_WRITE) == 0) { 7370Sstevel@tonic-gate _elf_seterr(EREQ_UPDWRT, 0); 7380Sstevel@tonic-gate ELFUNLOCK(elf) 7390Sstevel@tonic-gate return (-1); 7400Sstevel@tonic-gate } 7410Sstevel@tonic-gate break; 7420Sstevel@tonic-gate case ELF_C_WRITE: 7430Sstevel@tonic-gate if ((elf->ed_myflags & EDF_WRITE) == 0) { 7440Sstevel@tonic-gate _elf_seterr(EREQ_UPDWRT, 0); 7450Sstevel@tonic-gate ELFUNLOCK(elf) 7460Sstevel@tonic-gate return (-1); 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate if (elf->ed_wrimage) { 7490Sstevel@tonic-gate if (elf->ed_myflags & EDF_WRALLOC) { 7500Sstevel@tonic-gate free(elf->ed_wrimage); 7510Sstevel@tonic-gate /* 7520Sstevel@tonic-gate * The size is still returned even 7530Sstevel@tonic-gate * though nothing is actually written 7540Sstevel@tonic-gate * out. This is just to be consistant 7550Sstevel@tonic-gate * with the rest of the interface. 7560Sstevel@tonic-gate */ 7570Sstevel@tonic-gate sz = elf->ed_wrimagesz; 7580Sstevel@tonic-gate elf->ed_wrimage = 0; 7590Sstevel@tonic-gate elf->ed_wrimagesz = 0; 7600Sstevel@tonic-gate ELFUNLOCK(elf); 7610Sstevel@tonic-gate return ((off_t)sz); 7620Sstevel@tonic-gate } 7630Sstevel@tonic-gate sz = _elf_outsync(elf->ed_fd, elf->ed_wrimage, 7646206Sab196087 elf->ed_wrimagesz, 7656206Sab196087 (elf->ed_myflags & EDF_IMALLOC ? 0 : 1)); 7660Sstevel@tonic-gate elf->ed_myflags &= ~EDF_IMALLOC; 7670Sstevel@tonic-gate elf->ed_wrimage = 0; 7680Sstevel@tonic-gate elf->ed_wrimagesz = 0; 7690Sstevel@tonic-gate ELFUNLOCK(elf); 7700Sstevel@tonic-gate return ((off_t)sz); 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate /* FALLTHROUGH */ 7730Sstevel@tonic-gate case ELF_C_NULL: 7740Sstevel@tonic-gate break; 7750Sstevel@tonic-gate } 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate if (eh == 0) { 7780Sstevel@tonic-gate _elf_seterr(ESEQ_EHDR, 0); 7790Sstevel@tonic-gate ELFUNLOCK(elf) 7800Sstevel@tonic-gate return (-1); 7810Sstevel@tonic-gate } 7820Sstevel@tonic-gate 7830Sstevel@tonic-gate if ((u = eh->e_version) > EV_CURRENT) { 7840Sstevel@tonic-gate _elf_seterr(EREQ_VER, 0); 7850Sstevel@tonic-gate ELFUNLOCK(elf) 7860Sstevel@tonic-gate return (-1); 7870Sstevel@tonic-gate } 7880Sstevel@tonic-gate 7890Sstevel@tonic-gate if (u == EV_NONE) 7900Sstevel@tonic-gate eh->e_version = EV_CURRENT; 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate if ((u = eh->e_ident[EI_DATA]) == ELFDATANONE) { 7930Sstevel@tonic-gate unsigned encode; 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate ELFACCESSDATA(encode, _elf_encode) 7960Sstevel@tonic-gate if (encode == ELFDATANONE) { 7970Sstevel@tonic-gate _elf_seterr(EREQ_ENCODE, 0); 7980Sstevel@tonic-gate ELFUNLOCK(elf) 7990Sstevel@tonic-gate return (-1); 8000Sstevel@tonic-gate } 8010Sstevel@tonic-gate /* LINTED */ 8020Sstevel@tonic-gate eh->e_ident[EI_DATA] = (Byte)encode; 8030Sstevel@tonic-gate } 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate u = 1; 8060Sstevel@tonic-gate if (elf->ed_uflags & ELF_F_LAYOUT) { 8070Sstevel@tonic-gate sz = _elf_upd_usr(elf); 8080Sstevel@tonic-gate u = 0; 8090Sstevel@tonic-gate } else 8100Sstevel@tonic-gate sz = _elf_upd_lib(elf); 8110Sstevel@tonic-gate 8120Sstevel@tonic-gate if ((sz != 0) && ((cmd == ELF_C_WRITE) || (cmd == ELF_C_WRIMAGE))) 8130Sstevel@tonic-gate sz = wrt(elf, (Xword)sz, u, cmd); 8140Sstevel@tonic-gate 8150Sstevel@tonic-gate if (sz == 0) { 8160Sstevel@tonic-gate ELFUNLOCK(elf) 8170Sstevel@tonic-gate return (-1); 8180Sstevel@tonic-gate } 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate ELFUNLOCK(elf) 8210Sstevel@tonic-gate return ((off_t)sz); 8220Sstevel@tonic-gate } 8230Sstevel@tonic-gate 8240Sstevel@tonic-gate 8256206Sab196087 /* 8266206Sab196087 * When wrt() processes an ELF_C_WRIMAGE request, the resulting image 8276206Sab196087 * gets the byte order (encoding) of the platform running the linker 8286206Sab196087 * rather than that of the target host. This allows the linker to modify 8296206Sab196087 * the image, prior to flushing it to the output file. This routine 8306206Sab196087 * is used to re-translate such an image into the byte order of the 8316206Sab196087 * target host. 8326206Sab196087 */ 8336206Sab196087 int 8346572Sab196087 _elfxx_swap_wrimage(Elf *elf) 8356206Sab196087 { 8366206Sab196087 Elf_Data dst, src; 8376206Sab196087 Elf_Scn *s; 8386572Sab196087 Ehdr *eh; 8396572Sab196087 Half e_phnum; 8406572Sab196087 unsigned ver; 8416572Sab196087 unsigned encode; 8426206Sab196087 8436206Sab196087 /* 8446206Sab196087 * Ehdr first 8456206Sab196087 */ 8466206Sab196087 8476572Sab196087 ELFWLOCK(elf); 8486572Sab196087 eh = elf->ed_ehdr; 8496572Sab196087 e_phnum = eh->e_phnum; 8506572Sab196087 ver = eh->e_version; 8516572Sab196087 encode = eh->e_ident[EI_DATA]; 8526572Sab196087 8536206Sab196087 src.d_buf = dst.d_buf = (Elf_Void *)eh; 8546206Sab196087 src.d_type = dst.d_type = ELF_T_EHDR; 8556206Sab196087 src.d_size = dst.d_size = sizeof (Ehdr); 8566206Sab196087 src.d_version = dst.d_version = ver; 8576572Sab196087 if (elf_xlatetof(&dst, &src, encode) == 0) { 8586572Sab196087 ELFUNLOCK(elf); 8596206Sab196087 return (1); 8606572Sab196087 } 8616206Sab196087 8626206Sab196087 /* 8636206Sab196087 * Phdr table if one exists 8646206Sab196087 */ 8656206Sab196087 8666206Sab196087 if (e_phnum != 0) { 8676206Sab196087 unsigned work; 8686206Sab196087 /* 8696206Sab196087 * Unlike other library data, phdr table is 8706206Sab196087 * in the user version. 8716206Sab196087 */ 8726206Sab196087 8736206Sab196087 src.d_buf = dst.d_buf = (Elf_Void *)elf->ed_phdr; 8746206Sab196087 src.d_type = dst.d_type = ELF_T_PHDR; 8756206Sab196087 src.d_size = dst.d_size = elf->ed_phdrsz; 8766206Sab196087 ELFACCESSDATA(work, _elf_work) 8776206Sab196087 src.d_version = dst.d_version = work; 8786206Sab196087 if (elf_xlatetof(&dst, &src, encode) == 0) { 8796572Sab196087 ELFUNLOCK(elf); 8806206Sab196087 return (1); 8816206Sab196087 } 8826206Sab196087 } 8836206Sab196087 8846206Sab196087 /* 8856206Sab196087 * Loop through sections 8866206Sab196087 */ 8876206Sab196087 8886206Sab196087 for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 8896206Sab196087 register Dnode *d, *prevd; 8906206Sab196087 Shdr *sh = s->s_shdr; 8916206Sab196087 8926206Sab196087 if ((sh->sh_type == SHT_NOBITS) || (sh->sh_type == SHT_NULL)) 8936206Sab196087 continue; 8946206Sab196087 8956206Sab196087 for (d = s->s_hdnode, prevd = 0; 8966206Sab196087 d != 0; prevd = d, d = d->db_next) { 8976206Sab196087 8986206Sab196087 if ((d->db_myflags & DBF_READY) == 0) { 8996206Sab196087 SCNLOCK(s); 9006206Sab196087 if (_elf_locked_getdata(s, &prevd->db_data) != 9016206Sab196087 &d->db_data) { 9026206Sab196087 SCNUNLOCK(s); 9036572Sab196087 ELFUNLOCK(elf); 9046206Sab196087 return (1); 9056206Sab196087 } 9066206Sab196087 SCNUNLOCK(s); 9076206Sab196087 } 9086206Sab196087 9096206Sab196087 dst = d->db_data; 9106572Sab196087 if (elf_xlatetof(&dst, &d->db_data, encode) == 0) { 9116572Sab196087 ELFUNLOCK(elf); 9126206Sab196087 return (1); 9136572Sab196087 } 9146206Sab196087 } 9156206Sab196087 } 9166206Sab196087 9176206Sab196087 /* 9186206Sab196087 * Shdr table 9196206Sab196087 */ 9206206Sab196087 9216206Sab196087 src.d_type = dst.d_type = ELF_T_SHDR; 9226206Sab196087 src.d_version = dst.d_version = ver; 9236206Sab196087 for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 9246206Sab196087 src.d_buf = dst.d_buf = s->s_shdr; 9256206Sab196087 src.d_size = dst.d_size = sizeof (Shdr); 9266572Sab196087 if (elf_xlatetof(&dst, &src, encode) == 0) { 9276572Sab196087 ELFUNLOCK(elf); 9286206Sab196087 return (1); 9296572Sab196087 } 9306206Sab196087 } 9316206Sab196087 9326572Sab196087 ELFUNLOCK(elf); 9336206Sab196087 return (0); 9346206Sab196087 } 9356206Sab196087 9366206Sab196087 9376206Sab196087 9380Sstevel@tonic-gate #ifndef _ELF64 9390Sstevel@tonic-gate /* class-independent, only needs to be compiled once */ 9400Sstevel@tonic-gate 9410Sstevel@tonic-gate off_t 9420Sstevel@tonic-gate elf_update(Elf *elf, Elf_Cmd cmd) 9430Sstevel@tonic-gate { 9440Sstevel@tonic-gate if (elf == 0) 9450Sstevel@tonic-gate return (-1); 9460Sstevel@tonic-gate 9470Sstevel@tonic-gate if (elf->ed_class == ELFCLASS32) 9480Sstevel@tonic-gate return (_elf32_update(elf, cmd)); 9490Sstevel@tonic-gate else if (elf->ed_class == ELFCLASS64) { 9500Sstevel@tonic-gate return (_elf64_update(elf, cmd)); 9510Sstevel@tonic-gate } 9520Sstevel@tonic-gate 9530Sstevel@tonic-gate _elf_seterr(EREQ_CLASS, 0); 9540Sstevel@tonic-gate return (-1); 9550Sstevel@tonic-gate } 9560Sstevel@tonic-gate 9576206Sab196087 int 9586206Sab196087 _elf_swap_wrimage(Elf *elf) 9596206Sab196087 { 9606206Sab196087 if (elf == 0) 9616206Sab196087 return (0); 9626206Sab196087 9636206Sab196087 if (elf->ed_class == ELFCLASS32) 9646206Sab196087 return (_elf32_swap_wrimage(elf)); 9656206Sab196087 9666206Sab196087 if (elf->ed_class == ELFCLASS64) 9676206Sab196087 return (_elf64_swap_wrimage(elf)); 9686206Sab196087 9696206Sab196087 _elf_seterr(EREQ_CLASS, 0); 9706206Sab196087 return (0); 9716206Sab196087 } 9726206Sab196087 9730Sstevel@tonic-gate /* 9740Sstevel@tonic-gate * 4106312, 4106398, This is an ad-hoc means for the 32-bit 9750Sstevel@tonic-gate * Elf64 version of libld.so.3 to get around the limitation 9760Sstevel@tonic-gate * of a 32-bit d_off field. This is only intended to be 9770Sstevel@tonic-gate * used by libld to relocate symbols in large NOBITS sections. 9780Sstevel@tonic-gate */ 9790Sstevel@tonic-gate Elf64_Off 9800Sstevel@tonic-gate _elf_getxoff(Elf_Data * d) 9810Sstevel@tonic-gate { 9820Sstevel@tonic-gate return (((Dnode *)d)->db_xoff); 9830Sstevel@tonic-gate } 9840Sstevel@tonic-gate #endif /* !_ELF64 */ 985