2 * Copyright (c) 2006 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 $
37 * Retrieve counts for sections, phdrs and the section string table index
38 * from section header #0 of the ELF object.
41 _libelf_load_extended(Elf
*e
, int ec
, uint64_t shoff
, uint16_t phnum
,
46 void (*xlator
)(char *_d
, char *_s
, size_t _c
, int _swap
);
49 assert(STAILQ_EMPTY(&e
->e_u
.e_elf
.e_scn
));
51 fsz
= _libelf_fsize(ELF_T_SHDR
, ec
, e
->e_version
, 1);
54 if (e
->e_rawsize
< shoff
+ fsz
) { /* raw file too small */
55 LIBELF_SET_ERROR(HEADER
, 0);
59 if ((scn
= _libelf_allocate_scn(e
, (size_t) 0)) == NULL
)
62 xlator
= _libelf_get_translator(ELF_T_SHDR
, ELF_TOMEMORY
, ec
);
63 (*xlator
)((char *) &scn
->s_shdr
, e
->e_rawfile
+ shoff
, (size_t) 1,
64 e
->e_byteorder
!= LIBELF_PRIVATE(byteorder
));
66 #define GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \
67 scn->s_shdr.s_shdr64.M)
69 if ((shtype
= GET_SHDR_MEMBER(sh_type
)) != SHT_NULL
) {
70 LIBELF_SET_ERROR(SECTION
, 0);
74 e
->e_u
.e_elf
.e_nscn
= GET_SHDR_MEMBER(sh_size
);
75 e
->e_u
.e_elf
.e_nphdr
= (phnum
!= PN_XNUM
) ? phnum
:
76 GET_SHDR_MEMBER(sh_info
);
77 e
->e_u
.e_elf
.e_strndx
= (strndx
!= SHN_XINDEX
) ? strndx
:
78 GET_SHDR_MEMBER(sh_link
);
79 #undef GET_SHDR_MEMBER
84 #define EHDR_INIT(E,SZ) do { \
85 Elf##SZ##_Ehdr *eh = (E); \
86 eh->e_ident[EI_MAG0] = ELFMAG0; \
87 eh->e_ident[EI_MAG1] = ELFMAG1; \
88 eh->e_ident[EI_MAG2] = ELFMAG2; \
89 eh->e_ident[EI_MAG3] = ELFMAG3; \
90 eh->e_ident[EI_CLASS] = ELFCLASS##SZ; \
91 eh->e_ident[EI_DATA] = ELFDATANONE; \
92 eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version); \
93 eh->e_machine = EM_NONE; \
94 eh->e_type = ELF_K_NONE; \
95 eh->e_version = LIBELF_PRIVATE(version); \
99 _libelf_ehdr(Elf
*e
, int ec
, int allocate
)
103 uint16_t phnum
, shnum
, strndx
;
105 void (*xlator
)(char *_d
, char *_s
, size_t _c
, int _swap
);
107 assert(ec
== ELFCLASS32
|| ec
== ELFCLASS64
);
109 if (e
== NULL
|| e
->e_kind
!= ELF_K_ELF
) {
110 LIBELF_SET_ERROR(ARGUMENT
, 0);
114 if (e
->e_class
!= ELFCLASSNONE
&& e
->e_class
!= ec
) {
115 LIBELF_SET_ERROR(CLASS
, 0);
119 if (e
->e_version
!= EV_CURRENT
) {
120 LIBELF_SET_ERROR(VERSION
, 0);
124 if (e
->e_class
== ELFCLASSNONE
)
127 if (ec
== ELFCLASS32
)
128 ehdr
= (void *) e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
;
130 ehdr
= (void *) e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
;
132 if (ehdr
!= NULL
) /* already have a translated ehdr */
135 fsz
= _libelf_fsize(ELF_T_EHDR
, ec
, e
->e_version
, (size_t) 1);
138 if (e
->e_cmd
!= ELF_C_WRITE
&& e
->e_rawsize
< fsz
) {
139 LIBELF_SET_ERROR(HEADER
, 0);
143 msz
= _libelf_msize(ELF_T_EHDR
, ec
, EV_CURRENT
);
147 if ((ehdr
= calloc((size_t) 1, msz
)) == NULL
) {
148 LIBELF_SET_ERROR(RESOURCE
, 0);
152 if (ec
== ELFCLASS32
) {
153 e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
= ehdr
;
156 e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
= ehdr
;
161 e
->e_flags
|= ELF_F_DIRTY
;
163 if (e
->e_cmd
== ELF_C_WRITE
)
166 xlator
= _libelf_get_translator(ELF_T_EHDR
, ELF_TOMEMORY
, ec
);
167 (*xlator
)(ehdr
, e
->e_rawfile
, (size_t) 1,
168 e
->e_byteorder
!= LIBELF_PRIVATE(byteorder
));
171 * If extended numbering is being used, read the correct
172 * number of sections and program header entries.
174 if (ec
== ELFCLASS32
) {
175 phnum
= ((Elf32_Ehdr
*) ehdr
)->e_phnum
;
176 shnum
= ((Elf32_Ehdr
*) ehdr
)->e_shnum
;
177 shoff
= ((Elf32_Ehdr
*) ehdr
)->e_shoff
;
178 strndx
= ((Elf32_Ehdr
*) ehdr
)->e_shstrndx
;
180 phnum
= ((Elf64_Ehdr
*) ehdr
)->e_phnum
;
181 shnum
= ((Elf64_Ehdr
*) ehdr
)->e_shnum
;
182 shoff
= ((Elf64_Ehdr
*) ehdr
)->e_shoff
;
183 strndx
= ((Elf64_Ehdr
*) ehdr
)->e_shstrndx
;
186 if (shnum
>= SHN_LORESERVE
||
187 (shoff
== 0LL && (shnum
!= 0 || phnum
== PN_XNUM
||
188 strndx
== SHN_XINDEX
))) {
189 LIBELF_SET_ERROR(HEADER
, 0);
193 if (shnum
!= 0 || shoff
== 0LL) { /* not using extended numbering */
194 e
->e_u
.e_elf
.e_nphdr
= phnum
;
195 e
->e_u
.e_elf
.e_nscn
= shnum
;
196 e
->e_u
.e_elf
.e_strndx
= strndx
;
197 } else if (_libelf_load_extended(e
, ec
, shoff
, phnum
, strndx
) == 0)