1 /* $NetBSD: libelf_ehdr.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
4 * Copyright (c) 2006,2008 Joseph Koshy
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #if HAVE_NBTOOL_CONFIG_H
30 # include "nbtool_config.h"
33 #include <sys/cdefs.h>
42 __RCSID("$NetBSD: libelf_ehdr.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
43 ELFTC_VCSID("Id: libelf_ehdr.c 2225 2011-11-26 18:55:54Z jkoshy ");
46 * Retrieve counts for sections, phdrs and the section string table index
47 * from section header #0 of the ELF object.
50 _libelf_load_extended(Elf
*e
, int ec
, uint64_t shoff
, uint16_t phnum
,
55 int (*xlator
)(char *_d
, size_t _dsz
, char *_s
, size_t _c
, int _swap
);
58 assert(STAILQ_EMPTY(&e
->e_u
.e_elf
.e_scn
));
60 fsz
= _libelf_fsize(ELF_T_SHDR
, ec
, e
->e_version
, 1);
63 if (e
->e_rawsize
< shoff
+ fsz
) { /* raw file too small */
64 LIBELF_SET_ERROR(HEADER
, 0);
68 if ((scn
= _libelf_allocate_scn(e
, (size_t) 0)) == NULL
)
71 if (shoff
> SSIZE_MAX
) {
72 LIBELF_SET_ERROR(HEADER
, 0);
76 xlator
= _libelf_get_translator(ELF_T_SHDR
, ELF_TOMEMORY
, ec
);
77 (*xlator
)((void *) &scn
->s_shdr
, sizeof(scn
->s_shdr
),
78 e
->e_rawfile
+ shoff
, (size_t) 1,
79 e
->e_byteorder
!= _libelf_host_byteorder());
81 #define GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \
82 scn->s_shdr.s_shdr64.M)
84 if (GET_SHDR_MEMBER(sh_size
) > UINT_MAX
) {
85 LIBELF_SET_ERROR(HEADER
, 0);
89 if ((shtype
= GET_SHDR_MEMBER(sh_type
)) != SHT_NULL
) {
90 LIBELF_SET_ERROR(SECTION
, 0);
94 e
->e_u
.e_elf
.e_nscn
= (unsigned int)GET_SHDR_MEMBER(sh_size
);
95 e
->e_u
.e_elf
.e_nphdr
= (phnum
!= PN_XNUM
) ? phnum
:
96 GET_SHDR_MEMBER(sh_info
);
97 e
->e_u
.e_elf
.e_strndx
= (strndx
!= SHN_XINDEX
) ? strndx
:
98 GET_SHDR_MEMBER(sh_link
);
99 #undef GET_SHDR_MEMBER
104 #define EHDR_INIT(E,SZ) do { \
105 Elf##SZ##_Ehdr *eh = (E); \
106 eh->e_ident[EI_MAG0] = ELFMAG0; \
107 eh->e_ident[EI_MAG1] = ELFMAG1; \
108 eh->e_ident[EI_MAG2] = ELFMAG2; \
109 eh->e_ident[EI_MAG3] = ELFMAG3; \
110 eh->e_ident[EI_CLASS] = ELFCLASS##SZ; \
111 eh->e_ident[EI_DATA] = ELFDATANONE; \
112 eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version); \
113 eh->e_machine = EM_NONE; \
114 eh->e_type = ELF_K_NONE; \
115 eh->e_version = LIBELF_PRIVATE(version); \
116 } while (/*CONSTCOND*/0)
119 _libelf_ehdr(Elf
*e
, int ec
, int allocate
)
123 uint16_t phnum
, shnum
, strndx
;
125 int (*xlator
)(char *_d
, size_t _dsz
, char *_s
, size_t _c
, int _swap
);
127 assert(ec
== ELFCLASS32
|| ec
== ELFCLASS64
);
129 if (e
== NULL
|| e
->e_kind
!= ELF_K_ELF
) {
130 LIBELF_SET_ERROR(ARGUMENT
, 0);
134 if (e
->e_class
!= ELFCLASSNONE
&& e
->e_class
!= ec
) {
135 LIBELF_SET_ERROR(CLASS
, 0);
139 if (e
->e_version
!= EV_CURRENT
) {
140 LIBELF_SET_ERROR(VERSION
, 0);
144 if (e
->e_class
== ELFCLASSNONE
)
147 if (ec
== ELFCLASS32
)
148 ehdr
= (void *) e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
;
150 ehdr
= (void *) e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
;
152 if (ehdr
!= NULL
) /* already have a translated ehdr */
155 fsz
= _libelf_fsize(ELF_T_EHDR
, ec
, e
->e_version
, (size_t) 1);
158 if (e
->e_cmd
!= ELF_C_WRITE
&& e
->e_rawsize
< fsz
) {
159 LIBELF_SET_ERROR(HEADER
, 0);
163 msz
= _libelf_msize(ELF_T_EHDR
, ec
, EV_CURRENT
);
167 if ((ehdr
= calloc((size_t) 1, msz
)) == NULL
) {
168 LIBELF_SET_ERROR(RESOURCE
, 0);
172 if (ec
== ELFCLASS32
) {
173 e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
= ehdr
;
176 e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
= ehdr
;
181 e
->e_flags
|= ELF_F_DIRTY
;
183 if (e
->e_cmd
== ELF_C_WRITE
)
186 xlator
= _libelf_get_translator(ELF_T_EHDR
, ELF_TOMEMORY
, ec
);
187 (*xlator
)(ehdr
, msz
, e
->e_rawfile
, (size_t) 1,
188 e
->e_byteorder
!= _libelf_host_byteorder());
191 * If extended numbering is being used, read the correct
192 * number of sections and program header entries.
194 if (ec
== ELFCLASS32
) {
195 phnum
= ((Elf32_Ehdr
*) ehdr
)->e_phnum
;
196 shnum
= ((Elf32_Ehdr
*) ehdr
)->e_shnum
;
197 shoff
= ((Elf32_Ehdr
*) ehdr
)->e_shoff
;
198 strndx
= ((Elf32_Ehdr
*) ehdr
)->e_shstrndx
;
200 phnum
= ((Elf64_Ehdr
*) ehdr
)->e_phnum
;
201 shnum
= ((Elf64_Ehdr
*) ehdr
)->e_shnum
;
202 shoff
= ((Elf64_Ehdr
*) ehdr
)->e_shoff
;
203 strndx
= ((Elf64_Ehdr
*) ehdr
)->e_shstrndx
;
206 if (shnum
>= SHN_LORESERVE
||
207 (shoff
== 0LL && (shnum
!= 0 || phnum
== PN_XNUM
||
208 strndx
== SHN_XINDEX
))) {
209 LIBELF_SET_ERROR(HEADER
, 0);
213 if (shnum
!= 0 || shoff
== 0LL) { /* not using extended numbering */
214 e
->e_u
.e_elf
.e_nphdr
= phnum
;
215 e
->e_u
.e_elf
.e_nscn
= shnum
;
216 e
->e_u
.e_elf
.e_strndx
= strndx
;
217 } else if (_libelf_load_extended(e
, ec
, shoff
, phnum
, strndx
) == 0)