libexecinfo(3): Internalize libelf in symtab.c.
authorzrj <rimvydas.jasinskas@gmail.com>
Fri, 20 Dec 2019 09:21:44 +0000 (11:21 +0200)
committerzrj <rimvydas.jasinskas@gmail.com>
Sun, 22 Dec 2019 02:54:31 +0000 (04:54 +0200)
 Previous variant had symbol conflicts against ports libelf library.
 Use custom, cut down variant that provides basic set needed for
 libexecinfo symtab.c, ensure symbols are static and mangled.
 The libelf (as provided in contrib) is not very suitable for generic
 implementation of backtrace(3) function family.

 This is a temporary workaround to unbreak specific ports that are link
 against libelf and libexecinfo (including static compilations).

Reported-by: Romick@users
lib/libexecinfo/Makefile
lib/libexecinfo/private_libelf.h [new file with mode: 0644]
lib/libexecinfo/symtab.c

index 53f88e0..d10e36c 100644 (file)
@@ -12,6 +12,7 @@ MLINKS+=      backtrace.3 backtrace_symbols_fmt.3
 MLINKS+=       backtrace.3 backtrace_symbols_fd.3
 MLINKS+=       backtrace.3 backtrace_symbols_fd_fmt.3
 
+.if 0
 CONLIBS=       ${.OBJDIR}/../libelf/libelf.a
 DPADD=         ${CONLIBS:.a=_pic.a}
 LDADD=         ${CONLIBS:.a=_pic.a}
@@ -58,5 +59,6 @@ script_p.ar:
 GENFILES=      script.ar script_p.ar
 CLEANFILES=    ${GENFILES}
 beforedepend:  ${GENFILES}
+.endif
 
 .include <bsd.lib.mk>
