xref: /dragonfly/lib/libexecinfo/private_libelf.h (revision 77bd33e17033047707557baf11c4799f1d4a3110)
1 /*-
2  * Copyright (c) 2006,2008-2010 Joseph Koshy
3  * All rights reserved.
4  *
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.
13  *
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.
25  */
26 
27 #ifndef _PRIVATE_LIBELF_H_
28 #define   _PRIVATE_LIBELF_H_
29 
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>
42 
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__ */
49 
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
58 
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
102 
103 #define   elf64_fsize         __ei_elf64_fsize
104 #define   elf_getscn          __ei_elf_getscn
105 
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
117 
118 /* elfdefinitions.h */
119 /*
120  * Offsets in the `ei_ident[]` field of an ELF executable header.
121  */
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")
134 
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__
140 };
141 
142 /*
143  * The ELF class of an object.
144  */
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")
149 
150 #undef    _ELF_DEFINE_EC
151 #define   _ELF_DEFINE_EC(N, V, DESCR)   N = V ,
152 enum {
153           _ELF_DEFINE_ELFCLASS()
154           EC__LAST__
155 };
156 
157 /*
158  * Endianness of data in an ELF object.
159  */
160 
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")
165 
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__
171 };
172 
173 /*
174  * Values of the magic numbers used in identification array.
175  */
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')
181 
182 #undef    _ELF_DEFINE_EMAG
183 #define   _ELF_DEFINE_EMAG(N, V)                  N = V ,
184 enum {
185           _ELF_DEFINE_ELF_MAGIC()
186           ELFMAG__LAST__
187 };
188 
189 /*
190  * ELF Machine types: (EM_*).
191  */
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")
196 
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__
202 };
203 
204 /* ELF file format version numbers. */
205 #define   EV_NONE             0
206 #define   EV_CURRENT          1
207 
208 /*
209  * Special section indices.
210  */
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")
241 
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__
247 };
248 
249 /*
250  * Section types.
251  */
252 
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")
396 
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
402 };
403 
404 #define   PN_XNUM                       0xFFFFU /* Use extended section numbering. */
405 
406 /**
407  ** ELF Types.
408  **/
409 
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. */
418 
419 /*
420  * Capability descriptors.
421  */
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;
429 
430 /*
431  * Dynamic section entries.
432  */
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;
440 
441 /*
442  * The executable header (EHDR).
443  */
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;
460 
461 /*
462  * Note descriptors.
463  */
464 
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;
470 
471 /*
472  * Program Header Table (PHDR) entries.
473  */
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;
484 
485 /*
486  * Move entries, for describing data in COMMON blocks in a compact
487  * manner.
488  */
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;
496 
497 /*
498  * Section Header Table (SHDR) entries.
499  */
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;
512 
513 /*
514  * Symbol table entries.
515  */
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;
524 
525 /*
526  * Syminfo descriptors, containing additional symbol information.
527  */
528 typedef struct {
529           Elf64_Half          si_boundto;  /* Entry index with additional flags. */
530           Elf64_Half          si_flags;    /* Flags. */
531 } Elf64_Syminfo;
532 
533 /*
534  * Relocation descriptors.
535  */
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;
540 
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;
546 
547 /*
548  * Symbol versioning structures.
549  */
550 typedef struct {
551           Elf64_Word          vda_name;    /* Index to name. */
552           Elf64_Word          vda_next;    /* Offset to next entry. */
553 } Elf64_Verdaux;
554 
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;
562 
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;
572 
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;
580 
581 /*
582  * The header for GNU-style hash sections.
583  */
584 
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;
591 
592 /* libelf.h */
593 /* Library private data structures */
594 typedef struct _Elf Elf;
595 typedef struct _Elf_Scn Elf_Scn;
596 
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;
605 
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;
634 
635 #define   ELF_T_FIRST         ELF_T_ADDR
636 #define   ELF_T_LAST          ELF_T_GNUHASH
637 
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;
650 
651 /*
652  * An `Elf_Data' structure describes data in an
653  * ELF section.
654  */
655 typedef struct _Elf_Data {
656           /*
657            * `Public' members that are part of the ELF(3) API.
658            */
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;
666 
667 /*
668  * An `Elf_Arhdr' structure describes an archive
669  * header.
670  */
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;
679 
680           /*
681            * Members that are not part of the public API.
682            */
683           unsigned int        ar_flags;
684 } Elf_Arhdr;
685 
686 /*
687  * An `Elf_Arsym' describes an entry in the archive
688  * symbol table.
689  */
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;
695 
696 /*
697  * Error numbers.
698  */
699 
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 */
717 };
718 
719 /*
720  * Flags defined by the API.
721  */
722 
723 #define   ELF_F_LAYOUT        0x001U    /* application will layout the file */
724 #define   ELF_F_DIRTY         0x002U    /* a section or ELF file is dirty */
725 
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
746 }
747 #endif
748 
749 /* gelf.h */
750 typedef Elf64_Shdr  GElf_Shdr;          /* Section header */
751 typedef Elf64_Sym   GElf_Sym; /* Symbol table entries */
752 
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
761 }
762 #endif
763 
764 /* _libelf.h */
765 /*
766  * Library-private data structures.
767  */
768 
769 #define LIBELF_MSG_SIZE       256
770 
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];
779 };
780 
781 #if 0
782 extern struct _libelf_globals _libelf;
783 #endif
784 
785 #define   LIBELF_PRIVATE(N)   (_libelf.libelf_##N)
786 
787 #define   LIBELF_ELF_ERROR_MASK                             0xFF
788 #define   LIBELF_OS_ERROR_SHIFT                             8
789 
790 #define   LIBELF_ERROR(E, O) (((E) & LIBELF_ELF_ERROR_MASK) |         \
791           ((O) << LIBELF_OS_ERROR_SHIFT))
792 
793 #define   LIBELF_SET_ERROR(E, O) do {                                           \
794                     LIBELF_PRIVATE(error) = LIBELF_ERROR(ELF_E_##E, (O));       \
795           } while (0)
796 
797 /*
798  * Flags for library internal use.  These use the upper 16 bits of the
799  * `e_flags' field.
800  */
801 
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 */
807 
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 */
820 
821           /*
822            * Header information for archive members.  See the
823            * LIBELF_F_AR_HEADER flag.
824            */
825           union {
826                     Elf_Arhdr *e_arhdr; /* translated header */
827                     unsigned char       *e_rawhdr;          /* untranslated header */
828           } e_hdr;
829 
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;
860 };
861 
862 /*
863  * The internal descriptor wrapping the "Elf_Data" type.
864  */
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;
870 };
871 
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() */
888 };
889 
890 enum {
891           ELF_TOFILE,
892           ELF_TOMEMORY
893 };
894 
895 /* PRIVATE */
896 
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
905 };
906 
907 /* libelf_msize.c */
908 struct msize {
909           size_t    msz64;
910 };
911 
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) },
937 };
938 
939 static size_t
_libelf_msize(Elf_Type t,int elfclass,unsigned int version)940 _libelf_msize(Elf_Type t, int elfclass, unsigned int version)
941 {
942           size_t sz;
943 
944           assert(/*elfclass == ELFCLASS32 ||*/ elfclass == ELFCLASS64);
945           assert((signed) t >= ELF_T_FIRST && t <= ELF_T_LAST);
946 
947           if (version != EV_CURRENT) {
948                     LIBELF_SET_ERROR(VERSION, 0);
949                     return (0);
950           }
951 
952           sz = /* (elfclass == ELFCLASS32) ? msize[t].msz32 : */ msize[t].msz64;
953 
954           return (sz);
955 }
956 
957 /* libelf_fsize.c */
958 struct tfsize {
959           size_t fsz64;
960 };
961 
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) },
1005 };
1006 
1007 static size_t
_libelf_fsize(Elf_Type t,int ec,unsigned int v,size_t c)1008 _libelf_fsize(Elf_Type t, int ec, unsigned int v, size_t c)
1009 {
1010           size_t sz;
1011 
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);
1021           }
1022 
1023           return (sz*c);
1024 }
1025 
1026 /* gelf_fsize.c */
1027 static size_t
elf64_fsize(Elf_Type t,size_t c,unsigned int v)1028 elf64_fsize(Elf_Type t, size_t c, unsigned int v)
1029 {
1030           return (_libelf_fsize(t, ELFCLASS64, v, c));
1031 }
1032 
1033 /* libelf_allocate.h */
1034 static Elf *
_libelf_allocate_elf(void)1035 _libelf_allocate_elf(void)
1036 {
1037           Elf *e;
1038 
1039           if ((e = malloc(sizeof(*e))) == NULL) {
1040                     LIBELF_SET_ERROR(RESOURCE, errno);
1041                     return NULL;
1042           }
1043 
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);
1056 
1057           (void) memset(&e->e_u, 0, sizeof(e->e_u));
1058 
1059           return (e);
1060 }
1061 
1062 static void
_libelf_init_elf(Elf * e,Elf_Kind kind)1063 _libelf_init_elf(Elf *e, Elf_Kind kind)
1064 {
1065           assert(e != NULL);
1066           assert(e->e_kind == ELF_K_NONE);
1067 
1068           e->e_kind = kind;
1069 
1070           switch (kind) {
1071           case ELF_K_ELF:
1072                     STAILQ_INIT(&e->e_u.e_elf.e_scn);
1073                     break;
1074           default:
1075                     break;
1076           }
1077 }
1078 
1079 #define   FREE(P)             do {                                    \
1080                     if (P)                                            \
1081                               free(P);                      \
1082           } while (0)
1083 
1084 static Elf *
_libelf_release_elf(Elf * e)1085 _libelf_release_elf(Elf *e)
1086 {
1087 #if 0
1088           Elf_Arhdr *arh;
1089 #endif
1090 
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
1097 
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;
1110                     }
1111 
1112                     assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
1113 
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);
1120                     }
1121 #endif
1122 
1123                     break;
1124 
1125           default:
1126                     break;
1127           }
1128 
1129           free(e);
1130 
1131           return (NULL);
1132 }
1133 
1134 #undef FREE
1135 
1136 static struct _Libelf_Data *
_libelf_allocate_data(Elf_Scn * s)1137 _libelf_allocate_data(Elf_Scn *s)
1138 {
1139           struct _Libelf_Data *d;
1140 
1141           if ((d = calloc((size_t) 1, sizeof(*d))) == NULL) {
1142                     LIBELF_SET_ERROR(RESOURCE, 0);
1143                     return (NULL);
1144           }
1145 
1146           d->d_scn = s;
1147 
1148           return (d);
1149 }
1150 
1151 static struct _Libelf_Data *
_libelf_release_data(struct _Libelf_Data * d)1152 _libelf_release_data(struct _Libelf_Data *d)
1153 {
1154 
1155           if (d->d_flags & LIBELF_F_DATA_MALLOCED)
1156                     free(d->d_data.d_buf);
1157 
1158           free(d);
1159 
1160           return (NULL);
1161 }
1162 
1163 static Elf_Scn *
_libelf_allocate_scn(Elf * e,size_t ndx)1164 _libelf_allocate_scn(Elf *e, size_t ndx)
1165 {
1166           Elf_Scn *s;
1167 
1168           if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
1169                     LIBELF_SET_ERROR(RESOURCE, errno);
1170                     return (NULL);
1171           }
1172 
1173           s->s_elf = e;
1174           s->s_ndx = ndx;
1175 
1176           STAILQ_INIT(&s->s_data);
1177           STAILQ_INIT(&s->s_rawdata);
1178 
1179           STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
1180 
1181           return (s);
1182 }
1183 
1184 static Elf_Scn *
_libelf_release_scn(Elf_Scn * s)1185 _libelf_release_scn(Elf_Scn *s)
1186 {
1187           Elf *e;
1188           struct _Libelf_Data *d, *td;
1189 
1190           assert(s != NULL);
1191 
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);
1195           }
1196 
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);
1201           }
1202 
1203           e = s->s_elf;
1204 
1205           assert(e != NULL);
1206 
1207           STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
1208 
1209           free(s);
1210 
1211           return (NULL);
1212 }
1213 
1214 /* libelf_data.c */
1215 static int
_libelf_xlate_shtype(uint32_t sht)1216 _libelf_xlate_shtype(uint32_t sht)
1217 {
1218           /*
1219            * Look for known section types.
1220            */
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:
1269                     /*
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.
1274                      */
1275                     if (sht >= SHT_LOOS && sht <= SHT_HIUSER)
1276                               return (ELF_T_BYTE);
1277 
1278                     /*
1279                      * Other values are unsupported.
1280                      */
1281                     return (-1);
1282           }
1283 }
1284 
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)
1321 
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)
1377 
1378 #define   ROUNDUP2(V,N)       (V) = ((((V) + (N) - 1)) & ~((N) - 1))
1379 
1380 static int
_libelf_cvt_ADDR64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1381 _libelf_cvt_ADDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1382     size_t count, int byteswap)
1383 {
1384           Elf64_Addr t, *d = (Elf64_Addr *) (uintptr_t) dst;
1385           size_t c;
1386 
1387           if (dsz < count * sizeof(Elf64_Addr))
1388                     return (0);
1389 
1390           if (!byteswap) {
1391                     (void) memcpy(dst, src, count * sizeof(*d));
1392                     return (1);
1393           }
1394 
1395           for (c = 0; c < count; c++) {
1396                     READ_ADDR64(src,t);
1397                     SWAP_ADDR64(t);
1398                     *d++ = t;
1399           }
1400 
1401           return (1);
1402 }
1403 
1404 static int
_libelf_cvt_CAP64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1405 _libelf_cvt_CAP64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1406     size_t count, int byteswap)
1407 {
1408           Elf64_Cap t, *d;
1409           unsigned char       *s,*s0;
1410           size_t              fsz;
1411 
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;
1415 
1416           if (dsz < count * sizeof(Elf64_Cap))
1417                     return (0);
1418 
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                               /**/
1430                     }
1431                     *d-- = t; s0 -= fsz;
1432           }
1433 
1434           return (1);
1435 }
1436 
1437 static int
_libelf_cvt_DYN64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1438 _libelf_cvt_DYN64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1439     size_t count, int byteswap)
1440 {
1441           Elf64_Dyn t, *d;
1442           unsigned char       *s,*s0;
1443           size_t              fsz;
1444 
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;
1448 
1449           if (dsz < count * sizeof(Elf64_Dyn))
1450                     return (0);
1451 
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                               /**/
1463                     }
1464                     *d-- = t; s0 -= fsz;
1465           }
1466 
1467           return (1);
1468 }
1469 
1470 static int
_libelf_cvt_EHDR64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1471 _libelf_cvt_EHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1472     size_t count, int byteswap)
1473 {
1474           Elf64_Ehdr          t, *d;
1475           unsigned char       *s,*s0;
1476           size_t              fsz;
1477 
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;
1481 
1482           if (dsz < count * sizeof(Elf64_Ehdr))
1483                     return (0);
1484 
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                               /**/
1520                     }
1521                     *d-- = t; s0 -= fsz;
1522           }
1523 
1524           return (1);
1525 }
1526 
1527 static int
_libelf_cvt_HALF_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1528 _libelf_cvt_HALF_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1529     size_t count, int byteswap)
1530 {
1531           Elf64_Half t, *d = (Elf64_Half *) (uintptr_t) dst;
1532           size_t c;
1533 
1534           if (dsz < count * sizeof(Elf64_Half))
1535                     return (0);
1536 
1537           if (!byteswap) {
1538                     (void) memcpy(dst, src, count * sizeof(*d));
1539                     return (1);
1540           }
1541 
1542           for (c = 0; c < count; c++) {
1543                     READ_HALF(src,t);
1544                     SWAP_HALF(t);
1545                     *d++ = t;
1546           }
1547 
1548           return (1);
1549 }
1550 
1551 static int
_libelf_cvt_LWORD_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1552 _libelf_cvt_LWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1553     size_t count, int byteswap)
1554 {
1555           Elf64_Lword t, *d = (Elf64_Lword *) (uintptr_t) dst;
1556           size_t c;
1557 
1558           if (dsz < count * sizeof(Elf64_Lword))
1559                     return (0);
1560 
1561           if (!byteswap) {
1562                     (void) memcpy(dst, src, count * sizeof(*d));
1563                     return (1);
1564           }
1565 
1566           for (c = 0; c < count; c++) {
1567                     READ_LWORD(src,t);
1568                     SWAP_LWORD(t);
1569                     *d++ = t;
1570           }
1571 
1572           return (1);
1573 }
1574 
1575 static int
_libelf_cvt_MOVE64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1576 _libelf_cvt_MOVE64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1577     size_t count, int byteswap)
1578 {
1579           Elf64_Move          t, *d;
1580           unsigned char       *s,*s0;
1581           size_t              fsz;
1582 
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;
1586 
1587           if (dsz < count * sizeof(Elf64_Move))
1588                     return (0);
1589 
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                               /**/
1607                     }
1608                     *d-- = t; s0 -= fsz;
1609           }
1610 
1611           return (1);
1612 }
1613 
1614 static int
_libelf_cvt_OFF64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1615 _libelf_cvt_OFF64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1616     size_t count, int byteswap)
1617 {
1618           Elf64_Off t, *d = (Elf64_Off *) (uintptr_t) dst;
1619           size_t c;
1620 
1621           if (dsz < count * sizeof(Elf64_Off))
1622                     return (0);
1623 
1624           if (!byteswap) {
1625                     (void) memcpy(dst, src, count * sizeof(*d));
1626                     return (1);
1627           }
1628 
1629           for (c = 0; c < count; c++) {
1630                     READ_OFF64(src,t);
1631                     SWAP_OFF64(t);
1632                     *d++ = t;
1633           }
1634 
1635           return (1);
1636 }
1637 
1638 static int
_libelf_cvt_PHDR64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1639 _libelf_cvt_PHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1640     size_t count, int byteswap)
1641 {
1642           Elf64_Phdr          t, *d;
1643           unsigned char       *s,*s0;
1644           size_t              fsz;
1645 
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;
1649 
1650           if (dsz < count * sizeof(Elf64_Phdr))
1651                     return (0);
1652 
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                               /**/
1676                     }
1677                     *d-- = t; s0 -= fsz;
1678           }
1679 
1680           return (1);
1681 }
1682 
1683 static int
_libelf_cvt_REL64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1684 _libelf_cvt_REL64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1685     size_t count, int byteswap)
1686 {
1687           Elf64_Rel t, *d;
1688           unsigned char       *s,*s0;
1689           size_t              fsz;
1690 
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;
1694 
1695           if (dsz < count * sizeof(Elf64_Rel))
1696                     return (0);
1697 
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                               /**/
1709                     }
1710                     *d-- = t; s0 -= fsz;
1711           }
1712 
1713           return (1);
1714 }
1715 
1716 static int
_libelf_cvt_RELA64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1717 _libelf_cvt_RELA64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1718     size_t count, int byteswap)
1719 {
1720           Elf64_Rela          t, *d;
1721           unsigned char       *s,*s0;
1722           size_t              fsz;
1723 
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;
1727 
1728           if (dsz < count * sizeof(Elf64_Rela))
1729                     return (0);
1730 
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                               /**/
1744                     }
1745                     *d-- = t; s0 -= fsz;
1746           }
1747 
1748           return (1);
1749 }
1750 
1751 static int
_libelf_cvt_SHDR64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1752 _libelf_cvt_SHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1753     size_t count, int byteswap)
1754 {
1755           Elf64_Shdr          t, *d;
1756           unsigned char       *s,*s0;
1757           size_t              fsz;
1758 
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;
1762 
1763           if (dsz < count * sizeof(Elf64_Shdr))
1764                     return (0);
1765 
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                               /**/
1793                     }
1794                     *d-- = t; s0 -= fsz;
1795           }
1796 
1797           return (1);
1798 }
1799 
1800 static int
_libelf_cvt_SWORD_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1801 _libelf_cvt_SWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1802     size_t count, int byteswap)
1803 {
1804           Elf64_Sword t, *d = (Elf64_Sword *) (uintptr_t) dst;
1805           size_t c;
1806 
1807           if (dsz < count * sizeof(Elf64_Sword))
1808                     return (0);
1809 
1810           if (!byteswap) {
1811                     (void) memcpy(dst, src, count * sizeof(*d));
1812                     return (1);
1813           }
1814 
1815           for (c = 0; c < count; c++) {
1816                     READ_SWORD(src,t);
1817                     SWAP_SWORD(t);
1818                     *d++ = t;
1819           }
1820 
1821           return (1);
1822 }
1823 
1824 static int
_libelf_cvt_SXWORD_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1825 _libelf_cvt_SXWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1826     size_t count, int byteswap)
1827 {
1828           Elf64_Sxword t, *d = (Elf64_Sxword *) (uintptr_t) dst;
1829           size_t c;
1830 
1831           if (dsz < count * sizeof(Elf64_Sxword))
1832                     return (0);
1833 
1834           if (!byteswap) {
1835                     (void) memcpy(dst, src, count * sizeof(*d));
1836                     return (1);
1837           }
1838 
1839           for (c = 0; c < count; c++) {
1840                     READ_SXWORD(src,t);
1841                     SWAP_SXWORD(t);
1842                     *d++ = t;
1843           }
1844 
1845           return (1);
1846 }
1847 
1848 static int
_libelf_cvt_SYMINFO64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1849 _libelf_cvt_SYMINFO64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1850     size_t count, int byteswap)
1851 {
1852           Elf64_Syminfo       t, *d;
1853           unsigned char       *s,*s0;
1854           size_t              fsz;
1855 
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;
1859 
1860           if (dsz < count * sizeof(Elf64_Syminfo))
1861                     return (0);
1862 
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                               /**/
1874                     }
1875                     *d-- = t; s0 -= fsz;
1876           }
1877 
1878           return (1);
1879 }
1880 
1881 static int
_libelf_cvt_SYM64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1882 _libelf_cvt_SYM64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1883     size_t count, int byteswap)
1884 {
1885           Elf64_Sym t, *d;
1886           unsigned char       *s,*s0;
1887           size_t              fsz;
1888 
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;
1892 
1893           if (dsz < count * sizeof(Elf64_Sym))
1894                     return (0);
1895 
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                               /**/
1915                     }
1916                     *d-- = t; s0 -= fsz;
1917           }
1918 
1919           return (1);
1920 }
1921 
1922 static int
_libelf_cvt_WORD_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1923 _libelf_cvt_WORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1924     size_t count, int byteswap)
1925 {
1926           Elf64_Word t, *d = (Elf64_Word *) (uintptr_t) dst;
1927           size_t c;
1928 
1929           if (dsz < count * sizeof(Elf64_Word))
1930                     return (0);
1931 
1932           if (!byteswap) {
1933                     (void) memcpy(dst, src, count * sizeof(*d));
1934                     return (1);
1935           }
1936 
1937           for (c = 0; c < count; c++) {
1938                     READ_WORD(src,t);
1939                     SWAP_WORD(t);
1940                     *d++ = t;
1941           }
1942 
1943           return (1);
1944 }
1945 
1946 static int
_libelf_cvt_XWORD_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1947 _libelf_cvt_XWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1948     size_t count, int byteswap)
1949 {
1950           Elf64_Xword t, *d = (Elf64_Xword *) (uintptr_t) dst;
1951           size_t c;
1952 
1953           if (dsz < count * sizeof(Elf64_Xword))
1954                     return (0);
1955 
1956           if (!byteswap) {
1957                     (void) memcpy(dst, src, count * sizeof(*d));
1958                     return (1);
1959           }
1960 
1961           for (c = 0; c < count; c++) {
1962                     READ_XWORD(src,t);
1963                     SWAP_XWORD(t);
1964                     *d++ = t;
1965           }
1966 
1967           return (1);
1968 }
1969 
1970 static int
_libelf_cvt_VDEF64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1971 _libelf_cvt_VDEF64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1972     size_t count, int byteswap)
1973 {
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;
1984 
1985           for (stmp = src, vnext = ~0U;
1986                vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
1987                stmp += vnext, dst += vnext) {
1988 
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                               /**/
2010                     }
2011 
2012                     dp = (Elf64_Verdef *) (uintptr_t) dst;
2013                     *dp = t;
2014 
2015                     aux = t.vd_aux;
2016                     cnt = t.vd_cnt;
2017                     vnext = t.vd_next;
2018 
2019                     if (aux < vermsz)
2020                               return (0);
2021 
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--) {
2027 
2028                               s = srcaux;
2029                               /* Read an Elf64_Verdaux */
2030                     READ_WORD(s,a.vda_name);
2031                     READ_WORD(s,a.vda_next);
2032                     /**/
2033 
2034                               if (byteswap) {
2035                                         /* Swap an Elf64_Verdaux */
2036                               SWAP_WORD(a.vda_name);
2037                               SWAP_WORD(a.vda_next);
2038                               /**/
2039                               }
2040 
2041                               anext = a.vda_next;
2042 
2043                               ap = ((Elf64_Verdaux *) (uintptr_t) dstaux);
2044                               *ap = a;
2045                     }
2046 
2047                     if (anext || cnt)
2048                               return (0);
2049           }
2050 
2051           if (vnext)
2052                     return (0);
2053 
2054           return (1);
2055 }
2056 
2057 static int
_libelf_cvt_VNEED64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)2058 _libelf_cvt_VNEED64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
2059     size_t count, int byteswap)
2060 {
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;
2071 
2072           for (stmp = src, vnext = ~0U;
2073                vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
2074                stmp += vnext, dst += vnext) {
2075 
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                               /**/
2093                     }
2094 
2095                     dp = (Elf64_Verneed *) (uintptr_t) dst;
2096                     *dp = t;
2097 
2098                     aux = t.vn_aux;
2099                     cnt = t.vn_cnt;
2100                     vnext = t.vn_next;
2101 
2102                     if (aux < vermsz)
2103                               return (0);
2104 
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--) {
2110 
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                     /**/
2119 
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                               /**/
2128                               }
2129 
2130                               anext = a.vna_next;
2131 
2132                               ap = ((Elf64_Vernaux *) (uintptr_t) dstaux);
2133                               *ap = a;
2134                     }
2135 
2136                     if (anext || cnt)
2137                               return (0);
2138           }
2139 
2140           if (vnext)
2141                     return (0);
2142 
2143           return (1);
2144 }
2145 
2146 static int
_libelf_cvt_BYTE_tox(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)2147 _libelf_cvt_BYTE_tox(unsigned char *dst, size_t dsz, unsigned char *src,
2148     size_t count, int byteswap)
2149 {
2150           (void) byteswap;
2151           if (dsz < count)
2152                     return (0);
2153           if (dst != src)
2154                     (void) memcpy(dst, src, count);
2155           return (1);
2156 }
2157 
2158 static int
_libelf_cvt_GNUHASH64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t srcsz,int byteswap)2159 _libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
2160     size_t srcsz, int byteswap)
2161 {
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;
2167 
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);
2171 
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);
2177 
2178           srcsz -= sz;
2179 
2180           if (byteswap) {
2181                     SWAP_WORD(nbuckets);
2182                     SWAP_WORD(symndx);
2183                     SWAP_WORD(maskwords);
2184                     SWAP_WORD(shift2);
2185           }
2186 
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);
2191 
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;
2197 
2198           dsz -= sizeof(Elf_GNU_Hash_Header);
2199           dst += sizeof(Elf_GNU_Hash_Header);
2200 
2201           bloom64 = (uint64_t *) (uintptr_t) dst;
2202 
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;
2209           }
2210 
2211           /* The hash buckets follows the bloom filter. */
2212           dst += maskwords * sizeof(uint64_t);
2213           buckets = (uint32_t *) (uintptr_t) dst;
2214 
2215           for (n = 0; n < nbuckets; n++) {
2216                     READ_WORD(src, t32);
2217                     if (byteswap)
2218                               SWAP_WORD(t32);
2219                     buckets[n] = t32;
2220           }
2221 
2222           dst += nbuckets * sizeof(uint32_t);
2223 
2224           /* The hash chain follows the hash buckets. */
2225           dsz -= sz;
2226           srcsz -= sz;
2227 
2228           if (dsz < srcsz)    /* Destination lacks space. */
2229                     return (0);
2230 
2231           nchains = srcsz / sizeof(uint32_t);
2232           chains = (uint32_t *) (uintptr_t) dst;
2233 
2234           for (n = 0; n < nchains; n++) {
2235                     READ_WORD(src, t32);
2236                     if (byteswap)
2237                               SWAP_WORD(t32);
2238                     *chains++ = t32;
2239           }
2240 
2241           return (1);
2242 }
2243 
2244 static int
_libelf_cvt_NOTE_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)2245 _libelf_cvt_NOTE_tom(unsigned char *dst, size_t dsz, unsigned char *src,
2246     size_t count, int byteswap)
2247 {
2248           uint32_t namesz, descsz, type;
2249           Elf_Note *en;
2250           size_t sz, hdrsz;
2251 
2252           if (dsz < count)    /* Destination buffer is too small. */
2253                     return (0);
2254 
2255           hdrsz = 3 * sizeof(uint32_t);
2256           if (count < hdrsz)            /* Source too small. */
2257                     return (0);
2258 
2259           if (!byteswap) {
2260                     (void) memcpy(dst, src, count);
2261                     return (1);
2262           }
2263 
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);
2270 
2271                     /* Translate. */
2272                     SWAP_WORD(namesz);
2273                     SWAP_WORD(descsz);
2274                     SWAP_WORD(type);
2275 
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;
2281 
2282                     dsz -= sizeof(Elf_Note);
2283                     dst += sizeof(Elf_Note);
2284                     count -= hdrsz;
2285 
2286                     ROUNDUP2(namesz, 4U);
2287                     ROUNDUP2(descsz, 4U);
2288 
2289                     sz = namesz + descsz;
2290 
2291                     if (count < sz || dsz < sz)   /* Buffers are too small. */
2292                               return (0);
2293 
2294                     (void) memcpy(dst, src, sz);
2295 
2296                     src += sz;
2297                     dst += sz;
2298 
2299                     count -= sz;
2300                     dsz -= sz;
2301           }
2302 
2303           return (1);
2304 }
2305 
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);
2315 };
2316 
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           /*]*/
2362           /*
2363            * Types that need hand-coded converters follow.
2364            */
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 }
2369 };
2370 
_libelf_get_translator(Elf_Type t,int direction,int elfclass)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)
2374 {
2375           assert(/* elfclass == ELFCLASS32 || */ elfclass == ELFCLASS64);
2376           assert(/* direction == ELF_TOFILE || */ direction == ELF_TOMEMORY);
2377 
2378           if (t >= ELF_T_NUM ||
2379               (/* elfclass != ELFCLASS32 && */ elfclass != ELFCLASS64) ||
2380               (/* direction != ELF_TOFILE && */ direction != ELF_TOMEMORY))
2381                     return (NULL);
2382 
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
2390 }
2391 
2392 /* libelf_ehdr.h */
2393 /*
2394  * Retrieve counts for sections, phdrs and the section string table index
2395  * from section header #0 of the ELF object.
2396  */
2397 static int
_libelf_load_extended(Elf * e,int ec,uint64_t shoff,uint16_t phnum,uint16_t strndx)2398 _libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
2399     uint16_t strndx)
2400 {
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;
2406 
2407           assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
2408 
2409           fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1);
2410           assert(fsz > 0);
2411 
2412           if (e->e_rawsize < shoff + fsz) { /* raw file too small */
2413                     LIBELF_SET_ERROR(HEADER, 0);
2414                     return (0);
2415           }
2416 
2417           if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL)
2418                     return (0);
2419 
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));
2424 
2425 #define   GET_SHDR_MEMBER(M) (/* (ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M :*/ \
2426                     scn->s_shdr.s_shdr64.M)
2427 
2428           if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) {
2429                     LIBELF_SET_ERROR(SECTION, 0);
2430                     return (0);
2431           }
2432 
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
2439 
2440           return (1);
2441 }
2442 
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)
2456 
2457 static void *
_libelf_ehdr(Elf * e,int ec,int allocate)2458 _libelf_ehdr(Elf *e, int ec, int allocate)
2459 {
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);
2466 
2467           assert(ec == ELFCLASS32 || ec == ELFCLASS64);
2468 
2469           if (e == NULL || e->e_kind != ELF_K_ELF) {
2470                     LIBELF_SET_ERROR(ARGUMENT, 0);
2471                     return (NULL);
2472           }
2473 
2474           if (e->e_class != ELFCLASSNONE && e->e_class != ec) {
2475                     LIBELF_SET_ERROR(CLASS, 0);
2476                     return (NULL);
2477           }
2478 
2479           if (e->e_version != EV_CURRENT) {
2480                     LIBELF_SET_ERROR(VERSION, 0);
2481                     return (NULL);
2482           }
2483 
2484           if (e->e_class == ELFCLASSNONE)
2485                     e->e_class = ec;
2486 
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;
2493 
2494           if (ehdr != NULL)   /* already have a translated ehdr */
2495                     return (ehdr);
2496 
2497           fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
2498           assert(fsz > 0);
2499 
2500           if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) {
2501                     LIBELF_SET_ERROR(HEADER, 0);
2502                     return (NULL);
2503           }
2504 
2505           msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT);
2506 
2507           assert(msz > 0);
2508 
2509           if ((ehdr = calloc((size_t) 1, msz)) == NULL) {
2510                     LIBELF_SET_ERROR(RESOURCE, 0);
2511                     return (NULL);
2512           }
2513 
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
2520           {
2521                     e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr;
2522                     EHDR_INIT(ehdr,64);
2523           }
2524 
2525           if (allocate)
2526                     e->e_flags |= ELF_F_DIRTY;
2527 
2528           if (e->e_cmd == ELF_C_WRITE)
2529                     return (ehdr);
2530 
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));
2534 
2535           /*
2536            * If extended numbering is being used, read the correct
2537            * number of sections and program header entries.
2538            */
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
2547           {
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;
2552           }
2553 
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);
2559           }
2560 
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);
2567 
2568           return (ehdr);
2569 }
2570 
2571 /* libelf_shdr.c */
2572 static void *
_libelf_getshdr(Elf_Scn * s,int ec)2573 _libelf_getshdr(Elf_Scn *s, int ec)
2574 {
2575           Elf *e;
2576 
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);
2581           }
2582 
2583           if (ec == ELFCLASSNONE)
2584                     ec = e->e_class;
2585 
2586           if (ec != e->e_class) {
2587                     LIBELF_SET_ERROR(CLASS, 0);
2588                     return (NULL);
2589           }
2590 
2591           return ((void *) &s->s_shdr);
2592 }
2593 
2594 /* elf_scn.c */
2595 static int
_libelf_load_section_headers(Elf * e,void * ehdr)2596 _libelf_load_section_headers(Elf *e, void *ehdr)
2597 {
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);
2609 
2610           assert(e != NULL);
2611           assert(ehdr != NULL);
2612           assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0);
2613 
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);                                       \
2621                     }                                                           \
2622           } while (0)
2623 
2624           ec = e->e_class;
2625           fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
2626           assert(fsz > 0);
2627 
2628           shnum = e->e_u.e_elf.e_nscn;
2629 
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
2637           {
2638                     eh64 = (Elf64_Ehdr *) ehdr;
2639                     shoff = eh64->e_shoff;
2640                     CHECK_EHDR(e, eh64);
2641           }
2642 
2643           xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
2644 
2645           swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder);
2646           src = e->e_rawfile + shoff;
2647 
2648           /*
2649            * If the file is using extended numbering then section #0
2650            * would have already been read in.
2651            */
2652 
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));
2657 
2658                     i = 1;
2659                     src += fsz;
2660           }
2661 
2662           for (; i < shnum; i++, src += fsz) {
2663                     if ((scn = _libelf_allocate_scn(e, i)) == NULL)
2664                               return (0);
2665 
2666                     (*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
2667                         src, (size_t) 1, swapbytes);
2668 
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
2676                     {
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;
2680                     }
2681           }
2682 
2683           e->e_flags |= LIBELF_F_SHDRS_LOADED;
2684 
2685           return (1);
2686 }
2687 
2688 static Elf_Scn *
elf_getscn(Elf * e,size_t index)2689 elf_getscn(Elf *e, size_t index)
2690 {
2691           int ec;
2692           void *ehdr;
2693           Elf_Scn *s;
2694 
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);
2699           }
2700 
2701           if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
2702                     return (NULL);
2703 
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);
2708 
2709           STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next)
2710                     if (s->s_ndx == index)
2711                               return (s);
2712 
2713           LIBELF_SET_ERROR(ARGUMENT, 0);
2714           return (NULL);
2715 }
2716 
2717 /* libelf_memory.c */
2718 static Elf *
_libelf_memory(unsigned char * image,size_t sz,int reporterror)2719 _libelf_memory(unsigned char *image, size_t sz, int reporterror)
2720 {
2721           Elf *e;
2722           int e_class;
2723           enum Elf_Error error;
2724           unsigned int e_byteorder, e_version;
2725 
2726           assert(image != NULL);
2727           assert(sz > 0);
2728 
2729           if ((e = _libelf_allocate_elf()) == NULL)
2730                     return (NULL);
2731 
2732           e->e_cmd = ELF_C_READ;
2733           e->e_rawfile = image;
2734           e->e_rawsize = sz;
2735 
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)
2740 
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];
2745 
2746                     error = ELF_E_NONE;
2747 
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;
2754 
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);
2760                               }
2761                     } else {
2762                               _libelf_init_elf(e, ELF_K_ELF);
2763 
2764                               e->e_byteorder = e_byteorder;
2765                               e->e_class = e_class;
2766                               e->e_version = e_version;
2767                     }
2768           }
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
2774 
2775           return (e);
2776 }
2777 
2778 /* libelf_open.c */
2779 #define   _LIBELF_INITSIZE    (64*1024)
2780 
2781 static void *
_libelf_read_special_file(int fd,size_t * fsz)2782 _libelf_read_special_file(int fd, size_t *fsz)
2783 {
2784           ssize_t readsz;
2785           size_t bufsz, datasz;
2786           unsigned char *buf, *t;
2787 
2788           datasz = 0;
2789           readsz = 0;
2790           bufsz = _LIBELF_INITSIZE;
2791           if ((buf = malloc(bufsz)) == NULL)
2792                     goto resourceerror;
2793 
2794           /*
2795            * Read data from the file descriptor till we reach EOF, or
2796            * till an error is encountered.
2797            */
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;
2805                     }
2806 
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);
2814 
2815           } while (readsz > 0);
2816 
2817           if (readsz < 0) {
2818                     LIBELF_SET_ERROR(IO, errno);
2819                     goto error;
2820           }
2821 
2822           assert(readsz == 0);
2823 
2824           /*
2825            * Free up extra buffer space.
2826            */
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;
2836                     }
2837           }
2838 
2839           *fsz = datasz;
2840           return (buf);
2841 
2842 resourceerror:
2843           LIBELF_SET_ERROR(RESOURCE, 0);
2844 error:
2845           if (buf != NULL)
2846                     free(buf);
2847           return (NULL);
2848 }
2849 
2850 static Elf *
_libelf_open_object(int fd,Elf_Cmd c,int reporterror)2851 _libelf_open_object(int fd, Elf_Cmd c, int reporterror)
2852 {
2853           Elf *e;
2854           void *m;
2855           mode_t mode;
2856           size_t fsize;
2857           struct stat sb;
2858           unsigned int flags;
2859 
2860           assert(c == ELF_C_READ || c == ELF_C_RDWR || c == ELF_C_WRITE);
2861 
2862           if (fstat(fd, &sb) < 0) {
2863                     LIBELF_SET_ERROR(IO, errno);
2864                     return (NULL);
2865           }
2866 
2867           mode = sb.st_mode;
2868           fsize = (size_t) sb.st_size;
2869 
2870           /*
2871            * Reject unsupported file types.
2872            */
2873           if (!S_ISREG(mode) && !S_ISCHR(mode) && !S_ISFIFO(mode) &&
2874               !S_ISSOCK(mode)) {
2875                     LIBELF_SET_ERROR(ARGUMENT, 0);
2876                     return (NULL);
2877           }
2878 
2879           /*
2880            * For ELF_C_WRITE mode, allocate and return a descriptor.
2881            */
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;
2890                     }
2891 
2892                     return (e);
2893           }
2894 
2895 
2896           /*
2897            * ELF_C_READ and ELF_C_RDWR mode.
2898            */
2899           m = NULL;
2900           flags = 0;
2901           if (S_ISREG(mode)) {
2902 
2903                     /*
2904                      * Reject zero length files.
2905                      */
2906                     if (fsize == 0) {
2907                               LIBELF_SET_ERROR(ARGUMENT, 0);
2908                               return (NULL);
2909                     }
2910 
2911 #if       ELFTC_HAVE_MMAP
2912                     /*
2913                      * Always map regular files in with 'PROT_READ'
2914                      * permissions.
2915                      *
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.
2920                      */
2921                     m = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, (off_t) 0);
2922 
2923                     if (m == MAP_FAILED)
2924                               m = NULL;
2925                     else
2926                               flags = LIBELF_F_RAWFILE_MMAP;
2927 #endif
2928 
2929                     /*
2930                      * Fallback to a read() if the call to mmap() failed,
2931                      * or if mmap() is not available.
2932                      */
2933                     if (m == NULL) {
2934                               if ((m = malloc(fsize)) == NULL) {
2935                                         LIBELF_SET_ERROR(RESOURCE, 0);
2936                                         return (NULL);
2937                               }
2938 
2939                               if (read(fd, m, fsize) != (ssize_t) fsize) {
2940                                         LIBELF_SET_ERROR(IO, errno);
2941                                         free(m);
2942                                         return (NULL);
2943                               }
2944 
2945                               flags = LIBELF_F_RAWFILE_MALLOC;
2946                     }
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);
2951 
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);
2962           }
2963 
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);
2970           }
2971 #endif
2972 
2973           e->e_flags |= flags;
2974           e->e_fd = fd;
2975           e->e_cmd = c;
2976 
2977           return (e);
2978 }
2979 
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
2999 };
3000 
3001 /* PUBLIC */
3002 
3003 /* elf_errmsg.c */
3004 static const char *
elf_errmsg(int error)3005 elf_errmsg(int error)
3006 {
3007           int oserr;
3008 
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);
3014 
3015           oserr = error >> LIBELF_OS_ERROR_SHIFT;
3016           error &= LIBELF_ELF_ERROR_MASK;
3017 
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);
3025           }
3026           return _libelf_errors[error];
3027 }
3028 
3029 /* elf_errno.c */
3030 static int
elf_errno(void)3031 elf_errno(void)
3032 {
3033           int old;
3034 
3035           old = LIBELF_PRIVATE(error);
3036           LIBELF_PRIVATE(error) = 0;
3037           return (old & LIBELF_ELF_ERROR_MASK);
3038 }
3039 
3040 /* elf_version.c */
3041 static unsigned int
elf_version(unsigned int v)3042 elf_version(unsigned int v)
3043 {
3044           unsigned int old;
3045 
3046           if ((old = LIBELF_PRIVATE(version)) == EV_NONE)
3047                     old = EV_CURRENT;
3048 
3049           if (v == EV_NONE)
3050                     return old;
3051           if (v > EV_CURRENT) {
3052                     LIBELF_SET_ERROR(VERSION, 0);
3053                     return EV_NONE;
3054           }
3055 
3056           LIBELF_PRIVATE(version) = v;
3057           return (old);
3058 }
3059 
3060 /* elf_begin.c */
3061 static Elf *
elf_begin(int fd,Elf_Cmd c,Elf * a)3062 elf_begin(int fd, Elf_Cmd c, Elf *a)
3063 {
3064           Elf *e;
3065 
3066           e = NULL;
3067 
3068           if (LIBELF_PRIVATE(version) == EV_NONE) {
3069                     LIBELF_SET_ERROR(SEQUENCE, 0);
3070                     return (NULL);
3071           }
3072 
3073           switch (c) {
3074           case ELF_C_NULL:
3075                     return (NULL);
3076 
3077           case ELF_C_WRITE:
3078                     /*
3079                      * The ELF_C_WRITE command is required to ignore the
3080                      * descriptor passed in.
3081                      */
3082                     a = NULL;
3083                     break;
3084 
3085           case ELF_C_RDWR:
3086                     if (a != NULL) { /* not allowed for ar(1) archives. */
3087                               LIBELF_SET_ERROR(ARGUMENT, 0);
3088                               return (NULL);
3089                     }
3090                     /*FALLTHROUGH*/
3091           case ELF_C_READ:
3092                     /*
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.
3097                      */
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);
3102                     }
3103                     break;
3104 
3105           default:
3106                     LIBELF_SET_ERROR(ARGUMENT, 0);
3107                     return (NULL);
3108 
3109           }
3110 
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++;
3119 
3120           return (e);
3121 }
3122 
3123 /* elf_end.c */
3124 static int
elf_end(Elf * e)3125 elf_end(Elf *e)
3126 {
3127           Elf *sv;
3128           Elf_Scn *scn, *tscn;
3129 
3130           if (e == NULL || e->e_activations == 0)
3131                     return (0);
3132 
3133           if (--e->e_activations > 0)
3134                     return (e->e_activations);
3135 
3136           assert(e->e_activations == 0);
3137 
3138           while (e && e->e_activations == 0) {
3139                     switch (e->e_kind) {
3140                     case ELF_K_AR:
3141                               /*
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.
3146                                */
3147                               if (e->e_u.e_ar.e_nchildren > 0)
3148                                         return (0);
3149                               break;
3150                     case ELF_K_ELF:
3151                               /*
3152                                * Reclaim all section descriptors.
3153                                */
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;
3162                     }
3163 
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
3171                     }
3172 
3173                     sv = e;
3174                     if ((e = e->e_parent) != NULL)
3175                               e->e_u.e_ar.e_nchildren--;
3176                     sv = _libelf_release_elf(sv);
3177           }
3178 
3179           return (0);
3180 }
3181 
3182 /* gelf_shdr.c */
3183 static GElf_Shdr *
gelf_getshdr(Elf_Scn * s,GElf_Shdr * d)3184 gelf_getshdr(Elf_Scn *s, GElf_Shdr *d)
3185 {
3186           int ec;
3187           void *sh;
3188 #if 0
3189           Elf32_Shdr *sh32;
3190 #endif
3191           Elf64_Shdr *sh64;
3192 
3193           if (d == NULL) {
3194                     LIBELF_SET_ERROR(ARGUMENT, 0);
3195                     return (NULL);
3196           }
3197 
3198           if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL)
3199                     return (NULL);
3200 
3201           ec = s->s_elf->e_class;
3202           assert(/* ec == ELFCLASS32 || */ ec == ELFCLASS64);
3203 
3204 #if 0
3205           if (ec == ELFCLASS32) {
3206                     sh32 = (Elf32_Shdr *) sh;
3207 
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
3220           {
3221                     sh64 = (Elf64_Shdr *) sh;
3222                     *d = *sh64;
3223           }
3224 
3225           return (d);
3226 }
3227 
3228 /* gelf_sym.c */
3229 static GElf_Sym *
gelf_getsym(Elf_Data * ed,int ndx,GElf_Sym * dst)3230 gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst)
3231 {
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;
3242 
3243           d = (struct _Libelf_Data *) ed;
3244 
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);
3250           }
3251 
3252           ec = e->e_class;
3253           assert(/* ec == ELFCLASS32 || */ ec == ELFCLASS64);
3254 
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;
3261 
3262           if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
3263                     LIBELF_SET_ERROR(ARGUMENT, 0);
3264                     return (NULL);
3265           }
3266 
3267           msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);
3268 
3269           assert(msz > 0);
3270           assert(ndx >= 0);
3271 
3272           if (msz * (size_t) ndx >= d->d_data.d_size) {
3273                     LIBELF_SET_ERROR(ARGUMENT, 0);
3274                     return (NULL);
3275           }
3276 
3277 #if 0
3278           if (ec == ELFCLASS32) {
3279                     sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx;
3280 
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
3289           {
3290                     sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx;
3291 
3292                     *dst = *sym64;
3293           }
3294 
3295           return (dst);
3296 }
3297 
3298 /* elf_scn.c */
3299 static Elf_Scn *
elf_nextscn(Elf * e,Elf_Scn * s)3300 elf_nextscn(Elf *e, Elf_Scn *s)
3301 {
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);
3306           }
3307 
3308           return (s == NULL ? elf_getscn(e, (size_t) 1) :
3309               STAILQ_NEXT(s, s_next));
3310 }
3311 
3312 /* elf_strptr.c */
3313 static char *
elf_strptr(Elf * e,size_t scndx,size_t offset)3314 elf_strptr(Elf *e, size_t scndx, size_t offset)
3315 {
3316           Elf_Scn *s;
3317           Elf_Data *d;
3318           GElf_Shdr shdr;
3319           uint64_t alignment, count;
3320 
3321           if (e == NULL || e->e_kind != ELF_K_ELF) {
3322                     LIBELF_SET_ERROR(ARGUMENT, 0);
3323                     return (NULL);
3324           }
3325 
3326           if ((s = elf_getscn(e, scndx)) == NULL ||
3327               gelf_getshdr(s, &shdr) == NULL)
3328                     return (NULL);
3329 
3330           if (shdr.sh_type != SHT_STRTAB ||
3331               offset >= shdr.sh_size) {
3332                     LIBELF_SET_ERROR(ARGUMENT, 0);
3333                     return (NULL);
3334           }
3335 
3336           d = NULL;
3337           if (e->e_flags & ELF_F_LAYOUT) {
3338 
3339                     /*
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.
3344                      */
3345                     while ((d = elf_getdata(s, d)) != NULL) {
3346 
3347                               if (d->d_buf == 0 || d->d_size == 0)
3348                                         continue;
3349 
3350                               if (d->d_type != ELF_T_BYTE) {
3351                                         LIBELF_SET_ERROR(DATA, 0);
3352                                         return (NULL);
3353                               }
3354 
3355                               if (offset >= d->d_off &&
3356                                   offset < d->d_off + d->d_size)
3357                                         return ((char *) d->d_buf + offset - d->d_off);
3358                     }
3359           } else {
3360                     /*
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.
3365                      */
3366                     count = (uint64_t) 0;         /* cumulative count of bytes seen */
3367                     while ((d = elf_getdata(s, d)) != NULL && count <= offset) {
3368 
3369                               if (d->d_buf == NULL || d->d_size == 0)
3370                                         continue;
3371 
3372                               if (d->d_type != ELF_T_BYTE) {
3373                                         LIBELF_SET_ERROR(DATA, 0);
3374                                         return (NULL);
3375                               }
3376 
3377                               if ((alignment = d->d_align) > 1) {
3378                                         if ((alignment & (alignment - 1)) != 0) {
3379                                                   LIBELF_SET_ERROR(DATA, 0);
3380                                                   return (NULL);
3381                                         }
3382                                         count = roundup2(count, alignment);
3383                               }
3384 
3385                               if (offset < count) {
3386                                         /* offset starts in the 'hole' */
3387                                         LIBELF_SET_ERROR(ARGUMENT, 0);
3388                                         return (NULL);
3389                               }
3390 
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);
3397                               }
3398 
3399                               count += d->d_size;
3400                     }
3401           }
3402 
3403           LIBELF_SET_ERROR(ARGUMENT, 0);
3404           return (NULL);
3405 }
3406 
3407 /* elf_data.c */
3408 static Elf_Data *
elf_getdata(Elf_Scn * s,Elf_Data * ed)3409 elf_getdata(Elf_Scn *s, Elf_Data *ed)
3410 {
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);
3419 
3420           d = (struct _Libelf_Data *) ed;
3421 
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);
3426           }
3427 
3428           assert(e->e_kind == ELF_K_ELF);
3429 
3430           if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)
3431                     return (&d->d_data);
3432 
3433           if (d != NULL)
3434                     return (&STAILQ_NEXT(d, d_next)->d_data);
3435 
3436           if (e->e_rawfile == NULL) {
3437                     /*
3438                      * In the ELF_C_WRITE case, there is no source that
3439                      * can provide data for the section.
3440                      */
3441                     LIBELF_SET_ERROR(ARGUMENT, 0);
3442                     return (NULL);
3443           }
3444 
3445           elfclass = e->e_class;
3446 
3447           assert(/* elfclass == ELFCLASS32 || */ elfclass == ELFCLASS64);
3448 
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
3457           {
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;
3462           }
3463 
3464           if (sh_type == SHT_NULL) {
3465                     LIBELF_SET_ERROR(SECTION, 0);
3466                     return (NULL);
3467           }
3468 
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);
3474           }
3475 
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);
3480           }
3481 
3482           if (sh_size % fsz) {
3483                     LIBELF_SET_ERROR(SECTION, 0);
3484                     return (NULL);
3485           }
3486 
3487           if (sh_size / fsz > SIZE_MAX) {
3488                     LIBELF_SET_ERROR(RANGE, 0);
3489                     return (NULL);
3490           }
3491 
3492           count = (size_t) (sh_size / fsz);
3493 
3494           msz = _libelf_msize(elftype, elfclass, e->e_version);
3495 
3496           if (count > 0 && msz > SIZE_MAX / count) {
3497                     LIBELF_SET_ERROR(RANGE, 0);
3498                     return (NULL);
3499           }
3500 
3501           assert(msz > 0);
3502           assert(count <= SIZE_MAX);
3503           assert(msz * count <= SIZE_MAX);
3504 
3505           if ((d = _libelf_allocate_data(s)) == NULL)
3506                     return (NULL);
3507 
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;
3514 
3515           if (sh_type == SHT_NOBITS || sh_size == 0) {
3516                   STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
3517                     return (&d->d_data);
3518         }
3519 
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);
3524           }
3525 
3526           d->d_flags  |= LIBELF_F_DATA_MALLOCED;
3527 
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);
3535           }
3536 
3537           STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
3538 
3539           return (&d->d_data);
3540 }
3541 
3542 #endif /* !_PRIVATE_LIBELF_H_ */
3543