2 * Copyright (c) 2006,2008 Joseph Koshy
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/lib/libelf/libelf_ehdr.c,v 1.2 2006/12/25 02:22:22 jkoshy Exp $
29 #include <sys/cdefs.h>
41 * Retrieve counts for sections, phdrs and the section string table index
42 * from section header #0 of the ELF object.
45 _libelf_load_extended(Elf
*e
, int ec
, uint64_t shoff
, uint16_t phnum
,
50 int (*xlator
)(char *_d
, size_t _dsz
, char *_s
, size_t _c
, int _swap
);
53 assert(STAILQ_EMPTY(&e
->e_u
.e_elf
.e_scn
));
55 fsz
= _libelf_fsize(ELF_T_SHDR
, ec
, e
->e_version
, 1);
58 if (e
->e_rawsize
< shoff
+ fsz
) { /* raw file too small */
59 LIBELF_SET_ERROR(HEADER
, 0);
63 if ((scn
= _libelf_allocate_scn(e
, (size_t) 0)) == NULL
)
66 xlator
= _libelf_get_translator(ELF_T_SHDR
, ELF_TOMEMORY
, ec
);
67 (*xlator
)((char *) &scn
->s_shdr
, sizeof(scn
->s_shdr
),
68 e
->e_rawfile
+ shoff
, (size_t) 1,
69 e
->e_byteorder
!= LIBELF_PRIVATE(byteorder
));
71 #define GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \
72 scn->s_shdr.s_shdr64.M)
74 if ((shtype
= GET_SHDR_MEMBER(sh_type
)) != SHT_NULL
) {
75 LIBELF_SET_ERROR(SECTION
, 0);
79 e
->e_u
.e_elf
.e_nscn
= GET_SHDR_MEMBER(sh_size
);
80 e
->e_u
.e_elf
.e_nphdr
= (phnum
!= PN_XNUM
) ? phnum
:
81 GET_SHDR_MEMBER(sh_info
);
82 e
->e_u
.e_elf
.e_strndx
= (strndx
!= SHN_XINDEX
) ? strndx
:
83 GET_SHDR_MEMBER(sh_link
);
84 #undef GET_SHDR_MEMBER
89 #define EHDR_INIT(E,SZ) do { \
90 Elf##SZ##_Ehdr *eh = (E); \
91 eh->e_ident[EI_MAG0] = ELFMAG0; \
92 eh->e_ident[EI_MAG1] = ELFMAG1; \
93 eh->e_ident[EI_MAG2] = ELFMAG2; \
94 eh->e_ident[EI_MAG3] = ELFMAG3; \
95 eh->e_ident[EI_CLASS] = ELFCLASS##SZ; \
96 eh->e_ident[EI_DATA] = ELFDATANONE; \
97 eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version); \
98 eh->e_machine = EM_NONE; \
99 eh->e_type = ELF_K_NONE; \
100 eh->e_version = LIBELF_PRIVATE(version); \
104 _libelf_ehdr(Elf
*e
, int ec
, int allocate
)
108 uint16_t phnum
, shnum
, strndx
;
110 int (*xlator
)(char *_d
, size_t _dsz
, char *_s
, size_t _c
, int _swap
);
112 assert(ec
== ELFCLASS32
|| ec
== ELFCLASS64
);
114 if (e
== NULL
|| e
->e_kind
!= ELF_K_ELF
) {
115 LIBELF_SET_ERROR(ARGUMENT
, 0);
119 if (e
->e_class
!= ELFCLASSNONE
&& e
->e_class
!= ec
) {
120 LIBELF_SET_ERROR(CLASS
, 0);
124 if (e
->e_version
!= EV_CURRENT
) {
125 LIBELF_SET_ERROR(VERSION
, 0);
129 if (e
->e_class
== ELFCLASSNONE
)
132 if (ec
== ELFCLASS32
)
133 ehdr
= (void *) e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
;
135 ehdr
= (void *) e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
;
137 if (ehdr
!= NULL
) /* already have a translated ehdr */
140 fsz
= _libelf_fsize(ELF_T_EHDR
, ec
, e
->e_version
, (size_t) 1);
143 if (e
->e_cmd
!= ELF_C_WRITE
&& e
->e_rawsize
< fsz
) {
144 LIBELF_SET_ERROR(HEADER
, 0);
148 msz
= _libelf_msize(ELF_T_EHDR
, ec
, EV_CURRENT
);
152 if ((ehdr
= calloc((size_t) 1, msz
)) == NULL
) {
153 LIBELF_SET_ERROR(RESOURCE
, 0);
157 if (ec
== ELFCLASS32
) {
158 e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
= ehdr
;
161 e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
= ehdr
;
166 e
->e_flags
|= ELF_F_DIRTY
;
168 if (e
->e_cmd
== ELF_C_WRITE
)
171 xlator
= _libelf_get_translator(ELF_T_EHDR
, ELF_TOMEMORY
, ec
);
172 (*xlator
)(ehdr
, msz
, e
->e_rawfile
, (size_t) 1,
173 e
->e_byteorder
!= LIBELF_PRIVATE(byteorder
));
176 * If extended numbering is being used, read the correct
177 * number of sections and program header entries.
179 if (ec
== ELFCLASS32
) {
180 phnum
= ((Elf32_Ehdr
*) ehdr
)->e_phnum
;
181 shnum
= ((Elf32_Ehdr
*) ehdr
)->e_shnum
;
182 shoff
= ((Elf32_Ehdr
*) ehdr
)->e_shoff
;
183 strndx
= ((Elf32_Ehdr
*) ehdr
)->e_shstrndx
;
185 phnum
= ((Elf64_Ehdr
*) ehdr
)->e_phnum
;
186 shnum
= ((Elf64_Ehdr
*) ehdr
)->e_shnum
;
187 shoff
= ((Elf64_Ehdr
*) ehdr
)->e_shoff
;
188 strndx
= ((Elf64_Ehdr
*) ehdr
)->e_shstrndx
;
191 if (shnum
>= SHN_LORESERVE
||
192 (shoff
== 0LL && (shnum
!= 0 || phnum
== PN_XNUM
||
193 strndx
== SHN_XINDEX
))) {
194 LIBELF_SET_ERROR(HEADER
, 0);
198 if (shnum
!= 0 || shoff
== 0LL) { /* not using extended numbering */
199 e
->e_u
.e_elf
.e_nphdr
= phnum
;
200 e
->e_u
.e_elf
.e_nscn
= shnum
;
201 e
->e_u
.e_elf
.e_strndx
= strndx
;
202 } else if (_libelf_load_extended(e
, ec
, shoff
, phnum
, strndx
) == 0)