2 * Copyright (c) 2006,2008-2010 Joseph Koshy
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
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>
35 #include <sys/types.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__ */
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
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
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 ,
138 _ELF_DEFINE_EI_OFFSETS()
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 ,
153 _ELF_DEFINE_ELFCLASS()
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 ,
169 _ELF_DEFINE_ELF_DATA_ENDIANNESS()
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 ,
185 _ELF_DEFINE_ELF_MAGIC()
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 ,
200 _ELF_DEFINE_ELF_MACHINES()
204 /* ELF file format version numbers. */
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 ,
245 _ELF_DEFINE_SECTION_INDICES()
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, \
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, \
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, \
342 _ELF_DEFINE_SHT(SHT_MIPS_PACKSYM, 0x70000008UL, \
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, \
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, \
366 _ELF_DEFINE_SHT(SHT_MIPS_TRANSLATE, 0x70000022UL, \
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, \
380 _ELF_DEFINE_SHT(SHT_MIPS_PDR_EXCEPTION, 0x70000029UL, \
381 "runtime procedure descriptor table exception information") \
382 _ELF_DEFINE_SHT(SHT_MIPS_ABIFLAGS, 0x7000002AUL, \
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 ,
400 _ELF_DEFINE_SECTION_TYPES()
401 SHT__LAST__
= SHT_HIUSER
404 #define PN_XNUM 0xFFFFU /* Use extended section numbering. */
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.
423 Elf64_Xword c_tag
; /* Type of entry. */
425 Elf64_Xword c_val
; /* Integer value. */
426 Elf64_Addr c_ptr
; /* Pointer value. */
431 * Dynamic section entries.
434 Elf64_Sxword d_tag
; /* Type of entry. */
436 Elf64_Xword d_val
; /* Integer value. */
437 Elf64_Addr d_ptr
; /* Pointer value; */
442 * The executable header (EHDR).
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. */
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. */
472 * Program Header Table (PHDR) entries.
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. */
486 * Move entries, for describing data in COMMON blocks in a compact
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. */
498 * Section Header Table (SHDR) entries.
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 */
514 * Symbol table entries.
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 */
526 * Syminfo descriptors, containing additional symbol information.
529 Elf64_Half si_boundto
; /* Entry index with additional flags. */
530 Elf64_Half si_flags
; /* Flags. */
534 * Relocation descriptors.
537 Elf64_Addr r_offset
; /* location to apply relocation to */
538 Elf64_Xword r_info
; /* type+section for relocation */
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 */
548 * Symbol versioning structures.
551 Elf64_Word vda_name
; /* Index to name. */
552 Elf64_Word vda_next
; /* Offset to next entry. */
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. */
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. */
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. */
582 * The header for GNU-style hash sections.
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
;
593 /* Library private data structures */
594 typedef struct _Elf Elf
;
595 typedef struct _Elf_Scn Elf_Scn
;
600 ELF_K_AR
, /* `ar' archives */
601 ELF_K_COFF
, /* COFF files (unsupported) */
602 ELF_K_ELF
, /* ELF files */
631 ELF_T_GNUHASH
, /* GNU style hash tables. */
635 #define ELF_T_FIRST ELF_T_ADDR
636 #define ELF_T_LAST ELF_T_GNUHASH
652 * An `Elf_Data' structure describes data in an
655 typedef struct _Elf_Data
{
657 * `Public' members that are part of the ELF(3) API.
664 unsigned int d_version
;
668 * An `Elf_Arhdr' structure describes an archive
673 char *ar_name
; /* archive member name */
676 char *ar_rawname
; /* 'raw' member name */
681 * Members that are not part of the public API.
683 unsigned int ar_flags
;
687 * An `Elf_Arsym' describes an entry in the archive
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 */
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 */
730 Elf
*elf_begin(int _fd
, Elf_Cmd _cmd
, Elf
*_elf
);
732 int elf_end(Elf
*_elf
);
734 const char *elf_errmsg(int _error
);
738 Elf_Data
*elf_getdata(Elf_Scn
*, Elf_Data
*);
740 char *elf_strptr(Elf
*_elf
, size_t _section
, size_t _offset
);
742 unsigned int elf_version(unsigned int _version
);
744 Elf_Scn
*elf_nextscn(Elf
*_elf
, Elf_Scn
*_scn
);
750 typedef Elf64_Shdr GElf_Shdr
; /* Section header */
751 typedef Elf64_Sym GElf_Sym
; /* Symbol table entries */
757 GElf_Shdr
*gelf_getshdr(Elf_Scn
*_scn
, GElf_Shdr
*_dst
);
759 GElf_Sym
*gelf_getsym(Elf_Data
*_src
, int _index
, GElf_Sym
*_dst
);
766 * Library-private data structures.
769 #define LIBELF_MSG_SIZE 256
771 struct _libelf_globals
{
773 unsigned int libelf_byteorder
;
777 unsigned int libelf_version
;
778 unsigned char libelf_msg
[LIBELF_MSG_SIZE
];
782 extern struct _libelf_globals _libelf
;
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)); \
798 * Flags for library internal use. These use the upper 16 bits of the
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 */
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.
826 Elf_Arhdr
*e_arhdr
; /* translated header */
827 unsigned char *e_rawhdr
; /* untranslated header */
831 struct { /* ar(1) archives */
832 off_t e_next
; /* set by elf_rand()/elf_next() */
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
;
841 struct { /* regular ELF files */
844 Elf32_Ehdr
*e_ehdr32
;
846 Elf64_Ehdr
*e_ehdr64
;
850 Elf32_Phdr
*e_phdr32
;
852 Elf64_Phdr
*e_phdr64
;
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 */
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
;
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() */
898 static struct _libelf_globals _libelf
= {
899 .libelf_arch
= LIBELF_ARCH
,
900 .libelf_byteorder
= LIBELF_BYTEORDER
,
901 .libelf_class
= LIBELF_CLASS
,
903 .libelf_fillchar
= 0,
904 .libelf_version
= EV_NONE
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
) },
940 _libelf_msize(Elf_Type t
, int elfclass
, unsigned int version
)
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);
952 sz
= /* (elfclass == ELFCLASS32) ? msize[t].msz32 : */ msize
[t
].msz64
;
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
) },
1008 _libelf_fsize(Elf_Type t
, int ec
, unsigned int v
, size_t c
)
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);
1018 sz
= ec
== ELFCLASS64
? tfsize
[t
].fsz64
: /* tfsize[t].fsz32 */ 0;
1020 LIBELF_SET_ERROR(UNIMPL
, 0);
1028 elf64_fsize(Elf_Type t
, size_t c
, unsigned int v
)
1030 return (_libelf_fsize(t
, ELFCLASS64
, v
, c
));
1033 /* libelf_allocate.h */
1035 _libelf_allocate_elf(void)
1039 if ((e
= malloc(sizeof(*e
))) == NULL
) {
1040 LIBELF_SET_ERROR(RESOURCE
, errno
);
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
;
1051 e
->e_kind
= ELF_K_NONE
;
1053 e
->e_rawfile
= NULL
;
1055 e
->e_version
= LIBELF_PRIVATE(version
);
1057 (void) memset(&e
->e_u
, 0, sizeof(e
->e_u
));
1063 _libelf_init_elf(Elf
*e
, Elf_Kind kind
)
1066 assert(e
->e_kind
== ELF_K_NONE
);
1072 STAILQ_INIT(&e
->e_u
.e_elf
.e_scn
);
1079 #define FREE(P) do { \
1085 _libelf_release_elf(Elf
*e
)
1091 switch (e
->e_kind
) {
1094 FREE(e
->e_u
.e_ar
.e_symtab
);
1099 switch (e
->e_class
) {
1102 FREE(e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
);
1103 FREE(e
->e_u
.e_elf
.e_phdr
.e_phdr32
);
1107 FREE(e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
);
1108 FREE(e
->e_u
.e_elf
.e_phdr
.e_phdr64
);
1112 assert(STAILQ_EMPTY(&e
->e_u
.e_elf
.e_scn
));
1115 if (e
->e_flags
& LIBELF_F_AR_HEADER
) {
1116 arh
= e
->e_hdr
.e_arhdr
;
1118 FREE(arh
->ar_rawname
);
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);
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
);
1164 _libelf_allocate_scn(Elf
*e
, size_t ndx
)
1168 if ((s
= calloc((size_t) 1, sizeof(Elf_Scn
))) == NULL
) {
1169 LIBELF_SET_ERROR(RESOURCE
, errno
);
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
);
1185 _libelf_release_scn(Elf_Scn
*s
)
1188 struct _Libelf_Data
*d
, *td
;
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
);
1207 STAILQ_REMOVE(&e
->e_u
.e_elf
.e_scn
, s
, _Elf_Scn
, s_next
);
1216 _libelf_xlate_shtype(uint32_t sht
)
1219 * Look for known section types.
1226 case SHT_FINI_ARRAY
:
1227 return (ELF_T_ADDR
);
1229 return (ELF_T_GNUHASH
);
1230 case SHT_GNU_LIBLIST
:
1231 return (ELF_T_WORD
);
1233 return (ELF_T_WORD
);
1235 return (ELF_T_WORD
);
1236 case SHT_INIT_ARRAY
:
1237 return (ELF_T_ADDR
);
1239 return (ELF_T_BYTE
);
1241 return (ELF_T_NOTE
);
1242 case SHT_PREINIT_ARRAY
:
1243 return (ELF_T_ADDR
);
1245 return (ELF_T_BYTE
);
1249 return (ELF_T_RELA
);
1251 return (ELF_T_BYTE
);
1254 case SHT_SYMTAB_SHNDX
:
1255 return (ELF_T_WORD
);
1257 return (ELF_T_BYTE
);
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
);
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.
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; \
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; \
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; \
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); \
1328 #define READ_HALF(P,X) do { \
1330 unsigned char *const _q = (unsigned char *) &_t; \
1331 const unsigned char *const _p = \
1332 (const unsigned char *) (P); \
1338 #define _READ_WORD(P,X,T) do { \
1340 unsigned char *const _q = (unsigned char *) &_t; \
1341 const unsigned char *const _p = \
1342 (const unsigned char *) (P); \
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 { \
1354 unsigned char *const _q = (unsigned char *) &_t; \
1355 const unsigned char *const _p = \
1356 (const unsigned char *) (P); \
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; \
1378 #define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1))
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
;
1387 if (dsz
< count
* sizeof(Elf64_Addr
))
1391 (void) memcpy(dst
, src
, count
* sizeof(*d
));
1395 for (c
= 0; c
< count
; c
++) {
1405 _libelf_cvt_CAP64_tom(unsigned char *dst
, size_t dsz
, unsigned char *src
,
1406 size_t count
, int byteswap
)
1409 unsigned char *s
,*s0
;
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
))
1421 /* Read an Elf64_Cap */
1422 READ_XWORD(s
,t
.c_tag
);
1423 READ_XWORD(s
,t
.c_un
.c_val
);
1426 /* Swap an Elf64_Cap */
1427 SWAP_XWORD(t
.c_tag
);
1428 SWAP_XWORD(t
.c_un
.c_val
);
1431 *d
-- = t
; s0
-= fsz
;
1438 _libelf_cvt_DYN64_tom(unsigned char *dst
, size_t dsz
, unsigned char *src
,
1439 size_t count
, int byteswap
)
1442 unsigned char *s
,*s0
;
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
))
1454 /* Read an Elf64_Dyn */
1455 READ_SXWORD(s
,t
.d_tag
);
1456 READ_XWORD(s
,t
.d_un
.d_ptr
);
1459 /* Swap an Elf64_Dyn */
1460 SWAP_SXWORD(t
.d_tag
);
1461 SWAP_XWORD(t
.d_un
.d_ptr
);
1464 *d
-- = t
; s0
-= fsz
;
1471 _libelf_cvt_EHDR64_tom(unsigned char *dst
, size_t dsz
, unsigned char *src
,
1472 size_t count
, int byteswap
)
1475 unsigned char *s
,*s0
;
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
))
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
);
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
);
1521 *d
-- = t
; s0
-= fsz
;
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
;
1534 if (dsz
< count
* sizeof(Elf64_Half
))
1538 (void) memcpy(dst
, src
, count
* sizeof(*d
));
1542 for (c
= 0; c
< count
; c
++) {
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
;
1558 if (dsz
< count
* sizeof(Elf64_Lword
))
1562 (void) memcpy(dst
, src
, count
* sizeof(*d
));
1566 for (c
= 0; c
< count
; c
++) {
1576 _libelf_cvt_MOVE64_tom(unsigned char *dst
, size_t dsz
, unsigned char *src
,
1577 size_t count
, int byteswap
)
1580 unsigned char *s
,*s0
;
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
))
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
);
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
);
1608 *d
-- = t
; s0
-= fsz
;
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
;
1621 if (dsz
< count
* sizeof(Elf64_Off
))
1625 (void) memcpy(dst
, src
, count
* sizeof(*d
));
1629 for (c
= 0; c
< count
; c
++) {
1639 _libelf_cvt_PHDR64_tom(unsigned char *dst
, size_t dsz
, unsigned char *src
,
1640 size_t count
, int byteswap
)
1643 unsigned char *s
,*s0
;
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
))
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
);
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
);
1677 *d
-- = t
; s0
-= fsz
;
1684 _libelf_cvt_REL64_tom(unsigned char *dst
, size_t dsz
, unsigned char *src
,
1685 size_t count
, int byteswap
)
1688 unsigned char *s
,*s0
;
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
))
1700 /* Read an Elf64_Rel */
1701 READ_ADDR64(s
,t
.r_offset
);
1702 READ_XWORD(s
,t
.r_info
);
1705 /* Swap an Elf64_Rel */
1706 SWAP_ADDR64(t
.r_offset
);
1707 SWAP_XWORD(t
.r_info
);
1710 *d
-- = t
; s0
-= fsz
;
1717 _libelf_cvt_RELA64_tom(unsigned char *dst
, size_t dsz
, unsigned char *src
,
1718 size_t count
, int byteswap
)
1721 unsigned char *s
,*s0
;
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
))
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
);
1739 /* Swap an Elf64_Rela */
1740 SWAP_ADDR64(t
.r_offset
);
1741 SWAP_XWORD(t
.r_info
);
1742 SWAP_SXWORD(t
.r_addend
);
1745 *d
-- = t
; s0
-= fsz
;
1752 _libelf_cvt_SHDR64_tom(unsigned char *dst
, size_t dsz
, unsigned char *src
,
1753 size_t count
, int byteswap
)
1756 unsigned char *s
,*s0
;
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
))
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
);
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
);
1794 *d
-- = t
; s0
-= fsz
;
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
;
1807 if (dsz
< count
* sizeof(Elf64_Sword
))
1811 (void) memcpy(dst
, src
, count
* sizeof(*d
));
1815 for (c
= 0; c
< count
; c
++) {
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
;
1831 if (dsz
< count
* sizeof(Elf64_Sxword
))
1835 (void) memcpy(dst
, src
, count
* sizeof(*d
));
1839 for (c
= 0; c
< count
; c
++) {
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
;
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
))
1865 /* Read an Elf64_Syminfo */
1866 READ_HALF(s
,t
.si_boundto
);
1867 READ_HALF(s
,t
.si_flags
);
1870 /* Swap an Elf64_Syminfo */
1871 SWAP_HALF(t
.si_boundto
);
1872 SWAP_HALF(t
.si_flags
);
1875 *d
-- = t
; s0
-= fsz
;
1882 _libelf_cvt_SYM64_tom(unsigned char *dst
, size_t dsz
, unsigned char *src
,
1883 size_t count
, int byteswap
)
1886 unsigned char *s
,*s0
;
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
))
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
);
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
);
1916 *d
-- = t
; s0
-= fsz
;
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
;
1929 if (dsz
< count
* sizeof(Elf64_Word
))
1933 (void) memcpy(dst
, src
, count
* sizeof(*d
));
1937 for (c
= 0; c
< count
; c
++) {
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
;
1953 if (dsz
< count
* sizeof(Elf64_Xword
))
1957 (void) memcpy(dst
, src
, count
* sizeof(*d
));
1961 for (c
= 0; c
< count
; c
++) {
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. */
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
);
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
);
2012 dp
= (Elf64_Verdef
*) (uintptr_t) dst
;
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
--) {
2029 /* Read an Elf64_Verdaux */
2030 READ_WORD(s
,a
.vda_name
);
2031 READ_WORD(s
,a
.vda_next
);
2035 /* Swap an Elf64_Verdaux */
2036 SWAP_WORD(a
.vda_name
);
2037 SWAP_WORD(a
.vda_next
);
2043 ap
= ((Elf64_Verdaux
*) (uintptr_t) dstaux
);
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. */
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
);
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
);
2095 dp
= (Elf64_Verneed
*) (uintptr_t) dst
;
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
--) {
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
);
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
);
2132 ap
= ((Elf64_Vernaux
*) (uintptr_t) dstaux
);
2147 _libelf_cvt_BYTE_tox(unsigned char *dst
, size_t dsz
, unsigned char *src
,
2148 size_t count
, int byteswap
)
2154 (void) memcpy(dst
, src
, count
);
2159 _libelf_cvt_GNUHASH64_tom(unsigned char *dst
, size_t dsz
, unsigned char *src
,
2160 size_t srcsz
, int byteswap
)
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
)
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
);
2181 SWAP_WORD(nbuckets
);
2183 SWAP_WORD(maskwords
);
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
))
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
);
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
);
2222 dst
+= nbuckets
* sizeof(uint32_t);
2224 /* The hash chain follows the hash buckets. */
2228 if (dsz
< srcsz
) /* Destination lacks space. */
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
);
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
;
2252 if (dsz
< count
) /* Destination buffer is too small. */
2255 hdrsz
= 3 * sizeof(uint32_t);
2256 if (count
< hdrsz
) /* Source too small. */
2260 (void) memcpy(dst
, src
, count
);
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
);
2276 /* Copy out the translated note header. */
2277 en
= (Elf_Note
*) (uintptr_t) dst
;
2278 en
->n_namesz
= namesz
;
2279 en
->n_descsz
= descsz
;
2282 dsz
-= sizeof(Elf_Note
);
2283 dst
+= sizeof(Elf_Note
);
2286 ROUNDUP2(namesz
, 4U);
2287 ROUNDUP2(descsz
, 4U);
2289 sz
= namesz
+ descsz
;
2291 if (count
< sz
|| dsz
< sz
) /* Buffers are too small. */
2294 (void) memcpy(dst
, src
, sz
);
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
] = {
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
},
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
,
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
))
2384 return cvt
[t
].tom64
;
2386 return ((elfclass
== ELFCLASS32
) ?
2387 (direction
== ELF_TOFILE
? cvt
[t
].tof32
: cvt
[t
].tom32
) :
2388 (direction
== ELF_TOFILE
? cvt
[t
].tof64
: cvt
[t
].tom64
));
2394 * Retrieve counts for sections, phdrs and the section string table index
2395 * from section header #0 of the ELF object.
2398 _libelf_load_extended(Elf
*e
, int ec
, uint64_t shoff
, uint16_t phnum
,
2403 int (*xlator
)(unsigned char *_d
, size_t _dsz
, unsigned char *_s
,
2404 size_t _c
, int _swap
);
2407 assert(STAILQ_EMPTY(&e
->e_u
.e_elf
.e_scn
));
2409 fsz
= _libelf_fsize(ELF_T_SHDR
, ec
, e
->e_version
, 1);
2412 if (e
->e_rawsize
< shoff
+ fsz
) { /* raw file too small */
2413 LIBELF_SET_ERROR(HEADER
, 0);
2417 if ((scn
= _libelf_allocate_scn(e
, (size_t) 0)) == NULL
)
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);
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
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); \
2458 _libelf_ehdr(Elf
*e
, int ec
, int allocate
)
2462 uint16_t phnum
, shnum
, strndx
;
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);
2474 if (e
->e_class
!= ELFCLASSNONE
&& e
->e_class
!= ec
) {
2475 LIBELF_SET_ERROR(CLASS
, 0);
2479 if (e
->e_version
!= EV_CURRENT
) {
2480 LIBELF_SET_ERROR(VERSION
, 0);
2484 if (e
->e_class
== ELFCLASSNONE
)
2488 if (ec
== ELFCLASS32
)
2489 ehdr
= (void *) e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
;
2492 ehdr
= (void *) e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
;
2494 if (ehdr
!= NULL
) /* already have a translated ehdr */
2497 fsz
= _libelf_fsize(ELF_T_EHDR
, ec
, e
->e_version
, (size_t) 1);
2500 if (e
->e_cmd
!= ELF_C_WRITE
&& e
->e_rawsize
< fsz
) {
2501 LIBELF_SET_ERROR(HEADER
, 0);
2505 msz
= _libelf_msize(ELF_T_EHDR
, ec
, EV_CURRENT
);
2509 if ((ehdr
= calloc((size_t) 1, msz
)) == NULL
) {
2510 LIBELF_SET_ERROR(RESOURCE
, 0);
2515 if (ec
== ELFCLASS32
) {
2516 e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
= ehdr
;
2521 e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
= ehdr
;
2526 e
->e_flags
|= ELF_F_DIRTY
;
2528 if (e
->e_cmd
== ELF_C_WRITE
)
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.
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
;
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);
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)
2573 _libelf_getshdr(Elf_Scn
*s
, int ec
)
2577 if (s
== NULL
|| (e
= s
->s_elf
) == NULL
||
2578 e
->e_kind
!= ELF_K_ELF
) {
2579 LIBELF_SET_ERROR(ARGUMENT
, 0);
2583 if (ec
== ELFCLASSNONE
)
2586 if (ec
!= e
->e_class
) {
2587 LIBELF_SET_ERROR(CLASS
, 0);
2591 return ((void *) &s
->s_shdr
);
2596 _libelf_load_section_headers(Elf
*e
, void *ehdr
)
2606 size_t fsz
, i
, shnum
;
2607 int (*xlator
)(unsigned char *_d
, size_t _dsz
, unsigned char *_s
,
2608 size_t _c
, int _swap
);
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); \
2625 fsz
= _libelf_fsize(ELF_T_SHDR
, ec
, e
->e_version
, (size_t) 1);
2628 shnum
= e
->e_u
.e_elf
.e_nscn
;
2631 if (ec
== ELFCLASS32
) {
2632 eh32
= (Elf32_Ehdr
*) ehdr
;
2633 shoff
= (uint64_t) eh32
->e_shoff
;
2634 CHECK_EHDR(e
, eh32
);
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.
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
));
2662 for (; i
< shnum
; i
++, src
+= fsz
) {
2663 if ((scn
= _libelf_allocate_scn(e
, i
)) == NULL
)
2666 (*xlator
)((unsigned char *) &scn
->s_shdr
, sizeof(scn
->s_shdr
),
2667 src
, (size_t) 1, swapbytes
);
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
;
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
;
2689 elf_getscn(Elf
*e
, size_t index
)
2695 if (e
== NULL
|| e
->e_kind
!= ELF_K_ELF
||
2696 ((ec
= e
->e_class
) != ELFCLASS32
&& ec
!= ELFCLASS64
)) {
2697 LIBELF_SET_ERROR(ARGUMENT
, 0);
2701 if ((ehdr
= _libelf_ehdr(e
, ec
, 0)) == 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)
2709 STAILQ_FOREACH(s
, &e
->e_u
.e_elf
.e_scn
, s_next
)
2710 if (s
->s_ndx
== index
)
2713 LIBELF_SET_ERROR(ARGUMENT
, 0);
2717 /* libelf_memory.c */
2719 _libelf_memory(unsigned char *image
, size_t sz
, int reporterror
)
2723 enum Elf_Error error
;
2724 unsigned int e_byteorder
, e_version
;
2726 assert(image
!= NULL
);
2729 if ((e
= _libelf_allocate_elf()) == NULL
)
2732 e
->e_cmd
= ELF_C_READ
;
2733 e
->e_rawfile
= image
;
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
];
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
!=
2753 error
= ELF_E_HEADER
;
2755 if (error
!= ELF_E_NONE
) {
2757 LIBELF_PRIVATE(error
) = LIBELF_ERROR(error
, 0);
2758 (void) _libelf_release_elf(e
);
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
;
2770 else if (sz
>= SARMAG
&&
2771 strncmp((const char *) image
, ARMAG
, (size_t) SARMAG
) == 0)
2772 return (_libelf_ar_open(e
, reporterror
));
2779 #define _LIBELF_INITSIZE (64*1024)
2782 _libelf_read_special_file(int fd
, size_t *fsz
)
2785 size_t bufsz
, datasz
;
2786 unsigned char *buf
, *t
;
2790 bufsz
= _LIBELF_INITSIZE
;
2791 if ((buf
= malloc(bufsz
)) == NULL
)
2795 * Read data from the file descriptor till we reach EOF, or
2796 * till an error is encountered.
2799 /* Check if we need to expand the data buffer. */
2800 if (datasz
== bufsz
) {
2802 if ((t
= realloc(buf
, bufsz
)) == NULL
)
2808 assert(bufsz
- datasz
> 0);
2810 if ((readsz
= read(fd
, t
, bufsz
- datasz
)) <= 0)
2812 datasz
+= (size_t) readsz
;
2813 } while (datasz
< bufsz
);
2815 } while (readsz
> 0);
2818 LIBELF_SET_ERROR(IO
, errno
);
2822 assert(readsz
== 0);
2825 * Free up extra buffer space.
2827 if (bufsz
> datasz
) {
2829 if ((t
= realloc(buf
, datasz
)) == NULL
)
2832 } else { /* Zero bytes read. */
2833 LIBELF_SET_ERROR(ARGUMENT
, 0);
2843 LIBELF_SET_ERROR(RESOURCE
, 0);
2851 _libelf_open_object(int fd
, Elf_Cmd c
, int reporterror
)
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
);
2868 fsize
= (size_t) sb
.st_size
;
2871 * Reject unsupported file types.
2873 if (!S_ISREG(mode
) && !S_ISCHR(mode
) && !S_ISFIFO(mode
) &&
2875 LIBELF_SET_ERROR(ARGUMENT
, 0);
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
);
2889 e
->e_flags
|= LIBELF_F_SPECIAL_FILE
;
2897 * ELF_C_READ and ELF_C_RDWR mode.
2901 if (S_ISREG(mode
)) {
2904 * Reject zero length files.
2907 LIBELF_SET_ERROR(ARGUMENT
, 0);
2913 * Always map regular files in with 'PROT_READ'
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
2921 m
= mmap(NULL
, fsize
, PROT_READ
, MAP_PRIVATE
, fd
, (off_t
) 0);
2923 if (m
== MAP_FAILED
)
2926 flags
= LIBELF_F_RAWFILE_MMAP
;
2930 * Fallback to a read() if the call to mmap() failed,
2931 * or if mmap() is not available.
2934 if ((m
= malloc(fsize
)) == NULL
) {
2935 LIBELF_SET_ERROR(RESOURCE
, 0);
2939 if (read(fd
, m
, fsize
) != (ssize_t
) fsize
) {
2940 LIBELF_SET_ERROR(IO
, errno
);
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
;
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
)
2959 (void) munmap(m
, fsize
);
2964 /* ar(1) archives aren't supported in RDWR mode. */
2966 if (c
== ELF_C_RDWR
&& e
->e_kind
== ELF_K_AR
) {
2968 LIBELF_SET_ERROR(ARGUMENT
, 0);
2973 e
->e_flags
|= flags
;
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")
3005 elf_errmsg(int error
)
3009 if (error
== ELF_E_NONE
&&
3010 (error
= LIBELF_PRIVATE(error
)) == 0)
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
];
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
];
3035 old
= LIBELF_PRIVATE(error
);
3036 LIBELF_PRIVATE(error
) = 0;
3037 return (old
& LIBELF_ELF_ERROR_MASK
);
3042 elf_version(unsigned int v
)
3046 if ((old
= LIBELF_PRIVATE(version
)) == EV_NONE
)
3051 if (v
> EV_CURRENT
) {
3052 LIBELF_SET_ERROR(VERSION
, 0);
3056 LIBELF_PRIVATE(version
) = v
;
3062 elf_begin(int fd
, Elf_Cmd c
, Elf
*a
)
3068 if (LIBELF_PRIVATE(version
) == EV_NONE
) {
3069 LIBELF_SET_ERROR(SEQUENCE
, 0);
3079 * The ELF_C_WRITE command is required to ignore the
3080 * descriptor passed in.
3086 if (a
!= NULL
) { /* not allowed for ar(1) archives. */
3087 LIBELF_SET_ERROR(ARGUMENT
, 0);
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.
3099 ((a
->e_fd
!= -1 && a
->e_fd
!= fd
) || c
!= a
->e_cmd
)) {
3100 LIBELF_SET_ERROR(ARGUMENT
, 0);
3106 LIBELF_SET_ERROR(ARGUMENT
, 0);
3112 e
= _libelf_open_object(fd
, c
, 1);
3114 else if (a
->e_kind
== ELF_K_AR
)
3115 e
= _libelf_ar_open_member(a
->e_fd
, c
, a
);
3118 (e
= a
)->e_activations
++;
3128 Elf_Scn
*scn
, *tscn
;
3130 if (e
== NULL
|| e
->e_activations
== 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
) {
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
3147 if (e
->e_u
.e_ar
.e_nchildren
> 0)
3152 * Reclaim all section descriptors.
3154 STAILQ_FOREACH_SAFE(scn
, &e
->e_u
.e_elf
.e_scn
, s_next
,
3156 scn
= _libelf_release_scn(scn
);
3165 if (e
->e_flags
& LIBELF_F_RAWFILE_MALLOC
)
3168 else if (e
->e_flags
& LIBELF_F_RAWFILE_MMAP
)
3169 (void) munmap(e
->e_rawfile
, e
->e_rawsize
);
3174 if ((e
= e
->e_parent
) != NULL
)
3175 e
->e_u
.e_ar
.e_nchildren
--;
3176 sv
= _libelf_release_elf(sv
);
3184 gelf_getshdr(Elf_Scn
*s
, GElf_Shdr
*d
)
3194 LIBELF_SET_ERROR(ARGUMENT
, 0);
3198 if ((sh
= _libelf_getshdr(s
, ELFCLASSNONE
)) == NULL
)
3201 ec
= s
->s_elf
->e_class
;
3202 assert(/* ec == ELFCLASS32 || */ ec
== ELFCLASS64
);
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
;
3221 sh64
= (Elf64_Shdr
*) sh
;
3230 gelf_getsym(Elf_Data
*ed
, int ndx
, GElf_Sym
*dst
)
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);
3253 assert(/* ec == ELFCLASS32 || */ ec
== ELFCLASS64
);
3256 if (ec
== ELFCLASS32
)
3257 sh_type
= scn
->s_shdr
.s_shdr32
.sh_type
;
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);
3267 msz
= _libelf_msize(ELF_T_SYM
, ec
, e
->e_version
);
3272 if (msz
* (size_t) ndx
>= d
->d_data
.d_size
) {
3273 LIBELF_SET_ERROR(ARGUMENT
, 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
;
3290 sym64
= (Elf64_Sym
*) d
->d_data
.d_buf
+ ndx
;
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);
3308 return (s
== NULL
? elf_getscn(e
, (size_t) 1) :
3309 STAILQ_NEXT(s
, s_next
));
3314 elf_strptr(Elf
*e
, size_t scndx
, size_t offset
)
3319 uint64_t alignment
, count
;
3321 if (e
== NULL
|| e
->e_kind
!= ELF_K_ELF
) {
3322 LIBELF_SET_ERROR(ARGUMENT
, 0);
3326 if ((s
= elf_getscn(e
, scndx
)) == NULL
||
3327 gelf_getshdr(s
, &shdr
) == NULL
)
3330 if (shdr
.sh_type
!= SHT_STRTAB
||
3331 offset
>= shdr
.sh_size
) {
3332 LIBELF_SET_ERROR(ARGUMENT
, 0);
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)
3350 if (d
->d_type
!= ELF_T_BYTE
) {
3351 LIBELF_SET_ERROR(DATA
, 0);
3355 if (offset
>= d
->d_off
&&
3356 offset
< d
->d_off
+ d
->d_size
)
3357 return ((char *) d
->d_buf
+ offset
- d
->d_off
);
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)
3372 if (d
->d_type
!= ELF_T_BYTE
) {
3373 LIBELF_SET_ERROR(DATA
, 0);
3377 if ((alignment
= d
->d_align
) > 1) {
3378 if ((alignment
& (alignment
- 1)) != 0) {
3379 LIBELF_SET_ERROR(DATA
, 0);
3382 count
= roundup2(count
, alignment
);
3385 if (offset
< count
) {
3386 /* offset starts in the 'hole' */
3387 LIBELF_SET_ERROR(ARGUMENT
, 0);
3391 if (offset
< count
+ d
->d_size
) {
3392 if (d
->d_buf
!= NULL
)
3393 return ((char *) d
->d_buf
+
3395 LIBELF_SET_ERROR(DATA
, 0);
3403 LIBELF_SET_ERROR(ARGUMENT
, 0);
3409 elf_getdata(Elf_Scn
*s
, Elf_Data
*ed
)
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);
3428 assert(e
->e_kind
== ELF_K_ELF
);
3430 if (d
== NULL
&& (d
= STAILQ_FIRST(&s
->s_data
)) != NULL
)
3431 return (&d
->d_data
);
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);
3445 elfclass
= e
->e_class
;
3447 assert(/* elfclass == ELFCLASS32 || */ elfclass
== ELFCLASS64
);
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
;
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);
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);
3476 if ((fsz
= (/* elfclass == ELFCLASS32 ? elf32_fsize :*/ elf64_fsize
)
3477 (elftype
, (size_t) 1, e
->e_version
)) == 0) {
3478 LIBELF_SET_ERROR(UNIMPL
, 0);
3482 if (sh_size
% fsz
) {
3483 LIBELF_SET_ERROR(SECTION
, 0);
3487 if (sh_size
/ fsz
> SIZE_MAX
) {
3488 LIBELF_SET_ERROR(RANGE
, 0);
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);
3502 assert(count
<= SIZE_MAX
);
3503 assert(msz
* count
<= SIZE_MAX
);
3505 if ((d
= _libelf_allocate_data(s
)) == 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);
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);
3537 STAILQ_INSERT_TAIL(&s
->s_data
, d
, d_next
);
3539 return (&d
->d_data
);
3542 #endif /* !_PRIVATE_LIBELF_H_ */