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 */
31 * This stuff used to live in cook.c, but was moved out to
32 * facilitate dual (Elf32 and Elf64) compilation. See block
33 * comment in cook.c for more info.
40 #include <sys/sysmacros.h>
46 * This module is compiled twice, the second time having
47 * -D_ELF64 defined. The following set of macros, along
48 * with machelf.h, represent the differences between the
49 * two compilations. Be careful *not* to add any class-
50 * dependent code (anything that has elf32 or elf64 in the
51 * name) to this code without hiding it behind a switch-
52 * able macro like these.
56 #define ELFCLASS ELFCLASS64
57 #define ElfField Elf64
58 #define _elf_snode_init _elf64_snode_init
59 #define _elf_prepscan _elf64_prepscan
60 #define _elf_cookscn _elf64_cookscn
61 #define _elf_mtype _elf64_mtype
62 #define _elf_msize _elf64_msize
63 #define elf_fsize elf64_fsize
64 #define _elf_snode _elf64_snode
65 #define _elf_ehdr _elf64_ehdr
66 #define elf_xlatetom elf64_xlatetom
67 #define _elf_phdr _elf64_phdr
68 #define _elf_shdr _elf64_shdr
69 #define _elf_prepscn _elf64_prepscn
73 #define ELFCLASS ELFCLASS32
74 #define ElfField Elf32
75 #define _elf_snode_init _elf32_snode_init
76 #define _elf_prepscan _elf32_prepscan
77 #define _elf_cookscn _elf32_cookscn
78 #define _elf_mtype _elf32_mtype
79 #define _elf_msize _elf32_msize
80 #define elf_fsize elf32_fsize
81 #define _elf_snode _elf32_snode
82 #define _elf_ehdr _elf32_ehdr
83 #define elf_xlatetom elf32_xlatetom
84 #define _elf_phdr _elf32_phdr
85 #define _elf_shdr _elf32_shdr
86 #define _elf_prepscn _elf32_prepscn
92 _elf_prepscn(Elf
*elf
, size_t cnt
)
100 if ((s
= malloc(cnt
* sizeof (Elf_Scn
))) == 0) {
101 _elf_seterr(EMEM_SCN
, errno
);
104 elf
->ed_scntabsz
= cnt
;
108 *s
= _elf_snode_init
.sb_scn
;
111 s
->s_index
= s
- elf
->ed_hdscn
;
112 s
->s_shdr
= (Shdr
*)s
->s_elf
->ed_shdr
+ s
->s_index
;
113 ELFMUTEXINIT(&s
->s_mutex
);
116 * Section has not yet been cooked!
118 * We don't cook a section until it's data is actually
128 * Section index SHN_UNDEF (0) does not and cannot
129 * have a data buffer. Fix it here. Also mark the
130 * initial section as being allocated for the block
134 s
->s_myflags
= SF_ALLOC
;
142 _elf_cookscn(Elf_Scn
* s
)
146 register Dnode
* d
= &s
->s_dnode
;
150 s
->s_hdnode
= s
->s_tlnode
= d
;
157 * Prepare d_data for inspection, but don't actually
158 * translate data until needed. Leave the READY
159 * flag off. NOBITS sections see zero size.
165 d
->db_off
= sh
->sh_offset
;
166 d
->db_data
.d_align
= sh
->sh_addralign
;
167 d
->db_data
.d_version
= elf
->ed_version
;
168 ELFACCESSDATA(work
, _elf_work
)
169 d
->db_data
.d_type
= _elf_mtype(elf
, sh
->sh_type
, work
);
170 d
->db_data
.d_buf
= 0;
171 d
->db_data
.d_off
= 0;
172 fsz
= elf_fsize(d
->db_data
.d_type
, 1, elf
->ed_version
);
173 msz
= _elf_msize(d
->db_data
.d_type
, elf
->ed_version
);
174 d
->db_data
.d_size
= MAX(sh
->sh_size
, (sh
->sh_size
/ fsz
) * msz
);
175 d
->db_shsz
= sh
->sh_size
;
182 if (sh
->sh_type
!= SHT_NOBITS
)
183 d
->db_fsz
= sh
->sh_size
;
187 s
->s_myflags
|= SF_READY
;
199 if ((s
= malloc(sizeof (Snode
))) == 0) {
200 _elf_seterr(EMEM_SNODE
, errno
);
203 *s
= _elf_snode_init
;
204 ELFMUTEXINIT(&s
->sb_scn
.s_mutex
);
205 s
->sb_scn
.s_myflags
= SF_ALLOC
| SF_READY
;
206 s
->sb_scn
.s_shdr
= &s
->sb_shdr
;
213 _elf_ehdr(Elf
* elf
, int inplace
)
215 register size_t fsz
; /* field size */
218 fsz
= elf_fsize(ELF_T_EHDR
, 1, elf
->ed_version
);
219 if (fsz
> elf
->ed_fsz
) {
220 _elf_seterr(EFMT_EHDRSZ
, 0);
223 if (inplace
&& (fsz
>= sizeof (Ehdr
))) {
225 * The translated Ehdr will fit over the original Ehdr.
228 elf
->ed_ehdr
= (Ehdr
*)elf
->ed_ident
;
229 elf
->ed_status
= ES_COOKED
;
231 elf
->ed_ehdr
= malloc(sizeof (Ehdr
));
232 if (elf
->ed_ehdr
== 0) {
233 _elf_seterr(EMEM_EHDR
, errno
);
236 elf
->ed_myflags
|= EDF_EHALLOC
;
240 * Memory size >= fsz, because otherwise the memory version
241 * loses information and cannot accurately implement the
245 src
.d_buf
= (Elf_Void
*)elf
->ed_ident
;
246 src
.d_type
= ELF_T_EHDR
;
248 src
.d_version
= elf
->ed_version
;
249 dst
.d_buf
= (Elf_Void
*)elf
->ed_ehdr
;
250 dst
.d_size
= sizeof (Ehdr
);
251 dst
.d_version
= EV_CURRENT
;
253 if ((_elf_vm(elf
, (size_t)0, fsz
) != OK_YES
) ||
254 (elf_xlatetom(&dst
, &src
, elf
->ed_encode
) == 0)) {
255 if (elf
->ed_myflags
& EDF_EHALLOC
) {
256 elf
->ed_myflags
&= ~EDF_EHALLOC
;
263 if (((Ehdr
*)elf
->ed_ehdr
)->e_ident
[EI_CLASS
] != ELFCLASS
) {
264 _elf_seterr(EREQ_CLASS
, 0);
265 if (elf
->ed_myflags
& EDF_EHALLOC
) {
266 elf
->ed_myflags
&= ~EDF_EHALLOC
;
273 if (((Ehdr
*)elf
->ed_ehdr
)->e_version
!= elf
->ed_version
) {
274 _elf_seterr(EFMT_VER2
, 0);
275 if (elf
->ed_myflags
& EDF_EHALLOC
) {
276 elf
->ed_myflags
&= ~EDF_EHALLOC
;
289 _elf_phdr(Elf
* elf
, int inplace
)
291 register size_t fsz
, msz
;
293 Ehdr
* eh
= elf
->ed_ehdr
; /* must be present */
296 if (eh
->e_phnum
== 0)
299 fsz
= elf_fsize(ELF_T_PHDR
, 1, elf
->ed_version
);
300 if (eh
->e_phentsize
!= fsz
) {
301 _elf_seterr(EFMT_PHDRSZ
, 0);
306 ELFACCESSDATA(work
, _elf_work
)
307 msz
= _elf_msize(ELF_T_PHDR
, work
) * eh
->e_phnum
;
308 if ((eh
->e_phoff
== 0) ||
309 (elf
->ed_fsz
<= eh
->e_phoff
) ||
310 (elf
->ed_fsz
- eh
->e_phoff
< fsz
)) {
311 _elf_seterr(EFMT_PHTAB
, 0);
315 if (inplace
&& fsz
>= msz
&& eh
->e_phoff
% sizeof (ElfField
) == 0) {
316 elf
->ed_phdr
= (Elf_Void
*)(elf
->ed_ident
+ eh
->e_phoff
);
317 elf
->ed_status
= ES_COOKED
;
319 if ((elf
->ed_phdr
= malloc(msz
)) == 0) {
320 _elf_seterr(EMEM_PHDR
, errno
);
323 elf
->ed_myflags
|= EDF_PHALLOC
;
325 src
.d_buf
= (Elf_Void
*)(elf
->ed_ident
+ eh
->e_phoff
);
326 src
.d_type
= ELF_T_PHDR
;
328 src
.d_version
= elf
->ed_version
;
329 dst
.d_buf
= elf
->ed_phdr
;
331 dst
.d_version
= work
;
332 if ((_elf_vm(elf
, (size_t)eh
->e_phoff
, fsz
) != OK_YES
) ||
333 (elf_xlatetom(&dst
, &src
, elf
->ed_encode
) == 0)) {
334 if (elf
->ed_myflags
& EDF_PHALLOC
) {
335 elf
->ed_myflags
&= ~EDF_PHALLOC
;
341 elf
->ed_phdrsz
= msz
;
348 _elf_shdr(Elf
* elf
, int inplace
)
350 register size_t fsz
, msz
;
353 register Ehdr
*eh
= elf
->ed_ehdr
; /* must be present */
355 if ((eh
->e_shnum
== 0) && (eh
->e_shoff
== 0))
358 fsz
= elf_fsize(ELF_T_SHDR
, 1, elf
->ed_version
);
359 if (eh
->e_shentsize
!= fsz
) {
360 _elf_seterr(EFMT_SHDRSZ
, 0);
364 * If we are dealing with a file with 'extended section
365 * indexes' - then we need to load the first section
366 * header. The actual section count is stored in
369 if ((scncnt
= eh
->e_shnum
) == 0) {
371 if ((eh
->e_shoff
== 0) ||
372 (elf
->ed_fsz
<= eh
->e_shoff
) ||
373 (elf
->ed_fsz
- eh
->e_shoff
< fsz
)) {
374 _elf_seterr(EFMT_SHTAB
, 0);
377 src
.d_buf
= (Elf_Void
*)(elf
->ed_ident
+ eh
->e_shoff
);
378 src
.d_type
= ELF_T_SHDR
;
380 src
.d_version
= elf
->ed_version
;
381 dst
.d_buf
= (Elf_Void
*)&sh
;
382 dst
.d_size
= sizeof (Shdr
);
383 dst
.d_version
= EV_CURRENT
;
384 if ((_elf_vm(elf
, (size_t)eh
->e_shoff
, fsz
) != OK_YES
) ||
385 (elf_xlatetom(&dst
, &src
, elf
->ed_encode
) == 0)) {
392 msz
= scncnt
* sizeof (Shdr
);
393 if ((eh
->e_shoff
== 0) ||
394 (elf
->ed_fsz
<= eh
->e_shoff
) ||
395 (elf
->ed_fsz
- eh
->e_shoff
< fsz
)) {
396 _elf_seterr(EFMT_SHTAB
, 0);
400 if (inplace
&& (fsz
>= msz
) &&
401 ((eh
->e_shoff
% sizeof (ElfField
)) == 0)) {
403 elf
->ed_shdr
= (Shdr
*)(elf
->ed_ident
+ eh
->e_shoff
);
404 elf
->ed_status
= ES_COOKED
;
406 if ((elf
->ed_shdr
= malloc(msz
)) == 0) {
407 _elf_seterr(EMEM_SHDR
, errno
);
410 elf
->ed_myflags
|= EDF_SHALLOC
;
412 src
.d_buf
= (Elf_Void
*)(elf
->ed_ident
+ eh
->e_shoff
);
413 src
.d_type
= ELF_T_SHDR
;
415 src
.d_version
= elf
->ed_version
;
416 dst
.d_buf
= (Elf_Void
*)elf
->ed_shdr
;
418 dst
.d_version
= EV_CURRENT
;
419 if ((_elf_vm(elf
, (size_t)eh
->e_shoff
, fsz
) != OK_YES
) ||
420 (elf_xlatetom(&dst
, &src
, elf
->ed_encode
) == 0) ||
421 (_elf_prepscn(elf
, scncnt
) != OK_YES
)) {
422 if (elf
->ed_myflags
& EDF_SHALLOC
) {
423 elf
->ed_myflags
&= ~EDF_SHALLOC
;