1 /* $NetBSD: elf_data.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
4 * Copyright (c) 2006,2008,2011 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"
40 __RCSID("$NetBSD: elf_data.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
41 ELFTC_VCSID("Id: elf_data.c 2921 2013-03-04 16:19:22Z jkoshy ");
44 elf_getdata(Elf_Scn
*s
, Elf_Data
*ed
)
48 int elfclass
, elftype
;
49 size_t fsz
, msz
, count
;
50 struct _Libelf_Data
*d
;
51 uint64_t sh_align
, sh_offset
, sh_size
;
52 int (*xlate
)(char *_d
, size_t _dsz
, char *_s
, size_t _c
, int _swap
);
54 d
= (struct _Libelf_Data
*) ed
;
56 if (s
== NULL
|| (e
= s
->s_elf
) == NULL
||
57 (d
!= NULL
&& s
!= d
->d_scn
)) {
58 LIBELF_SET_ERROR(ARGUMENT
, 0);
62 assert(e
->e_kind
== ELF_K_ELF
);
64 if (d
== NULL
&& (d
= STAILQ_FIRST(&s
->s_data
)) != NULL
)
68 return (&STAILQ_NEXT(d
, d_next
)->d_data
);
70 if (e
->e_rawfile
== NULL
) {
72 * In the ELF_C_WRITE case, there is no source that
73 * can provide data for the section.
75 LIBELF_SET_ERROR(ARGUMENT
, 0);
79 elfclass
= e
->e_class
;
81 assert(elfclass
== ELFCLASS32
|| elfclass
== ELFCLASS64
);
83 if (elfclass
== ELFCLASS32
) {
84 sh_type
= s
->s_shdr
.s_shdr32
.sh_type
;
85 sh_offset
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_offset
;
86 sh_size
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_size
;
87 sh_align
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_addralign
;
89 sh_type
= s
->s_shdr
.s_shdr64
.sh_type
;
90 sh_offset
= s
->s_shdr
.s_shdr64
.sh_offset
;
91 sh_size
= s
->s_shdr
.s_shdr64
.sh_size
;
92 sh_align
= s
->s_shdr
.s_shdr64
.sh_addralign
;
95 if (sh_type
== SHT_NULL
) {
96 LIBELF_SET_ERROR(SECTION
, 0);
100 if ((elftype
= _libelf_xlate_shtype(sh_type
)) < ELF_T_FIRST
||
101 elftype
> ELF_T_LAST
|| (sh_type
!= SHT_NOBITS
&&
102 sh_offset
+ sh_size
> (uint64_t) e
->e_rawsize
)) {
103 LIBELF_SET_ERROR(SECTION
, 0);
107 if ((fsz
= (elfclass
== ELFCLASS32
? elf32_fsize
: elf64_fsize
)
108 (elftype
, (size_t) 1, e
->e_version
)) == 0) {
109 LIBELF_SET_ERROR(UNIMPL
, 0);
114 LIBELF_SET_ERROR(SECTION
, 0);
118 count
= sh_size
/ fsz
;
120 msz
= _libelf_msize(elftype
, elfclass
, e
->e_version
);
124 if ((d
= _libelf_allocate_data(s
)) == NULL
)
127 d
->d_data
.d_buf
= NULL
;
129 d
->d_data
.d_align
= sh_align
;
130 d
->d_data
.d_size
= msz
* count
;
131 d
->d_data
.d_type
= elftype
;
132 d
->d_data
.d_version
= e
->e_version
;
134 if (sh_type
== SHT_NOBITS
|| sh_size
== 0) {
135 STAILQ_INSERT_TAIL(&s
->s_data
, d
, d_next
);
139 if ((d
->d_data
.d_buf
= malloc(msz
*count
)) == NULL
) {
140 (void) _libelf_release_data(d
);
141 LIBELF_SET_ERROR(RESOURCE
, 0);
145 d
->d_flags
|= LIBELF_F_DATA_MALLOCED
;
147 xlate
= _libelf_get_translator(elftype
, ELF_TOMEMORY
, elfclass
);
148 if (!(*xlate
)(d
->d_data
.d_buf
, d
->d_data
.d_size
,
149 e
->e_rawfile
+ sh_offset
, count
,
150 e
->e_byteorder
!= _libelf_host_byteorder())) {
151 _libelf_release_data(d
);
152 LIBELF_SET_ERROR(DATA
, 0);
156 STAILQ_INSERT_TAIL(&s
->s_data
, d
, d_next
);
162 elf_newdata(Elf_Scn
*s
)
165 struct _Libelf_Data
*d
;
167 if (s
== NULL
|| (e
= s
->s_elf
) == NULL
) {
168 LIBELF_SET_ERROR(ARGUMENT
, 0);
172 assert(e
->e_kind
== ELF_K_ELF
);
175 * elf_newdata() has to append a data descriptor, so
176 * bring in existing section data if not already present.
178 if (e
->e_rawfile
&& s
->s_size
> 0 && STAILQ_EMPTY(&s
->s_data
))
179 if (elf_getdata(s
, NULL
) == NULL
)
182 if ((d
= _libelf_allocate_data(s
)) == NULL
)
185 STAILQ_INSERT_TAIL(&s
->s_data
, d
, d_next
);
187 d
->d_data
.d_align
= 1;
188 d
->d_data
.d_buf
= NULL
;
189 d
->d_data
.d_off
= (uint64_t) ~0;
190 d
->d_data
.d_size
= 0;
191 d
->d_data
.d_type
= ELF_T_BYTE
;
192 d
->d_data
.d_version
= LIBELF_PRIVATE(version
);
194 (void) elf_flagscn(s
, ELF_C_SET
, ELF_F_DIRTY
);
200 * Retrieve a data descriptor for raw (untranslated) data for section
205 elf_rawdata(Elf_Scn
*s
, Elf_Data
*ed
)
210 struct _Libelf_Data
*d
;
211 uint64_t sh_align
, sh_offset
, sh_size
;
213 if (s
== NULL
|| (e
= s
->s_elf
) == NULL
|| e
->e_rawfile
== NULL
) {
214 LIBELF_SET_ERROR(ARGUMENT
, 0);
218 assert(e
->e_kind
== ELF_K_ELF
);
220 d
= (struct _Libelf_Data
*) ed
;
222 if (d
== NULL
&& (d
= STAILQ_FIRST(&s
->s_rawdata
)) != NULL
)
226 return (&STAILQ_NEXT(d
, d_next
)->d_data
);
228 elf_class
= e
->e_class
;
230 assert(elf_class
== ELFCLASS32
|| elf_class
== ELFCLASS64
);
232 if (elf_class
== ELFCLASS32
) {
233 sh_type
= s
->s_shdr
.s_shdr32
.sh_type
;
234 sh_offset
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_offset
;
235 sh_size
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_size
;
236 sh_align
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_addralign
;
238 sh_type
= s
->s_shdr
.s_shdr64
.sh_type
;
239 sh_offset
= s
->s_shdr
.s_shdr64
.sh_offset
;
240 sh_size
= s
->s_shdr
.s_shdr64
.sh_size
;
241 sh_align
= s
->s_shdr
.s_shdr64
.sh_addralign
;
244 if (sh_type
== SHT_NULL
) {
245 LIBELF_SET_ERROR(SECTION
, 0);
249 if ((d
= _libelf_allocate_data(s
)) == NULL
)
252 d
->d_data
.d_buf
= (sh_type
== SHT_NOBITS
|| sh_size
== 0) ? NULL
:
253 e
->e_rawfile
+ sh_offset
;
255 d
->d_data
.d_align
= sh_align
;
256 d
->d_data
.d_size
= sh_size
;
257 d
->d_data
.d_type
= ELF_T_BYTE
;
258 d
->d_data
.d_version
= e
->e_version
;
260 STAILQ_INSERT_TAIL(&s
->s_rawdata
, d
, d_next
);