17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57257d1b4Sraf * Common Development and Distribution License (the "License"). 67257d1b4Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate /* 237257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277257d1b4Sraf /* Copyright (c) 1988 AT&T */ 287257d1b4Sraf /* All Rights Reserved */ 297257d1b4Sraf 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * This stuff used to live in cook.c, but was moved out to 327c478bd9Sstevel@tonic-gate * facilitate dual (Elf32 and Elf64) compilation. See block 337c478bd9Sstevel@tonic-gate * comment in cook.c for more info. 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <string.h> 377c478bd9Sstevel@tonic-gate #include <ar.h> 387c478bd9Sstevel@tonic-gate #include <stdlib.h> 397c478bd9Sstevel@tonic-gate #include <errno.h> 4098cadd32SRichard Lowe #include <sys/sysmacros.h> 417c478bd9Sstevel@tonic-gate #include "decl.h" 427c478bd9Sstevel@tonic-gate #include "member.h" 437c478bd9Sstevel@tonic-gate #include "msg.h" 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /* 467c478bd9Sstevel@tonic-gate * This module is compiled twice, the second time having 477c478bd9Sstevel@tonic-gate * -D_ELF64 defined. The following set of macros, along 487c478bd9Sstevel@tonic-gate * with machelf.h, represent the differences between the 497c478bd9Sstevel@tonic-gate * two compilations. Be careful *not* to add any class- 507c478bd9Sstevel@tonic-gate * dependent code (anything that has elf32 or elf64 in the 517c478bd9Sstevel@tonic-gate * name) to this code without hiding it behind a switch- 527c478bd9Sstevel@tonic-gate * able macro like these. 537c478bd9Sstevel@tonic-gate */ 547c478bd9Sstevel@tonic-gate #if defined(_ELF64) 557c478bd9Sstevel@tonic-gate #define Snode Snode64 567c478bd9Sstevel@tonic-gate #define ELFCLASS ELFCLASS64 577c478bd9Sstevel@tonic-gate #define ElfField Elf64 587c478bd9Sstevel@tonic-gate #define _elf_snode_init _elf64_snode_init 597c478bd9Sstevel@tonic-gate #define _elf_prepscan _elf64_prepscan 607c478bd9Sstevel@tonic-gate #define _elf_cookscn _elf64_cookscn 617c478bd9Sstevel@tonic-gate #define _elf_mtype _elf64_mtype 627c478bd9Sstevel@tonic-gate #define _elf_msize _elf64_msize 637c478bd9Sstevel@tonic-gate #define elf_fsize elf64_fsize 647c478bd9Sstevel@tonic-gate #define _elf_snode _elf64_snode 657c478bd9Sstevel@tonic-gate #define _elf_ehdr _elf64_ehdr 667c478bd9Sstevel@tonic-gate #define elf_xlatetom elf64_xlatetom 677c478bd9Sstevel@tonic-gate #define _elf_phdr _elf64_phdr 687c478bd9Sstevel@tonic-gate #define _elf_shdr _elf64_shdr 697c478bd9Sstevel@tonic-gate #define _elf_prepscn _elf64_prepscn 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate #else /* Elf32 */ 727c478bd9Sstevel@tonic-gate #define Snode Snode32 737c478bd9Sstevel@tonic-gate #define ELFCLASS ELFCLASS32 747c478bd9Sstevel@tonic-gate #define ElfField Elf32 757c478bd9Sstevel@tonic-gate #define _elf_snode_init _elf32_snode_init 767c478bd9Sstevel@tonic-gate #define _elf_prepscan _elf32_prepscan 777c478bd9Sstevel@tonic-gate #define _elf_cookscn _elf32_cookscn 787c478bd9Sstevel@tonic-gate #define _elf_mtype _elf32_mtype 797c478bd9Sstevel@tonic-gate #define _elf_msize _elf32_msize 807c478bd9Sstevel@tonic-gate #define elf_fsize elf32_fsize 817c478bd9Sstevel@tonic-gate #define _elf_snode _elf32_snode 827c478bd9Sstevel@tonic-gate #define _elf_ehdr _elf32_ehdr 837c478bd9Sstevel@tonic-gate #define elf_xlatetom elf32_xlatetom 847c478bd9Sstevel@tonic-gate #define _elf_phdr _elf32_phdr 857c478bd9Sstevel@tonic-gate #define _elf_shdr _elf32_shdr 867c478bd9Sstevel@tonic-gate #define _elf_prepscn _elf32_prepscn 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate #endif /* _ELF64 */ 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate static Okay 927c478bd9Sstevel@tonic-gate _elf_prepscn(Elf *elf, size_t cnt) 937c478bd9Sstevel@tonic-gate { 947c478bd9Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 957c478bd9Sstevel@tonic-gate Elf_Scn * s; 967c478bd9Sstevel@tonic-gate Elf_Scn * end; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if (cnt == 0) 997c478bd9Sstevel@tonic-gate return (OK_YES); 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate if ((s = malloc(cnt * sizeof (Elf_Scn))) == 0) { 1027c478bd9Sstevel@tonic-gate _elf_seterr(EMEM_SCN, errno); 1037c478bd9Sstevel@tonic-gate return (OK_NO); 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s)) 1067c478bd9Sstevel@tonic-gate elf->ed_scntabsz = cnt; 1077c478bd9Sstevel@tonic-gate end = s + cnt; 1087c478bd9Sstevel@tonic-gate elf->ed_hdscn = s; 1097c478bd9Sstevel@tonic-gate do { 1107c478bd9Sstevel@tonic-gate *s = _elf_snode_init.sb_scn; 1117c478bd9Sstevel@tonic-gate s->s_elf = elf; 1127c478bd9Sstevel@tonic-gate s->s_next = s + 1; 1137c478bd9Sstevel@tonic-gate s->s_index = s - elf->ed_hdscn; 1147c478bd9Sstevel@tonic-gate s->s_shdr = (Shdr*)s->s_elf->ed_shdr + s->s_index; 1157c478bd9Sstevel@tonic-gate ELFMUTEXINIT(&s->s_mutex); 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate /* 1187c478bd9Sstevel@tonic-gate * Section has not yet been cooked! 1197c478bd9Sstevel@tonic-gate * 1207c478bd9Sstevel@tonic-gate * We don't cook a section until it's data is actually 1217c478bd9Sstevel@tonic-gate * referenced. 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate s->s_myflags = 0; 1247c478bd9Sstevel@tonic-gate } while (++s < end); 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate elf->ed_tlscn = --s; 1277c478bd9Sstevel@tonic-gate s->s_next = 0; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate /* 1307c478bd9Sstevel@tonic-gate * Section index SHN_UNDEF (0) does not and cannot 1317c478bd9Sstevel@tonic-gate * have a data buffer. Fix it here. Also mark the 1327c478bd9Sstevel@tonic-gate * initial section as being allocated for the block 1337c478bd9Sstevel@tonic-gate */ 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate s = elf->ed_hdscn; 1367c478bd9Sstevel@tonic-gate s->s_myflags = SF_ALLOC; 1377c478bd9Sstevel@tonic-gate s->s_hdnode = 0; 1387c478bd9Sstevel@tonic-gate s->s_tlnode = 0; 1397c478bd9Sstevel@tonic-gate NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s)) 1407c478bd9Sstevel@tonic-gate return (OK_YES); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate Okay 1457c478bd9Sstevel@tonic-gate _elf_cookscn(Elf_Scn * s) 1467c478bd9Sstevel@tonic-gate { 1477c478bd9Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*s, *(s->s_elf))) 1487c478bd9Sstevel@tonic-gate Elf * elf; 1497c478bd9Sstevel@tonic-gate Shdr * sh; 1507c478bd9Sstevel@tonic-gate register Dnode * d = &s->s_dnode; 1517c478bd9Sstevel@tonic-gate size_t fsz, msz; 1527c478bd9Sstevel@tonic-gate unsigned work; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*d)) 1557c478bd9Sstevel@tonic-gate s->s_hdnode = s->s_tlnode = d; 1567c478bd9Sstevel@tonic-gate s->s_err = 0; 1577c478bd9Sstevel@tonic-gate s->s_shflags = 0; 1587c478bd9Sstevel@tonic-gate s->s_uflags = 0; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Prepare d_data for inspection, but don't actually 1637c478bd9Sstevel@tonic-gate * translate data until needed. Leave the READY 1647c478bd9Sstevel@tonic-gate * flag off. NOBITS sections see zero size. 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate elf = s->s_elf; 1677c478bd9Sstevel@tonic-gate sh = s->s_shdr; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate d->db_scn = s; 1707c478bd9Sstevel@tonic-gate d->db_off = sh->sh_offset; 1717c478bd9Sstevel@tonic-gate d->db_data.d_align = sh->sh_addralign; 1727c478bd9Sstevel@tonic-gate d->db_data.d_version = elf->ed_version; 1737c478bd9Sstevel@tonic-gate ELFACCESSDATA(work, _elf_work) 1747c478bd9Sstevel@tonic-gate d->db_data.d_type = _elf_mtype(elf, sh->sh_type, work); 1757c478bd9Sstevel@tonic-gate d->db_data.d_buf = 0; 1767c478bd9Sstevel@tonic-gate d->db_data.d_off = 0; 1777c478bd9Sstevel@tonic-gate fsz = elf_fsize(d->db_data.d_type, 1, elf->ed_version); 1787c478bd9Sstevel@tonic-gate msz = _elf_msize(d->db_data.d_type, elf->ed_version); 17998cadd32SRichard Lowe d->db_data.d_size = MAX(sh->sh_size, (sh->sh_size / fsz) * msz); 1807c478bd9Sstevel@tonic-gate d->db_shsz = sh->sh_size; 1817c478bd9Sstevel@tonic-gate d->db_raw = 0; 1827c478bd9Sstevel@tonic-gate d->db_buf = 0; 1837c478bd9Sstevel@tonic-gate d->db_uflags = 0; 1847c478bd9Sstevel@tonic-gate d->db_myflags = 0; 1857c478bd9Sstevel@tonic-gate d->db_next = 0; 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate if (sh->sh_type != SHT_NOBITS) 1887c478bd9Sstevel@tonic-gate d->db_fsz = sh->sh_size; 1897c478bd9Sstevel@tonic-gate else 1907c478bd9Sstevel@tonic-gate d->db_fsz = 0; 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate s->s_myflags |= SF_READY; 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*d)) 1957c478bd9Sstevel@tonic-gate return (OK_YES); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate Snode * 2017c478bd9Sstevel@tonic-gate _elf_snode() 2027c478bd9Sstevel@tonic-gate { 2037c478bd9Sstevel@tonic-gate register Snode *s; 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate if ((s = malloc(sizeof (Snode))) == 0) { 2067c478bd9Sstevel@tonic-gate _elf_seterr(EMEM_SNODE, errno); 2077c478bd9Sstevel@tonic-gate return (0); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate *s = _elf_snode_init; 2107c478bd9Sstevel@tonic-gate ELFMUTEXINIT(&s->sb_scn.s_mutex); 2117c478bd9Sstevel@tonic-gate s->sb_scn.s_myflags = SF_ALLOC | SF_READY; 2127c478bd9Sstevel@tonic-gate s->sb_scn.s_shdr = &s->sb_shdr; 2137c478bd9Sstevel@tonic-gate return (s); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate int 2197c478bd9Sstevel@tonic-gate _elf_ehdr(Elf * elf, int inplace) 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 2227c478bd9Sstevel@tonic-gate register size_t fsz; /* field size */ 2237c478bd9Sstevel@tonic-gate Elf_Data dst, src; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate fsz = elf_fsize(ELF_T_EHDR, 1, elf->ed_version); 2267c478bd9Sstevel@tonic-gate if (fsz > elf->ed_fsz) { 2277c478bd9Sstevel@tonic-gate _elf_seterr(EFMT_EHDRSZ, 0); 2287c478bd9Sstevel@tonic-gate return (-1); 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate if (inplace && (fsz >= sizeof (Ehdr))) { 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * The translated Ehdr will fit over the original Ehdr. 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate /* LINTED */ 2357c478bd9Sstevel@tonic-gate elf->ed_ehdr = (Ehdr *)elf->ed_ident; 2367c478bd9Sstevel@tonic-gate elf->ed_status = ES_COOKED; 2377c478bd9Sstevel@tonic-gate } else { 2387c478bd9Sstevel@tonic-gate elf->ed_ehdr = malloc(sizeof (Ehdr)); 2397c478bd9Sstevel@tonic-gate if (elf->ed_ehdr == 0) { 2407c478bd9Sstevel@tonic-gate _elf_seterr(EMEM_EHDR, errno); 2417c478bd9Sstevel@tonic-gate return (-1); 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate elf->ed_myflags |= EDF_EHALLOC; 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /* 2477c478bd9Sstevel@tonic-gate * Memory size >= fsz, because otherwise the memory version 2487c478bd9Sstevel@tonic-gate * loses information and cannot accurately implement the 2497c478bd9Sstevel@tonic-gate * file. 2507c478bd9Sstevel@tonic-gate */ 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate src.d_buf = (Elf_Void *)elf->ed_ident; 2537c478bd9Sstevel@tonic-gate src.d_type = ELF_T_EHDR; 2547c478bd9Sstevel@tonic-gate src.d_size = fsz; 2557c478bd9Sstevel@tonic-gate src.d_version = elf->ed_version; 2567c478bd9Sstevel@tonic-gate dst.d_buf = (Elf_Void *)elf->ed_ehdr; 2577c478bd9Sstevel@tonic-gate dst.d_size = sizeof (Ehdr); 2587c478bd9Sstevel@tonic-gate dst.d_version = EV_CURRENT; 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate if ((_elf_vm(elf, (size_t)0, fsz) != OK_YES) || 2617c478bd9Sstevel@tonic-gate (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) { 2627c478bd9Sstevel@tonic-gate if (elf->ed_myflags & EDF_EHALLOC) { 2637c478bd9Sstevel@tonic-gate elf->ed_myflags &= ~EDF_EHALLOC; 2647c478bd9Sstevel@tonic-gate free(elf->ed_ehdr); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate elf->ed_ehdr = 0; 2677c478bd9Sstevel@tonic-gate return (-1); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate if (((Ehdr*)elf->ed_ehdr)->e_ident[EI_CLASS] != ELFCLASS) { 2717c478bd9Sstevel@tonic-gate _elf_seterr(EREQ_CLASS, 0); 2727c478bd9Sstevel@tonic-gate if (elf->ed_myflags & EDF_EHALLOC) { 2737c478bd9Sstevel@tonic-gate elf->ed_myflags &= ~EDF_EHALLOC; 2747c478bd9Sstevel@tonic-gate free(elf->ed_ehdr); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate elf->ed_ehdr = 0; 2777c478bd9Sstevel@tonic-gate return (-1); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate if (((Ehdr*)elf->ed_ehdr)->e_version != elf->ed_version) { 2817c478bd9Sstevel@tonic-gate _elf_seterr(EFMT_VER2, 0); 2827c478bd9Sstevel@tonic-gate if (elf->ed_myflags & EDF_EHALLOC) { 2837c478bd9Sstevel@tonic-gate elf->ed_myflags &= ~EDF_EHALLOC; 2847c478bd9Sstevel@tonic-gate free(elf->ed_ehdr); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate elf->ed_ehdr = 0; 2877c478bd9Sstevel@tonic-gate return (-1); 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate return (0); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate int 2967c478bd9Sstevel@tonic-gate _elf_phdr(Elf * elf, int inplace) 2977c478bd9Sstevel@tonic-gate { 2987c478bd9Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 2997c478bd9Sstevel@tonic-gate register size_t fsz, msz; 3007c478bd9Sstevel@tonic-gate Elf_Data dst, src; 3017c478bd9Sstevel@tonic-gate Ehdr * eh = elf->ed_ehdr; /* must be present */ 3027c478bd9Sstevel@tonic-gate unsigned work; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate if (eh->e_phnum == 0) 3057c478bd9Sstevel@tonic-gate return (0); 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate fsz = elf_fsize(ELF_T_PHDR, 1, elf->ed_version); 3087c478bd9Sstevel@tonic-gate if (eh->e_phentsize != fsz) { 3097c478bd9Sstevel@tonic-gate _elf_seterr(EFMT_PHDRSZ, 0); 3107c478bd9Sstevel@tonic-gate return (-1); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate fsz *= eh->e_phnum; 3147c478bd9Sstevel@tonic-gate ELFACCESSDATA(work, _elf_work) 3157c478bd9Sstevel@tonic-gate msz = _elf_msize(ELF_T_PHDR, work) * eh->e_phnum; 3167c478bd9Sstevel@tonic-gate if ((eh->e_phoff == 0) || 317*18059eaeSRichard Lowe (elf->ed_fsz <= eh->e_phoff) || 318*18059eaeSRichard Lowe (elf->ed_fsz - eh->e_phoff < fsz)) { 3197c478bd9Sstevel@tonic-gate _elf_seterr(EFMT_PHTAB, 0); 3207c478bd9Sstevel@tonic-gate return (-1); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate if (inplace && fsz >= msz && eh->e_phoff % sizeof (ElfField) == 0) { 3247c478bd9Sstevel@tonic-gate elf->ed_phdr = (Elf_Void *)(elf->ed_ident + eh->e_phoff); 3257c478bd9Sstevel@tonic-gate elf->ed_status = ES_COOKED; 3267c478bd9Sstevel@tonic-gate } else { 3277c478bd9Sstevel@tonic-gate if ((elf->ed_phdr = malloc(msz)) == 0) { 3287c478bd9Sstevel@tonic-gate _elf_seterr(EMEM_PHDR, errno); 3297c478bd9Sstevel@tonic-gate return (-1); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate elf->ed_myflags |= EDF_PHALLOC; 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_phoff); 3347c478bd9Sstevel@tonic-gate src.d_type = ELF_T_PHDR; 3357c478bd9Sstevel@tonic-gate src.d_size = fsz; 3367c478bd9Sstevel@tonic-gate src.d_version = elf->ed_version; 3377c478bd9Sstevel@tonic-gate dst.d_buf = elf->ed_phdr; 3387c478bd9Sstevel@tonic-gate dst.d_size = msz; 3397c478bd9Sstevel@tonic-gate dst.d_version = work; 3407c478bd9Sstevel@tonic-gate if ((_elf_vm(elf, (size_t)eh->e_phoff, fsz) != OK_YES) || 3417c478bd9Sstevel@tonic-gate (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) { 3427c478bd9Sstevel@tonic-gate if (elf->ed_myflags & EDF_PHALLOC) { 3437c478bd9Sstevel@tonic-gate elf->ed_myflags &= ~EDF_PHALLOC; 3447c478bd9Sstevel@tonic-gate free(elf->ed_phdr); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate elf->ed_phdr = 0; 3477c478bd9Sstevel@tonic-gate return (-1); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate elf->ed_phdrsz = msz; 3507c478bd9Sstevel@tonic-gate return (0); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate int 3567c478bd9Sstevel@tonic-gate _elf_shdr(Elf * elf, int inplace) 3577c478bd9Sstevel@tonic-gate { 3587c478bd9Sstevel@tonic-gate NOTE(ASSUMING_PROTECTED(*elf)) 3597c478bd9Sstevel@tonic-gate register size_t fsz, msz; 3607c478bd9Sstevel@tonic-gate size_t scncnt; 3617c478bd9Sstevel@tonic-gate Elf_Data dst, src; 3627c478bd9Sstevel@tonic-gate register Ehdr *eh = elf->ed_ehdr; /* must be present */ 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if ((eh->e_shnum == 0) && (eh->e_shoff == 0)) 3657c478bd9Sstevel@tonic-gate return (0); 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate fsz = elf_fsize(ELF_T_SHDR, 1, elf->ed_version); 3687c478bd9Sstevel@tonic-gate if (eh->e_shentsize != fsz) { 3697c478bd9Sstevel@tonic-gate _elf_seterr(EFMT_SHDRSZ, 0); 3707c478bd9Sstevel@tonic-gate return (-1); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate /* 3737c478bd9Sstevel@tonic-gate * If we are dealing with a file with 'extended section 3747c478bd9Sstevel@tonic-gate * indexes' - then we need to load the first section 3757c478bd9Sstevel@tonic-gate * header. The actual section count is stored in 3767c478bd9Sstevel@tonic-gate * Shdr[0].sh_size. 3777c478bd9Sstevel@tonic-gate */ 3787c478bd9Sstevel@tonic-gate if ((scncnt = eh->e_shnum) == 0) { 3797c478bd9Sstevel@tonic-gate Shdr sh; 3807c478bd9Sstevel@tonic-gate if ((eh->e_shoff == 0) || 3817c478bd9Sstevel@tonic-gate (elf->ed_fsz <= eh->e_shoff) || 3827c478bd9Sstevel@tonic-gate (elf->ed_fsz - eh->e_shoff < fsz)) { 3837c478bd9Sstevel@tonic-gate _elf_seterr(EFMT_SHTAB, 0); 3847c478bd9Sstevel@tonic-gate return (-1); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff); 3877c478bd9Sstevel@tonic-gate src.d_type = ELF_T_SHDR; 3887c478bd9Sstevel@tonic-gate src.d_size = fsz; 3897c478bd9Sstevel@tonic-gate src.d_version = elf->ed_version; 3907c478bd9Sstevel@tonic-gate dst.d_buf = (Elf_Void *)&sh; 3917c478bd9Sstevel@tonic-gate dst.d_size = sizeof (Shdr); 3927c478bd9Sstevel@tonic-gate dst.d_version = EV_CURRENT; 3937c478bd9Sstevel@tonic-gate if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) || 3947c478bd9Sstevel@tonic-gate (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) { 3957c478bd9Sstevel@tonic-gate return (-1); 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate scncnt = sh.sh_size; 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate fsz *= scncnt; 4017c478bd9Sstevel@tonic-gate msz = scncnt * sizeof (Shdr); 4027c478bd9Sstevel@tonic-gate if ((eh->e_shoff == 0) || 4037c478bd9Sstevel@tonic-gate (elf->ed_fsz <= eh->e_shoff) || 4047c478bd9Sstevel@tonic-gate (elf->ed_fsz - eh->e_shoff < fsz)) { 4057c478bd9Sstevel@tonic-gate _elf_seterr(EFMT_SHTAB, 0); 4067c478bd9Sstevel@tonic-gate return (-1); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate if (inplace && (fsz >= msz) && 4107c478bd9Sstevel@tonic-gate ((eh->e_shoff % sizeof (ElfField)) == 0)) { 4117c478bd9Sstevel@tonic-gate /* LINTED */ 4127c478bd9Sstevel@tonic-gate elf->ed_shdr = (Shdr *)(elf->ed_ident + eh->e_shoff); 4137c478bd9Sstevel@tonic-gate elf->ed_status = ES_COOKED; 4147c478bd9Sstevel@tonic-gate } else { 4157c478bd9Sstevel@tonic-gate if ((elf->ed_shdr = malloc(msz)) == 0) { 4167c478bd9Sstevel@tonic-gate _elf_seterr(EMEM_SHDR, errno); 4177c478bd9Sstevel@tonic-gate return (-1); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate elf->ed_myflags |= EDF_SHALLOC; 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff); 4227c478bd9Sstevel@tonic-gate src.d_type = ELF_T_SHDR; 4237c478bd9Sstevel@tonic-gate src.d_size = fsz; 4247c478bd9Sstevel@tonic-gate src.d_version = elf->ed_version; 4257c478bd9Sstevel@tonic-gate dst.d_buf = (Elf_Void *)elf->ed_shdr; 4267c478bd9Sstevel@tonic-gate dst.d_size = msz; 4277c478bd9Sstevel@tonic-gate dst.d_version = EV_CURRENT; 4287c478bd9Sstevel@tonic-gate if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) || 4297c478bd9Sstevel@tonic-gate (elf_xlatetom(&dst, &src, elf->ed_encode) == 0) || 4307c478bd9Sstevel@tonic-gate (_elf_prepscn(elf, scncnt) != OK_YES)) { 4317c478bd9Sstevel@tonic-gate if (elf->ed_myflags & EDF_SHALLOC) { 4327c478bd9Sstevel@tonic-gate elf->ed_myflags &= ~EDF_SHALLOC; 4337c478bd9Sstevel@tonic-gate free(elf->ed_shdr); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate elf->ed_shdr = 0; 4367c478bd9Sstevel@tonic-gate return (-1); 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate return (0); 4397c478bd9Sstevel@tonic-gate } 440