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