2 * Copyright (c) 2006,2008,2011 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
37 elf_getdata(Elf_Scn
*s
, Elf_Data
*d
)
40 size_t fsz
, msz
, count
;
41 int elfclass
, elftype
;
43 uint64_t sh_align
, sh_offset
, sh_size
;
44 int (*xlate
)(char *_d
, size_t _dsz
, char *_s
, size_t _c
, int _swap
);
46 if (s
== NULL
|| (e
= s
->s_elf
) == NULL
||
47 (d
!= NULL
&& s
!= d
->d_scn
)) {
48 LIBELF_SET_ERROR(ARGUMENT
, 0);
52 assert(e
->e_kind
== ELF_K_ELF
);
54 if (d
== NULL
&& (d
= STAILQ_FIRST(&s
->s_data
)) != NULL
)
58 return (STAILQ_NEXT(d
, d_next
));
60 if (e
->e_rawfile
== NULL
) {
61 LIBELF_SET_ERROR(ARGUMENT
, 0);
65 elfclass
= e
->e_class
;
67 assert(elfclass
== ELFCLASS32
|| elfclass
== ELFCLASS64
);
69 if (elfclass
== ELFCLASS32
) {
70 sh_type
= s
->s_shdr
.s_shdr32
.sh_type
;
71 sh_offset
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_offset
;
72 sh_size
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_size
;
73 sh_align
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_addralign
;
75 sh_type
= s
->s_shdr
.s_shdr64
.sh_type
;
76 sh_offset
= s
->s_shdr
.s_shdr64
.sh_offset
;
77 sh_size
= s
->s_shdr
.s_shdr64
.sh_size
;
78 sh_align
= s
->s_shdr
.s_shdr64
.sh_addralign
;
81 if (sh_type
== SHT_NULL
)
84 if ((elftype
= _libelf_xlate_shtype(sh_type
)) < ELF_T_FIRST
||
85 elftype
> ELF_T_LAST
|| (sh_type
!= SHT_NOBITS
&&
86 sh_offset
+ sh_size
> (uint64_t) e
->e_rawsize
)) {
87 LIBELF_SET_ERROR(SECTION
, 0);
91 if ((fsz
= (elfclass
== ELFCLASS32
? elf32_fsize
: elf64_fsize
)
92 (elftype
, (size_t) 1, e
->e_version
)) == 0) {
93 LIBELF_SET_ERROR(UNIMPL
, 0);
98 LIBELF_SET_ERROR(SECTION
, 0);
102 count
= sh_size
/ fsz
;
104 msz
= _libelf_msize(elftype
, elfclass
, e
->e_version
);
108 if ((d
= _libelf_allocate_data(s
)) == NULL
)
113 d
->d_align
= sh_align
;
114 d
->d_size
= msz
* count
;
116 d
->d_version
= e
->e_version
;
118 if (sh_type
== SHT_NOBITS
|| sh_size
== 0) {
119 STAILQ_INSERT_TAIL(&s
->s_data
, d
, d_next
);
123 if ((d
->d_buf
= malloc(msz
*count
)) == NULL
) {
124 (void) _libelf_release_data(d
);
125 LIBELF_SET_ERROR(RESOURCE
, 0);
129 d
->d_flags
|= LIBELF_F_DATA_MALLOCED
;
131 xlate
= _libelf_get_translator(elftype
, ELF_TOMEMORY
, elfclass
);
132 if (!(*xlate
)(d
->d_buf
, d
->d_size
, e
->e_rawfile
+ sh_offset
, count
,
133 e
->e_byteorder
!= LIBELF_PRIVATE(byteorder
))) {
134 _libelf_release_data(d
);
135 LIBELF_SET_ERROR(DATA
, 0);
139 STAILQ_INSERT_TAIL(&s
->s_data
, d
, d_next
);
145 elf_newdata(Elf_Scn
*s
)
150 if (s
== NULL
|| (e
= s
->s_elf
) == NULL
) {
151 LIBELF_SET_ERROR(ARGUMENT
, 0);
155 assert(e
->e_kind
== ELF_K_ELF
);
158 * elf_newdata() has to append a data descriptor, so
159 * bring in existing section data if not already present.
161 if (e
->e_rawfile
&& s
->s_size
> 0 && STAILQ_EMPTY(&s
->s_data
))
162 if (elf_getdata(s
, NULL
) == NULL
)
165 if ((d
= _libelf_allocate_data(s
)) == NULL
)
168 STAILQ_INSERT_TAIL(&s
->s_data
, d
, d_next
);
172 d
->d_off
= (uint64_t) ~0;
174 d
->d_type
= ELF_T_BYTE
;
175 d
->d_version
= LIBELF_PRIVATE(version
);
177 (void) elf_flagscn(s
, ELF_C_SET
, ELF_F_DIRTY
);
183 * Retrieve a data descriptor for raw (untranslated) data for section
188 elf_rawdata(Elf_Scn
*s
, Elf_Data
*d
)
193 uint64_t sh_align
, sh_offset
, sh_size
;
195 if (s
== NULL
|| (e
= s
->s_elf
) == NULL
|| e
->e_rawfile
== NULL
) {
196 LIBELF_SET_ERROR(ARGUMENT
, 0);
200 assert(e
->e_kind
== ELF_K_ELF
);
202 if (d
== NULL
&& (d
= STAILQ_FIRST(&s
->s_rawdata
)) != NULL
)
206 return (STAILQ_NEXT(d
, d_next
));
208 elf_class
= e
->e_class
;
210 assert(elf_class
== ELFCLASS32
|| elf_class
== ELFCLASS64
);
212 if (elf_class
== ELFCLASS32
) {
213 sh_type
= s
->s_shdr
.s_shdr32
.sh_type
;
214 sh_offset
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_offset
;
215 sh_size
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_size
;
216 sh_align
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_addralign
;
218 sh_type
= s
->s_shdr
.s_shdr64
.sh_type
;
219 sh_offset
= s
->s_shdr
.s_shdr64
.sh_offset
;
220 sh_size
= s
->s_shdr
.s_shdr64
.sh_size
;
221 sh_align
= s
->s_shdr
.s_shdr64
.sh_addralign
;
224 if (sh_type
== SHT_NULL
)
227 if ((d
= _libelf_allocate_data(s
)) == NULL
)
230 d
->d_buf
= (sh_type
== SHT_NOBITS
|| sh_size
== 0) ? NULL
:
231 e
->e_rawfile
+ sh_offset
;
233 d
->d_align
= sh_align
;
235 d
->d_type
= ELF_T_BYTE
;
236 d
->d_version
= e
->e_version
;
238 STAILQ_INSERT_TAIL(&s
->s_rawdata
, d
, d_next
);