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 *
elf_newphdr(Elf * elf,size_t count)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