Index: include/lld/ReaderWriter/ELFTargetInfo.h =================================================================== --- include/lld/ReaderWriter/ELFTargetInfo.h +++ include/lld/ReaderWriter/ELFTargetInfo.h @@ -35,10 +35,18 @@ class ELFTargetInfo : public TargetInfo { public: + enum Magic { + DEFAULT, // The default mode, no specific magic set + NMAGIC, // Disallow shared libraries and dont align sections + // PageAlign Data, Mark Text Segment/Data segment RW + OMAGIC // Disallow shared libraries and dont align sections, + // Mark Text Segment/Data segment RW + }; llvm::Triple getTriple() const { return _triple; } virtual bool is64Bits() const; virtual bool isLittleEndian() const; virtual uint64_t getPageSize() const { return 0x1000; } + uint8_t getOutputMagic() const { return _outputMagic; } uint16_t getOutputType() const { return _outputFileType; } uint16_t getOutputMachine() const; bool outputYAML() const { return _outputYAML; } @@ -64,6 +72,15 @@ } virtual bool validateImpl(raw_ostream &diagnostics); + /// \brief Does the linker allow dynamic libraries to be linked with ? + /// This is true when the output mode of the executable is set to be + /// having NMAGIC/OMAGIC + virtual bool allowLinkWithDynamicLibraries() const { + if (_outputMagic == NMAGIC || _outputMagic == OMAGIC || + _noAllowDynamicLibraries) + return false; + return true; + } virtual error_code parseFile(std::unique_ptr &mb, std::vector> &result) const; @@ -121,6 +138,15 @@ _dynamicLinkerPath = dynamicLinker; } + /// \brief Set NMAGIC output kind when the linker specifies --nmagic + /// or -n in the command line + /// Set OMAGIC output kind when the linker specifies --omagic + /// or -N in the command line + virtual void setOutputMagic(Magic magic) { _outputMagic = magic; } + + /// \brief Disallow dynamic libraries during linking + virtual void setNoAllowDynamicLibraries() { _noAllowDynamicLibraries = true; } + void appendSearchPath(StringRef dirPath) { _inputSearchPaths.push_back(dirPath); } @@ -145,6 +171,8 @@ bool _runLayoutPass; bool _useShlibUndefines; bool _dynamicLinkerArg; + bool _noAllowDynamicLibraries; + uint8_t _outputMagic; std::vector _inputSearchPaths; llvm::BumpPtrAllocator _extraStrings; std::unique_ptr _elfReader; Index: lib/Driver/GnuLdDriver.cpp =================================================================== --- lib/Driver/GnuLdDriver.cpp +++ lib/Driver/GnuLdDriver.cpp @@ -198,6 +198,25 @@ parsedArgs->getLastArg(OPT_dynamic_linker)) options->setInterpreter(dynamicLinker->getValue()); + // Handle NMAGIC + if (parsedArgs->getLastArg(OPT_nmagic)) + options->setOutputMagic(ELFTargetInfo::NMAGIC); + + // Handle OMAGIC + if (parsedArgs->getLastArg(OPT_omagic)) + options->setOutputMagic(ELFTargetInfo::OMAGIC); + + // Handle --no-omagic + if (parsedArgs->getLastArg(OPT_no_omagic)) { + options->setOutputMagic(ELFTargetInfo::DEFAULT); + options->setNoAllowDynamicLibraries(); + } + + // If either of the options NMAGIC/OMAGIC have been set, make the executable + // static + if (!options->allowLinkWithDynamicLibraries()) + options->setIsStaticExecutable(true); + // Handle -Lxxx for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_L), ie = parsedArgs->filtered_end(); Index: lib/Driver/LDOptions.td =================================================================== --- lib/Driver/LDOptions.td +++ lib/Driver/LDOptions.td @@ -61,6 +61,17 @@ def use_shlib_undefs: Flag<["--"], "use-shlib-undefines">, HelpText<"Resolve undefined symbols from dynamic libraries">; +def nmagic : Flag<["--"], "nmagic">, + HelpText<"Turn off page alignment of sections, and disable linking against shared libraries">; +def nmagic_alias : Flag<["-"], "n">, Alias; + +def omagic : Flag<["--"], "omagic">, + HelpText<"Set the text and data sections to be readable and writable. Also, do not page-align the data segment, and disable linking against shared libraries.">; +def omagic_alias : Flag<["-"], "N">, Alias; + +def no_omagic : Flag<["--"], "no-omagic">, + HelpText<"This option negates most of the effects of the -N option. Disable linking with shared libraries">; + // extensions def emit_yaml : Flag<["-"], "emit-yaml">, HelpText<"Write YAML instead of ELF">; Index: lib/ReaderWriter/ELF/Chunk.h =================================================================== --- lib/ReaderWriter/ELF/Chunk.h +++ lib/ReaderWriter/ELF/Chunk.h @@ -41,10 +41,19 @@ K_AtomSection, ///< A section containing atoms. K_SectionHeader ///< Section header }; + /// \brief the ContentType of the chunk + enum ContentType { + CT_Unknown, + CT_Header, + CT_Code, + CT_Data, + CT_Note, + CT_Tls, + }; + Chunk(StringRef name, Kind kind, const ELFTargetInfo &ti) : _name(name), _kind(kind), _fsize(0), _msize(0), _align2(0), _order(0), - _ordinal(1), _start(0), _fileoffset(0), _targetInfo(ti) { - } + _ordinal(1), _start(0), _fileoffset(0), _targetInfo(ti) {} virtual ~Chunk() {} // Does the chunk occupy disk space virtual bool occupiesNoDiskSpace() const { return false; } @@ -70,6 +79,8 @@ // Does the chunk occupy memory during execution ? uint64_t memSize() const { return _msize; } void setMemSize(uint64_t msize) { _msize = msize; } + // Whats the contentType of the chunk ? + virtual int getContentType() const = 0; // Writer the chunk virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) = 0; // Finalize the chunk before assigning offsets/virtual addresses Index: lib/ReaderWriter/ELF/DefaultLayout.h =================================================================== --- lib/ReaderWriter/ELF/DefaultLayout.h +++ lib/ReaderWriter/ELF/DefaultLayout.h @@ -547,8 +547,9 @@ template void DefaultLayout::assignSectionsToSegments() { ScopedTask task(getDefaultDomain(), "assignSectionsToSegments"); - // TODO: Do we want to give a chance for the targetHandlers - // to sort segments in an arbitrary order ? + uint8_t magic = _targetInfo.getOutputMagic(); + // TODO: Do we want to give a chance for the targetHandlers + // to sort segments in an arbitrary order ? // sort the sections by their order as defined by the layout std::stable_sort(_sections.begin(), _sections.end(), [](Chunk *A, Chunk *B) { @@ -608,6 +609,12 @@ segment->append(section); } + // If the output magic is set to NMAGIC / OMAGIC, Place the data + // alongside text in one single segment + if (magic == ELFTargetInfo::NMAGIC || magic == ELFTargetInfo::OMAGIC) + lookupSectionFlag = llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC | + llvm::ELF::SHF_WRITE; + // Use the flags of the merged Section for the segment const SegmentKey key("PT_LOAD", lookupSectionFlag); const std::pair *> currentSegment(key, @@ -660,6 +667,7 @@ return; uint64_t virtualAddress = _targetInfo.getBaseAddress(); + uint8_t magic = _targetInfo.getOutputMagic(); // HACK: This is a super dirty hack. The elf header and program header are // not part of a section, but we need them to be loaded at the base address @@ -690,9 +698,11 @@ // Dont assign offsets for non loadable segments if (si->segmentType() != llvm::ELF::PT_LOAD) continue; - // Align the segment to a page boundary - fileoffset = - llvm::RoundUpToAlignment(fileoffset, _targetInfo.getPageSize()); + // Align the segment to a page boundary only if the output mode is + // not NMAGIC/OMAGIC + if (magic != ELFTargetInfo::NMAGIC && magic != ELFTargetInfo::OMAGIC) + fileoffset = + llvm::RoundUpToAlignment(fileoffset, _targetInfo.getPageSize()); si->assignOffsets(fileoffset); fileoffset = si->fileOffset() + si->fileSize(); } @@ -707,8 +717,9 @@ // first segment to the pagesize (*si)->assignVirtualAddress(address); (*si)->setMemSize(address - virtualAddress); - virtualAddress = llvm::RoundUpToAlignment(address, - _targetInfo.getPageSize()); + if (magic != ELFTargetInfo::NMAGIC && magic != ELFTargetInfo::OMAGIC) + virtualAddress = + llvm::RoundUpToAlignment(address, _targetInfo.getPageSize()); } _programHeader->resetProgramHeaders(); } Index: lib/ReaderWriter/ELF/ELFTargetInfo.cpp =================================================================== --- lib/ReaderWriter/ELF/ELFTargetInfo.cpp +++ lib/ReaderWriter/ELF/ELFTargetInfo.cpp @@ -34,7 +34,8 @@ _mergeCommonStrings(false), _runLayoutPass(true), _useShlibUndefines(false), - _dynamicLinkerArg(false) {} + _dynamicLinkerArg(false), + _outputMagic(DEFAULT) {} bool ELFTargetInfo::is64Bits() const { return getTriple().isArch64Bit(); } Index: lib/ReaderWriter/ELF/HeaderChunks.h =================================================================== --- lib/ReaderWriter/ELF/HeaderChunks.h +++ lib/ReaderWriter/ELF/HeaderChunks.h @@ -51,6 +51,10 @@ return c->Kind() == Chunk::K_Header; } + inline int getContentType() const { + return Chunk::CT_Header; + } + void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); virtual void doPreFlight() {} @@ -162,6 +166,10 @@ return _ph.size(); } + inline int getContentType() const { + return Chunk::CT_Header; + } + private: Elf_Phdr *allocateProgramHeader(bool &allocatedNew) { Elf_Phdr *phdr; @@ -185,6 +193,7 @@ template bool ProgramHeader::addSegment(Segment *segment) { bool allocatedNew = false; + uint8_t magic = this->_targetInfo.getOutputMagic(); // For segments that are not a loadable segment, we // just pick the values directly from the segment as there // wouldnt be any slices within that @@ -213,8 +222,11 @@ phdr->p_filesz = slice->fileSize(); phdr->p_memsz = slice->memSize(); phdr->p_flags = segment->flags(); - phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ? - segment->pageSize() : slice->align2(); + if (magic != ELFTargetInfo::NMAGIC && magic != ELFTargetInfo::OMAGIC) + phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ? segment->pageSize() + : slice->align2(); + else + phdr->p_align = slice->align2(); } this->_fsize = fileSize(); this->_msize = this->_fsize; @@ -266,6 +278,10 @@ return sizeof(Elf_Shdr); } + inline int getContentType() const { + return Chunk::CT_Header; + } + inline uint64_t numHeaders() { return _sectionInfo.size(); } Index: lib/ReaderWriter/ELF/Reader.cpp =================================================================== --- lib/ReaderWriter/ELF/Reader.cpp +++ lib/ReaderWriter/ELF/Reader.cpp @@ -103,6 +103,10 @@ break; } case llvm::sys::fs::file_magic::elf_shared_object: { + // If the link doesnot allow dynamic libraries to be present during the + // link, lets not parse the file and just return + if (!_elfTargetInfo.allowLinkWithDynamicLibraries()) + return llvm::make_error_code(llvm::errc::executable_format_error); auto f = createELF( getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb)); if (!f) Index: lib/ReaderWriter/ELF/SectionChunks.h =================================================================== --- lib/ReaderWriter/ELF/SectionChunks.h +++ lib/ReaderWriter/ELF/SectionChunks.h @@ -78,6 +78,18 @@ uint32_t getInfo() const { return _info; } Layout::SegmentType getSegmentType() const { return _segmentType; } + /// \brief Return the type of content that the section contains + virtual int getContentType() const { + if (_flags & llvm::ELF::SHF_EXECINSTR) + return Chunk::CT_Code; + else if (_flags & llvm::ELF::SHF_WRITE) + return Chunk::CT_Data; + else if (_flags & llvm::ELF::SHF_ALLOC) + return Chunk::CT_Code; + else + return Chunk::CT_Unknown; + } + /// \brief convert the segment type to a String for diagnostics and printing /// purposes StringRef segmentKindToStr() const; Index: lib/ReaderWriter/ELF/SegmentChunks.h =================================================================== --- lib/ReaderWriter/ELF/SegmentChunks.h +++ lib/ReaderWriter/ELF/SegmentChunks.h @@ -114,6 +114,7 @@ Segment(const ELFTargetInfo &ti, StringRef name, const Layout::SegmentType type); + /// \brief the Order of segments that appear in the output file enum SegmentOrder { permUnknown, permRWX, @@ -199,8 +200,31 @@ return _sections.size(); } + /// \brief, this function returns the type of segment (PT_*) inline Layout::SegmentType segmentType() { return _segmentType; } + /// \brief return the segment type depending on the content, + /// If the content corresponds to Code, this will return Segment::Code + /// If the content corresponds to Data, this will return Segment::Data + /// If the content corresponds to TLS, this will return Segment::TLS + virtual int getContentType() const { + int64_t fl = flags(); + switch (_segmentType) { + case llvm::ELF::PT_LOAD: { + if (fl && llvm::ELF::PF_X) + return Chunk::CT_Code; + if (fl && llvm::ELF::PF_W) + return Chunk::CT_Data; + } + case llvm::ELF::PT_TLS: + return Chunk::CT_Tls; + case llvm::ELF::PT_NOTE: + return Chunk::CT_Note; + default: + return Chunk::CT_Unknown; + } + } + inline int pageSize() const { return this->_targetInfo.getPageSize(); } inline int rawflags() const { return _atomflags; } @@ -246,6 +270,19 @@ return _segmentSlices.end(); } +private: + + /// \brief Check if the chunk needs to be aligned + bool needAlign(Chunk *chunk) const { + if (chunk->getContentType() == Chunk::CT_Data && + _outputMagic == ELFTargetInfo::NMAGIC) + return true; + return false; + } + + // Cached value of outputMagic + uint8_t _outputMagic; + protected: /// \brief Section or some other chunk type. std::vector *> _sections; @@ -294,6 +331,7 @@ _flags(0), _atomflags(0) { this->_align2 = 0; this->_fsize = 0; + _outputMagic = ti.getOutputMagic(); } // This function actually is used, but not in all instantiations of Segment. @@ -316,7 +354,7 @@ template void Segment::append(Section *section) { _sections.push_back(section); if (_flags < section->getFlags()) - _flags = section->getFlags(); + _flags |= section->getFlags(); if (_atomflags < toAtomPerms(_flags)) _atomflags = toAtomPerms(_flags); if (this->_align2 < section->align2()) @@ -385,8 +423,16 @@ endSectionIter = _sections.end(); startSection = 0; bool isFirstSection = true; + bool isDataPageAlignedForNMagic = false; for (auto si = _sections.begin(); si != _sections.end(); ++si) { if (isFirstSection) { + // If the linker outputmagic is set to NMAGIC, align the Data + // to a page boundary + if (!isDataPageAlignedForNMagic && needAlign(*si)) { + startOffset = llvm::RoundUpToAlignment(startOffset, + this->_targetInfo.getPageSize()); + isDataPageAlignedForNMagic = true; + } // align the startOffset to the section alignment uint64_t newOffset = llvm::RoundUpToAlignment(startOffset, (*si)->align2()); @@ -398,12 +444,21 @@ isFirstSection = false; } else { uint64_t curOffset = curSliceFileOffset + curSliceSize; - uint64_t newOffset = - llvm::RoundUpToAlignment(curOffset, (*si)->align2()); + // If the linker outputmagic is set to NMAGIC, align the Data + // to a page boundary + if (!isDataPageAlignedForNMagic && needAlign(*si)) { + curOffset = llvm::RoundUpToAlignment(curOffset, + this->_targetInfo.getPageSize()); + isDataPageAlignedForNMagic = true; + } + uint64_t newOffset = llvm::RoundUpToAlignment(curOffset, (*si)->align2()); SegmentSlice *slice = nullptr; // If the newOffset computed is more than a page away, lets create // a seperate segment, so that memory is not used up while running - if ((newOffset - curOffset) > this->_targetInfo.getPageSize()) { + if (((newOffset - curOffset) > this->_targetInfo.getPageSize()) && + (_outputMagic != ELFTargetInfo::NMAGIC && + _outputMagic != ELFTargetInfo::OMAGIC)) { + // TODO: use std::find here for (auto s : slices()) { if (s->startSection() == startSection) { @@ -464,16 +519,26 @@ /// \brief Assign virtual addresses to the slices template void Segment::assignVirtualAddress(uint64_t &addr) { bool isTLSSegment = false; + bool isDataPageAlignedForNMagic = false; uint64_t tlsStartAddr = 0; for (auto slice : slices()) { - // Align to a page - addr = llvm::RoundUpToAlignment(addr, this->_targetInfo.getPageSize()); + // Align to a page only if the output is not NMAGIC/OMAGIC + if (_outputMagic != ELFTargetInfo::NMAGIC && + _outputMagic != ELFTargetInfo::OMAGIC) + addr = llvm::RoundUpToAlignment(addr, this->_targetInfo.getPageSize()); + // Align to the slice alignment addr = llvm::RoundUpToAlignment(addr, slice->align2()); bool virtualAddressSet = false; for (auto section : slice->sections()) { + // If the linker outputmagic is set to NMAGIC, align the Data + // to a page boundary + if (!isDataPageAlignedForNMagic && needAlign(section)) { + addr = llvm::RoundUpToAlignment(addr, this->_targetInfo.getPageSize()); + isDataPageAlignedForNMagic = true; + } // Align the section address addr = llvm::RoundUpToAlignment(addr, section->align2()); // Check if the segment is of type TLS Index: test/elf/X86_64/Inputs/nmagic.c =================================================================== --- /dev/null +++ test/elf/X86_64/Inputs/nmagic.c @@ -0,0 +1,8 @@ +int a = 10; +__thread int b = 20; +__thread int c; +__thread int d; + +int main() { + return 0; +} Index: test/elf/X86_64/nmagic.test =================================================================== --- /dev/null +++ test/elf/X86_64/nmagic.test @@ -0,0 +1,239 @@ +# This tests verifies functionality of NMAGIC that we create only two segments, +# PT_LOAD, PT_TLS +# The data segment should be aligned to a page boundary +RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/nmagic.o \ +RUN: --noinhibit-exec -o %t --nmagic +RUN: llvm-readobj -sections %t | FileCheck -check-prefix=NMAGICSECTIONS %s +RUN: llvm-readobj -program-headers %t | FileCheck -check-prefix=NMAGICPROGRAMHEADERS %s + +NMAGICSECTIONS: Sections [ +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 0 +NMAGICSECTIONS: Name: (0) +NMAGICSECTIONS: Type: SHT_NULL (0x0) +NMAGICSECTIONS: Flags [ (0x0) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x0 +NMAGICSECTIONS: Offset: 0x0 +NMAGICSECTIONS: Size: 0 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 0 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 1 +NMAGICSECTIONS: Name: .text (1) +NMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +NMAGICSECTIONS: Flags [ (0x6) +NMAGICSECTIONS: SHF_ALLOC (0x2) +NMAGICSECTIONS: SHF_EXECINSTR (0x4) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x4000B0 +NMAGICSECTIONS: Offset: 0xB0 +NMAGICSECTIONS: Size: 11 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 4 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 2 +NMAGICSECTIONS: Name: .note.GNU-stack (7) +NMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +NMAGICSECTIONS: Flags [ (0x2) +NMAGICSECTIONS: SHF_ALLOC (0x2) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x4000BB +NMAGICSECTIONS: Offset: 0xBB +NMAGICSECTIONS: Size: 0 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 1 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 3 +NMAGICSECTIONS: Name: .comment (23) +NMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +NMAGICSECTIONS: Flags [ (0x2) +NMAGICSECTIONS: SHF_ALLOC (0x2) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x4000BB +NMAGICSECTIONS: Offset: 0xBB +NMAGICSECTIONS: Size: 43 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 1 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 4 +NMAGICSECTIONS: Name: .eh_frame (32) +NMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +NMAGICSECTIONS: Flags [ (0x2) +NMAGICSECTIONS: SHF_ALLOC (0x2) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x4000E8 +NMAGICSECTIONS: Offset: 0xE8 +NMAGICSECTIONS: Size: 56 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 8 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 5 +NMAGICSECTIONS: Name: .tdata (42) +NMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +NMAGICSECTIONS: Flags [ (0x403) +NMAGICSECTIONS: SHF_ALLOC (0x2) +NMAGICSECTIONS: SHF_TLS (0x400) +NMAGICSECTIONS: SHF_WRITE (0x1) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x401000 +NMAGICSECTIONS: Offset: 0x1000 +NMAGICSECTIONS: Size: 4 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 4 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 6 +NMAGICSECTIONS: Name: .tbss (49) +NMAGICSECTIONS: Type: SHT_NOBITS (0x8) +NMAGICSECTIONS: Flags [ (0x403) +NMAGICSECTIONS: SHF_ALLOC (0x2) +NMAGICSECTIONS: SHF_TLS (0x400) +NMAGICSECTIONS: SHF_WRITE (0x1) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x401004 +NMAGICSECTIONS: Offset: 0x1004 +NMAGICSECTIONS: Size: 8 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 4 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 7 +NMAGICSECTIONS: Name: .got.plt (55) +NMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +NMAGICSECTIONS: Flags [ (0x3) +NMAGICSECTIONS: SHF_ALLOC (0x2) +NMAGICSECTIONS: SHF_WRITE (0x1) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x401008 +NMAGICSECTIONS: Offset: 0x1008 +NMAGICSECTIONS: Size: 0 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 8 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 8 +NMAGICSECTIONS: Name: .data (64) +NMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +NMAGICSECTIONS: Flags [ (0x3) +NMAGICSECTIONS: SHF_ALLOC (0x2) +NMAGICSECTIONS: SHF_WRITE (0x1) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x401008 +NMAGICSECTIONS: Offset: 0x1008 +NMAGICSECTIONS: Size: 4 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 4 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 9 +NMAGICSECTIONS: Name: .bss (70) +NMAGICSECTIONS: Type: SHT_NOBITS (0x8) +NMAGICSECTIONS: Flags [ (0x3) +NMAGICSECTIONS: SHF_ALLOC (0x2) +NMAGICSECTIONS: SHF_WRITE (0x1) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x40100C +NMAGICSECTIONS: Offset: 0x100C +NMAGICSECTIONS: Size: 0 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 4 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 10 +NMAGICSECTIONS: Name: .shstrtab (75) +NMAGICSECTIONS: Type: SHT_STRTAB (0x3) +NMAGICSECTIONS: Flags [ (0x0) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x0 +NMAGICSECTIONS: Offset: 0x100C +NMAGICSECTIONS: Size: 101 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 1 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 11 +NMAGICSECTIONS: Name: .symtab (85) +NMAGICSECTIONS: Type: SHT_SYMTAB (0x2) +NMAGICSECTIONS: Flags [ (0x0) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x0 +NMAGICSECTIONS: Offset: 0x1078 +NMAGICSECTIONS: Size: 528 +NMAGICSECTIONS: Link: 12 +NMAGICSECTIONS: Info: 2 +NMAGICSECTIONS: AddressAlignment: 8 +NMAGICSECTIONS: EntrySize: 24 +NMAGICSECTIONS: } +NMAGICSECTIONS: Section { +NMAGICSECTIONS: Index: 12 +NMAGICSECTIONS: Name: .strtab (93) +NMAGICSECTIONS: Type: SHT_STRTAB (0x3) +NMAGICSECTIONS: Flags [ (0x0) +NMAGICSECTIONS: ] +NMAGICSECTIONS: Address: 0x0 +NMAGICSECTIONS: Offset: 0x1288 +NMAGICSECTIONS: Size: 246 +NMAGICSECTIONS: Link: 0 +NMAGICSECTIONS: Info: 0 +NMAGICSECTIONS: AddressAlignment: 1 +NMAGICSECTIONS: EntrySize: 0 +NMAGICSECTIONS: } +NMAGICSECTIONS: ] + +NMAGICPROGRAMHEADERS: ProgramHeaders [ +NMAGICPROGRAMHEADERS: ProgramHeader { +NMAGICPROGRAMHEADERS: Type: PT_LOAD (0x1) +NMAGICPROGRAMHEADERS: Offset: 0x0 +NMAGICPROGRAMHEADERS: VirtualAddress: 0x400000 +NMAGICPROGRAMHEADERS: PhysicalAddress: 0x400000 +NMAGICPROGRAMHEADERS: FileSize: 4108 +NMAGICPROGRAMHEADERS: MemSize: 4108 +NMAGICPROGRAMHEADERS: Flags [ (0x7) +NMAGICPROGRAMHEADERS: PF_R (0x4) +NMAGICPROGRAMHEADERS: PF_W (0x2) +NMAGICPROGRAMHEADERS: PF_X (0x1) +NMAGICPROGRAMHEADERS: ] +NMAGICPROGRAMHEADERS: Alignment: 8 +NMAGICPROGRAMHEADERS: } +NMAGICPROGRAMHEADERS: ProgramHeader { +NMAGICPROGRAMHEADERS: Type: PT_TLS (0x7) +NMAGICPROGRAMHEADERS: Offset: 0x1000 +NMAGICPROGRAMHEADERS: VirtualAddress: 0x401000 +NMAGICPROGRAMHEADERS: PhysicalAddress: 0x401000 +NMAGICPROGRAMHEADERS: FileSize: 4 +NMAGICPROGRAMHEADERS: MemSize: 12 +NMAGICPROGRAMHEADERS: Flags [ (0x6) +NMAGICPROGRAMHEADERS: PF_R (0x4) +NMAGICPROGRAMHEADERS: PF_W (0x2) +NMAGICPROGRAMHEADERS: ] +NMAGICPROGRAMHEADERS: Alignment: 4 +NMAGICPROGRAMHEADERS: } +NMAGICPROGRAMHEADERS: ] Index: test/elf/X86_64/omagic.test =================================================================== --- /dev/null +++ test/elf/X86_64/omagic.test @@ -0,0 +1,239 @@ +# This tests verifies functionality of omagic that we create only two segments, +# PT_LOAD, PT_TLS +# The data segment should not be aligned to a page boundary +RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/nmagic.o \ +RUN: --noinhibit-exec -o %t --omagic +RUN: llvm-readobj -sections %t | FileCheck -check-prefix=OMAGICSECTIONS %s +RUN: llvm-readobj -program-headers %t | FileCheck -check-prefix=OMAGICPROGRAMHEADERS %s + +OMAGICSECTIONS: Sections [ +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 0 +OMAGICSECTIONS: Name: (0) +OMAGICSECTIONS: Type: SHT_NULL (0x0) +OMAGICSECTIONS: Flags [ (0x0) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x0 +OMAGICSECTIONS: Offset: 0x0 +OMAGICSECTIONS: Size: 0 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 0 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 1 +OMAGICSECTIONS: Name: .text (1) +OMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +OMAGICSECTIONS: Flags [ (0x6) +OMAGICSECTIONS: SHF_ALLOC (0x2) +OMAGICSECTIONS: SHF_EXECINSTR (0x4) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x4000B0 +OMAGICSECTIONS: Offset: 0xB0 +OMAGICSECTIONS: Size: 11 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 4 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 2 +OMAGICSECTIONS: Name: .note.GNU-stack (7) +OMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +OMAGICSECTIONS: Flags [ (0x2) +OMAGICSECTIONS: SHF_ALLOC (0x2) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x4000BB +OMAGICSECTIONS: Offset: 0xBB +OMAGICSECTIONS: Size: 0 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 1 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 3 +OMAGICSECTIONS: Name: .comment (23) +OMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +OMAGICSECTIONS: Flags [ (0x2) +OMAGICSECTIONS: SHF_ALLOC (0x2) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x4000BB +OMAGICSECTIONS: Offset: 0xBB +OMAGICSECTIONS: Size: 43 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 1 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 4 +OMAGICSECTIONS: Name: .eh_frame (32) +OMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +OMAGICSECTIONS: Flags [ (0x2) +OMAGICSECTIONS: SHF_ALLOC (0x2) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x4000E8 +OMAGICSECTIONS: Offset: 0xE8 +OMAGICSECTIONS: Size: 56 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 8 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 5 +OMAGICSECTIONS: Name: .tdata (42) +OMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +OMAGICSECTIONS: Flags [ (0x403) +OMAGICSECTIONS: SHF_ALLOC (0x2) +OMAGICSECTIONS: SHF_TLS (0x400) +OMAGICSECTIONS: SHF_WRITE (0x1) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x400120 +OMAGICSECTIONS: Offset: 0x120 +OMAGICSECTIONS: Size: 4 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 4 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 6 +OMAGICSECTIONS: Name: .tbss (49) +OMAGICSECTIONS: Type: SHT_NOBITS (0x8) +OMAGICSECTIONS: Flags [ (0x403) +OMAGICSECTIONS: SHF_ALLOC (0x2) +OMAGICSECTIONS: SHF_TLS (0x400) +OMAGICSECTIONS: SHF_WRITE (0x1) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x400124 +OMAGICSECTIONS: Offset: 0x124 +OMAGICSECTIONS: Size: 8 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 4 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 7 +OMAGICSECTIONS: Name: .got.plt (55) +OMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +OMAGICSECTIONS: Flags [ (0x3) +OMAGICSECTIONS: SHF_ALLOC (0x2) +OMAGICSECTIONS: SHF_WRITE (0x1) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x400128 +OMAGICSECTIONS: Offset: 0x128 +OMAGICSECTIONS: Size: 0 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 8 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 8 +OMAGICSECTIONS: Name: .data (64) +OMAGICSECTIONS: Type: SHT_PROGBITS (0x1) +OMAGICSECTIONS: Flags [ (0x3) +OMAGICSECTIONS: SHF_ALLOC (0x2) +OMAGICSECTIONS: SHF_WRITE (0x1) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x400128 +OMAGICSECTIONS: Offset: 0x128 +OMAGICSECTIONS: Size: 4 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 4 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 9 +OMAGICSECTIONS: Name: .bss (70) +OMAGICSECTIONS: Type: SHT_NOBITS (0x8) +OMAGICSECTIONS: Flags [ (0x3) +OMAGICSECTIONS: SHF_ALLOC (0x2) +OMAGICSECTIONS: SHF_WRITE (0x1) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x40012C +OMAGICSECTIONS: Offset: 0x12C +OMAGICSECTIONS: Size: 0 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 4 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 10 +OMAGICSECTIONS: Name: .shstrtab (75) +OMAGICSECTIONS: Type: SHT_STRTAB (0x3) +OMAGICSECTIONS: Flags [ (0x0) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x0 +OMAGICSECTIONS: Offset: 0x12C +OMAGICSECTIONS: Size: 101 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 1 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 11 +OMAGICSECTIONS: Name: .symtab (85) +OMAGICSECTIONS: Type: SHT_SYMTAB (0x2) +OMAGICSECTIONS: Flags [ (0x0) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x0 +OMAGICSECTIONS: Offset: 0x198 +OMAGICSECTIONS: Size: 528 +OMAGICSECTIONS: Link: 12 +OMAGICSECTIONS: Info: 2 +OMAGICSECTIONS: AddressAlignment: 8 +OMAGICSECTIONS: EntrySize: 24 +OMAGICSECTIONS: } +OMAGICSECTIONS: Section { +OMAGICSECTIONS: Index: 12 +OMAGICSECTIONS: Name: .strtab (93) +OMAGICSECTIONS: Type: SHT_STRTAB (0x3) +OMAGICSECTIONS: Flags [ (0x0) +OMAGICSECTIONS: ] +OMAGICSECTIONS: Address: 0x0 +OMAGICSECTIONS: Offset: 0x3A8 +OMAGICSECTIONS: Size: 246 +OMAGICSECTIONS: Link: 0 +OMAGICSECTIONS: Info: 0 +OMAGICSECTIONS: AddressAlignment: 1 +OMAGICSECTIONS: EntrySize: 0 +OMAGICSECTIONS: } +OMAGICSECTIONS: ] + +OMAGICPROGRAMHEADERS: ProgramHeaders [ +OMAGICPROGRAMHEADERS: ProgramHeader { +OMAGICPROGRAMHEADERS: Type: PT_LOAD (0x1) +OMAGICPROGRAMHEADERS: Offset: 0x0 +OMAGICPROGRAMHEADERS: VirtualAddress: 0x400000 +OMAGICPROGRAMHEADERS: PhysicalAddress: 0x400000 +OMAGICPROGRAMHEADERS: FileSize: 300 +OMAGICPROGRAMHEADERS: MemSize: 300 +OMAGICPROGRAMHEADERS: Flags [ (0x7) +OMAGICPROGRAMHEADERS: PF_R (0x4) +OMAGICPROGRAMHEADERS: PF_W (0x2) +OMAGICPROGRAMHEADERS: PF_X (0x1) +OMAGICPROGRAMHEADERS: ] +OMAGICPROGRAMHEADERS: Alignment: 8 +OMAGICPROGRAMHEADERS: } +OMAGICPROGRAMHEADERS: ProgramHeader { +OMAGICPROGRAMHEADERS: Type: PT_TLS (0x7) +OMAGICPROGRAMHEADERS: Offset: 0x120 +OMAGICPROGRAMHEADERS: VirtualAddress: 0x400120 +OMAGICPROGRAMHEADERS: PhysicalAddress: 0x400120 +OMAGICPROGRAMHEADERS: FileSize: 4 +OMAGICPROGRAMHEADERS: MemSize: 12 +OMAGICPROGRAMHEADERS: Flags [ (0x6) +OMAGICPROGRAMHEADERS: PF_R (0x4) +OMAGICPROGRAMHEADERS: PF_W (0x2) +OMAGICPROGRAMHEADERS: ] +OMAGICPROGRAMHEADERS: Alignment: 4 +OMAGICPROGRAMHEADERS: } +OMAGICPROGRAMHEADERS: ]