diff --git a/lib/libexecinfo/private_libelf.h b/lib/libexecinfo/private_libelf.h
new file mode 100644 (file)
index 0000000..10b4e56
--- /dev/null
@@ -0,0 +1,3542 @@
+/*-
+ * Copyright (c) 2006,2008-2010 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PRIVATE_LIBELF_H_
+#define        _PRIVATE_LIBELF_H_
+
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/queue.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+
+/* _libelf_config.h */
+#if defined(__DragonFly__)
+#define        LIBELF_ARCH             EM_X86_64
+#define        LIBELF_BYTEORDER        ELFDATA2LSB
+#define        LIBELF_CLASS            ELFCLASS64
+#endif /* __DragonFly__ */
+
+/* _elftc.h */
+#if defined(__DragonFly__)
+#define        ELFTC_BYTE_ORDER                        _BYTE_ORDER
+#define        ELFTC_BYTE_ORDER_LITTLE_ENDIAN          _LITTLE_ENDIAN
+#define        ELFTC_BYTE_ORDER_BIG_ENDIAN             _BIG_ENDIAN
+#define        ELFTC_HAVE_MMAP                         1
+#define        STAILQ_FOREACH_SAFE                     STAILQ_FOREACH_MUTABLE
+#endif
+
+#if 1
+#define        _libelf_allocate_data           __ei_libelf_allocate_data
+#define        _libelf_allocate_elf            __ei_libelf_allocate_elf
+#define        _libelf_allocate_scn            __ei_libelf_allocate_scn
+#define        _libelf_cvt_ADDR64_tom          __ei_libelf_cvt_ADDR64_tom
+#define        _libelf_cvt_BYTE_tox            __ei_libelf_cvt_BYTE_tox
+#define        _libelf_cvt_CAP64_tom           __ei_libelf_cvt_CAP64_tom
+#define        _libelf_cvt_DYN64_tom           __ei_libelf_cvt_DYN64_tom
+#define        _libelf_cvt_EHDR64_tom          __ei_libelf_cvt_EHDR64_tom
+#define        _libelf_cvt_GNUHASH64_tom       __ei_libelf_cvt_GNUHASH64_tom
+#define        _libelf_cvt_HALF_tom            __ei_libelf_cvt_HALF_tom
+#define        _libelf_cvt_LWORD_tom           __ei_libelf_cvt_LWORD_tom
+#define        _libelf_cvt_MOVE64_tom          __ei_libelf_cvt_MOVE64_tom
+#define        _libelf_cvt_NOTE_tom            __ei_libelf_cvt_NOTE_tom
+#define        _libelf_cvt_OFF64_tom           __ei_libelf_cvt_OFF64_tom
+#define        _libelf_cvt_PHDR64_tom          __ei_libelf_cvt_PHDR64_tom
+#define        _libelf_cvt_REL64_tom           __ei_libelf_cvt_REL64_tom
+#define        _libelf_cvt_RELA64_tom          __ei_libelf_cvt_RELA64_tom
+#define        _libelf_cvt_SHDR64_tom          __ei_libelf_cvt_SHDR64_tom
+#define        _libelf_cvt_SWORD_tom           __ei_libelf_cvt_SWORD_tom
+#define        _libelf_cvt_SXWORD_tom          __ei_libelf_cvt_SXWORD_tom
+#define        _libelf_cvt_SYM64_tom           __ei_libelf_cvt_SYM64_tom
+#define        _libelf_cvt_SYMINFO64_tom       __ei_libelf_cvt_SYMINFO64_tom
+#define        _libelf_cvt_VDEF64_tom          __ei_libelf_cvt_VDEF64_tom
+#define        _libelf_cvt_VNEED64_tom         __ei_libelf_cvt_VNEED64_tom
+#define        _libelf_cvt_WORD_tom            __ei_libelf_cvt_WORD_tom
+#define        _libelf_cvt_XWORD_tom           __ei_libelf_cvt_XWORD_tom
+#define        _libelf_ehdr                    __ei_libelf_ehdr
+#define        _libelf_fsize                   __ei_libelf_fsize
+#define        _libelf_get_translator          __ei_libelf_get_translator
+#define        _libelf_getshdr                 __ei_libelf_getshdr
+#define        _libelf_init_elf                __ei_libelf_init_elf
+#define        _libelf_load_extended           __ei_libelf_load_extended
+#define        _libelf_load_section_headers    __ei_libelf_load_section_headers
+#define        _libelf_memory                  __ei_libelf_memory
+#define        _libelf_msize                   __ei_libelf_msize
+#define        _libelf_open_object             __ei_libelf_open_object
+#define        _libelf_read_special_file       __ei_libelf_read_special_file
+#define        _libelf_release_data            __ei_libelf_release_data
+#define        _libelf_release_elf             __ei_libelf_release_elf
+#define        _libelf_release_scn             __ei_libelf_release_scn
+#define        _libelf_xlate_shtype            __ei_libelf_xlate_shtype
+#define        _libelf         __ei_libelf
+
+#define        elf64_fsize     __ei_elf64_fsize
+#define        elf_getscn      __ei_elf_getscn
+
+#define        elf_begin       _ei_elf_begin
+#define        elf_end         _ei_elf_end
+#define        elf_errmsg      _ei_elf_errmsg
+#define        elf_errno       _ei_elf_errno
+#define        elf_getdata     _ei_elf_getdata
+#define        elf_nextscn     _ei_elf_nextscn
+#define        elf_strptr      _ei_elf_strptr
+#define        elf_version     _ei_elf_version
+#define        gelf_getshdr    _ei_gelf_getshdr
+#define        gelf_getsym     _ei_gelf_getsym
+#endif
+
+/* elfdefinitions.h */
+/*
+ * Offsets in the `ei_ident[]` field of an ELF executable header.
+ */
+#define        _ELF_DEFINE_EI_OFFSETS()                        \
+_ELF_DEFINE_EI(EI_MAG0,     0, "magic number")         \
+_ELF_DEFINE_EI(EI_MAG1,     1, "magic number")         \
+_ELF_DEFINE_EI(EI_MAG2,     2, "magic number")         \
+_ELF_DEFINE_EI(EI_MAG3,     3, "magic number")         \
+_ELF_DEFINE_EI(EI_CLASS,    4, "file class")           \
+_ELF_DEFINE_EI(EI_DATA,     5, "data encoding")                \
+_ELF_DEFINE_EI(EI_VERSION,  6, "file version")         \
+_ELF_DEFINE_EI(EI_OSABI,    7, "OS ABI kind")          \
+_ELF_DEFINE_EI(EI_ABIVERSION, 8, "OS ABI version")     \
+_ELF_DEFINE_EI(EI_PAD,     9, "padding start")         \
+_ELF_DEFINE_EI(EI_NIDENT,  16, "total size")
+
+#undef _ELF_DEFINE_EI
+#define        _ELF_DEFINE_EI(N, V, DESCR)     N = V ,
+enum {
+       _ELF_DEFINE_EI_OFFSETS()
+       EI__LAST__
+};
+
+/*
+ * The ELF class of an object.
+ */
+#define        _ELF_DEFINE_ELFCLASS()                          \
+_ELF_DEFINE_EC(ELFCLASSNONE, 0, "Unknown ELF class")   \
+_ELF_DEFINE_EC(ELFCLASS32,   1, "32 bit objects")      \
+_ELF_DEFINE_EC(ELFCLASS64,   2, "64 bit objects")
+
+#undef _ELF_DEFINE_EC
+#define        _ELF_DEFINE_EC(N, V, DESCR)     N = V ,
+enum {
+       _ELF_DEFINE_ELFCLASS()
+       EC__LAST__
+};
+
+/*
+ * Endianness of data in an ELF object.
+ */
+
+#define        _ELF_DEFINE_ELF_DATA_ENDIANNESS()                       \
+_ELF_DEFINE_ED(ELFDATANONE, 0, "Unknown data endianness")      \
+_ELF_DEFINE_ED(ELFDATA2LSB, 1, "little endian")                        \
+_ELF_DEFINE_ED(ELFDATA2MSB, 2, "big endian")
+
+#undef _ELF_DEFINE_ED
+#define        _ELF_DEFINE_ED(N, V, DESCR)     N = V ,
+enum {
+       _ELF_DEFINE_ELF_DATA_ENDIANNESS()
+       ED__LAST__
+};
+
+/*
+ * Values of the magic numbers used in identification array.
+ */
+#define        _ELF_DEFINE_ELF_MAGIC()                 \
+_ELF_DEFINE_EMAG(ELFMAG0, 0x7FU)               \
+_ELF_DEFINE_EMAG(ELFMAG1, 'E')                 \
+_ELF_DEFINE_EMAG(ELFMAG2, 'L')                 \
+_ELF_DEFINE_EMAG(ELFMAG3, 'F')
+
+#undef _ELF_DEFINE_EMAG
+#define        _ELF_DEFINE_EMAG(N, V)          N = V ,
+enum {
+       _ELF_DEFINE_ELF_MAGIC()
+       ELFMAG__LAST__
+};
+
+/*
+ * ELF Machine types: (EM_*).
+ */
+#define        _ELF_DEFINE_ELF_MACHINES()                                      \
+_ELF_DEFINE_EM(EM_NONE,             0, "No machine")                   \
+_ELF_DEFINE_EM(EM_386,              3, "Intel 80386")                  \
+_ELF_DEFINE_EM(EM_X86_64,           62, "AMD x86-64 architecture")
+
+#undef _ELF_DEFINE_EM
+#define        _ELF_DEFINE_EM(N, V, DESCR)     N = V ,
+enum {
+       _ELF_DEFINE_ELF_MACHINES()
+       EM__LAST__
+};
+
+/* ELF file format version numbers. */
+#define        EV_NONE         0
+#define        EV_CURRENT      1
+
+/*
+ * Special section indices.
+ */
+#define _ELF_DEFINE_SECTION_INDICES()                                  \
+_ELF_DEFINE_SHN(SHN_UNDEF,     0,       "undefined section")           \
+_ELF_DEFINE_SHN(SHN_LORESERVE, 0xFF00U, "start of reserved area")      \
+_ELF_DEFINE_SHN(SHN_LOPROC,    0xFF00U,                                \
+       "start of processor-specific range")                            \
+_ELF_DEFINE_SHN(SHN_BEFORE,    0xFF00U, "used for section ordering")   \
+_ELF_DEFINE_SHN(SHN_AFTER,     0xFF01U, "used for section ordering")   \
+_ELF_DEFINE_SHN(SHN_AMD64_LCOMMON, 0xFF02U, "large common block label") \
+_ELF_DEFINE_SHN(SHN_MIPS_ACOMMON, 0xFF00U,                             \
+       "allocated common symbols in a DSO")                            \
+_ELF_DEFINE_SHN(SHN_MIPS_TEXT, 0xFF01U, "Reserved (obsolete)")         \
+_ELF_DEFINE_SHN(SHN_MIPS_DATA, 0xFF02U, "Reserved (obsolete)")         \
+_ELF_DEFINE_SHN(SHN_MIPS_SCOMMON, 0xFF03U,                             \
+       "gp-addressable common symbols")                                \
+_ELF_DEFINE_SHN(SHN_MIPS_SUNDEFINED, 0xFF04U,                          \
+       "gp-addressable undefined symbols")                             \
+_ELF_DEFINE_SHN(SHN_MIPS_LCOMMON, 0xFF05U, "local common symbols")     \
+_ELF_DEFINE_SHN(SHN_MIPS_LUNDEFINED, 0xFF06U,                          \
+       "local undefined symbols")                                      \
+_ELF_DEFINE_SHN(SHN_HIPROC,    0xFF1FU,                                \
+       "end of processor-specific range")                              \
+_ELF_DEFINE_SHN(SHN_LOOS,      0xFF20U,                                \
+       "start of OS-specific range")                                   \
+_ELF_DEFINE_SHN(SHN_SUNW_IGNORE, 0xFF3FU, "used by dtrace")            \
+_ELF_DEFINE_SHN(SHN_HIOS,      0xFF3FU,                                \
+       "end of OS-specific range")                                     \
+_ELF_DEFINE_SHN(SHN_ABS,       0xFFF1U, "absolute references")         \
+_ELF_DEFINE_SHN(SHN_COMMON,    0xFFF2U, "references to COMMON areas")  \
+_ELF_DEFINE_SHN(SHN_XINDEX,    0xFFFFU, "extended index")              \
+_ELF_DEFINE_SHN(SHN_HIRESERVE, 0xFFFFU, "end of reserved area")
+
+#undef _ELF_DEFINE_SHN
+#define        _ELF_DEFINE_SHN(N, V, DESCR)    N = V ,
+enum {
+       _ELF_DEFINE_SECTION_INDICES()
+       SHN__LAST__
+};
+
+/*
+ * Section types.
+ */
+
+#define        _ELF_DEFINE_SECTION_TYPES()                                     \
+_ELF_DEFINE_SHT(SHT_NULL,            0, "inactive header")             \
+_ELF_DEFINE_SHT(SHT_PROGBITS,        1, "program defined information") \
+_ELF_DEFINE_SHT(SHT_SYMTAB,          2, "symbol table")                        \
+_ELF_DEFINE_SHT(SHT_STRTAB,          3, "string table")                        \
+_ELF_DEFINE_SHT(SHT_RELA,            4,                                        \
+       "relocation entries with addends")                              \
+_ELF_DEFINE_SHT(SHT_HASH,            5, "symbol hash table")           \
+_ELF_DEFINE_SHT(SHT_DYNAMIC,         6,                                        \
+       "information for dynamic linking")                              \
+_ELF_DEFINE_SHT(SHT_NOTE,            7, "additional notes")            \
+_ELF_DEFINE_SHT(SHT_NOBITS,          8, "section occupying no space")  \
+_ELF_DEFINE_SHT(SHT_REL,             9,                                        \
+       "relocation entries without addends")                           \
+_ELF_DEFINE_SHT(SHT_SHLIB,           10, "reserved")                   \
+_ELF_DEFINE_SHT(SHT_DYNSYM,          11, "symbol table")               \
+_ELF_DEFINE_SHT(SHT_INIT_ARRAY,      14,                               \
+       "pointers to initialization functions")                         \
+_ELF_DEFINE_SHT(SHT_FINI_ARRAY,      15,                               \
+       "pointers to termination functions")                            \
+_ELF_DEFINE_SHT(SHT_PREINIT_ARRAY,   16,                               \
+       "pointers to functions called before initialization")           \
+_ELF_DEFINE_SHT(SHT_GROUP,           17, "defines a section group")    \
+_ELF_DEFINE_SHT(SHT_SYMTAB_SHNDX,    18,                               \
+       "used for extended section numbering")                          \
+_ELF_DEFINE_SHT(SHT_LOOS,            0x60000000UL,                     \
+       "start of OS-specific range")                                   \
+_ELF_DEFINE_SHT(SHT_SUNW_dof,       0x6FFFFFF4UL,                      \
+       "used by dtrace")                                               \
+_ELF_DEFINE_SHT(SHT_SUNW_cap,       0x6FFFFFF5UL,                      \
+       "capability requirements")                                      \
+_ELF_DEFINE_SHT(SHT_GNU_ATTRIBUTES,  0x6FFFFFF5UL,                     \
+       "object attributes")                                            \
+_ELF_DEFINE_SHT(SHT_SUNW_SIGNATURE,  0x6FFFFFF6UL,                     \
+       "module verification signature")                                \
+_ELF_DEFINE_SHT(SHT_GNU_HASH,       0x6FFFFFF6UL,                      \
+       "GNU Hash sections")                                            \
+_ELF_DEFINE_SHT(SHT_GNU_LIBLIST,     0x6FFFFFF7UL,                     \
+       "List of libraries to be prelinked")                            \
+_ELF_DEFINE_SHT(SHT_SUNW_ANNOTATE,   0x6FFFFFF7UL,                     \
+       "special section where unresolved references are allowed")      \
+_ELF_DEFINE_SHT(SHT_SUNW_DEBUGSTR,   0x6FFFFFF8UL,                     \
+       "debugging information")                                        \
+_ELF_DEFINE_SHT(SHT_CHECKSUM,       0x6FFFFFF8UL,                      \
+       "checksum for dynamic shared objects")                          \
+_ELF_DEFINE_SHT(SHT_SUNW_DEBUG,      0x6FFFFFF9UL,                     \
+       "debugging information")                                        \
+_ELF_DEFINE_SHT(SHT_SUNW_move,       0x6FFFFFFAUL,                     \
+       "information to handle partially initialized symbols")          \
+_ELF_DEFINE_SHT(SHT_SUNW_COMDAT,     0x6FFFFFFBUL,                     \
+       "section supporting merging of multiple copies of data")        \
+_ELF_DEFINE_SHT(SHT_SUNW_syminfo,    0x6FFFFFFCUL,                     \
+       "additional symbol information")                                \
+_ELF_DEFINE_SHT(SHT_SUNW_verdef,     0x6FFFFFFDUL,                     \
+       "symbol versioning information")                                \
+_ELF_DEFINE_SHT(SHT_SUNW_verneed,    0x6FFFFFFEUL,                     \
+       "symbol versioning requirements")                               \
+_ELF_DEFINE_SHT(SHT_SUNW_versym,     0x6FFFFFFFUL,                     \
+       "symbol versioning table")                                      \
+_ELF_DEFINE_SHT(SHT_HIOS,            0x6FFFFFFFUL,                     \
+       "end of OS-specific range")                                     \
+_ELF_DEFINE_SHT(SHT_LOPROC,          0x70000000UL,                     \
+       "start of processor-specific range")                            \
+_ELF_DEFINE_SHT(SHT_ARM_EXIDX,       0x70000001UL,                     \
+       "exception index table")                                        \
+_ELF_DEFINE_SHT(SHT_ARM_PREEMPTMAP,  0x70000002UL,                     \
+       "BPABI DLL dynamic linking preemption map")                     \
+_ELF_DEFINE_SHT(SHT_ARM_ATTRIBUTES,  0x70000003UL,                     \
+       "object file compatibility attributes")                         \
+_ELF_DEFINE_SHT(SHT_ARM_DEBUGOVERLAY, 0x70000004UL,                    \
+       "overlay debug information")                                    \
+_ELF_DEFINE_SHT(SHT_ARM_OVERLAYSECTION, 0x70000005UL,                  \
+       "overlay debug information")                                    \
+_ELF_DEFINE_SHT(SHT_MIPS_LIBLIST,    0x70000000UL,                     \
+       "DSO library information used in link")                         \
+_ELF_DEFINE_SHT(SHT_MIPS_MSYM,       0x70000001UL,                     \
+       "MIPS symbol table extension")                                  \
+_ELF_DEFINE_SHT(SHT_MIPS_CONFLICT,   0x70000002UL,                     \
+       "symbol conflicting with DSO-defined symbols ")                 \
+_ELF_DEFINE_SHT(SHT_MIPS_GPTAB,      0x70000003UL,                     \
+       "global pointer table")                                         \
+_ELF_DEFINE_SHT(SHT_MIPS_UCODE,      0x70000004UL,                     \
+       "reserved")                                                     \
+_ELF_DEFINE_SHT(SHT_MIPS_DEBUG,      0x70000005UL,                     \
+       "reserved (obsolete debug information)")                        \
+_ELF_DEFINE_SHT(SHT_MIPS_REGINFO,    0x70000006UL,                     \
+       "register usage information")                                   \
+_ELF_DEFINE_SHT(SHT_MIPS_PACKAGE,    0x70000007UL,                     \
+       "OSF reserved")                                                 \
+_ELF_DEFINE_SHT(SHT_MIPS_PACKSYM,    0x70000008UL,                     \
+       "OSF reserved")                                                 \
+_ELF_DEFINE_SHT(SHT_MIPS_RELD,       0x70000009UL,                     \
+       "dynamic relocation")                                           \
+_ELF_DEFINE_SHT(SHT_MIPS_IFACE,      0x7000000BUL,                     \
+       "subprogram interface information")                             \
+_ELF_DEFINE_SHT(SHT_MIPS_CONTENT,    0x7000000CUL,                     \
+       "section content classification")                               \
+_ELF_DEFINE_SHT(SHT_MIPS_OPTIONS,     0x7000000DUL,                    \
+       "general options")                                              \
+_ELF_DEFINE_SHT(SHT_MIPS_DELTASYM,   0x7000001BUL,                     \
+       "Delta C++: symbol table")                                      \
+_ELF_DEFINE_SHT(SHT_MIPS_DELTAINST,  0x7000001CUL,                     \
+       "Delta C++: instance table")                                    \
+_ELF_DEFINE_SHT(SHT_MIPS_DELTACLASS, 0x7000001DUL,                     \
+       "Delta C++: class table")                                       \
+_ELF_DEFINE_SHT(SHT_MIPS_DWARF,      0x7000001EUL,                     \
+       "DWARF debug information")                                      \
+_ELF_DEFINE_SHT(SHT_MIPS_DELTADECL,  0x7000001FUL,                     \
+       "Delta C++: declarations")                                      \
+_ELF_DEFINE_SHT(SHT_MIPS_SYMBOL_LIB, 0x70000020UL,                     \
+       "symbol-to-library mapping")                                    \
+_ELF_DEFINE_SHT(SHT_MIPS_EVENTS,     0x70000021UL,                     \
+       "event locations")                                              \
+_ELF_DEFINE_SHT(SHT_MIPS_TRANSLATE,  0x70000022UL,                     \
+       "???")                                                          \
+_ELF_DEFINE_SHT(SHT_MIPS_PIXIE,      0x70000023UL,                     \
+       "special pixie sections")                                       \
+_ELF_DEFINE_SHT(SHT_MIPS_XLATE,      0x70000024UL,                     \
+       "address translation table")                                    \
+_ELF_DEFINE_SHT(SHT_MIPS_XLATE_DEBUG, 0x70000025UL,                    \
+       "SGI internal address translation table")                       \
+_ELF_DEFINE_SHT(SHT_MIPS_WHIRL,      0x70000026UL,                     \
+       "intermediate code")                                            \
+_ELF_DEFINE_SHT(SHT_MIPS_EH_REGION,  0x70000027UL,                     \
+       "C++ exception handling region info")                           \
+_ELF_DEFINE_SHT(SHT_MIPS_XLATE_OLD,  0x70000028UL,                     \
+       "obsolete")                                                     \
+_ELF_DEFINE_SHT(SHT_MIPS_PDR_EXCEPTION, 0x70000029UL,                  \
+       "runtime procedure descriptor table exception information")     \
+_ELF_DEFINE_SHT(SHT_MIPS_ABIFLAGS,   0x7000002AUL,                     \
+       "ABI flags")                                                    \
+_ELF_DEFINE_SHT(SHT_SPARC_GOTDATA,   0x70000000UL,                     \
+       "SPARC-specific data")                                          \
+_ELF_DEFINE_SHT(SHT_AMD64_UNWIND,    0x70000001UL,                     \
+       "unwind tables for the AMD64")                                  \
+_ELF_DEFINE_SHT(SHT_ORDERED,         0x7FFFFFFFUL,                     \
+       "sort entries in the section")                                  \
+_ELF_DEFINE_SHT(SHT_HIPROC,          0x7FFFFFFFUL,                     \
+       "end of processor-specific range")                              \
+_ELF_DEFINE_SHT(SHT_LOUSER,          0x80000000UL,                     \
+       "start of application-specific range")                          \
+_ELF_DEFINE_SHT(SHT_HIUSER,          0xFFFFFFFFUL,                     \
+       "end of application-specific range")
+
+#undef _ELF_DEFINE_SHT
+#define        _ELF_DEFINE_SHT(N, V, DESCR)    N = V ,
+enum {
+       _ELF_DEFINE_SECTION_TYPES()
+       SHT__LAST__ = SHT_HIUSER
+};
+
+#define        PN_XNUM                 0xFFFFU /* Use extended section numbering. */
+
+/**
+ ** ELF Types.
+ **/
+
+typedef uint64_t       Elf64_Addr;     /* Program address. */
+typedef uint16_t       Elf64_Half;     /* Unsigned medium integer. */
+typedef uint64_t       Elf64_Off;      /* File offset. */
+typedef int32_t                Elf64_Sword;    /* Signed integer. */
+typedef uint32_t       Elf64_Word;     /* Unsigned integer. */
+typedef uint64_t       Elf64_Lword;    /* Unsigned long integer. */
+typedef uint64_t       Elf64_Xword;    /* Unsigned long integer. */
+typedef int64_t                Elf64_Sxword;   /* Signed long integer. */
+
+/*
+ * Capability descriptors.
+ */
+typedef struct {
+       Elf64_Xword     c_tag;       /* Type of entry. */
+       union {
+               Elf64_Xword     c_val; /* Integer value. */
+               Elf64_Addr      c_ptr; /* Pointer value. */
+       } c_un;
+} Elf64_Cap;
+
+/*
+ * Dynamic section entries.
+ */
+typedef struct {
+       Elf64_Sxword    d_tag;       /* Type of entry. */
+       union {
+               Elf64_Xword     d_val; /* Integer value. */
+               Elf64_Addr      d_ptr; /* Pointer value; */
+       } d_un;
+} Elf64_Dyn;
+
+/*
+ * The executable header (EHDR).
+ */
+typedef struct {
+       unsigned char   e_ident[EI_NIDENT]; /* ELF identification. */
+       Elf64_Half      e_type;      /* Object file type (ET_*). */
+       Elf64_Half      e_machine;   /* Machine type (EM_*). */
+       Elf64_Word      e_version;   /* File format version (EV_*). */
+       Elf64_Addr      e_entry;     /* Start address. */
+       Elf64_Off       e_phoff;     /* File offset to the PHDR table. */
+       Elf64_Off       e_shoff;     /* File offset to the SHDRheader. */
+       Elf64_Word      e_flags;     /* Flags (EF_*). */
+       Elf64_Half      e_ehsize;    /* Elf header size in bytes. */
+       Elf64_Half      e_phentsize; /* PHDR table entry size in bytes. */
+       Elf64_Half      e_phnum;     /* Number of PHDR entries. */
+       Elf64_Half      e_shentsize; /* SHDR table entry size in bytes. */
+       Elf64_Half      e_shnum;     /* Number of SHDR entries. */
+       Elf64_Half      e_shstrndx;  /* Index of section name string table. */
+} Elf64_Ehdr;
+
+/*
+ * Note descriptors.
+ */
+
+typedef        struct {
+       uint32_t        n_namesz;    /* Length of note's name. */
+       uint32_t        n_descsz;    /* Length of note's value. */
+       uint32_t        n_type;      /* Type of note. */
+} Elf_Note;
+
+/*
+ * Program Header Table (PHDR) entries.
+ */
+typedef struct {
+       Elf64_Word      p_type;      /* Type of segment. */
+       Elf64_Word      p_flags;     /* Segment flags. */
+       Elf64_Off       p_offset;    /* File offset to segment. */
+       Elf64_Addr      p_vaddr;     /* Virtual address in memory. */
+       Elf64_Addr      p_paddr;     /* Physical address (if relevant). */
+       Elf64_Xword     p_filesz;    /* Size of segment in file. */
+       Elf64_Xword     p_memsz;     /* Size of segment in memory. */
+       Elf64_Xword     p_align;     /* Alignment constraints. */
+} Elf64_Phdr;
+
+/*
+ * Move entries, for describing data in COMMON blocks in a compact
+ * manner.
+ */
+typedef struct {
+       Elf64_Lword     m_value;     /* Initialization value. */
+       Elf64_Xword     m_info;      /* Encoded size and index. */
+       Elf64_Xword     m_poffset;   /* Offset relative to symbol. */
+       Elf64_Half      m_repeat;    /* Repeat count. */
+       Elf64_Half      m_stride;    /* Number of units to skip. */
+} Elf64_Move;
+
+/*
+ * Section Header Table (SHDR) entries.
+ */
+typedef struct {
+       Elf64_Word      sh_name;     /* index of section name */
+       Elf64_Word      sh_type;     /* section type */
+       Elf64_Xword     sh_flags;    /* section flags */
+       Elf64_Addr      sh_addr;     /* in-memory address of section */
+       Elf64_Off       sh_offset;   /* file offset of section */
+       Elf64_Xword     sh_size;     /* section size in bytes */
+       Elf64_Word      sh_link;     /* section header table link */
+       Elf64_Word      sh_info;     /* extra information */
+       Elf64_Xword     sh_addralign; /* alignment constraint */
+       Elf64_Xword     sh_entsize;  /* size for fixed-size entries */
+} Elf64_Shdr;
+
+/*
+ * Symbol table entries.
+ */
+typedef struct {
+       Elf64_Word      st_name;     /* index of symbol's name */
+       unsigned char   st_info;     /* type and binding attributes */
+       unsigned char   st_other;    /* visibility */
+       Elf64_Half      st_shndx;    /* index of related section */
+       Elf64_Addr      st_value;    /* value for the symbol */
+       Elf64_Xword     st_size;     /* size of associated data */
+} Elf64_Sym;
+
+/*
+ * Syminfo descriptors, containing additional symbol information.
+ */
+typedef struct {
+       Elf64_Half      si_boundto;  /* Entry index with additional flags. */
+       Elf64_Half      si_flags;    /* Flags. */
+} Elf64_Syminfo;
+
+/*
+ * Relocation descriptors.
+ */
+typedef struct {
+       Elf64_Addr      r_offset;    /* location to apply relocation to */
+       Elf64_Xword     r_info;      /* type+section for relocation */
+} Elf64_Rel;
+
+typedef struct {
+       Elf64_Addr      r_offset;    /* location to apply relocation to */
+       Elf64_Xword     r_info;      /* type+section for relocation */
+       Elf64_Sxword    r_addend;    /* constant addend */
+} Elf64_Rela;
+
+/*
+ * Symbol versioning structures.
+ */
+typedef struct {
+       Elf64_Word      vda_name;    /* Index to name. */
+       Elf64_Word      vda_next;    /* Offset to next entry. */
+} Elf64_Verdaux;
+
+typedef struct {
+       Elf64_Word      vna_hash;    /* Hash value of dependency name. */
+       Elf64_Half      vna_flags;   /* Flags. */
+       Elf64_Half      vna_other;   /* Unused. */
+       Elf64_Word      vna_name;    /* Offset to dependency name. */
+       Elf64_Word      vna_next;    /* Offset to next vernaux entry. */
+} Elf64_Vernaux;
+
+typedef struct {
+       Elf64_Half      vd_version;  /* Version information. */
+       Elf64_Half      vd_flags;    /* Flags. */
+       Elf64_Half      vd_ndx;      /* Index into the versym section. */
+       Elf64_Half      vd_cnt;      /* Number of aux entries. */
+       Elf64_Word      vd_hash;     /* Hash value of name. */
+       Elf64_Word      vd_aux;      /* Offset to aux entries. */
+       Elf64_Word      vd_next;     /* Offset to next version definition. */
+} Elf64_Verdef;
+
+typedef struct {
+       Elf64_Half      vn_version;  /* Version number. */
+       Elf64_Half      vn_cnt;      /* Number of aux entries. */
+       Elf64_Word      vn_file;     /* Offset of associated file name. */
+       Elf64_Word      vn_aux;      /* Offset of vernaux array. */
+       Elf64_Word      vn_next;     /* Offset of next verneed entry. */
+} Elf64_Verneed;
+
+/*
+ * The header for GNU-style hash sections.
+ */
+
+typedef struct {
+       uint32_t        gh_nbuckets;    /* Number of hash buckets. */
+       uint32_t        gh_symndx;      /* First visible symbol in .dynsym. */
+       uint32_t        gh_maskwords;   /* #maskwords used in bloom filter. */
+       uint32_t        gh_shift2;      /* Bloom filter shift count. */
+} Elf_GNU_Hash_Header;
+
+/* libelf.h */
+/* Library private data structures */
+typedef struct _Elf Elf;
+typedef struct _Elf_Scn Elf_Scn;
+
+/* File types */
+typedef enum {
+       ELF_K_NONE = 0,
+       ELF_K_AR,       /* `ar' archives */
+       ELF_K_COFF,     /* COFF files (unsupported) */
+       ELF_K_ELF,      /* ELF files */
+       ELF_K_NUM
+} Elf_Kind;
+
+/* Data types */
+typedef enum {
+       ELF_T_ADDR,
+       ELF_T_BYTE,
+       ELF_T_CAP,
+       ELF_T_DYN,
+       ELF_T_EHDR,
+       ELF_T_HALF,
+       ELF_T_LWORD,
+       ELF_T_MOVE,
+       ELF_T_MOVEP,
+       ELF_T_NOTE,
+       ELF_T_OFF,
+       ELF_T_PHDR,
+       ELF_T_REL,
+       ELF_T_RELA,
+       ELF_T_SHDR,
+       ELF_T_SWORD,
+       ELF_T_SXWORD,
+       ELF_T_SYMINFO,
+       ELF_T_SYM,
+       ELF_T_VDEF,
+       ELF_T_VNEED,
+       ELF_T_WORD,
+       ELF_T_XWORD,
+       ELF_T_GNUHASH,  /* GNU style hash tables. */
+       ELF_T_NUM
+} Elf_Type;
+
+#define        ELF_T_FIRST     ELF_T_ADDR
+#define        ELF_T_LAST      ELF_T_GNUHASH
+
+/* Commands */
+typedef enum {
+       ELF_C_NULL = 0,
+       ELF_C_CLR,
+       ELF_C_FDDONE,
+       ELF_C_FDREAD,
+       ELF_C_RDWR,
+       ELF_C_READ,
+       ELF_C_SET,
+       ELF_C_WRITE,
+       ELF_C_NUM
+} Elf_Cmd;
+
+/*
+ * An `Elf_Data' structure describes data in an
+ * ELF section.
+ */
+typedef struct _Elf_Data {
+       /*
+        * `Public' members that are part of the ELF(3) API.
+        */
+       uint64_t        d_align;
+       void            *d_buf;
+       uint64_t        d_off;
+       uint64_t        d_size;
+       Elf_Type        d_type;
+       unsigned int    d_version;
+} Elf_Data;
+
+/*
+ * An `Elf_Arhdr' structure describes an archive
+ * header.
+ */
+typedef struct {
+       time_t          ar_date;
+       char            *ar_name;       /* archive member name */
+       gid_t           ar_gid;
+       mode_t          ar_mode;
+       char            *ar_rawname;    /* 'raw' member name */
+       size_t          ar_size;
+       uid_t           ar_uid;
+
+       /*
+        * Members that are not part of the public API.
+        */
+       unsigned int    ar_flags;
+} Elf_Arhdr;
+
+/*
+ * An `Elf_Arsym' describes an entry in the archive
+ * symbol table.
+ */
+typedef struct {
+       off_t           as_off;         /* byte offset to member's header */
+       unsigned long   as_hash;        /* elf_hash() value for name */
+       char            *as_name;       /* null terminated symbol name */
+} Elf_Arsym;
+
+/*
+ * Error numbers.
+ */
+
+enum Elf_Error {
+       ELF_E_NONE,     /* No error */
+       ELF_E_ARCHIVE,  /* Malformed ar(1) archive */
+       ELF_E_ARGUMENT, /* Invalid argument */
+       ELF_E_CLASS,    /* Mismatched ELF class */
+       ELF_E_DATA,     /* Invalid data descriptor */
+       ELF_E_HEADER,   /* Missing or malformed ELF header */
+       ELF_E_IO,       /* I/O error */
+       ELF_E_LAYOUT,   /* Layout constraint violation */
+       ELF_E_MODE,     /* Wrong mode for ELF descriptor */
+       ELF_E_RANGE,    /* Value out of range */
+       ELF_E_RESOURCE, /* Resource exhaustion */
+       ELF_E_SECTION,  /* Invalid section descriptor */
+       ELF_E_SEQUENCE, /* API calls out of sequence */
+       ELF_E_UNIMPL,   /* Feature is unimplemented */
+       ELF_E_VERSION,  /* Unknown API version */
+       ELF_E_NUM       /* Max error number */
+};
+
+/*
+ * Flags defined by the API.
+ */
+
+#define        ELF_F_LAYOUT    0x001U  /* application will layout the file */
+#define        ELF_F_DIRTY     0x002U  /* a section or ELF file is dirty */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+static
+Elf            *elf_begin(int _fd, Elf_Cmd _cmd, Elf *_elf);
+static
+int            elf_end(Elf *_elf);
+static
+const char     *elf_errmsg(int _error);
+static
+int            elf_errno(void);
+static
+Elf_Data       *elf_getdata(Elf_Scn *, Elf_Data *);
+static
+char           *elf_strptr(Elf *_elf, size_t _section, size_t _offset);
+static
+unsigned int   elf_version(unsigned int _version);
+static
+Elf_Scn                *elf_nextscn(Elf *_elf, Elf_Scn *_scn);
+#ifdef __cplusplus
+}
+#endif
+
+/* gelf.h */
+typedef Elf64_Shdr     GElf_Shdr;      /* Section header */
+typedef Elf64_Sym      GElf_Sym;       /* Symbol table entries */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+static
+GElf_Shdr      *gelf_getshdr(Elf_Scn *_scn, GElf_Shdr *_dst);
+static
+GElf_Sym       *gelf_getsym(Elf_Data *_src, int _index, GElf_Sym *_dst);
+#ifdef __cplusplus
+}
+#endif
+
+/* _libelf.h */
+/*
+ * Library-private data structures.
+ */
+
+#define LIBELF_MSG_SIZE        256
+
+struct _libelf_globals {
+       int             libelf_arch;
+       unsigned int    libelf_byteorder;
+       int             libelf_class;
+       int             libelf_error;
+       int             libelf_fillchar;
+       unsigned int    libelf_version;
+       unsigned char   libelf_msg[LIBELF_MSG_SIZE];
+};
+
+#if 0
+extern struct _libelf_globals _libelf;
+#endif
+
+#define        LIBELF_PRIVATE(N)       (_libelf.libelf_##N)
+
+#define        LIBELF_ELF_ERROR_MASK                   0xFF
+#define        LIBELF_OS_ERROR_SHIFT                   8
+
+#define        LIBELF_ERROR(E, O) (((E) & LIBELF_ELF_ERROR_MASK) |     \
+       ((O) << LIBELF_OS_ERROR_SHIFT))
+
+#define        LIBELF_SET_ERROR(E, O) do {                                     \
+               LIBELF_PRIVATE(error) = LIBELF_ERROR(ELF_E_##E, (O));   \
+       } while (0)
+
+/*
+ * Flags for library internal use.  These use the upper 16 bits of the
+ * `e_flags' field.
+ */
+
+#define        LIBELF_F_DATA_MALLOCED  0x040000U /* whether data was malloc'ed */
+#define        LIBELF_F_RAWFILE_MALLOC 0x080000U /* whether e_rawfile was malloc'ed */
+#define        LIBELF_F_RAWFILE_MMAP   0x100000U /* whether e_rawfile was mmap'ed */
+#define        LIBELF_F_SHDRS_LOADED   0x200000U /* whether all shdrs were read in */
+#define        LIBELF_F_SPECIAL_FILE   0x400000U /* non-regular file */
+
+struct _Elf {
+       int             e_activations;  /* activation count */
+       unsigned int    e_byteorder;    /* ELFDATA* */
+       int             e_class;        /* ELFCLASS*  */
+       Elf_Cmd         e_cmd;          /* ELF_C_* used at creation time */
+       int             e_fd;           /* associated file descriptor */
+       unsigned int    e_flags;        /* ELF_F_* & LIBELF_F_* flags */
+       Elf_Kind        e_kind;         /* ELF_K_* */
+       Elf             *e_parent;      /* non-NULL for archive members */
+       unsigned char   *e_rawfile;     /* uninterpreted bytes */
+       size_t          e_rawsize;      /* size of uninterpreted bytes */
+       unsigned int    e_version;      /* file version */
+
+       /*
+        * Header information for archive members.  See the
+        * LIBELF_F_AR_HEADER flag.
+        */
+       union {
+               Elf_Arhdr       *e_arhdr;       /* translated header */
+               unsigned char   *e_rawhdr;      /* untranslated header */
+       } e_hdr;
+
+       union {
+               struct {                /* ar(1) archives */
+                       off_t   e_next; /* set by elf_rand()/elf_next() */
+                       int     e_nchildren;
+                       unsigned char *e_rawstrtab; /* file name strings */
+                       size_t  e_rawstrtabsz;
+                       unsigned char *e_rawsymtab;     /* symbol table */
+                       size_t  e_rawsymtabsz;
+                       Elf_Arsym *e_symtab;
+                       size_t  e_symtabsz;
+               } e_ar;
+               struct {                /* regular ELF files */
+                       union {
+#if 0
+                               Elf32_Ehdr *e_ehdr32;
+#endif
+                               Elf64_Ehdr *e_ehdr64;
+                       } e_ehdr;
+                       union {
+#if 0
+                               Elf32_Phdr *e_phdr32;
+#endif
+                               Elf64_Phdr *e_phdr64;
+                       } e_phdr;
+                       STAILQ_HEAD(, _Elf_Scn) e_scn;  /* section list */
+                       size_t  e_nphdr;        /* number of Phdr entries */
+                       size_t  e_nscn;         /* number of sections */
+                       size_t  e_strndx;       /* string table section index */
+               } e_elf;
+       } e_u;
+};
+
+/*
+ * The internal descriptor wrapping the "Elf_Data" type.
+ */
+struct _Libelf_Data {
+       Elf_Data        d_data;         /* The exported descriptor. */
+       Elf_Scn         *d_scn;         /* The containing section */
+       unsigned int    d_flags;
+       STAILQ_ENTRY(_Libelf_Data) d_next;
+};
+
+struct _Elf_Scn {
+       union {
+#if 0
+               Elf32_Shdr      s_shdr32;
+#endif
+               Elf64_Shdr      s_shdr64;
+       } s_shdr;
+       STAILQ_HEAD(, _Libelf_Data) s_data;     /* translated data */
+       STAILQ_HEAD(, _Libelf_Data) s_rawdata;  /* raw data */
+       STAILQ_ENTRY(_Elf_Scn) s_next;
+       struct _Elf     *s_elf;         /* parent ELF descriptor */
+       unsigned int    s_flags;        /* flags for the section as a whole */
+       size_t          s_ndx;          /* index# for this section */
+       uint64_t        s_offset;       /* managed by elf_update() */
+       uint64_t        s_rawoff;       /* original offset in the file */
+       uint64_t        s_size;         /* managed by elf_update() */
+};
+
+enum {
+       ELF_TOFILE,
+       ELF_TOMEMORY
+};
+
+/* PRIVATE */
+
+/* elf.c */
+static struct _libelf_globals _libelf = {
+       .libelf_arch            = LIBELF_ARCH,
+       .libelf_byteorder       = LIBELF_BYTEORDER,
+       .libelf_class           = LIBELF_CLASS,
+       .libelf_error           = 0,
+       .libelf_fillchar        = 0,
+       .libelf_version         = EV_NONE
+};
+
+/* libelf_msize.c */
+struct msize {
+       size_t  msz64;
+};
+
+static struct msize msize[ELF_T_NUM] = {
+[ELF_T_ADDR] = { .msz64 = sizeof(Elf64_Addr) },
+[ELF_T_BYTE] = { .msz64 = 1 },
+[ELF_T_CAP] = { .msz64 = sizeof(Elf64_Cap) },
+[ELF_T_DYN] = { .msz64 = sizeof(Elf64_Dyn) },
+[ELF_T_EHDR] = { .msz64 = sizeof(Elf64_Ehdr) },
+[ELF_T_GNUHASH] = { .msz64 = 1 },
+[ELF_T_HALF] = { .msz64 = sizeof(Elf64_Half) },
+[ELF_T_LWORD] = { .msz64 = sizeof(Elf64_Lword) },
+[ELF_T_MOVE] = { .msz64 = sizeof(Elf64_Move) },
+[ELF_T_MOVEP] = { .msz64 = 0 },
+[ELF_T_NOTE] = { .msz64 = 1 },
+[ELF_T_OFF] = { .msz64 = sizeof(Elf64_Off) },
+[ELF_T_PHDR] = { .msz64 = sizeof(Elf64_Phdr) },
+[ELF_T_REL] = { .msz64 = sizeof(Elf64_Rel) },
+[ELF_T_RELA] = { .msz64 = sizeof(Elf64_Rela) },
+[ELF_T_SHDR] = { .msz64 = sizeof(Elf64_Shdr) },
+[ELF_T_SWORD] = { .msz64 = sizeof(Elf64_Sword) },
+[ELF_T_SXWORD] = { .msz64 = sizeof(Elf64_Sxword) },
+[ELF_T_SYMINFO] = { .msz64 = sizeof(Elf64_Syminfo) },
+[ELF_T_SYM] = { .msz64 = sizeof(Elf64_Sym) },
+[ELF_T_VDEF] = { .msz64 = 1 },
+[ELF_T_VNEED] = { .msz64 = 1 },
+[ELF_T_WORD] = { .msz64 = sizeof(Elf64_Word) },
+[ELF_T_XWORD] = { .msz64 = sizeof(Elf64_Xword) },
+};
+
+static size_t
+_libelf_msize(Elf_Type t, int elfclass, unsigned int version)
+{
+       size_t sz;
+
+       assert(/*elfclass == ELFCLASS32 ||*/ elfclass == ELFCLASS64);
+       assert((signed) t >= ELF_T_FIRST && t <= ELF_T_LAST);
+
+       if (version != EV_CURRENT) {
+               LIBELF_SET_ERROR(VERSION, 0);
+               return (0);
+       }
+
+       sz = /* (elfclass == ELFCLASS32) ? msize[t].msz32 : */ msize[t].msz64;
+
+       return (sz);
+}
+
+/* libelf_fsize.c */
+struct tfsize {
+       size_t fsz64;
+};
+
+static struct tfsize tfsize[ELF_T_NUM] = {
+[ELF_T_ADDR] =    { .fsz64 = sizeof(Elf64_Addr) },
+[ELF_T_BYTE] =    { .fsz64 = 1 },
+[ELF_T_CAP] =     { .fsz64 = sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
+[ELF_T_DYN] =     { .fsz64 = sizeof(Elf64_Sxword)+sizeof(Elf64_Xword)+0 },
+[ELF_T_EHDR] =    { .fsz64 = EI_NIDENT
+                           +sizeof(Elf64_Half)+sizeof(Elf64_Half)
+                           +sizeof(Elf64_Word)+sizeof(Elf64_Addr)
+                           +sizeof(Elf64_Off)+ sizeof(Elf64_Off)
+                           +sizeof(Elf64_Word)+sizeof(Elf64_Half)
+                           +sizeof(Elf64_Half)+sizeof(Elf64_Half)
+                           +sizeof(Elf64_Half)+sizeof(Elf64_Half)
+                           +sizeof(Elf64_Half)+0 },
+[ELF_T_GNUHASH] = { .fsz64 = 1 },
+[ELF_T_HALF] =    { .fsz64 = sizeof(Elf64_Half) },
+[ELF_T_LWORD] =   { .fsz64 = sizeof(Elf64_Lword) },
+[ELF_T_MOVE] =    { .fsz64 = sizeof(Elf64_Lword)+sizeof(Elf64_Xword)
+                           +sizeof(Elf64_Xword)+sizeof(Elf64_Half)
+                           +sizeof(Elf64_Half)+0 },
+[ELF_T_MOVEP] =   { .fsz64 = 0 },
+[ELF_T_NOTE] =    { .fsz64 = 1 },
+[ELF_T_OFF] =     { .fsz64 = sizeof(Elf64_Off) },
+[ELF_T_PHDR] =    { .fsz64 = sizeof(Elf64_Word)+sizeof(Elf64_Word)
+                           +sizeof(Elf64_Off)+ sizeof(Elf64_Addr)
+                           +sizeof(Elf64_Addr)+sizeof(Elf64_Xword)
+                           +sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
+[ELF_T_REL] =     { .fsz64 = sizeof(Elf64_Addr)+sizeof(Elf64_Xword)+0 },
+[ELF_T_RELA] =    { .fsz64 = sizeof(Elf64_Addr)+sizeof(Elf64_Xword)
+                           +sizeof(Elf64_Sxword)+0 },
+[ELF_T_SHDR] =    { .fsz64 = sizeof(Elf64_Word)+sizeof(Elf64_Word)
+                           +sizeof(Elf64_Xword)+sizeof(Elf64_Addr)
+                           +sizeof(Elf64_Off)+ sizeof(Elf64_Xword)
+                           +sizeof(Elf64_Word)+sizeof(Elf64_Word)
+                           +sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
+[ELF_T_SWORD] =   { .fsz64 = sizeof(Elf64_Sword) },
+[ELF_T_SXWORD] =  { .fsz64 = sizeof(Elf64_Sxword) },
+[ELF_T_SYMINFO] = { .fsz64 = sizeof(Elf64_Half)+sizeof(Elf64_Half)+0 },
+[ELF_T_SYM] =     { .fsz64 = sizeof(Elf64_Word)+1+1+sizeof(Elf64_Half)
+                           +sizeof(Elf64_Addr)+sizeof(Elf64_Xword)+0 },
+[ELF_T_VDEF] =    { .fsz64 = 1 },
+[ELF_T_VNEED] =   { .fsz64 = 1 },
+[ELF_T_WORD] =    { .fsz64 = sizeof(Elf64_Word) },
+[ELF_T_XWORD] =   { .fsz64 = sizeof(Elf64_Xword) },
+};
+
+static size_t
+_libelf_fsize(Elf_Type t, int ec, unsigned int v, size_t c)
+{
+       size_t sz;
+
+       sz = 0;
+       if (v != EV_CURRENT)
+               LIBELF_SET_ERROR(VERSION, 0);
+       else if ((int) t < ELF_T_FIRST || t > ELF_T_LAST)
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+       else {
+               sz = ec == ELFCLASS64 ? tfsize[t].fsz64 : /* tfsize[t].fsz32 */ 0;
+               if (sz == 0)
+                       LIBELF_SET_ERROR(UNIMPL, 0);
+       }
+
+       return (sz*c);
+}
+
+/* gelf_fsize.c */
+static size_t
+elf64_fsize(Elf_Type t, size_t c, unsigned int v)
+{
+       return (_libelf_fsize(t, ELFCLASS64, v, c));
+}
+
+/* libelf_allocate.h */
+static Elf *
+_libelf_allocate_elf(void)
+{
+       Elf *e;
+
+       if ((e = malloc(sizeof(*e))) == NULL) {
+               LIBELF_SET_ERROR(RESOURCE, errno);
+               return NULL;
+       }
+
+       e->e_activations = 1;
+       e->e_hdr.e_rawhdr = NULL;
+       e->e_byteorder   = ELFDATANONE;
+       e->e_class       = ELFCLASSNONE;
+       e->e_cmd         = ELF_C_NULL;
+       e->e_fd          = -1;
+       e->e_flags       = 0;
+       e->e_kind        = ELF_K_NONE;
+       e->e_parent      = NULL;
+       e->e_rawfile     = NULL;
+       e->e_rawsize     = 0;
+       e->e_version     = LIBELF_PRIVATE(version);
+
+       (void) memset(&e->e_u, 0, sizeof(e->e_u));
+
+       return (e);
+}
+
+static void
+_libelf_init_elf(Elf *e, Elf_Kind kind)
+{
+       assert(e != NULL);
+       assert(e->e_kind == ELF_K_NONE);
+
+       e->e_kind = kind;
+
+       switch (kind) {
+       case ELF_K_ELF:
+               STAILQ_INIT(&e->e_u.e_elf.e_scn);
+               break;
+       default:
+               break;
+       }
+}
+
+#define        FREE(P)         do {                            \
+               if (P)                                  \
+                       free(P);                        \
+       } while (0)
+
+static Elf *
+_libelf_release_elf(Elf *e)
+{
+#if 0
+       Elf_Arhdr *arh;
+#endif
+
+       switch (e->e_kind) {
+#if 0
+       case ELF_K_AR:
+               FREE(e->e_u.e_ar.e_symtab);
+               break;
+#endif
+
+       case ELF_K_ELF:
+               switch (e->e_class) {
+#if 0
+               case ELFCLASS32:
+                       FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
+                       FREE(e->e_u.e_elf.e_phdr.e_phdr32);
+                       break;
+#endif
+               case ELFCLASS64:
+                       FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
+                       FREE(e->e_u.e_elf.e_phdr.e_phdr64);
+                       break;
+               }
+
+               assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
+
+#if 0
+               if (e->e_flags & LIBELF_F_AR_HEADER) {
+                       arh = e->e_hdr.e_arhdr;
+                       FREE(arh->ar_name);
+                       FREE(arh->ar_rawname);
+                       free(arh);
+               }
+#endif
+
+               break;
+
+       default:
+               break;
+       }
+
+       free(e);
+
+       return (NULL);
+}
+
+#undef FREE
+
+static struct _Libelf_Data *
+_libelf_allocate_data(Elf_Scn *s)
+{
+       struct _Libelf_Data *d;
+
+       if ((d = calloc((size_t) 1, sizeof(*d))) == NULL) {
+               LIBELF_SET_ERROR(RESOURCE, 0);
+               return (NULL);
+       }
+
+       d->d_scn = s;
+
+       return (d);
+}
+
+static struct _Libelf_Data *
+_libelf_release_data(struct _Libelf_Data *d)
+{
+
+       if (d->d_flags & LIBELF_F_DATA_MALLOCED)
+               free(d->d_data.d_buf);
+
+       free(d);
+
+       return (NULL);
+}
+
+static Elf_Scn *
+_libelf_allocate_scn(Elf *e, size_t ndx)
+{
+       Elf_Scn *s;
+
+       if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
+               LIBELF_SET_ERROR(RESOURCE, errno);
+               return (NULL);
+       }
+
+       s->s_elf = e;
+       s->s_ndx = ndx;
+
+       STAILQ_INIT(&s->s_data);
+       STAILQ_INIT(&s->s_rawdata);
+
+       STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
+
+       return (s);
+}
+
+static Elf_Scn *
+_libelf_release_scn(Elf_Scn *s)
+{
+       Elf *e;
+       struct _Libelf_Data *d, *td;
+
+       assert(s != NULL);
+
+       STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
+               STAILQ_REMOVE(&s->s_data, d, _Libelf_Data, d_next);
+               d = _libelf_release_data(d);
+       }
+
+       STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) {
+               assert((d->d_flags & LIBELF_F_DATA_MALLOCED) == 0);
+               STAILQ_REMOVE(&s->s_rawdata, d, _Libelf_Data, d_next);
+               d = _libelf_release_data(d);
+       }
+
+       e = s->s_elf;
+
+       assert(e != NULL);
+
+       STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
+
+       free(s);
+
+       return (NULL);
+}
+
+/* libelf_data.c */
+static int
+_libelf_xlate_shtype(uint32_t sht)
+{
+       /*
+        * Look for known section types.
+        */
+       switch (sht) {
+       case SHT_DYNAMIC:
+               return (ELF_T_DYN);
+       case SHT_DYNSYM:
+               return (ELF_T_SYM);
+       case SHT_FINI_ARRAY:
+               return (ELF_T_ADDR);
+       case SHT_GNU_HASH:
+               return (ELF_T_GNUHASH);
+       case SHT_GNU_LIBLIST:
+               return (ELF_T_WORD);
+       case SHT_GROUP:
+               return (ELF_T_WORD);
+       case SHT_HASH:
+               return (ELF_T_WORD);
+       case SHT_INIT_ARRAY:
+               return (ELF_T_ADDR);
+       case SHT_NOBITS:
+               return (ELF_T_BYTE);
+       case SHT_NOTE:
+               return (ELF_T_NOTE);
+       case SHT_PREINIT_ARRAY:
+               return (ELF_T_ADDR);
+       case SHT_PROGBITS:
+               return (ELF_T_BYTE);
+       case SHT_REL:
+               return (ELF_T_REL);
+       case SHT_RELA:
+               return (ELF_T_RELA);
+       case SHT_STRTAB:
+               return (ELF_T_BYTE);
+       case SHT_SYMTAB:
+               return (ELF_T_SYM);
+       case SHT_SYMTAB_SHNDX:
+               return (ELF_T_WORD);
+       case SHT_SUNW_dof:
+               return (ELF_T_BYTE);
+       case SHT_SUNW_move:
+               return (ELF_T_MOVE);
+       case SHT_SUNW_syminfo:
+               return (ELF_T_SYMINFO);
+       case SHT_SUNW_verdef:   /* == SHT_GNU_verdef */
+               return (ELF_T_VDEF);
+       case SHT_SUNW_verneed:  /* == SHT_GNU_verneed */
+               return (ELF_T_VNEED);
+       case SHT_SUNW_versym:   /* == SHT_GNU_versym */
+               return (ELF_T_HALF);
+       default:
+               /*
+                * Values in the range [SHT_LOOS..SHT_HIUSER] (i.e.,
+                * OS, processor and user-defined section types) are
+                * legal, but since we do not know anything more about
+                * their semantics, we return a type of ELF_T_BYTE.
+                */
+               if (sht >= SHT_LOOS && sht <= SHT_HIUSER)
+                       return (ELF_T_BYTE);
+
+               /*
+                * Other values are unsupported.
+                */
+               return (-1);
+       }
+}
+
+/* libelf_convert.c */
+#define        SWAP_BYTE(X)    do { (void) (X); } while (0)
+#define        SWAP_IDENT(X)   do { (void) (X); } while (0)
+#define        SWAP_HALF(X)    do {                                            \
+               uint16_t _x = (uint16_t) (X);                           \
+               uint32_t _t = _x & 0xFFU;                               \
+               _t <<= 8U; _x >>= 8U; _t |= _x & 0xFFU;                 \
+               (X) = (uint16_t) _t;                                    \
+       } while (0)
+#define        _SWAP_WORD(X, T) do {                                           \
+               uint32_t _x = (uint32_t) (X);                           \
+               uint32_t _t = _x & 0xFF;                                \
+               _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
+               _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
+               _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
+               (X) = (T) _t;                                           \
+       } while (0)
+#define        SWAP_SWORD(X)   _SWAP_WORD(X, /* Elf32_Sword */ Elf64_Sword)
+#define        SWAP_WORD(X)    _SWAP_WORD(X, /* Elf32_Word */ Elf64_Word)
+#define        _SWAP_WORD64(X, T) do {                                         \
+               uint64_t _x = (uint64_t) (X);                           \
+               uint64_t _t = _x & 0xFF;                                \
+               _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
+               _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
+               _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
+               _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
+               _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
+               _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
+               _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
+               (X) = (T) _t;                                           \
+       } while (0)
+#define        SWAP_ADDR64(X)  _SWAP_WORD64(X, Elf64_Addr)
+#define        SWAP_LWORD(X)   _SWAP_WORD64(X, Elf64_Lword)
+#define        SWAP_OFF64(X)   _SWAP_WORD64(X, Elf64_Off)
+#define        SWAP_SXWORD(X)  _SWAP_WORD64(X, Elf64_Sxword)
+#define        SWAP_XWORD(X)   _SWAP_WORD64(X, Elf64_Xword)
+
+#define        READ_BYTE(P,X)  do {                                            \
+               const unsigned char *const _p =                         \
+                       (const unsigned char *) (P);                    \
+               (X)             = _p[0];                                \
+               (P)             = (P) + 1;                              \
+       } while (0)
+#define        READ_HALF(P,X)  do {                                            \
+               uint16_t _t;                                            \
+               unsigned char *const _q = (unsigned char *) &_t;        \
+               const unsigned char *const _p =                         \
+                       (const unsigned char *) (P);                    \
+               _q[0]           = _p[0];                                \
+               _q[1]           = _p[1];                                \
+               (P)             = (P) + 2;                              \
+               (X)             = _t;                                   \
+       } while (0)
+#define        _READ_WORD(P,X,T) do {                                          \
+               uint32_t _t;                                            \
+               unsigned char *const _q = (unsigned char *) &_t;        \
+               const unsigned char *const _p =                         \
+                       (const unsigned char *) (P);                    \
+               _q[0]           = _p[0];                                \
+               _q[1]           = _p[1];                                \
+               _q[2]           = _p[2];                                \
+               _q[3]           = _p[3];                                \
+               (P)             = (P) + 4;                              \
+               (X)             = (T) _t;                               \
+       } while (0)
+#define        READ_SWORD(P,X)         _READ_WORD(P, X, /*Elf32_Sword*/ Elf64_Sword)
+#define        READ_WORD(P,X)          _READ_WORD(P, X, /*Elf32_Word*/ Elf64_Word)
+#define        _READ_WORD64(P,X,T)     do {                                    \
+               uint64_t _t;                                            \
+               unsigned char *const _q = (unsigned char *) &_t;        \
+               const unsigned char *const _p =                         \
+                       (const unsigned char *) (P);                    \
+               _q[0]           = _p[0];                                \
+               _q[1]           = _p[1];                                \
+               _q[2]           = _p[2];                                \
+               _q[3]           = _p[3];                                \
+               _q[4]           = _p[4];                                \
+               _q[5]           = _p[5];                                \
+               _q[6]           = _p[6];                                \
+               _q[7]           = _p[7];                                \
+               (P)             = (P) + 8;                              \
+               (X)             = (T) _t;                               \
+       } while (0)
+#define        READ_ADDR64(P,X)        _READ_WORD64(P, X, Elf64_Addr)
+#define        READ_LWORD(P,X)         _READ_WORD64(P, X, Elf64_Lword)
+#define        READ_OFF64(P,X)         _READ_WORD64(P, X, Elf64_Off)
+#define        READ_SXWORD(P,X)        _READ_WORD64(P, X, Elf64_Sxword)
+#define        READ_XWORD(P,X)         _READ_WORD64(P, X, Elf64_Xword)
+#define        READ_IDENT(P,X)         do {                                    \
+               (void) memcpy((X), (P), sizeof((X)));                   \
+               (P)             = (P) + EI_NIDENT;                      \
+       } while (0)
+
+#define        ROUNDUP2(V,N)   (V) = ((((V) + (N) - 1)) & ~((N) - 1))
+
+static int
+_libelf_cvt_ADDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Addr t, *d = (Elf64_Addr *) (uintptr_t) dst;
+       size_t c;
+
+       if (dsz < count * sizeof(Elf64_Addr))
+               return (0);
+
+       if (!byteswap) {
+               (void) memcpy(dst, src, count * sizeof(*d));
+               return (1);
+       }
+
+       for (c = 0; c < count; c++) {
+               READ_ADDR64(src,t);
+               SWAP_ADDR64(t);
+               *d++ = t;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_CAP64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Cap       t, *d;
+       unsigned char   *s,*s0;
+       size_t          fsz;
+
+       fsz = elf64_fsize(ELF_T_CAP, (size_t) 1, EV_CURRENT);
+       d   = ((Elf64_Cap *) (uintptr_t) dst) + (count - 1);
+       s0  = src + (count - 1) * fsz;
+
+       if (dsz < count * sizeof(Elf64_Cap))
+               return (0);
+
+       while (count--) {
+               s = s0;
+               /* Read an Elf64_Cap */
+               READ_XWORD(s,t.c_tag);
+               READ_XWORD(s,t.c_un.c_val);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Cap */
+                       SWAP_XWORD(t.c_tag);
+                       SWAP_XWORD(t.c_un.c_val);
+                       /**/
+               }
+               *d-- = t; s0 -= fsz;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_DYN64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Dyn       t, *d;
+       unsigned char   *s,*s0;
+       size_t          fsz;
+
+       fsz = elf64_fsize(ELF_T_DYN, (size_t) 1, EV_CURRENT);
+       d   = ((Elf64_Dyn *) (uintptr_t) dst) + (count - 1);
+       s0  = src + (count - 1) * fsz;
+
+       if (dsz < count * sizeof(Elf64_Dyn))
+               return (0);
+
+       while (count--) {
+               s = s0;
+               /* Read an Elf64_Dyn */
+               READ_SXWORD(s,t.d_tag);
+               READ_XWORD(s,t.d_un.d_ptr);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Dyn */
+                       SWAP_SXWORD(t.d_tag);
+                       SWAP_XWORD(t.d_un.d_ptr);
+                       /**/
+               }
+               *d-- = t; s0 -= fsz;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_EHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Ehdr      t, *d;
+       unsigned char   *s,*s0;
+       size_t          fsz;
+
+       fsz = elf64_fsize(ELF_T_EHDR, (size_t) 1, EV_CURRENT);
+       d   = ((Elf64_Ehdr *) (uintptr_t) dst) + (count - 1);
+       s0  = src + (count - 1) * fsz;
+
+       if (dsz < count * sizeof(Elf64_Ehdr))
+               return (0);
+
+       while (count--) {
+               s = s0;
+               /* Read an Elf64_Ehdr */
+               READ_IDENT(s,t.e_ident);
+               READ_HALF(s,t.e_type);
+               READ_HALF(s,t.e_machine);
+               READ_WORD(s,t.e_version);
+               READ_ADDR64(s,t.e_entry);
+               READ_OFF64(s,t.e_phoff);
+               READ_OFF64(s,t.e_shoff);
+               READ_WORD(s,t.e_flags);
+               READ_HALF(s,t.e_ehsize);
+               READ_HALF(s,t.e_phentsize);
+               READ_HALF(s,t.e_phnum);
+               READ_HALF(s,t.e_shentsize);
+               READ_HALF(s,t.e_shnum);
+               READ_HALF(s,t.e_shstrndx);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Ehdr */
+                       SWAP_IDENT(t.e_ident);
+                       SWAP_HALF(t.e_type);
+                       SWAP_HALF(t.e_machine);
+                       SWAP_WORD(t.e_version);
+                       SWAP_ADDR64(t.e_entry);
+                       SWAP_OFF64(t.e_phoff);
+                       SWAP_OFF64(t.e_shoff);
+                       SWAP_WORD(t.e_flags);
+                       SWAP_HALF(t.e_ehsize);
+                       SWAP_HALF(t.e_phentsize);
+                       SWAP_HALF(t.e_phnum);
+                       SWAP_HALF(t.e_shentsize);
+                       SWAP_HALF(t.e_shnum);
+                       SWAP_HALF(t.e_shstrndx);
+                       /**/
+               }
+               *d-- = t; s0 -= fsz;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_HALF_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Half t, *d = (Elf64_Half *) (uintptr_t) dst;
+       size_t c;
+
+       if (dsz < count * sizeof(Elf64_Half))
+               return (0);
+
+       if (!byteswap) {
+               (void) memcpy(dst, src, count * sizeof(*d));
+               return (1);
+       }
+
+       for (c = 0; c < count; c++) {
+               READ_HALF(src,t);
+               SWAP_HALF(t);
+               *d++ = t;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_LWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Lword t, *d = (Elf64_Lword *) (uintptr_t) dst;
+       size_t c;
+
+       if (dsz < count * sizeof(Elf64_Lword))
+               return (0);
+
+       if (!byteswap) {
+               (void) memcpy(dst, src, count * sizeof(*d));
+               return (1);
+       }
+
+       for (c = 0; c < count; c++) {
+               READ_LWORD(src,t);
+               SWAP_LWORD(t);
+               *d++ = t;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_MOVE64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Move      t, *d;
+       unsigned char   *s,*s0;
+       size_t          fsz;
+
+       fsz = elf64_fsize(ELF_T_MOVE, (size_t) 1, EV_CURRENT);
+       d   = ((Elf64_Move *) (uintptr_t) dst) + (count - 1);
+       s0  = src + (count - 1) * fsz;
+
+       if (dsz < count * sizeof(Elf64_Move))
+               return (0);
+
+       while (count--) {
+               s = s0;
+               /* Read an Elf64_Move */
+               READ_LWORD(s,t.m_value);
+               READ_XWORD(s,t.m_info);
+               READ_XWORD(s,t.m_poffset);
+               READ_HALF(s,t.m_repeat);
+               READ_HALF(s,t.m_stride);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Move */
+                       SWAP_LWORD(t.m_value);
+                       SWAP_XWORD(t.m_info);
+                       SWAP_XWORD(t.m_poffset);
+                       SWAP_HALF(t.m_repeat);
+                       SWAP_HALF(t.m_stride);
+                       /**/
+               }
+               *d-- = t; s0 -= fsz;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_OFF64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Off t, *d = (Elf64_Off *) (uintptr_t) dst;
+       size_t c;
+
+       if (dsz < count * sizeof(Elf64_Off))
+               return (0);
+
+       if (!byteswap) {
+               (void) memcpy(dst, src, count * sizeof(*d));
+               return (1);
+       }
+
+       for (c = 0; c < count; c++) {
+               READ_OFF64(src,t);
+               SWAP_OFF64(t);
+               *d++ = t;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_PHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Phdr      t, *d;
+       unsigned char   *s,*s0;
+       size_t          fsz;
+
+       fsz = elf64_fsize(ELF_T_PHDR, (size_t) 1, EV_CURRENT);
+       d   = ((Elf64_Phdr *) (uintptr_t) dst) + (count - 1);
+       s0  = src + (count - 1) * fsz;
+
+       if (dsz < count * sizeof(Elf64_Phdr))
+               return (0);
+
+       while (count--) {
+               s = s0;
+               /* Read an Elf64_Phdr */
+               READ_WORD(s,t.p_type);
+               READ_WORD(s,t.p_flags);
+               READ_OFF64(s,t.p_offset);
+               READ_ADDR64(s,t.p_vaddr);
+               READ_ADDR64(s,t.p_paddr);
+               READ_XWORD(s,t.p_filesz);
+               READ_XWORD(s,t.p_memsz);
+               READ_XWORD(s,t.p_align);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Phdr */
+                       SWAP_WORD(t.p_type);
+                       SWAP_WORD(t.p_flags);
+                       SWAP_OFF64(t.p_offset);
+                       SWAP_ADDR64(t.p_vaddr);
+                       SWAP_ADDR64(t.p_paddr);
+                       SWAP_XWORD(t.p_filesz);
+                       SWAP_XWORD(t.p_memsz);
+                       SWAP_XWORD(t.p_align);
+                       /**/
+               }
+               *d-- = t; s0 -= fsz;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_REL64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Rel       t, *d;
+       unsigned char   *s,*s0;
+       size_t          fsz;
+
+       fsz = elf64_fsize(ELF_T_REL, (size_t) 1, EV_CURRENT);
+       d   = ((Elf64_Rel *) (uintptr_t) dst) + (count - 1);
+       s0  = src + (count - 1) * fsz;
+
+       if (dsz < count * sizeof(Elf64_Rel))
+               return (0);
+
+       while (count--) {
+               s = s0;
+               /* Read an Elf64_Rel */
+               READ_ADDR64(s,t.r_offset);
+               READ_XWORD(s,t.r_info);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Rel */
+                       SWAP_ADDR64(t.r_offset);
+                       SWAP_XWORD(t.r_info);
+                       /**/
+               }
+               *d-- = t; s0 -= fsz;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_RELA64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Rela      t, *d;
+       unsigned char   *s,*s0;
+       size_t          fsz;
+
+       fsz = elf64_fsize(ELF_T_RELA, (size_t) 1, EV_CURRENT);
+       d   = ((Elf64_Rela *) (uintptr_t) dst) + (count - 1);
+       s0  = src + (count - 1) * fsz;
+
+       if (dsz < count * sizeof(Elf64_Rela))
+               return (0);
+
+       while (count--) {
+               s = s0;
+               /* Read an Elf64_Rela */
+               READ_ADDR64(s,t.r_offset);
+               READ_XWORD(s,t.r_info);
+               READ_SXWORD(s,t.r_addend);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Rela */
+                       SWAP_ADDR64(t.r_offset);
+                       SWAP_XWORD(t.r_info);
+                       SWAP_SXWORD(t.r_addend);
+                       /**/
+               }
+               *d-- = t; s0 -= fsz;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_SHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Shdr      t, *d;
+       unsigned char   *s,*s0;
+       size_t          fsz;
+
+       fsz = elf64_fsize(ELF_T_SHDR, (size_t) 1, EV_CURRENT);
+       d   = ((Elf64_Shdr *) (uintptr_t) dst) + (count - 1);
+       s0  = src + (count - 1) * fsz;
+
+       if (dsz < count * sizeof(Elf64_Shdr))
+               return (0);
+
+       while (count--) {
+               s = s0;
+               /* Read an Elf64_Shdr */
+               READ_WORD(s,t.sh_name);
+               READ_WORD(s,t.sh_type);
+               READ_XWORD(s,t.sh_flags);
+               READ_ADDR64(s,t.sh_addr);
+               READ_OFF64(s,t.sh_offset);
+               READ_XWORD(s,t.sh_size);
+               READ_WORD(s,t.sh_link);
+               READ_WORD(s,t.sh_info);
+               READ_XWORD(s,t.sh_addralign);
+               READ_XWORD(s,t.sh_entsize);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Shdr */
+                       SWAP_WORD(t.sh_name);
+                       SWAP_WORD(t.sh_type);
+                       SWAP_XWORD(t.sh_flags);
+                       SWAP_ADDR64(t.sh_addr);
+                       SWAP_OFF64(t.sh_offset);
+                       SWAP_XWORD(t.sh_size);
+                       SWAP_WORD(t.sh_link);
+                       SWAP_WORD(t.sh_info);
+                       SWAP_XWORD(t.sh_addralign);
+                       SWAP_XWORD(t.sh_entsize);
+                       /**/
+               }
+               *d-- = t; s0 -= fsz;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_SWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Sword t, *d = (Elf64_Sword *) (uintptr_t) dst;
+       size_t c;
+
+       if (dsz < count * sizeof(Elf64_Sword))
+               return (0);
+
+       if (!byteswap) {
+               (void) memcpy(dst, src, count * sizeof(*d));
+               return (1);
+       }
+
+       for (c = 0; c < count; c++) {
+               READ_SWORD(src,t);
+               SWAP_SWORD(t);
+               *d++ = t;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_SXWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Sxword t, *d = (Elf64_Sxword *) (uintptr_t) dst;
+       size_t c;
+
+       if (dsz < count * sizeof(Elf64_Sxword))
+               return (0);
+
+       if (!byteswap) {
+               (void) memcpy(dst, src, count * sizeof(*d));
+               return (1);
+       }
+
+       for (c = 0; c < count; c++) {
+               READ_SXWORD(src,t);
+               SWAP_SXWORD(t);
+               *d++ = t;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_SYMINFO64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Syminfo   t, *d;
+       unsigned char   *s,*s0;
+       size_t          fsz;
+
+       fsz = elf64_fsize(ELF_T_SYMINFO, (size_t) 1, EV_CURRENT);
+       d   = ((Elf64_Syminfo *) (uintptr_t) dst) + (count - 1);
+       s0  = src + (count - 1) * fsz;
+
+       if (dsz < count * sizeof(Elf64_Syminfo))
+               return (0);
+
+       while (count--) {
+               s = s0;
+               /* Read an Elf64_Syminfo */
+               READ_HALF(s,t.si_boundto);
+               READ_HALF(s,t.si_flags);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Syminfo */
+                       SWAP_HALF(t.si_boundto);
+                       SWAP_HALF(t.si_flags);
+                       /**/
+               }
+               *d-- = t; s0 -= fsz;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_SYM64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Sym       t, *d;
+       unsigned char   *s,*s0;
+       size_t          fsz;
+
+       fsz = elf64_fsize(ELF_T_SYM, (size_t) 1, EV_CURRENT);
+       d   = ((Elf64_Sym *) (uintptr_t) dst) + (count - 1);
+       s0  = src + (count - 1) * fsz;
+
+       if (dsz < count * sizeof(Elf64_Sym))
+               return (0);
+
+       while (count--) {
+               s = s0;
+               /* Read an Elf64_Sym */
+               READ_WORD(s,t.st_name);
+               READ_BYTE(s,t.st_info);
+               READ_BYTE(s,t.st_other);
+               READ_HALF(s,t.st_shndx);
+               READ_ADDR64(s,t.st_value);
+               READ_XWORD(s,t.st_size);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Sym */
+                       SWAP_WORD(t.st_name);
+                       SWAP_BYTE(t.st_info);
+                       SWAP_BYTE(t.st_other);
+                       SWAP_HALF(t.st_shndx);
+                       SWAP_ADDR64(t.st_value);
+                       SWAP_XWORD(t.st_size);
+                       /**/
+               }
+               *d-- = t; s0 -= fsz;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_WORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Word t, *d = (Elf64_Word *) (uintptr_t) dst;
+       size_t c;
+
+       if (dsz < count * sizeof(Elf64_Word))
+               return (0);
+
+       if (!byteswap) {
+               (void) memcpy(dst, src, count * sizeof(*d));
+               return (1);
+       }
+
+       for (c = 0; c < count; c++) {
+               READ_WORD(src,t);
+               SWAP_WORD(t);
+               *d++ = t;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_XWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Xword t, *d = (Elf64_Xword *) (uintptr_t) dst;
+       size_t c;
+
+       if (dsz < count * sizeof(Elf64_Xword))
+               return (0);
+
+       if (!byteswap) {
+               (void) memcpy(dst, src, count * sizeof(*d));
+               return (1);
+       }
+
+       for (c = 0; c < count; c++) {
+               READ_XWORD(src,t);
+               SWAP_XWORD(t);
+               *d++ = t;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_VDEF64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Verdef    t, *dp;
+       Elf64_Verdaux   a, *ap;
+       const size_t    verfsz = 20;
+       const size_t    auxfsz = 8;
+       const size_t    vermsz = sizeof(Elf64_Verdef);
+       const size_t    auxmsz = sizeof(Elf64_Verdaux);
+       unsigned char * const dstend = dst + dsz;
+       unsigned char * const srcend = src + count;
+       unsigned char   *dstaux, *s, *srcaux, *stmp;
+       Elf64_Word      aux, anext, cnt, vnext;
+
+       for (stmp = src, vnext = ~0U;
+            vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
+            stmp += vnext, dst += vnext) {
+
+               /* Read in a VDEF structure. */
+               s = stmp;
+               /* Read an Elf64_Verdef */
+               READ_HALF(s,t.vd_version);
+               READ_HALF(s,t.vd_flags);
+               READ_HALF(s,t.vd_ndx);
+               READ_HALF(s,t.vd_cnt);
+               READ_WORD(s,t.vd_hash);
+               READ_WORD(s,t.vd_aux);
+               READ_WORD(s,t.vd_next);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Verdef */
+                       SWAP_HALF(t.vd_version);
+                       SWAP_HALF(t.vd_flags);
+                       SWAP_HALF(t.vd_ndx);
+                       SWAP_HALF(t.vd_cnt);
+                       SWAP_WORD(t.vd_hash);
+                       SWAP_WORD(t.vd_aux);
+                       SWAP_WORD(t.vd_next);
+                       /**/
+               }
+
+               dp = (Elf64_Verdef *) (uintptr_t) dst;
+               *dp = t;
+
+               aux = t.vd_aux;
+               cnt = t.vd_cnt;
+               vnext = t.vd_next;
+
+               if (aux < vermsz)
+                       return (0);
+
+               /* Process AUX entries. */
+               for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux;
+                    cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
+                       srcaux + auxfsz <= srcend;
+                    dstaux += anext, srcaux += anext, cnt--) {
+
+                       s = srcaux;
+                       /* Read an Elf64_Verdaux */
+               READ_WORD(s,a.vda_name);
+               READ_WORD(s,a.vda_next);
+               /**/
+
+                       if (byteswap) {
+                               /* Swap an Elf64_Verdaux */
+                       SWAP_WORD(a.vda_name);
+                       SWAP_WORD(a.vda_next);
+                       /**/
+                       }
+
+                       anext = a.vda_next;
+
+                       ap = ((Elf64_Verdaux *) (uintptr_t) dstaux);
+                       *ap = a;
+               }
+
+               if (anext || cnt)
+                       return (0);
+       }
+
+       if (vnext)
+               return (0);
+
+       return (1);
+}
+
+static int
+_libelf_cvt_VNEED64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       Elf64_Verneed   t, *dp;
+       Elf64_Vernaux   a, *ap;
+       const size_t    verfsz = 16;
+       const size_t    auxfsz = 16;
+       const size_t    vermsz = sizeof(Elf64_Verneed);
+       const size_t    auxmsz = sizeof(Elf64_Vernaux);
+       unsigned char * const dstend = dst + dsz;
+       unsigned char * const srcend = src + count;
+       unsigned char   *dstaux, *s, *srcaux, *stmp;
+       Elf64_Word      aux, anext, cnt, vnext;
+
+       for (stmp = src, vnext = ~0U;
+            vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
+            stmp += vnext, dst += vnext) {
+
+               /* Read in a VNEED structure. */
+               s = stmp;
+               /* Read an Elf64_Verneed */
+               READ_HALF(s,t.vn_version);
+               READ_HALF(s,t.vn_cnt);
+               READ_WORD(s,t.vn_file);
+               READ_WORD(s,t.vn_aux);
+               READ_WORD(s,t.vn_next);
+               /**/
+               if (byteswap) {
+                       /* Swap an Elf64_Verneed */
+                       SWAP_HALF(t.vn_version);
+                       SWAP_HALF(t.vn_cnt);
+                       SWAP_WORD(t.vn_file);
+                       SWAP_WORD(t.vn_aux);
+                       SWAP_WORD(t.vn_next);
+                       /**/
+               }
+
+               dp = (Elf64_Verneed *) (uintptr_t) dst;
+               *dp = t;
+
+               aux = t.vn_aux;
+               cnt = t.vn_cnt;
+               vnext = t.vn_next;
+
+               if (aux < vermsz)
+                       return (0);
+
+               /* Process AUX entries. */
+               for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux;
+                    cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
+                       srcaux + auxfsz <= srcend;
+                    dstaux += anext, srcaux += anext, cnt--) {
+
+                       s = srcaux;
+                       /* Read an Elf64_Vernaux */
+               READ_WORD(s,a.vna_hash);
+               READ_HALF(s,a.vna_flags);
+               READ_HALF(s,a.vna_other);
+               READ_WORD(s,a.vna_name);
+               READ_WORD(s,a.vna_next);
+               /**/
+
+                       if (byteswap) {
+                               /* Swap an Elf64_Vernaux */
+                       SWAP_WORD(a.vna_hash);
+                       SWAP_HALF(a.vna_flags);
+                       SWAP_HALF(a.vna_other);
+                       SWAP_WORD(a.vna_name);
+                       SWAP_WORD(a.vna_next);
+                       /**/
+                       }
+
+                       anext = a.vna_next;
+
+                       ap = ((Elf64_Vernaux *) (uintptr_t) dstaux);
+                       *ap = a;
+               }
+
+               if (anext || cnt)
+                       return (0);
+       }
+
+       if (vnext)
+               return (0);
+
+       return (1);
+}
+
+static int
+_libelf_cvt_BYTE_tox(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       (void) byteswap;
+       if (dsz < count)
+               return (0);
+       if (dst != src)
+               (void) memcpy(dst, src, count);
+       return (1);
+}
+
+static int
+_libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t srcsz, int byteswap)
+{
+       size_t sz;
+       uint64_t t64, *bloom64;
+       Elf_GNU_Hash_Header *gh;
+       uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
+       uint32_t *buckets, *chains;
+
+       sz = 4 * sizeof(uint32_t);      /* File header is 4 words long. */
+       if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
+               return (0);
+
+       /* Read in the section header and byteswap if needed. */
+       READ_WORD(src, nbuckets);
+       READ_WORD(src, symndx);
+       READ_WORD(src, maskwords);
+       READ_WORD(src, shift2);
+
+       srcsz -= sz;
+
+       if (byteswap) {
+               SWAP_WORD(nbuckets);
+               SWAP_WORD(symndx);
+               SWAP_WORD(maskwords);
+               SWAP_WORD(shift2);
+       }
+
+       /* Check source buffer and destination buffer sizes. */
+       sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
+       if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
+               return (0);
+
+       gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
+       gh->gh_nbuckets  = nbuckets;
+       gh->gh_symndx    = symndx;
+       gh->gh_maskwords = maskwords;
+       gh->gh_shift2    = shift2;
+
+       dsz -= sizeof(Elf_GNU_Hash_Header);
+       dst += sizeof(Elf_GNU_Hash_Header);
+
+       bloom64 = (uint64_t *) (uintptr_t) dst;
+
+       /* Copy bloom filter data. */
+       for (n = 0; n < maskwords; n++) {
+               READ_XWORD(src, t64);
+               if (byteswap)
+                       SWAP_XWORD(t64);
+               bloom64[n] = t64;
+       }
+
+       /* The hash buckets follows the bloom filter. */
+       dst += maskwords * sizeof(uint64_t);
+       buckets = (uint32_t *) (uintptr_t) dst;
+
+       for (n = 0; n < nbuckets; n++) {
+               READ_WORD(src, t32);
+               if (byteswap)
+                       SWAP_WORD(t32);
+               buckets[n] = t32;
+       }
+
+       dst += nbuckets * sizeof(uint32_t);
+
+       /* The hash chain follows the hash buckets. */
+       dsz -= sz;
+       srcsz -= sz;
+
+       if (dsz < srcsz)        /* Destination lacks space. */
+               return (0);
+
+       nchains = srcsz / sizeof(uint32_t);
+       chains = (uint32_t *) (uintptr_t) dst;
+
+       for (n = 0; n < nchains; n++) {
+               READ_WORD(src, t32);
+               if (byteswap)
+                       SWAP_WORD(t32);
+               *chains++ = t32;
+       }
+
+       return (1);
+}
+
+static int
+_libelf_cvt_NOTE_tom(unsigned char *dst, size_t dsz, unsigned char *src,
+    size_t count, int byteswap)
+{
+       uint32_t namesz, descsz, type;
+       Elf_Note *en;
+       size_t sz, hdrsz;
+
+       if (dsz < count)        /* Destination buffer is too small. */
+               return (0);
+
+       hdrsz = 3 * sizeof(uint32_t);
+       if (count < hdrsz)              /* Source too small. */
+               return (0);
+
+       if (!byteswap) {
+               (void) memcpy(dst, src, count);
+               return (1);
+       }
+
+       /* Process all notes in the section. */
+       while (count > hdrsz) {
+               /* Read the note header. */
+               READ_WORD(src, namesz);
+               READ_WORD(src, descsz);
+               READ_WORD(src, type);
+
+               /* Translate. */
+               SWAP_WORD(namesz);
+               SWAP_WORD(descsz);
+               SWAP_WORD(type);
+
+               /* Copy out the translated note header. */
+               en = (Elf_Note *) (uintptr_t) dst;
+               en->n_namesz = namesz;
+               en->n_descsz = descsz;
+               en->n_type = type;
+
+               dsz -= sizeof(Elf_Note);
+               dst += sizeof(Elf_Note);
+               count -= hdrsz;
+
+               ROUNDUP2(namesz, 4U);
+               ROUNDUP2(descsz, 4U);
+
+               sz = namesz + descsz;
+
+               if (count < sz || dsz < sz)     /* Buffers are too small. */
+                       return (0);
+
+               (void) memcpy(dst, src, sz);
+
+               src += sz;
+               dst += sz;
+
+               count -= sz;
+               dsz -= sz;
+       }
+
+       return (1);
+}
+
+struct converters {
+       int     (*tof32)(unsigned char *dst, size_t dsz, unsigned char *src,
+                   size_t cnt, int byteswap);
+       int     (*tom32)(unsigned char *dst, size_t dsz, unsigned char *src,
+                   size_t cnt, int byteswap);
+       int     (*tof64)(unsigned char *dst, size_t dsz, unsigned char *src,
+                   size_t cnt, int byteswap);
+       int     (*tom64)(unsigned char *dst, size_t dsz, unsigned char *src,
+                   size_t cnt, int byteswap);
+};
+
+static struct converters cvt[ELF_T_NUM] = {
+       /*[*/
+       [ELF_T_ADDR] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_ADDR64_tom },
+       [ELF_T_CAP] =     { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_CAP64_tom },
+       [ELF_T_DYN] =     { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_DYN64_tom },
+       [ELF_T_EHDR] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_EHDR64_tom },
+       [ELF_T_GNUHASH] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_GNUHASH64_tom },
+       [ELF_T_HALF] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_HALF_tom },
+       [ELF_T_LWORD] =   { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_LWORD_tom },
+       [ELF_T_MOVE] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_MOVE64_tom },
+       [ELF_T_OFF] =     { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_OFF64_tom },
+       [ELF_T_PHDR] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_PHDR64_tom },
+       [ELF_T_REL] =     { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_REL64_tom },
+       [ELF_T_RELA] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_RELA64_tom },
+       [ELF_T_SHDR] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_SHDR64_tom },
+       [ELF_T_SWORD] =   { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_SWORD_tom },
+       [ELF_T_SXWORD] =  { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_SXWORD_tom },
+       [ELF_T_SYMINFO] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_SYMINFO64_tom },
+       [ELF_T_SYM] =     { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_SYM64_tom },
+       [ELF_T_VDEF] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_VDEF64_tom },
+       [ELF_T_VNEED] =   { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_VNEED64_tom },
+       [ELF_T_WORD] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_WORD_tom },
+       [ELF_T_XWORD] =   { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_XWORD_tom },
+       /*]*/
+       /*
+        * Types that need hand-coded converters follow.
+        */
+       [ELF_T_BYTE] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_BYTE_tox },
+       [ELF_T_NOTE] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
+               .tom64 = _libelf_cvt_NOTE_tom }
+};
+
+static int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
+ (unsigned char *_dst, size_t dsz, unsigned char *_src, size_t _cnt,
+  int _byteswap)
+{
+       assert(/* elfclass == ELFCLASS32 || */ elfclass == ELFCLASS64);
+       assert(/* direction == ELF_TOFILE || */ direction == ELF_TOMEMORY);
+
+       if (t >= ELF_T_NUM ||
+           (/* elfclass != ELFCLASS32 && */ elfclass != ELFCLASS64) ||
+           (/* direction != ELF_TOFILE && */ direction != ELF_TOMEMORY))
+               return (NULL);
+
+#if 1
+       return cvt[t].tom64;
+#else
+       return ((elfclass == ELFCLASS32) ?
+           (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
+           (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));
+#endif
+}
+
+/* libelf_ehdr.h */
+/*
+ * Retrieve counts for sections, phdrs and the section string table index
+ * from section header #0 of the ELF object.
+ */
+static int
+_libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
+    uint16_t strndx)
+{
+       Elf_Scn *scn;
+       size_t fsz;
+       int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
+           size_t _c, int _swap);
+       uint32_t shtype;
+
+       assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
+
+       fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1);
+       assert(fsz > 0);
+
+       if (e->e_rawsize < shoff + fsz) { /* raw file too small */
+               LIBELF_SET_ERROR(HEADER, 0);
+               return (0);
+       }
+
+       if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL)
+               return (0);
+
+       xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
+       (*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
+           (unsigned char *) e->e_rawfile + shoff, (size_t) 1,
+           e->e_byteorder != LIBELF_PRIVATE(byteorder));
+
+#define        GET_SHDR_MEMBER(M) (/* (ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M :*/ \
+               scn->s_shdr.s_shdr64.M)
+
+       if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) {
+               LIBELF_SET_ERROR(SECTION, 0);
+               return (0);
+       }
+
+       e->e_u.e_elf.e_nscn = (size_t) GET_SHDR_MEMBER(sh_size);
+       e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum :
+           GET_SHDR_MEMBER(sh_info);
+       e->e_u.e_elf.e_strndx = (strndx != SHN_XINDEX) ? strndx :
+           GET_SHDR_MEMBER(sh_link);
+#undef GET_SHDR_MEMBER
+
+       return (1);
+}
+
+#define        EHDR_INIT(E,SZ)  do {                                           \
+               Elf##SZ##_Ehdr *eh = (E);                               \
+               eh->e_ident[EI_MAG0] = ELFMAG0;                         \
+               eh->e_ident[EI_MAG1] = ELFMAG1;                         \
+               eh->e_ident[EI_MAG2] = ELFMAG2;                         \
+               eh->e_ident[EI_MAG3] = ELFMAG3;                         \
+               eh->e_ident[EI_CLASS] = ELFCLASS##SZ;                   \
+               eh->e_ident[EI_DATA]  = ELFDATANONE;                    \
+               eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version) & 0xFFU; \
+               eh->e_machine = EM_NONE;                                \
+               eh->e_type    = ELF_K_NONE;                             \
+               eh->e_version = LIBELF_PRIVATE(version);                \
+       } while (0)
+
+static void *
+_libelf_ehdr(Elf *e, int ec, int allocate)
+{
+       void *ehdr;
+       size_t fsz, msz;
+       uint16_t phnum, shnum, strndx;
+       uint64_t shoff;
+       int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
+           size_t _c, int _swap);
+
+       assert(ec == ELFCLASS32 || ec == ELFCLASS64);
+
+       if (e == NULL || e->e_kind != ELF_K_ELF) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       if (e->e_class != ELFCLASSNONE && e->e_class != ec) {
+               LIBELF_SET_ERROR(CLASS, 0);
+               return (NULL);
+       }
+
+       if (e->e_version != EV_CURRENT) {
+               LIBELF_SET_ERROR(VERSION, 0);
+               return (NULL);
+       }
+
+       if (e->e_class == ELFCLASSNONE)
+               e->e_class = ec;
+
+#if 0
+       if (ec == ELFCLASS32)
+               ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr32;
+       else
+#endif
+               ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr64;
+
+       if (ehdr != NULL)       /* already have a translated ehdr */
+               return (ehdr);
+
+       fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
+       assert(fsz > 0);
+
+       if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) {
+               LIBELF_SET_ERROR(HEADER, 0);
+               return (NULL);
+       }
+
+       msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT);
+
+       assert(msz > 0);
+
+       if ((ehdr = calloc((size_t) 1, msz)) == NULL) {
+               LIBELF_SET_ERROR(RESOURCE, 0);
+               return (NULL);
+       }
+
+#if 0
+       if (ec == ELFCLASS32) {
+               e->e_u.e_elf.e_ehdr.e_ehdr32 = ehdr;
+               EHDR_INIT(ehdr,32);
+       } else
+#endif
+       {
+               e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr;
+               EHDR_INIT(ehdr,64);
+       }
+
+       if (allocate)
+               e->e_flags |= ELF_F_DIRTY;
+
+       if (e->e_cmd == ELF_C_WRITE)
+               return (ehdr);
+
+       xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec);
+       (*xlator)((unsigned char*) ehdr, msz, e->e_rawfile, (size_t) 1,
+           e->e_byteorder != LIBELF_PRIVATE(byteorder));
+
+       /*
+        * If extended numbering is being used, read the correct
+        * number of sections and program header entries.
+        */
+#if 0
+       if (ec == ELFCLASS32) {
+               phnum = ((Elf32_Ehdr *) ehdr)->e_phnum;
+               shnum = ((Elf32_Ehdr *) ehdr)->e_shnum;
+               shoff = ((Elf32_Ehdr *) ehdr)->e_shoff;
+               strndx = ((Elf32_Ehdr *) ehdr)->e_shstrndx;
+       } else
+#endif
+       {
+               phnum = ((Elf64_Ehdr *) ehdr)->e_phnum;
+               shnum = ((Elf64_Ehdr *) ehdr)->e_shnum;
+               shoff = ((Elf64_Ehdr *) ehdr)->e_shoff;
+               strndx = ((Elf64_Ehdr *) ehdr)->e_shstrndx;
+       }
+
+       if (shnum >= SHN_LORESERVE ||
+           (shoff == 0LL && (shnum != 0 || phnum == PN_XNUM ||
+               strndx == SHN_XINDEX))) {
+               LIBELF_SET_ERROR(HEADER, 0);
+               return (NULL);
+       }
+
+       if (shnum != 0 || shoff == 0LL) { /* not using extended numbering */
+               e->e_u.e_elf.e_nphdr = phnum;
+               e->e_u.e_elf.e_nscn = shnum;
+               e->e_u.e_elf.e_strndx = strndx;
+       } else if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0)
+               return (NULL);
+
+       return (ehdr);
+}
+
+/* libelf_shdr.c */
+static void *
+_libelf_getshdr(Elf_Scn *s, int ec)
+{
+       Elf *e;
+
+       if (s == NULL || (e = s->s_elf) == NULL ||
+           e->e_kind != ELF_K_ELF) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       if (ec == ELFCLASSNONE)
+               ec = e->e_class;
+
+       if (ec != e->e_class) {
+               LIBELF_SET_ERROR(CLASS, 0);
+               return (NULL);
+       }
+
+       return ((void *) &s->s_shdr);
+}
+
+/* elf_scn.c */
+static int
+_libelf_load_section_headers(Elf *e, void *ehdr)
+{
+       Elf_Scn *scn;
+       uint64_t shoff;
+#if 0
+       Elf32_Ehdr *eh32;
+#endif
+       Elf64_Ehdr *eh64;
+       int ec, swapbytes;
+       unsigned char *src;
+       size_t fsz, i, shnum;
+       int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
+           size_t _c, int _swap);
+
+       assert(e != NULL);
+       assert(ehdr != NULL);
+       assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0);
+
+#define        CHECK_EHDR(E,EH)        do {                            \
+               if (shoff > e->e_rawsize ||                     \
+                   fsz != (EH)->e_shentsize ||                 \
+                   shnum > SIZE_MAX / fsz ||                   \
+                   fsz * shnum > e->e_rawsize - shoff) {       \
+                       LIBELF_SET_ERROR(HEADER, 0);            \
+                       return (0);                             \
+               }                                               \
+       } while (0)
+
+       ec = e->e_class;
+       fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
+       assert(fsz > 0);
+
+       shnum = e->e_u.e_elf.e_nscn;
+
+#if 0
+       if (ec == ELFCLASS32) {
+               eh32 = (Elf32_Ehdr *) ehdr;
+               shoff = (uint64_t) eh32->e_shoff;
+               CHECK_EHDR(e, eh32);
+       } else
+#endif
+       {
+               eh64 = (Elf64_Ehdr *) ehdr;
+               shoff = eh64->e_shoff;
+               CHECK_EHDR(e, eh64);
+       }
+
+       xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
+
+       swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder);
+       src = e->e_rawfile + shoff;
+
+       /*
+        * If the file is using extended numbering then section #0
+        * would have already been read in.
+        */
+
+       i = 0;
+       if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
+               assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) ==
+                   STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next));
+
+               i = 1;
+               src += fsz;
+       }
+
+       for (; i < shnum; i++, src += fsz) {
+               if ((scn = _libelf_allocate_scn(e, i)) == NULL)
+                       return (0);
+
+               (*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
+                   src, (size_t) 1, swapbytes);
+
+#if 0
+               if (ec == ELFCLASS32) {
+                       scn->s_offset = scn->s_rawoff =
+                           scn->s_shdr.s_shdr32.sh_offset;
+                       scn->s_size = scn->s_shdr.s_shdr32.sh_size;
+               } else
+#endif
+               {
+                       scn->s_offset = scn->s_rawoff =
+                           scn->s_shdr.s_shdr64.sh_offset;
+                       scn->s_size = scn->s_shdr.s_shdr64.sh_size;
+               }
+       }
+
+       e->e_flags |= LIBELF_F_SHDRS_LOADED;
+
+       return (1);
+}
+
+static Elf_Scn *
+elf_getscn(Elf *e, size_t index)
+{
+       int ec;
+       void *ehdr;
+       Elf_Scn *s;
+
+       if (e == NULL || e->e_kind != ELF_K_ELF ||
+           ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
+               return (NULL);
+
+       if (e->e_cmd != ELF_C_WRITE &&
+           (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 &&
+           _libelf_load_section_headers(e, ehdr) == 0)
+               return (NULL);
+
+       STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next)
+               if (s->s_ndx == index)
+                       return (s);
+
+       LIBELF_SET_ERROR(ARGUMENT, 0);
+       return (NULL);
+}
+
+/* libelf_memory.c */
+static Elf *
+_libelf_memory(unsigned char *image, size_t sz, int reporterror)
+{
+       Elf *e;
+       int e_class;
+       enum Elf_Error error;
+       unsigned int e_byteorder, e_version;
+
+       assert(image != NULL);
+       assert(sz > 0);
+
+       if ((e = _libelf_allocate_elf()) == NULL)
+               return (NULL);
+
+       e->e_cmd = ELF_C_READ;
+       e->e_rawfile = image;
+       e->e_rawsize = sz;
+
+#undef LIBELF_IS_ELF
+#define        LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 &&            \
+       (P)[EI_MAG1] == ELFMAG1 && (P)[EI_MAG2] == ELFMAG2 &&   \
+       (P)[EI_MAG3] == ELFMAG3)
+
+       if (sz > EI_NIDENT && LIBELF_IS_ELF(image)) {
+               e_byteorder = image[EI_DATA];
+               e_class     = image[EI_CLASS];
+               e_version   = image[EI_VERSION];
+
+               error = ELF_E_NONE;
+
+               if (e_version > EV_CURRENT)
+                       error = ELF_E_VERSION;
+               else if ((e_byteorder != ELFDATA2LSB && e_byteorder !=
+                   ELFDATA2MSB) || (e_class != ELFCLASS32 && e_class !=
+                   ELFCLASS64))
+                       error = ELF_E_HEADER;
+
+               if (error != ELF_E_NONE) {
+                       if (reporterror) {
+                               LIBELF_PRIVATE(error) = LIBELF_ERROR(error, 0);
+                               (void) _libelf_release_elf(e);
+                               return (NULL);
+                       }
+               } else {
+                       _libelf_init_elf(e, ELF_K_ELF);
+
+                       e->e_byteorder = e_byteorder;
+                       e->e_class = e_class;
+                       e->e_version = e_version;
+               }
+       }
+#if 0
+       else if (sz >= SARMAG &&
+           strncmp((const char *) image, ARMAG, (size_t) SARMAG) == 0)
+               return (_libelf_ar_open(e, reporterror));
+#endif
+
+       return (e);
+}
+
+/* libelf_open.c */
+#define        _LIBELF_INITSIZE        (64*1024)
+
+static void *
+_libelf_read_special_file(int fd, size_t *fsz)
+{
+       ssize_t readsz;
+       size_t bufsz, datasz;
+       unsigned char *buf, *t;
+
+       datasz = 0;
+       readsz = 0;
+       bufsz = _LIBELF_INITSIZE;
+       if ((buf = malloc(bufsz)) == NULL)
+               goto resourceerror;
+
+       /*
+        * Read data from the file descriptor till we reach EOF, or
+        * till an error is encountered.
+        */
+       do {
+               /* Check if we need to expand the data buffer. */
+               if (datasz == bufsz) {
+                       bufsz *= 2;
+                       if ((t = realloc(buf, bufsz)) == NULL)
+                               goto resourceerror;
+                       buf = t;
+               }
+
+               do {
+                       assert(bufsz - datasz > 0);
+                       t = buf + datasz;
+                       if ((readsz = read(fd, t, bufsz - datasz)) <= 0)
+                               break;
+                       datasz += (size_t) readsz;
+               } while (datasz < bufsz);
+
+       } while (readsz > 0);
+
+       if (readsz < 0) {
+               LIBELF_SET_ERROR(IO, errno);
+               goto error;
+       }
+
+       assert(readsz == 0);
+
+       /*
+        * Free up extra buffer space.
+        */
+       if (bufsz > datasz) {
+               if (datasz > 0) {
+                       if ((t = realloc(buf, datasz)) == NULL)
+                               goto resourceerror;
+                       buf = t;
+               } else {        /* Zero bytes read. */
+                       LIBELF_SET_ERROR(ARGUMENT, 0);
+                       free(buf);
+                       buf = NULL;
+               }
+       }
+
+       *fsz = datasz;
+       return (buf);
+
+resourceerror:
+       LIBELF_SET_ERROR(RESOURCE, 0);
+error:
+       if (buf != NULL)
+               free(buf);
+       return (NULL);
+}
+
+static Elf *
+_libelf_open_object(int fd, Elf_Cmd c, int reporterror)
+{
+       Elf *e;
+       void *m;
+       mode_t mode;
+       size_t fsize;
+       struct stat sb;
+       unsigned int flags;
+
+       assert(c == ELF_C_READ || c == ELF_C_RDWR || c == ELF_C_WRITE);
+
+       if (fstat(fd, &sb) < 0) {
+               LIBELF_SET_ERROR(IO, errno);
+               return (NULL);
+       }
+
+       mode = sb.st_mode;
+       fsize = (size_t) sb.st_size;
+
+       /*
+        * Reject unsupported file types.
+        */
+       if (!S_ISREG(mode) && !S_ISCHR(mode) && !S_ISFIFO(mode) &&
+           !S_ISSOCK(mode)) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       /*
+        * For ELF_C_WRITE mode, allocate and return a descriptor.
+        */
+       if (c == ELF_C_WRITE) {
+               if ((e = _libelf_allocate_elf()) != NULL) {
+                       _libelf_init_elf(e, ELF_K_ELF);
+                       e->e_byteorder = LIBELF_PRIVATE(byteorder);
+                       e->e_fd = fd;
+                       e->e_cmd = c;
+                       if (!S_ISREG(mode))
+                               e->e_flags |= LIBELF_F_SPECIAL_FILE;
+               }
+
+               return (e);
+       }
+
+
+       /*
+        * ELF_C_READ and ELF_C_RDWR mode.
+        */
+       m = NULL;
+       flags = 0;
+       if (S_ISREG(mode)) {
+
+               /*
+                * Reject zero length files.
+                */
+               if (fsize == 0) {
+                       LIBELF_SET_ERROR(ARGUMENT, 0);
+                       return (NULL);
+               }
+
+#if    ELFTC_HAVE_MMAP
+               /*
+                * Always map regular files in with 'PROT_READ'
+                * permissions.
+                *
+                * For objects opened in ELF_C_RDWR mode, when
+                * elf_update(3) is called, we remove this mapping,
+                * write file data out using write(2), and map the new
+                * contents back.
+                */
+               m = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, (off_t) 0);
+
+               if (m == MAP_FAILED)
+                       m = NULL;
+               else
+                       flags = LIBELF_F_RAWFILE_MMAP;
+#endif
+
+               /*
+                * Fallback to a read() if the call to mmap() failed,
+                * or if mmap() is not available.
+                */
+               if (m == NULL) {
+                       if ((m = malloc(fsize)) == NULL) {
+                               LIBELF_SET_ERROR(RESOURCE, 0);
+                               return (NULL);
+                       }
+
+                       if (read(fd, m, fsize) != (ssize_t) fsize) {
+                               LIBELF_SET_ERROR(IO, errno);
+                               free(m);
+                               return (NULL);
+                       }
+
+                       flags = LIBELF_F_RAWFILE_MALLOC;
+               }
+       } else if ((m = _libelf_read_special_file(fd, &fsize)) != NULL)
+               flags = LIBELF_F_RAWFILE_MALLOC | LIBELF_F_SPECIAL_FILE;
+       else
+               return (NULL);
+
+       if ((e = _libelf_memory(m, fsize, reporterror)) == NULL) {
+               assert((flags & LIBELF_F_RAWFILE_MALLOC) ||
+                   (flags & LIBELF_F_RAWFILE_MMAP));
+               if (flags & LIBELF_F_RAWFILE_MALLOC)
+                       free(m);
+#if    ELFTC_HAVE_MMAP
+               else
+                       (void) munmap(m, fsize);
+#endif
+               return (NULL);
+       }
+
+       /* ar(1) archives aren't supported in RDWR mode. */
+#if 0
+       if (c == ELF_C_RDWR && e->e_kind == ELF_K_AR) {
+               (void) elf_end(e);
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+#endif
+
+       e->e_flags |= flags;
+       e->e_fd = fd;
+       e->e_cmd = c;
+
+       return (e);
+}
+
+static const char *_libelf_errors[] = {
+#define        DEFINE_ERROR(N,S)       [ELF_E_##N] = S
+       DEFINE_ERROR(NONE,      "No Error"),
+       DEFINE_ERROR(ARCHIVE,   "Malformed ar(1) archive"),
+       DEFINE_ERROR(ARGUMENT,  "Invalid argument"),
+       DEFINE_ERROR(CLASS,     "ELF class mismatch"),
+       DEFINE_ERROR(DATA,      "Invalid data buffer descriptor"),
+       DEFINE_ERROR(HEADER,    "Missing or malformed ELF header"),
+       DEFINE_ERROR(IO,        "I/O error"),
+       DEFINE_ERROR(LAYOUT,    "Layout constraint violation"),
+       DEFINE_ERROR(MODE,      "Incorrect ELF descriptor mode"),
+       DEFINE_ERROR(RANGE,     "Value out of range of target"),
+       DEFINE_ERROR(RESOURCE,  "Resource exhaustion"),
+       DEFINE_ERROR(SECTION,   "Invalid section descriptor"),
+       DEFINE_ERROR(SEQUENCE,  "API calls out of sequence"),
+       DEFINE_ERROR(UNIMPL,    "Unimplemented feature"),
+       DEFINE_ERROR(VERSION,   "Unknown ELF API version"),
+       DEFINE_ERROR(NUM,       "Unknown error")
+#undef DEFINE_ERROR
+};
+
+/* PUBLIC */
+
+/* elf_errmsg.c */
+static const char *
+elf_errmsg(int error)
+{
+       int oserr;
+
+       if (error == ELF_E_NONE &&
+           (error = LIBELF_PRIVATE(error)) == 0)
+           return NULL;
+       else if (error == -1)
+           error = LIBELF_PRIVATE(error);
+
+       oserr = error >> LIBELF_OS_ERROR_SHIFT;
+       error &= LIBELF_ELF_ERROR_MASK;
+
+       if (error < ELF_E_NONE || error >= ELF_E_NUM)
+               return _libelf_errors[ELF_E_NUM];
+       if (oserr) {
+               (void) snprintf((char *) LIBELF_PRIVATE(msg),
+                   sizeof(LIBELF_PRIVATE(msg)), "%s: %s",
+                   _libelf_errors[error], strerror(oserr));
+               return (const char *)&LIBELF_PRIVATE(msg);
+       }
+       return _libelf_errors[error];
+}
+
+/* elf_errno.c */
+static int
+elf_errno(void)
+{
+       int old;
+
+       old = LIBELF_PRIVATE(error);
+       LIBELF_PRIVATE(error) = 0;
+       return (old & LIBELF_ELF_ERROR_MASK);
+}
+
+/* elf_version.c */
+static unsigned int
+elf_version(unsigned int v)
+{
+       unsigned int old;
+
+       if ((old = LIBELF_PRIVATE(version)) == EV_NONE)
+               old = EV_CURRENT;
+
+       if (v == EV_NONE)
+               return old;
+       if (v > EV_CURRENT) {
+               LIBELF_SET_ERROR(VERSION, 0);
+               return EV_NONE;
+       }
+
+       LIBELF_PRIVATE(version) = v;
+       return (old);
+}
+
+/* elf_begin.c */
+static Elf *
+elf_begin(int fd, Elf_Cmd c, Elf *a)
+{
+       Elf *e;
+
+       e = NULL;
+
+       if (LIBELF_PRIVATE(version) == EV_NONE) {
+               LIBELF_SET_ERROR(SEQUENCE, 0);
+               return (NULL);
+       }
+
+       switch (c) {
+       case ELF_C_NULL:
+               return (NULL);
+
+       case ELF_C_WRITE:
+               /*
+                * The ELF_C_WRITE command is required to ignore the
+                * descriptor passed in.
+                */
+               a = NULL;
+               break;
+
+       case ELF_C_RDWR:
+               if (a != NULL) { /* not allowed for ar(1) archives. */
+                       LIBELF_SET_ERROR(ARGUMENT, 0);
+                       return (NULL);
+               }
+               /*FALLTHROUGH*/
+       case ELF_C_READ:
+               /*
+                * Descriptor `a' could be for a regular ELF file, or
+                * for an ar(1) archive.  If descriptor `a' was opened
+                * using a valid file descriptor, we need to check if
+                * the passed in `fd' value matches the original one.
+                */
+               if (a &&
+                   ((a->e_fd != -1 && a->e_fd != fd) || c != a->e_cmd)) {
+                       LIBELF_SET_ERROR(ARGUMENT, 0);
+                       return (NULL);
+               }
+               break;
+
+       default:
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+
+       }
+
+       if (a == NULL)
+               e = _libelf_open_object(fd, c, 1);
+#if 0
+       else if (a->e_kind == ELF_K_AR)
+               e = _libelf_ar_open_member(a->e_fd, c, a);
+#endif
+       else
+               (e = a)->e_activations++;
+
+       return (e);
+}
+
+/* elf_end.c */
+static int
+elf_end(Elf *e)
+{
+       Elf *sv;
+       Elf_Scn *scn, *tscn;
+
+       if (e == NULL || e->e_activations == 0)
+               return (0);
+
+       if (--e->e_activations > 0)
+               return (e->e_activations);
+
+       assert(e->e_activations == 0);
+
+       while (e && e->e_activations == 0) {
+               switch (e->e_kind) {
+               case ELF_K_AR:
+                       /*
+                        * If we still have open child descriptors, we
+                        * need to defer reclaiming resources till all
+                        * the child descriptors for the archive are
+                        * closed.
+                        */
+                       if (e->e_u.e_ar.e_nchildren > 0)
+                               return (0);
+                       break;
+               case ELF_K_ELF:
+                       /*
+                        * Reclaim all section descriptors.
+                        */
+                       STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next,
+                           tscn)
+                               scn = _libelf_release_scn(scn);
+                       break;
+               case ELF_K_NUM:
+                       assert(0);
+               default:
+                       break;
+               }
+
+               if (e->e_rawfile) {
+                       if (e->e_flags & LIBELF_F_RAWFILE_MALLOC)
+                               free(e->e_rawfile);
+#if    ELFTC_HAVE_MMAP
+                       else if (e->e_flags & LIBELF_F_RAWFILE_MMAP)
+                               (void) munmap(e->e_rawfile, e->e_rawsize);
+#endif
+               }
+
+               sv = e;
+               if ((e = e->e_parent) != NULL)
+                       e->e_u.e_ar.e_nchildren--;
+               sv = _libelf_release_elf(sv);
+       }
+
+       return (0);
+}
+
+/* gelf_shdr.c */
+static GElf_Shdr *
+gelf_getshdr(Elf_Scn *s, GElf_Shdr *d)
+{
+       int ec;
+       void *sh;
+#if 0
+       Elf32_Shdr *sh32;
+#endif
+       Elf64_Shdr *sh64;
+
+       if (d == NULL) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL)
+               return (NULL);
+
+       ec = s->s_elf->e_class;
+       assert(/* ec == ELFCLASS32 || */ ec == ELFCLASS64);
+
+#if 0
+       if (ec == ELFCLASS32) {
+               sh32 = (Elf32_Shdr *) sh;
+
+               d->sh_name      = sh32->sh_name;
+               d->sh_type      = sh32->sh_type;
+               d->sh_flags     = (Elf64_Xword) sh32->sh_flags;
+               d->sh_addr      = (Elf64_Addr) sh32->sh_addr;
+               d->sh_offset    = (Elf64_Off) sh32->sh_offset;
+               d->sh_size      = (Elf64_Xword) sh32->sh_size;
+               d->sh_link      = sh32->sh_link;
+               d->sh_info      = sh32->sh_info;
+               d->sh_addralign = (Elf64_Xword) sh32->sh_addralign;
+               d->sh_entsize   = (Elf64_Xword) sh32->sh_entsize;
+       } else
+#endif
+       {
+               sh64 = (Elf64_Shdr *) sh;
+               *d = *sh64;
+       }
+
+       return (d);
+}
+
+/* gelf_sym.c */
+static GElf_Sym *
+gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst)
+{
+       int ec;
+       Elf *e;
+       size_t msz;
+       Elf_Scn *scn;
+       uint32_t sh_type;
+#if 0
+       Elf32_Sym *sym32;
+#endif
+       Elf64_Sym *sym64;
+       struct _Libelf_Data *d;
+
+       d = (struct _Libelf_Data *) ed;
+
+       if (d == NULL || ndx < 0 || dst == NULL ||
+           (scn = d->d_scn) == NULL ||
+           (e = scn->s_elf) == NULL) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       ec = e->e_class;
+       assert(/* ec == ELFCLASS32 || */ ec == ELFCLASS64);
+
+#if 0
+       if (ec == ELFCLASS32)
+               sh_type = scn->s_shdr.s_shdr32.sh_type;
+       else
+#endif
+               sh_type = scn->s_shdr.s_shdr64.sh_type;
+
+       if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);
+
+       assert(msz > 0);
+       assert(ndx >= 0);
+
+       if (msz * (size_t) ndx >= d->d_data.d_size) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+#if 0
+       if (ec == ELFCLASS32) {
+               sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx;
+
+               dst->st_name  = sym32->st_name;
+               dst->st_value = (Elf64_Addr) sym32->st_value;
+               dst->st_size  = (Elf64_Xword) sym32->st_size;
+               dst->st_info  = sym32->st_info;
+               dst->st_other = sym32->st_other;
+               dst->st_shndx = sym32->st_shndx;
+       } else
+#endif
+       {
+               sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx;
+
+               *dst = *sym64;
+       }
+
+       return (dst);
+}
+
+/* elf_scn.c */
+static Elf_Scn *
+elf_nextscn(Elf *e, Elf_Scn *s)
+{
+       if (e == NULL || (e->e_kind != ELF_K_ELF) ||
+           (s && s->s_elf != e)) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       return (s == NULL ? elf_getscn(e, (size_t) 1) :
+           STAILQ_NEXT(s, s_next));
+}
+
+/* elf_strptr.c */
+static char *
+elf_strptr(Elf *e, size_t scndx, size_t offset)
+{
+       Elf_Scn *s;
+       Elf_Data *d;
+       GElf_Shdr shdr;
+       uint64_t alignment, count;
+
+       if (e == NULL || e->e_kind != ELF_K_ELF) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       if ((s = elf_getscn(e, scndx)) == NULL ||
+           gelf_getshdr(s, &shdr) == NULL)
+               return (NULL);
+
+       if (shdr.sh_type != SHT_STRTAB ||
+           offset >= shdr.sh_size) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       d = NULL;
+       if (e->e_flags & ELF_F_LAYOUT) {
+
+               /*
+                * The application is taking responsibility for the
+                * ELF object's layout, so we can directly translate
+                * an offset to a `char *' address using the `d_off'
+                * members of Elf_Data descriptors.
+                */
+               while ((d = elf_getdata(s, d)) != NULL) {
+
+                       if (d->d_buf == 0 || d->d_size == 0)
+                               continue;
+
+                       if (d->d_type != ELF_T_BYTE) {
+                               LIBELF_SET_ERROR(DATA, 0);
+                               return (NULL);
+                       }
+
+                       if (offset >= d->d_off &&
+                           offset < d->d_off + d->d_size)
+                               return ((char *) d->d_buf + offset - d->d_off);
+               }
+       } else {
+               /*
+                * Otherwise, the `d_off' members are not useable and
+                * we need to compute offsets ourselves, taking into
+                * account 'holes' in coverage of the section introduced
+                * by alignment requirements.
+                */
+               count = (uint64_t) 0;   /* cumulative count of bytes seen */
+               while ((d = elf_getdata(s, d)) != NULL && count <= offset) {
+
+                       if (d->d_buf == NULL || d->d_size == 0)
+                               continue;
+
+                       if (d->d_type != ELF_T_BYTE) {
+                               LIBELF_SET_ERROR(DATA, 0);
+                               return (NULL);
+                       }
+
+                       if ((alignment = d->d_align) > 1) {
+                               if ((alignment & (alignment - 1)) != 0) {
+                                       LIBELF_SET_ERROR(DATA, 0);
+                                       return (NULL);
+                               }
+                               count = roundup2(count, alignment);
+                       }
+
+                       if (offset < count) {
+                               /* offset starts in the 'hole' */
+                               LIBELF_SET_ERROR(ARGUMENT, 0);
+                               return (NULL);
+                       }
+
+                       if (offset < count + d->d_size) {
+                               if (d->d_buf != NULL)
+                                       return ((char *) d->d_buf +
+                                           offset - count);
+                               LIBELF_SET_ERROR(DATA, 0);
+                               return (NULL);
+                       }
+
+                       count += d->d_size;
+               }
+       }
+
+       LIBELF_SET_ERROR(ARGUMENT, 0);
+       return (NULL);
+}
+
+/* elf_data.c */
+static Elf_Data *
+elf_getdata(Elf_Scn *s, Elf_Data *ed)
+{
+       Elf *e;
+       unsigned int sh_type;
+       int elfclass, elftype;
+       size_t count, fsz, msz;
+       struct _Libelf_Data *d;
+       uint64_t sh_align, sh_offset, sh_size;
+       int (*xlate)(unsigned char *_d, size_t _dsz, unsigned char *_s,
+           size_t _c, int _swap);
+
+       d = (struct _Libelf_Data *) ed;
+
+       if (s == NULL || (e = s->s_elf) == NULL ||
+           (d != NULL && s != d->d_scn)) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       assert(e->e_kind == ELF_K_ELF);
+
+       if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)
+               return (&d->d_data);
+
+       if (d != NULL)
+               return (&STAILQ_NEXT(d, d_next)->d_data);
+
+       if (e->e_rawfile == NULL) {
+               /*
+                * In the ELF_C_WRITE case, there is no source that
+                * can provide data for the section.
+                */
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       elfclass = e->e_class;
+
+       assert(/* elfclass == ELFCLASS32 || */ elfclass == ELFCLASS64);
+
+#if 0
+       if (elfclass == ELFCLASS32) {
+               sh_type   = s->s_shdr.s_shdr32.sh_type;
+               sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
+               sh_size   = (uint64_t) s->s_shdr.s_shdr32.sh_size;
+               sh_align  = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
+       } else
+#endif
+       {
+               sh_type   = s->s_shdr.s_shdr64.sh_type;
+               sh_offset = s->s_shdr.s_shdr64.sh_offset;
+               sh_size   = s->s_shdr.s_shdr64.sh_size;
+               sh_align  = s->s_shdr.s_shdr64.sh_addralign;
+       }
+
+       if (sh_type == SHT_NULL) {
+               LIBELF_SET_ERROR(SECTION, 0);
+               return (NULL);
+       }
+
+       if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
+           elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
+           sh_offset + sh_size > (uint64_t) e->e_rawsize)) {
+               LIBELF_SET_ERROR(SECTION, 0);
+               return (NULL);
+       }
+
+       if ((fsz = (/* elfclass == ELFCLASS32 ? elf32_fsize :*/ elf64_fsize)
+            (elftype, (size_t) 1, e->e_version)) == 0) {
+               LIBELF_SET_ERROR(UNIMPL, 0);
+               return (NULL);
+       }
+
+       if (sh_size % fsz) {
+               LIBELF_SET_ERROR(SECTION, 0);
+               return (NULL);
+       }
+
+       if (sh_size / fsz > SIZE_MAX) {
+               LIBELF_SET_ERROR(RANGE, 0);
+               return (NULL);
+       }
+
+       count = (size_t) (sh_size / fsz);
+
+       msz = _libelf_msize(elftype, elfclass, e->e_version);
+
+       if (count > 0 && msz > SIZE_MAX / count) {
+               LIBELF_SET_ERROR(RANGE, 0);
+               return (NULL);
+       }
+
+       assert(msz > 0);
+       assert(count <= SIZE_MAX);
+       assert(msz * count <= SIZE_MAX);
+
+       if ((d = _libelf_allocate_data(s)) == NULL)
+               return (NULL);
+
+       d->d_data.d_buf     = NULL;
+       d->d_data.d_off     = 0;
+       d->d_data.d_align   = sh_align;
+       d->d_data.d_size    = msz * count;
+       d->d_data.d_type    = elftype;
+       d->d_data.d_version = e->e_version;
+
+       if (sh_type == SHT_NOBITS || sh_size == 0) {
+               STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
+               return (&d->d_data);
+        }
+
+       if ((d->d_data.d_buf = malloc(msz * count)) == NULL) {
+               (void) _libelf_release_data(d);
+               LIBELF_SET_ERROR(RESOURCE, 0);
+               return (NULL);
+       }
+
+       d->d_flags  |= LIBELF_F_DATA_MALLOCED;
+
+       xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass);
+       if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size,
+           e->e_rawfile + sh_offset, count,
+           e->e_byteorder != LIBELF_PRIVATE(byteorder))) {
+               _libelf_release_data(d);
+               LIBELF_SET_ERROR(DATA, 0);
+               return (NULL);
+       }
+
+       STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
+
+       return (&d->d_data);
+}
+
+#endif /* !_PRIVATE_LIBELF_H_ */
index 7286c4d..8e52915 100644 (file)
 #include <err.h>
 #include <dlfcn.h>
 
+#if 1
+#include "private_libelf.h"
+#else
 #include <libelf.h>
 #include <gelf.h>
+#endif
 #ifndef ELF_ST_BIND
 #define ELF_ST_BIND(x)          ((x) >> 4)
 #endif