Build with dhcpcd-9.1.1
[dragonfly.git] / lib / libexecinfo / private_libelf.h
blob10b4e56fc104b4fdaca1a52b9185de568bf582ee
1 /*-
2 * Copyright (c) 2006,2008-2010 Joseph Koshy
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
24 * SUCH DAMAGE.
27 #ifndef _PRIVATE_LIBELF_H_
28 #define _PRIVATE_LIBELF_H_
30 #include <sys/param.h>
31 #include <sys/endian.h>
32 #include <sys/queue.h>
33 #include <sys/mman.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <assert.h>
37 #include <errno.h>
38 #include <limits.h>
39 #include <stddef.h>
40 #include <stdint.h>
41 #include <unistd.h>
43 /* _libelf_config.h */
44 #if defined(__DragonFly__)
45 #define LIBELF_ARCH EM_X86_64
46 #define LIBELF_BYTEORDER ELFDATA2LSB
47 #define LIBELF_CLASS ELFCLASS64
48 #endif /* __DragonFly__ */
50 /* _elftc.h */
51 #if defined(__DragonFly__)
52 #define ELFTC_BYTE_ORDER _BYTE_ORDER
53 #define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN
54 #define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN
55 #define ELFTC_HAVE_MMAP 1
56 #define STAILQ_FOREACH_SAFE STAILQ_FOREACH_MUTABLE
57 #endif
59 #if 1
60 #define _libelf_allocate_data __ei_libelf_allocate_data
61 #define _libelf_allocate_elf __ei_libelf_allocate_elf
62 #define _libelf_allocate_scn __ei_libelf_allocate_scn
63 #define _libelf_cvt_ADDR64_tom __ei_libelf_cvt_ADDR64_tom
64 #define _libelf_cvt_BYTE_tox __ei_libelf_cvt_BYTE_tox
65 #define _libelf_cvt_CAP64_tom __ei_libelf_cvt_CAP64_tom
66 #define _libelf_cvt_DYN64_tom __ei_libelf_cvt_DYN64_tom
67 #define _libelf_cvt_EHDR64_tom __ei_libelf_cvt_EHDR64_tom
68 #define _libelf_cvt_GNUHASH64_tom __ei_libelf_cvt_GNUHASH64_tom
69 #define _libelf_cvt_HALF_tom __ei_libelf_cvt_HALF_tom
70 #define _libelf_cvt_LWORD_tom __ei_libelf_cvt_LWORD_tom
71 #define _libelf_cvt_MOVE64_tom __ei_libelf_cvt_MOVE64_tom
72 #define _libelf_cvt_NOTE_tom __ei_libelf_cvt_NOTE_tom
73 #define _libelf_cvt_OFF64_tom __ei_libelf_cvt_OFF64_tom
74 #define _libelf_cvt_PHDR64_tom __ei_libelf_cvt_PHDR64_tom
75 #define _libelf_cvt_REL64_tom __ei_libelf_cvt_REL64_tom
76 #define _libelf_cvt_RELA64_tom __ei_libelf_cvt_RELA64_tom
77 #define _libelf_cvt_SHDR64_tom __ei_libelf_cvt_SHDR64_tom
78 #define _libelf_cvt_SWORD_tom __ei_libelf_cvt_SWORD_tom
79 #define _libelf_cvt_SXWORD_tom __ei_libelf_cvt_SXWORD_tom
80 #define _libelf_cvt_SYM64_tom __ei_libelf_cvt_SYM64_tom
81 #define _libelf_cvt_SYMINFO64_tom __ei_libelf_cvt_SYMINFO64_tom
82 #define _libelf_cvt_VDEF64_tom __ei_libelf_cvt_VDEF64_tom
83 #define _libelf_cvt_VNEED64_tom __ei_libelf_cvt_VNEED64_tom
84 #define _libelf_cvt_WORD_tom __ei_libelf_cvt_WORD_tom
85 #define _libelf_cvt_XWORD_tom __ei_libelf_cvt_XWORD_tom
86 #define _libelf_ehdr __ei_libelf_ehdr
87 #define _libelf_fsize __ei_libelf_fsize
88 #define _libelf_get_translator __ei_libelf_get_translator
89 #define _libelf_getshdr __ei_libelf_getshdr
90 #define _libelf_init_elf __ei_libelf_init_elf
91 #define _libelf_load_extended __ei_libelf_load_extended
92 #define _libelf_load_section_headers __ei_libelf_load_section_headers
93 #define _libelf_memory __ei_libelf_memory
94 #define _libelf_msize __ei_libelf_msize
95 #define _libelf_open_object __ei_libelf_open_object
96 #define _libelf_read_special_file __ei_libelf_read_special_file
97 #define _libelf_release_data __ei_libelf_release_data
98 #define _libelf_release_elf __ei_libelf_release_elf
99 #define _libelf_release_scn __ei_libelf_release_scn
100 #define _libelf_xlate_shtype __ei_libelf_xlate_shtype
101 #define _libelf __ei_libelf
103 #define elf64_fsize __ei_elf64_fsize
104 #define elf_getscn __ei_elf_getscn
106 #define elf_begin _ei_elf_begin
107 #define elf_end _ei_elf_end
108 #define elf_errmsg _ei_elf_errmsg
109 #define elf_errno _ei_elf_errno
110 #define elf_getdata _ei_elf_getdata
111 #define elf_nextscn _ei_elf_nextscn
112 #define elf_strptr _ei_elf_strptr
113 #define elf_version _ei_elf_version
114 #define gelf_getshdr _ei_gelf_getshdr
115 #define gelf_getsym _ei_gelf_getsym
116 #endif
118 /* elfdefinitions.h */
120 * Offsets in the `ei_ident[]` field of an ELF executable header.
122 #define _ELF_DEFINE_EI_OFFSETS() \
123 _ELF_DEFINE_EI(EI_MAG0, 0, "magic number") \
124 _ELF_DEFINE_EI(EI_MAG1, 1, "magic number") \
125 _ELF_DEFINE_EI(EI_MAG2, 2, "magic number") \
126 _ELF_DEFINE_EI(EI_MAG3, 3, "magic number") \
127 _ELF_DEFINE_EI(EI_CLASS, 4, "file class") \
128 _ELF_DEFINE_EI(EI_DATA, 5, "data encoding") \
129 _ELF_DEFINE_EI(EI_VERSION, 6, "file version") \
130 _ELF_DEFINE_EI(EI_OSABI, 7, "OS ABI kind") \
131 _ELF_DEFINE_EI(EI_ABIVERSION, 8, "OS ABI version") \
132 _ELF_DEFINE_EI(EI_PAD, 9, "padding start") \
133 _ELF_DEFINE_EI(EI_NIDENT, 16, "total size")
135 #undef _ELF_DEFINE_EI
136 #define _ELF_DEFINE_EI(N, V, DESCR) N = V ,
137 enum {
138 _ELF_DEFINE_EI_OFFSETS()
139 EI__LAST__
143 * The ELF class of an object.
145 #define _ELF_DEFINE_ELFCLASS() \
146 _ELF_DEFINE_EC(ELFCLASSNONE, 0, "Unknown ELF class") \
147 _ELF_DEFINE_EC(ELFCLASS32, 1, "32 bit objects") \
148 _ELF_DEFINE_EC(ELFCLASS64, 2, "64 bit objects")
150 #undef _ELF_DEFINE_EC
151 #define _ELF_DEFINE_EC(N, V, DESCR) N = V ,
152 enum {
153 _ELF_DEFINE_ELFCLASS()
154 EC__LAST__
158 * Endianness of data in an ELF object.
161 #define _ELF_DEFINE_ELF_DATA_ENDIANNESS() \
162 _ELF_DEFINE_ED(ELFDATANONE, 0, "Unknown data endianness") \
163 _ELF_DEFINE_ED(ELFDATA2LSB, 1, "little endian") \
164 _ELF_DEFINE_ED(ELFDATA2MSB, 2, "big endian")
166 #undef _ELF_DEFINE_ED
167 #define _ELF_DEFINE_ED(N, V, DESCR) N = V ,
168 enum {
169 _ELF_DEFINE_ELF_DATA_ENDIANNESS()
170 ED__LAST__
174 * Values of the magic numbers used in identification array.
176 #define _ELF_DEFINE_ELF_MAGIC() \
177 _ELF_DEFINE_EMAG(ELFMAG0, 0x7FU) \
178 _ELF_DEFINE_EMAG(ELFMAG1, 'E') \
179 _ELF_DEFINE_EMAG(ELFMAG2, 'L') \
180 _ELF_DEFINE_EMAG(ELFMAG3, 'F')
182 #undef _ELF_DEFINE_EMAG
183 #define _ELF_DEFINE_EMAG(N, V) N = V ,
184 enum {
185 _ELF_DEFINE_ELF_MAGIC()
186 ELFMAG__LAST__
190 * ELF Machine types: (EM_*).
192 #define _ELF_DEFINE_ELF_MACHINES() \
193 _ELF_DEFINE_EM(EM_NONE, 0, "No machine") \
194 _ELF_DEFINE_EM(EM_386, 3, "Intel 80386") \
195 _ELF_DEFINE_EM(EM_X86_64, 62, "AMD x86-64 architecture")
197 #undef _ELF_DEFINE_EM
198 #define _ELF_DEFINE_EM(N, V, DESCR) N = V ,
199 enum {
200 _ELF_DEFINE_ELF_MACHINES()
201 EM__LAST__
204 /* ELF file format version numbers. */
205 #define EV_NONE 0
206 #define EV_CURRENT 1
209 * Special section indices.
211 #define _ELF_DEFINE_SECTION_INDICES() \
212 _ELF_DEFINE_SHN(SHN_UNDEF, 0, "undefined section") \
213 _ELF_DEFINE_SHN(SHN_LORESERVE, 0xFF00U, "start of reserved area") \
214 _ELF_DEFINE_SHN(SHN_LOPROC, 0xFF00U, \
215 "start of processor-specific range") \
216 _ELF_DEFINE_SHN(SHN_BEFORE, 0xFF00U, "used for section ordering") \
217 _ELF_DEFINE_SHN(SHN_AFTER, 0xFF01U, "used for section ordering") \
218 _ELF_DEFINE_SHN(SHN_AMD64_LCOMMON, 0xFF02U, "large common block label") \
219 _ELF_DEFINE_SHN(SHN_MIPS_ACOMMON, 0xFF00U, \
220 "allocated common symbols in a DSO") \
221 _ELF_DEFINE_SHN(SHN_MIPS_TEXT, 0xFF01U, "Reserved (obsolete)") \
222 _ELF_DEFINE_SHN(SHN_MIPS_DATA, 0xFF02U, "Reserved (obsolete)") \
223 _ELF_DEFINE_SHN(SHN_MIPS_SCOMMON, 0xFF03U, \
224 "gp-addressable common symbols") \
225 _ELF_DEFINE_SHN(SHN_MIPS_SUNDEFINED, 0xFF04U, \
226 "gp-addressable undefined symbols") \
227 _ELF_DEFINE_SHN(SHN_MIPS_LCOMMON, 0xFF05U, "local common symbols") \
228 _ELF_DEFINE_SHN(SHN_MIPS_LUNDEFINED, 0xFF06U, \
229 "local undefined symbols") \
230 _ELF_DEFINE_SHN(SHN_HIPROC, 0xFF1FU, \
231 "end of processor-specific range") \
232 _ELF_DEFINE_SHN(SHN_LOOS, 0xFF20U, \
233 "start of OS-specific range") \
234 _ELF_DEFINE_SHN(SHN_SUNW_IGNORE, 0xFF3FU, "used by dtrace") \
235 _ELF_DEFINE_SHN(SHN_HIOS, 0xFF3FU, \
236 "end of OS-specific range") \
237 _ELF_DEFINE_SHN(SHN_ABS, 0xFFF1U, "absolute references") \
238 _ELF_DEFINE_SHN(SHN_COMMON, 0xFFF2U, "references to COMMON areas") \
239 _ELF_DEFINE_SHN(SHN_XINDEX, 0xFFFFU, "extended index") \
240 _ELF_DEFINE_SHN(SHN_HIRESERVE, 0xFFFFU, "end of reserved area")
242 #undef _ELF_DEFINE_SHN
243 #define _ELF_DEFINE_SHN(N, V, DESCR) N = V ,
244 enum {
245 _ELF_DEFINE_SECTION_INDICES()
246 SHN__LAST__
250 * Section types.
253 #define _ELF_DEFINE_SECTION_TYPES() \
254 _ELF_DEFINE_SHT(SHT_NULL, 0, "inactive header") \
255 _ELF_DEFINE_SHT(SHT_PROGBITS, 1, "program defined information") \
256 _ELF_DEFINE_SHT(SHT_SYMTAB, 2, "symbol table") \
257 _ELF_DEFINE_SHT(SHT_STRTAB, 3, "string table") \
258 _ELF_DEFINE_SHT(SHT_RELA, 4, \
259 "relocation entries with addends") \
260 _ELF_DEFINE_SHT(SHT_HASH, 5, "symbol hash table") \
261 _ELF_DEFINE_SHT(SHT_DYNAMIC, 6, \
262 "information for dynamic linking") \
263 _ELF_DEFINE_SHT(SHT_NOTE, 7, "additional notes") \
264 _ELF_DEFINE_SHT(SHT_NOBITS, 8, "section occupying no space") \
265 _ELF_DEFINE_SHT(SHT_REL, 9, \
266 "relocation entries without addends") \
267 _ELF_DEFINE_SHT(SHT_SHLIB, 10, "reserved") \
268 _ELF_DEFINE_SHT(SHT_DYNSYM, 11, "symbol table") \
269 _ELF_DEFINE_SHT(SHT_INIT_ARRAY, 14, \
270 "pointers to initialization functions") \
271 _ELF_DEFINE_SHT(SHT_FINI_ARRAY, 15, \
272 "pointers to termination functions") \
273 _ELF_DEFINE_SHT(SHT_PREINIT_ARRAY, 16, \
274 "pointers to functions called before initialization") \
275 _ELF_DEFINE_SHT(SHT_GROUP, 17, "defines a section group") \
276 _ELF_DEFINE_SHT(SHT_SYMTAB_SHNDX, 18, \
277 "used for extended section numbering") \
278 _ELF_DEFINE_SHT(SHT_LOOS, 0x60000000UL, \
279 "start of OS-specific range") \
280 _ELF_DEFINE_SHT(SHT_SUNW_dof, 0x6FFFFFF4UL, \
281 "used by dtrace") \
282 _ELF_DEFINE_SHT(SHT_SUNW_cap, 0x6FFFFFF5UL, \
283 "capability requirements") \
284 _ELF_DEFINE_SHT(SHT_GNU_ATTRIBUTES, 0x6FFFFFF5UL, \
285 "object attributes") \
286 _ELF_DEFINE_SHT(SHT_SUNW_SIGNATURE, 0x6FFFFFF6UL, \
287 "module verification signature") \
288 _ELF_DEFINE_SHT(SHT_GNU_HASH, 0x6FFFFFF6UL, \
289 "GNU Hash sections") \
290 _ELF_DEFINE_SHT(SHT_GNU_LIBLIST, 0x6FFFFFF7UL, \
291 "List of libraries to be prelinked") \
292 _ELF_DEFINE_SHT(SHT_SUNW_ANNOTATE, 0x6FFFFFF7UL, \
293 "special section where unresolved references are allowed") \
294 _ELF_DEFINE_SHT(SHT_SUNW_DEBUGSTR, 0x6FFFFFF8UL, \
295 "debugging information") \
296 _ELF_DEFINE_SHT(SHT_CHECKSUM, 0x6FFFFFF8UL, \
297 "checksum for dynamic shared objects") \
298 _ELF_DEFINE_SHT(SHT_SUNW_DEBUG, 0x6FFFFFF9UL, \
299 "debugging information") \
300 _ELF_DEFINE_SHT(SHT_SUNW_move, 0x6FFFFFFAUL, \
301 "information to handle partially initialized symbols") \
302 _ELF_DEFINE_SHT(SHT_SUNW_COMDAT, 0x6FFFFFFBUL, \
303 "section supporting merging of multiple copies of data") \
304 _ELF_DEFINE_SHT(SHT_SUNW_syminfo, 0x6FFFFFFCUL, \
305 "additional symbol information") \
306 _ELF_DEFINE_SHT(SHT_SUNW_verdef, 0x6FFFFFFDUL, \
307 "symbol versioning information") \
308 _ELF_DEFINE_SHT(SHT_SUNW_verneed, 0x6FFFFFFEUL, \
309 "symbol versioning requirements") \
310 _ELF_DEFINE_SHT(SHT_SUNW_versym, 0x6FFFFFFFUL, \
311 "symbol versioning table") \
312 _ELF_DEFINE_SHT(SHT_HIOS, 0x6FFFFFFFUL, \
313 "end of OS-specific range") \
314 _ELF_DEFINE_SHT(SHT_LOPROC, 0x70000000UL, \
315 "start of processor-specific range") \
316 _ELF_DEFINE_SHT(SHT_ARM_EXIDX, 0x70000001UL, \
317 "exception index table") \
318 _ELF_DEFINE_SHT(SHT_ARM_PREEMPTMAP, 0x70000002UL, \
319 "BPABI DLL dynamic linking preemption map") \
320 _ELF_DEFINE_SHT(SHT_ARM_ATTRIBUTES, 0x70000003UL, \
321 "object file compatibility attributes") \
322 _ELF_DEFINE_SHT(SHT_ARM_DEBUGOVERLAY, 0x70000004UL, \
323 "overlay debug information") \
324 _ELF_DEFINE_SHT(SHT_ARM_OVERLAYSECTION, 0x70000005UL, \
325 "overlay debug information") \
326 _ELF_DEFINE_SHT(SHT_MIPS_LIBLIST, 0x70000000UL, \
327 "DSO library information used in link") \
328 _ELF_DEFINE_SHT(SHT_MIPS_MSYM, 0x70000001UL, \
329 "MIPS symbol table extension") \
330 _ELF_DEFINE_SHT(SHT_MIPS_CONFLICT, 0x70000002UL, \
331 "symbol conflicting with DSO-defined symbols ") \
332 _ELF_DEFINE_SHT(SHT_MIPS_GPTAB, 0x70000003UL, \
333 "global pointer table") \
334 _ELF_DEFINE_SHT(SHT_MIPS_UCODE, 0x70000004UL, \
335 "reserved") \
336 _ELF_DEFINE_SHT(SHT_MIPS_DEBUG, 0x70000005UL, \
337 "reserved (obsolete debug information)") \
338 _ELF_DEFINE_SHT(SHT_MIPS_REGINFO, 0x70000006UL, \
339 "register usage information") \
340 _ELF_DEFINE_SHT(SHT_MIPS_PACKAGE, 0x70000007UL, \
341 "OSF reserved") \
342 _ELF_DEFINE_SHT(SHT_MIPS_PACKSYM, 0x70000008UL, \
343 "OSF reserved") \
344 _ELF_DEFINE_SHT(SHT_MIPS_RELD, 0x70000009UL, \
345 "dynamic relocation") \
346 _ELF_DEFINE_SHT(SHT_MIPS_IFACE, 0x7000000BUL, \
347 "subprogram interface information") \
348 _ELF_DEFINE_SHT(SHT_MIPS_CONTENT, 0x7000000CUL, \
349 "section content classification") \
350 _ELF_DEFINE_SHT(SHT_MIPS_OPTIONS, 0x7000000DUL, \
351 "general options") \
352 _ELF_DEFINE_SHT(SHT_MIPS_DELTASYM, 0x7000001BUL, \
353 "Delta C++: symbol table") \
354 _ELF_DEFINE_SHT(SHT_MIPS_DELTAINST, 0x7000001CUL, \
355 "Delta C++: instance table") \
356 _ELF_DEFINE_SHT(SHT_MIPS_DELTACLASS, 0x7000001DUL, \
357 "Delta C++: class table") \
358 _ELF_DEFINE_SHT(SHT_MIPS_DWARF, 0x7000001EUL, \
359 "DWARF debug information") \
360 _ELF_DEFINE_SHT(SHT_MIPS_DELTADECL, 0x7000001FUL, \
361 "Delta C++: declarations") \
362 _ELF_DEFINE_SHT(SHT_MIPS_SYMBOL_LIB, 0x70000020UL, \
363 "symbol-to-library mapping") \
364 _ELF_DEFINE_SHT(SHT_MIPS_EVENTS, 0x70000021UL, \
365 "event locations") \
366 _ELF_DEFINE_SHT(SHT_MIPS_TRANSLATE, 0x70000022UL, \
367 "???") \
368 _ELF_DEFINE_SHT(SHT_MIPS_PIXIE, 0x70000023UL, \
369 "special pixie sections") \
370 _ELF_DEFINE_SHT(SHT_MIPS_XLATE, 0x70000024UL, \
371 "address translation table") \
372 _ELF_DEFINE_SHT(SHT_MIPS_XLATE_DEBUG, 0x70000025UL, \
373 "SGI internal address translation table") \
374 _ELF_DEFINE_SHT(SHT_MIPS_WHIRL, 0x70000026UL, \
375 "intermediate code") \
376 _ELF_DEFINE_SHT(SHT_MIPS_EH_REGION, 0x70000027UL, \
377 "C++ exception handling region info") \
378 _ELF_DEFINE_SHT(SHT_MIPS_XLATE_OLD, 0x70000028UL, \
379 "obsolete") \
380 _ELF_DEFINE_SHT(SHT_MIPS_PDR_EXCEPTION, 0x70000029UL, \
381 "runtime procedure descriptor table exception information") \
382 _ELF_DEFINE_SHT(SHT_MIPS_ABIFLAGS, 0x7000002AUL, \
383 "ABI flags") \
384 _ELF_DEFINE_SHT(SHT_SPARC_GOTDATA, 0x70000000UL, \
385 "SPARC-specific data") \
386 _ELF_DEFINE_SHT(SHT_AMD64_UNWIND, 0x70000001UL, \
387 "unwind tables for the AMD64") \
388 _ELF_DEFINE_SHT(SHT_ORDERED, 0x7FFFFFFFUL, \
389 "sort entries in the section") \
390 _ELF_DEFINE_SHT(SHT_HIPROC, 0x7FFFFFFFUL, \
391 "end of processor-specific range") \
392 _ELF_DEFINE_SHT(SHT_LOUSER, 0x80000000UL, \
393 "start of application-specific range") \
394 _ELF_DEFINE_SHT(SHT_HIUSER, 0xFFFFFFFFUL, \
395 "end of application-specific range")
397 #undef _ELF_DEFINE_SHT
398 #define _ELF_DEFINE_SHT(N, V, DESCR) N = V ,
399 enum {
400 _ELF_DEFINE_SECTION_TYPES()
401 SHT__LAST__ = SHT_HIUSER
404 #define PN_XNUM 0xFFFFU /* Use extended section numbering. */
407 ** ELF Types.
410 typedef uint64_t Elf64_Addr; /* Program address. */
411 typedef uint16_t Elf64_Half; /* Unsigned medium integer. */
412 typedef uint64_t Elf64_Off; /* File offset. */
413 typedef int32_t Elf64_Sword; /* Signed integer. */
414 typedef uint32_t Elf64_Word; /* Unsigned integer. */
415 typedef uint64_t Elf64_Lword; /* Unsigned long integer. */
416 typedef uint64_t Elf64_Xword; /* Unsigned long integer. */
417 typedef int64_t Elf64_Sxword; /* Signed long integer. */
420 * Capability descriptors.
422 typedef struct {
423 Elf64_Xword c_tag; /* Type of entry. */
424 union {
425 Elf64_Xword c_val; /* Integer value. */
426 Elf64_Addr c_ptr; /* Pointer value. */
427 } c_un;
428 } Elf64_Cap;
431 * Dynamic section entries.
433 typedef struct {
434 Elf64_Sxword d_tag; /* Type of entry. */
435 union {
436 Elf64_Xword d_val; /* Integer value. */
437 Elf64_Addr d_ptr; /* Pointer value; */
438 } d_un;
439 } Elf64_Dyn;
442 * The executable header (EHDR).
444 typedef struct {
445 unsigned char e_ident[EI_NIDENT]; /* ELF identification. */
446 Elf64_Half e_type; /* Object file type (ET_*). */
447 Elf64_Half e_machine; /* Machine type (EM_*). */
448 Elf64_Word e_version; /* File format version (EV_*). */
449 Elf64_Addr e_entry; /* Start address. */
450 Elf64_Off e_phoff; /* File offset to the PHDR table. */
451 Elf64_Off e_shoff; /* File offset to the SHDRheader. */
452 Elf64_Word e_flags; /* Flags (EF_*). */
453 Elf64_Half e_ehsize; /* Elf header size in bytes. */
454 Elf64_Half e_phentsize; /* PHDR table entry size in bytes. */
455 Elf64_Half e_phnum; /* Number of PHDR entries. */
456 Elf64_Half e_shentsize; /* SHDR table entry size in bytes. */
457 Elf64_Half e_shnum; /* Number of SHDR entries. */
458 Elf64_Half e_shstrndx; /* Index of section name string table. */
459 } Elf64_Ehdr;
462 * Note descriptors.
465 typedef struct {
466 uint32_t n_namesz; /* Length of note's name. */
467 uint32_t n_descsz; /* Length of note's value. */
468 uint32_t n_type; /* Type of note. */
469 } Elf_Note;
472 * Program Header Table (PHDR) entries.
474 typedef struct {
475 Elf64_Word p_type; /* Type of segment. */
476 Elf64_Word p_flags; /* Segment flags. */
477 Elf64_Off p_offset; /* File offset to segment. */
478 Elf64_Addr p_vaddr; /* Virtual address in memory. */
479 Elf64_Addr p_paddr; /* Physical address (if relevant). */
480 Elf64_Xword p_filesz; /* Size of segment in file. */
481 Elf64_Xword p_memsz; /* Size of segment in memory. */
482 Elf64_Xword p_align; /* Alignment constraints. */
483 } Elf64_Phdr;
486 * Move entries, for describing data in COMMON blocks in a compact
487 * manner.
489 typedef struct {
490 Elf64_Lword m_value; /* Initialization value. */
491 Elf64_Xword m_info; /* Encoded size and index. */
492 Elf64_Xword m_poffset; /* Offset relative to symbol. */
493 Elf64_Half m_repeat; /* Repeat count. */
494 Elf64_Half m_stride; /* Number of units to skip. */
495 } Elf64_Move;
498 * Section Header Table (SHDR) entries.
500 typedef struct {
501 Elf64_Word sh_name; /* index of section name */
502 Elf64_Word sh_type; /* section type */
503 Elf64_Xword sh_flags; /* section flags */
504 Elf64_Addr sh_addr; /* in-memory address of section */
505 Elf64_Off sh_offset; /* file offset of section */
506 Elf64_Xword sh_size; /* section size in bytes */
507 Elf64_Word sh_link; /* section header table link */
508 Elf64_Word sh_info; /* extra information */
509 Elf64_Xword sh_addralign; /* alignment constraint */
510 Elf64_Xword sh_entsize; /* size for fixed-size entries */
511 } Elf64_Shdr;
514 * Symbol table entries.
516 typedef struct {
517 Elf64_Word st_name; /* index of symbol's name */
518 unsigned char st_info; /* type and binding attributes */
519 unsigned char st_other; /* visibility */
520 Elf64_Half st_shndx; /* index of related section */
521 Elf64_Addr st_value; /* value for the symbol */
522 Elf64_Xword st_size; /* size of associated data */
523 } Elf64_Sym;
526 * Syminfo descriptors, containing additional symbol information.
528 typedef struct {
529 Elf64_Half si_boundto; /* Entry index with additional flags. */
530 Elf64_Half si_flags; /* Flags. */
531 } Elf64_Syminfo;
534 * Relocation descriptors.
536 typedef struct {
537 Elf64_Addr r_offset; /* location to apply relocation to */
538 Elf64_Xword r_info; /* type+section for relocation */
539 } Elf64_Rel;
541 typedef struct {
542 Elf64_Addr r_offset; /* location to apply relocation to */
543 Elf64_Xword r_info; /* type+section for relocation */
544 Elf64_Sxword r_addend; /* constant addend */
545 } Elf64_Rela;
548 * Symbol versioning structures.
550 typedef struct {
551 Elf64_Word vda_name; /* Index to name. */
552 Elf64_Word vda_next; /* Offset to next entry. */
553 } Elf64_Verdaux;
555 typedef struct {
556 Elf64_Word vna_hash; /* Hash value of dependency name. */
557 Elf64_Half vna_flags; /* Flags. */
558 Elf64_Half vna_other; /* Unused. */
559 Elf64_Word vna_name; /* Offset to dependency name. */
560 Elf64_Word vna_next; /* Offset to next vernaux entry. */
561 } Elf64_Vernaux;
563 typedef struct {
564 Elf64_Half vd_version; /* Version information. */
565 Elf64_Half vd_flags; /* Flags. */
566 Elf64_Half vd_ndx; /* Index into the versym section. */
567 Elf64_Half vd_cnt; /* Number of aux entries. */
568 Elf64_Word vd_hash; /* Hash value of name. */
569 Elf64_Word vd_aux; /* Offset to aux entries. */
570 Elf64_Word vd_next; /* Offset to next version definition. */
571 } Elf64_Verdef;
573 typedef struct {
574 Elf64_Half vn_version; /* Version number. */
575 Elf64_Half vn_cnt; /* Number of aux entries. */
576 Elf64_Word vn_file; /* Offset of associated file name. */
577 Elf64_Word vn_aux; /* Offset of vernaux array. */
578 Elf64_Word vn_next; /* Offset of next verneed entry. */
579 } Elf64_Verneed;
582 * The header for GNU-style hash sections.
585 typedef struct {
586 uint32_t gh_nbuckets; /* Number of hash buckets. */
587 uint32_t gh_symndx; /* First visible symbol in .dynsym. */
588 uint32_t gh_maskwords; /* #maskwords used in bloom filter. */
589 uint32_t gh_shift2; /* Bloom filter shift count. */
590 } Elf_GNU_Hash_Header;
592 /* libelf.h */
593 /* Library private data structures */
594 typedef struct _Elf Elf;
595 typedef struct _Elf_Scn Elf_Scn;
597 /* File types */
598 typedef enum {
599 ELF_K_NONE = 0,
600 ELF_K_AR, /* `ar' archives */
601 ELF_K_COFF, /* COFF files (unsupported) */
602 ELF_K_ELF, /* ELF files */
603 ELF_K_NUM
604 } Elf_Kind;
606 /* Data types */
607 typedef enum {
608 ELF_T_ADDR,
609 ELF_T_BYTE,
610 ELF_T_CAP,
611 ELF_T_DYN,
612 ELF_T_EHDR,
613 ELF_T_HALF,
614 ELF_T_LWORD,
615 ELF_T_MOVE,
616 ELF_T_MOVEP,
617 ELF_T_NOTE,
618 ELF_T_OFF,
619 ELF_T_PHDR,
620 ELF_T_REL,
621 ELF_T_RELA,
622 ELF_T_SHDR,
623 ELF_T_SWORD,
624 ELF_T_SXWORD,
625 ELF_T_SYMINFO,
626 ELF_T_SYM,
627 ELF_T_VDEF,
628 ELF_T_VNEED,
629 ELF_T_WORD,
630 ELF_T_XWORD,
631 ELF_T_GNUHASH, /* GNU style hash tables. */
632 ELF_T_NUM
633 } Elf_Type;
635 #define ELF_T_FIRST ELF_T_ADDR
636 #define ELF_T_LAST ELF_T_GNUHASH
638 /* Commands */
639 typedef enum {
640 ELF_C_NULL = 0,
641 ELF_C_CLR,
642 ELF_C_FDDONE,
643 ELF_C_FDREAD,
644 ELF_C_RDWR,
645 ELF_C_READ,
646 ELF_C_SET,
647 ELF_C_WRITE,
648 ELF_C_NUM
649 } Elf_Cmd;
652 * An `Elf_Data' structure describes data in an
653 * ELF section.
655 typedef struct _Elf_Data {
657 * `Public' members that are part of the ELF(3) API.
659 uint64_t d_align;
660 void *d_buf;
661 uint64_t d_off;
662 uint64_t d_size;
663 Elf_Type d_type;
664 unsigned int d_version;
665 } Elf_Data;
668 * An `Elf_Arhdr' structure describes an archive
669 * header.
671 typedef struct {
672 time_t ar_date;
673 char *ar_name; /* archive member name */
674 gid_t ar_gid;
675 mode_t ar_mode;
676 char *ar_rawname; /* 'raw' member name */
677 size_t ar_size;
678 uid_t ar_uid;
681 * Members that are not part of the public API.
683 unsigned int ar_flags;
684 } Elf_Arhdr;
687 * An `Elf_Arsym' describes an entry in the archive
688 * symbol table.
690 typedef struct {
691 off_t as_off; /* byte offset to member's header */
692 unsigned long as_hash; /* elf_hash() value for name */
693 char *as_name; /* null terminated symbol name */
694 } Elf_Arsym;
697 * Error numbers.
700 enum Elf_Error {
701 ELF_E_NONE, /* No error */
702 ELF_E_ARCHIVE, /* Malformed ar(1) archive */
703 ELF_E_ARGUMENT, /* Invalid argument */
704 ELF_E_CLASS, /* Mismatched ELF class */
705 ELF_E_DATA, /* Invalid data descriptor */
706 ELF_E_HEADER, /* Missing or malformed ELF header */
707 ELF_E_IO, /* I/O error */
708 ELF_E_LAYOUT, /* Layout constraint violation */
709 ELF_E_MODE, /* Wrong mode for ELF descriptor */
710 ELF_E_RANGE, /* Value out of range */
711 ELF_E_RESOURCE, /* Resource exhaustion */
712 ELF_E_SECTION, /* Invalid section descriptor */
713 ELF_E_SEQUENCE, /* API calls out of sequence */
714 ELF_E_UNIMPL, /* Feature is unimplemented */
715 ELF_E_VERSION, /* Unknown API version */
716 ELF_E_NUM /* Max error number */
720 * Flags defined by the API.
723 #define ELF_F_LAYOUT 0x001U /* application will layout the file */
724 #define ELF_F_DIRTY 0x002U /* a section or ELF file is dirty */
726 #ifdef __cplusplus
727 extern "C" {
728 #endif
729 static
730 Elf *elf_begin(int _fd, Elf_Cmd _cmd, Elf *_elf);
731 static
732 int elf_end(Elf *_elf);
733 static
734 const char *elf_errmsg(int _error);
735 static
736 int elf_errno(void);
737 static
738 Elf_Data *elf_getdata(Elf_Scn *, Elf_Data *);
739 static
740 char *elf_strptr(Elf *_elf, size_t _section, size_t _offset);
741 static
742 unsigned int elf_version(unsigned int _version);
743 static
744 Elf_Scn *elf_nextscn(Elf *_elf, Elf_Scn *_scn);
745 #ifdef __cplusplus
747 #endif
749 /* gelf.h */
750 typedef Elf64_Shdr GElf_Shdr; /* Section header */
751 typedef Elf64_Sym GElf_Sym; /* Symbol table entries */
753 #ifdef __cplusplus
754 extern "C" {
755 #endif
756 static
757 GElf_Shdr *gelf_getshdr(Elf_Scn *_scn, GElf_Shdr *_dst);
758 static
759 GElf_Sym *gelf_getsym(Elf_Data *_src, int _index, GElf_Sym *_dst);
760 #ifdef __cplusplus
762 #endif
764 /* _libelf.h */
766 * Library-private data structures.
769 #define LIBELF_MSG_SIZE 256
771 struct _libelf_globals {
772 int libelf_arch;
773 unsigned int libelf_byteorder;
774 int libelf_class;
775 int libelf_error;
776 int libelf_fillchar;
777 unsigned int libelf_version;
778 unsigned char libelf_msg[LIBELF_MSG_SIZE];
781 #if 0
782 extern struct _libelf_globals _libelf;
783 #endif
785 #define LIBELF_PRIVATE(N) (_libelf.libelf_##N)
787 #define LIBELF_ELF_ERROR_MASK 0xFF
788 #define LIBELF_OS_ERROR_SHIFT 8
790 #define LIBELF_ERROR(E, O) (((E) & LIBELF_ELF_ERROR_MASK) | \
791 ((O) << LIBELF_OS_ERROR_SHIFT))
793 #define LIBELF_SET_ERROR(E, O) do { \
794 LIBELF_PRIVATE(error) = LIBELF_ERROR(ELF_E_##E, (O)); \
795 } while (0)
798 * Flags for library internal use. These use the upper 16 bits of the
799 * `e_flags' field.
802 #define LIBELF_F_DATA_MALLOCED 0x040000U /* whether data was malloc'ed */
803 #define LIBELF_F_RAWFILE_MALLOC 0x080000U /* whether e_rawfile was malloc'ed */
804 #define LIBELF_F_RAWFILE_MMAP 0x100000U /* whether e_rawfile was mmap'ed */
805 #define LIBELF_F_SHDRS_LOADED 0x200000U /* whether all shdrs were read in */
806 #define LIBELF_F_SPECIAL_FILE 0x400000U /* non-regular file */
808 struct _Elf {
809 int e_activations; /* activation count */
810 unsigned int e_byteorder; /* ELFDATA* */
811 int e_class; /* ELFCLASS* */
812 Elf_Cmd e_cmd; /* ELF_C_* used at creation time */
813 int e_fd; /* associated file descriptor */
814 unsigned int e_flags; /* ELF_F_* & LIBELF_F_* flags */
815 Elf_Kind e_kind; /* ELF_K_* */
816 Elf *e_parent; /* non-NULL for archive members */
817 unsigned char *e_rawfile; /* uninterpreted bytes */
818 size_t e_rawsize; /* size of uninterpreted bytes */
819 unsigned int e_version; /* file version */
822 * Header information for archive members. See the
823 * LIBELF_F_AR_HEADER flag.
825 union {
826 Elf_Arhdr *e_arhdr; /* translated header */
827 unsigned char *e_rawhdr; /* untranslated header */
828 } e_hdr;
830 union {
831 struct { /* ar(1) archives */
832 off_t e_next; /* set by elf_rand()/elf_next() */
833 int e_nchildren;
834 unsigned char *e_rawstrtab; /* file name strings */
835 size_t e_rawstrtabsz;
836 unsigned char *e_rawsymtab; /* symbol table */
837 size_t e_rawsymtabsz;
838 Elf_Arsym *e_symtab;
839 size_t e_symtabsz;
840 } e_ar;
841 struct { /* regular ELF files */
842 union {
843 #if 0
844 Elf32_Ehdr *e_ehdr32;
845 #endif
846 Elf64_Ehdr *e_ehdr64;
847 } e_ehdr;
848 union {
849 #if 0
850 Elf32_Phdr *e_phdr32;
851 #endif
852 Elf64_Phdr *e_phdr64;
853 } e_phdr;
854 STAILQ_HEAD(, _Elf_Scn) e_scn; /* section list */
855 size_t e_nphdr; /* number of Phdr entries */
856 size_t e_nscn; /* number of sections */
857 size_t e_strndx; /* string table section index */
858 } e_elf;
859 } e_u;
863 * The internal descriptor wrapping the "Elf_Data" type.
865 struct _Libelf_Data {
866 Elf_Data d_data; /* The exported descriptor. */
867 Elf_Scn *d_scn; /* The containing section */
868 unsigned int d_flags;
869 STAILQ_ENTRY(_Libelf_Data) d_next;
872 struct _Elf_Scn {
873 union {
874 #if 0
875 Elf32_Shdr s_shdr32;
876 #endif
877 Elf64_Shdr s_shdr64;
878 } s_shdr;
879 STAILQ_HEAD(, _Libelf_Data) s_data; /* translated data */
880 STAILQ_HEAD(, _Libelf_Data) s_rawdata; /* raw data */
881 STAILQ_ENTRY(_Elf_Scn) s_next;
882 struct _Elf *s_elf; /* parent ELF descriptor */
883 unsigned int s_flags; /* flags for the section as a whole */
884 size_t s_ndx; /* index# for this section */
885 uint64_t s_offset; /* managed by elf_update() */
886 uint64_t s_rawoff; /* original offset in the file */
887 uint64_t s_size; /* managed by elf_update() */
890 enum {
891 ELF_TOFILE,
892 ELF_TOMEMORY
895 /* PRIVATE */
897 /* elf.c */
898 static struct _libelf_globals _libelf = {
899 .libelf_arch = LIBELF_ARCH,
900 .libelf_byteorder = LIBELF_BYTEORDER,
901 .libelf_class = LIBELF_CLASS,
902 .libelf_error = 0,
903 .libelf_fillchar = 0,
904 .libelf_version = EV_NONE
907 /* libelf_msize.c */
908 struct msize {
909 size_t msz64;
912 static struct msize msize[ELF_T_NUM] = {
913 [ELF_T_ADDR] = { .msz64 = sizeof(Elf64_Addr) },
914 [ELF_T_BYTE] = { .msz64 = 1 },
915 [ELF_T_CAP] = { .msz64 = sizeof(Elf64_Cap) },
916 [ELF_T_DYN] = { .msz64 = sizeof(Elf64_Dyn) },
917 [ELF_T_EHDR] = { .msz64 = sizeof(Elf64_Ehdr) },
918 [ELF_T_GNUHASH] = { .msz64 = 1 },
919 [ELF_T_HALF] = { .msz64 = sizeof(Elf64_Half) },
920 [ELF_T_LWORD] = { .msz64 = sizeof(Elf64_Lword) },
921 [ELF_T_MOVE] = { .msz64 = sizeof(Elf64_Move) },
922 [ELF_T_MOVEP] = { .msz64 = 0 },
923 [ELF_T_NOTE] = { .msz64 = 1 },
924 [ELF_T_OFF] = { .msz64 = sizeof(Elf64_Off) },
925 [ELF_T_PHDR] = { .msz64 = sizeof(Elf64_Phdr) },
926 [ELF_T_REL] = { .msz64 = sizeof(Elf64_Rel) },
927 [ELF_T_RELA] = { .msz64 = sizeof(Elf64_Rela) },
928 [ELF_T_SHDR] = { .msz64 = sizeof(Elf64_Shdr) },
929 [ELF_T_SWORD] = { .msz64 = sizeof(Elf64_Sword) },
930 [ELF_T_SXWORD] = { .msz64 = sizeof(Elf64_Sxword) },
931 [ELF_T_SYMINFO] = { .msz64 = sizeof(Elf64_Syminfo) },
932 [ELF_T_SYM] = { .msz64 = sizeof(Elf64_Sym) },
933 [ELF_T_VDEF] = { .msz64 = 1 },
934 [ELF_T_VNEED] = { .msz64 = 1 },
935 [ELF_T_WORD] = { .msz64 = sizeof(Elf64_Word) },
936 [ELF_T_XWORD] = { .msz64 = sizeof(Elf64_Xword) },
939 static size_t
940 _libelf_msize(Elf_Type t, int elfclass, unsigned int version)
942 size_t sz;
944 assert(/*elfclass == ELFCLASS32 ||*/ elfclass == ELFCLASS64);
945 assert((signed) t >= ELF_T_FIRST && t <= ELF_T_LAST);
947 if (version != EV_CURRENT) {
948 LIBELF_SET_ERROR(VERSION, 0);
949 return (0);
952 sz = /* (elfclass == ELFCLASS32) ? msize[t].msz32 : */ msize[t].msz64;
954 return (sz);
957 /* libelf_fsize.c */
958 struct tfsize {
959 size_t fsz64;
962 static struct tfsize tfsize[ELF_T_NUM] = {
963 [ELF_T_ADDR] = { .fsz64 = sizeof(Elf64_Addr) },
964 [ELF_T_BYTE] = { .fsz64 = 1 },
965 [ELF_T_CAP] = { .fsz64 = sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
966 [ELF_T_DYN] = { .fsz64 = sizeof(Elf64_Sxword)+sizeof(Elf64_Xword)+0 },
967 [ELF_T_EHDR] = { .fsz64 = EI_NIDENT
968 +sizeof(Elf64_Half)+sizeof(Elf64_Half)
969 +sizeof(Elf64_Word)+sizeof(Elf64_Addr)
970 +sizeof(Elf64_Off)+ sizeof(Elf64_Off)
971 +sizeof(Elf64_Word)+sizeof(Elf64_Half)
972 +sizeof(Elf64_Half)+sizeof(Elf64_Half)
973 +sizeof(Elf64_Half)+sizeof(Elf64_Half)
974 +sizeof(Elf64_Half)+0 },
975 [ELF_T_GNUHASH] = { .fsz64 = 1 },
976 [ELF_T_HALF] = { .fsz64 = sizeof(Elf64_Half) },
977 [ELF_T_LWORD] = { .fsz64 = sizeof(Elf64_Lword) },
978 [ELF_T_MOVE] = { .fsz64 = sizeof(Elf64_Lword)+sizeof(Elf64_Xword)
979 +sizeof(Elf64_Xword)+sizeof(Elf64_Half)
980 +sizeof(Elf64_Half)+0 },
981 [ELF_T_MOVEP] = { .fsz64 = 0 },
982 [ELF_T_NOTE] = { .fsz64 = 1 },
983 [ELF_T_OFF] = { .fsz64 = sizeof(Elf64_Off) },
984 [ELF_T_PHDR] = { .fsz64 = sizeof(Elf64_Word)+sizeof(Elf64_Word)
985 +sizeof(Elf64_Off)+ sizeof(Elf64_Addr)
986 +sizeof(Elf64_Addr)+sizeof(Elf64_Xword)
987 +sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
988 [ELF_T_REL] = { .fsz64 = sizeof(Elf64_Addr)+sizeof(Elf64_Xword)+0 },
989 [ELF_T_RELA] = { .fsz64 = sizeof(Elf64_Addr)+sizeof(Elf64_Xword)
990 +sizeof(Elf64_Sxword)+0 },
991 [ELF_T_SHDR] = { .fsz64 = sizeof(Elf64_Word)+sizeof(Elf64_Word)
992 +sizeof(Elf64_Xword)+sizeof(Elf64_Addr)
993 +sizeof(Elf64_Off)+ sizeof(Elf64_Xword)
994 +sizeof(Elf64_Word)+sizeof(Elf64_Word)
995 +sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
996 [ELF_T_SWORD] = { .fsz64 = sizeof(Elf64_Sword) },
997 [ELF_T_SXWORD] = { .fsz64 = sizeof(Elf64_Sxword) },
998 [ELF_T_SYMINFO] = { .fsz64 = sizeof(Elf64_Half)+sizeof(Elf64_Half)+0 },
999 [ELF_T_SYM] = { .fsz64 = sizeof(Elf64_Word)+1+1+sizeof(Elf64_Half)
1000 +sizeof(Elf64_Addr)+sizeof(Elf64_Xword)+0 },
1001 [ELF_T_VDEF] = { .fsz64 = 1 },
1002 [ELF_T_VNEED] = { .fsz64 = 1 },
1003 [ELF_T_WORD] = { .fsz64 = sizeof(Elf64_Word) },
1004 [ELF_T_XWORD] = { .fsz64 = sizeof(Elf64_Xword) },
1007 static size_t
1008 _libelf_fsize(Elf_Type t, int ec, unsigned int v, size_t c)
1010 size_t sz;
1012 sz = 0;
1013 if (v != EV_CURRENT)
1014 LIBELF_SET_ERROR(VERSION, 0);
1015 else if ((int) t < ELF_T_FIRST || t > ELF_T_LAST)
1016 LIBELF_SET_ERROR(ARGUMENT, 0);
1017 else {
1018 sz = ec == ELFCLASS64 ? tfsize[t].fsz64 : /* tfsize[t].fsz32 */ 0;
1019 if (sz == 0)
1020 LIBELF_SET_ERROR(UNIMPL, 0);
1023 return (sz*c);
1026 /* gelf_fsize.c */
1027 static size_t
1028 elf64_fsize(Elf_Type t, size_t c, unsigned int v)
1030 return (_libelf_fsize(t, ELFCLASS64, v, c));
1033 /* libelf_allocate.h */
1034 static Elf *
1035 _libelf_allocate_elf(void)
1037 Elf *e;
1039 if ((e = malloc(sizeof(*e))) == NULL) {
1040 LIBELF_SET_ERROR(RESOURCE, errno);
1041 return NULL;
1044 e->e_activations = 1;
1045 e->e_hdr.e_rawhdr = NULL;
1046 e->e_byteorder = ELFDATANONE;
1047 e->e_class = ELFCLASSNONE;
1048 e->e_cmd = ELF_C_NULL;
1049 e->e_fd = -1;
1050 e->e_flags = 0;
1051 e->e_kind = ELF_K_NONE;
1052 e->e_parent = NULL;
1053 e->e_rawfile = NULL;
1054 e->e_rawsize = 0;
1055 e->e_version = LIBELF_PRIVATE(version);
1057 (void) memset(&e->e_u, 0, sizeof(e->e_u));
1059 return (e);
1062 static void
1063 _libelf_init_elf(Elf *e, Elf_Kind kind)
1065 assert(e != NULL);
1066 assert(e->e_kind == ELF_K_NONE);
1068 e->e_kind = kind;
1070 switch (kind) {
1071 case ELF_K_ELF:
1072 STAILQ_INIT(&e->e_u.e_elf.e_scn);
1073 break;
1074 default:
1075 break;
1079 #define FREE(P) do { \
1080 if (P) \
1081 free(P); \
1082 } while (0)
1084 static Elf *
1085 _libelf_release_elf(Elf *e)
1087 #if 0
1088 Elf_Arhdr *arh;
1089 #endif
1091 switch (e->e_kind) {
1092 #if 0
1093 case ELF_K_AR:
1094 FREE(e->e_u.e_ar.e_symtab);
1095 break;
1096 #endif
1098 case ELF_K_ELF:
1099 switch (e->e_class) {
1100 #if 0
1101 case ELFCLASS32:
1102 FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
1103 FREE(e->e_u.e_elf.e_phdr.e_phdr32);
1104 break;
1105 #endif
1106 case ELFCLASS64:
1107 FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
1108 FREE(e->e_u.e_elf.e_phdr.e_phdr64);
1109 break;
1112 assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
1114 #if 0
1115 if (e->e_flags & LIBELF_F_AR_HEADER) {
1116 arh = e->e_hdr.e_arhdr;
1117 FREE(arh->ar_name);
1118 FREE(arh->ar_rawname);
1119 free(arh);
1121 #endif
1123 break;
1125 default:
1126 break;
1129 free(e);
1131 return (NULL);
1134 #undef FREE
1136 static struct _Libelf_Data *
1137 _libelf_allocate_data(Elf_Scn *s)
1139 struct _Libelf_Data *d;
1141 if ((d = calloc((size_t) 1, sizeof(*d))) == NULL) {
1142 LIBELF_SET_ERROR(RESOURCE, 0);
1143 return (NULL);
1146 d->d_scn = s;
1148 return (d);
1151 static struct _Libelf_Data *
1152 _libelf_release_data(struct _Libelf_Data *d)
1155 if (d->d_flags & LIBELF_F_DATA_MALLOCED)
1156 free(d->d_data.d_buf);
1158 free(d);
1160 return (NULL);
1163 static Elf_Scn *
1164 _libelf_allocate_scn(Elf *e, size_t ndx)
1166 Elf_Scn *s;
1168 if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
1169 LIBELF_SET_ERROR(RESOURCE, errno);
1170 return (NULL);
1173 s->s_elf = e;
1174 s->s_ndx = ndx;
1176 STAILQ_INIT(&s->s_data);
1177 STAILQ_INIT(&s->s_rawdata);
1179 STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
1181 return (s);
1184 static Elf_Scn *
1185 _libelf_release_scn(Elf_Scn *s)
1187 Elf *e;
1188 struct _Libelf_Data *d, *td;
1190 assert(s != NULL);
1192 STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
1193 STAILQ_REMOVE(&s->s_data, d, _Libelf_Data, d_next);
1194 d = _libelf_release_data(d);
1197 STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) {
1198 assert((d->d_flags & LIBELF_F_DATA_MALLOCED) == 0);
1199 STAILQ_REMOVE(&s->s_rawdata, d, _Libelf_Data, d_next);
1200 d = _libelf_release_data(d);
1203 e = s->s_elf;
1205 assert(e != NULL);
1207 STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
1209 free(s);
1211 return (NULL);
1214 /* libelf_data.c */
1215 static int
1216 _libelf_xlate_shtype(uint32_t sht)
1219 * Look for known section types.
1221 switch (sht) {
1222 case SHT_DYNAMIC:
1223 return (ELF_T_DYN);
1224 case SHT_DYNSYM:
1225 return (ELF_T_SYM);
1226 case SHT_FINI_ARRAY:
1227 return (ELF_T_ADDR);
1228 case SHT_GNU_HASH:
1229 return (ELF_T_GNUHASH);
1230 case SHT_GNU_LIBLIST:
1231 return (ELF_T_WORD);
1232 case SHT_GROUP:
1233 return (ELF_T_WORD);
1234 case SHT_HASH:
1235 return (ELF_T_WORD);
1236 case SHT_INIT_ARRAY:
1237 return (ELF_T_ADDR);
1238 case SHT_NOBITS:
1239 return (ELF_T_BYTE);
1240 case SHT_NOTE:
1241 return (ELF_T_NOTE);
1242 case SHT_PREINIT_ARRAY:
1243 return (ELF_T_ADDR);
1244 case SHT_PROGBITS:
1245 return (ELF_T_BYTE);
1246 case SHT_REL:
1247 return (ELF_T_REL);
1248 case SHT_RELA:
1249 return (ELF_T_RELA);
1250 case SHT_STRTAB:
1251 return (ELF_T_BYTE);
1252 case SHT_SYMTAB:
1253 return (ELF_T_SYM);
1254 case SHT_SYMTAB_SHNDX:
1255 return (ELF_T_WORD);
1256 case SHT_SUNW_dof:
1257 return (ELF_T_BYTE);
1258 case SHT_SUNW_move:
1259 return (ELF_T_MOVE);
1260 case SHT_SUNW_syminfo:
1261 return (ELF_T_SYMINFO);
1262 case SHT_SUNW_verdef: /* == SHT_GNU_verdef */
1263 return (ELF_T_VDEF);
1264 case SHT_SUNW_verneed: /* == SHT_GNU_verneed */
1265 return (ELF_T_VNEED);
1266 case SHT_SUNW_versym: /* == SHT_GNU_versym */
1267 return (ELF_T_HALF);
1268 default:
1270 * Values in the range [SHT_LOOS..SHT_HIUSER] (i.e.,
1271 * OS, processor and user-defined section types) are
1272 * legal, but since we do not know anything more about
1273 * their semantics, we return a type of ELF_T_BYTE.
1275 if (sht >= SHT_LOOS && sht <= SHT_HIUSER)
1276 return (ELF_T_BYTE);
1279 * Other values are unsupported.
1281 return (-1);
1285 /* libelf_convert.c */
1286 #define SWAP_BYTE(X) do { (void) (X); } while (0)
1287 #define SWAP_IDENT(X) do { (void) (X); } while (0)
1288 #define SWAP_HALF(X) do { \
1289 uint16_t _x = (uint16_t) (X); \
1290 uint32_t _t = _x & 0xFFU; \
1291 _t <<= 8U; _x >>= 8U; _t |= _x & 0xFFU; \
1292 (X) = (uint16_t) _t; \
1293 } while (0)
1294 #define _SWAP_WORD(X, T) do { \
1295 uint32_t _x = (uint32_t) (X); \
1296 uint32_t _t = _x & 0xFF; \
1297 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
1298 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
1299 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
1300 (X) = (T) _t; \
1301 } while (0)
1302 #define SWAP_SWORD(X) _SWAP_WORD(X, /* Elf32_Sword */ Elf64_Sword)
1303 #define SWAP_WORD(X) _SWAP_WORD(X, /* Elf32_Word */ Elf64_Word)
1304 #define _SWAP_WORD64(X, T) do { \
1305 uint64_t _x = (uint64_t) (X); \
1306 uint64_t _t = _x & 0xFF; \
1307 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
1308 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
1309 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
1310 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
1311 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
1312 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
1313 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
1314 (X) = (T) _t; \
1315 } while (0)
1316 #define SWAP_ADDR64(X) _SWAP_WORD64(X, Elf64_Addr)
1317 #define SWAP_LWORD(X) _SWAP_WORD64(X, Elf64_Lword)
1318 #define SWAP_OFF64(X) _SWAP_WORD64(X, Elf64_Off)
1319 #define SWAP_SXWORD(X) _SWAP_WORD64(X, Elf64_Sxword)
1320 #define SWAP_XWORD(X) _SWAP_WORD64(X, Elf64_Xword)
1322 #define READ_BYTE(P,X) do { \
1323 const unsigned char *const _p = \
1324 (const unsigned char *) (P); \
1325 (X) = _p[0]; \
1326 (P) = (P) + 1; \
1327 } while (0)
1328 #define READ_HALF(P,X) do { \
1329 uint16_t _t; \
1330 unsigned char *const _q = (unsigned char *) &_t; \
1331 const unsigned char *const _p = \
1332 (const unsigned char *) (P); \
1333 _q[0] = _p[0]; \
1334 _q[1] = _p[1]; \
1335 (P) = (P) + 2; \
1336 (X) = _t; \
1337 } while (0)
1338 #define _READ_WORD(P,X,T) do { \
1339 uint32_t _t; \
1340 unsigned char *const _q = (unsigned char *) &_t; \
1341 const unsigned char *const _p = \
1342 (const unsigned char *) (P); \
1343 _q[0] = _p[0]; \
1344 _q[1] = _p[1]; \
1345 _q[2] = _p[2]; \
1346 _q[3] = _p[3]; \
1347 (P) = (P) + 4; \
1348 (X) = (T) _t; \
1349 } while (0)
1350 #define READ_SWORD(P,X) _READ_WORD(P, X, /*Elf32_Sword*/ Elf64_Sword)
1351 #define READ_WORD(P,X) _READ_WORD(P, X, /*Elf32_Word*/ Elf64_Word)
1352 #define _READ_WORD64(P,X,T) do { \
1353 uint64_t _t; \
1354 unsigned char *const _q = (unsigned char *) &_t; \
1355 const unsigned char *const _p = \
1356 (const unsigned char *) (P); \
1357 _q[0] = _p[0]; \
1358 _q[1] = _p[1]; \
1359 _q[2] = _p[2]; \
1360 _q[3] = _p[3]; \
1361 _q[4] = _p[4]; \
1362 _q[5] = _p[5]; \
1363 _q[6] = _p[6]; \
1364 _q[7] = _p[7]; \
1365 (P) = (P) + 8; \
1366 (X) = (T) _t; \
1367 } while (0)
1368 #define READ_ADDR64(P,X) _READ_WORD64(P, X, Elf64_Addr)
1369 #define READ_LWORD(P,X) _READ_WORD64(P, X, Elf64_Lword)
1370 #define READ_OFF64(P,X) _READ_WORD64(P, X, Elf64_Off)
1371 #define READ_SXWORD(P,X) _READ_WORD64(P, X, Elf64_Sxword)
1372 #define READ_XWORD(P,X) _READ_WORD64(P, X, Elf64_Xword)
1373 #define READ_IDENT(P,X) do { \
1374 (void) memcpy((X), (P), sizeof((X))); \
1375 (P) = (P) + EI_NIDENT; \
1376 } while (0)
1378 #define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1))
1380 static int
1381 _libelf_cvt_ADDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1382 size_t count, int byteswap)
1384 Elf64_Addr t, *d = (Elf64_Addr *) (uintptr_t) dst;
1385 size_t c;
1387 if (dsz < count * sizeof(Elf64_Addr))
1388 return (0);
1390 if (!byteswap) {
1391 (void) memcpy(dst, src, count * sizeof(*d));
1392 return (1);
1395 for (c = 0; c < count; c++) {
1396 READ_ADDR64(src,t);
1397 SWAP_ADDR64(t);
1398 *d++ = t;
1401 return (1);
1404 static int
1405 _libelf_cvt_CAP64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1406 size_t count, int byteswap)
1408 Elf64_Cap t, *d;
1409 unsigned char *s,*s0;
1410 size_t fsz;
1412 fsz = elf64_fsize(ELF_T_CAP, (size_t) 1, EV_CURRENT);
1413 d = ((Elf64_Cap *) (uintptr_t) dst) + (count - 1);
1414 s0 = src + (count - 1) * fsz;
1416 if (dsz < count * sizeof(Elf64_Cap))
1417 return (0);
1419 while (count--) {
1420 s = s0;
1421 /* Read an Elf64_Cap */
1422 READ_XWORD(s,t.c_tag);
1423 READ_XWORD(s,t.c_un.c_val);
1424 /**/
1425 if (byteswap) {
1426 /* Swap an Elf64_Cap */
1427 SWAP_XWORD(t.c_tag);
1428 SWAP_XWORD(t.c_un.c_val);
1429 /**/
1431 *d-- = t; s0 -= fsz;
1434 return (1);
1437 static int
1438 _libelf_cvt_DYN64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1439 size_t count, int byteswap)
1441 Elf64_Dyn t, *d;
1442 unsigned char *s,*s0;
1443 size_t fsz;
1445 fsz = elf64_fsize(ELF_T_DYN, (size_t) 1, EV_CURRENT);
1446 d = ((Elf64_Dyn *) (uintptr_t) dst) + (count - 1);
1447 s0 = src + (count - 1) * fsz;
1449 if (dsz < count * sizeof(Elf64_Dyn))
1450 return (0);
1452 while (count--) {
1453 s = s0;
1454 /* Read an Elf64_Dyn */
1455 READ_SXWORD(s,t.d_tag);
1456 READ_XWORD(s,t.d_un.d_ptr);
1457 /**/
1458 if (byteswap) {
1459 /* Swap an Elf64_Dyn */
1460 SWAP_SXWORD(t.d_tag);
1461 SWAP_XWORD(t.d_un.d_ptr);
1462 /**/
1464 *d-- = t; s0 -= fsz;
1467 return (1);
1470 static int
1471 _libelf_cvt_EHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1472 size_t count, int byteswap)
1474 Elf64_Ehdr t, *d;
1475 unsigned char *s,*s0;
1476 size_t fsz;
1478 fsz = elf64_fsize(ELF_T_EHDR, (size_t) 1, EV_CURRENT);
1479 d = ((Elf64_Ehdr *) (uintptr_t) dst) + (count - 1);
1480 s0 = src + (count - 1) * fsz;
1482 if (dsz < count * sizeof(Elf64_Ehdr))
1483 return (0);
1485 while (count--) {
1486 s = s0;
1487 /* Read an Elf64_Ehdr */
1488 READ_IDENT(s,t.e_ident);
1489 READ_HALF(s,t.e_type);
1490 READ_HALF(s,t.e_machine);
1491 READ_WORD(s,t.e_version);
1492 READ_ADDR64(s,t.e_entry);
1493 READ_OFF64(s,t.e_phoff);
1494 READ_OFF64(s,t.e_shoff);
1495 READ_WORD(s,t.e_flags);
1496 READ_HALF(s,t.e_ehsize);
1497 READ_HALF(s,t.e_phentsize);
1498 READ_HALF(s,t.e_phnum);
1499 READ_HALF(s,t.e_shentsize);
1500 READ_HALF(s,t.e_shnum);
1501 READ_HALF(s,t.e_shstrndx);
1502 /**/
1503 if (byteswap) {
1504 /* Swap an Elf64_Ehdr */
1505 SWAP_IDENT(t.e_ident);
1506 SWAP_HALF(t.e_type);
1507 SWAP_HALF(t.e_machine);
1508 SWAP_WORD(t.e_version);
1509 SWAP_ADDR64(t.e_entry);
1510 SWAP_OFF64(t.e_phoff);
1511 SWAP_OFF64(t.e_shoff);
1512 SWAP_WORD(t.e_flags);
1513 SWAP_HALF(t.e_ehsize);
1514 SWAP_HALF(t.e_phentsize);
1515 SWAP_HALF(t.e_phnum);
1516 SWAP_HALF(t.e_shentsize);
1517 SWAP_HALF(t.e_shnum);
1518 SWAP_HALF(t.e_shstrndx);
1519 /**/
1521 *d-- = t; s0 -= fsz;
1524 return (1);
1527 static int
1528 _libelf_cvt_HALF_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1529 size_t count, int byteswap)
1531 Elf64_Half t, *d = (Elf64_Half *) (uintptr_t) dst;
1532 size_t c;
1534 if (dsz < count * sizeof(Elf64_Half))
1535 return (0);
1537 if (!byteswap) {
1538 (void) memcpy(dst, src, count * sizeof(*d));
1539 return (1);
1542 for (c = 0; c < count; c++) {
1543 READ_HALF(src,t);
1544 SWAP_HALF(t);
1545 *d++ = t;
1548 return (1);
1551 static int
1552 _libelf_cvt_LWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1553 size_t count, int byteswap)
1555 Elf64_Lword t, *d = (Elf64_Lword *) (uintptr_t) dst;
1556 size_t c;
1558 if (dsz < count * sizeof(Elf64_Lword))
1559 return (0);
1561 if (!byteswap) {
1562 (void) memcpy(dst, src, count * sizeof(*d));
1563 return (1);
1566 for (c = 0; c < count; c++) {
1567 READ_LWORD(src,t);
1568 SWAP_LWORD(t);
1569 *d++ = t;
1572 return (1);
1575 static int
1576 _libelf_cvt_MOVE64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1577 size_t count, int byteswap)
1579 Elf64_Move t, *d;
1580 unsigned char *s,*s0;
1581 size_t fsz;
1583 fsz = elf64_fsize(ELF_T_MOVE, (size_t) 1, EV_CURRENT);
1584 d = ((Elf64_Move *) (uintptr_t) dst) + (count - 1);
1585 s0 = src + (count - 1) * fsz;
1587 if (dsz < count * sizeof(Elf64_Move))
1588 return (0);
1590 while (count--) {
1591 s = s0;
1592 /* Read an Elf64_Move */
1593 READ_LWORD(s,t.m_value);
1594 READ_XWORD(s,t.m_info);
1595 READ_XWORD(s,t.m_poffset);
1596 READ_HALF(s,t.m_repeat);
1597 READ_HALF(s,t.m_stride);
1598 /**/
1599 if (byteswap) {
1600 /* Swap an Elf64_Move */
1601 SWAP_LWORD(t.m_value);
1602 SWAP_XWORD(t.m_info);
1603 SWAP_XWORD(t.m_poffset);
1604 SWAP_HALF(t.m_repeat);
1605 SWAP_HALF(t.m_stride);
1606 /**/
1608 *d-- = t; s0 -= fsz;
1611 return (1);
1614 static int
1615 _libelf_cvt_OFF64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1616 size_t count, int byteswap)
1618 Elf64_Off t, *d = (Elf64_Off *) (uintptr_t) dst;
1619 size_t c;
1621 if (dsz < count * sizeof(Elf64_Off))
1622 return (0);
1624 if (!byteswap) {
1625 (void) memcpy(dst, src, count * sizeof(*d));
1626 return (1);
1629 for (c = 0; c < count; c++) {
1630 READ_OFF64(src,t);
1631 SWAP_OFF64(t);
1632 *d++ = t;
1635 return (1);
1638 static int
1639 _libelf_cvt_PHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1640 size_t count, int byteswap)
1642 Elf64_Phdr t, *d;
1643 unsigned char *s,*s0;
1644 size_t fsz;
1646 fsz = elf64_fsize(ELF_T_PHDR, (size_t) 1, EV_CURRENT);
1647 d = ((Elf64_Phdr *) (uintptr_t) dst) + (count - 1);
1648 s0 = src + (count - 1) * fsz;
1650 if (dsz < count * sizeof(Elf64_Phdr))
1651 return (0);
1653 while (count--) {
1654 s = s0;
1655 /* Read an Elf64_Phdr */
1656 READ_WORD(s,t.p_type);
1657 READ_WORD(s,t.p_flags);
1658 READ_OFF64(s,t.p_offset);
1659 READ_ADDR64(s,t.p_vaddr);
1660 READ_ADDR64(s,t.p_paddr);
1661 READ_XWORD(s,t.p_filesz);
1662 READ_XWORD(s,t.p_memsz);
1663 READ_XWORD(s,t.p_align);
1664 /**/
1665 if (byteswap) {
1666 /* Swap an Elf64_Phdr */
1667 SWAP_WORD(t.p_type);
1668 SWAP_WORD(t.p_flags);
1669 SWAP_OFF64(t.p_offset);
1670 SWAP_ADDR64(t.p_vaddr);
1671 SWAP_ADDR64(t.p_paddr);
1672 SWAP_XWORD(t.p_filesz);
1673 SWAP_XWORD(t.p_memsz);
1674 SWAP_XWORD(t.p_align);
1675 /**/
1677 *d-- = t; s0 -= fsz;
1680 return (1);
1683 static int
1684 _libelf_cvt_REL64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1685 size_t count, int byteswap)
1687 Elf64_Rel t, *d;
1688 unsigned char *s,*s0;
1689 size_t fsz;
1691 fsz = elf64_fsize(ELF_T_REL, (size_t) 1, EV_CURRENT);
1692 d = ((Elf64_Rel *) (uintptr_t) dst) + (count - 1);
1693 s0 = src + (count - 1) * fsz;
1695 if (dsz < count * sizeof(Elf64_Rel))
1696 return (0);
1698 while (count--) {
1699 s = s0;
1700 /* Read an Elf64_Rel */
1701 READ_ADDR64(s,t.r_offset);
1702 READ_XWORD(s,t.r_info);
1703 /**/
1704 if (byteswap) {
1705 /* Swap an Elf64_Rel */
1706 SWAP_ADDR64(t.r_offset);
1707 SWAP_XWORD(t.r_info);
1708 /**/
1710 *d-- = t; s0 -= fsz;
1713 return (1);
1716 static int
1717 _libelf_cvt_RELA64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1718 size_t count, int byteswap)
1720 Elf64_Rela t, *d;
1721 unsigned char *s,*s0;
1722 size_t fsz;
1724 fsz = elf64_fsize(ELF_T_RELA, (size_t) 1, EV_CURRENT);
1725 d = ((Elf64_Rela *) (uintptr_t) dst) + (count - 1);
1726 s0 = src + (count - 1) * fsz;
1728 if (dsz < count * sizeof(Elf64_Rela))
1729 return (0);
1731 while (count--) {
1732 s = s0;
1733 /* Read an Elf64_Rela */
1734 READ_ADDR64(s,t.r_offset);
1735 READ_XWORD(s,t.r_info);
1736 READ_SXWORD(s,t.r_addend);
1737 /**/
1738 if (byteswap) {
1739 /* Swap an Elf64_Rela */
1740 SWAP_ADDR64(t.r_offset);
1741 SWAP_XWORD(t.r_info);
1742 SWAP_SXWORD(t.r_addend);
1743 /**/
1745 *d-- = t; s0 -= fsz;
1748 return (1);
1751 static int
1752 _libelf_cvt_SHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1753 size_t count, int byteswap)
1755 Elf64_Shdr t, *d;
1756 unsigned char *s,*s0;
1757 size_t fsz;
1759 fsz = elf64_fsize(ELF_T_SHDR, (size_t) 1, EV_CURRENT);
1760 d = ((Elf64_Shdr *) (uintptr_t) dst) + (count - 1);
1761 s0 = src + (count - 1) * fsz;
1763 if (dsz < count * sizeof(Elf64_Shdr))
1764 return (0);
1766 while (count--) {
1767 s = s0;
1768 /* Read an Elf64_Shdr */
1769 READ_WORD(s,t.sh_name);
1770 READ_WORD(s,t.sh_type);
1771 READ_XWORD(s,t.sh_flags);
1772 READ_ADDR64(s,t.sh_addr);
1773 READ_OFF64(s,t.sh_offset);
1774 READ_XWORD(s,t.sh_size);
1775 READ_WORD(s,t.sh_link);
1776 READ_WORD(s,t.sh_info);
1777 READ_XWORD(s,t.sh_addralign);
1778 READ_XWORD(s,t.sh_entsize);
1779 /**/
1780 if (byteswap) {
1781 /* Swap an Elf64_Shdr */
1782 SWAP_WORD(t.sh_name);
1783 SWAP_WORD(t.sh_type);
1784 SWAP_XWORD(t.sh_flags);
1785 SWAP_ADDR64(t.sh_addr);
1786 SWAP_OFF64(t.sh_offset);
1787 SWAP_XWORD(t.sh_size);
1788 SWAP_WORD(t.sh_link);
1789 SWAP_WORD(t.sh_info);
1790 SWAP_XWORD(t.sh_addralign);
1791 SWAP_XWORD(t.sh_entsize);
1792 /**/
1794 *d-- = t; s0 -= fsz;
1797 return (1);
1800 static int
1801 _libelf_cvt_SWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1802 size_t count, int byteswap)
1804 Elf64_Sword t, *d = (Elf64_Sword *) (uintptr_t) dst;
1805 size_t c;
1807 if (dsz < count * sizeof(Elf64_Sword))
1808 return (0);
1810 if (!byteswap) {
1811 (void) memcpy(dst, src, count * sizeof(*d));
1812 return (1);
1815 for (c = 0; c < count; c++) {
1816 READ_SWORD(src,t);
1817 SWAP_SWORD(t);
1818 *d++ = t;
1821 return (1);
1824 static int
1825 _libelf_cvt_SXWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1826 size_t count, int byteswap)
1828 Elf64_Sxword t, *d = (Elf64_Sxword *) (uintptr_t) dst;
1829 size_t c;
1831 if (dsz < count * sizeof(Elf64_Sxword))
1832 return (0);
1834 if (!byteswap) {
1835 (void) memcpy(dst, src, count * sizeof(*d));
1836 return (1);
1839 for (c = 0; c < count; c++) {
1840 READ_SXWORD(src,t);
1841 SWAP_SXWORD(t);
1842 *d++ = t;
1845 return (1);
1848 static int
1849 _libelf_cvt_SYMINFO64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1850 size_t count, int byteswap)
1852 Elf64_Syminfo t, *d;
1853 unsigned char *s,*s0;
1854 size_t fsz;
1856 fsz = elf64_fsize(ELF_T_SYMINFO, (size_t) 1, EV_CURRENT);
1857 d = ((Elf64_Syminfo *) (uintptr_t) dst) + (count - 1);
1858 s0 = src + (count - 1) * fsz;
1860 if (dsz < count * sizeof(Elf64_Syminfo))
1861 return (0);
1863 while (count--) {
1864 s = s0;
1865 /* Read an Elf64_Syminfo */
1866 READ_HALF(s,t.si_boundto);
1867 READ_HALF(s,t.si_flags);
1868 /**/
1869 if (byteswap) {
1870 /* Swap an Elf64_Syminfo */
1871 SWAP_HALF(t.si_boundto);
1872 SWAP_HALF(t.si_flags);
1873 /**/
1875 *d-- = t; s0 -= fsz;
1878 return (1);
1881 static int
1882 _libelf_cvt_SYM64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1883 size_t count, int byteswap)
1885 Elf64_Sym t, *d;
1886 unsigned char *s,*s0;
1887 size_t fsz;
1889 fsz = elf64_fsize(ELF_T_SYM, (size_t) 1, EV_CURRENT);
1890 d = ((Elf64_Sym *) (uintptr_t) dst) + (count - 1);
1891 s0 = src + (count - 1) * fsz;
1893 if (dsz < count * sizeof(Elf64_Sym))
1894 return (0);
1896 while (count--) {
1897 s = s0;
1898 /* Read an Elf64_Sym */
1899 READ_WORD(s,t.st_name);
1900 READ_BYTE(s,t.st_info);
1901 READ_BYTE(s,t.st_other);
1902 READ_HALF(s,t.st_shndx);
1903 READ_ADDR64(s,t.st_value);
1904 READ_XWORD(s,t.st_size);
1905 /**/
1906 if (byteswap) {
1907 /* Swap an Elf64_Sym */
1908 SWAP_WORD(t.st_name);
1909 SWAP_BYTE(t.st_info);
1910 SWAP_BYTE(t.st_other);
1911 SWAP_HALF(t.st_shndx);
1912 SWAP_ADDR64(t.st_value);
1913 SWAP_XWORD(t.st_size);
1914 /**/
1916 *d-- = t; s0 -= fsz;
1919 return (1);
1922 static int
1923 _libelf_cvt_WORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1924 size_t count, int byteswap)
1926 Elf64_Word t, *d = (Elf64_Word *) (uintptr_t) dst;
1927 size_t c;
1929 if (dsz < count * sizeof(Elf64_Word))
1930 return (0);
1932 if (!byteswap) {
1933 (void) memcpy(dst, src, count * sizeof(*d));
1934 return (1);
1937 for (c = 0; c < count; c++) {
1938 READ_WORD(src,t);
1939 SWAP_WORD(t);
1940 *d++ = t;
1943 return (1);
1946 static int
1947 _libelf_cvt_XWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1948 size_t count, int byteswap)
1950 Elf64_Xword t, *d = (Elf64_Xword *) (uintptr_t) dst;
1951 size_t c;
1953 if (dsz < count * sizeof(Elf64_Xword))
1954 return (0);
1956 if (!byteswap) {
1957 (void) memcpy(dst, src, count * sizeof(*d));
1958 return (1);
1961 for (c = 0; c < count; c++) {
1962 READ_XWORD(src,t);
1963 SWAP_XWORD(t);
1964 *d++ = t;
1967 return (1);
1970 static int
1971 _libelf_cvt_VDEF64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1972 size_t count, int byteswap)
1974 Elf64_Verdef t, *dp;
1975 Elf64_Verdaux a, *ap;
1976 const size_t verfsz = 20;
1977 const size_t auxfsz = 8;
1978 const size_t vermsz = sizeof(Elf64_Verdef);
1979 const size_t auxmsz = sizeof(Elf64_Verdaux);
1980 unsigned char * const dstend = dst + dsz;
1981 unsigned char * const srcend = src + count;
1982 unsigned char *dstaux, *s, *srcaux, *stmp;
1983 Elf64_Word aux, anext, cnt, vnext;
1985 for (stmp = src, vnext = ~0U;
1986 vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
1987 stmp += vnext, dst += vnext) {
1989 /* Read in a VDEF structure. */
1990 s = stmp;
1991 /* Read an Elf64_Verdef */
1992 READ_HALF(s,t.vd_version);
1993 READ_HALF(s,t.vd_flags);
1994 READ_HALF(s,t.vd_ndx);
1995 READ_HALF(s,t.vd_cnt);
1996 READ_WORD(s,t.vd_hash);
1997 READ_WORD(s,t.vd_aux);
1998 READ_WORD(s,t.vd_next);
1999 /**/
2000 if (byteswap) {
2001 /* Swap an Elf64_Verdef */
2002 SWAP_HALF(t.vd_version);
2003 SWAP_HALF(t.vd_flags);
2004 SWAP_HALF(t.vd_ndx);
2005 SWAP_HALF(t.vd_cnt);
2006 SWAP_WORD(t.vd_hash);
2007 SWAP_WORD(t.vd_aux);
2008 SWAP_WORD(t.vd_next);
2009 /**/
2012 dp = (Elf64_Verdef *) (uintptr_t) dst;
2013 *dp = t;
2015 aux = t.vd_aux;
2016 cnt = t.vd_cnt;
2017 vnext = t.vd_next;
2019 if (aux < vermsz)
2020 return (0);
2022 /* Process AUX entries. */
2023 for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux;
2024 cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
2025 srcaux + auxfsz <= srcend;
2026 dstaux += anext, srcaux += anext, cnt--) {
2028 s = srcaux;
2029 /* Read an Elf64_Verdaux */
2030 READ_WORD(s,a.vda_name);
2031 READ_WORD(s,a.vda_next);
2032 /**/
2034 if (byteswap) {
2035 /* Swap an Elf64_Verdaux */
2036 SWAP_WORD(a.vda_name);
2037 SWAP_WORD(a.vda_next);
2038 /**/
2041 anext = a.vda_next;
2043 ap = ((Elf64_Verdaux *) (uintptr_t) dstaux);
2044 *ap = a;
2047 if (anext || cnt)
2048 return (0);
2051 if (vnext)
2052 return (0);
2054 return (1);
2057 static int
2058 _libelf_cvt_VNEED64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
2059 size_t count, int byteswap)
2061 Elf64_Verneed t, *dp;
2062 Elf64_Vernaux a, *ap;
2063 const size_t verfsz = 16;
2064 const size_t auxfsz = 16;
2065 const size_t vermsz = sizeof(Elf64_Verneed);
2066 const size_t auxmsz = sizeof(Elf64_Vernaux);
2067 unsigned char * const dstend = dst + dsz;
2068 unsigned char * const srcend = src + count;
2069 unsigned char *dstaux, *s, *srcaux, *stmp;
2070 Elf64_Word aux, anext, cnt, vnext;
2072 for (stmp = src, vnext = ~0U;
2073 vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
2074 stmp += vnext, dst += vnext) {
2076 /* Read in a VNEED structure. */
2077 s = stmp;
2078 /* Read an Elf64_Verneed */
2079 READ_HALF(s,t.vn_version);
2080 READ_HALF(s,t.vn_cnt);
2081 READ_WORD(s,t.vn_file);
2082 READ_WORD(s,t.vn_aux);
2083 READ_WORD(s,t.vn_next);
2084 /**/
2085 if (byteswap) {
2086 /* Swap an Elf64_Verneed */
2087 SWAP_HALF(t.vn_version);
2088 SWAP_HALF(t.vn_cnt);
2089 SWAP_WORD(t.vn_file);
2090 SWAP_WORD(t.vn_aux);
2091 SWAP_WORD(t.vn_next);
2092 /**/
2095 dp = (Elf64_Verneed *) (uintptr_t) dst;
2096 *dp = t;
2098 aux = t.vn_aux;
2099 cnt = t.vn_cnt;
2100 vnext = t.vn_next;
2102 if (aux < vermsz)
2103 return (0);
2105 /* Process AUX entries. */
2106 for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux;
2107 cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
2108 srcaux + auxfsz <= srcend;
2109 dstaux += anext, srcaux += anext, cnt--) {
2111 s = srcaux;
2112 /* Read an Elf64_Vernaux */
2113 READ_WORD(s,a.vna_hash);
2114 READ_HALF(s,a.vna_flags);
2115 READ_HALF(s,a.vna_other);
2116 READ_WORD(s,a.vna_name);
2117 READ_WORD(s,a.vna_next);
2118 /**/
2120 if (byteswap) {
2121 /* Swap an Elf64_Vernaux */
2122 SWAP_WORD(a.vna_hash);
2123 SWAP_HALF(a.vna_flags);
2124 SWAP_HALF(a.vna_other);
2125 SWAP_WORD(a.vna_name);
2126 SWAP_WORD(a.vna_next);
2127 /**/
2130 anext = a.vna_next;
2132 ap = ((Elf64_Vernaux *) (uintptr_t) dstaux);
2133 *ap = a;
2136 if (anext || cnt)
2137 return (0);
2140 if (vnext)
2141 return (0);
2143 return (1);
2146 static int
2147 _libelf_cvt_BYTE_tox(unsigned char *dst, size_t dsz, unsigned char *src,
2148 size_t count, int byteswap)
2150 (void) byteswap;
2151 if (dsz < count)
2152 return (0);
2153 if (dst != src)
2154 (void) memcpy(dst, src, count);
2155 return (1);
2158 static int
2159 _libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
2160 size_t srcsz, int byteswap)
2162 size_t sz;
2163 uint64_t t64, *bloom64;
2164 Elf_GNU_Hash_Header *gh;
2165 uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
2166 uint32_t *buckets, *chains;
2168 sz = 4 * sizeof(uint32_t); /* File header is 4 words long. */
2169 if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
2170 return (0);
2172 /* Read in the section header and byteswap if needed. */
2173 READ_WORD(src, nbuckets);
2174 READ_WORD(src, symndx);
2175 READ_WORD(src, maskwords);
2176 READ_WORD(src, shift2);
2178 srcsz -= sz;
2180 if (byteswap) {
2181 SWAP_WORD(nbuckets);
2182 SWAP_WORD(symndx);
2183 SWAP_WORD(maskwords);
2184 SWAP_WORD(shift2);
2187 /* Check source buffer and destination buffer sizes. */
2188 sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
2189 if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
2190 return (0);
2192 gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
2193 gh->gh_nbuckets = nbuckets;
2194 gh->gh_symndx = symndx;
2195 gh->gh_maskwords = maskwords;
2196 gh->gh_shift2 = shift2;
2198 dsz -= sizeof(Elf_GNU_Hash_Header);
2199 dst += sizeof(Elf_GNU_Hash_Header);
2201 bloom64 = (uint64_t *) (uintptr_t) dst;
2203 /* Copy bloom filter data. */
2204 for (n = 0; n < maskwords; n++) {
2205 READ_XWORD(src, t64);
2206 if (byteswap)
2207 SWAP_XWORD(t64);
2208 bloom64[n] = t64;
2211 /* The hash buckets follows the bloom filter. */
2212 dst += maskwords * sizeof(uint64_t);
2213 buckets = (uint32_t *) (uintptr_t) dst;
2215 for (n = 0; n < nbuckets; n++) {
2216 READ_WORD(src, t32);
2217 if (byteswap)
2218 SWAP_WORD(t32);
2219 buckets[n] = t32;
2222 dst += nbuckets * sizeof(uint32_t);
2224 /* The hash chain follows the hash buckets. */
2225 dsz -= sz;
2226 srcsz -= sz;
2228 if (dsz < srcsz) /* Destination lacks space. */
2229 return (0);
2231 nchains = srcsz / sizeof(uint32_t);
2232 chains = (uint32_t *) (uintptr_t) dst;
2234 for (n = 0; n < nchains; n++) {
2235 READ_WORD(src, t32);
2236 if (byteswap)
2237 SWAP_WORD(t32);
2238 *chains++ = t32;
2241 return (1);
2244 static int
2245 _libelf_cvt_NOTE_tom(unsigned char *dst, size_t dsz, unsigned char *src,
2246 size_t count, int byteswap)
2248 uint32_t namesz, descsz, type;
2249 Elf_Note *en;
2250 size_t sz, hdrsz;
2252 if (dsz < count) /* Destination buffer is too small. */
2253 return (0);
2255 hdrsz = 3 * sizeof(uint32_t);
2256 if (count < hdrsz) /* Source too small. */
2257 return (0);
2259 if (!byteswap) {
2260 (void) memcpy(dst, src, count);
2261 return (1);
2264 /* Process all notes in the section. */
2265 while (count > hdrsz) {
2266 /* Read the note header. */
2267 READ_WORD(src, namesz);
2268 READ_WORD(src, descsz);
2269 READ_WORD(src, type);
2271 /* Translate. */
2272 SWAP_WORD(namesz);
2273 SWAP_WORD(descsz);
2274 SWAP_WORD(type);
2276 /* Copy out the translated note header. */
2277 en = (Elf_Note *) (uintptr_t) dst;
2278 en->n_namesz = namesz;
2279 en->n_descsz = descsz;
2280 en->n_type = type;
2282 dsz -= sizeof(Elf_Note);
2283 dst += sizeof(Elf_Note);
2284 count -= hdrsz;
2286 ROUNDUP2(namesz, 4U);
2287 ROUNDUP2(descsz, 4U);
2289 sz = namesz + descsz;
2291 if (count < sz || dsz < sz) /* Buffers are too small. */
2292 return (0);
2294 (void) memcpy(dst, src, sz);
2296 src += sz;
2297 dst += sz;
2299 count -= sz;
2300 dsz -= sz;
2303 return (1);
2306 struct converters {
2307 int (*tof32)(unsigned char *dst, size_t dsz, unsigned char *src,
2308 size_t cnt, int byteswap);
2309 int (*tom32)(unsigned char *dst, size_t dsz, unsigned char *src,
2310 size_t cnt, int byteswap);
2311 int (*tof64)(unsigned char *dst, size_t dsz, unsigned char *src,
2312 size_t cnt, int byteswap);
2313 int (*tom64)(unsigned char *dst, size_t dsz, unsigned char *src,
2314 size_t cnt, int byteswap);
2317 static struct converters cvt[ELF_T_NUM] = {
2318 /*[*/
2319 [ELF_T_ADDR] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2320 .tom64 = _libelf_cvt_ADDR64_tom },
2321 [ELF_T_CAP] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2322 .tom64 = _libelf_cvt_CAP64_tom },
2323 [ELF_T_DYN] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2324 .tom64 = _libelf_cvt_DYN64_tom },
2325 [ELF_T_EHDR] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2326 .tom64 = _libelf_cvt_EHDR64_tom },
2327 [ELF_T_GNUHASH] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2328 .tom64 = _libelf_cvt_GNUHASH64_tom },
2329 [ELF_T_HALF] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2330 .tom64 = _libelf_cvt_HALF_tom },
2331 [ELF_T_LWORD] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2332 .tom64 = _libelf_cvt_LWORD_tom },
2333 [ELF_T_MOVE] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2334 .tom64 = _libelf_cvt_MOVE64_tom },
2335 [ELF_T_OFF] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2336 .tom64 = _libelf_cvt_OFF64_tom },
2337 [ELF_T_PHDR] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2338 .tom64 = _libelf_cvt_PHDR64_tom },
2339 [ELF_T_REL] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2340 .tom64 = _libelf_cvt_REL64_tom },
2341 [ELF_T_RELA] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2342 .tom64 = _libelf_cvt_RELA64_tom },
2343 [ELF_T_SHDR] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2344 .tom64 = _libelf_cvt_SHDR64_tom },
2345 [ELF_T_SWORD] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2346 .tom64 = _libelf_cvt_SWORD_tom },
2347 [ELF_T_SXWORD] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2348 .tom64 = _libelf_cvt_SXWORD_tom },
2349 [ELF_T_SYMINFO] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2350 .tom64 = _libelf_cvt_SYMINFO64_tom },
2351 [ELF_T_SYM] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2352 .tom64 = _libelf_cvt_SYM64_tom },
2353 [ELF_T_VDEF] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2354 .tom64 = _libelf_cvt_VDEF64_tom },
2355 [ELF_T_VNEED] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2356 .tom64 = _libelf_cvt_VNEED64_tom },
2357 [ELF_T_WORD] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2358 .tom64 = _libelf_cvt_WORD_tom },
2359 [ELF_T_XWORD] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2360 .tom64 = _libelf_cvt_XWORD_tom },
2361 /*]*/
2363 * Types that need hand-coded converters follow.
2365 [ELF_T_BYTE] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2366 .tom64 = _libelf_cvt_BYTE_tox },
2367 [ELF_T_NOTE] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2368 .tom64 = _libelf_cvt_NOTE_tom }
2371 static int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
2372 (unsigned char *_dst, size_t dsz, unsigned char *_src, size_t _cnt,
2373 int _byteswap)
2375 assert(/* elfclass == ELFCLASS32 || */ elfclass == ELFCLASS64);
2376 assert(/* direction == ELF_TOFILE || */ direction == ELF_TOMEMORY);
2378 if (t >= ELF_T_NUM ||
2379 (/* elfclass != ELFCLASS32 && */ elfclass != ELFCLASS64) ||
2380 (/* direction != ELF_TOFILE && */ direction != ELF_TOMEMORY))
2381 return (NULL);
2383 #if 1
2384 return cvt[t].tom64;
2385 #else
2386 return ((elfclass == ELFCLASS32) ?
2387 (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
2388 (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));
2389 #endif
2392 /* libelf_ehdr.h */
2394 * Retrieve counts for sections, phdrs and the section string table index
2395 * from section header #0 of the ELF object.
2397 static int
2398 _libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
2399 uint16_t strndx)
2401 Elf_Scn *scn;
2402 size_t fsz;
2403 int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
2404 size_t _c, int _swap);
2405 uint32_t shtype;
2407 assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
2409 fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1);
2410 assert(fsz > 0);
2412 if (e->e_rawsize < shoff + fsz) { /* raw file too small */
2413 LIBELF_SET_ERROR(HEADER, 0);
2414 return (0);
2417 if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL)
2418 return (0);
2420 xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
2421 (*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
2422 (unsigned char *) e->e_rawfile + shoff, (size_t) 1,
2423 e->e_byteorder != LIBELF_PRIVATE(byteorder));
2425 #define GET_SHDR_MEMBER(M) (/* (ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M :*/ \
2426 scn->s_shdr.s_shdr64.M)
2428 if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) {
2429 LIBELF_SET_ERROR(SECTION, 0);
2430 return (0);
2433 e->e_u.e_elf.e_nscn = (size_t) GET_SHDR_MEMBER(sh_size);
2434 e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum :
2435 GET_SHDR_MEMBER(sh_info);
2436 e->e_u.e_elf.e_strndx = (strndx != SHN_XINDEX) ? strndx :
2437 GET_SHDR_MEMBER(sh_link);
2438 #undef GET_SHDR_MEMBER
2440 return (1);
2443 #define EHDR_INIT(E,SZ) do { \
2444 Elf##SZ##_Ehdr *eh = (E); \
2445 eh->e_ident[EI_MAG0] = ELFMAG0; \
2446 eh->e_ident[EI_MAG1] = ELFMAG1; \
2447 eh->e_ident[EI_MAG2] = ELFMAG2; \
2448 eh->e_ident[EI_MAG3] = ELFMAG3; \
2449 eh->e_ident[EI_CLASS] = ELFCLASS##SZ; \
2450 eh->e_ident[EI_DATA] = ELFDATANONE; \
2451 eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version) & 0xFFU; \
2452 eh->e_machine = EM_NONE; \
2453 eh->e_type = ELF_K_NONE; \
2454 eh->e_version = LIBELF_PRIVATE(version); \
2455 } while (0)
2457 static void *
2458 _libelf_ehdr(Elf *e, int ec, int allocate)
2460 void *ehdr;
2461 size_t fsz, msz;
2462 uint16_t phnum, shnum, strndx;
2463 uint64_t shoff;
2464 int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
2465 size_t _c, int _swap);
2467 assert(ec == ELFCLASS32 || ec == ELFCLASS64);
2469 if (e == NULL || e->e_kind != ELF_K_ELF) {
2470 LIBELF_SET_ERROR(ARGUMENT, 0);
2471 return (NULL);
2474 if (e->e_class != ELFCLASSNONE && e->e_class != ec) {
2475 LIBELF_SET_ERROR(CLASS, 0);
2476 return (NULL);
2479 if (e->e_version != EV_CURRENT) {
2480 LIBELF_SET_ERROR(VERSION, 0);
2481 return (NULL);
2484 if (e->e_class == ELFCLASSNONE)
2485 e->e_class = ec;
2487 #if 0
2488 if (ec == ELFCLASS32)
2489 ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr32;
2490 else
2491 #endif
2492 ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr64;
2494 if (ehdr != NULL) /* already have a translated ehdr */
2495 return (ehdr);
2497 fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
2498 assert(fsz > 0);
2500 if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) {
2501 LIBELF_SET_ERROR(HEADER, 0);
2502 return (NULL);
2505 msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT);
2507 assert(msz > 0);
2509 if ((ehdr = calloc((size_t) 1, msz)) == NULL) {
2510 LIBELF_SET_ERROR(RESOURCE, 0);
2511 return (NULL);
2514 #if 0
2515 if (ec == ELFCLASS32) {
2516 e->e_u.e_elf.e_ehdr.e_ehdr32 = ehdr;
2517 EHDR_INIT(ehdr,32);
2518 } else
2519 #endif
2521 e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr;
2522 EHDR_INIT(ehdr,64);
2525 if (allocate)
2526 e->e_flags |= ELF_F_DIRTY;
2528 if (e->e_cmd == ELF_C_WRITE)
2529 return (ehdr);
2531 xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec);
2532 (*xlator)((unsigned char*) ehdr, msz, e->e_rawfile, (size_t) 1,
2533 e->e_byteorder != LIBELF_PRIVATE(byteorder));
2536 * If extended numbering is being used, read the correct
2537 * number of sections and program header entries.
2539 #if 0
2540 if (ec == ELFCLASS32) {
2541 phnum = ((Elf32_Ehdr *) ehdr)->e_phnum;
2542 shnum = ((Elf32_Ehdr *) ehdr)->e_shnum;
2543 shoff = ((Elf32_Ehdr *) ehdr)->e_shoff;
2544 strndx = ((Elf32_Ehdr *) ehdr)->e_shstrndx;
2545 } else
2546 #endif
2548 phnum = ((Elf64_Ehdr *) ehdr)->e_phnum;
2549 shnum = ((Elf64_Ehdr *) ehdr)->e_shnum;
2550 shoff = ((Elf64_Ehdr *) ehdr)->e_shoff;
2551 strndx = ((Elf64_Ehdr *) ehdr)->e_shstrndx;
2554 if (shnum >= SHN_LORESERVE ||
2555 (shoff == 0LL && (shnum != 0 || phnum == PN_XNUM ||
2556 strndx == SHN_XINDEX))) {
2557 LIBELF_SET_ERROR(HEADER, 0);
2558 return (NULL);
2561 if (shnum != 0 || shoff == 0LL) { /* not using extended numbering */
2562 e->e_u.e_elf.e_nphdr = phnum;
2563 e->e_u.e_elf.e_nscn = shnum;
2564 e->e_u.e_elf.e_strndx = strndx;
2565 } else if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0)
2566 return (NULL);
2568 return (ehdr);
2571 /* libelf_shdr.c */
2572 static void *
2573 _libelf_getshdr(Elf_Scn *s, int ec)
2575 Elf *e;
2577 if (s == NULL || (e = s->s_elf) == NULL ||
2578 e->e_kind != ELF_K_ELF) {
2579 LIBELF_SET_ERROR(ARGUMENT, 0);
2580 return (NULL);
2583 if (ec == ELFCLASSNONE)
2584 ec = e->e_class;
2586 if (ec != e->e_class) {
2587 LIBELF_SET_ERROR(CLASS, 0);
2588 return (NULL);
2591 return ((void *) &s->s_shdr);
2594 /* elf_scn.c */
2595 static int
2596 _libelf_load_section_headers(Elf *e, void *ehdr)
2598 Elf_Scn *scn;
2599 uint64_t shoff;
2600 #if 0
2601 Elf32_Ehdr *eh32;
2602 #endif
2603 Elf64_Ehdr *eh64;
2604 int ec, swapbytes;
2605 unsigned char *src;
2606 size_t fsz, i, shnum;
2607 int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
2608 size_t _c, int _swap);
2610 assert(e != NULL);
2611 assert(ehdr != NULL);
2612 assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0);
2614 #define CHECK_EHDR(E,EH) do { \
2615 if (shoff > e->e_rawsize || \
2616 fsz != (EH)->e_shentsize || \
2617 shnum > SIZE_MAX / fsz || \
2618 fsz * shnum > e->e_rawsize - shoff) { \
2619 LIBELF_SET_ERROR(HEADER, 0); \
2620 return (0); \
2622 } while (0)
2624 ec = e->e_class;
2625 fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
2626 assert(fsz > 0);
2628 shnum = e->e_u.e_elf.e_nscn;
2630 #if 0
2631 if (ec == ELFCLASS32) {
2632 eh32 = (Elf32_Ehdr *) ehdr;
2633 shoff = (uint64_t) eh32->e_shoff;
2634 CHECK_EHDR(e, eh32);
2635 } else
2636 #endif
2638 eh64 = (Elf64_Ehdr *) ehdr;
2639 shoff = eh64->e_shoff;
2640 CHECK_EHDR(e, eh64);
2643 xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
2645 swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder);
2646 src = e->e_rawfile + shoff;
2649 * If the file is using extended numbering then section #0
2650 * would have already been read in.
2653 i = 0;
2654 if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
2655 assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) ==
2656 STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next));
2658 i = 1;
2659 src += fsz;
2662 for (; i < shnum; i++, src += fsz) {
2663 if ((scn = _libelf_allocate_scn(e, i)) == NULL)
2664 return (0);
2666 (*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
2667 src, (size_t) 1, swapbytes);
2669 #if 0
2670 if (ec == ELFCLASS32) {
2671 scn->s_offset = scn->s_rawoff =
2672 scn->s_shdr.s_shdr32.sh_offset;
2673 scn->s_size = scn->s_shdr.s_shdr32.sh_size;
2674 } else
2675 #endif
2677 scn->s_offset = scn->s_rawoff =
2678 scn->s_shdr.s_shdr64.sh_offset;
2679 scn->s_size = scn->s_shdr.s_shdr64.sh_size;
2683 e->e_flags |= LIBELF_F_SHDRS_LOADED;
2685 return (1);
2688 static Elf_Scn *
2689 elf_getscn(Elf *e, size_t index)
2691 int ec;
2692 void *ehdr;
2693 Elf_Scn *s;
2695 if (e == NULL || e->e_kind != ELF_K_ELF ||
2696 ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
2697 LIBELF_SET_ERROR(ARGUMENT, 0);
2698 return (NULL);
2701 if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
2702 return (NULL);
2704 if (e->e_cmd != ELF_C_WRITE &&
2705 (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 &&
2706 _libelf_load_section_headers(e, ehdr) == 0)
2707 return (NULL);
2709 STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next)
2710 if (s->s_ndx == index)
2711 return (s);
2713 LIBELF_SET_ERROR(ARGUMENT, 0);
2714 return (NULL);
2717 /* libelf_memory.c */
2718 static Elf *
2719 _libelf_memory(unsigned char *image, size_t sz, int reporterror)
2721 Elf *e;
2722 int e_class;
2723 enum Elf_Error error;
2724 unsigned int e_byteorder, e_version;
2726 assert(image != NULL);
2727 assert(sz > 0);
2729 if ((e = _libelf_allocate_elf()) == NULL)
2730 return (NULL);
2732 e->e_cmd = ELF_C_READ;
2733 e->e_rawfile = image;
2734 e->e_rawsize = sz;
2736 #undef LIBELF_IS_ELF
2737 #define LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 && \
2738 (P)[EI_MAG1] == ELFMAG1 && (P)[EI_MAG2] == ELFMAG2 && \
2739 (P)[EI_MAG3] == ELFMAG3)
2741 if (sz > EI_NIDENT && LIBELF_IS_ELF(image)) {
2742 e_byteorder = image[EI_DATA];
2743 e_class = image[EI_CLASS];
2744 e_version = image[EI_VERSION];
2746 error = ELF_E_NONE;
2748 if (e_version > EV_CURRENT)
2749 error = ELF_E_VERSION;
2750 else if ((e_byteorder != ELFDATA2LSB && e_byteorder !=
2751 ELFDATA2MSB) || (e_class != ELFCLASS32 && e_class !=
2752 ELFCLASS64))
2753 error = ELF_E_HEADER;
2755 if (error != ELF_E_NONE) {
2756 if (reporterror) {
2757 LIBELF_PRIVATE(error) = LIBELF_ERROR(error, 0);
2758 (void) _libelf_release_elf(e);
2759 return (NULL);
2761 } else {
2762 _libelf_init_elf(e, ELF_K_ELF);
2764 e->e_byteorder = e_byteorder;
2765 e->e_class = e_class;
2766 e->e_version = e_version;
2769 #if 0
2770 else if (sz >= SARMAG &&
2771 strncmp((const char *) image, ARMAG, (size_t) SARMAG) == 0)
2772 return (_libelf_ar_open(e, reporterror));
2773 #endif
2775 return (e);
2778 /* libelf_open.c */
2779 #define _LIBELF_INITSIZE (64*1024)
2781 static void *
2782 _libelf_read_special_file(int fd, size_t *fsz)
2784 ssize_t readsz;
2785 size_t bufsz, datasz;
2786 unsigned char *buf, *t;
2788 datasz = 0;
2789 readsz = 0;
2790 bufsz = _LIBELF_INITSIZE;
2791 if ((buf = malloc(bufsz)) == NULL)
2792 goto resourceerror;
2795 * Read data from the file descriptor till we reach EOF, or
2796 * till an error is encountered.
2798 do {
2799 /* Check if we need to expand the data buffer. */
2800 if (datasz == bufsz) {
2801 bufsz *= 2;
2802 if ((t = realloc(buf, bufsz)) == NULL)
2803 goto resourceerror;
2804 buf = t;
2807 do {
2808 assert(bufsz - datasz > 0);
2809 t = buf + datasz;
2810 if ((readsz = read(fd, t, bufsz - datasz)) <= 0)
2811 break;
2812 datasz += (size_t) readsz;
2813 } while (datasz < bufsz);
2815 } while (readsz > 0);
2817 if (readsz < 0) {
2818 LIBELF_SET_ERROR(IO, errno);
2819 goto error;
2822 assert(readsz == 0);
2825 * Free up extra buffer space.
2827 if (bufsz > datasz) {
2828 if (datasz > 0) {
2829 if ((t = realloc(buf, datasz)) == NULL)
2830 goto resourceerror;
2831 buf = t;
2832 } else { /* Zero bytes read. */
2833 LIBELF_SET_ERROR(ARGUMENT, 0);
2834 free(buf);
2835 buf = NULL;
2839 *fsz = datasz;
2840 return (buf);
2842 resourceerror:
2843 LIBELF_SET_ERROR(RESOURCE, 0);
2844 error:
2845 if (buf != NULL)
2846 free(buf);
2847 return (NULL);
2850 static Elf *
2851 _libelf_open_object(int fd, Elf_Cmd c, int reporterror)
2853 Elf *e;
2854 void *m;
2855 mode_t mode;
2856 size_t fsize;
2857 struct stat sb;
2858 unsigned int flags;
2860 assert(c == ELF_C_READ || c == ELF_C_RDWR || c == ELF_C_WRITE);
2862 if (fstat(fd, &sb) < 0) {
2863 LIBELF_SET_ERROR(IO, errno);
2864 return (NULL);
2867 mode = sb.st_mode;
2868 fsize = (size_t) sb.st_size;
2871 * Reject unsupported file types.
2873 if (!S_ISREG(mode) && !S_ISCHR(mode) && !S_ISFIFO(mode) &&
2874 !S_ISSOCK(mode)) {
2875 LIBELF_SET_ERROR(ARGUMENT, 0);
2876 return (NULL);
2880 * For ELF_C_WRITE mode, allocate and return a descriptor.
2882 if (c == ELF_C_WRITE) {
2883 if ((e = _libelf_allocate_elf()) != NULL) {
2884 _libelf_init_elf(e, ELF_K_ELF);
2885 e->e_byteorder = LIBELF_PRIVATE(byteorder);
2886 e->e_fd = fd;
2887 e->e_cmd = c;
2888 if (!S_ISREG(mode))
2889 e->e_flags |= LIBELF_F_SPECIAL_FILE;
2892 return (e);
2897 * ELF_C_READ and ELF_C_RDWR mode.
2899 m = NULL;
2900 flags = 0;
2901 if (S_ISREG(mode)) {
2904 * Reject zero length files.
2906 if (fsize == 0) {
2907 LIBELF_SET_ERROR(ARGUMENT, 0);
2908 return (NULL);
2911 #if ELFTC_HAVE_MMAP
2913 * Always map regular files in with 'PROT_READ'
2914 * permissions.
2916 * For objects opened in ELF_C_RDWR mode, when
2917 * elf_update(3) is called, we remove this mapping,
2918 * write file data out using write(2), and map the new
2919 * contents back.
2921 m = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, (off_t) 0);
2923 if (m == MAP_FAILED)
2924 m = NULL;
2925 else
2926 flags = LIBELF_F_RAWFILE_MMAP;
2927 #endif
2930 * Fallback to a read() if the call to mmap() failed,
2931 * or if mmap() is not available.
2933 if (m == NULL) {
2934 if ((m = malloc(fsize)) == NULL) {
2935 LIBELF_SET_ERROR(RESOURCE, 0);
2936 return (NULL);
2939 if (read(fd, m, fsize) != (ssize_t) fsize) {
2940 LIBELF_SET_ERROR(IO, errno);
2941 free(m);
2942 return (NULL);
2945 flags = LIBELF_F_RAWFILE_MALLOC;
2947 } else if ((m = _libelf_read_special_file(fd, &fsize)) != NULL)
2948 flags = LIBELF_F_RAWFILE_MALLOC | LIBELF_F_SPECIAL_FILE;
2949 else
2950 return (NULL);
2952 if ((e = _libelf_memory(m, fsize, reporterror)) == NULL) {
2953 assert((flags & LIBELF_F_RAWFILE_MALLOC) ||
2954 (flags & LIBELF_F_RAWFILE_MMAP));
2955 if (flags & LIBELF_F_RAWFILE_MALLOC)
2956 free(m);
2957 #if ELFTC_HAVE_MMAP
2958 else
2959 (void) munmap(m, fsize);
2960 #endif
2961 return (NULL);
2964 /* ar(1) archives aren't supported in RDWR mode. */
2965 #if 0
2966 if (c == ELF_C_RDWR && e->e_kind == ELF_K_AR) {
2967 (void) elf_end(e);
2968 LIBELF_SET_ERROR(ARGUMENT, 0);
2969 return (NULL);
2971 #endif
2973 e->e_flags |= flags;
2974 e->e_fd = fd;
2975 e->e_cmd = c;
2977 return (e);
2980 static const char *_libelf_errors[] = {
2981 #define DEFINE_ERROR(N,S) [ELF_E_##N] = S
2982 DEFINE_ERROR(NONE, "No Error"),
2983 DEFINE_ERROR(ARCHIVE, "Malformed ar(1) archive"),
2984 DEFINE_ERROR(ARGUMENT, "Invalid argument"),
2985 DEFINE_ERROR(CLASS, "ELF class mismatch"),
2986 DEFINE_ERROR(DATA, "Invalid data buffer descriptor"),
2987 DEFINE_ERROR(HEADER, "Missing or malformed ELF header"),
2988 DEFINE_ERROR(IO, "I/O error"),
2989 DEFINE_ERROR(LAYOUT, "Layout constraint violation"),
2990 DEFINE_ERROR(MODE, "Incorrect ELF descriptor mode"),
2991 DEFINE_ERROR(RANGE, "Value out of range of target"),
2992 DEFINE_ERROR(RESOURCE, "Resource exhaustion"),
2993 DEFINE_ERROR(SECTION, "Invalid section descriptor"),
2994 DEFINE_ERROR(SEQUENCE, "API calls out of sequence"),
2995 DEFINE_ERROR(UNIMPL, "Unimplemented feature"),
2996 DEFINE_ERROR(VERSION, "Unknown ELF API version"),
2997 DEFINE_ERROR(NUM, "Unknown error")
2998 #undef DEFINE_ERROR
3001 /* PUBLIC */
3003 /* elf_errmsg.c */
3004 static const char *
3005 elf_errmsg(int error)
3007 int oserr;
3009 if (error == ELF_E_NONE &&
3010 (error = LIBELF_PRIVATE(error)) == 0)
3011 return NULL;
3012 else if (error == -1)
3013 error = LIBELF_PRIVATE(error);
3015 oserr = error >> LIBELF_OS_ERROR_SHIFT;
3016 error &= LIBELF_ELF_ERROR_MASK;
3018 if (error < ELF_E_NONE || error >= ELF_E_NUM)
3019 return _libelf_errors[ELF_E_NUM];
3020 if (oserr) {
3021 (void) snprintf((char *) LIBELF_PRIVATE(msg),
3022 sizeof(LIBELF_PRIVATE(msg)), "%s: %s",
3023 _libelf_errors[error], strerror(oserr));
3024 return (const char *)&LIBELF_PRIVATE(msg);
3026 return _libelf_errors[error];
3029 /* elf_errno.c */
3030 static int
3031 elf_errno(void)
3033 int old;
3035 old = LIBELF_PRIVATE(error);
3036 LIBELF_PRIVATE(error) = 0;
3037 return (old & LIBELF_ELF_ERROR_MASK);
3040 /* elf_version.c */
3041 static unsigned int
3042 elf_version(unsigned int v)
3044 unsigned int old;
3046 if ((old = LIBELF_PRIVATE(version)) == EV_NONE)
3047 old = EV_CURRENT;
3049 if (v == EV_NONE)
3050 return old;
3051 if (v > EV_CURRENT) {
3052 LIBELF_SET_ERROR(VERSION, 0);
3053 return EV_NONE;
3056 LIBELF_PRIVATE(version) = v;
3057 return (old);
3060 /* elf_begin.c */
3061 static Elf *
3062 elf_begin(int fd, Elf_Cmd c, Elf *a)
3064 Elf *e;
3066 e = NULL;
3068 if (LIBELF_PRIVATE(version) == EV_NONE) {
3069 LIBELF_SET_ERROR(SEQUENCE, 0);
3070 return (NULL);
3073 switch (c) {
3074 case ELF_C_NULL:
3075 return (NULL);
3077 case ELF_C_WRITE:
3079 * The ELF_C_WRITE command is required to ignore the
3080 * descriptor passed in.
3082 a = NULL;
3083 break;
3085 case ELF_C_RDWR:
3086 if (a != NULL) { /* not allowed for ar(1) archives. */
3087 LIBELF_SET_ERROR(ARGUMENT, 0);
3088 return (NULL);
3090 /*FALLTHROUGH*/
3091 case ELF_C_READ:
3093 * Descriptor `a' could be for a regular ELF file, or
3094 * for an ar(1) archive. If descriptor `a' was opened
3095 * using a valid file descriptor, we need to check if
3096 * the passed in `fd' value matches the original one.
3098 if (a &&
3099 ((a->e_fd != -1 && a->e_fd != fd) || c != a->e_cmd)) {
3100 LIBELF_SET_ERROR(ARGUMENT, 0);
3101 return (NULL);
3103 break;
3105 default:
3106 LIBELF_SET_ERROR(ARGUMENT, 0);
3107 return (NULL);
3111 if (a == NULL)
3112 e = _libelf_open_object(fd, c, 1);
3113 #if 0
3114 else if (a->e_kind == ELF_K_AR)
3115 e = _libelf_ar_open_member(a->e_fd, c, a);
3116 #endif
3117 else
3118 (e = a)->e_activations++;
3120 return (e);
3123 /* elf_end.c */
3124 static int
3125 elf_end(Elf *e)
3127 Elf *sv;
3128 Elf_Scn *scn, *tscn;
3130 if (e == NULL || e->e_activations == 0)
3131 return (0);
3133 if (--e->e_activations > 0)
3134 return (e->e_activations);
3136 assert(e->e_activations == 0);
3138 while (e && e->e_activations == 0) {
3139 switch (e->e_kind) {
3140 case ELF_K_AR:
3142 * If we still have open child descriptors, we
3143 * need to defer reclaiming resources till all
3144 * the child descriptors for the archive are
3145 * closed.
3147 if (e->e_u.e_ar.e_nchildren > 0)
3148 return (0);
3149 break;
3150 case ELF_K_ELF:
3152 * Reclaim all section descriptors.
3154 STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next,
3155 tscn)
3156 scn = _libelf_release_scn(scn);
3157 break;
3158 case ELF_K_NUM:
3159 assert(0);
3160 default:
3161 break;
3164 if (e->e_rawfile) {
3165 if (e->e_flags & LIBELF_F_RAWFILE_MALLOC)
3166 free(e->e_rawfile);
3167 #if ELFTC_HAVE_MMAP
3168 else if (e->e_flags & LIBELF_F_RAWFILE_MMAP)
3169 (void) munmap(e->e_rawfile, e->e_rawsize);
3170 #endif
3173 sv = e;
3174 if ((e = e->e_parent) != NULL)
3175 e->e_u.e_ar.e_nchildren--;
3176 sv = _libelf_release_elf(sv);
3179 return (0);
3182 /* gelf_shdr.c */
3183 static GElf_Shdr *
3184 gelf_getshdr(Elf_Scn *s, GElf_Shdr *d)
3186 int ec;
3187 void *sh;
3188 #if 0
3189 Elf32_Shdr *sh32;
3190 #endif
3191 Elf64_Shdr *sh64;
3193 if (d == NULL) {
3194 LIBELF_SET_ERROR(ARGUMENT, 0);
3195 return (NULL);
3198 if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL)
3199 return (NULL);
3201 ec = s->s_elf->e_class;
3202 assert(/* ec == ELFCLASS32 || */ ec == ELFCLASS64);
3204 #if 0
3205 if (ec == ELFCLASS32) {
3206 sh32 = (Elf32_Shdr *) sh;
3208 d->sh_name = sh32->sh_name;
3209 d->sh_type = sh32->sh_type;
3210 d->sh_flags = (Elf64_Xword) sh32->sh_flags;
3211 d->sh_addr = (Elf64_Addr) sh32->sh_addr;
3212 d->sh_offset = (Elf64_Off) sh32->sh_offset;
3213 d->sh_size = (Elf64_Xword) sh32->sh_size;
3214 d->sh_link = sh32->sh_link;
3215 d->sh_info = sh32->sh_info;
3216 d->sh_addralign = (Elf64_Xword) sh32->sh_addralign;
3217 d->sh_entsize = (Elf64_Xword) sh32->sh_entsize;
3218 } else
3219 #endif
3221 sh64 = (Elf64_Shdr *) sh;
3222 *d = *sh64;
3225 return (d);
3228 /* gelf_sym.c */
3229 static GElf_Sym *
3230 gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst)
3232 int ec;
3233 Elf *e;
3234 size_t msz;
3235 Elf_Scn *scn;
3236 uint32_t sh_type;
3237 #if 0
3238 Elf32_Sym *sym32;
3239 #endif
3240 Elf64_Sym *sym64;
3241 struct _Libelf_Data *d;
3243 d = (struct _Libelf_Data *) ed;
3245 if (d == NULL || ndx < 0 || dst == NULL ||
3246 (scn = d->d_scn) == NULL ||
3247 (e = scn->s_elf) == NULL) {
3248 LIBELF_SET_ERROR(ARGUMENT, 0);
3249 return (NULL);
3252 ec = e->e_class;
3253 assert(/* ec == ELFCLASS32 || */ ec == ELFCLASS64);
3255 #if 0
3256 if (ec == ELFCLASS32)
3257 sh_type = scn->s_shdr.s_shdr32.sh_type;
3258 else
3259 #endif
3260 sh_type = scn->s_shdr.s_shdr64.sh_type;
3262 if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
3263 LIBELF_SET_ERROR(ARGUMENT, 0);
3264 return (NULL);
3267 msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);
3269 assert(msz > 0);
3270 assert(ndx >= 0);
3272 if (msz * (size_t) ndx >= d->d_data.d_size) {
3273 LIBELF_SET_ERROR(ARGUMENT, 0);
3274 return (NULL);
3277 #if 0
3278 if (ec == ELFCLASS32) {
3279 sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx;
3281 dst->st_name = sym32->st_name;
3282 dst->st_value = (Elf64_Addr) sym32->st_value;
3283 dst->st_size = (Elf64_Xword) sym32->st_size;
3284 dst->st_info = sym32->st_info;
3285 dst->st_other = sym32->st_other;
3286 dst->st_shndx = sym32->st_shndx;
3287 } else
3288 #endif
3290 sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx;
3292 *dst = *sym64;
3295 return (dst);
3298 /* elf_scn.c */
3299 static Elf_Scn *
3300 elf_nextscn(Elf *e, Elf_Scn *s)
3302 if (e == NULL || (e->e_kind != ELF_K_ELF) ||
3303 (s && s->s_elf != e)) {
3304 LIBELF_SET_ERROR(ARGUMENT, 0);
3305 return (NULL);
3308 return (s == NULL ? elf_getscn(e, (size_t) 1) :
3309 STAILQ_NEXT(s, s_next));
3312 /* elf_strptr.c */
3313 static char *
3314 elf_strptr(Elf *e, size_t scndx, size_t offset)
3316 Elf_Scn *s;
3317 Elf_Data *d;
3318 GElf_Shdr shdr;
3319 uint64_t alignment, count;
3321 if (e == NULL || e->e_kind != ELF_K_ELF) {
3322 LIBELF_SET_ERROR(ARGUMENT, 0);
3323 return (NULL);
3326 if ((s = elf_getscn(e, scndx)) == NULL ||
3327 gelf_getshdr(s, &shdr) == NULL)
3328 return (NULL);
3330 if (shdr.sh_type != SHT_STRTAB ||
3331 offset >= shdr.sh_size) {
3332 LIBELF_SET_ERROR(ARGUMENT, 0);
3333 return (NULL);
3336 d = NULL;
3337 if (e->e_flags & ELF_F_LAYOUT) {
3340 * The application is taking responsibility for the
3341 * ELF object's layout, so we can directly translate
3342 * an offset to a `char *' address using the `d_off'
3343 * members of Elf_Data descriptors.
3345 while ((d = elf_getdata(s, d)) != NULL) {
3347 if (d->d_buf == 0 || d->d_size == 0)
3348 continue;
3350 if (d->d_type != ELF_T_BYTE) {
3351 LIBELF_SET_ERROR(DATA, 0);
3352 return (NULL);
3355 if (offset >= d->d_off &&
3356 offset < d->d_off + d->d_size)
3357 return ((char *) d->d_buf + offset - d->d_off);
3359 } else {
3361 * Otherwise, the `d_off' members are not useable and
3362 * we need to compute offsets ourselves, taking into
3363 * account 'holes' in coverage of the section introduced
3364 * by alignment requirements.
3366 count = (uint64_t) 0; /* cumulative count of bytes seen */
3367 while ((d = elf_getdata(s, d)) != NULL && count <= offset) {
3369 if (d->d_buf == NULL || d->d_size == 0)
3370 continue;
3372 if (d->d_type != ELF_T_BYTE) {
3373 LIBELF_SET_ERROR(DATA, 0);
3374 return (NULL);
3377 if ((alignment = d->d_align) > 1) {
3378 if ((alignment & (alignment - 1)) != 0) {
3379 LIBELF_SET_ERROR(DATA, 0);
3380 return (NULL);
3382 count = roundup2(count, alignment);
3385 if (offset < count) {
3386 /* offset starts in the 'hole' */
3387 LIBELF_SET_ERROR(ARGUMENT, 0);
3388 return (NULL);
3391 if (offset < count + d->d_size) {
3392 if (d->d_buf != NULL)
3393 return ((char *) d->d_buf +
3394 offset - count);
3395 LIBELF_SET_ERROR(DATA, 0);
3396 return (NULL);
3399 count += d->d_size;
3403 LIBELF_SET_ERROR(ARGUMENT, 0);
3404 return (NULL);
3407 /* elf_data.c */
3408 static Elf_Data *
3409 elf_getdata(Elf_Scn *s, Elf_Data *ed)
3411 Elf *e;
3412 unsigned int sh_type;
3413 int elfclass, elftype;
3414 size_t count, fsz, msz;
3415 struct _Libelf_Data *d;
3416 uint64_t sh_align, sh_offset, sh_size;
3417 int (*xlate)(unsigned char *_d, size_t _dsz, unsigned char *_s,
3418 size_t _c, int _swap);
3420 d = (struct _Libelf_Data *) ed;
3422 if (s == NULL || (e = s->s_elf) == NULL ||
3423 (d != NULL && s != d->d_scn)) {
3424 LIBELF_SET_ERROR(ARGUMENT, 0);
3425 return (NULL);
3428 assert(e->e_kind == ELF_K_ELF);
3430 if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)
3431 return (&d->d_data);
3433 if (d != NULL)
3434 return (&STAILQ_NEXT(d, d_next)->d_data);
3436 if (e->e_rawfile == NULL) {
3438 * In the ELF_C_WRITE case, there is no source that
3439 * can provide data for the section.
3441 LIBELF_SET_ERROR(ARGUMENT, 0);
3442 return (NULL);
3445 elfclass = e->e_class;
3447 assert(/* elfclass == ELFCLASS32 || */ elfclass == ELFCLASS64);
3449 #if 0
3450 if (elfclass == ELFCLASS32) {
3451 sh_type = s->s_shdr.s_shdr32.sh_type;
3452 sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
3453 sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
3454 sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
3455 } else
3456 #endif
3458 sh_type = s->s_shdr.s_shdr64.sh_type;
3459 sh_offset = s->s_shdr.s_shdr64.sh_offset;
3460 sh_size = s->s_shdr.s_shdr64.sh_size;
3461 sh_align = s->s_shdr.s_shdr64.sh_addralign;
3464 if (sh_type == SHT_NULL) {
3465 LIBELF_SET_ERROR(SECTION, 0);
3466 return (NULL);
3469 if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
3470 elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
3471 sh_offset + sh_size > (uint64_t) e->e_rawsize)) {
3472 LIBELF_SET_ERROR(SECTION, 0);
3473 return (NULL);
3476 if ((fsz = (/* elfclass == ELFCLASS32 ? elf32_fsize :*/ elf64_fsize)
3477 (elftype, (size_t) 1, e->e_version)) == 0) {
3478 LIBELF_SET_ERROR(UNIMPL, 0);
3479 return (NULL);
3482 if (sh_size % fsz) {
3483 LIBELF_SET_ERROR(SECTION, 0);
3484 return (NULL);
3487 if (sh_size / fsz > SIZE_MAX) {
3488 LIBELF_SET_ERROR(RANGE, 0);
3489 return (NULL);
3492 count = (size_t) (sh_size / fsz);
3494 msz = _libelf_msize(elftype, elfclass, e->e_version);
3496 if (count > 0 && msz > SIZE_MAX / count) {
3497 LIBELF_SET_ERROR(RANGE, 0);
3498 return (NULL);
3501 assert(msz > 0);
3502 assert(count <= SIZE_MAX);
3503 assert(msz * count <= SIZE_MAX);
3505 if ((d = _libelf_allocate_data(s)) == NULL)
3506 return (NULL);
3508 d->d_data.d_buf = NULL;
3509 d->d_data.d_off = 0;
3510 d->d_data.d_align = sh_align;
3511 d->d_data.d_size = msz * count;
3512 d->d_data.d_type = elftype;
3513 d->d_data.d_version = e->e_version;
3515 if (sh_type == SHT_NOBITS || sh_size == 0) {
3516 STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
3517 return (&d->d_data);
3520 if ((d->d_data.d_buf = malloc(msz * count)) == NULL) {
3521 (void) _libelf_release_data(d);
3522 LIBELF_SET_ERROR(RESOURCE, 0);
3523 return (NULL);
3526 d->d_flags |= LIBELF_F_DATA_MALLOCED;
3528 xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass);
3529 if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size,
3530 e->e_rawfile + sh_offset, count,
3531 e->e_byteorder != LIBELF_PRIVATE(byteorder))) {
3532 _libelf_release_data(d);
3533 LIBELF_SET_ERROR(DATA, 0);
3534 return (NULL);
3537 STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
3539 return (&d->d_data);
3542 #endif /* !_PRIVATE_LIBELF_H_ */