From ac729b468ccb9e55127407b26627ed2194d5381f Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 2 Jun 2015 12:05:27 +0000 Subject: [PATCH] Simplify now that we always use an alignment of 2 for ELF files. This saves 123144 bytes out of llvm-nm on powerpc64le. llvm-svn: 238824 --- llvm/include/llvm/Object/ELF.h | 10 +- llvm/include/llvm/Object/ELFObjectFile.h | 10 +- llvm/include/llvm/Object/ELFTypes.h | 186 ++++++++---------- llvm/include/llvm/Support/Compiler.h | 13 -- .../RuntimeDyld/RuntimeDyldELF.cpp | 8 +- llvm/lib/Object/ELFObjectFile.cpp | 56 ++---- llvm/tools/llvm-readobj/ELFDumper.cpp | 8 +- llvm/tools/yaml2obj/yaml2elf.cpp | 8 +- 8 files changed, 116 insertions(+), 183 deletions(-) diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h index dc97c5fe7bb0..7403b4cedd3a 100644 --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -423,12 +423,10 @@ public: StringRef getLoadName() const; }; -// Use an alignment of 2 for the typedefs since that is the worst case for -// ELF files in archives. -typedef ELFFile > ELF32LEFile; -typedef ELFFile > ELF64LEFile; -typedef ELFFile > ELF32BEFile; -typedef ELFFile > ELF64BEFile; +typedef ELFFile> ELF32LEFile; +typedef ELFFile> ELF64LEFile; +typedef ELFFile> ELF32BEFile; +typedef ELFFile> ELF64BEFile; // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index 1c92aa3d9172..1a9e2dadd673 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -243,12 +243,10 @@ public: bool isRelocatableObject() const override; }; -// Use an alignment of 2 for the typedefs since that is the worst case for -// ELF files in archives. -typedef ELFObjectFile > ELF32LEObjectFile; -typedef ELFObjectFile > ELF64LEObjectFile; -typedef ELFObjectFile > ELF32BEObjectFile; -typedef ELFObjectFile > ELF64BEObjectFile; +typedef ELFObjectFile> ELF32LEObjectFile; +typedef ELFObjectFile> ELF64LEObjectFile; +typedef ELFObjectFile> ELF32BEObjectFile; +typedef ELFObjectFile> ELF64BEObjectFile; template void ELFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h index 287d3670678a..85e1e019f995 100644 --- a/llvm/include/llvm/Object/ELFTypes.h +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -10,7 +10,6 @@ #ifndef LLVM_OBJECT_ELFTYPES_H #define LLVM_OBJECT_ELFTYPES_H -#include "llvm/Support/AlignOf.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" @@ -20,95 +19,74 @@ namespace object { using support::endianness; -template -struct ELFType { +template struct ELFType { static const endianness TargetEndianness = target_endianness; - static const std::size_t MaxAlignment = max_alignment; static const bool Is64Bits = is64Bits; }; -template struct MaximumAlignment { - enum { value = AlignOf::Alignment > max_align ? max_align - : AlignOf::Alignment - }; -}; +// Use an alignment of 2 for the typedefs since that is the worst case for +// ELF files in archives. // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. -template -struct ELFDataTypeTypedefHelperCommon { +template struct ELFDataTypeTypedefHelperCommon { typedef support::detail::packed_endian_specific_integral< - uint16_t, target_endianness, - MaximumAlignment::value> Elf_Half; + uint16_t, target_endianness, 2> Elf_Half; typedef support::detail::packed_endian_specific_integral< - uint32_t, target_endianness, - MaximumAlignment::value> Elf_Word; + uint32_t, target_endianness, 2> Elf_Word; typedef support::detail::packed_endian_specific_integral< - int32_t, target_endianness, - MaximumAlignment::value> Elf_Sword; + int32_t, target_endianness, 2> Elf_Sword; typedef support::detail::packed_endian_specific_integral< - uint64_t, target_endianness, - MaximumAlignment::value> Elf_Xword; + uint64_t, target_endianness, 2> Elf_Xword; typedef support::detail::packed_endian_specific_integral< - int64_t, target_endianness, - MaximumAlignment::value> Elf_Sxword; + int64_t, target_endianness, 2> Elf_Sxword; }; template struct ELFDataTypeTypedefHelper; /// ELF 32bit types. -template -struct ELFDataTypeTypedefHelper > - : ELFDataTypeTypedefHelperCommon { +template +struct ELFDataTypeTypedefHelper> + : ELFDataTypeTypedefHelperCommon { typedef uint32_t value_type; typedef support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, - MaximumAlignment::value> Elf_Addr; + value_type, TargetEndianness, 2> Elf_Addr; typedef support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, - MaximumAlignment::value> Elf_Off; + value_type, TargetEndianness, 2> Elf_Off; }; /// ELF 64bit types. -template -struct ELFDataTypeTypedefHelper > - : ELFDataTypeTypedefHelperCommon { +template +struct ELFDataTypeTypedefHelper> + : ELFDataTypeTypedefHelperCommon { typedef uint64_t value_type; typedef support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, - MaximumAlignment::value> Elf_Addr; + value_type, TargetEndianness, 2> Elf_Addr; typedef support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, - MaximumAlignment::value> Elf_Off; + value_type, TargetEndianness, 2> Elf_Off; }; // I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Addr \ - Elf_Addr; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Off \ - Elf_Off; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Half \ - Elf_Half; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Word \ - Elf_Word; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Sword \ - Elf_Sword; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Xword \ - Elf_Xword; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Sxword \ - Elf_Sxword; +#define LLVM_ELF_IMPORT_TYPES(E, W) \ + typedef typename ELFDataTypeTypedefHelper>::Elf_Addr Elf_Addr; \ + typedef typename ELFDataTypeTypedefHelper>::Elf_Off Elf_Off; \ + typedef typename ELFDataTypeTypedefHelper>::Elf_Half Elf_Half; \ + typedef typename ELFDataTypeTypedefHelper>::Elf_Word Elf_Word; \ + typedef \ + typename ELFDataTypeTypedefHelper>::Elf_Sword Elf_Sword; \ + typedef \ + typename ELFDataTypeTypedefHelper>::Elf_Xword Elf_Xword; \ + typedef \ + typename ELFDataTypeTypedefHelper>::Elf_Sxword Elf_Sxword; #define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ - LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ - ELFT::Is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::Is64Bits) // Section header. template struct Elf_Shdr_Base; -template -struct Elf_Shdr_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Shdr_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_flags; // Section flags (SHF_*) @@ -121,9 +99,9 @@ struct Elf_Shdr_Base > { Elf_Word sh_entsize; // Size of records contained within the section }; -template -struct Elf_Shdr_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Shdr_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Xword sh_flags; // Section flags (SHF_*) @@ -151,9 +129,9 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base { template struct Elf_Sym_Base; -template -struct Elf_Sym_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Sym_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Word st_name; // Symbol name (index into string table) Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol @@ -162,9 +140,9 @@ struct Elf_Sym_Base > { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template -struct Elf_Sym_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Sym_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved @@ -267,9 +245,9 @@ struct Elf_Vernaux_Impl { /// table section (.dynamic) look like. template struct Elf_Dyn_Base; -template -struct Elf_Dyn_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Dyn_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Sword d_tag; union { Elf_Word d_val; @@ -277,9 +255,9 @@ struct Elf_Dyn_Base > { } d_un; }; -template -struct Elf_Dyn_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Dyn_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -300,9 +278,9 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base { // Elf_Rel: Elf Relocation template struct Elf_Rel_Base; -template -struct Elf_Rel_Base, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Rel_Base, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply @@ -316,9 +294,9 @@ struct Elf_Rel_Base, false> { } }; -template -struct Elf_Rel_Base, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Rel_Base, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply @@ -341,9 +319,9 @@ struct Elf_Rel_Base, false> { } }; -template -struct Elf_Rel_Base, true> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Rel_Base, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply Elf_Sword r_addend; // Compute value for relocatable field by adding this @@ -358,9 +336,9 @@ struct Elf_Rel_Base, true> { } }; -template -struct Elf_Rel_Base, true> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Rel_Base, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply Elf_Sxword r_addend; // Compute value for relocatable field by adding this. @@ -386,11 +364,10 @@ struct Elf_Rel_Base, true> { template struct Elf_Rel_Impl; -template -struct Elf_Rel_Impl, - isRela> : Elf_Rel_Base< - ELFType, isRela> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Rel_Impl, isRela> + : Elf_Rel_Base, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: @@ -411,11 +388,10 @@ struct Elf_Rel_Impl, } }; -template -struct Elf_Rel_Impl, - isRela> : Elf_Rel_Base< - ELFType, isRela> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Rel_Impl, isRela> + : Elf_Rel_Base, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // and ELF32_R_INFO macros defined in the ELF specification: @@ -463,9 +439,9 @@ struct Elf_Ehdr_Impl { template struct Elf_Phdr_Impl; -template -struct Elf_Phdr_Impl > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Phdr_Impl> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Word p_type; // Type of segment Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Addr p_vaddr; // Virtual Address of beginning of segment @@ -476,9 +452,9 @@ struct Elf_Phdr_Impl > { Elf_Word p_align; // Segment alignment constraint }; -template -struct Elf_Phdr_Impl > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Phdr_Impl> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Word p_type; // Type of segment Elf_Word p_flags; // Segment flags Elf_Off p_offset; // FileOffset where segment is located, in bytes @@ -493,17 +469,17 @@ struct Elf_Phdr_Impl > { template struct Elf_Mips_RegInfo; -template -struct Elf_Mips_RegInfo> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Mips_RegInfo> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Word ri_gprmask; // bit-mask of used general registers Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers Elf_Addr ri_gp_value; // gp register value }; -template -struct Elf_Mips_RegInfo> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Mips_RegInfo> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Word ri_gprmask; // bit-mask of used general registers Elf_Word ri_pad; // unused padding field Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers diff --git a/llvm/include/llvm/Support/Compiler.h b/llvm/include/llvm/Support/Compiler.h index c81fbaff9dba..67ef23d43c99 100644 --- a/llvm/include/llvm/Support/Compiler.h +++ b/llvm/include/llvm/Support/Compiler.h @@ -350,19 +350,6 @@ # define LLVM_ADDRESS_SANITIZER_BUILD 0 #endif -/// \macro LLVM_IS_UNALIGNED_ACCESS_FAST -/// \brief Is unaligned memory access fast on the host machine. -/// -/// Don't specialize on alignment for platforms where unaligned memory accesses -/// generates the same code as aligned memory accesses for common types. -#if defined(_M_AMD64) || defined(_M_IX86) || defined(__amd64) || \ - defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || \ - defined(_X86_) || defined(__i386) || defined(__i386__) -# define LLVM_IS_UNALIGNED_ACCESS_FAST 1 -#else -# define LLVM_IS_UNALIGNED_ACCESS_FAST 0 -#endif - /// \brief Mark debug helper function definitions like dump() that should not be /// stripped from debug builds. // FIXME: Move this to a private config.h as it's not usable in public headers. diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 204f91b74a02..8679368d7736 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -157,16 +157,16 @@ OwningBinary createELFDebugObject(const ObjectFile &Obj, std::unique_ptr DebugObj; if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) { - typedef ELFType ELF32LE; + typedef ELFType ELF32LE; DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); } else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) { - typedef ELFType ELF32BE; + typedef ELFType ELF32BE; DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); } else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) { - typedef ELFType ELF64BE; + typedef ELFType ELF64BE; DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); } else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) { - typedef ELFType ELF64LE; + typedef ELFType ELF64LE; DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); } else llvm_unreachable("Unexpected ELF format"); diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index 8ccb2538ac78..8847a20d96e8 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -27,51 +27,27 @@ ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { std::size_t MaxAlignment = 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); + if (MaxAlignment < 2) + return object_error::parse_failed; + std::error_code EC; std::unique_ptr R; - if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) -#if !LLVM_IS_UNALIGNED_ACCESS_FAST - if (MaxAlignment >= 4) - R.reset(new ELFObjectFile>(Obj, EC)); + if (Ident.first == ELF::ELFCLASS32) { + if (Ident.second == ELF::ELFDATA2LSB) + R.reset(new ELFObjectFile>(Obj, EC)); + else if (Ident.second == ELF::ELFDATA2MSB) + R.reset(new ELFObjectFile>(Obj, EC)); else -#endif - if (MaxAlignment >= 2) - R.reset(new ELFObjectFile>(Obj, EC)); + llvm_unreachable("Buffer is not an ELF object file!"); + } else { + assert(Ident.first == ELF::ELFCLASS64); + if (Ident.second == ELF::ELFDATA2LSB) + R.reset(new ELFObjectFile>(Obj, EC)); + else if (Ident.second == ELF::ELFDATA2MSB) + R.reset(new ELFObjectFile>(Obj, EC)); else - return object_error::parse_failed; - else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) -#if !LLVM_IS_UNALIGNED_ACCESS_FAST - if (MaxAlignment >= 4) - R.reset(new ELFObjectFile>(Obj, EC)); - else -#endif - if (MaxAlignment >= 2) - R.reset(new ELFObjectFile>(Obj, EC)); - else - return object_error::parse_failed; - else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) -#if !LLVM_IS_UNALIGNED_ACCESS_FAST - if (MaxAlignment >= 8) - R.reset(new ELFObjectFile>(Obj, EC)); - else -#endif - if (MaxAlignment >= 2) - R.reset(new ELFObjectFile>(Obj, EC)); - else - return object_error::parse_failed; - else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { -#if !LLVM_IS_UNALIGNED_ACCESS_FAST - if (MaxAlignment >= 8) - R.reset(new ELFObjectFile>(Obj, EC)); - else -#endif - if (MaxAlignment >= 2) - R.reset(new ELFObjectFile>(Obj, EC)); - else - return object_error::parse_failed; + llvm_unreachable("Buffer is not an ELF object file!"); } - else - llvm_unreachable("Buffer is not an ELF object file!"); if (EC) return EC; diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index a20512f20534..880143af7125 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -991,11 +991,10 @@ void ELFDumper::printUnwindInfo() { } namespace { -template <> -void ELFDumper >::printUnwindInfo() { +template <> void ELFDumper>::printUnwindInfo() { const unsigned Machine = Obj->getHeader()->e_machine; if (Machine == EM_ARM) { - ARM::EHABI::PrinterContext > Ctx(W, Obj); + ARM::EHABI::PrinterContext> Ctx(W, Obj); return Ctx.PrintUnwindInformation(); } W.startLine() << "UnwindInfo not implemented.\n"; @@ -1075,8 +1074,7 @@ void ELFDumper::printAttributes() { } namespace { -template <> -void ELFDumper >::printAttributes() { +template <> void ELFDumper>::printAttributes() { if (Obj->getHeader()->e_machine != EM_ARM) { W.startLine() << "Attributes not implemented.\n"; return; diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp index 338658805638..772b5b918eca 100644 --- a/llvm/tools/yaml2obj/yaml2elf.cpp +++ b/llvm/tools/yaml2obj/yaml2elf.cpp @@ -552,10 +552,10 @@ int yaml2elf(yaml::Input &YIn, raw_ostream &Out) { return 1; } using object::ELFType; - typedef ELFType LE64; - typedef ELFType BE64; - typedef ELFType LE32; - typedef ELFType BE32; + typedef ELFType LE64; + typedef ELFType BE64; + typedef ELFType LE32; + typedef ELFType BE32; if (is64Bit(Doc)) { if (isLittleEndian(Doc)) return ELFState::writeELF(Out, Doc);