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 #include <stdlib.h> 31 #include <memory.h> 32 #include <errno.h> 33 #include "decl.h" 34 #include "msg.h" 35 36 /* 37 * This module is compiled twice, the second time having 38 * -D_ELF64 defined. The following set of macros, along 39 * with machelf.h, represent the differences between the 40 * two compilations. Be careful *not* to add any class- 41 * dependent code (anything that has elf32 or elf64 in the 42 * name) to this code without hiding it behind a switch- 43 * able macro like these. 44 */ 45 #if defined(_ELF64) 46 47 #define ELFCLASS ELFCLASS64 48 #define elf_newphdr elf64_newphdr 49 #define elf_getehdr elf64_getehdr 50 #define _elf_msize _elf64_msize 51 #define elf_fsize elf64_fsize 52 53 #else /* else ELF32 */ 54 55 #define ELFCLASS ELFCLASS32 56 #define elf_newphdr elf32_newphdr 57 #define elf_getehdr elf32_getehdr 58 #define _elf_msize _elf32_msize 59 #define elf_fsize elf32_fsize 60 61 #endif /* ELF64 */ 62 63 64 Phdr * 65 elf_newphdr(Elf * elf, size_t count) 66 { 67 Elf_Void * ph; 68 size_t sz; 69 Phdr * rc; 70 unsigned work; 71 72 if (elf == 0) 73 return (0); 74 ELFRLOCK(elf) 75 if (elf->ed_class != ELFCLASS) { 76 _elf_seterr(EREQ_CLASS, 0); 77 ELFUNLOCK(elf) 78 return (0); 79 } 80 ELFUNLOCK(elf) 81 if (elf_getehdr(elf) == 0) { /* this cooks if necessary */ 82 _elf_seterr(ESEQ_EHDR, 0); 83 return (0); 84 } 85 86 /* 87 * Free the existing header if appropriate. This could reuse 88 * existing space if big enough, but that's unlikely, benefit 89 * would be negligible, and code would be more complicated. 90 */ 91 92 ELFWLOCK(elf) 93 if (elf->ed_myflags & EDF_PHALLOC) { 94 elf->ed_myflags &= ~EDF_PHALLOC; 95 rc = elf->ed_phdr; 96 free(rc); 97 } 98 99 /* 100 * Delete the header if count is zero. 101 */ 102 103 ELFACCESSDATA(work, _elf_work) 104 if ((sz = count * _elf_msize(ELF_T_PHDR, work)) == 0) { 105 elf->ed_phflags &= ~ELF_F_DIRTY; 106 elf->ed_phdr = 0; 107 ((Ehdr*)elf->ed_ehdr)->e_phnum = 0; 108 ((Ehdr*)elf->ed_ehdr)->e_phentsize = 0; 109 elf->ed_phdrsz = 0; 110 ELFUNLOCK(elf) 111 return (0); 112 } 113 114 if ((ph = malloc(sz)) == 0) { 115 _elf_seterr(EMEM_PHDR, errno); 116 elf->ed_phflags &= ~ELF_F_DIRTY; 117 elf->ed_phdr = 0; 118 ((Ehdr*)elf->ed_ehdr)->e_phnum = 0; 119 ((Ehdr*)elf->ed_ehdr)->e_phentsize = 0; 120 elf->ed_phdrsz = 0; 121 ELFUNLOCK(elf) 122 return (0); 123 } 124 125 elf->ed_myflags |= EDF_PHALLOC; 126 (void) memset(ph, 0, sz); 127 elf->ed_phflags |= ELF_F_DIRTY; 128 /* LINTED */ 129 ((Ehdr*)elf->ed_ehdr)->e_phnum = (Half)count; 130 ((Ehdr*)elf->ed_ehdr)->e_phentsize 131 /* LINTED */ 132 = (Half)elf_fsize(ELF_T_PHDR, 1, work); 133 elf->ed_phdrsz = sz; 134 elf->ed_phdr = rc = ph; 135 136 ELFUNLOCK(elf) 137 return (rc); 138 } 139