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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
41 * Convert data from file format to memory format.
45 static const size_t align32
[ELF_T_NUM
] =
48 sizeof (Elf32
), /* ELF_T_ADDR */
49 sizeof (Elf32
), /* ELF_T_DYN */
50 sizeof (Elf32
), /* ELF_T_EHDR */
51 sizeof (Elf32_Half
), /* ELF_T_HALF */
52 sizeof (Elf32
), /* ELF_T_OFF */
53 sizeof (Elf32
), /* ELF_T_PHDR */
54 sizeof (Elf32
), /* ELF_T_RELA */
55 sizeof (Elf32
), /* ELF_T_REL */
56 sizeof (Elf32
), /* ELF_T_SHDR */
57 sizeof (Elf32
), /* ELF_T_SWORD */
58 sizeof (Elf32
), /* ELF_T_SYM */
59 sizeof (Elf32
), /* ELF_T_WORD */
60 sizeof (Elf32
), /* ELF_T_VERDEF */
61 sizeof (Elf32
), /* ELF_T_VERNEED */
62 sizeof (Elf64_Sxword
), /* ELF_T_SXWORD */
63 sizeof (Elf64
), /* ELF_T_XWORD */
64 sizeof (Elf32_Half
), /* ELF_T_SYMINFO */
65 sizeof (Elf32
), /* ELF_T_NOTE */
66 sizeof (Elf32_Lword
), /* ELF_T_MOVE */
67 sizeof (Elf32_Lword
), /* ELF_T_MOVEP */
68 sizeof (Elf32_Word
) /* ELF_T_CAP */
72 #define Nalign32 (sizeof (align32)/sizeof (align32[0]))
74 static const size_t align64
[ELF_T_NUM
] =
77 sizeof (Elf64
), /* ELF_T_ADDR */
78 sizeof (Elf64
), /* ELF_T_DYN */
79 sizeof (Elf64
), /* ELF_T_EHDR */
80 sizeof (Elf64_Half
), /* ELF_T_HALF */
81 sizeof (Elf64
), /* ELF_T_OFF */
82 sizeof (Elf64
), /* ELF_T_PHDR */
83 sizeof (Elf64
), /* ELF_T_RELA */
84 sizeof (Elf64
), /* ELF_T_REL */
85 sizeof (Elf64
), /* ELF_T_SHDR */
86 sizeof (Elf64_Word
), /* ELF_T_SWORD */
87 sizeof (Elf64
), /* ELF_T_SYM */
88 sizeof (Elf64_Word
), /* ELF_T_WORD */
89 sizeof (Elf64
), /* ELF_T_VDEF */
90 sizeof (Elf64
), /* ELF_T_VNEED */
91 sizeof (Elf64
), /* ELF_T_SXWORD */
92 sizeof (Elf64
), /* ELF_T_XWORD */
93 sizeof (Elf32_Half
), /* ELF_T_SYMINFO */
94 sizeof (Elf32
), /* ELF_T_NOTE */
95 sizeof (Elf64
), /* ELF_T_MOVE */
96 sizeof (Elf64
), /* ELF_T_MOVEP */
97 sizeof (Elf64_Word
) /* ELF_T_CAP */
100 #define Nalign64 (sizeof (align64)/sizeof (align64[0]))
104 * Could use an array indexed by ELFCLASS*, but I'd rather
105 * avoid .data over something this infrequently used. The
106 * next choice would be to add extra conditionals.
108 #define NALIGN(elf) ((elf->ed_class == ELFCLASS32) ? Nalign32 : Nalign64)
109 #define ALIGN(elf) ((elf->ed_class == ELFCLASS32) ? align32 : align64)
113 _elf_locked_getdata(Elf_Scn
* scn
, Elf_Data
* data
)
115 Dnode
* d
= (Dnode
*)data
;
120 assert(!elf_threaded
|| RW_LOCK_HELD(&(scn
->s_elf
->ed_rwlock
)));
121 assert(!elf_threaded
|| MUTEX_HELD(&(scn
->s_mutex
)));
124 if ((scn
->s_myflags
& SF_READY
) == 0) {
125 UPGRADELOCKS(elf
, scn
)
127 * make sure someone else didn't come along and cook
130 if ((scn
->s_myflags
& SF_READY
) == 0)
131 (void) _elf_cookscn(scn
);
132 DOWNGRADELOCKS(elf
, scn
)
140 if (scn
->s_err
!= 0) {
142 _elf_seterr((Msg
)scn
->s_err
, 0);
150 if (d
->db_scn
!= scn
) {
151 _elf_seterr(EREQ_DATA
, 0);
155 if (d
->db_myflags
& DBF_READY
) {
156 return (&d
->db_data
);
161 * Prepare return buffer. The data comes from the memory
162 * image of the file. "Empty" regions get an empty buffer.
164 * Only sections of an ELF_C_READ file can be not READY here.
165 * Furthermore, the input file must have been cooked or
166 * frozen by now. Translate cooked files in place if possible.
169 ELFACCESSDATA(work
, _elf_work
)
170 d
->db_data
.d_version
= work
;
171 if ((d
->db_off
== 0) || (d
->db_fsz
== 0)) {
172 d
->db_myflags
|= DBF_READY
;
173 return (&d
->db_data
);
176 if (elf
->ed_class
== ELFCLASS32
) {
177 Elf32_Shdr
*sh
= scn
->s_shdr
;
178 size_t sz
= sh
->sh_entsize
;
179 Elf_Type t
= d
->db_data
.d_type
;
181 if ((t
!= ELF_T_BYTE
) &&
182 (sz
> 1) && (sz
!= elf32_fsize(t
, 1, elf
->ed_version
))) {
183 _elf_seterr(EFMT_ENTSZ
, 0);
186 } else if (elf
->ed_class
== ELFCLASS64
) {
187 Elf64_Shdr
*sh
= scn
->s_shdr
;
188 Elf64_Xword sz
= sh
->sh_entsize
;
189 Elf_Type t
= d
->db_data
.d_type
;
191 if (t
!= ELF_T_BYTE
&& sz
> 1 &&
192 sz
!= elf64_fsize(t
, 1, elf
->ed_version
)) {
193 _elf_seterr(EFMT_ENTSZ
, 0);
197 _elf_seterr(EREQ_CLASS
, 0);
203 * validate the region
206 if ((d
->db_off
< 0) || (d
->db_off
>= elf
->ed_fsz
) ||
207 (elf
->ed_fsz
- d
->db_off
< d
->db_fsz
)) {
208 _elf_seterr(EFMT_DATA
, 0);
213 * set up translation buffers and validate
216 src
.d_buf
= (Elf_Void
*)(elf
->ed_ident
+ d
->db_off
);
217 src
.d_size
= d
->db_fsz
;
218 src
.d_type
= d
->db_data
.d_type
;
219 src
.d_version
= elf
->ed_version
;
221 UPGRADELOCKS(elf
, scn
)
222 if (_elf_vm(elf
, (size_t)d
->db_off
, d
->db_fsz
) != OK_YES
) {
223 DOWNGRADELOCKS(elf
, scn
)
226 DOWNGRADELOCKS(elf
, scn
)
230 * decide where to put destination
233 switch (elf
->ed_status
) {
235 if ((size_t)d
->db_data
.d_type
>= NALIGN(elf
)) {
236 _elf_seterr(EBUG_COOKTYPE
, 0);
241 * If the destination size (memory) is at least as
242 * big as the source size (file), and has the necessary
243 * alignment, reuse the space.
245 * Note that it is not sufficient to check the alignment
246 * of the offset within the object. Rather, we must check
247 * the alignment of the actual data buffer. The offset is
248 * sufficient if the file is a plain object file, which
249 * will always be mapped on a page boundary. In an archive
250 * however, the only guarantee is that the object will start
251 * on an even boundary within the archive file. The
252 * Solaris ar(1) adds padding in most (but not all cases)
253 * which minimizes this issue, but it is still important
254 * for the remaining cases that do not get padded. It also
255 * matters with archives produced by other versions of
256 * ar(1), such as the GNU version, or one from another
257 * ELF based operating system.
260 if (d
->db_data
.d_size
<= src
.d_size
) {
261 d
->db_data
.d_buf
= (Elf_Void
*)(elf
->ed_ident
+
263 if (((uintptr_t)d
->db_data
.d_buf
264 % ALIGN(elf
)[d
->db_data
.d_type
]) == 0) {
266 } else { /* Failure: Restore NULL buffer pointer */
267 d
->db_data
.d_buf
= 0;
273 if ((d
->db_buf
= malloc(d
->db_data
.d_size
)) == 0) {
274 _elf_seterr(EMEM_DATA
, errno
);
277 d
->db_data
.d_buf
= d
->db_buf
;
281 _elf_seterr(EBUG_COOKSTAT
, 0);
285 if (elf
->ed_class
== ELFCLASS32
) {
286 if (elf32_xlatetom(&d
->db_data
, &src
, elf
->ed_encode
) == 0)
288 } else { /* ELFCLASS64 */
289 if (elf64_xlatetom(&d
->db_data
, &src
, elf
->ed_encode
) == 0)
292 d
->db_myflags
|= DBF_READY
;
294 return (&d
->db_data
);
298 elf_getdata(Elf_Scn
* scn
, Elf_Data
* data
)
304 * trap null args, end of list, previous buffer.
305 * SHT_NULL sections have no buffer list, so they
313 rc
= _elf_locked_getdata(scn
, data
);
314 READUNLOCKS(elf
, scn
);