1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <stdlib.h> 33 #include <memory.h> 34 #include <errno.h> 35 #include "decl.h" 36 #include "msg.h" 37 38 /* 39 * This module is compiled twice, the second time having 40 * -D_ELF64 defined. The following set of macros, along 41 * with machelf.h, represent the differences between the 42 * two compilations. Be careful *not* to add any class- 43 * dependent code (anything that has elf32 or elf64 in the 44 * name) to this code without hiding it behind a switch- 45 * able macro like these. 46 */ 47 #if defined(_ELF64) 48 49 #define ELFCLASS ELFCLASS64 50 #define elf_newphdr elf64_newphdr 51 #define elf_getehdr elf64_getehdr 52 #define _elf_msize _elf64_msize 53 #define elf_fsize elf64_fsize 54 55 #else /* else ELF32 */ 56 57 #define ELFCLASS ELFCLASS32 58 #define elf_newphdr elf32_newphdr 59 #define elf_getehdr elf32_getehdr 60 #define _elf_msize _elf32_msize 61 #define elf_fsize elf32_fsize 62 63 #endif /* ELF64 */ 64 65 66 Phdr * 67 elf_newphdr(Elf * elf, size_t count) 68 { 69 Elf_Void * ph; 70 size_t sz; 71 Phdr * rc; 72 unsigned work; 73 74 if (elf == 0) 75 return (0); 76 ELFRLOCK(elf) 77 if (elf->ed_class != ELFCLASS) { 78 _elf_seterr(EREQ_CLASS, 0); 79 ELFUNLOCK(elf) 80 return (0); 81 } 82 ELFUNLOCK(elf) 83 if (elf_getehdr(elf) == 0) { /* this cooks if necessary */ 84 _elf_seterr(ESEQ_EHDR, 0); 85 return (0); 86 } 87 88 /* 89 * Free the existing header if appropriate. This could reuse 90 * existing space if big enough, but that's unlikely, benefit 91 * would be negligible, and code would be more complicated. 92 */ 93 94 ELFWLOCK(elf) 95 if (elf->ed_myflags & EDF_PHALLOC) { 96 elf->ed_myflags &= ~EDF_PHALLOC; 97 rc = elf->ed_phdr; 98 free(rc); 99 } 100 101 /* 102 * Delete the header if count is zero. 103 */ 104 105 ELFACCESSDATA(work, _elf_work) 106 if ((sz = count * _elf_msize(ELF_T_PHDR, work)) == 0) { 107 elf->ed_phflags &= ~ELF_F_DIRTY; 108 elf->ed_phdr = 0; 109 ((Ehdr*)elf->ed_ehdr)->e_phnum = 0; 110 ((Ehdr*)elf->ed_ehdr)->e_phentsize = 0; 111 elf->ed_phdrsz = 0; 112 ELFUNLOCK(elf) 113 return (0); 114 } 115 116 if ((ph = malloc(sz)) == 0) { 117 _elf_seterr(EMEM_PHDR, errno); 118 elf->ed_phflags &= ~ELF_F_DIRTY; 119 elf->ed_phdr = 0; 120 ((Ehdr*)elf->ed_ehdr)->e_phnum = 0; 121 ((Ehdr*)elf->ed_ehdr)->e_phentsize = 0; 122 elf->ed_phdrsz = 0; 123 ELFUNLOCK(elf) 124 return (0); 125 } 126 127 elf->ed_myflags |= EDF_PHALLOC; 128 (void) memset(ph, 0, sz); 129 elf->ed_phflags |= ELF_F_DIRTY; 130 /* LINTED */ 131 ((Ehdr*)elf->ed_ehdr)->e_phnum = (Half)count; 132 ((Ehdr*)elf->ed_ehdr)->e_phentsize 133 /* LINTED */ 134 = (Half)elf_fsize(ELF_T_PHDR, 1, work); 135 elf->ed_phdrsz = sz; 136 elf->ed_phdr = rc = ph; 137 138 ELFUNLOCK(elf) 139 return (rc); 140 } 141